diff --git a/DEPS b/DEPS index 09c08daf..466da64 100644 --- a/DEPS +++ b/DEPS
@@ -128,7 +128,7 @@ 'checkout_simplechrome': '(checkout_chromeos and host_os == "linux") and ("{cros_board}" != "")', # Surround the board var in quotes so gclient doesn't try parsing the string # as an expression. - 'cros_download_vm': '("{cros_board}" == "amd64-generic") or ("{cros_board}" == "betty") or ("{cros_board}" == "betty-pi-arc")', + 'cros_download_vm': '("{cros_board}" == "amd64-generic") or ("{cros_board}" == "betty")', # Should we build and test for public (ie: full) CrOS images, or private # (ie: release) images. 'use_public_cros_config': 'not checkout_src_internal', @@ -162,27 +162,27 @@ # Three lines of non-changing comments so that # the commit queue can handle CLs rolling Skia # and whatever else without interference from each other. - 'skia_revision': 'e7bd1cb4f6505ce57a2a08cdde99bccdbabb694b', + 'skia_revision': '4dd7c01ca87e97eec0820eb39313bbe7de4dfbd3', # 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': '246cf2b1bea18b4edd54bd8a6118679fbacf95c3', + 'v8_revision': 'd0581808098980bc6cb0ab62a361432267e68bad', # 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. - 'swarming_revision': '96f125709acfd0b48fc1e5dae7d6ea42291726ac', + 'swarming_revision': '885b3febcc170a60f25795304e60927b77d1e92d', # 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': '341482072a1909e6d4aa25e40954cb5dcdddc208', + 'angle_revision': 'a905cbcdc21b5a09bb0bb1d5ef557c260378b2eb', # 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': '1f89f58faeb8287f29e3e5ba7d03d62f667404a0', + 'swiftshader_revision': 'e3a5983705da24448382bc696b0663dc5d0a3ed7', # 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': 'bf5be75f420ce3882089ba05a01f93ad43284db2', + 'pdfium_revision': 'c171a2106b2b70c38f7cca7c26da9b67c413d05d', # Three lines of non-changing comments so that # the commit queue can handle CLs rolling BoringSSL # and whatever else without interference from each other. @@ -225,7 +225,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': '5073a9e8d71d0f12f10635e6787b36a9bd21e04c', + 'catapult_revision': '28837bfd862a41e35946d1c76a05ad242638fa78', # Three lines of non-changing comments so that # the commit queue can handle CLs rolling libFuzzer # and whatever else without interference from each other. @@ -241,7 +241,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. - 'feed_revision': '4e6265827406b37da706e1e404cac5f99ae2854e', + 'feed_revision': 'c25c8f41145ed610d1a73004e8bcd62d8e8111c1', # Three lines of non-changing comments so that # the commit queue can handle CLs rolling android_sdk_build-tools_version # and whatever else without interference from each other. @@ -281,7 +281,7 @@ # Three lines of non-changing comments so that # the commit queue can handle CLs rolling feed # and whatever else without interference from each other. - 'spv_tools_revision': '605c2e3c0ea7cab09c6cc3bc2a48030ba78d3a03', + 'spv_tools_revision': '3a762d54f649c756e6b4c25957d11bd0a9d71c1c', # Three lines of non-changing comments so that # the commit queue can handle CLs rolling feed # and whatever else without interference from each other. @@ -293,11 +293,11 @@ # 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': 'cb8b3fc5caf99c54fba88ac3c0a45ed6e50c0f43', + 'shaderc_revision': 'c5b0621faea0cf8df848365edd002d4b19b1a740', # Three lines of non-changing comments so that # the commit queue can handle CLs rolling feed # and whatever else without interference from each other. - 'dawn_revision': 'd46cabd73fb4b06bc5a18ce56b2803bb4bb64d21', + 'dawn_revision': '27a35eb2a93800e786c2d490e66c5e6c8dc77048', # Three lines of non-changing comments so that # the commit queue can handle CLs rolling feed # and whatever else without interference from each other. @@ -853,7 +853,7 @@ # Build tools for Chrome OS. Note: This depends on third_party/pyelftools. 'src/third_party/chromite': { - 'url': Var('chromium_git') + '/chromiumos/chromite.git' + '@' + '16f6f6e4dd634dee420412e55bff13352e96bdad', + 'url': Var('chromium_git') + '/chromiumos/chromite.git' + '@' + '62ba8cb7666f8c3ad0834b9ada6f34685a6bfc31', 'condition': 'checkout_linux', }, @@ -878,7 +878,7 @@ }, 'src/third_party/depot_tools': - Var('chromium_git') + '/chromium/tools/depot_tools.git' + '@' + 'b5578f4f0b22e51f6c2bf59c93edd4d2defb63f0', + Var('chromium_git') + '/chromium/tools/depot_tools.git' + '@' + '6f18e68719fc02f9e08185e8c27a583deca2d1e5', 'src/third_party/devtools-node-modules': Var('chromium_git') + '/external/github.com/ChromeDevTools/devtools-node-modules' + '@' + Var('devtools_node_modules_revision'), @@ -1146,7 +1146,7 @@ }, 'src/third_party/libvpx/source/libvpx': - Var('chromium_git') + '/webm/libvpx.git' + '@' + 'c094391e954aa274b9dcce3d6afcb5ba6bae7eff', + Var('chromium_git') + '/webm/libvpx.git' + '@' + 'b8d86733e9d9c58e17028720751f96dad2df7a09', 'src/third_party/libwebm/source': Var('chromium_git') + '/webm/libwebm.git' + '@' + '51ca718c3adf0ddedacd7df25fe45f67dc5a9ce1', @@ -1257,7 +1257,7 @@ }, 'src/third_party/perfetto': - Var('android_git') + '/platform/external/perfetto.git' + '@' + 'eb06d51adc82ace982e414969ab18cd35f85344c', + Var('android_git') + '/platform/external/perfetto.git' + '@' + '55783c1d04037e95075acbed55abb2968a5c5819', 'src/third_party/perl': { 'url': Var('chromium_git') + '/chromium/deps/perl.git' + '@' + '6f3e5028eb65d0b4c5fdd792106ac4c84eee1eb3', @@ -1425,7 +1425,7 @@ Var('chromium_git') + '/external/khronosgroup/webgl.git' + '@' + '7c4e67ff117d6c640e6dd17989afe2fb7da7eecb', 'src/third_party/webrtc': - Var('webrtc_git') + '/src.git' + '@' + '3c5f91b74871ba0c716ab9650e9779064aa864ff', + Var('webrtc_git') + '/src.git' + '@' + 'f7457e55fe3d883bc7daa784f0c38ea76f82b873', 'src/third_party/xdg-utils': { 'url': Var('chromium_git') + '/chromium/deps/xdg-utils.git' + '@' + 'd80274d5869b17b8c9067a1022e4416ee7ed5e0d', @@ -1487,7 +1487,7 @@ Var('chromium_git') + '/v8/v8.git' + '@' + Var('v8_revision'), 'src-internal': { - 'url': 'https://chrome-internal.googlesource.com/chrome/src-internal.git@b3c3754a9c0fe3c9c4f09625e1c28c08a343d52d', + 'url': 'https://chrome-internal.googlesource.com/chrome/src-internal.git@ce9b13eb99e18ea1aad83017f113a1fd814d31c3', 'condition': 'checkout_src_internal', },
diff --git a/android_webview/browser/state_serializer.cc b/android_webview/browser/state_serializer.cc index 08ab52e..ef9fd9d 100644 --- a/android_webview/browser/state_serializer.cc +++ b/android_webview/browser/state_serializer.cc
@@ -187,11 +187,22 @@ base::PickleIterator* iterator, content::NavigationEntry* entry) { DCHECK(IsSupportedVersion(state_version)); + + GURL deserialized_url; { string url; if (!iterator->ReadString(&url)) return false; - entry->SetURL(GURL(url)); + deserialized_url = GURL(url); + + // Note: The url will be cloberred by the SetPageState call below (see how + // RecursivelyGenerateFrameEntries uses PageState data to create + // FrameNavigationEntries). + // + // Nevertheless, we call SetURL here to temporarily set the URL, because it + // modifies the state that might be depended on in some calls below (e.g. + // the SetVirtualURL call). + entry->SetURL(deserialized_url); } { @@ -201,8 +212,11 @@ entry->SetVirtualURL(GURL(virtual_url)); } + content::Referrer deserialized_referrer; { - content::Referrer referrer; + // Note: The referrer will be cloberred by the SetPageState call below (see + // how RecursivelyGenerateFrameEntries uses PageState data to create + // FrameNavigationEntries). string referrer_url; int policy; @@ -211,9 +225,9 @@ if (!iterator->ReadInt(&policy)) return false; - referrer.url = GURL(referrer_url); - referrer.policy = static_cast<network::mojom::ReferrerPolicy>(policy); - entry->SetReferrer(referrer); + deserialized_referrer.url = GURL(referrer_url); + deserialized_referrer.policy = + static_cast<network::mojom::ReferrerPolicy>(policy); } { @@ -227,8 +241,37 @@ string content_state; if (!iterator->ReadString(&content_state)) return false; - entry->SetPageState( - content::PageState::CreateFromEncodedData(content_state)); + + // In legacy output of WebViewProvider.saveState, the |content_state| + // might be empty - we need to gracefully handle such data when + // it is deserialized via WebViewProvider.restoreState. + if (content_state.empty()) { + // Ensure that the deserialized/restored content::NavigationEntry (and + // the content::FrameNavigationEntry underneath) has a valid PageState. + entry->SetPageState(content::PageState::CreateFromURL(deserialized_url)); + + // The |deserialized_referrer| might be inconsistent with the referrer + // embedded inside the PageState set above. Nevertheless, to minimize + // changes to behavior of old session restore entries, we restore the + // deserialized referrer here. + // + // TODO(lukasza): Consider including the |deserialized_referrer| in the + // PageState set above + drop the SetReferrer call below. This will + // slightly change the legacy behavior, but will make PageState and + // Referrer consistent. + entry->SetReferrer(deserialized_referrer); + } else { + // Note that PageState covers and will clobber some of the values covered + // by data within |iterator| (e.g. URL and referrer). + entry->SetPageState( + content::PageState::CreateFromEncodedData(content_state)); + + // |deserialized_url| and |deserialized_referrer| are redundant wrt + // PageState, but they should be consistent / in-sync. + DCHECK_EQ(deserialized_url, entry->GetURL()); + DCHECK_EQ(deserialized_referrer.url, entry->GetReferrer().url); + DCHECK_EQ(deserialized_referrer.policy, entry->GetReferrer().policy); + } } {
diff --git a/android_webview/browser/state_serializer_unittest.cc b/android_webview/browser/state_serializer_unittest.cc index 5cdf3b6..062147a 100644 --- a/android_webview/browser/state_serializer_unittest.cc +++ b/android_webview/browser/state_serializer_unittest.cc
@@ -14,6 +14,7 @@ #include "content/public/browser/navigation_entry.h" #include "content/public/common/content_client.h" #include "content/public/common/page_state.h" +#include "services/network/public/mojom/referrer_policy.mojom-shared.h" #include "testing/gtest/include/gtest/gtest.h" #include "url/gurl.h" @@ -33,8 +34,6 @@ referrer.url = GURL("http://referrer_url"); referrer.policy = network::mojom::ReferrerPolicy::kOrigin; const base::string16 title(base::UTF8ToUTF16("title")); - const content::PageState page_state = - content::PageState::CreateFromEncodedData("completely bogus state"); const bool has_post_data = true; const GURL original_request_url("http://original_request_url"); const GURL base_url_for_data_url("http://base_url"); @@ -47,7 +46,6 @@ entry->SetVirtualURL(virtual_url); entry->SetReferrer(referrer); entry->SetTitle(title); - entry->SetPageState(page_state); entry->SetHasPostData(has_post_data); entry->SetOriginalRequestURL(original_request_url); entry->SetBaseURLForDataURL(base_url_for_data_url); @@ -174,6 +172,76 @@ EXPECT_EQ(entry->GetHttpStatusCode(), copy->GetHttpStatusCode()); } +// This is a regression test for https://crbug.com/999078 - it checks that code +// is able to safely restore entries that were serialized with an empty +// PageState. +TEST_F(AndroidWebViewStateSerializerTest, + TestDeserialization_20151204_EmptyPageState) { + // Test data. + GURL url("data:text/html,main_url"); + GURL virtual_url("https://example.com/virtual_url"); + content::Referrer referrer(GURL("https://example.com/referrer"), + network::mojom::ReferrerPolicy::kDefault); + base::string16 title = base::UTF8ToUTF16("title"); + std::string empty_encoded_page_state = ""; + bool has_post_data = false; + GURL original_request_url("https://example.com/original"); + GURL base_url_for_data_url("https://example.com/base_url_for_data_url"); + bool is_overriding_user_agent = false; + int64_t timestamp = 123456; + int http_status_code = 404; + + // Write data to |pickle| in a way that would trigger https://crbug.com/999078 + // in the past. The serialization format used below is based on version + // 20151204 (aka AW_STATE_VERSION_DATA_URL). + base::Pickle pickle; + pickle.WriteString(url.spec()); + pickle.WriteString(virtual_url.spec()); + pickle.WriteString(referrer.url.spec()); + pickle.WriteInt(static_cast<int>(referrer.policy)); + pickle.WriteString16(title); + pickle.WriteString(empty_encoded_page_state); + pickle.WriteBool(has_post_data); + pickle.WriteString(original_request_url.spec()); + pickle.WriteString(base_url_for_data_url.spec()); + pickle.WriteData(nullptr, 0); // data_url_as_string + pickle.WriteBool(is_overriding_user_agent); + pickle.WriteInt64(timestamp); + pickle.WriteInt(http_status_code); + + // Deserialize the |pickle|. + base::PickleIterator iterator(pickle); + std::unique_ptr<content::NavigationEntry> copy = + content::NavigationEntry::Create(); + bool result = + internal::RestoreNavigationEntryFromPickle(&iterator, copy.get()); + EXPECT_TRUE(result); + + // In https://crbug.com/999078, the empty PageState would clobber the URL + // leading to renderer-side CHECKs later on. Code should replace the empty + // PageState from the |pickle| with a real PageState that preserves the URL. + // Additionally, the referrer needs to be restored in the NavigationEntry + // (but not necessarily in the PageState - this preserves old behavior). + EXPECT_EQ(url, copy->GetURL()); + EXPECT_FALSE(copy->GetPageState().ToEncodedData().empty()); + EXPECT_EQ(referrer.url, copy->GetReferrer().url); + EXPECT_EQ(referrer.policy, copy->GetReferrer().policy); + + // Verify that other properties have deserialized as expected. + EXPECT_EQ(virtual_url, copy->GetVirtualURL()); + EXPECT_EQ(referrer.policy, copy->GetReferrer().policy); + EXPECT_EQ(title, copy->GetTitle()); + EXPECT_EQ(has_post_data, copy->GetHasPostData()); + EXPECT_EQ(original_request_url, copy->GetOriginalRequestURL()); + EXPECT_EQ(base_url_for_data_url, copy->GetBaseURLForDataURL()); + EXPECT_FALSE(copy->GetDataURLAsString()); + EXPECT_EQ(is_overriding_user_agent, copy->GetIsOverridingUserAgent()); + EXPECT_EQ(base::Time::FromDeltaSinceWindowsEpoch( + base::TimeDelta::FromMicroseconds(timestamp)), + copy->GetTimestamp()); + EXPECT_EQ(http_status_code, copy->GetHttpStatusCode()); +} + TEST_F(AndroidWebViewStateSerializerTest, TestEmptyDataURLSerialization) { std::unique_ptr<content::NavigationEntry> entry( content::NavigationEntry::Create());
diff --git a/ash/app_list/app_list_controller_impl.cc b/ash/app_list/app_list_controller_impl.cc index 4fb95e6d..bb7059f 100644 --- a/ash/app_list/app_list_controller_impl.cc +++ b/ash/app_list/app_list_controller_impl.cc
@@ -1254,8 +1254,7 @@ // Skip adjacent same changes. if (last_visible_ == real_visibility && - (display::kInvalidDisplayId == display_id || - last_visible_display_id_ == display_id)) { + last_visible_display_id_ == display_id) { return; }
diff --git a/ash/app_list/app_list_presenter_delegate_unittest.cc b/ash/app_list/app_list_presenter_delegate_unittest.cc index 201c6a8..861f0d2 100644 --- a/ash/app_list/app_list_presenter_delegate_unittest.cc +++ b/ash/app_list/app_list_presenter_delegate_unittest.cc
@@ -1562,7 +1562,6 @@ base::RunLoop().RunUntilIdle(); GetAppListTestHelper()->CheckState(AppListViewState::kClosed); - LOG(ERROR) << "AHA"; EXPECT_FALSE(GetAppListView()->is_in_drag()); // Show the app list and verify the app list returns to peeking position. @@ -1958,6 +1957,33 @@ config.grid_fadeout_zone_height(); } + // Calculates expected apps grid position on the search results page based on + // the display height and the search box in-screen bounds. + int ExpectedAppsGridTopForSearchResults(const app_list::AppListConfig& config, + int display_height, + const gfx::Rect& search_box_bounds) { + const int top = + ExpectedAppsGridTop(config, display_height, search_box_bounds); + // In the search results page, the apps grid is shown 24 dip below where + // they'd be shown in the apps page. The |top| was calculated relative to + // search box bounds in the search results page, so it has to be further + // offset by the difference between search box bottom bounds in the apps and + // search results page. + const int search_box_diff = + contents_view() + ->GetSearchBoxBounds(ash::AppListState::kStateApps) + .bottom() - + contents_view() + ->GetSearchBoxBounds(ash::AppListState::kStateSearchResults) + .bottom(); + return top + search_box_diff + + 24 /*apps grid offset in fullscreen search state*/; + } + + app_list::ContentsView* contents_view() { + return GetAppListView()->app_list_main_view()->contents_view(); + } + app_list::AppsGridView* apps_grid_view() { return GetAppListView() ->app_list_main_view() @@ -2026,6 +2052,7 @@ search_box_bounds.y()); EXPECT_EQ(ExpectedAppsGridTop(config, 900, search_box_bounds), apps_grid_view()->GetBoundsInScreen().y()); + EXPECT_TRUE(apps_grid_view()->GetVisible()); // In apps state, search results page should be hidden behind the search // box. EXPECT_EQ(search_box_bounds, search_result_page()->GetBoundsInScreen()); @@ -2044,6 +2071,7 @@ EXPECT_EQ(fullscreen_search_box_padding, search_box_bounds.y()); EXPECT_EQ(ExpectedAppsGridTop(config, 900, search_box_bounds), apps_grid_view()->GetBoundsInScreen().y()); + EXPECT_TRUE(apps_grid_view()->GetVisible()); EXPECT_EQ(search_box_bounds, search_result_page()->GetBoundsInScreen()); // Move half way between peeking and closed state - the search box padding @@ -2067,6 +2095,7 @@ search_box_bounds.y()); EXPECT_EQ(ExpectedAppsGridTop(config, 900, search_box_bounds), apps_grid_view()->GetBoundsInScreen().y()); + EXPECT_TRUE(apps_grid_view()->GetVisible()); EXPECT_EQ(search_box_bounds, search_result_page()->GetBoundsInScreen()); // Move to the closed state height, and verify the search box padding matches @@ -2083,6 +2112,7 @@ search_box_bounds.y()); EXPECT_EQ(ExpectedAppsGridTop(config, 900, search_box_bounds), apps_grid_view()->GetBoundsInScreen().y()); + EXPECT_TRUE(apps_grid_view()->GetVisible()); EXPECT_EQ(search_box_bounds, search_result_page()->GetBoundsInScreen()); } @@ -2136,8 +2166,15 @@ search_result_page()->GetBoundsInScreen().y()); EXPECT_EQ(search_results_height, search_result_page()->GetBoundsInScreen().height()); - // Apps grid should be off screen. - EXPECT_GT(apps_grid_view()->GetBoundsInScreen().y(), 900); + if (ScalableAppListEnabled()) { + EXPECT_EQ( + ExpectedAppsGridTopForSearchResults(config, 900, search_box_bounds), + apps_grid_view()->GetBoundsInScreen().y()); + } else { + // Apps grid should be off screen. + EXPECT_GT(apps_grid_view()->GetBoundsInScreen().y(), 900); + } + EXPECT_TRUE(apps_grid_view()->GetVisible()); // Move to the fullscreen position, and verify the search box padding is // equal to the expected fullscreen value. @@ -2154,8 +2191,15 @@ search_result_page()->GetBoundsInScreen().y()); EXPECT_EQ(search_results_height, search_result_page()->GetBoundsInScreen().height()); - // Apps grid should be off screen. - EXPECT_GT(apps_grid_view()->GetBoundsInScreen().y(), 900); + if (ScalableAppListEnabled()) { + EXPECT_EQ( + ExpectedAppsGridTopForSearchResults(config, 900, search_box_bounds), + apps_grid_view()->GetBoundsInScreen().y()); + } else { + // Apps grid should be off screen. + EXPECT_GT(apps_grid_view()->GetBoundsInScreen().y(), 900); + } + EXPECT_TRUE(apps_grid_view()->GetVisible()); // Move half way between peeking and closed state - the search box padding // should be half distance between closed and peeking padding. @@ -2178,8 +2222,15 @@ search_result_page()->GetBoundsInScreen().y()); EXPECT_EQ(search_results_height, search_result_page()->GetBoundsInScreen().height()); - // Apps grid should be off screen. - EXPECT_GT(apps_grid_view()->GetBoundsInScreen().y(), 900); + if (ScalableAppListEnabled()) { + EXPECT_EQ( + ExpectedAppsGridTopForSearchResults(config, 900, search_box_bounds), + apps_grid_view()->GetBoundsInScreen().y()); + } else { + // Apps grid should be off screen. + EXPECT_GT(apps_grid_view()->GetBoundsInScreen().y(), 900); + } + EXPECT_TRUE(apps_grid_view()->GetVisible()); // Move to the closed state height, and verify the search box padding matches // the state. @@ -2197,8 +2248,15 @@ search_result_page()->GetBoundsInScreen().y()); EXPECT_EQ(search_results_height, search_result_page()->GetBoundsInScreen().height()); - // Apps grid should be off screen. - EXPECT_GT(apps_grid_view()->GetBoundsInScreen().y(), 900); + if (ScalableAppListEnabled()) { + EXPECT_EQ( + ExpectedAppsGridTopForSearchResults(config, 900, search_box_bounds), + apps_grid_view()->GetBoundsInScreen().y()); + } else { + // Apps grid should be off screen. + EXPECT_GT(apps_grid_view()->GetBoundsInScreen().y(), 900); + } + EXPECT_TRUE(apps_grid_view()->GetVisible()); } // Tests changing the active app list page while drag is in progress. @@ -2245,9 +2303,18 @@ search_result_page()->GetBoundsInScreen().y()); EXPECT_EQ(search_results_height, search_result_page()->GetBoundsInScreen().height()); - // Apps grid should be off screen. - EXPECT_GT(apps_grid_view()->GetBoundsInScreen().y(), 900); + if (ScalableAppListEnabled()) { + EXPECT_EQ( + ExpectedAppsGridTopForSearchResults(config, 900, search_box_bounds), + apps_grid_view()->GetBoundsInScreen().y()); + } else { + // Apps grid should be off screen. + EXPECT_GT(apps_grid_view()->GetBoundsInScreen().y(), 900); + } + EXPECT_TRUE(apps_grid_view()->GetVisible()); + const gfx::Rect apps_grid_bounds_in_results_page = + apps_grid_view()->GetBoundsInScreen(); const gfx::Rect app_list_bounds = GetAppListView()->GetBoundsInScreen(); // Press ESC key - this should move the UI back to the app list. @@ -2271,6 +2338,13 @@ EXPECT_EQ(expected_search_box_top, search_box_bounds.y()); EXPECT_EQ(ExpectedAppsGridTop(config, 900, search_box_bounds), apps_grid_view()->GetBoundsInScreen().y()); + EXPECT_TRUE(apps_grid_view()->GetVisible()); + if (ScalableAppListEnabled()) { + EXPECT_EQ(apps_grid_bounds_in_results_page.y() - 24, + apps_grid_view()->GetBoundsInScreen().y()); + } + EXPECT_EQ(apps_grid_bounds_in_results_page.size(), + apps_grid_view()->GetBoundsInScreen().size()); EXPECT_EQ(search_box_bounds, search_result_page()->GetBoundsInScreen()); // Enter text in the search box to transition back to search results page. @@ -2289,8 +2363,15 @@ search_result_page()->GetBoundsInScreen().y()); EXPECT_EQ(search_results_height, search_result_page()->GetBoundsInScreen().height()); - // Apps grid should be off screen. - EXPECT_GT(apps_grid_view()->GetBoundsInScreen().y(), 900); + if (ScalableAppListEnabled()) { + EXPECT_EQ( + ExpectedAppsGridTopForSearchResults(config, 900, search_box_bounds), + apps_grid_view()->GetBoundsInScreen().y()); + } else { + // Apps grid should be off screen. + EXPECT_GT(apps_grid_view()->GetBoundsInScreen().y(), 900); + } + EXPECT_TRUE(apps_grid_view()->GetVisible()); } // Tests changing the active app list page in fullscreen state. @@ -2315,6 +2396,7 @@ search_box_bounds.y()); EXPECT_EQ(ExpectedAppsGridTop(config, 900, search_box_bounds), apps_grid_view()->GetBoundsInScreen().y()); + EXPECT_TRUE(apps_grid_view()->GetVisible()); EXPECT_EQ(search_box_bounds, search_result_page()->GetBoundsInScreen()); const gfx::Rect app_list_bounds = GetAppListView()->GetBoundsInScreen(); @@ -2334,8 +2416,17 @@ search_result_page()->GetBoundsInScreen().y()); EXPECT_EQ(search_results_height, search_result_page()->GetBoundsInScreen().height()); - // Apps grid should be off screen. - EXPECT_GT(apps_grid_view()->GetBoundsInScreen().y(), 900); + if (ScalableAppListEnabled()) { + EXPECT_EQ( + ExpectedAppsGridTopForSearchResults(config, 900, search_box_bounds), + apps_grid_view()->GetBoundsInScreen().y()); + } else { + // Apps grid should be off screen. + EXPECT_GT(apps_grid_view()->GetBoundsInScreen().y(), 900); + } + EXPECT_EQ(ScalableAppListEnabled(), apps_grid_view()->GetVisible()); + const gfx::Rect apps_grid_bounds_in_results_page = + apps_grid_view()->GetBoundsInScreen(); // Press ESC key - this should move the UI back to the app list. generator->PressKey(ui::KeyboardCode::VKEY_ESCAPE, 0); @@ -2349,6 +2440,13 @@ search_box_bounds.y()); EXPECT_EQ(ExpectedAppsGridTop(config, 900, search_box_bounds), apps_grid_view()->GetBoundsInScreen().y()); + EXPECT_TRUE(apps_grid_view()->GetVisible()); + if (ScalableAppListEnabled()) { + EXPECT_EQ(apps_grid_bounds_in_results_page.y() - 24, + apps_grid_view()->GetBoundsInScreen().y()); + } + EXPECT_EQ(apps_grid_bounds_in_results_page.size(), + apps_grid_view()->GetBoundsInScreen().size()); EXPECT_EQ(search_box_bounds, search_result_page()->GetBoundsInScreen()); }
diff --git a/ash/app_list/views/app_list_page.cc b/ash/app_list/views/app_list_page.cc index 0af41f77..34ca386 100644 --- a/ash/app_list/views/app_list_page.cc +++ b/ash/app_list/views/app_list_page.cc
@@ -34,6 +34,8 @@ return base::nullopt; } +void AppListPage::UpdateOpacityForState(ash::AppListState state) {} + void AppListPage::UpdatePageBoundsForState(ash::AppListState state, const gfx::Rect& contents_bounds, const gfx::Rect& search_box_bounds) {
diff --git a/ash/app_list/views/app_list_page.h b/ash/app_list/views/app_list_page.h index a60dfb9..ec698540 100644 --- a/ash/app_list/views/app_list_page.h +++ b/ash/app_list/views/app_list_page.h
@@ -75,6 +75,13 @@ const gfx::Rect& contents_bounds, const gfx::Rect& search_box_bounds) const = 0; + // Should update the app list page opacity for the current state. Called when + // the selected page changes without animation - if the page implements this, + // it should make sure the page transition animation updates the opacity as + // well. + // Default implementation is no-op. + virtual void UpdateOpacityForState(ash::AppListState state); + // Convenience method that sets the page bounds to the bounds returned by // GetPageBoundsForState(). void UpdatePageBoundsForState(ash::AppListState state,
diff --git a/ash/app_list/views/apps_container_view.cc b/ash/app_list/views/apps_container_view.cc index 8e91c80..dc0e43f 100644 --- a/ash/app_list/views/apps_container_view.cc +++ b/ash/app_list/views/apps_container_view.cc
@@ -202,10 +202,13 @@ bool is_in_drag) { if (app_list_state == ash::AppListViewState::kClosed) return; + apps_grid_view_->UpdateControlVisibility(app_list_state, is_in_drag); - page_switcher_->SetVisible(app_list_state == - ash::AppListViewState::kFullscreenAllApps || - is_in_drag); + page_switcher_->SetVisible( + is_in_drag || + app_list_state == ash::AppListViewState::kFullscreenAllApps || + (app_list_features::IsScalableAppListEnabled() && + app_list_state == ash::AppListViewState::kFullscreenSearch)); // Ignore button press during dragging to avoid app list item views' opacity // being set to wrong value.
diff --git a/ash/app_list/views/apps_grid_view.cc b/ash/app_list/views/apps_grid_view.cc index f96205a..b237468 100644 --- a/ash/app_list/views/apps_grid_view.cc +++ b/ash/app_list/views/apps_grid_view.cc
@@ -1022,9 +1022,12 @@ } } - const bool fullscreen_apps_in_drag = - app_list_state == ash::AppListViewState::kFullscreenAllApps || is_in_drag; - SetVisible(fullscreen_apps_in_drag); + const bool fullscreen_or_in_drag = + is_in_drag || + app_list_state == ash::AppListViewState::kFullscreenAllApps || + (app_list_features::IsScalableAppListEnabled() && + app_list_state == ash::AppListViewState::kFullscreenSearch); + SetVisible(fullscreen_or_in_drag); } bool AppsGridView::OnKeyPressed(const ui::KeyEvent& event) {
diff --git a/ash/app_list/views/contents_view.cc b/ash/app_list/views/contents_view.cc index c176818e..9f673bb 100644 --- a/ash/app_list/views/contents_view.cc +++ b/ash/app_list/views/contents_view.cc
@@ -620,8 +620,10 @@ gfx::Rect search_box_bounds = GetSearchBoxBounds(current_state); // Update app list pages. - for (AppListPage* page : app_list_pages_) + for (AppListPage* page : app_list_pages_) { page->UpdatePageBoundsForState(current_state, rect, search_box_bounds); + page->UpdateOpacityForState(current_state); + } UpdateExpandArrowOpacity(current_state, false); @@ -737,8 +739,17 @@ search_box_bounds); } - if (current_state == ash::AppListState::kStateApps) { - GetAppsContainerView()->UpdateYPositionAndOpacity(progress, + if (app_list_features::IsScalableAppListEnabled() || + current_state == ash::AppListState::kStateApps) { + // Layout the apps container at the position where it would be with apps + // page active with the current app list height - use apps state app list + // progress to aciheve that. + const float apps_container_progress = + app_list_view_->is_in_drag() + ? app_list_view_->GetAppListTransitionProgress( + AppListView::kProgressFlagNone) + : progress; + GetAppsContainerView()->UpdateYPositionAndOpacity(apps_container_progress, restore_opacity); } } @@ -896,18 +907,20 @@ bool ContentsView::ShouldLayoutPage(AppListPage* page, ash::AppListState current_state, ash::AppListState target_state) const { - if (page == horizontal_page_container_) { - return (current_state == ash::AppListState::kStateSearchResults && - target_state == ash::AppListState::kStateApps); - } - - if (page == search_results_page_view_) { + if ((page == horizontal_page_container_ && + app_list_features::IsScalableAppListEnabled()) || + page == search_results_page_view_) { return ((current_state == ash::AppListState::kStateSearchResults && target_state == ash::AppListState::kStateApps) || (current_state == ash::AppListState::kStateApps && target_state == ash::AppListState::kStateSearchResults)); } + if (page == horizontal_page_container_) { + return (current_state == ash::AppListState::kStateSearchResults && + target_state == ash::AppListState::kStateApps); + } + if (page == assistant_page_view_) { return current_state == ash::AppListState::kStateEmbeddedAssistant || target_state == ash::AppListState::kStateEmbeddedAssistant;
diff --git a/ash/app_list/views/horizontal_page_container.cc b/ash/app_list/views/horizontal_page_container.cc index 6e1ea43..9debdca 100644 --- a/ash/app_list/views/horizontal_page_container.cc +++ b/ash/app_list/views/horizontal_page_container.cc
@@ -11,6 +11,7 @@ #include "ash/app_list/views/search_box_view.h" #include "ash/app_list/views/search_result_page_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/pagination/pagination_controller.h" #include "base/strings/utf_string_conversions.h" #include "ui/chromeos/search_box/search_box_constants.h" @@ -19,6 +20,17 @@ namespace app_list { +namespace { + +// The amount by which the apps container UI should be offset downwards when +// shown on non apps page UI. +constexpr int kNonAppsStateVerticalOffset = 24; + +// The opacity the apps container UI should have when shown on non apps page UI. +constexpr float kNonAppsStateOpacity = 0.1; + +} // namespace + HorizontalPageContainer::HorizontalPageContainer(ContentsView* contents_view, AppListModel* model) : contents_view_(contents_view) { @@ -88,9 +100,23 @@ const gfx::Rect to_rect = GetPageBoundsForState(to_state, contents_bounds, gfx::Rect()); if (from_rect != to_rect) { - SetBoundsRect(from_rect); - auto settings = contents_view()->CreateTransitionAnimationSettings(layer()); + DCHECK_EQ(from_rect.size(), to_rect.size()); + DCHECK_EQ(from_rect.x(), to_rect.x()); + SetBoundsRect(to_rect); + + gfx::Transform initial_transform; + initial_transform.Translate(0, from_rect.y() - to_rect.y()); + layer()->SetTransform(initial_transform); + + auto settings = contents_view()->CreateTransitionAnimationSettings(layer()); + layer()->SetTransform(gfx::Transform()); + } + + // Set the page opacity. + if (app_list_features::IsScalableAppListEnabled()) { + auto settings = contents_view()->CreateTransitionAnimationSettings(layer()); + UpdateOpacityForState(to_state); } for (size_t i = 0; i < horizontal_pages_.size(); ++i) { @@ -115,7 +141,19 @@ const gfx::Rect& search_box_bounds) const { if (state == ash::AppListState::kStateApps) return contents_bounds; - return GetBelowContentsOffscreenBounds(contents_bounds.size()); + if (!app_list_features::IsScalableAppListEnabled()) + return GetBelowContentsOffscreenBounds(contents_bounds.size()); + + gfx::Rect bounds = contents_bounds; + bounds.Offset(0, kNonAppsStateVerticalOffset); + return bounds; +} + +void HorizontalPageContainer::UpdateOpacityForState(ash::AppListState state) { + if (!app_list_features::IsScalableAppListEnabled()) + return; + layer()->SetOpacity( + state == ash::AppListState::kStateApps ? 1.0f : kNonAppsStateOpacity); } views::View* HorizontalPageContainer::GetFirstFocusableView() {
diff --git a/ash/app_list/views/horizontal_page_container.h b/ash/app_list/views/horizontal_page_container.h index 6165b305..9668aa4 100644 --- a/ash/app_list/views/horizontal_page_container.h +++ b/ash/app_list/views/horizontal_page_container.h
@@ -46,6 +46,7 @@ ash::AppListState state, const gfx::Rect& contents_bounds, const gfx::Rect& search_box_bounds) const override; + void UpdateOpacityForState(ash::AppListState state) override; views::View* GetFirstFocusableView() override; views::View* GetLastFocusableView() override; bool ShouldShowSearchBox() const override;
diff --git a/ash/app_list/views/result_selection_controller.cc b/ash/app_list/views/result_selection_controller.cc index e6a758de..2554cb5 100644 --- a/ash/app_list/views/result_selection_controller.cc +++ b/ash/app_list/views/result_selection_controller.cc
@@ -37,8 +37,10 @@ } ResultSelectionController::ResultSelectionController( - const ResultSelectionModel* result_container_views) - : result_selection_model_(result_container_views) {} + const ResultSelectionModel* result_container_views, + const base::RepeatingClosure& selection_change_callback) + : result_selection_model_(result_container_views), + selection_change_callback_(selection_change_callback) {} ResultSelectionController::~ResultSelectionController() = default; @@ -99,6 +101,8 @@ if (selected_result_) selected_result_->SetSelected(true, is_shift_tab); + + selection_change_callback_.Run(); } void ResultSelectionController::ClearSelection() { @@ -230,6 +234,7 @@ selected_location_details_ = std::make_unique<ResultLocationDetails>(location); selected_result_->SetSelected(true, reverse_tab_order); + selection_change_callback_.Run(); } SearchResultBaseView* ResultSelectionController::GetResultAtLocation(
diff --git a/ash/app_list/views/result_selection_controller.h b/ash/app_list/views/result_selection_controller.h index 7db7224..e6d8b7e 100644 --- a/ash/app_list/views/result_selection_controller.h +++ b/ash/app_list/views/result_selection_controller.h
@@ -11,6 +11,7 @@ #include "ash/app_list/app_list_export.h" #include "ash/app_list/views/search_result_base_view.h" #include "ash/app_list/views/search_result_container_view.h" +#include "base/callback.h" #include "base/macros.h" namespace app_list { @@ -77,8 +78,9 @@ kResultChanged, }; - explicit ResultSelectionController( - const ResultSelectionModel* result_container_views); + ResultSelectionController( + const ResultSelectionModel* result_container_views, + const base::RepeatingClosure& selection_change_callback); ~ResultSelectionController(); // Returns the currently selected result. @@ -147,6 +149,10 @@ // |SearchResultContainerView|->|IsHorizontallyTraversable|. bool IsContainerAtIndexHorizontallyTraversable(int index) const; + // The callback run when the selected result changes (including when the + // selected result is cleared). + base::RepeatingClosure selection_change_callback_; + // The currently selected result view SearchResultBaseView* selected_result_ = nullptr;
diff --git a/ash/app_list/views/result_selection_controller_unittest.cc b/ash/app_list/views/result_selection_controller_unittest.cc index 2e2cb1b..0be7333 100644 --- a/ash/app_list/views/result_selection_controller_unittest.cc +++ b/ash/app_list/views/result_selection_controller_unittest.cc
@@ -166,8 +166,10 @@ base::i18n::SetICUDefaultLocale("en"); } - result_selection_controller_ = - std::make_unique<ResultSelectionController>(&containers_); + result_selection_controller_ = std::make_unique<ResultSelectionController>( + &containers_, + base::BindRepeating(&ResultSelectionTest::OnSelectionChanged, + base::Unretained(this))); testing::Test::SetUp(); } @@ -302,6 +304,7 @@ for (size_t i = 1; i < locations.size(); i++) { ASSERT_EQ(ResultSelectionController::MoveResult::kResultChanged, result_selection_controller_->MoveSelection(*forward)); + EXPECT_EQ(1, GetAndResetSelectionChangeCount()); ASSERT_EQ(*result_selection_controller_->selected_location_details(), locations[i]); } @@ -317,6 +320,7 @@ // Expect loop back to first result. EXPECT_EQ(ResultSelectionController::MoveResult::kResultChanged, result_selection_controller_->MoveSelection(*forward)); + EXPECT_EQ(1, GetAndResetSelectionChangeCount()); ASSERT_EQ(*result_selection_controller_->selected_location_details(), locations[0]); } @@ -331,6 +335,7 @@ // Expect loop back to last result. EXPECT_EQ(ResultSelectionController::MoveResult::kResultChanged, result_selection_controller_->MoveSelection(*backward)); + EXPECT_EQ(1, GetAndResetSelectionChangeCount()); ASSERT_EQ(*result_selection_controller_->selected_location_details(), locations[3]); } @@ -345,6 +350,7 @@ // Expect no change in location. ASSERT_EQ(ResultSelectionController::MoveResult::kSelectionCycleRejected, result_selection_controller_->MoveSelection(*forward)); + EXPECT_EQ(0, GetAndResetSelectionChangeCount()); ASSERT_EQ(*result_selection_controller_->selected_location_details(), locations[3]); } @@ -359,6 +365,7 @@ // Expect no change in location. ASSERT_EQ(ResultSelectionController::MoveResult::kSelectionCycleRejected, result_selection_controller_->MoveSelection(*backward)); + EXPECT_EQ(0, GetAndResetSelectionChangeCount()); ASSERT_EQ(*result_selection_controller_->selected_location_details(), locations[0]); } @@ -375,6 +382,7 @@ for (size_t i = last_index; i > 0; i--) { ASSERT_EQ(ResultSelectionController::MoveResult::kResultChanged, result_selection_controller_->MoveSelection(*backward)); + EXPECT_EQ(1, GetAndResetSelectionChangeCount()); ASSERT_EQ(*result_selection_controller_->selected_location_details(), locations[i - 1]); } @@ -428,6 +436,8 @@ ? ResultSelectionController::MoveResult::kSelectionCycleRejected : ResultSelectionController::MoveResult::kResultChanged, result_selection_controller_->MoveSelection(*vertical_forward)); + EXPECT_EQ(i == num_containers - 1 ? 0 : 1, + GetAndResetSelectionChangeCount()); } } @@ -453,6 +463,7 @@ // Initialize the RSC for test. result_selection_controller_->ResetSelection(nullptr); + EXPECT_EQ(1, GetAndResetSelectionChangeCount()); ASSERT_EQ(create_test_location(0, 0), GetCurrentLocation()); EXPECT_TRUE(CurrentResultActionNotSelected()); @@ -461,6 +472,7 @@ // expected to change. EXPECT_EQ(ResultSelectionController::MoveResult::kNone, result_selection_controller_->MoveSelection(tab_key_)); + EXPECT_EQ(0, GetAndResetSelectionChangeCount()); ASSERT_EQ(create_test_location(0, 0), GetCurrentLocation()); EXPECT_TRUE(CurrentResultActionSelected(0)); @@ -469,6 +481,7 @@ // expected to change. EXPECT_EQ(ResultSelectionController::MoveResult::kNone, result_selection_controller_->MoveSelection(tab_key_)); + EXPECT_EQ(0, GetAndResetSelectionChangeCount()); ASSERT_EQ(create_test_location(0, 0), GetCurrentLocation()); EXPECT_TRUE(CurrentResultActionSelected(1)); @@ -477,6 +490,7 @@ TestResultView* previous_result = GetCurrentSelection(); EXPECT_EQ(ResultSelectionController::MoveResult::kResultChanged, result_selection_controller_->MoveSelection(tab_key_)); + EXPECT_EQ(1, GetAndResetSelectionChangeCount()); ASSERT_EQ(create_test_location(0, 1), GetCurrentLocation()); EXPECT_TRUE(CurrentResultActionNotSelected()); @@ -486,6 +500,7 @@ // to be selected. EXPECT_EQ(ResultSelectionController::MoveResult::kResultChanged, result_selection_controller_->MoveSelection(shift_tab_key_)); + EXPECT_EQ(1, GetAndResetSelectionChangeCount()); ASSERT_EQ(create_test_location(0, 0), GetCurrentLocation()); EXPECT_TRUE(CurrentResultActionSelected(1)); @@ -494,6 +509,7 @@ previous_result = GetCurrentSelection(); EXPECT_EQ(ResultSelectionController::MoveResult::kResultChanged, result_selection_controller_->MoveSelection(tab_key_)); + EXPECT_EQ(1, GetAndResetSelectionChangeCount()); ASSERT_EQ(create_test_location(0, 1), GetCurrentLocation()); EXPECT_TRUE(CurrentResultActionNotSelected()); @@ -502,6 +518,7 @@ // TAB - stay at the same result, but select next action. EXPECT_EQ(ResultSelectionController::MoveResult::kNone, result_selection_controller_->MoveSelection(tab_key_)); + EXPECT_EQ(0, GetAndResetSelectionChangeCount()); ASSERT_EQ(create_test_location(0, 1), GetCurrentLocation()); EXPECT_TRUE(CurrentResultActionSelected(0)); @@ -509,6 +526,7 @@ // Shift-TAB - same result, but deselects actions. EXPECT_EQ(ResultSelectionController::MoveResult::kNone, result_selection_controller_->MoveSelection(shift_tab_key_)); + EXPECT_EQ(0, GetAndResetSelectionChangeCount()); ASSERT_EQ(create_test_location(0, 1), GetCurrentLocation()); EXPECT_TRUE(CurrentResultActionNotSelected()); @@ -516,6 +534,7 @@ // TAB - reselect the first action. EXPECT_EQ(ResultSelectionController::MoveResult::kNone, result_selection_controller_->MoveSelection(tab_key_)); + EXPECT_EQ(0, GetAndResetSelectionChangeCount()); ASSERT_EQ(create_test_location(0, 1), GetCurrentLocation()); EXPECT_TRUE(CurrentResultActionSelected(0)); @@ -523,6 +542,7 @@ // TAB - select the next action. EXPECT_EQ(ResultSelectionController::MoveResult::kNone, result_selection_controller_->MoveSelection(tab_key_)); + EXPECT_EQ(0, GetAndResetSelectionChangeCount()); ASSERT_EQ(create_test_location(0, 1), GetCurrentLocation()); EXPECT_TRUE(CurrentResultActionSelected(1)); @@ -531,6 +551,7 @@ previous_result = GetCurrentSelection(); EXPECT_EQ(ResultSelectionController::MoveResult::kResultChanged, result_selection_controller_->MoveSelection(tab_key_)); + EXPECT_EQ(1, GetAndResetSelectionChangeCount()); ASSERT_EQ(create_test_location(1, 0), GetCurrentLocation()); EXPECT_TRUE(CurrentResultActionNotSelected()); @@ -540,6 +561,7 @@ previous_result = GetCurrentSelection(); EXPECT_EQ(ResultSelectionController::MoveResult::kResultChanged, result_selection_controller_->MoveSelection(shift_tab_key_)); + EXPECT_EQ(1, GetAndResetSelectionChangeCount()); ASSERT_EQ(create_test_location(0, 1), GetCurrentLocation()); EXPECT_TRUE(CurrentResultActionSelected(1)); @@ -548,6 +570,7 @@ // Shift-TAB - move to previous action. EXPECT_EQ(ResultSelectionController::MoveResult::kNone, result_selection_controller_->MoveSelection(shift_tab_key_)); + EXPECT_EQ(0, GetAndResetSelectionChangeCount()); ASSERT_EQ(create_test_location(0, 1), GetCurrentLocation()); EXPECT_TRUE(CurrentResultActionSelected(0)); @@ -575,6 +598,7 @@ EXPECT_EQ(ResultSelectionController::MoveResult::kResultChanged, result_selection_controller_->MoveSelection(key_event)); + EXPECT_EQ(1, GetAndResetSelectionChangeCount()); if (expect_reverse) { ASSERT_EQ(create_test_location(1, 1), GetCurrentLocation()); @@ -606,7 +630,16 @@ ui::KeyEvent shift_tab_key_ = ui::KeyEvent(ui::ET_KEY_PRESSED, ui::VKEY_TAB, ui::EF_SHIFT_DOWN); + int GetAndResetSelectionChangeCount() { + const int result = selection_change_count_; + selection_change_count_ = 0; + return result; + } + + void OnSelectionChanged() { selection_change_count_++; } + bool is_rtl_ = false; + int selection_change_count_ = 0; DISALLOW_COPY_AND_ASSIGN(ResultSelectionTest); }; @@ -626,6 +659,7 @@ // Initialize the RSC for test. result_selection_controller_->ResetSelection(nullptr); + EXPECT_EQ(1, GetAndResetSelectionChangeCount()); TestSingleAxisTraversal(&down_arrow_, &up_arrow_); } @@ -642,6 +676,7 @@ // Initialize the RSC for test. result_selection_controller_->ResetSelection(nullptr); + EXPECT_EQ(1, GetAndResetSelectionChangeCount()); TestSingleAxisTraversal(&tab_key_, &shift_tab_key_); } @@ -661,6 +696,7 @@ // Initialize the RSC for test. result_selection_controller_->ResetSelection(nullptr); + EXPECT_EQ(1, GetAndResetSelectionChangeCount()); TestSingleAxisTraversal(forward, backward); } @@ -677,6 +713,7 @@ // Initialize the RSC for test. result_selection_controller_->ResetSelection(nullptr); + EXPECT_EQ(1, GetAndResetSelectionChangeCount()); TestMultiAxisTraversal(false); } @@ -693,6 +730,7 @@ // Initialize the RSC for test. result_selection_controller_->ResetSelection(nullptr); + EXPECT_EQ(1, GetAndResetSelectionChangeCount()); TestMultiAxisTraversal(true); } @@ -704,6 +742,7 @@ // Initialize the RSC for test. result_selection_controller_->ResetSelection(nullptr); + EXPECT_EQ(1, GetAndResetSelectionChangeCount()); TestMultiAxisTraversal(false); } @@ -715,6 +754,7 @@ // Initialize the RSC for test. result_selection_controller_->ResetSelection(nullptr); + EXPECT_EQ(1, GetAndResetSelectionChangeCount()); TestMultiAxisTraversal(true); } @@ -727,6 +767,7 @@ // Initialize the RSC for test. result_selection_controller_->ResetSelection(nullptr); + EXPECT_EQ(1, GetAndResetSelectionChangeCount()); TestMultiAxisTraversal(false); } @@ -739,6 +780,7 @@ // Initialize the RSC for test. result_selection_controller_->ResetSelection(nullptr); + EXPECT_EQ(1, GetAndResetSelectionChangeCount()); TestMultiAxisTraversal(true); } @@ -750,6 +792,7 @@ // Initialize the RSC for test. result_selection_controller_->ResetSelection(nullptr); + EXPECT_EQ(1, GetAndResetSelectionChangeCount()); TestMultiAxisTraversal(false); } @@ -761,6 +804,7 @@ // Initialize the RSC for test. result_selection_controller_->ResetSelection(nullptr); + EXPECT_EQ(1, GetAndResetSelectionChangeCount()); TestMultiAxisTraversal(false); } @@ -772,6 +816,7 @@ // Initialize the RSC for test. result_selection_controller_->ResetSelection(nullptr); + EXPECT_EQ(1, GetAndResetSelectionChangeCount()); TestMultiAxisTraversal(false); } @@ -783,6 +828,7 @@ // Initialize the RSC for test. result_selection_controller_->ResetSelection(nullptr); + EXPECT_EQ(1, GetAndResetSelectionChangeCount()); TestMultiAxisTraversal(false); } @@ -812,6 +858,7 @@ // Initialize the RSC for test. result_selection_controller_->ResetSelection(nullptr); + EXPECT_EQ(1, GetAndResetSelectionChangeCount()); ASSERT_EQ(create_test_location(0, 0), GetCurrentLocation()); EXPECT_TRUE(CurrentResultActionNotSelected()); @@ -819,6 +866,7 @@ // Shift TAB - reject. EXPECT_EQ(ResultSelectionController::MoveResult::kSelectionCycleRejected, result_selection_controller_->MoveSelection(shift_tab_key_)); + EXPECT_EQ(0, GetAndResetSelectionChangeCount()); ASSERT_EQ(create_test_location(0, 0), GetCurrentLocation()); EXPECT_TRUE(CurrentResultActionNotSelected()); @@ -827,6 +875,7 @@ // expected to change. EXPECT_EQ(ResultSelectionController::MoveResult::kNone, result_selection_controller_->MoveSelection(tab_key_)); + EXPECT_EQ(0, GetAndResetSelectionChangeCount()); ASSERT_EQ(create_test_location(0, 0), GetCurrentLocation()); EXPECT_TRUE(CurrentResultActionSelected(0)); @@ -835,6 +884,7 @@ TestResultView* previous_result = GetCurrentSelection(); EXPECT_EQ(ResultSelectionController::MoveResult::kResultChanged, result_selection_controller_->MoveSelection(tab_key_)); + EXPECT_EQ(1, GetAndResetSelectionChangeCount()); ASSERT_EQ(create_test_location(1, 0), GetCurrentLocation()); EXPECT_TRUE(CurrentResultActionNotSelected()); @@ -843,6 +893,7 @@ // TAB - next action selected. EXPECT_EQ(ResultSelectionController::MoveResult::kNone, result_selection_controller_->MoveSelection(tab_key_)); + EXPECT_EQ(0, GetAndResetSelectionChangeCount()); ASSERT_EQ(create_test_location(1, 0), GetCurrentLocation()); EXPECT_TRUE(CurrentResultActionSelected(0)); @@ -850,6 +901,7 @@ // TAB - rejected, as selection would cycle to the beginning. EXPECT_EQ(ResultSelectionController::MoveResult::kSelectionCycleRejected, result_selection_controller_->MoveSelection(tab_key_)); + EXPECT_EQ(0, GetAndResetSelectionChangeCount()); ASSERT_EQ(create_test_location(1, 0), GetCurrentLocation()); EXPECT_TRUE(CurrentResultActionSelected(0)); } @@ -869,6 +921,7 @@ // Initialize the RSC for test. result_selection_controller_->ResetSelection(nullptr); + EXPECT_EQ(1, GetAndResetSelectionChangeCount()); ASSERT_EQ(create_test_location(0, 0), GetCurrentLocation()); @@ -876,12 +929,14 @@ // the first result). EXPECT_EQ(ResultSelectionController::MoveResult::kSelectionCycleRejected, result_selection_controller_->MoveSelection(shift_tab_key_)); + EXPECT_EQ(0, GetAndResetSelectionChangeCount()); ASSERT_EQ(create_test_location(0, 0), GetCurrentLocation()); // TAB - reject goting to the first result (event though it's the same as the // last result). EXPECT_EQ(ResultSelectionController::MoveResult::kSelectionCycleRejected, result_selection_controller_->MoveSelection(tab_key_)); + EXPECT_EQ(0, GetAndResetSelectionChangeCount()); ASSERT_EQ(create_test_location(0, 0), GetCurrentLocation()); } @@ -902,6 +957,7 @@ // Initialize the RSC for test. result_selection_controller_->ResetSelection(nullptr); + EXPECT_EQ(1, GetAndResetSelectionChangeCount()); ASSERT_EQ(create_test_location(0, 0), GetCurrentLocation()); EXPECT_TRUE(CurrentResultActionNotSelected()); @@ -909,6 +965,7 @@ // Shift TAB - reject going to the last result. EXPECT_EQ(ResultSelectionController::MoveResult::kSelectionCycleRejected, result_selection_controller_->MoveSelection(shift_tab_key_)); + EXPECT_EQ(0, GetAndResetSelectionChangeCount()); ASSERT_EQ(create_test_location(0, 0), GetCurrentLocation()); EXPECT_TRUE(CurrentResultActionNotSelected()); @@ -917,6 +974,7 @@ // expected to change. EXPECT_EQ(ResultSelectionController::MoveResult::kNone, result_selection_controller_->MoveSelection(tab_key_)); + EXPECT_EQ(0, GetAndResetSelectionChangeCount()); ASSERT_EQ(create_test_location(0, 0), GetCurrentLocation()); EXPECT_TRUE(CurrentResultActionSelected(0)); @@ -924,6 +982,7 @@ // TAB - rejected, as selection would cycle to the beginning. EXPECT_EQ(ResultSelectionController::MoveResult::kSelectionCycleRejected, result_selection_controller_->MoveSelection(tab_key_)); + EXPECT_EQ(0, GetAndResetSelectionChangeCount()); ASSERT_EQ(create_test_location(0, 0), GetCurrentLocation()); EXPECT_TRUE(CurrentResultActionSelected(0)); } @@ -946,6 +1005,7 @@ // Initialize the RSC for test. result_selection_controller_->ResetSelection(nullptr); + EXPECT_EQ(1, GetAndResetSelectionChangeCount()); ASSERT_EQ(create_test_location(0, 0), GetCurrentLocation()); EXPECT_TRUE(CurrentResultActionNotSelected()); @@ -953,6 +1013,7 @@ // UP - reject going to the last result. EXPECT_EQ(ResultSelectionController::MoveResult::kSelectionCycleRejected, result_selection_controller_->MoveSelection(up_arrow_)); + EXPECT_EQ(0, GetAndResetSelectionChangeCount()); ASSERT_EQ(create_test_location(0, 0), GetCurrentLocation()); EXPECT_TRUE(CurrentResultActionNotSelected()); @@ -961,6 +1022,7 @@ // first element is the same as the last). EXPECT_EQ(ResultSelectionController::MoveResult::kSelectionCycleRejected, result_selection_controller_->MoveSelection(down_arrow_)); + EXPECT_EQ(0, GetAndResetSelectionChangeCount()); ASSERT_EQ(create_test_location(0, 0), GetCurrentLocation()); EXPECT_TRUE(CurrentResultActionNotSelected()); } @@ -984,6 +1046,7 @@ // Initialize the RSC for test. result_selection_controller_->ResetSelection(nullptr); + EXPECT_EQ(1, GetAndResetSelectionChangeCount()); ui::KeyEvent* forward = is_rtl_ ? &left_arrow_ : &right_arrow_; ui::KeyEvent* backward = is_rtl_ ? &right_arrow_ : &left_arrow_; @@ -994,6 +1057,7 @@ // TAB to select an action. EXPECT_EQ(ResultSelectionController::MoveResult::kNone, result_selection_controller_->MoveSelection(tab_key_)); + EXPECT_EQ(0, GetAndResetSelectionChangeCount()); ASSERT_EQ(create_test_location(0, 0), GetCurrentLocation()); EXPECT_TRUE(CurrentResultActionSelected(0)); @@ -1001,6 +1065,7 @@ TestResultView* previous_result = GetCurrentSelection(); EXPECT_EQ(ResultSelectionController::MoveResult::kResultChanged, result_selection_controller_->MoveSelection(*forward)); + EXPECT_EQ(1, GetAndResetSelectionChangeCount()); ASSERT_EQ(create_test_location(0, 1), GetCurrentLocation()); EXPECT_TRUE(CurrentResultActionNotSelected()); EXPECT_FALSE(previous_result->selected()); @@ -1008,6 +1073,7 @@ // TAB to select an action. EXPECT_EQ(ResultSelectionController::MoveResult::kNone, result_selection_controller_->MoveSelection(tab_key_)); + EXPECT_EQ(0, GetAndResetSelectionChangeCount()); ASSERT_EQ(create_test_location(0, 1), GetCurrentLocation()); EXPECT_TRUE(CurrentResultActionSelected(0)); @@ -1015,6 +1081,7 @@ previous_result = GetCurrentSelection(); EXPECT_EQ(ResultSelectionController::MoveResult::kResultChanged, result_selection_controller_->MoveSelection(*backward)); + EXPECT_EQ(1, GetAndResetSelectionChangeCount()); ASSERT_EQ(create_test_location(0, 0), GetCurrentLocation()); EXPECT_TRUE(CurrentResultActionNotSelected()); EXPECT_FALSE(previous_result->selected()); @@ -1039,6 +1106,7 @@ // Initialize the RSC for test. result_selection_controller_->ResetSelection(nullptr); + EXPECT_EQ(1, GetAndResetSelectionChangeCount()); ASSERT_EQ(create_test_location(0, 0), GetCurrentLocation()); EXPECT_TRUE(CurrentResultActionNotSelected()); @@ -1046,6 +1114,7 @@ // TAB to select an action. EXPECT_EQ(ResultSelectionController::MoveResult::kNone, result_selection_controller_->MoveSelection(tab_key_)); + EXPECT_EQ(0, GetAndResetSelectionChangeCount()); ASSERT_EQ(create_test_location(0, 0), GetCurrentLocation()); EXPECT_TRUE(CurrentResultActionSelected(0)); @@ -1053,6 +1122,7 @@ TestResultView* previous_result = GetCurrentSelection(); EXPECT_EQ(ResultSelectionController::MoveResult::kResultChanged, result_selection_controller_->MoveSelection(down_arrow_)); + EXPECT_EQ(1, GetAndResetSelectionChangeCount()); ASSERT_EQ(create_test_location(0, 1), GetCurrentLocation()); EXPECT_TRUE(CurrentResultActionNotSelected()); EXPECT_FALSE(previous_result->selected()); @@ -1060,6 +1130,7 @@ // TAB to select an action. EXPECT_EQ(ResultSelectionController::MoveResult::kNone, result_selection_controller_->MoveSelection(tab_key_)); + EXPECT_EQ(0, GetAndResetSelectionChangeCount()); ASSERT_EQ(create_test_location(0, 1), GetCurrentLocation()); EXPECT_TRUE(CurrentResultActionSelected(0)); @@ -1067,6 +1138,7 @@ previous_result = GetCurrentSelection(); EXPECT_EQ(ResultSelectionController::MoveResult::kResultChanged, result_selection_controller_->MoveSelection(up_arrow_)); + EXPECT_EQ(1, GetAndResetSelectionChangeCount()); ASSERT_EQ(create_test_location(0, 0), GetCurrentLocation()); EXPECT_TRUE(CurrentResultActionNotSelected()); EXPECT_FALSE(previous_result->selected()); @@ -1090,6 +1162,7 @@ // Initialize the RSC for test. result_selection_controller_->ResetSelection(nullptr); + EXPECT_EQ(1, GetAndResetSelectionChangeCount()); ASSERT_EQ(create_test_location(0, 0), GetCurrentLocation()); EXPECT_TRUE(CurrentResultActionNotSelected()); @@ -1097,6 +1170,7 @@ // TAB to select an action. EXPECT_EQ(ResultSelectionController::MoveResult::kNone, result_selection_controller_->MoveSelection(tab_key_)); + EXPECT_EQ(0, GetAndResetSelectionChangeCount()); ASSERT_EQ(create_test_location(0, 0), GetCurrentLocation()); EXPECT_TRUE(CurrentResultActionSelected(0)); @@ -1127,6 +1201,7 @@ // Initialize the RSC for test. result_selection_controller_->ResetSelection(nullptr); + EXPECT_EQ(1, GetAndResetSelectionChangeCount()); ASSERT_EQ(create_test_location(0, 0), GetCurrentLocation()); EXPECT_TRUE(CurrentResultActionNotSelected()); @@ -1134,18 +1209,21 @@ // DOWN to select another result. EXPECT_EQ(ResultSelectionController::MoveResult::kResultChanged, result_selection_controller_->MoveSelection(down_arrow_)); + EXPECT_EQ(1, GetAndResetSelectionChangeCount()); ASSERT_EQ(create_test_location(0, 1), GetCurrentLocation()); EXPECT_TRUE(CurrentResultActionNotSelected()); // TAB to select an action. EXPECT_EQ(ResultSelectionController::MoveResult::kNone, result_selection_controller_->MoveSelection(tab_key_)); + EXPECT_EQ(0, GetAndResetSelectionChangeCount()); ASSERT_EQ(create_test_location(0, 1), GetCurrentLocation()); EXPECT_TRUE(CurrentResultActionSelected(0)); // Reset selection. TestResultView* pre_reset_selection = GetCurrentSelection(); result_selection_controller_->ResetSelection(nullptr); + EXPECT_EQ(1, GetAndResetSelectionChangeCount()); ASSERT_EQ(create_test_location(0, 0), GetCurrentLocation()); EXPECT_TRUE(CurrentResultActionNotSelected()); EXPECT_FALSE(pre_reset_selection->selected()); @@ -1169,6 +1247,7 @@ // Initialize the RSC for test. result_selection_controller_->ResetSelection(nullptr); + EXPECT_EQ(1, GetAndResetSelectionChangeCount()); ASSERT_EQ(create_test_location(0, 0), GetCurrentLocation()); EXPECT_TRUE(CurrentResultActionNotSelected()); @@ -1176,6 +1255,7 @@ // DOWN to select another result. EXPECT_EQ(ResultSelectionController::MoveResult::kResultChanged, result_selection_controller_->MoveSelection(down_arrow_)); + EXPECT_EQ(1, GetAndResetSelectionChangeCount()); ASSERT_EQ(create_test_location(0, 1), GetCurrentLocation()); EXPECT_TRUE(CurrentResultActionNotSelected()); @@ -1186,6 +1266,7 @@ result_selection_controller_->MoveSelection(tab_key_)); EXPECT_EQ(ResultSelectionController::MoveResult::kNone, result_selection_controller_->MoveSelection(tab_key_)); + EXPECT_EQ(0, GetAndResetSelectionChangeCount()); ASSERT_EQ(create_test_location(0, 1), GetCurrentLocation()); EXPECT_TRUE(CurrentResultActionSelected(2)); @@ -1203,6 +1284,7 @@ // Shift-TAB move selection to the previous result. EXPECT_EQ(ResultSelectionController::MoveResult::kResultChanged, result_selection_controller_->MoveSelection(shift_tab_key_)); + EXPECT_EQ(1, GetAndResetSelectionChangeCount()); ASSERT_EQ(create_test_location(0, 0), GetCurrentLocation()); EXPECT_TRUE(CurrentResultActionSelected(2)); } @@ -1254,6 +1336,7 @@ // Set up non default selection, result_selection_controller_->ResetSelection(nullptr); result_selection_controller_->MoveSelection(down_arrow_); + EXPECT_EQ(2, GetAndResetSelectionChangeCount()); ASSERT_EQ(create_test_location(0, 1), GetCurrentLocation()); // Test that calling reset selection while selection changes are blocked does @@ -1261,6 +1344,7 @@ result_selection_controller_->set_block_selection_changes(true); result_selection_controller_->ResetSelection(nullptr); + EXPECT_EQ(0, GetAndResetSelectionChangeCount()); ASSERT_EQ(create_test_location(0, 1), GetCurrentLocation()); EXPECT_TRUE(result_selection_controller_->selected_result()); @@ -1268,6 +1352,7 @@ result_selection_controller_->set_block_selection_changes(false); result_selection_controller_->ResetSelection(nullptr); + EXPECT_EQ(1, GetAndResetSelectionChangeCount()); ASSERT_EQ(create_test_location(0, 0), GetCurrentLocation()); EXPECT_TRUE(result_selection_controller_->selected_result()); @@ -1285,6 +1370,7 @@ // not set the selected result. result_selection_controller_->set_block_selection_changes(true); result_selection_controller_->ResetSelection(nullptr); + EXPECT_EQ(0, GetAndResetSelectionChangeCount()); EXPECT_FALSE(result_selection_controller_->selected_result()); EXPECT_FALSE(result_selection_controller_->selected_location_details()); @@ -1293,6 +1379,7 @@ result_selection_controller_->set_block_selection_changes(false); result_selection_controller_->ResetSelection(nullptr); + EXPECT_EQ(1, GetAndResetSelectionChangeCount()); EXPECT_TRUE(result_selection_controller_->selected_result()); EXPECT_TRUE(result_selection_controller_->selected_location_details()); @@ -1313,6 +1400,7 @@ }; result_selection_controller_->ResetSelection(nullptr); + EXPECT_EQ(1, GetAndResetSelectionChangeCount()); ASSERT_EQ(create_test_location(0, 0), GetCurrentLocation()); // Test that calling move selection while selection chages are blocked does @@ -1321,6 +1409,7 @@ EXPECT_EQ(ResultSelectionController::MoveResult::kNone, result_selection_controller_->MoveSelection(down_arrow_)); + EXPECT_EQ(0, GetAndResetSelectionChangeCount()); ASSERT_EQ(create_test_location(0, 0), GetCurrentLocation()); EXPECT_TRUE(result_selection_controller_->selected_result()); @@ -1328,6 +1417,7 @@ result_selection_controller_->set_block_selection_changes(false); EXPECT_EQ(ResultSelectionController::MoveResult::kResultChanged, result_selection_controller_->MoveSelection(down_arrow_)); + EXPECT_EQ(1, GetAndResetSelectionChangeCount()); ASSERT_EQ(create_test_location(0, 1), GetCurrentLocation()); EXPECT_TRUE(result_selection_controller_->selected_result()); @@ -1353,6 +1443,7 @@ EXPECT_EQ(ResultSelectionController::MoveResult::kNone, result_selection_controller_->MoveSelection(down_arrow_)); + EXPECT_EQ(0, GetAndResetSelectionChangeCount()); EXPECT_FALSE(result_selection_controller_->selected_result()); EXPECT_FALSE(result_selection_controller_->selected_location_details()); @@ -1361,6 +1452,7 @@ EXPECT_EQ(ResultSelectionController::MoveResult::kResultChanged, result_selection_controller_->MoveSelection(down_arrow_)); + EXPECT_EQ(1, GetAndResetSelectionChangeCount()); ASSERT_EQ(create_test_location(0, 0), GetCurrentLocation()); EXPECT_TRUE(result_selection_controller_->selected_result());
diff --git a/ash/app_list/views/search_result_page_view.cc b/ash/app_list/views/search_result_page_view.cc index 32d6374..eb14c81 100644 --- a/ash/app_list/views/search_result_page_view.cc +++ b/ash/app_list/views/search_result_page_view.cc
@@ -21,6 +21,7 @@ #include "ash/public/cpp/app_list/app_list_config.h" #include "ash/public/cpp/app_list/app_list_features.h" #include "ash/public/cpp/view_shadow.h" +#include "base/bind.h" #include "base/memory/ptr_util.h" #include "ui/chromeos/search_box/search_box_constants.h" #include "ui/compositor/layer.h" @@ -170,7 +171,7 @@ // set transparent so that the rounded corner is not overwritten. SetBackground(std::make_unique<SearchResultPageBackground>( AppListConfig::instance().card_background_color())); - views::ScrollView* const scroller = new views::ScrollView; + auto scroller = std::make_unique<views::ScrollView>(); // Leaves a placeholder area for the search box and the separator below it. scroller->SetBorder(views::CreateEmptyBorder(gfx::Insets( kSearchBoxHeight + kSearchBoxBottomSpacing + kSeparatorThickness, 0, 0, @@ -181,14 +182,16 @@ // contents' size. Using zeroes doesn't prevent it from scrolling and sizing // correctly. scroller->ClipHeightTo(0, 0); - scroller->SetVerticalScrollBar(new ZeroWidthVerticalScrollBar); + scroller->SetVerticalScrollBar(new ZeroWidthVerticalScrollBar()); scroller->SetBackgroundColor(SK_ColorTRANSPARENT); - AddChildView(scroller); + AddChildView(std::move(scroller)); SetLayoutManager(std::make_unique<views::FillLayout>()); - result_selection_controller_ = - std::make_unique<ResultSelectionController>(&result_container_views_); + result_selection_controller_ = std::make_unique<ResultSelectionController>( + &result_container_views_, + base::BindRepeating(&SearchResultPageView::SelectedResultChanged, + base::Unretained(this))); } SearchResultPageView::~SearchResultPageView() = default; @@ -307,6 +310,26 @@ Layout(); } +void SearchResultPageView::SelectedResultChanged() { + if (!result_selection_controller_->selected_location_details() || + !result_selection_controller_->selected_result()) { + return; + } + + const ResultLocationDetails* selection_details = + result_selection_controller_->selected_location_details(); + views::View* selected_row = nullptr; + // For horizontal containers ensure that the whole container fits in the + // scroll view, to account for vertical padding within the container. + if (selection_details->container_is_horizontal) { + selected_row = result_container_views_[selection_details->container_index]; + } else { + selected_row = result_selection_controller_->selected_result(); + } + + selected_row->ScrollViewToVisible(); +} + void SearchResultPageView::OnSearchResultContainerResultsChanging() { // Block any result selection changes while result updates are in flight. // The selection will be reset once the results are all updated.
diff --git a/ash/app_list/views/search_result_page_view.h b/ash/app_list/views/search_result_page_view.h index 725206e..145f9d0 100644 --- a/ash/app_list/views/search_result_page_view.h +++ b/ash/app_list/views/search_result_page_view.h
@@ -89,6 +89,11 @@ // Sort the result container views. void ReorderSearchResultContainers(); + // Passed to |result_selection_controller_| as a callback that gets called + // when the currently selected result changes. + // Ensures that |scroller_| visible rect contains the newly selected result. + void SelectedResultChanged(); + AppListViewDelegate* view_delegate_; // The SearchResultContainerViews that compose the search page. All owned by
diff --git a/ash/assistant/assistant_ui_controller.cc b/ash/assistant/assistant_ui_controller.cc index be63e0b..f00d85e 100644 --- a/ash/assistant/assistant_ui_controller.cc +++ b/ash/assistant/assistant_ui_controller.cc
@@ -300,6 +300,15 @@ void AssistantUiController::OnProactiveSuggestionsViewHoverChanged( bool is_hovering) { + if (!proactive_suggestions_view_ || + !proactive_suggestions_view_->GetWidget() || + proactive_suggestions_view_->GetWidget()->IsClosed()) { + // Hover changed events may occur during the proactive suggestions widget's + // close sequence. When this occurs, we quit early as the proactive + // suggestions view is being destroyed. + return; + } + if (!is_hovering) { // When the user is no longer hovering over the proactive suggestions view // we need to reset the timer so that it will auto-close appropriately.
diff --git a/ash/events/switch_access_event_handler.cc b/ash/events/switch_access_event_handler.cc index 0d2ec9f..f7b619d2 100644 --- a/ash/events/switch_access_event_handler.cc +++ b/ash/events/switch_access_event_handler.cc
@@ -8,6 +8,8 @@ #include "ash/public/cpp/switch_access_event_handler_delegate.h" #include "ash/shell.h" #include "ui/events/event.h" +#include "ui/events/event_constants.h" +#include "ui/events/event_utils.h" namespace ash { @@ -101,8 +103,17 @@ bool SwitchAccessEventHandler::ShouldCancelEvent( const ui::KeyEvent& event) const { // Ignore virtual key events so users can type with the onscreen keyboard. - if (ignore_virtual_key_events_ && !event.HasNativeEvent()) - return false; + if (ignore_virtual_key_events_ && + event.source_device_id() == ui::ED_UNKNOWN_DEVICE) { + // When running Chrome OS on Linux, the source_device_id property is never + // populated. + auto* properties = event.properties(); + bool is_linux_xevent = + properties && + properties->find(ui::kPropertyKeyboardIBusFlag) != properties->end(); + if (!is_linux_xevent) + return false; + } if (forward_key_events_) return true;
diff --git a/ash/public/cpp/shelf_config.h b/ash/public/cpp/shelf_config.h index a4e2b80..4fb01a2 100644 --- a/ash/public/cpp/shelf_config.h +++ b/ash/public/cpp/shelf_config.h
@@ -81,6 +81,8 @@ // The extra padding added to status area tray buttons on the shelf. int status_area_hit_region_padding() const; + bool is_in_app() const { return !is_app_list_visible_; } + int app_icon_group_margin() const { return app_icon_group_margin_; } SkColor shelf_control_permanent_highlight_background() const { return shelf_control_permanent_highlight_background_;
diff --git a/ash/shelf/scrollable_shelf_view.cc b/ash/shelf/scrollable_shelf_view.cc index c1bd949..db757ae 100644 --- a/ash/shelf/scrollable_shelf_view.cc +++ b/ash/shelf/scrollable_shelf_view.cc
@@ -18,6 +18,7 @@ #include "ui/gfx/geometry/vector2d_conversions.h" #include "ui/gfx/skia_paint_util.h" #include "ui/views/focus/focus_search.h" +#include "ui/views/view_targeter_delegate.h" namespace ash { @@ -42,6 +43,9 @@ // neglected. constexpr int kFlingVelocityThreshold = 1000; +// Horizontal size of the tap areafor the overflow arrow button. +constexpr int kArrowButtonTapAreaHorizontal = 32; + // Sum of the shelf button size and the gap between shelf buttons. int GetUnit() { return ShelfConfig::Get()->button_size() + @@ -85,17 +89,6 @@ class ScrollableShelfView::GradientLayerDelegate : public ui::LayerDelegate { public: - struct FadeZone { - // Bounds of the fade in/out zone. - gfx::Rect zone_rect; - - // Specifies the type of FadeZone: fade in or fade out. - bool fade_in = false; - - // Indicates the drawing direction. - bool is_horizontal = false; - }; - GradientLayerDelegate() : layer_(ui::LAYER_TEXTURED) { layer_.set_delegate(this); layer_.SetFillsBoundsOpaquely(false); @@ -155,6 +148,41 @@ }; //////////////////////////////////////////////////////////////////////////////// +// ScrollableShelfArrowView + +class ScrollableShelfView::ScrollableShelfArrowView + : public ash::ScrollArrowView, + public views::ViewTargeterDelegate { + public: + explicit ScrollableShelfArrowView(ArrowType arrow_type, + bool is_horizontal_alignment, + Shelf* shelf, + ShelfButtonDelegate* shelf_button_delegate) + : ScrollArrowView(arrow_type, + is_horizontal_alignment, + shelf, + shelf_button_delegate) { + SetEventTargeter(std::make_unique<views::ViewTargeter>(this)); + } + ~ScrollableShelfArrowView() override = default; + + // views::ViewTargeterDelegate: + bool DoesIntersectRect(const views::View* target, + const gfx::Rect& rect) const override { + DCHECK_EQ(target, this); + gfx::Rect bounds = gfx::Rect(size()); + + // Calculate padding for the tap area. (Should be 32 x shelfButtonSize) + constexpr int horizontalPadding = + (kArrowButtonTapAreaHorizontal - kArrowButtonSize) / 2; + const int verticalPadding = + (ShelfConfig::Get()->button_size() - kArrowButtonSize) / 2; + bounds.Inset(gfx::Insets(-verticalPadding, -horizontalPadding)); + return bounds.Intersects(rect); + } +}; + +//////////////////////////////////////////////////////////////////////////////// // ScrollableShelfFocusSearch class ScrollableShelfFocusSearch : public views::FocusSearch { @@ -242,12 +270,12 @@ layer()->SetFillsBoundsOpaquely(false); // Initialize the left arrow button. - left_arrow_ = AddChildView(std::make_unique<ScrollArrowView>( + left_arrow_ = AddChildView(std::make_unique<ScrollableShelfArrowView>( ScrollArrowView::kLeft, GetShelf()->IsHorizontalAlignment(), GetShelf(), this)); // Initialize the right arrow button. - right_arrow_ = AddChildView(std::make_unique<ScrollArrowView>( + right_arrow_ = AddChildView(std::make_unique<ScrollableShelfArrowView>( ScrollArrowView::kRight, GetShelf()->IsHorizontalAlignment(), GetShelf(), this)); @@ -272,7 +300,8 @@ SetPaneFocusAndFocusDefault(); // Clears the gradient shader when the focus ring shows. - GradientLayerDelegate::FadeZone fade_zone = {gfx::Rect(), false, false}; + FadeZone fade_zone = {/*zone_rect=*/gfx::Rect(), /*fade_in=*/false, + /*is_horizontal=*/false}; gradient_layer_delegate_->set_fade_zone(fade_zone); gradient_layer_delegate_->layer()->SetBounds(layer()->bounds()); SchedulePaint(); @@ -896,37 +925,77 @@ } void ScrollableShelfView::UpdateGradientZone() { + FadeZone fade_zone = {/*zone_rect=*/gfx::Rect(), /*fade_in=*/false, + /*is_horizontal=*/false}; + + // Calculates the bounds of the gradient zone based on the arrow buttons' + // location. + if (right_arrow_->GetVisible()) + fade_zone = CalculateEndGradientZone(); + else if (left_arrow_->GetVisible()) + fade_zone = CalculateStartGradientZone(); + + gradient_layer_delegate_->set_fade_zone(fade_zone); + SchedulePaint(); +} + +ScrollableShelfView::FadeZone ScrollableShelfView::CalculateStartGradientZone() + const { gfx::Rect zone_rect; bool fade_in; const int zone_length = GetFadeZoneLength(); const bool is_horizontal_alignment = GetShelf()->IsHorizontalAlignment(); + const gfx::Rect left_arrow_bounds = left_arrow_->bounds(); - // Calculates the bounds of the gradient zone based on the arrow buttons' - // location. - if (right_arrow_->GetVisible()) { - const gfx::Rect right_arrow_bounds = right_arrow_->bounds(); - zone_rect = is_horizontal_alignment - ? gfx::Rect(right_arrow_bounds.x() - zone_length, 0, - zone_length, height()) - : gfx::Rect(0, right_arrow_bounds.y() - zone_length, - width(), zone_length); - fade_in = false; - } else if (left_arrow_->GetVisible()) { - const gfx::Rect left_arrow_bounds = left_arrow_->bounds(); - zone_rect = - is_horizontal_alignment - ? gfx::Rect(left_arrow_bounds.right(), 0, zone_length, height()) - : gfx::Rect(0, left_arrow_bounds.bottom(), width(), zone_length); - fade_in = true; + if (is_horizontal_alignment) { + int x; + + // Calculates the start location on x-axis of the gradient zone. + if (ShouldAdaptToRTL()) { + const gfx::Rect mirrored_left_arrow_bounds = + GetMirroredRect(left_arrow_bounds); + x = mirrored_left_arrow_bounds.x() - zone_length; + } else { + x = left_arrow_bounds.right(); + } + zone_rect = gfx::Rect(x, 0, zone_length, height()); } else { - zone_rect = gfx::Rect(); - fade_in = false; + zone_rect = gfx::Rect(0, left_arrow_bounds.bottom(), width(), zone_length); } - GradientLayerDelegate::FadeZone fade_zone = {zone_rect, fade_in, - is_horizontal_alignment}; - gradient_layer_delegate_->set_fade_zone(fade_zone); - SchedulePaint(); + fade_in = !ShouldAdaptToRTL(); + + return {zone_rect, fade_in, is_horizontal_alignment}; +} + +ScrollableShelfView::FadeZone ScrollableShelfView::CalculateEndGradientZone() + const { + gfx::Rect zone_rect; + bool fade_in; + const int zone_length = GetFadeZoneLength(); + const bool is_horizontal_alignment = GetShelf()->IsHorizontalAlignment(); + const gfx::Rect right_arrow_bounds = right_arrow_->bounds(); + + if (is_horizontal_alignment) { + int x; + + // Calculates the start location on x-axis of the gradient zone. + if (ShouldAdaptToRTL()) { + const gfx::Rect mirrored_right_arrow_bounds = + GetMirroredRect(right_arrow_bounds); + x = mirrored_right_arrow_bounds.right(); + } else { + x = right_arrow_bounds.x() - zone_length; + } + zone_rect = gfx::Rect(x, 0, zone_length, height()); + } else { + zone_rect = gfx::Rect(0, right_arrow_bounds.y() - zone_length, width(), + zone_length); + } + + fade_in = ShouldAdaptToRTL(); + + return {zone_rect, fade_in, is_horizontal_alignment}; } int ScrollableShelfView::GetActualScrollOffset() const {
diff --git a/ash/shelf/scrollable_shelf_view.h b/ash/shelf/scrollable_shelf_view.h index 73d47375..f34879e 100644 --- a/ash/shelf/scrollable_shelf_view.h +++ b/ash/shelf/scrollable_shelf_view.h
@@ -88,6 +88,18 @@ private: class GradientLayerDelegate; + class ScrollableShelfArrowView; + + struct FadeZone { + // Bounds of the fade in/out zone. + gfx::Rect zone_rect; + + // Specifies the type of FadeZone: fade in or fade out. + bool fade_in = false; + + // Indicates the drawing direction. + bool is_horizontal = false; + }; enum ScrollStatus { // Indicates whether the gesture scrolling is across the main axis. @@ -195,6 +207,11 @@ // Updates the gradient zone. void UpdateGradientZone(); + // Calculates the bounds of the gradient zone before/after the shelf + // container. + FadeZone CalculateStartGradientZone() const; + FadeZone CalculateEndGradientZone() const; + // Returns the actual scroll offset on the view's main axis. When the left // arrow button shows, |shelf_view_| is translated due to the change in // |shelf_container_view_|'s bounds. That translation offset is not included
diff --git a/ash/shelf/scrollable_shelf_view_unittest.cc b/ash/shelf/scrollable_shelf_view_unittest.cc index 5af9f645..951ca412 100644 --- a/ash/shelf/scrollable_shelf_view_unittest.cc +++ b/ash/shelf/scrollable_shelf_view_unittest.cc
@@ -4,6 +4,7 @@ #include "ash/shelf/scrollable_shelf_view.h" +#include "ash/public/cpp/shelf_config.h" #include "ash/shelf/shelf_test_util.h" #include "ash/shelf/shelf_tooltip_manager.h" #include "ash/shelf/shelf_view_test_api.h" @@ -39,8 +40,6 @@ ~ScrollableShelfViewTest() override = default; void SetUp() override { - base::CommandLine::ForCurrentProcess()->AppendSwitch( - chromeos::switches::kShelfScrollable); AshTestBase::SetUp(); scrollable_shelf_view_ = GetPrimaryShelf() ->shelf_widget() @@ -166,4 +165,46 @@ EXPECT_FALSE(tooltip_manager->IsVisible()); } +// Test that tapping near the scroll arrow button triggers scrolling. (see +// https://crbug.com/1004998) +TEST_F(ScrollableShelfViewTest, ScrollAfterTappingNearScrollArrow) { + AddAppShortcutUntilOverflow(); + + ASSERT_EQ(ScrollableShelfView::kShowRightArrowButton, + scrollable_shelf_view_->layout_strategy_for_test()); + + // Tap right arrow and check that the scrollable shelf now shows the left + // arrow only. Then do the same for the left arrow. + const gfx::Rect right_arrow = + scrollable_shelf_view_->right_arrow()->GetBoundsInScreen(); + GetEventGenerator()->GestureTapAt(right_arrow.CenterPoint()); + ASSERT_EQ(ScrollableShelfView::kShowLeftArrowButton, + scrollable_shelf_view_->layout_strategy_for_test()); + + const gfx::Rect left_arrow = + scrollable_shelf_view_->left_arrow()->GetBoundsInScreen(); + GetEventGenerator()->GestureTapAt(left_arrow.CenterPoint()); + ASSERT_EQ(ScrollableShelfView::kShowRightArrowButton, + scrollable_shelf_view_->layout_strategy_for_test()); + + // Recalculate the right arrow bounds considering the padding for the tap + // area. + const int horizontalPadding = (32 - right_arrow.width()) / 2; + const int verticalPadding = + (ShelfConfig::Get()->button_size() - right_arrow.height()) / 2; + + // Tap near the right arrow and check that the scrollable shelf now shows the + // left arrow only. Then do the same for the left arrow. + GetEventGenerator()->GestureTapAt( + gfx::Point(right_arrow.top_right().x() - horizontalPadding, + right_arrow.top_right().y() + verticalPadding)); + ASSERT_EQ(ScrollableShelfView::kShowLeftArrowButton, + scrollable_shelf_view_->layout_strategy_for_test()); + + GetEventGenerator()->GestureTapAt( + gfx::Point(left_arrow.top_right().x(), left_arrow.top_right().y())); + EXPECT_EQ(ScrollableShelfView::kShowRightArrowButton, + scrollable_shelf_view_->layout_strategy_for_test()); +} + } // namespace ash
diff --git a/ash/shelf/shelf_view.cc b/ash/shelf/shelf_view.cc index 3608326..5b80259c 100644 --- a/ash/shelf/shelf_view.cc +++ b/ash/shelf/shelf_view.cc
@@ -376,10 +376,14 @@ // We'll layout when our bounds change. - // Add the main shelf view as ShelfTooltipDelegate when scrollable shelf - // is not enabled. - if (!is_overflow_mode() && !chromeos::switches::ShouldShowScrollableShelf()) + if (chromeos::switches::ShouldShowScrollableShelf()) { + UpdateVisibleIndice(); + overflow_button_->SetVisible(false); + } else if (!is_overflow_mode()) { + // Add the main shelf view as ShelfTooltipDelegate when scrollable shelf + // is not enabled. shelf_->tooltip()->set_shelf_tooltip_delegate(this); + } } gfx::Rect ShelfView::GetIdealBoundsOfItemIcon(const ShelfID& id) { @@ -876,6 +880,15 @@ if (!button->IsIconSizeCurrent()) ShelfItemChanged(i, model_->items()[i]); } + + if (chromeos::switches::ShouldShowShelfHotseat() && IsTabletModeEnabled() && + !ShelfConfig::Get()->is_in_app()) { + SetBackground(views::CreateRoundedRectBackground( + ShelfConfig::Get()->shelf_control_permanent_highlight_background(), + ShelfConfig::Get()->button_size() / 2)); + } else { + SetBackground(views::CreateSolidBackground(SK_ColorTRANSPARENT)); + } } bool ShelfView::ShouldEventActivateButton(View* view, const ui::Event& event) { @@ -1185,10 +1198,8 @@ // When the scrollable shelf is enabled, overflow mode is disabled. Meanwhile, // centering padding is calculated in ScrollableShelfView, which means that // |center_on_screen| is always false. - if (chromeos::switches::ShouldShowScrollableShelf()) { - last_visible_index_ = view_model()->view_size() - 1; + if (chromeos::switches::ShouldShowScrollableShelf()) return strategy; - } // There are two possibilities. Either all the apps fit when centered // on the whole screen width, in which case we do that. Or, when space @@ -2124,6 +2135,11 @@ view->layer()->SetOpacity(0); view_model_->Add(view, model_index); + // When the scrollable shelf is enabled, |last_visible_index_| is always the + // index to the last shelf item. + if (chromeos::switches::ShouldShowScrollableShelf()) + UpdateVisibleIndice(); + // Give the button its ideal bounds. That way if we end up animating the // button before this animation completes it doesn't appear at some random // spot (because it was in the middle of animating from 0,0 0x0 to its @@ -2152,6 +2168,11 @@ views::View* view = view_model_->view_at(model_index); view_model_->Remove(model_index); + // When the scrollable shelf is enabled, |last_visible_index_| is always the + // index to the last shelf item. + if (chromeos::switches::ShouldShowScrollableShelf()) + UpdateVisibleIndice(); + { base::AutoReset<bool> cancelling_drag(&cancelling_drag_model_changed_, true); @@ -2497,4 +2518,10 @@ return item ? item->title : base::string16(); } +void ShelfView::UpdateVisibleIndice() { + DCHECK_EQ(true, chromeos::switches::ShouldShowScrollableShelf()); + first_visible_index_ = view_model()->view_size() == 0 ? -1 : 0; + last_visible_index_ = model_->item_count() - 1; +} + } // namespace ash
diff --git a/ash/shelf/shelf_view.h b/ash/shelf/shelf_view.h index 06e48c2..521eea4 100644 --- a/ash/shelf/shelf_view.h +++ b/ash/shelf/shelf_view.h
@@ -557,6 +557,10 @@ // Different from GetTitleForView, |view| here must be a child view. base::string16 GetTitleForChildView(const views::View* view) const; + // Update |first_visible_index_| and |last_visible_index_| when the scrollable + // shelf is enabled. + void UpdateVisibleIndice(); + // The model; owned by Launcher. ShelfModel* model_;
diff --git a/ash/shelf/shelf_widget.cc b/ash/shelf/shelf_widget.cc index ea9a2863..7fce164c 100644 --- a/ash/shelf/shelf_widget.cc +++ b/ash/shelf/shelf_widget.cc
@@ -29,6 +29,7 @@ #include "ash/shell.h" #include "ash/system/status_area_layout_manager.h" #include "ash/system/status_area_widget.h" +#include "ash/wm/tablet_mode/tablet_mode_controller.h" #include "base/command_line.h" #include "chromeos/constants/chromeos_switches.h" #include "ui/compositor/layer.h" @@ -202,8 +203,12 @@ const ShelfBackgroundType background_type = shelf_widget_->GetBackgroundType(); - if (!opaque_background_.visible()) - opaque_background_.SetVisible(true); + bool show_opaque_background = + !Shell::Get()->tablet_mode_controller()->InTabletMode() || + ShelfConfig::Get()->is_in_app() || + !chromeos::switches::ShouldShowShelfHotseat(); + if (show_opaque_background != opaque_background_.visible()) + opaque_background_.SetVisible(show_opaque_background); // Extend the opaque layer a little bit to handle "overshoot" gestures // gracefully (the user drags the shelf further than it can actually go).
diff --git a/ash/system/message_center/unified_message_center_bubble.cc b/ash/system/message_center/unified_message_center_bubble.cc index a1f43c86..4b1d8c6e 100644 --- a/ash/system/message_center/unified_message_center_bubble.cc +++ b/ash/system/message_center/unified_message_center_bubble.cc
@@ -14,6 +14,7 @@ #include "ash/system/unified/unified_system_tray.h" #include "ash/system/unified/unified_system_tray_bubble.h" #include "ash/system/unified/unified_system_tray_view.h" +#include "ui/views/focus/focus_search.h" #include "ui/views/widget/widget.h" namespace ash { @@ -29,12 +30,13 @@ init_params.max_width = kTrayMenuWidth; init_params.corner_radius = kUnifiedTrayCornerRadius; init_params.has_shadow = false; + init_params.close_on_deactivate = false; bubble_view_ = new TrayBubbleView(init_params); message_center_view_ = bubble_view_->AddChildView(std::make_unique<UnifiedMessageCenterView>( - nullptr /* parent */, tray->model())); + nullptr /* parent */, tray->model(), this)); message_center_view_->AddObserver(this); @@ -83,6 +85,14 @@ bubble_view_->ChangeAnchorRect(resting_bounds); } +void UnifiedMessageCenterBubble::FocusEntered(bool reverse) { + message_center_view_->FocusEntered(reverse); +} + +bool UnifiedMessageCenterBubble::FocusOut(bool reverse) { + return tray_->FocusQuickSettings(reverse); +} + TrayBackgroundView* UnifiedMessageCenterBubble::GetTray() const { return tray_; }
diff --git a/ash/system/message_center/unified_message_center_bubble.h b/ash/system/message_center/unified_message_center_bubble.h index 88bd1966..6d0bf39 100644 --- a/ash/system/message_center/unified_message_center_bubble.h +++ b/ash/system/message_center/unified_message_center_bubble.h
@@ -28,8 +28,16 @@ explicit UnifiedMessageCenterBubble(UnifiedSystemTray* tray); ~UnifiedMessageCenterBubble() override; + // Move the message center bubble to keep it on top of the quick settings + // widget whenever the quick settings widget is resized. void UpdatePosition(); + // Inform message_center_view_ of focus being acquired. + void FocusEntered(bool reverse); + + // Relinquish focus and transfer it to the quick settings widget. + bool FocusOut(bool reverse); + // TrayBubbleBase: TrayBackgroundView* GetTray() const override; TrayBubbleView* GetBubbleView() const override; @@ -43,6 +51,10 @@ // views::WidgetObserver: void OnWidgetDestroying(views::Widget* widget) override; + UnifiedMessageCenterView* message_center_view() { + return message_center_view_; + } + private: UnifiedSystemTray* const tray_;
diff --git a/ash/system/message_center/unified_message_center_bubble_unittest.cc b/ash/system/message_center/unified_message_center_bubble_unittest.cc index 360b3f8..9539c22b 100644 --- a/ash/system/message_center/unified_message_center_bubble_unittest.cc +++ b/ash/system/message_center/unified_message_center_bubble_unittest.cc
@@ -7,6 +7,8 @@ #include <memory> #include "ash/public/cpp/ash_features.h" +#include "ash/shell.h" +#include "ash/system/message_center/unified_message_center_view.h" #include "ash/system/tray/tray_constants.h" #include "ash/system/unified/unified_system_tray.h" #include "ash/system/unified/unified_system_tray_bubble.h" @@ -66,6 +68,38 @@ tray_bounds.y(); } + // Helper functions for focus cycle testing. + void DoTab() { + ui::test::EventGenerator generator(Shell::GetPrimaryRootWindow()); + generator.PressKey(ui::KeyboardCode::VKEY_TAB, ui::EventFlags::EF_NONE); + } + + void DoShiftTab() { + ui::test::EventGenerator generator(Shell::GetPrimaryRootWindow()); + generator.PressKey(ui::KeyboardCode::VKEY_TAB, + ui::EventFlags::EF_SHIFT_DOWN); + } + + views::View* GetFirstMessageCenterFocusable() { + return GetMessageCenterBubble() + ->message_center_view() + ->GetFirstFocusableChild(); + } + + views::View* GetLastMessageCenterFocusable() { + return GetMessageCenterBubble() + ->message_center_view() + ->GetLastFocusableChild(); + } + + views::View* GetFirstQuickSettingsFocusable() { + return GetSystemTrayBubble()->unified_view()->GetFirstFocusableChild(); + } + + views::View* GetLastQuickSettingsFocusable() { + return GetSystemTrayBubble()->unified_view()->GetLastFocusableChild(); + } + private: int id_ = 0; std::unique_ptr<base::test::ScopedFeatureList> scoped_feature_list_; @@ -117,4 +151,102 @@ } } +TEST_F(UnifiedMessageCenterBubbleTest, FocusCycle) { + EnableMessageCenterRefactor(); + GetPrimaryUnifiedSystemTray()->ShowBubble(true); + AddNotification(); + AddNotification(); + + views::Widget* quick_settings_widget = + GetSystemTrayBubble()->GetBubbleWidget(); + views::Widget* message_center_widget = + GetMessageCenterBubble()->GetBubbleWidget(); + + // First tab should focus the first element in the quick settings bubble. + DoTab(); + EXPECT_TRUE(quick_settings_widget->IsActive()); + EXPECT_FALSE(message_center_widget->IsActive()); + EXPECT_EQ(quick_settings_widget->GetFocusManager()->GetFocusedView(), + GetFirstQuickSettingsFocusable()); + + // Keep tabbing until we reach the last focusable element in the quick + // settings bubble. + while (quick_settings_widget->GetFocusManager()->GetFocusedView() != + GetLastQuickSettingsFocusable()) { + DoTab(); + } + + // Tab at the last element in the quick settings bubble should move focus to + // the first element in the message center. + DoTab(); + EXPECT_TRUE(message_center_widget->IsActive()); + EXPECT_FALSE(quick_settings_widget->IsActive()); + EXPECT_EQ(message_center_widget->GetFocusManager()->GetFocusedView(), + GetFirstMessageCenterFocusable()); + + // Keep tabbing until we reach the last focusable element in the message + // center bubble. + while (message_center_widget->GetFocusManager()->GetFocusedView() != + GetLastMessageCenterFocusable()) { + DoTab(); + } + + // Tab at the last element in the message center bubble should move focus to + // the first element in the quick settings bubble. + DoTab(); + EXPECT_TRUE(quick_settings_widget->IsActive()); + EXPECT_FALSE(message_center_widget->IsActive()); + EXPECT_EQ(quick_settings_widget->GetFocusManager()->GetFocusedView(), + GetFirstQuickSettingsFocusable()); +} + +TEST_F(UnifiedMessageCenterBubbleTest, ReverseFocusCycle) { + EnableMessageCenterRefactor(); + GetPrimaryUnifiedSystemTray()->ShowBubble(true); + AddNotification(); + AddNotification(); + + views::Widget* quick_settings_widget = + GetSystemTrayBubble()->GetBubbleWidget(); + views::Widget* message_center_widget = + GetMessageCenterBubble()->GetBubbleWidget(); + + // First shift tab should focus the last element in the quick settings bubble. + DoShiftTab(); + EXPECT_TRUE(quick_settings_widget->IsActive()); + EXPECT_FALSE(message_center_widget->IsActive()); + EXPECT_EQ(quick_settings_widget->GetFocusManager()->GetFocusedView(), + GetLastQuickSettingsFocusable()); + + // Keep shift tabbing until we reach the first focusable element in the quick + // settings bubble. + while (quick_settings_widget->GetFocusManager()->GetFocusedView() != + GetFirstQuickSettingsFocusable()) { + DoShiftTab(); + } + + // Shift tab at the first element in the quick settings bubble should move + // focus to the last element in the message center. + DoShiftTab(); + EXPECT_TRUE(message_center_widget->IsActive()); + EXPECT_FALSE(quick_settings_widget->IsActive()); + EXPECT_EQ(message_center_widget->GetFocusManager()->GetFocusedView(), + GetLastMessageCenterFocusable()); + + // Keep shift tabbing until we reach the first focusable element in the + // message center bubble. + while (message_center_widget->GetFocusManager()->GetFocusedView() != + GetFirstMessageCenterFocusable()) { + DoShiftTab(); + } + + // Shift tab at the first element in the message center bubble should move + // focus to the last element in the quick settings bubble. + DoShiftTab(); + EXPECT_TRUE(quick_settings_widget->IsActive()); + EXPECT_FALSE(message_center_widget->IsActive()); + EXPECT_EQ(quick_settings_widget->GetFocusManager()->GetFocusedView(), + GetLastQuickSettingsFocusable()); +} + } // namespace ash
diff --git a/ash/system/message_center/unified_message_center_view.cc b/ash/system/message_center/unified_message_center_view.cc index d560bd6..41ed6624 100644 --- a/ash/system/message_center/unified_message_center_view.cc +++ b/ash/system/message_center/unified_message_center_view.cc
@@ -15,6 +15,7 @@ #include "ash/style/default_color_constants.h" #include "ash/system/message_center/ash_message_center_lock_screen_controller.h" #include "ash/system/message_center/message_center_scroll_bar.h" +#include "ash/system/message_center/unified_message_center_bubble.h" #include "ash/system/message_center/unified_message_list_view.h" #include "ash/system/tray/tray_constants.h" #include "ash/system/tray/tray_popup_utils.h" @@ -35,6 +36,7 @@ #include "ui/views/background.h" #include "ui/views/controls/button/label_button.h" #include "ui/views/controls/scroll_view.h" +#include "ui/views/focus/focus_search.h" #include "ui/views/layout/box_layout.h" #include "ui/views/layout/fill_layout.h" #include "ui/views/widget/widget.h" @@ -279,15 +281,18 @@ UnifiedMessageCenterView::UnifiedMessageCenterView( UnifiedSystemTrayView* parent, - UnifiedSystemTrayModel* model) + UnifiedSystemTrayModel* model, + UnifiedMessageCenterBubble* bubble) : parent_(parent), model_(model), + message_center_bubble_(bubble), stacking_counter_(new StackingNotificationCounterView(this)), scroll_bar_(new MessageCenterScrollBar(this)), scroller_(new views::ScrollView()), message_list_view_(new UnifiedMessageListView(this, model)), last_scroll_position_from_bottom_(0), - animation_(std::make_unique<gfx::LinearAnimation>(this)) { + animation_(std::make_unique<gfx::LinearAnimation>(this)), + focus_search_(std::make_unique<views::FocusSearch>(this, false, false)) { message_list_view_->Init(); AddChildView(stacking_counter_); @@ -451,6 +456,29 @@ return; OnMessageCenterScrolled(); + + if (features::IsUnifiedMessageCenterRefactorEnabled()) { + views::View* first_view = GetFirstFocusableChild(); + views::View* last_view = GetLastFocusableChild(); + + // If we are cycling back to the first view from the last view or vice + // verse. Focus out of the message center to the quick settings bubble. The + // direction of the cycle determines where the focus will move to in quick + // settings. + bool focused_out = false; + if (before == last_view && now == first_view) + focused_out = message_center_bubble_->FocusOut(false /* reverse */); + else if (before == first_view && now == last_view) + focused_out = message_center_bubble_->FocusOut(true /* reverse */); + + // Clear the focus state completely for the message center. + // We acquire the focus back from the quick settings widget based on the + // cycling direction. + if (focused_out) { + GetFocusManager()->ClearFocus(); + GetFocusManager()->SetStoredFocusView(nullptr); + } + } } void UnifiedMessageCenterView::AnimationEnded(const gfx::Animation* animation) { @@ -621,4 +649,32 @@ SetNotificationRectBelowScroll(rect_below_scroll); } +void UnifiedMessageCenterView::FocusEntered(bool reverse) { + views::View* focus_view = + reverse ? GetLastFocusableChild() : GetFirstFocusableChild(); + GetFocusManager()->SetFocusedView(focus_view); +} + +views::View* UnifiedMessageCenterView::GetFirstFocusableChild() { + views::FocusTraversable* dummy_focus_traversable; + views::View* dummy_focus_traversable_view; + return focus_search_->FindNextFocusableView( + nullptr, views::FocusSearch::SearchDirection::kForwards, + views::FocusSearch::TraversalDirection::kDown, + views::FocusSearch::StartingViewPolicy::kSkipStartingView, + views::FocusSearch::AnchoredDialogPolicy::kCanGoIntoAnchoredDialog, + &dummy_focus_traversable, &dummy_focus_traversable_view); +} + +views::View* UnifiedMessageCenterView::GetLastFocusableChild() { + views::FocusTraversable* dummy_focus_traversable; + views::View* dummy_focus_traversable_view; + return focus_search_->FindNextFocusableView( + nullptr, views::FocusSearch::SearchDirection::kBackwards, + views::FocusSearch::TraversalDirection::kDown, + views::FocusSearch::StartingViewPolicy::kSkipStartingView, + views::FocusSearch::AnchoredDialogPolicy::kCanGoIntoAnchoredDialog, + &dummy_focus_traversable, &dummy_focus_traversable_view); +} + } // namespace ash
diff --git a/ash/system/message_center/unified_message_center_view.h b/ash/system/message_center/unified_message_center_view.h index aa9df6d..2f37b9b 100644 --- a/ash/system/message_center/unified_message_center_view.h +++ b/ash/system/message_center/unified_message_center_view.h
@@ -26,6 +26,7 @@ namespace ash { class MessageCenterScrollBar; +class UnifiedMessageCenterBubble; class UnifiedSystemTrayModel; class UnifiedSystemTrayView; @@ -92,7 +93,8 @@ public gfx::AnimationDelegate { public: UnifiedMessageCenterView(UnifiedSystemTrayView* parent, - UnifiedSystemTrayModel* model); + UnifiedSystemTrayModel* model, + UnifiedMessageCenterBubble* bubble); ~UnifiedMessageCenterView() override; // Sets the maximum height that the view can take. @@ -119,6 +121,11 @@ // Count number of notifications that are above visible area. int GetStackedNotificationCount() const; + // Set the first child view to be focused when focus is acquired. + // This is the first visible child unless reverse is true, in which case + // it is the last visible child. + void FocusEntered(bool reverse); + // views::View: void AddedToWidget() override; void RemovedFromWidget() override; @@ -148,6 +155,7 @@ private: friend class UnifiedMessageCenterViewTest; + friend class UnifiedMessageCenterBubbleTest; // Starts the animation to hide the notification stacking bar. void StartHideStackingBarAnimation(); @@ -169,8 +177,15 @@ // TopCornerBorder. void NotifyRectBelowScroll(); + // Get first and last focusable child views. These functions are used to + // figure out if we need to focus out or to set the correct focused view + // when focus is acquired from another widget. + View* GetFirstFocusableChild(); + View* GetLastFocusableChild(); + UnifiedSystemTrayView* const parent_; UnifiedSystemTrayModel* const model_; + UnifiedMessageCenterBubble* const message_center_bubble_; StackingNotificationCounterView* const stacking_counter_; MessageCenterScrollBar* const scroll_bar_; views::ScrollView* const scroller_; @@ -189,6 +204,8 @@ UnifiedMessageCenterAnimationState::IDLE; const std::unique_ptr<gfx::LinearAnimation> animation_; + const std::unique_ptr<views::FocusSearch> focus_search_; + views::FocusManager* focus_manager_ = nullptr; DISALLOW_COPY_AND_ASSIGN(UnifiedMessageCenterView);
diff --git a/ash/system/message_center/unified_message_center_view_unittest.cc b/ash/system/message_center/unified_message_center_view_unittest.cc index 4af630b..935a808e 100644 --- a/ash/system/message_center/unified_message_center_view_unittest.cc +++ b/ash/system/message_center/unified_message_center_view_unittest.cc
@@ -43,7 +43,9 @@ class TestUnifiedMessageCenterView : public UnifiedMessageCenterView { public: explicit TestUnifiedMessageCenterView(UnifiedSystemTrayModel* model) - : UnifiedMessageCenterView(nullptr, model) {} + : UnifiedMessageCenterView(nullptr /*parent*/, + model, + nullptr /*bubble*/) {} ~TestUnifiedMessageCenterView() override = default;
diff --git a/ash/system/unified/unified_system_tray.cc b/ash/system/unified/unified_system_tray.cc index 1fbf3447..7061232 100644 --- a/ash/system/unified/unified_system_tray.cc +++ b/ash/system/unified/unified_system_tray.cc
@@ -5,6 +5,7 @@ #include "ash/system/unified/unified_system_tray.h" #include "ash/accessibility/accessibility_controller_impl.h" +#include "ash/focus_cycler.h" #include "ash/public/cpp/ash_features.h" #include "ash/session/session_controller_impl.h" #include "ash/shelf/shelf.h" @@ -211,6 +212,31 @@ ui_delegate_->SetTrayBubbleHeight(height); } +bool UnifiedSystemTray::FocusMessageCenter(bool reverse) { + if (!IsMessageCenterBubbleShown()) + return false; + + views::Widget* message_center_widget = + message_center_bubble_->GetBubbleWidget(); + message_center_widget->widget_delegate()->SetCanActivate(true); + + Shell::Get()->focus_cycler()->FocusWidget(message_center_widget); + message_center_bubble_->FocusEntered(reverse); + + return true; +} + +bool UnifiedSystemTray::FocusQuickSettings(bool reverse) { + if (!IsBubbleShown()) + return false; + + views::Widget* quick_settings_widget = bubble_->GetBubbleWidget(); + Shell::Get()->focus_cycler()->FocusWidget(quick_settings_widget); + bubble_->FocusEntered(reverse); + + return true; +} + gfx::Rect UnifiedSystemTray::GetBubbleBoundsInScreen() const { return bubble_ ? bubble_->GetBoundsInScreen() : gfx::Rect(); }
diff --git a/ash/system/unified/unified_system_tray.h b/ash/system/unified/unified_system_tray.h index 8dfb7d5..eb1ba069 100644 --- a/ash/system/unified/unified_system_tray.h +++ b/ash/system/unified/unified_system_tray.h
@@ -97,6 +97,10 @@ // bubble is shown. void SetTrayBubbleHeight(int height); + bool FocusMessageCenter(bool reverse); + + bool FocusQuickSettings(bool reverse); + // TrayBackgroundView: bool PerformAction(const ui::Event& event) override; void ShowBubble(bool show_by_click) override;
diff --git a/ash/system/unified/unified_system_tray_bubble.cc b/ash/system/unified/unified_system_tray_bubble.cc index 69231dbb..6c236df 100644 --- a/ash/system/unified/unified_system_tray_bubble.cc +++ b/ash/system/unified/unified_system_tray_bubble.cc
@@ -253,6 +253,14 @@ return free_space_height_above_anchor - kUnifiedMenuPadding * 2; } +bool UnifiedSystemTrayBubble::FocusOut(bool reverse) { + return tray_->FocusMessageCenter(reverse); +} + +void UnifiedSystemTrayBubble::FocusEntered(bool reverse) { + unified_view_->FocusEntered(reverse); +} + void UnifiedSystemTrayBubble::OnDisplayConfigurationChanged() { UpdateBubbleBounds(); }
diff --git a/ash/system/unified/unified_system_tray_bubble.h b/ash/system/unified/unified_system_tray_bubble.h index 18a1103..14806d2 100644 --- a/ash/system/unified/unified_system_tray_bubble.h +++ b/ash/system/unified/unified_system_tray_bubble.h
@@ -84,6 +84,12 @@ // collapsed / expanded. int GetCurrentTrayHeight() const; + // Relinquish focus and transfer it to the message center widget. + bool FocusOut(bool reverse); + + // Inform UnifiedSystemTrayView of focus being acquired. + void FocusEntered(bool reverse); + // TrayBubbleBase: TrayBackgroundView* GetTray() const override; TrayBubbleView* GetBubbleView() const override;
diff --git a/ash/system/unified/unified_system_tray_controller.cc b/ash/system/unified/unified_system_tray_controller.cc index b5a69b5..d91c2ba 100644 --- a/ash/system/unified/unified_system_tray_controller.cc +++ b/ash/system/unified/unified_system_tray_controller.cc
@@ -300,6 +300,10 @@ unified_view_->GetWidget()->CloseNow(); } +bool UnifiedSystemTrayController::FocusOut(bool reverse) { + return bubble_->FocusOut(reverse); +} + void UnifiedSystemTrayController::EnsureExpanded() { if (detailed_view_controller_) { detailed_view_controller_.reset();
diff --git a/ash/system/unified/unified_system_tray_controller.h b/ash/system/unified/unified_system_tray_controller.h index 211472c..0412e791 100644 --- a/ash/system/unified/unified_system_tray_controller.h +++ b/ash/system/unified/unified_system_tray_controller.h
@@ -101,6 +101,10 @@ // Close the bubble. Called from a detailed view controller. void CloseBubble(); + // Inform UnifiedSystemTrayBubble that UnifiedSystemTrayView is requesting to + // relinquish focus. + bool FocusOut(bool reverse); + // Ensure the main view is expanded. Called from the slider bubble controller. void EnsureExpanded();
diff --git a/ash/system/unified/unified_system_tray_view.cc b/ash/system/unified/unified_system_tray_view.cc index 89eccdb..4d5bb978 100644 --- a/ash/system/unified/unified_system_tray_view.cc +++ b/ash/system/unified/unified_system_tray_view.cc
@@ -214,7 +214,8 @@ views::View* default_start_view = search_direction == FocusSearch::SearchDirection::kForwards ? view_->system_tray_container_ - : view_->notification_hidden_view_; + : view_->detailed_view_container_; + return views::FocusSearch::FindNextFocusableView( starting_view ? starting_view : default_start_view, search_direction, traversal_direction, @@ -279,8 +280,8 @@ Shell::Get()->session_controller(); if (!features::IsUnifiedMessageCenterRefactorEnabled()) { - message_center_view_ = - new UnifiedMessageCenterView(this, controller->model()); + message_center_view_ = new UnifiedMessageCenterView( + this, controller->model(), nullptr /* message_center_bubble */); AddChildView(message_center_view_); layout->SetFlexForView(message_center_view_, 1); } @@ -467,6 +468,34 @@ return feature_pods_container_->GetVisibleCount(); } +views::View* UnifiedSystemTrayView::GetFirstFocusableChild() { + FocusTraversable* focus_traversable = GetFocusTraversable(); + views::View* focus_traversable_view = this; + return focus_search_->FindNextFocusableView( + nullptr, FocusSearch::SearchDirection::kForwards, + FocusSearch::TraversalDirection::kDown, + FocusSearch::StartingViewPolicy::kSkipStartingView, + FocusSearch::AnchoredDialogPolicy::kCanGoIntoAnchoredDialog, + &focus_traversable, &focus_traversable_view); +} + +views::View* UnifiedSystemTrayView::GetLastFocusableChild() { + FocusTraversable* focus_traversable = GetFocusTraversable(); + views::View* focus_traversable_view = this; + return focus_search_->FindNextFocusableView( + nullptr, FocusSearch::SearchDirection::kBackwards, + FocusSearch::TraversalDirection::kDown, + FocusSearch::StartingViewPolicy::kSkipStartingView, + FocusSearch::AnchoredDialogPolicy::kCanGoIntoAnchoredDialog, + &focus_traversable, &focus_traversable_view); +} + +void UnifiedSystemTrayView::FocusEntered(bool reverse) { + views::View* focus_view = + reverse ? GetLastFocusableChild() : GetFirstFocusableChild(); + GetFocusManager()->SetFocusedView(focus_view); +} + void UnifiedSystemTrayView::OnGestureEvent(ui::GestureEvent* event) { gfx::Point screen_location = event->location(); ConvertPointToScreen(this, &screen_location); @@ -502,6 +531,19 @@ return "UnifiedSystemTrayView"; } +void UnifiedSystemTrayView::AddedToWidget() { + focus_manager_ = GetFocusManager(); + if (focus_manager_) + focus_manager_->AddFocusChangeListener(this); +} + +void UnifiedSystemTrayView::RemovedFromWidget() { + if (!focus_manager_) + return; + focus_manager_->RemoveFocusChangeListener(this); + focus_manager_ = nullptr; +} + views::FocusTraversable* UnifiedSystemTrayView::GetFocusTraversable() { return this; } @@ -518,4 +560,26 @@ return this; } +void UnifiedSystemTrayView::OnWillChangeFocus(views::View* before, + views::View* now) {} + +void UnifiedSystemTrayView::OnDidChangeFocus(views::View* before, + views::View* now) { + if (features::IsUnifiedMessageCenterRefactorEnabled()) { + views::View* first_view = GetFirstFocusableChild(); + views::View* last_view = GetLastFocusableChild(); + + bool focused_out = false; + if (before == last_view && now == first_view) + focused_out = controller_->FocusOut(false); + else if (before == first_view && now == last_view) + focused_out = controller_->FocusOut(true); + + if (focused_out) { + GetFocusManager()->ClearFocus(); + GetFocusManager()->SetStoredFocusView(nullptr); + } + } +} + } // namespace ash
diff --git a/ash/system/unified/unified_system_tray_view.h b/ash/system/unified/unified_system_tray_view.h index a07a42e..d86674af 100644 --- a/ash/system/unified/unified_system_tray_view.h +++ b/ash/system/unified/unified_system_tray_view.h
@@ -58,7 +58,8 @@ // Note that the term "UnifiedSystemTray" refers to entire bubble containing // both (1) and (2). class ASH_EXPORT UnifiedSystemTrayView : public views::View, - public views::FocusTraversable { + public views::FocusTraversable, + public views::FocusChangeListener { public: // Get the background color of unified system tray. static SkColor GetBackgroundColor(); @@ -91,6 +92,11 @@ void SaveFocus(); void RestoreFocus(); + // Set the first child view to be focused when focus is acquired. + // This is the first visible child unless reverse is true, in which case + // it is the last visible child. + void FocusEntered(bool reverse); + // Change the expanded state. 0.0 if collapsed, and 1.0 if expanded. // Otherwise, it shows intermediate state. void SetExpandedAmount(double expanded_amount); @@ -130,12 +136,18 @@ void ChildPreferredSizeChanged(views::View* child) override; const char* GetClassName() const override; views::FocusTraversable* GetFocusTraversable() override; + void AddedToWidget() override; + void RemovedFromWidget() override; // views::FocusTraversable: views::FocusSearch* GetFocusSearch() override; views::FocusTraversable* GetFocusTraversableParent() override; views::View* GetFocusTraversableParentView() override; + // views::FocusChangeListener: + void OnWillChangeFocus(views::View* before, views::View* now) override; + void OnDidChangeFocus(views::View* before, views::View* now) override; + NotificationHiddenView* notification_hidden_view_for_testing() { return notification_hidden_view_; } @@ -143,6 +155,14 @@ View* detailed_view_for_testing() { return detailed_view_container_; } private: + friend class UnifiedMessageCenterBubbleTest; + + // Get first and last focusable child views. These functions are used to + // figure out if we need to focus out or to set the correct focused view + // when focus is acquired from another widget. + View* GetFirstFocusableChild(); + View* GetLastFocusableChild(); + class FocusSearch; double expanded_amount_; @@ -171,6 +191,9 @@ views::View* saved_focused_view_ = nullptr; const std::unique_ptr<FocusSearch> focus_search_; + + views::FocusManager* focus_manager_ = nullptr; + const std::unique_ptr<ui::EventHandler> interacted_by_tap_recorder_; DISALLOW_COPY_AND_ASSIGN(UnifiedSystemTrayView);
diff --git a/ash/wm/splitview/split_view_controller.cc b/ash/wm/splitview/split_view_controller.cc index 9c137128..1a10632 100644 --- a/ash/wm/splitview/split_view_controller.cc +++ b/ash/wm/splitview/split_view_controller.cc
@@ -1019,23 +1019,21 @@ } aura::Window* root_window = GetDefaultSnappedWindow()->GetRootWindow(); - if (state_ == SplitViewState::kBothSnapped) { - // If overview is ended because of the window gets snapped, do not do - // exiting overview animation. + // If overview is ended because of a window getting snapped, suppress the + // overview exiting animation. + if (state_ == SplitViewState::kBothSnapped) overview_session->SetWindowListNotAnimatedWhenExiting(root_window); - return; - } - // If we're in clamshell splitview mode, do not auto snap overview window - // when overview ends. + // If clamshell split view mode is active, end it and bail out. if (split_view_type_ == SplitViewType::kClamshellType) { EndSplitView(); return; } - // If split view mode is active but only has one snapped window when overview - // mode is ending, retrieve the first snappable window in the overview window - // grid and snap it. + // Tablet split view mode is active. If it still only has one snapped window, + // snap the first snappable window in the overview grid on the other side. + if (state_ == SplitViewState::kBothSnapped) + return; OverviewGrid* current_grid = overview_session->GetGridWithRootWindow(root_window); if (!current_grid || current_grid->empty()) @@ -1526,12 +1524,6 @@ RestoreTransformIfApplicable(window); UpdateSplitViewStateAndNotifyObservers(); UpdateWindowStackingAfterSnap(window); - - // If there are two window snapped in clamshell mode, splitview mode is ended. - if (state_ == SplitViewState::kBothSnapped && - split_view_type_ == SplitViewType::kClamshellType) { - EndSplitView(); - } } void SplitViewController::OnSnappedWindowDetached(aura::Window* window,
diff --git a/base/android/java/src/org/chromium/base/ContextUtils.java b/base/android/java/src/org/chromium/base/ContextUtils.java index 167282a..e7007cc 100644 --- a/base/android/java/src/org/chromium/base/ContextUtils.java +++ b/base/android/java/src/org/chromium/base/ContextUtils.java
@@ -10,6 +10,7 @@ import android.content.ContextWrapper; import android.content.SharedPreferences; import android.content.res.AssetManager; +import android.os.Build; import android.os.Process; import android.preference.PreferenceManager; @@ -17,6 +18,7 @@ import org.chromium.base.annotations.JNINamespace; import org.chromium.base.annotations.MainDex; +import org.chromium.base.annotations.VerifiesOnP; /** * This class provides Android application context related utility methods. @@ -25,8 +27,6 @@ public class ContextUtils { private static final String TAG = "ContextUtils"; private static Context sApplicationContext; - // TODO(agrieve): Remove sProcessName caching when we stop supporting JB. - private static String sProcessName; /** * Initialization-on-demand holder. This exists for thread-safe lazy initialization. @@ -131,35 +131,22 @@ /** * @return Whether the process is isolated. */ + @SuppressWarnings("NewApi") public static boolean isIsolatedProcess() { - try { - return (Boolean) Process.class.getMethod("isIsolated").invoke(null); - } catch (Exception e) { // No multi-catch below API level 19 for reflection exceptions. - // If fallback logic is ever needed, refer to: - // https://chromium-review.googlesource.com/c/chromium/src/+/905563/1 - throw new RuntimeException(e); - } + // Was not made visible until Android P, but the method has always been there. + return Process.isIsolated(); } /** @return The name of the current process. E.g. "org.chromium.chrome:privileged_process0". */ + @VerifiesOnP public static String getProcessName() { - // Once we drop support JB, this method can be simplified to not cache sProcessName and call - // ActivityThread.currentProcessName(). - if (sProcessName != null) { - return sProcessName; + if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.P) { + return Application.getProcessName(); } try { - // An even more convenient ActivityThread.currentProcessName() exists, but was not added - // until JB MR2. Class<?> activityThreadClazz = Class.forName("android.app.ActivityThread"); - Object activityThread = - activityThreadClazz.getMethod("currentActivityThread").invoke(null); - // Before JB MR2, currentActivityThread() returns null when called on a non-UI thread. - // Cache the name to allow other threads to access it. - sProcessName = - (String) activityThreadClazz.getMethod("getProcessName").invoke(activityThread); - return sProcessName; - } catch (Exception e) { // No multi-catch below API level 19 for reflection exceptions. + return (String) activityThreadClazz.getMethod("currentProcessName").invoke(null); + } catch (Exception e) { // If fallback logic is ever needed, refer to: // https://chromium-review.googlesource.com/c/chromium/src/+/905563/1 throw new RuntimeException(e);
diff --git a/build/config/android/rules.gni b/build/config/android/rules.gni index deb412f..5936b57 100644 --- a/build/config/android/rules.gni +++ b/build/config/android/rules.gni
@@ -4100,6 +4100,7 @@ # any apk that depends on this library. # ignore_aidl: Whether to ignore .aidl files found with the .aar. # ignore_assets: Whether to ignore assets found in the .aar. + # ignore_manifest: Whether to ignore creating manifest. # ignore_native_libraries: Whether to ignore .so files found in the .aar. # See also extract_native_libraries. # ignore_proguard_configs: Whether to ignore proguard configs. @@ -4129,6 +4130,8 @@ _unpack_target_name = "${target_name}__unpack_aar" _ignore_aidl = defined(invoker.ignore_aidl) && invoker.ignore_aidl _ignore_assets = defined(invoker.ignore_assets) && invoker.ignore_assets + _ignore_manifest = + defined(invoker.ignore_manifest) && invoker.ignore_manifest _ignore_native_libraries = defined(invoker.ignore_native_libraries) && invoker.ignore_native_libraries _ignore_proguard_configs = defined(invoker.ignore_proguard_configs) && @@ -4193,10 +4196,10 @@ inputs = [ invoker.aar_path, ] - outputs = [ - "${_output_path}/AndroidManifest.xml", - ] - + outputs = [] + if (!_ignore_manifest) { + outputs += [ "${_output_path}/AndroidManifest.xml" ] + } if (!_strip_resources && _scanned_files.has_r_text_file) { # Certain packages, in particular Play Services have no R.txt even # though its presence is mandated by AAR spec. Such packages cause @@ -4231,7 +4234,8 @@ (_scanned_files.resources != [] || _scanned_files.has_r_text_file) # Create the android_resources target for resources. - if (_has_unignored_resources || !_scanned_files.is_manifest_empty) { + if (_has_unignored_resources || + (!_scanned_files.is_manifest_empty && !_ignore_manifest)) { _res_target_name = "${target_name}__res" android_resources(_res_target_name) { forward_variables_from(invoker, @@ -4246,7 +4250,9 @@ } deps += [ ":$_unpack_target_name" ] android_manifest_dep = ":$_unpack_target_name" - android_manifest = "${_output_path}/AndroidManifest.xml" + if (!_ignore_manifest) { + android_manifest = "${_output_path}/AndroidManifest.xml" + } resource_dirs = [] generated_resource_dirs = [] if (!_strip_resources && _scanned_files.resources != []) {
diff --git a/build/fuchsia/linux.sdk.sha1 b/build/fuchsia/linux.sdk.sha1 index e4c3ddf..af82c66 100644 --- a/build/fuchsia/linux.sdk.sha1 +++ b/build/fuchsia/linux.sdk.sha1
@@ -1 +1 @@ -8901536583754825344 \ No newline at end of file +8901506071232259296 \ No newline at end of file
diff --git a/build/fuchsia/mac.sdk.sha1 b/build/fuchsia/mac.sdk.sha1 index 99e4d73..908d9741 100644 --- a/build/fuchsia/mac.sdk.sha1 +++ b/build/fuchsia/mac.sdk.sha1
@@ -1 +1 @@ -8901534789813246320 \ No newline at end of file +8901506068351790832 \ No newline at end of file
diff --git a/cc/metrics/frame_sequence_tracker.cc b/cc/metrics/frame_sequence_tracker.cc index 8786c6f..587c9bb 100644 --- a/cc/metrics/frame_sequence_tracker.cc +++ b/cc/metrics/frame_sequence_tracker.cc
@@ -78,9 +78,7 @@ CompositorFrameReportingController* compositor_frame_reporting_controller) : is_single_threaded_(is_single_threaded), compositor_frame_reporting_controller_( - compositor_frame_reporting_controller) { - StartSequence(FrameSequenceTrackerType::kUniversal); -} + compositor_frame_reporting_controller) {} FrameSequenceTrackerCollection::~FrameSequenceTrackerCollection() { frame_trackers_.clear(); @@ -119,7 +117,6 @@ void FrameSequenceTrackerCollection::ClearAll() { frame_trackers_.clear(); removal_trackers_.clear(); - StartSequence(FrameSequenceTrackerType::kUniversal); } void FrameSequenceTrackerCollection::NotifyBeginImplFrame(
diff --git a/cc/metrics/frame_sequence_tracker_unittest.cc b/cc/metrics/frame_sequence_tracker_unittest.cc index 1c492db..f1a6ed6 100644 --- a/cc/metrics/frame_sequence_tracker_unittest.cc +++ b/cc/metrics/frame_sequence_tracker_unittest.cc
@@ -88,6 +88,8 @@ // The kTouchScroll tracker is created in the test constructor, and the // kUniversal tracker is created in the FrameSequenceTrackerCollection // constructor. + EXPECT_EQ(collection_.frame_trackers_.size(), 3u); + collection_.StartSequence(FrameSequenceTrackerType::kUniversal); EXPECT_EQ(collection_.frame_trackers_.size(), 4u); collection_.StopSequence(kCompositorAnimation); @@ -152,13 +154,19 @@ } TEST_F(FrameSequenceTrackerTest, UniversalTrackerCreation) { - // The universal tracker should have been created when the |collection_| is - // created. - EXPECT_TRUE(TrackerExists(FrameSequenceTrackerType::kUniversal)); + // The universal tracker should be explicitly created by the object that + // manages the |collection_| + EXPECT_FALSE(TrackerExists(FrameSequenceTrackerType::kUniversal)); } -TEST_F(FrameSequenceTrackerTest, UniversalTrackerExistsAfterClearAll) { +TEST_F(FrameSequenceTrackerTest, UniversalTrackerRestartableAfterClearAll) { + collection_.StartSequence(FrameSequenceTrackerType::kUniversal); + EXPECT_TRUE(TrackerExists(FrameSequenceTrackerType::kUniversal)); + collection_.ClearAll(); + EXPECT_FALSE(TrackerExists(FrameSequenceTrackerType::kUniversal)); + + collection_.StartSequence(FrameSequenceTrackerType::kUniversal); EXPECT_TRUE(TrackerExists(FrameSequenceTrackerType::kUniversal)); }
diff --git a/cc/trees/layer_tree_host_impl.cc b/cc/trees/layer_tree_host_impl.cc index 8d8d18e2..cd9fe74 100644 --- a/cc/trees/layer_tree_host_impl.cc +++ b/cc/trees/layer_tree_host_impl.cc
@@ -3466,6 +3466,8 @@ has_valid_layer_tree_frame_sink_ = true; auto* context_provider = layer_tree_frame_sink_->context_provider(); + frame_trackers_.StartSequence(FrameSequenceTrackerType::kUniversal); + if (context_provider) { max_texture_size_ = context_provider->ContextCapabilities().max_texture_size;
diff --git a/chrome/BUILD.gn b/chrome/BUILD.gn index 03dcf65..59c0b81 100644 --- a/chrome/BUILD.gn +++ b/chrome/BUILD.gn
@@ -1815,6 +1815,7 @@ ":angle_egl_symbols", ":angle_gles_symbols", ":chrome_symbols", + ":crashpad_symbols", ":swiftshader_egl_symbols", ":swiftshader_gles_symbols", ] @@ -1833,6 +1834,20 @@ ":chrome", ] } + extract_symbols("crashpad_symbols") { + binary = "$root_out_dir/crashpad_handler" + + if (current_cpu == "x86") { + # GYP used "ia32" so keep that naming for back-compat. + symbol_file = "$root_out_dir/crashpad.breakpad.ia32" + } else { + symbol_file = "$root_out_dir/crashpad.breakpad.$current_cpu" + } + + deps = [ + "//third_party/crashpad/crashpad/handler:crashpad_handler", + ] + } extract_symbols("swiftshader_egl_symbols") { binary = "$root_out_dir/swiftshader/libEGL.so"
diff --git a/chrome/android/BUILD.gn b/chrome/android/BUILD.gn index 90f21e2..aeac9d9 100644 --- a/chrome/android/BUILD.gn +++ b/chrome/android/BUILD.gn
@@ -509,6 +509,7 @@ "//chrome/android/features/keyboard_accessory:internal_java", "//chrome/android/features/media_router:java", "//chrome/android/features/test_dummy/internal:base_module_java", + "//chrome/android/modules/extra_icu/provider:java", "//chrome/browser/touch_to_fill/android/internal:java", ]
diff --git a/chrome/android/chrome_junit_test_java_sources.gni b/chrome/android/chrome_junit_test_java_sources.gni index 3d1fbe0..8b207ec 100644 --- a/chrome/android/chrome_junit_test_java_sources.gni +++ b/chrome/android/chrome_junit_test_java_sources.gni
@@ -156,6 +156,7 @@ "junit/src/org/chromium/chrome/browser/omnibox/geo/PlatformNetworksManagerTest.java", "junit/src/org/chromium/chrome/browser/omnibox/geo/VisibleNetworksTest.java", "junit/src/org/chromium/chrome/browser/omnibox/geo/VisibleNetworksTrackerTest.java", + "junit/src/org/chromium/chrome/browser/omnibox/status/StatusMediatorUnitTest.java", "junit/src/org/chromium/chrome/browser/omnibox/suggestions/base/BaseSuggestionViewTest.java", "junit/src/org/chromium/chrome/browser/omnibox/suggestions/base/SimpleHorizontalLayoutViewTest.java", "junit/src/org/chromium/chrome/browser/omnibox/suggestions/basic/BasicSuggestionProcessorTest.java",
diff --git a/chrome/android/features/autofill_assistant/java/src/org/chromium/chrome/browser/autofill_assistant/details/AssistantDetailsViewBinder.java b/chrome/android/features/autofill_assistant/java/src/org/chromium/chrome/browser/autofill_assistant/details/AssistantDetailsViewBinder.java index 46580ed..706fa26 100644 --- a/chrome/android/features/autofill_assistant/java/src/org/chromium/chrome/browser/autofill_assistant/details/AssistantDetailsViewBinder.java +++ b/chrome/android/features/autofill_assistant/java/src/org/chromium/chrome/browser/autofill_assistant/details/AssistantDetailsViewBinder.java
@@ -28,10 +28,10 @@ import org.chromium.base.ApiCompatibilityUtils; import org.chromium.chrome.autofill_assistant.R; -import org.chromium.chrome.browser.compositor.animation.CompositorAnimator; import org.chromium.chrome.browser.customtabs.CustomTabActivity; import org.chromium.chrome.browser.image_fetcher.ImageFetcher; import org.chromium.chrome.browser.modaldialog.AppModalPresenter; +import org.chromium.chrome.browser.ui.widget.animation.Interpolators; import org.chromium.ui.modaldialog.DialogDismissalCause; import org.chromium.ui.modaldialog.ModalDialogManager; import org.chromium.ui.modaldialog.ModalDialogManager.ModalDialogType; @@ -305,7 +305,7 @@ mPulseAnimation.setEvaluator(new ArgbEvaluator()); mPulseAnimation.setRepeatCount(ValueAnimator.INFINITE); mPulseAnimation.setRepeatMode(ValueAnimator.REVERSE); - mPulseAnimation.setInterpolator(CompositorAnimator.ACCELERATE_INTERPOLATOR); + mPulseAnimation.setInterpolator(Interpolators.ACCELERATE_INTERPOLATOR); mPulseAnimation.addListener(new AnimatorListenerAdapter() { @Override public void onAnimationCancel(Animator animation) {
diff --git a/chrome/android/features/autofill_assistant/java/src/org/chromium/chrome/browser/autofill_assistant/header/AnimatedProgressBar.java b/chrome/android/features/autofill_assistant/java/src/org/chromium/chrome/browser/autofill_assistant/header/AnimatedProgressBar.java index d36c220..afb812c 100644 --- a/chrome/android/features/autofill_assistant/java/src/org/chromium/chrome/browser/autofill_assistant/header/AnimatedProgressBar.java +++ b/chrome/android/features/autofill_assistant/java/src/org/chromium/chrome/browser/autofill_assistant/header/AnimatedProgressBar.java
@@ -10,7 +10,7 @@ import android.view.View; import org.chromium.base.VisibleForTesting; -import org.chromium.chrome.browser.compositor.animation.CompositorAnimator; +import org.chromium.chrome.browser.ui.widget.animation.Interpolators; import org.chromium.chrome.browser.widget.MaterialProgressBar; import java.util.ArrayDeque; @@ -54,7 +54,7 @@ ValueAnimator progressAnimation = ValueAnimator.ofInt(mLastProgress, progress); progressAnimation.setDuration( mProgressBarSpeedMs * Math.abs(progress - mLastProgress) / 100); - progressAnimation.setInterpolator(CompositorAnimator.ACCELERATE_INTERPOLATOR); + progressAnimation.setInterpolator(Interpolators.ACCELERATE_INTERPOLATOR); progressAnimation.addListener(new AnimatorListenerAdapter() { @Override public void onAnimationEnd(Animator animation) {
diff --git a/chrome/android/features/start_surface/DEPS b/chrome/android/features/start_surface/DEPS index 3b1fce5..175bf31 100644 --- a/chrome/android/features/start_surface/DEPS +++ b/chrome/android/features/start_surface/DEPS
@@ -1,3 +1,4 @@ include_rules = [ + "+chrome/browser/ui/android/widget", "+content/public/android/java/src/org/chromium/content_public", ] \ No newline at end of file
diff --git a/chrome/android/features/start_surface/internal/BUILD.gn b/chrome/android/features/start_surface/internal/BUILD.gn index d7192a4..6f6748a5 100644 --- a/chrome/android/features/start_surface/internal/BUILD.gn +++ b/chrome/android/features/start_surface/internal/BUILD.gn
@@ -95,6 +95,7 @@ ":java_resources", "//base:base_java", "//chrome/android:chrome_java", + "//chrome/browser/ui/android/widget:java", "//third_party/android_deps:android_support_v7_appcompat_java", "//third_party/android_deps:com_android_support_design_java", "//ui/android:ui_full_java",
diff --git a/chrome/android/features/start_surface/internal/java/src/org/chromium/chrome/features/start_surface/StartSurfaceLayout.java b/chrome/android/features/start_surface/internal/java/src/org/chromium/chrome/features/start_surface/StartSurfaceLayout.java index ab8cfd53..be45aa8 100644 --- a/chrome/android/features/start_surface/internal/java/src/org/chromium/chrome/features/start_surface/StartSurfaceLayout.java +++ b/chrome/android/features/start_surface/internal/java/src/org/chromium/chrome/features/start_surface/StartSurfaceLayout.java
@@ -4,8 +4,6 @@ package org.chromium.chrome.features.start_surface; -import static org.chromium.chrome.browser.compositor.animation.CompositorAnimator.FAST_OUT_SLOW_IN_INTERPOLATOR; - import android.animation.Animator; import android.animation.AnimatorListenerAdapter; import android.animation.AnimatorSet; @@ -37,6 +35,7 @@ import org.chromium.chrome.browser.fullscreen.ChromeFullscreenManager; import org.chromium.chrome.browser.tab.Tab; import org.chromium.chrome.browser.tasks.tab_management.TabSwitcher; +import org.chromium.chrome.browser.ui.widget.animation.Interpolators; import org.chromium.chrome.browser.util.FeatureUtilities; import org.chromium.ui.resources.ResourceManager; @@ -280,25 +279,25 @@ animationList.add(CompositorAnimator.ofFloatProperty( handler, sourceLayoutTab, LayoutTab.SCALE, () -> 1f, () -> { return target.get().width() / (getWidth() * mDpToPx); - }, ZOOMING_DURATION, FAST_OUT_SLOW_IN_INTERPOLATOR)); + }, ZOOMING_DURATION, Interpolators.FAST_OUT_SLOW_IN_INTERPOLATOR)); animationList.add(CompositorAnimator.ofFloatProperty( handler, sourceLayoutTab, LayoutTab.X, () -> 0f, () -> { return target.get().left / mDpToPx; - }, ZOOMING_DURATION, FAST_OUT_SLOW_IN_INTERPOLATOR)); + }, ZOOMING_DURATION, Interpolators.FAST_OUT_SLOW_IN_INTERPOLATOR)); animationList.add(CompositorAnimator.ofFloatProperty( handler, sourceLayoutTab, LayoutTab.Y, () -> 0f, () -> { return target.get().top / mDpToPx; - }, ZOOMING_DURATION, FAST_OUT_SLOW_IN_INTERPOLATOR)); + }, ZOOMING_DURATION, Interpolators.FAST_OUT_SLOW_IN_INTERPOLATOR)); // TODO(crbug.com/964406): when shrinking to the bottom row, bottom of the tab goes up and // down, making the "create group" visible for a while. animationList.add(CompositorAnimator.ofFloatProperty(handler, sourceLayoutTab, LayoutTab.MAX_CONTENT_HEIGHT, sourceLayoutTab.getUnclampedOriginalContentHeight(), - getWidth(), ZOOMING_DURATION, FAST_OUT_SLOW_IN_INTERPOLATOR)); + getWidth(), ZOOMING_DURATION, Interpolators.FAST_OUT_SLOW_IN_INTERPOLATOR)); CompositorAnimator backgroundAlpha = CompositorAnimator.ofFloat(handler, 0f, 1f, BACKGROUND_FADING_DURATION_MS, animator -> mBackgroundAlpha = animator.getAnimatedValue()); - backgroundAlpha.setInterpolator(CompositorAnimator.FAST_OUT_LINEAR_IN_INTERPOLATOR); + backgroundAlpha.setInterpolator(Interpolators.FAST_OUT_LINEAR_IN_INTERPOLATOR); animationList.add(backgroundAlpha); mTabToSwitcherAnimation = new AnimatorSet(); @@ -334,22 +333,24 @@ // Zoom in the source tab animationList.add(CompositorAnimator.ofFloatProperty(handler, sourceLayoutTab, LayoutTab.SCALE, source.width() / (getWidth() * mDpToPx), 1, ZOOMING_DURATION, - FAST_OUT_SLOW_IN_INTERPOLATOR)); + Interpolators.FAST_OUT_SLOW_IN_INTERPOLATOR)); animationList.add(CompositorAnimator.ofFloatProperty(handler, sourceLayoutTab, LayoutTab.X, - source.left / mDpToPx, 0f, ZOOMING_DURATION, FAST_OUT_SLOW_IN_INTERPOLATOR)); + source.left / mDpToPx, 0f, ZOOMING_DURATION, + Interpolators.FAST_OUT_SLOW_IN_INTERPOLATOR)); animationList.add(CompositorAnimator.ofFloatProperty(handler, sourceLayoutTab, LayoutTab.Y, - source.top / mDpToPx, 0f, ZOOMING_DURATION, FAST_OUT_SLOW_IN_INTERPOLATOR)); + source.top / mDpToPx, 0f, ZOOMING_DURATION, + Interpolators.FAST_OUT_SLOW_IN_INTERPOLATOR)); // TODO(crbug.com/964406): when shrinking to the bottom row, bottom of the tab goes up and // down, making the "create group" visible for a while. animationList.add(CompositorAnimator.ofFloatProperty(handler, sourceLayoutTab, LayoutTab.MAX_CONTENT_HEIGHT, getWidth(), sourceLayoutTab.getUnclampedOriginalContentHeight(), ZOOMING_DURATION, - FAST_OUT_SLOW_IN_INTERPOLATOR)); + Interpolators.FAST_OUT_SLOW_IN_INTERPOLATOR)); CompositorAnimator backgroundAlpha = CompositorAnimator.ofFloat(handler, 1f, 0f, BACKGROUND_FADING_DURATION_MS, animator -> mBackgroundAlpha = animator.getAnimatedValue()); - backgroundAlpha.setInterpolator(CompositorAnimator.FAST_OUT_LINEAR_IN_INTERPOLATOR); + backgroundAlpha.setInterpolator(Interpolators.FAST_OUT_LINEAR_IN_INTERPOLATOR); animationList.add(backgroundAlpha); mTabToSwitcherAnimation = new AnimatorSet();
diff --git a/chrome/android/features/tab_ui/java/src/org/chromium/chrome/browser/tasks/tab_management/TabGridDialogParent.java b/chrome/android/features/tab_ui/java/src/org/chromium/chrome/browser/tasks/tab_management/TabGridDialogParent.java index 0e60b346..68a5698b6 100644 --- a/chrome/android/features/tab_ui/java/src/org/chromium/chrome/browser/tasks/tab_management/TabGridDialogParent.java +++ b/chrome/android/features/tab_ui/java/src/org/chromium/chrome/browser/tasks/tab_management/TabGridDialogParent.java
@@ -4,11 +4,6 @@ package org.chromium.chrome.browser.tasks.tab_management; -import static org.chromium.chrome.browser.compositor.animation.CompositorAnimator.FAST_OUT_LINEAR_IN_INTERPOLATOR; -import static org.chromium.chrome.browser.compositor.animation.CompositorAnimator.FAST_OUT_SLOW_IN_INTERPOLATOR; -import static org.chromium.chrome.browser.compositor.animation.CompositorAnimator.LINEAR_INTERPOLATOR; -import static org.chromium.chrome.browser.compositor.animation.CompositorAnimator.LINEAR_OUT_SLOW_IN_INTERPOLATOR; - import android.animation.Animator; import android.animation.AnimatorListenerAdapter; import android.animation.AnimatorSet; @@ -40,6 +35,7 @@ import org.chromium.base.ApiCompatibilityUtils; import org.chromium.base.ContextUtils; import org.chromium.base.VisibleForTesting; +import org.chromium.chrome.browser.ui.widget.animation.Interpolators; import org.chromium.chrome.browser.widget.ScrimView; import org.chromium.chrome.tab_ui.R; import org.chromium.ui.interpolators.BakedBezierInterpolator; @@ -238,7 +234,7 @@ mUngroupBarShow = ObjectAnimator.ofFloat(mUngroupBar, View.TRANSLATION_Y, mUngroupBarHeight, 0); mUngroupBarShow.setDuration(DIALOG_ANIMATION_DURATION); - mUngroupBarShow.setInterpolator(LINEAR_OUT_SLOW_IN_INTERPOLATOR); + mUngroupBarShow.setInterpolator(Interpolators.LINEAR_OUT_SLOW_IN_INTERPOLATOR); mUngroupBarShow.addListener(new AnimatorListenerAdapter() { @Override public void onAnimationStart(Animator animation) { @@ -258,7 +254,7 @@ mUngroupBarHide = ObjectAnimator.ofFloat(mUngroupBar, View.TRANSLATION_Y, 0, mUngroupBarHeight); mUngroupBarHide.setDuration(DIALOG_ANIMATION_DURATION); - mUngroupBarHide.setInterpolator(FAST_OUT_LINEAR_IN_INTERPOLATOR); + mUngroupBarHide.setInterpolator(Interpolators.FAST_OUT_LINEAR_IN_INTERPOLATOR); mUngroupBarHide.addListener(new AnimatorListenerAdapter() { @Override public void onAnimationStart(Animator animation) { @@ -347,7 +343,7 @@ AnimatorSet cardZoomOutAnimatorSet = new AnimatorSet(); cardZoomOutAnimatorSet.setDuration(DIALOG_ANIMATION_DURATION); - cardZoomOutAnimatorSet.setInterpolator(FAST_OUT_SLOW_IN_INTERPOLATOR); + cardZoomOutAnimatorSet.setInterpolator(Interpolators.FAST_OUT_SLOW_IN_INTERPOLATOR); cardZoomOutAnimatorSet.play(cardZoomOutMoveYAnimator) .with(cardZoomOutMoveXAnimator) .with(cardZoomOutScaleYAnimator) @@ -358,7 +354,7 @@ final ObjectAnimator cardZoomOutAlphaAnimator = ObjectAnimator.ofFloat(mAnimationCardView, View.ALPHA, 1f, 0f); cardZoomOutAlphaAnimator.setDuration(DIALOG_ALPHA_ANIMATION_DURATION); - cardZoomOutAlphaAnimator.setInterpolator(LINEAR_INTERPOLATOR); + cardZoomOutAlphaAnimator.setInterpolator(Interpolators.LINEAR_INTERPOLATOR); // In the second half of the dialog showing animation, the dialog zooms out from where the // card stops at the end of the first half and moves towards where the dialog should be. @@ -373,7 +369,7 @@ AnimatorSet dialogZoomOutAnimatorSet = new AnimatorSet(); dialogZoomOutAnimatorSet.setDuration(DIALOG_ANIMATION_DURATION); - dialogZoomOutAnimatorSet.setInterpolator(FAST_OUT_SLOW_IN_INTERPOLATOR); + dialogZoomOutAnimatorSet.setInterpolator(Interpolators.FAST_OUT_SLOW_IN_INTERPOLATOR); dialogZoomOutAnimatorSet.play(dialogZoomOutMoveYAnimator) .with(dialogZoomOutMoveXAnimator) .with(dialogZoomOutScaleYAnimator) @@ -385,7 +381,7 @@ ObjectAnimator.ofFloat(mDialogContainerView, View.ALPHA, 0f, 1f); dialogZoomOutAlphaAnimator.setDuration(DIALOG_ALPHA_ANIMATION_DURATION); dialogZoomOutAlphaAnimator.setStartDelay(DIALOG_ALPHA_ANIMATION_DURATION); - dialogZoomOutAlphaAnimator.setInterpolator(LINEAR_INTERPOLATOR); + dialogZoomOutAlphaAnimator.setInterpolator(Interpolators.LINEAR_INTERPOLATOR); // During the whole dialog showing animation, the frame background scales up and moves so // that it looks like the card zooms out and becomes the dialog. @@ -400,7 +396,7 @@ AnimatorSet frameZoomOutAnimatorSet = new AnimatorSet(); frameZoomOutAnimatorSet.setDuration(DIALOG_ANIMATION_DURATION); - frameZoomOutAnimatorSet.setInterpolator(FAST_OUT_SLOW_IN_INTERPOLATOR); + frameZoomOutAnimatorSet.setInterpolator(Interpolators.FAST_OUT_SLOW_IN_INTERPOLATOR); frameZoomOutAnimatorSet.play(frameZoomOutMoveYAnimator) .with(frameZoomOutMoveXAnimator) .with(frameZoomOutScaleYAnimator) @@ -459,14 +455,14 @@ .with(dialogZoomInScaleYAnimator) .with(dialogZoomInScaleXAnimator); dialogZoomInAnimatorSet.setDuration(DIALOG_ANIMATION_DURATION); - dialogZoomInAnimatorSet.setInterpolator(FAST_OUT_SLOW_IN_INTERPOLATOR); + dialogZoomInAnimatorSet.setInterpolator(Interpolators.FAST_OUT_SLOW_IN_INTERPOLATOR); // In the first half of the dialog hiding animation, the dialog fades out while it moves and // scales down. final ObjectAnimator dialogZoomInAlphaAnimator = ObjectAnimator.ofFloat(mDialogContainerView, View.ALPHA, 1f, 0f); dialogZoomInAlphaAnimator.setDuration(DIALOG_ALPHA_ANIMATION_DURATION); - dialogZoomInAlphaAnimator.setInterpolator(LINEAR_INTERPOLATOR); + dialogZoomInAlphaAnimator.setInterpolator(Interpolators.LINEAR_INTERPOLATOR); // In the second half of the dialog hiding animation, the animation card zooms in from where // the dialog stops at the end of the first half and moves towards where the card should be. @@ -485,7 +481,7 @@ .with(cardZoomInScaleXAnimator) .with(cardZoomInScaleYAnimator); cardZoomInAnimatorSet.setDuration(DIALOG_ANIMATION_DURATION); - cardZoomInAnimatorSet.setInterpolator(FAST_OUT_SLOW_IN_INTERPOLATOR); + cardZoomInAnimatorSet.setInterpolator(Interpolators.FAST_OUT_SLOW_IN_INTERPOLATOR); // In the second half of the dialog hiding animation, the tab grid card fades in while it // scales down and moves. @@ -493,7 +489,7 @@ ObjectAnimator.ofFloat(mAnimationCardView, View.ALPHA, 0f, 1f); cardZoomInAlphaAnimator.setDuration(DIALOG_ALPHA_ANIMATION_DURATION); cardZoomInAlphaAnimator.setStartDelay(DIALOG_ALPHA_ANIMATION_DURATION); - cardZoomInAlphaAnimator.setInterpolator(LINEAR_INTERPOLATOR); + cardZoomInAlphaAnimator.setInterpolator(Interpolators.LINEAR_INTERPOLATOR); // During the whole dialog hiding animation, the frame background scales down and moves so // that it looks like the dialog zooms in and becomes the card. @@ -512,7 +508,7 @@ .with(frameZoomInScaleYAnimator) .with(frameZoomInScaleXAnimator); frameZoomInAnimatorSet.setDuration(DIALOG_ANIMATION_DURATION); - frameZoomInAnimatorSet.setInterpolator(FAST_OUT_SLOW_IN_INTERPOLATOR); + frameZoomInAnimatorSet.setInterpolator(Interpolators.FAST_OUT_SLOW_IN_INTERPOLATOR); // At the end of the dialog hiding animation, the original tab grid card fades in. final ObjectAnimator tabFadeInAnimator =
diff --git a/chrome/android/java/res/values/colors.xml b/chrome/android/java/res/values/colors.xml index afdd6f9..43161b36 100644 --- a/chrome/android/java/res/values/colors.xml +++ b/chrome/android/java/res/values/colors.xml
@@ -104,7 +104,7 @@ <color name="incognito_emphasis">@android:color/white</color> <!-- Overlay Panel colors --> - <color name="overlay_panel_bar_background_color">@color/default_bg_color_elev_2</color> + <color name="overlay_panel_bar_background_color">@color/default_bg_color_elev_4</color> <color name="overlay_panel_separator_line_color">@color/modern_secondary_color</color> <!-- Contextual Search colors -->
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/bookmarks/BookmarkActionBar.java b/chrome/android/java/src/org/chromium/chrome/browser/bookmarks/BookmarkActionBar.java index 13afb833..fe5930f 100644 --- a/chrome/android/java/src/org/chromium/chrome/browser/bookmarks/BookmarkActionBar.java +++ b/chrome/android/java/src/org/chromium/chrome/browser/bookmarks/BookmarkActionBar.java
@@ -15,7 +15,6 @@ import org.chromium.base.metrics.RecordUserAction; import org.chromium.chrome.R; import org.chromium.chrome.browser.bookmarks.BookmarkBridge.BookmarkItem; -import org.chromium.chrome.browser.bookmarks.BookmarkBridge.BookmarkModelObserver; import org.chromium.chrome.browser.preferences.PrefServiceBridge; import org.chromium.chrome.browser.tabmodel.TabLaunchType; import org.chromium.chrome.browser.tabmodel.document.TabDelegate; @@ -38,13 +37,6 @@ private BookmarkItem mCurrentFolder; private BookmarkDelegate mDelegate; - private BookmarkModelObserver mBookmarkModelObserver = new BookmarkModelObserver() { - @Override - public void bookmarkModelChanged() { - onSelectionStateChange(mDelegate.getSelectionDelegate().getSelectedItemsAsList()); - } - }; - public BookmarkActionBar(Context context, AttributeSet attrs) { super(context, attrs); setNavigationOnClickListener(this); @@ -163,7 +155,6 @@ mDelegate = delegate; mDelegate.addUIObserver(this); if (!delegate.isDialogUi()) getMenu().removeItem(R.id.close_menu_id); - delegate.getModel().addObserver(mBookmarkModelObserver); getMenu().setGroupEnabled(R.id.selection_mode_menu_group, true); } @@ -175,7 +166,6 @@ if (mDelegate == null) return; mDelegate.removeUIObserver(this); - mDelegate.getModel().removeObserver(mBookmarkModelObserver); } @Override
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/bookmarks/BookmarkBridge.java b/chrome/android/java/src/org/chromium/chrome/browser/bookmarks/BookmarkBridge.java index a3551a4..c605c66 100644 --- a/chrome/android/java/src/org/chromium/chrome/browser/bookmarks/BookmarkBridge.java +++ b/chrome/android/java/src/org/chromium/chrome/browser/bookmarks/BookmarkBridge.java
@@ -5,6 +5,7 @@ package org.chromium.chrome.browser.bookmarks; import android.os.SystemClock; +import android.support.annotation.Nullable; import android.text.TextUtils; import android.util.Pair; @@ -361,6 +362,7 @@ * @return A BookmarkItem instance for the given BookmarkId. * <code>null</code> if it doesn't exist. */ + @Nullable public BookmarkItem getBookmarkById(BookmarkId id) { assert mIsNativeBookmarkModelLoaded; return BookmarkBridgeJni.get().getBookmarkByID( @@ -754,7 +756,8 @@ /** * Notifies the observer that bookmark model has been loaded. */ - protected void notifyBookmarkModelLoaded() { + @VisibleForTesting + public void notifyBookmarkModelLoaded() { // Call isBookmarkModelLoaded() to do the check since it could be overridden by the child // class to add the addition logic. if (isBookmarkModelLoaded()) {
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/bookmarks/BookmarkItemsAdapter.java b/chrome/android/java/src/org/chromium/chrome/browser/bookmarks/BookmarkItemsAdapter.java index ce1470b..e5d72b84 100644 --- a/chrome/android/java/src/org/chromium/chrome/browser/bookmarks/BookmarkItemsAdapter.java +++ b/chrome/android/java/src/org/chromium/chrome/browser/bookmarks/BookmarkItemsAdapter.java
@@ -146,7 +146,8 @@ /** * @return The position of the given bookmark in adapter. Will return -1 if not found. */ - private int getPositionForBookmark(BookmarkId bookmark) { + @Override + public int getPositionForBookmark(BookmarkId bookmark) { assert bookmark != null; int position = -1; for (int i = 0; i < getItemCount(); i++) {
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/bookmarks/BookmarkManager.java b/chrome/android/java/src/org/chromium/chrome/browser/bookmarks/BookmarkManager.java index 6f32e23b..fcc7e7f7 100644 --- a/chrome/android/java/src/org/chromium/chrome/browser/bookmarks/BookmarkManager.java +++ b/chrome/android/java/src/org/chromium/chrome/browser/bookmarks/BookmarkManager.java
@@ -8,6 +8,7 @@ import android.app.ActivityManager; import android.content.Context; import android.support.v7.widget.RecyclerView; +import android.support.v7.widget.RecyclerView.AdapterDataObserver; import android.text.TextUtils; import android.view.View; import android.view.ViewGroup; @@ -76,6 +77,7 @@ // TODO(crbug.com/160194): Clean up after bookmark reordering launches. private ItemsAdapter mAdapter; private BookmarkDragStateDelegate mDragStateDelegate; + private AdapterDataObserver mAdapterDataObserver; /** * An adapter responsible for managing bookmark items. @@ -85,11 +87,14 @@ void notifyDataSetChanged(); void onBookmarkDelegateInitialized(BookmarkDelegate bookmarkDelegate); void search(String query); + void registerAdapterDataObserver(AdapterDataObserver observer); + void unregisterAdapterDataObserver(AdapterDataObserver observer); void moveUpOne(BookmarkId bookmarkId); void moveDownOne(BookmarkId bookmarkId); void highlightBookmark(BookmarkId bookmarkId); + int getPositionForBookmark(BookmarkId bookmarkId); } private final BookmarkModelObserver mBookmarkModelObserver = new BookmarkModelObserver() { @@ -112,7 +117,6 @@ openFolder(parent.getId()); } } - mSelectionDelegate.clearSelection(); // This is necessary as long as we rely on RecyclerView.ItemDecorations to apply padding // at the bottom of the bookmarks list to avoid the bottom navigation menu. This ensures @@ -122,19 +126,12 @@ } @Override - public void bookmarkNodeMoved(BookmarkItem oldParent, int oldIndex, BookmarkItem newParent, - int newIndex) { - mSelectionDelegate.clearSelection(); - } - - @Override public void bookmarkModelChanged() { // If the folder no longer exists in folder mode, we need to fall back. Relying on the // default behavior by setting the folder mode again. if (getCurrentState() == BookmarkUIState.STATE_FOLDER) { setState(mStateStack.peek()); } - mSelectionDelegate.clearSelection(); } }; @@ -203,7 +200,10 @@ mSelectionDelegate = new SelectionDelegate<BookmarkId>() { @Override public boolean toggleSelectionForItem(BookmarkId bookmark) { - if (!mBookmarkModel.getBookmarkById(bookmark).isEditable()) return false; + if (mBookmarkModel.getBookmarkById(bookmark) != null + && !mBookmarkModel.getBookmarkById(bookmark).isEditable()) { + return false; + } return super.toggleSelectionForItem(bookmark); } }; @@ -227,6 +227,18 @@ } else { mAdapter = new BookmarkItemsAdapter(activity); } + mAdapterDataObserver = new AdapterDataObserver() { + @Override + public void onItemRangeRemoved(int positionStart, int itemCount) { + syncAdapterAndSelectionDelegate(); + } + + @Override + public void onChanged() { + syncAdapterAndSelectionDelegate(); + } + }; + mAdapter.registerAdapterDataObserver(mAdapterDataObserver); mRecyclerView = mSelectableListLayout.initializeRecyclerView( (RecyclerView.Adapter<RecyclerView.ViewHolder>) mAdapter); @@ -296,6 +308,7 @@ * Destroys and cleans up itself. This must be called after done using this class. */ public void onDestroyed() { + mAdapter.unregisterAdapterDataObserver(mAdapterDataObserver); mIsDestroyed = true; RecordUserAction.record("MobileBookmarkManagerClose"); mSelectableListLayout.onDestroyed(); @@ -446,13 +459,25 @@ } } - mSelectionDelegate.clearSelection(); - for (BookmarkUIObserver observer : mUIObservers) { notifyStateChange(observer); } } + // TODO(lazzzis): This method can be moved to adapter after bookmark reordering launches. + /** + * Some bookmarks may be moved to another folder or removed in another devices. However, it may + * still be stored by {@link #mSelectionDelegate}, which causes incorrect selection counting. + */ + private void syncAdapterAndSelectionDelegate() { + for (BookmarkId node : mSelectionDelegate.getSelectedItemsAsList()) { + if (mSelectionDelegate.isItemSelected(node) + && mAdapter.getPositionForBookmark(node) == -1) { + mSelectionDelegate.toggleSelectionForItem(node); + } + } + } + @Override public void moveDownOne(BookmarkId bookmarkId) { mAdapter.moveDownOne(bookmarkId);
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/bookmarks/BookmarkRow.java b/chrome/android/java/src/org/chromium/chrome/browser/bookmarks/BookmarkRow.java index d516476..2ff8000 100644 --- a/chrome/android/java/src/org/chromium/chrome/browser/bookmarks/BookmarkRow.java +++ b/chrome/android/java/src/org/chromium/chrome/browser/bookmarks/BookmarkRow.java
@@ -265,7 +265,8 @@ @Override public void onSearchStateSet() {} - boolean isItemSelected() { + @VisibleForTesting + public boolean isItemSelected() { return mDelegate.getSelectionDelegate().isItemSelected(mBookmarkId); }
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/bookmarks/ReorderBookmarkItemsAdapter.java b/chrome/android/java/src/org/chromium/chrome/browser/bookmarks/ReorderBookmarkItemsAdapter.java index 4c357ce5..4520927 100644 --- a/chrome/android/java/src/org/chromium/chrome/browser/bookmarks/ReorderBookmarkItemsAdapter.java +++ b/chrome/android/java/src/org/chromium/chrome/browser/bookmarks/ReorderBookmarkItemsAdapter.java
@@ -127,7 +127,8 @@ /** * @return The position of the given bookmark in adapter. Will return -1 if not found. */ - private int getPositionForBookmark(BookmarkId bookmark) { + @Override + public int getPositionForBookmark(BookmarkId bookmark) { assert bookmark != null; int position = -1; for (int i = 0; i < getItemCount(); i++) {
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/compositor/animation/CompositorAnimator.java b/chrome/android/java/src/org/chromium/chrome/browser/compositor/animation/CompositorAnimator.java index 94770aef..dc1cad0 100644 --- a/chrome/android/java/src/org/chromium/chrome/browser/compositor/animation/CompositorAnimator.java +++ b/chrome/android/java/src/org/chromium/chrome/browser/compositor/animation/CompositorAnimator.java
@@ -10,12 +10,6 @@ import android.animation.TimeInterpolator; import android.animation.ValueAnimator; import android.provider.Settings; -import android.support.v4.view.animation.FastOutLinearInInterpolator; -import android.support.v4.view.animation.FastOutSlowInInterpolator; -import android.support.v4.view.animation.LinearOutSlowInInterpolator; -import android.view.animation.AccelerateInterpolator; -import android.view.animation.DecelerateInterpolator; -import android.view.animation.LinearInterpolator; import androidx.annotation.IntDef; import androidx.annotation.NonNull; @@ -25,6 +19,7 @@ import org.chromium.base.ObserverList; import org.chromium.base.Supplier; import org.chromium.base.VisibleForTesting; +import org.chromium.chrome.browser.ui.widget.animation.Interpolators; import java.lang.annotation.Retention; import java.lang.annotation.RetentionPolicy; @@ -110,19 +105,6 @@ */ private boolean mDidUpdateToCompletion; - /** Reference to one of each standard interpolator to avoid allocations. */ - public static final AccelerateInterpolator ACCELERATE_INTERPOLATOR = - new AccelerateInterpolator(); - public static final DecelerateInterpolator DECELERATE_INTERPOLATOR = - new DecelerateInterpolator(); - public static final FastOutSlowInInterpolator FAST_OUT_SLOW_IN_INTERPOLATOR = - new FastOutSlowInInterpolator(); - public static final LinearOutSlowInInterpolator LINEAR_OUT_SLOW_IN_INTERPOLATOR = - new LinearOutSlowInInterpolator(); - public static final FastOutLinearInInterpolator FAST_OUT_LINEAR_IN_INTERPOLATOR = - new FastOutLinearInInterpolator(); - public static final LinearInterpolator LINEAR_INTERPOLATOR = new LinearInterpolator(); - /** * A utility for creating a basic animator. * @param handler The {@link CompositorAnimationHandler} responsible for running the animation. @@ -201,7 +183,7 @@ final T target, final FloatProperty<T> property, float startValue, float endValue, long durationMs) { return ofFloatProperty(handler, target, property, startValue, endValue, durationMs, - DECELERATE_INTERPOLATOR); + Interpolators.DECELERATE_INTERPOLATOR); } /** @@ -218,7 +200,7 @@ final T target, final FloatProperty<T> property, Supplier<Float> startValue, Supplier<Float> endValue, long durationMs) { return ofFloatProperty(handler, target, property, startValue, endValue, durationMs, - DECELERATE_INTERPOLATOR); + Interpolators.DECELERATE_INTERPOLATOR); } /** An interface for listening for frames of an animation. */ @@ -239,7 +221,7 @@ // The default interpolator is decelerate; this mimics the existing ChromeAnimation // behavior. - mTimeInterpolator = DECELERATE_INTERPOLATOR; + mTimeInterpolator = Interpolators.DECELERATE_INTERPOLATOR; // By default, animate for 0 to 1. setValues(0, 1);
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/compositor/bottombar/contextualsearch/ContextualSearchCaptionControl.java b/chrome/android/java/src/org/chromium/chrome/browser/compositor/bottombar/contextualsearch/ContextualSearchCaptionControl.java index ecc75e7..96f743d 100644 --- a/chrome/android/java/src/org/chromium/chrome/browser/compositor/bottombar/contextualsearch/ContextualSearchCaptionControl.java +++ b/chrome/android/java/src/org/chromium/chrome/browser/compositor/bottombar/contextualsearch/ContextualSearchCaptionControl.java
@@ -16,6 +16,7 @@ import org.chromium.chrome.browser.compositor.bottombar.OverlayPanel; import org.chromium.chrome.browser.compositor.bottombar.OverlayPanelAnimation; import org.chromium.chrome.browser.compositor.bottombar.OverlayPanelTextViewInflater; +import org.chromium.chrome.browser.ui.widget.animation.Interpolators; import org.chromium.ui.resources.dynamics.DynamicResourceLoader; /** @@ -276,7 +277,7 @@ OverlayPanelAnimation.BASE_ANIMATION_DURATION_MS, null); mTransitionAnimator.addUpdateListener( animator -> mAnimationPercentage = animator.getAnimatedValue()); - mTransitionAnimator.setInterpolator(CompositorAnimator.FAST_OUT_SLOW_IN_INTERPOLATOR); + mTransitionAnimator.setInterpolator(Interpolators.FAST_OUT_SLOW_IN_INTERPOLATOR); mTransitionAnimator.start(); }
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/compositor/layouts/ToolbarSwipeLayout.java b/chrome/android/java/src/org/chromium/chrome/browser/compositor/layouts/ToolbarSwipeLayout.java index 2f2ba79..e04b5bd43 100644 --- a/chrome/android/java/src/org/chromium/chrome/browser/compositor/layouts/ToolbarSwipeLayout.java +++ b/chrome/android/java/src/org/chromium/chrome/browser/compositor/layouts/ToolbarSwipeLayout.java
@@ -23,6 +23,7 @@ import org.chromium.chrome.browser.fullscreen.ChromeFullscreenManager; import org.chromium.chrome.browser.tab.Tab; import org.chromium.chrome.browser.tabmodel.TabModel; +import org.chromium.chrome.browser.ui.widget.animation.Interpolators; import org.chromium.chrome.browser.util.MathUtils; import org.chromium.ui.base.LocalizationUtils; import org.chromium.ui.resources.ResourceManager; @@ -281,7 +282,7 @@ float progress = mOffset / getWidth(); float direction = Math.signum(progress); float smoothedProgress = - CompositorAnimator.DECELERATE_INTERPOLATOR.getInterpolation(Math.abs(progress)); + Interpolators.DECELERATE_INTERPOLATOR.getInterpolation(Math.abs(progress)); float maxSlide = getWidth() / 5.f; rightX = direction * smoothedProgress * maxSlide;
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/compositor/layouts/phone/stack/StackViewAnimation.java b/chrome/android/java/src/org/chromium/chrome/browser/compositor/layouts/phone/stack/StackViewAnimation.java index a564572..4617502b 100644 --- a/chrome/android/java/src/org/chromium/chrome/browser/compositor/layouts/phone/stack/StackViewAnimation.java +++ b/chrome/android/java/src/org/chromium/chrome/browser/compositor/layouts/phone/stack/StackViewAnimation.java
@@ -15,11 +15,11 @@ import android.widget.FrameLayout; import org.chromium.chrome.R; -import org.chromium.chrome.browser.compositor.animation.CompositorAnimator; import org.chromium.chrome.browser.compositor.layouts.phone.stack.StackAnimation.OverviewAnimationType; import org.chromium.chrome.browser.tab.Tab; import org.chromium.chrome.browser.tab.TabThemeColorHelper; import org.chromium.chrome.browser.tabmodel.TabList; +import org.chromium.chrome.browser.ui.widget.animation.Interpolators; /** * A factory that builds Android view animations for the tab stack. @@ -87,19 +87,19 @@ PropertyValuesHolder viewAlpha = PropertyValuesHolder.ofFloat(View.ALPHA, 0.f, 1.f); ObjectAnimator viewAlphaAnimator = ObjectAnimator.ofPropertyValuesHolder(view, viewAlpha); viewAlphaAnimator.setDuration(TAB_OPENED_VIEW_ANIMATION_DURATION); - viewAlphaAnimator.setInterpolator(CompositorAnimator.FAST_OUT_SLOW_IN_INTERPOLATOR); + viewAlphaAnimator.setInterpolator(Interpolators.FAST_OUT_SLOW_IN_INTERPOLATOR); PropertyValuesHolder yTranslation = PropertyValuesHolder.ofFloat(View.TRANSLATION_Y, mTranslationYStart, 0.f); ObjectAnimator viewYTranslationAnimator = ObjectAnimator.ofPropertyValuesHolder(view, yTranslation); viewYTranslationAnimator.setDuration(TAB_OPENED_VIEW_ANIMATION_DURATION); - viewYTranslationAnimator.setInterpolator(CompositorAnimator.FAST_OUT_SLOW_IN_INTERPOLATOR); + viewYTranslationAnimator.setInterpolator(Interpolators.FAST_OUT_SLOW_IN_INTERPOLATOR); PropertyValuesHolder bgAlpha = PropertyValuesHolder.ofFloat(View.ALPHA, 0.f, 1.f); ObjectAnimator bgAlphaAnimator = ObjectAnimator.ofPropertyValuesHolder(bgView, bgAlpha); bgAlphaAnimator.setDuration(TAB_OPENED_BG_ANIMATION_DURATION); - bgAlphaAnimator.setInterpolator(CompositorAnimator.FAST_OUT_SLOW_IN_INTERPOLATOR); + bgAlphaAnimator.setInterpolator(Interpolators.FAST_OUT_SLOW_IN_INTERPOLATOR); AnimatorSet set = new AnimatorSet(); set.playTogether(viewAlphaAnimator, viewYTranslationAnimator, bgAlphaAnimator);
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/download/DownloadManagerService.java b/chrome/android/java/src/org/chromium/chrome/browser/download/DownloadManagerService.java index 8d0563ff..364e26f0 100644 --- a/chrome/android/java/src/org/chromium/chrome/browser/download/DownloadManagerService.java +++ b/chrome/android/java/src/org/chromium/chrome/browser/download/DownloadManagerService.java
@@ -372,6 +372,7 @@ downloadItem.setSystemDownloadId( DownloadManagerBridge.getDownloadIdForDownloadGuid(downloadInfo.getDownloadGuid())); updateDownloadProgress(downloadItem, status); + updateDownloadInfoBar(downloadItem); } @Override @@ -382,6 +383,7 @@ removeAutoResumableDownload(item.getId()); } updateDownloadProgress(item, DownloadStatus.IN_PROGRESS); + updateDownloadInfoBar(item); scheduleUpdateIfNeeded(); } @@ -390,6 +392,7 @@ DownloadItem item = new DownloadItem(false, downloadInfo); removeAutoResumableDownload(item.getId()); updateDownloadProgress(new DownloadItem(false, downloadInfo), DownloadStatus.CANCELLED); + updateDownloadInfoBar(item); } @Override @@ -410,6 +413,7 @@ UmaBackgroundDownload.INTERRUPTED, downloadInfo.getDownloadGuid()); } updateDownloadProgress(item, status); + updateDownloadInfoBar(item); if (FeatureUtilities.isDownloadAutoResumptionEnabledInNative()) return; DownloadProgress progress = mDownloadProgressMap.get(item.getId()); @@ -460,6 +464,12 @@ } } + private void updateDownloadInfoBar(DownloadItem item) { + DownloadInfoBarController infobarController = + getInfoBarController(item.getDownloadInfo().isOffTheRecord()); + if (infobarController != null) infobarController.onDownloadItemUpdated(item); + } + /** * Broadcast that a download was successful. * @param downloadInfo info about the download. @@ -1769,9 +1779,6 @@ for (DownloadObserver adapter : mDownloadObservers) { adapter.onDownloadItemCreated(item); } - DownloadInfoBarController infobarController = - getInfoBarController(item.getDownloadInfo().isOffTheRecord()); - if (infobarController != null) infobarController.onDownloadItemUpdated(item); } @CalledByNative @@ -1779,10 +1786,6 @@ for (DownloadObserver adapter : mDownloadObservers) { adapter.onDownloadItemUpdated(item); } - - DownloadInfoBarController infobarController = - getInfoBarController(item.getDownloadInfo().isOffTheRecord()); - if (infobarController != null) infobarController.onDownloadItemUpdated(item); } @CalledByNative
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/download/DownloadSnackbarController.java b/chrome/android/java/src/org/chromium/chrome/browser/download/DownloadSnackbarController.java index 5054a5b..931f4a9 100644 --- a/chrome/android/java/src/org/chromium/chrome/browser/download/DownloadSnackbarController.java +++ b/chrome/android/java/src/org/chromium/chrome/browser/download/DownloadSnackbarController.java
@@ -129,8 +129,9 @@ } private boolean isShowingDownloadInfoBar() { - return DownloadManagerService.getDownloadManagerService() - .getInfoBarController(Profile.getLastUsedProfile().isOffTheRecord()) - .isShowing(); + DownloadInfoBarController infoBarController = + DownloadManagerService.getDownloadManagerService().getInfoBarController( + Profile.getLastUsedProfile().isOffTheRecord()); + return infoBarController == null ? false : infoBarController.isShowing(); } }
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/findinpage/FindToolbarTablet.java b/chrome/android/java/src/org/chromium/chrome/browser/findinpage/FindToolbarTablet.java index 98286d6..6a653c1 100644 --- a/chrome/android/java/src/org/chromium/chrome/browser/findinpage/FindToolbarTablet.java +++ b/chrome/android/java/src/org/chromium/chrome/browser/findinpage/FindToolbarTablet.java
@@ -12,11 +12,11 @@ import android.graphics.Rect; import android.util.AttributeSet; import android.view.View; -import android.view.animation.DecelerateInterpolator; import android.widget.FrameLayout; import org.chromium.chrome.R; import org.chromium.chrome.browser.ui.widget.animation.CancelAwareAnimatorListener; +import org.chromium.chrome.browser.ui.widget.animation.Interpolators; /** * A tablet specific version of the {@link FindToolbar}. @@ -58,7 +58,7 @@ mAnimationEnter = ObjectAnimator.ofFloat(this, View.TRANSLATION_X, translateWidth, 0); mAnimationEnter.setDuration(ENTER_EXIT_ANIMATION_DURATION_MS); - mAnimationEnter.setInterpolator(new DecelerateInterpolator()); + mAnimationEnter.setInterpolator(Interpolators.DECELERATE_INTERPOLATOR); mAnimationEnter.addListener(new CancelAwareAnimatorListener() { @Override public void onStart(Animator animation) { @@ -75,7 +75,7 @@ mAnimationLeave = ObjectAnimator.ofFloat(this, View.TRANSLATION_X, 0, translateWidth); mAnimationLeave.setDuration(ENTER_EXIT_ANIMATION_DURATION_MS); - mAnimationLeave.setInterpolator(new DecelerateInterpolator()); + mAnimationLeave.setInterpolator(Interpolators.DECELERATE_INTERPOLATOR); mAnimationLeave.addListener(new CancelAwareAnimatorListener() { @Override public void onStart(Animator animator) { @@ -146,7 +146,7 @@ mCurrentAnimation = ObjectAnimator.ofFloat(this, View.TRANSLATION_Y, translationY); mCurrentAnimation.setDuration(MAKE_ROOM_ANIMATION_DURATION_MS); - mCurrentAnimation.setInterpolator(new DecelerateInterpolator()); + mCurrentAnimation.setInterpolator(Interpolators.DECELERATE_INTERPOLATOR); mCurrentAnimation.addListener(new AnimatorListenerAdapter() { @Override public void onAnimationStart(Animator animation) {
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/gesturenav/SideSlideLayout.java b/chrome/android/java/src/org/chromium/chrome/browser/gesturenav/SideSlideLayout.java index e529a17..49a8d2e 100644 --- a/chrome/android/java/src/org/chromium/chrome/browser/gesturenav/SideSlideLayout.java +++ b/chrome/android/java/src/org/chromium/chrome/browser/gesturenav/SideSlideLayout.java
@@ -14,11 +14,11 @@ import android.view.animation.Animation.AnimationListener; import android.view.animation.AnimationSet; import android.view.animation.DecelerateInterpolator; -import android.view.animation.LinearInterpolator; import android.view.animation.ScaleAnimation; import android.view.animation.Transformation; import org.chromium.chrome.R; +import org.chromium.chrome.browser.ui.widget.animation.Interpolators; /** * The SideSlideLayout can be used whenever the user navigates the contents @@ -64,7 +64,6 @@ private static final int NAVIGATION_REVERSAL_MS = 3 * 1000; private final DecelerateInterpolator mDecelerateInterpolator; - private final LinearInterpolator mLinearInterpolator; private final float mTotalDragDistance; private final int mMediumAnimationDuration; private final int mCircleWidth; @@ -141,7 +140,6 @@ setWillNotDraw(false); mDecelerateInterpolator = new DecelerateInterpolator(DECELERATE_INTERPOLATION_FACTOR); - mLinearInterpolator = new LinearInterpolator(); mCircleWidth = (int) getResources().getDimensionPixelSize(R.dimen.navigation_bubble_size); @@ -199,7 +197,7 @@ mAnimationViewWidth = mArrowViewWidth; ScaleAnimation scalingDown = new ScaleAnimation(1, 0, 1, 0, mArrowViewWidth / 2, mArrowView.getHeight() / 2); - scalingDown.setInterpolator(mLinearInterpolator); + scalingDown.setInterpolator(Interpolators.LINEAR_INTERPOLATOR); scalingDown.setDuration(SCALE_DOWN_DURATION_MS); Animation fadingOut = new AlphaAnimation(1, 0); fadingOut.setInterpolator(mDecelerateInterpolator);
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/infobar/translate/TranslateTabLayout.java b/chrome/android/java/src/org/chromium/chrome/browser/infobar/translate/TranslateTabLayout.java index d9089f0..f81fe9a 100644 --- a/chrome/android/java/src/org/chromium/chrome/browser/infobar/translate/TranslateTabLayout.java +++ b/chrome/android/java/src/org/chromium/chrome/browser/infobar/translate/TranslateTabLayout.java
@@ -14,11 +14,11 @@ import android.util.AttributeSet; import android.view.LayoutInflater; import android.view.MotionEvent; -import android.view.animation.DecelerateInterpolator; import androidx.annotation.NonNull; import org.chromium.chrome.R; +import org.chromium.chrome.browser.ui.widget.animation.Interpolators; /** * TabLayout shown in the TranslateCompactInfoBar. @@ -216,7 +216,7 @@ getLayoutDirection() == LAYOUT_DIRECTION_RTL ? 0 : maxScrollDistance); mScrollToEndAnimator.setStartDelay(START_POSITION_WAIT_DURATION_MS); mScrollToEndAnimator.setDuration(SCROLL_DURATION_MS); - mScrollToEndAnimator.setInterpolator(new DecelerateInterpolator()); + mScrollToEndAnimator.setInterpolator(Interpolators.DECELERATE_INTERPOLATOR); mScrollToEndAnimator.addListener(new AnimatorListenerAdapter() { @Override public void onAnimationEnd(Animator animation) {
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/metrics/WebApkUma.java b/chrome/android/java/src/org/chromium/chrome/browser/metrics/WebApkUma.java index ebb767c0..d0d262c 100644 --- a/chrome/android/java/src/org/chromium/chrome/browser/metrics/WebApkUma.java +++ b/chrome/android/java/src/org/chromium/chrome/browser/metrics/WebApkUma.java
@@ -370,20 +370,10 @@ * @return The available space that can be used to install WebAPK. Negative value means there is * less free space available than the system's minimum by the given amount. */ - @SuppressWarnings("deprecation") public static long getAvailableSpaceAboveLowSpaceLimit() { - long partitionAvailableBytes; - long partitionTotalBytes; StatFs partitionStats = new StatFs(Environment.getDataDirectory().getAbsolutePath()); - if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.JELLY_BEAN_MR2) { - partitionAvailableBytes = partitionStats.getAvailableBytes(); - partitionTotalBytes = partitionStats.getTotalBytes(); - } else { - // these APIs were deprecated in API level 18. - long blockSize = partitionStats.getBlockSize(); - partitionAvailableBytes = blockSize * (long) partitionStats.getAvailableBlocks(); - partitionTotalBytes = blockSize * (long) partitionStats.getBlockCount(); - } + long partitionAvailableBytes = partitionStats.getAvailableBytes(); + long partitionTotalBytes = partitionStats.getTotalBytes(); long minimumFreeBytes = getLowSpaceLimitBytes(partitionTotalBytes); long webApkExtraSpaceBytes = 0;
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/night_mode/GlobalNightModeStateController.java b/chrome/android/java/src/org/chromium/chrome/browser/night_mode/GlobalNightModeStateController.java index 9c49e107..fa50584c 100644 --- a/chrome/android/java/src/org/chromium/chrome/browser/night_mode/GlobalNightModeStateController.java +++ b/chrome/android/java/src/org/chromium/chrome/browser/night_mode/GlobalNightModeStateController.java
@@ -128,7 +128,7 @@ private void updateNightMode() { boolean powerSaveModeOn = mPowerSaveModeMonitor.powerSavingIsOn(); - final int themeSetting = mChromePreferenceManager.readInt(UI_THEME_SETTING_KEY); + final int themeSetting = NightModeUtils.getThemeSetting(); final boolean newNightModeOn = themeSetting == ThemePreferences.ThemeSetting.SYSTEM_DEFAULT && (powerSaveModeOn || mSystemNightModeMonitor.isSystemNightModeOn()) || themeSetting == ThemePreferences.ThemeSetting.DARK;
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/night_mode/NightModeUtils.java b/chrome/android/java/src/org/chromium/chrome/browser/night_mode/NightModeUtils.java index f74f8588..3152fad 100644 --- a/chrome/android/java/src/org/chromium/chrome/browser/night_mode/NightModeUtils.java +++ b/chrome/android/java/src/org/chromium/chrome/browser/night_mode/NightModeUtils.java
@@ -4,6 +4,8 @@ package org.chromium.chrome.browser.night_mode; +import static org.chromium.chrome.browser.preferences.ChromePreferenceManager.UI_THEME_SETTING_KEY; + import android.app.Activity; import android.content.Context; import android.content.res.Configuration; @@ -15,6 +17,9 @@ import org.chromium.base.VisibleForTesting; import org.chromium.chrome.browser.ChromeBaseAppCompatActivity; +import org.chromium.chrome.browser.preferences.ChromePreferenceManager; +import org.chromium.chrome.browser.preferences.themes.ThemePreferences; +import org.chromium.chrome.browser.util.FeatureUtilities; /** * Helper methods for supporting night mode. @@ -125,6 +130,22 @@ return wrapper; } + /** + * The current theme setting, reflecting either the user setting or the default if the user has + * not explicitly set a preference. + * @return The current theme setting. See {@link ThemePreferences.ThemeSetting}. + */ + public static @ThemePreferences.ThemeSetting int getThemeSetting() { + int userSetting = ChromePreferenceManager.getInstance().readInt(UI_THEME_SETTING_KEY, -1); + if (userSetting == -1) { + return FeatureUtilities.isNightModeDefaultToLight() + ? ThemePreferences.ThemeSetting.LIGHT + : ThemePreferences.ThemeSetting.SYSTEM_DEFAULT; + } else { + return userSetting; + } + } + @VisibleForTesting public static void setNightModeSupportedForTesting(@Nullable Boolean nightModeSupported) { sNightModeSupportedForTest = nightModeSupported;
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/ntp/NewTabPage.java b/chrome/android/java/src/org/chromium/chrome/browser/ntp/NewTabPage.java index 5216811..2c3b28f 100644 --- a/chrome/android/java/src/org/chromium/chrome/browser/ntp/NewTabPage.java +++ b/chrome/android/java/src/org/chromium/chrome/browser/ntp/NewTabPage.java
@@ -9,7 +9,6 @@ import android.graphics.Point; import android.graphics.Rect; import android.graphics.drawable.Drawable; -import android.support.v4.view.ViewCompat; import android.support.v7.widget.RecyclerView; import android.view.LayoutInflater; import android.view.View; @@ -698,9 +697,11 @@ @Override public void destroy() { - assert !mIsDestroyed; - assert !ViewCompat - .isAttachedToWindow(getView()) : "Destroy called before removed from window"; + // Temporarily removing asserts during window when they're not compiled out of release + // builds, see https://crbug.com/992585 for more information. + // assert !mIsDestroyed; + // assert !ViewCompat + // .isAttachedToWindow(getView()) : "Destroy called before removed from window"; if (mIsLoaded && !mTab.isHidden()) recordNTPHidden(); mNewTabPageManager.onDestroy();
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/omnibox/LocationBarLayout.java b/chrome/android/java/src/org/chromium/chrome/browser/omnibox/LocationBarLayout.java index 85d6f0c..8b49fee 100644 --- a/chrome/android/java/src/org/chromium/chrome/browser/omnibox/LocationBarLayout.java +++ b/chrome/android/java/src/org/chromium/chrome/browser/omnibox/LocationBarLayout.java
@@ -79,7 +79,7 @@ LocationBarVoiceRecognitionHandler.Delegate { protected ImageButton mDeleteButton; protected ImageButton mMicButton; - protected View mUrlBar; + protected UrlBar mUrlBar; private final boolean mIsTablet; protected UrlBarCoordinator mUrlCoordinator; @@ -193,7 +193,7 @@ mAutocompleteCoordinator = AutocompleteCoordinatorFactory.createAutocompleteCoordinator( this, this, embedder, mUrlCoordinator); addUrlFocusChangeListener(mAutocompleteCoordinator); - mUrlCoordinator.setUrlTextChangeListener(mAutocompleteCoordinator); + mUrlCoordinator.addUrlTextChangeListener(mAutocompleteCoordinator); mMicButton = findViewById(R.id.mic_button); @@ -221,6 +221,7 @@ updateShouldAnimateIconChanges(); mUrlBar.setOnKeyListener(new UrlBarKeyListener()); + mUrlCoordinator.addUrlTextChangeListener(mStatusViewCoordinator); // mLocationBar's direction is tied to this UrlBar's text direction. Icons inside the // location bar, e.g. lock, refresh, X, should be reversed if UrlBar's text is RTL. @@ -435,7 +436,7 @@ mUrlCoordinator.setUrlBarData(UrlBarData.forNonUrlText(existingText), UrlBar.ScrollType.NO_SCROLL, UrlBarCoordinator.SelectionState.SELECT_END); - mAutocompleteCoordinator.onTextChangedForAutocomplete(); + forceOnTextChanged(); } } @@ -547,7 +548,7 @@ // This must be happen after requestUrlFocus(), which changes the selection. mUrlCoordinator.setUrlBarData(UrlBarData.forNonUrlText(pastedText), UrlBar.ScrollType.NO_SCROLL, UrlBarCoordinator.SelectionState.SELECT_END); - mAutocompleteCoordinator.onTextChangedForAutocomplete(); + forceOnTextChanged(); } else { ToolbarManager.recordOmniboxFocusReason(ToolbarManager.OmniboxFocusReason.FAKE_BOX_TAP); } @@ -910,7 +911,7 @@ private boolean setUrlBarTextEmpty() { boolean textChanged = mUrlCoordinator.setUrlBarData( UrlBarData.EMPTY, UrlBar.ScrollType.SCROLL_TO_BEGINNING, SelectionState.SELECT_ALL); - mAutocompleteCoordinator.onTextChangedForAutocomplete(); + forceOnTextChanged(); return textChanged; } @@ -1112,4 +1113,11 @@ public StatusViewCoordinator getStatusViewCoordinatorForTesting() { return mStatusViewCoordinator; } + + private void forceOnTextChanged() { + String textWithoutAutocomplete = mUrlCoordinator.getTextWithoutAutocomplete(); + String textWithAutocomplete = mUrlCoordinator.getTextWithoutAutocomplete(); + mAutocompleteCoordinator.onTextChanged(textWithoutAutocomplete, textWithAutocomplete); + mStatusViewCoordinator.onTextChanged(textWithoutAutocomplete, textWithAutocomplete); + } }
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/omnibox/UrlBar.java b/chrome/android/java/src/org/chromium/chrome/browser/omnibox/UrlBar.java index 2f99f8c..c7956f5 100644 --- a/chrome/android/java/src/org/chromium/chrome/browser/omnibox/UrlBar.java +++ b/chrome/android/java/src/org/chromium/chrome/browser/omnibox/UrlBar.java
@@ -212,10 +212,12 @@ /** Provides updates about the URL text changes. */ public interface UrlTextChangeListener { /** - * Called when the text state has changed and the autocomplete suggestions should be - * refreshed. + * Called when the text state has changed. + * @param textWithoutAutocomplete The url bar text without autocompletion. + * @param textWithAutocomplete The url bar text with autocompletion. */ - void onTextChangedForAutocomplete(); + // TODO(crbug.com/1003080): Consider splitting these into two different callbacks. + void onTextChanged(String textWithoutAutocomplete, String textWithAutocomplete); } /** Delegate that provides the additional functionality to the textual context menus. */ @@ -953,7 +955,7 @@ // crbug.com/764749 Log.w(TAG, "Text change observed, triggering autocomplete."); - mTextChangeListener.onTextChangedForAutocomplete(); + mTextChangeListener.onTextChanged(getTextWithoutAutocomplete(), getTextWithAutocomplete()); } /**
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/omnibox/UrlBarCoordinator.java b/chrome/android/java/src/org/chromium/chrome/browser/omnibox/UrlBarCoordinator.java index 12b03ec..8aa56a0 100644 --- a/chrome/android/java/src/org/chromium/chrome/browser/omnibox/UrlBarCoordinator.java +++ b/chrome/android/java/src/org/chromium/chrome/browser/omnibox/UrlBarCoordinator.java
@@ -56,8 +56,8 @@ } /** @see UrlBarMediator#setDelegate(UrlBarDelegate) */ - public void setUrlTextChangeListener(UrlTextChangeListener listener) { - mMediator.setUrlTextChangeListener(listener); + public void addUrlTextChangeListener(UrlTextChangeListener listener) { + mMediator.addUrlTextChangeListener(listener); } /** @see UrlBarMediator#setUrlBarData(UrlBarData, int, int) */
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/omnibox/UrlBarMediator.java b/chrome/android/java/src/org/chromium/chrome/browser/omnibox/UrlBarMediator.java index ec9cdeb..5cb8764 100644 --- a/chrome/android/java/src/org/chromium/chrome/browser/omnibox/UrlBarMediator.java +++ b/chrome/android/java/src/org/chromium/chrome/browser/omnibox/UrlBarMediator.java
@@ -29,11 +29,13 @@ import java.net.MalformedURLException; import java.net.URL; +import java.util.ArrayList; +import java.util.List; /** * Handles collecting and pushing state information to the UrlBar model. */ -class UrlBarMediator implements UrlBar.UrlBarTextContextMenuDelegate { +class UrlBarMediator implements UrlBar.UrlBarTextContextMenuDelegate, UrlBar.UrlTextChangeListener { private final PropertyModel mModel; private Callback<Boolean> mOnFocusChangeCallback; @@ -43,12 +45,15 @@ private @ScrollType int mScrollType = UrlBar.ScrollType.NO_SCROLL; private @SelectionState int mSelectionState = UrlBarCoordinator.SelectionState.SELECT_ALL; + private final List<UrlTextChangeListener> mUrlTextChangeListeners = new ArrayList<>(); + public UrlBarMediator(PropertyModel model) { mModel = model; mModel.set(UrlBarProperties.FOCUS_CHANGE_CALLBACK, this::onUrlFocusChange); mModel.set(UrlBarProperties.SHOW_CURSOR, false); mModel.set(UrlBarProperties.TEXT_CONTEXT_MENU_DELEGATE, this); + mModel.set(UrlBarProperties.URL_TEXT_CHANGE_LISTENER, this); setUseDarkTextColors(true); } @@ -59,9 +64,9 @@ mModel.set(UrlBarProperties.DELEGATE, delegate); } - /** Set the listener to be notified when the url text chagnes. */ - public void setUrlTextChangeListener(UrlTextChangeListener listener) { - mModel.set(UrlBarProperties.URL_TEXT_CHANGE_LISTENER, listener); + /** @see UrlBarMediator#setDelegate(UrlBarDelegate) */ + public void addUrlTextChangeListener(UrlTextChangeListener listener) { + mUrlTextChangeListeners.add(listener); } /** @@ -334,4 +339,12 @@ return url.substring(0, pathIndex); } + + @Override + public void onTextChanged(String textWithoutAutocomplete, String textWithAutocomplete) { + for (int i = 0; i < mUrlTextChangeListeners.size(); i++) { + mUrlTextChangeListeners.get(i).onTextChanged( + textWithoutAutocomplete, textWithAutocomplete); + } + } }
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/omnibox/status/StatusMediator.java b/chrome/android/java/src/org/chromium/chrome/browser/omnibox/status/StatusMediator.java index dfd5de1..35e4ac0 100644 --- a/chrome/android/java/src/org/chromium/chrome/browser/omnibox/status/StatusMediator.java +++ b/chrome/android/java/src/org/chromium/chrome/browser/omnibox/status/StatusMediator.java
@@ -5,25 +5,63 @@ package org.chromium.chrome.browser.omnibox.status; import android.content.res.Resources; +import android.graphics.Bitmap; +import android.text.TextUtils; import android.view.View; import androidx.annotation.ColorRes; import androidx.annotation.DrawableRes; import androidx.annotation.StringRes; +import org.chromium.base.Callback; import org.chromium.base.VisibleForTesting; +import org.chromium.base.library_loader.LibraryProcessType; import org.chromium.chrome.R; import org.chromium.chrome.browser.omnibox.SearchEngineLogoUtils; +import org.chromium.chrome.browser.omnibox.UrlBar; +import org.chromium.chrome.browser.omnibox.suggestions.AutocompleteCoordinatorFactory; import org.chromium.chrome.browser.profiles.Profile; import org.chromium.chrome.browser.toolbar.ToolbarCommonPropertiesModel; import org.chromium.chrome.browser.util.ColorUtils; import org.chromium.components.security_state.ConnectionSecurityLevel; +import org.chromium.content_public.browser.BrowserStartupController; import org.chromium.ui.modelutil.PropertyModel; /** * Contains the controller logic of the Status component. */ class StatusMediator { + @VisibleForTesting + class StatusMediatorDelegate { + /** @see {@link AutocompleteCoordinatorFactory#qualifyPartialURLQuery} */ + boolean isUrlValid(String partialUrl) { + return BrowserStartupController.get(LibraryProcessType.PROCESS_BROWSER) + .isFullBrowserStarted() + && AutocompleteCoordinatorFactory.qualifyPartialURLQuery(partialUrl) != null; + } + + /** @see {@link SearchEngineLogoUtils#getSearchEngineLogoFavicon} */ + void getSearchEngineLogoFavicon(Resources res, Callback<Bitmap> callback) { + SearchEngineLogoUtils.getSearchEngineLogoFavicon( + Profile.getLastUsedProfile().getOriginalProfile(), res, callback); + } + + /** @see {@link SearchEngineLogoUtils#shouldShowSearchEngineLogo} */ + boolean shouldShowSearchEngineLogo() { + return SearchEngineLogoUtils.shouldShowSearchEngineLogo(); + } + + /** @see {@link SearchEngineLogoUtils#shouldShowSearchLoupeEverywhere} */ + boolean shouldShowSearchLoupeEverywhere() { + return SearchEngineLogoUtils.shouldShowSearchLoupeEverywhere(); + } + + /** @see {@link SearchEngineLogoUtils#doesUrlMatchDefaultSearchEngine} */ + boolean doesUrlMatchDefaultSearchEngine(String url) { + return SearchEngineLogoUtils.doesUrlMatchDefaultSearchEngine(url); + } + } + // The size that the icon should be displayed as. private static final int SEARCH_ENGINE_LOGO_ICON_TARGET_SIZE_DP = 24; // The size given to LargeIconBridge to increase the probability that we'll get an icon back. @@ -53,11 +91,15 @@ private @StringRes int mSecurityIconDescriptionRes; private @DrawableRes int mNavigationIconTintRes; + private StatusMediatorDelegate mDelegate; private Resources mResources; private ToolbarCommonPropertiesModel mToolbarCommonPropertiesModel; + private String mUrlBarTextWithAutocomplete = ""; + private boolean mUrlBarTextIsValidUrl; StatusMediator(PropertyModel model, Resources resources) { mModel = model; + mDelegate = new StatusMediatorDelegate(); updateColorTheme(); mResources = resources; @@ -66,7 +108,8 @@ /** * Set the ToolbarDataProvider for this class. */ - void setToolbarDataProvider(ToolbarCommonPropertiesModel toolbarCommonPropertiesModel) { + void setToolbarCommonPropertiesModel( + ToolbarCommonPropertiesModel toolbarCommonPropertiesModel) { mToolbarCommonPropertiesModel = toolbarCommonPropertiesModel; } @@ -342,28 +385,30 @@ boolean showUnfocusedSearchResultsPage = !mUrlHasFocus && mToolbarCommonPropertiesModel != null && mToolbarCommonPropertiesModel.getDisplaySearchTerms() != null - && SearchEngineLogoUtils.doesUrlMatchDefaultSearchEngine( + && mDelegate.doesUrlMatchDefaultSearchEngine( mToolbarCommonPropertiesModel.getCurrentUrl()); - if (SearchEngineLogoUtils.shouldShowSearchEngineLogo() && mIsSearchEngineStateSetup + if (mDelegate.shouldShowSearchEngineLogo() && mIsSearchEngineStateSetup && (showFocused || showUnfocusedNewTabPage || showUnfocusedSearchResultsPage)) { mShouldCancelCustomFavicon = false; - mModel.set(StatusProperties.STATUS_ICON_TINT_RES, 0); - if (mIsSearchEngineGoogle) { + // If the current url text is a valid url, then swap the dse icon for a globe. + if (mUrlBarTextIsValidUrl) { + mModel.set(StatusProperties.STATUS_ICON_RES, R.drawable.ic_globe_24dp); + } else if (mIsSearchEngineGoogle) { mModel.set(StatusProperties.STATUS_ICON_RES, - SearchEngineLogoUtils.shouldShowSearchLoupeEverywhere() - ? R.drawable.omnibox_search + mDelegate.shouldShowSearchLoupeEverywhere() + ? R.drawable.ic_search : R.drawable.ic_logo_googleg_24dp); } else { mModel.set(StatusProperties.STATUS_ICON_RES, R.drawable.ic_search); - if (!SearchEngineLogoUtils.shouldShowSearchLoupeEverywhere()) { - SearchEngineLogoUtils.getSearchEngineLogoFavicon( - Profile.getLastUsedProfile().getOriginalProfile(), mResources, - (favicon) -> { - if (favicon == null || mShouldCancelCustomFavicon) return; - mModel.set(StatusProperties.STATUS_ICON, favicon); - }); + if (!mDelegate.shouldShowSearchLoupeEverywhere()) { + mDelegate.getSearchEngineLogoFavicon(mResources, (favicon) -> { + if (favicon == null || mShouldCancelCustomFavicon) return; + mModel.set(StatusProperties.STATUS_ICON, favicon); + }); } } + // None of the icons associated with dse should be tinted. + mModel.set(StatusProperties.STATUS_ICON_TINT_RES, 0); return; } else { mShouldCancelCustomFavicon = true; @@ -411,4 +456,22 @@ return 0; } + + /** @see {@link UrlBar.UrlTextChangeListener} */ + void onTextChanged(String urlTextWithoutAutocomplete, String urlTextWithAutocomplete) { + if (TextUtils.equals(mUrlBarTextWithAutocomplete, urlTextWithAutocomplete)) { + return; + } + + mUrlBarTextWithAutocomplete = urlTextWithAutocomplete; + boolean isValid = mDelegate.isUrlValid(mUrlBarTextWithAutocomplete); + if (isValid != mUrlBarTextIsValidUrl) { + mUrlBarTextIsValidUrl = isValid; + updateLocationBarIcon(); + } + } + + void setDelegateForTesting(StatusMediatorDelegate delegate) { + mDelegate = delegate; + } }
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/omnibox/status/StatusViewCoordinator.java b/chrome/android/java/src/org/chromium/chrome/browser/omnibox/status/StatusViewCoordinator.java index 92f5e356..0d7a07f 100644 --- a/chrome/android/java/src/org/chromium/chrome/browser/omnibox/status/StatusViewCoordinator.java +++ b/chrome/android/java/src/org/chromium/chrome/browser/omnibox/status/StatusViewCoordinator.java
@@ -11,6 +11,7 @@ import org.chromium.base.VisibleForTesting; import org.chromium.chrome.R; +import org.chromium.chrome.browser.omnibox.UrlBar; import org.chromium.chrome.browser.page_info.PageInfoController; import org.chromium.chrome.browser.toolbar.ToolbarDataProvider; import org.chromium.ui.modelutil.PropertyModel; @@ -20,7 +21,7 @@ * A component for displaying a status icon (e.g. security icon or navigation icon) and optional * verbose status text. */ -public class StatusViewCoordinator implements View.OnClickListener { +public class StatusViewCoordinator implements View.OnClickListener, UrlBar.UrlTextChangeListener { private final StatusView mStatusView; private final StatusMediator mMediator; private final PropertyModel mModel; @@ -64,7 +65,7 @@ */ public void setToolbarDataProvider(ToolbarDataProvider toolbarDataProvider) { mToolbarDataProvider = toolbarDataProvider; - mMediator.setToolbarDataProvider(mToolbarDataProvider); + mMediator.setToolbarCommonPropertiesModel(mToolbarDataProvider); // Update status immediately after receiving the data provider to avoid initial presence // glitch on tablet devices. This glitch would be typically seen upon launch of app, right // before the landing page is presented to the user. @@ -212,4 +213,9 @@ public int getStatusIconWidth() { return mStatusView.getStatusIconWidth(); } + + @Override + public void onTextChanged(String textWithoutAutocomplete, String textWithAutocomplete) { + mMediator.onTextChanged(textWithoutAutocomplete, textWithAutocomplete); + } }
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/omnibox/suggestions/AutocompleteCoordinatorImpl.java b/chrome/android/java/src/org/chromium/chrome/browser/omnibox/suggestions/AutocompleteCoordinatorImpl.java index b94819e..cdab2c3 100644 --- a/chrome/android/java/src/org/chromium/chrome/browser/omnibox/suggestions/AutocompleteCoordinatorImpl.java +++ b/chrome/android/java/src/org/chromium/chrome/browser/omnibox/suggestions/AutocompleteCoordinatorImpl.java
@@ -254,8 +254,8 @@ } @Override - public void onTextChangedForAutocomplete() { - mMediator.onTextChangedForAutocomplete(); + public void onTextChanged(String textWithoutAutocomplete, String textWithAutocomplete) { + mMediator.onTextChanged(textWithoutAutocomplete, textWithAutocomplete); } @Override
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/omnibox/suggestions/AutocompleteMediator.java b/chrome/android/java/src/org/chromium/chrome/browser/omnibox/suggestions/AutocompleteMediator.java index 7310ec68..3581f2f 100644 --- a/chrome/android/java/src/org/chromium/chrome/browser/omnibox/suggestions/AutocompleteMediator.java +++ b/chrome/android/java/src/org/chromium/chrome/browser/omnibox/suggestions/AutocompleteMediator.java
@@ -553,7 +553,8 @@ if (!isUrlSuggestion) refineText = TextUtils.concat(refineText, " ").toString(); mDelegate.setOmniboxEditingText(refineText); - onTextChangedForAutocomplete(); + onTextChanged(mUrlBarEditingTextProvider.getTextWithoutAutocomplete(), + mUrlBarEditingTextProvider.getTextWithAutocomplete()); if (isUrlSuggestion) { RecordUserAction.record("MobileOmniboxRefineSuggestion.Url"); } else { @@ -713,7 +714,7 @@ * Notifies the autocomplete system that the text has changed that drives autocomplete and the * autocomplete suggestions should be updated. */ - public void onTextChangedForAutocomplete() { + public void onTextChanged(String textWithoutAutocomplete, String textWithAutocomplete) { // crbug.com/764749 Log.w(TAG, "onTextChangedForAutocomplete"); @@ -729,7 +730,7 @@ } stopAutocomplete(false); - if (TextUtils.isEmpty(mUrlBarEditingTextProvider.getTextWithoutAutocomplete())) { + if (TextUtils.isEmpty(textWithoutAutocomplete)) { // crbug.com/764749 Log.w(TAG, "onTextChangedForAutocomplete: url is empty"); hideSuggestions(); @@ -737,8 +738,6 @@ } else { assert mRequestSuggestions == null : "Multiple omnibox requests in flight."; mRequestSuggestions = () -> { - String textWithoutAutocomplete = - mUrlBarEditingTextProvider.getTextWithoutAutocomplete(); boolean preventAutocomplete = !mUrlBarEditingTextProvider.shouldAutocomplete(); mRequestSuggestions = null;
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/payments/ui/DimmingDialog.java b/chrome/android/java/src/org/chromium/chrome/browser/payments/ui/DimmingDialog.java index bbe68e9..10a6756 100644 --- a/chrome/android/java/src/org/chromium/chrome/browser/payments/ui/DimmingDialog.java +++ b/chrome/android/java/src/org/chromium/chrome/browser/payments/ui/DimmingDialog.java
@@ -15,8 +15,6 @@ import android.graphics.Color; import android.graphics.drawable.ColorDrawable; import android.os.Build; -import android.support.v4.view.animation.FastOutLinearInInterpolator; -import android.support.v4.view.animation.LinearOutSlowInInterpolator; import android.view.Gravity; import android.view.View; import android.view.View.OnLayoutChangeListener; @@ -30,6 +28,7 @@ import org.chromium.chrome.R; import org.chromium.chrome.browser.ui.widget.AlwaysDismissedDialog; import org.chromium.chrome.browser.ui.widget.animation.AnimatorProperties; +import org.chromium.chrome.browser.ui.widget.animation.Interpolators; import org.chromium.chrome.browser.util.ColorUtils; /** @@ -185,7 +184,7 @@ AnimatorSet alphaSet = new AnimatorSet(); alphaSet.playTogether(scrimFader, alphaAnimator); alphaSet.setDuration(DIALOG_ENTER_ANIMATION_MS); - alphaSet.setInterpolator(new LinearOutSlowInInterpolator()); + alphaSet.setInterpolator(Interpolators.LINEAR_OUT_SLOW_IN_INTERPOLATOR); alphaSet.start(); } } @@ -206,7 +205,7 @@ AnimatorSet current = new AnimatorSet(); current.setDuration(DIALOG_EXIT_ANIMATION_MS); - current.setInterpolator(new FastOutLinearInInterpolator()); + current.setInterpolator(Interpolators.FAST_OUT_LINEAR_IN_INTERPOLATOR); if (mIsDialogClosing) { Animator scrimFader = ObjectAnimator.ofInt(mFullContainer.getBackground(), AnimatorProperties.DRAWABLE_ALPHA_PROPERTY, 127, 0);
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/payments/ui/PaymentRequestSection.java b/chrome/android/java/src/org/chromium/chrome/browser/payments/ui/PaymentRequestSection.java index aa5363f..f3b0bab 100644 --- a/chrome/android/java/src/org/chromium/chrome/browser/payments/ui/PaymentRequestSection.java +++ b/chrome/android/java/src/org/chromium/chrome/browser/payments/ui/PaymentRequestSection.java
@@ -9,7 +9,6 @@ import android.graphics.drawable.Drawable; import android.os.Handler; import android.support.v4.view.MarginLayoutParamsCompat; -import android.support.v4.view.animation.LinearOutSlowInInterpolator; import android.support.v7.widget.GridLayout; import android.text.SpannableStringBuilder; import android.text.TextUtils; @@ -39,6 +38,7 @@ import org.chromium.chrome.R; import org.chromium.chrome.browser.ui.widget.DualControlLayout; import org.chromium.chrome.browser.ui.widget.TintedDrawable; +import org.chromium.chrome.browser.ui.widget.animation.Interpolators; import org.chromium.chrome.browser.widget.prefeditor.EditableOption; import org.chromium.ui.HorizontalListDividerDrawable; import org.chromium.ui.UiUtils; @@ -546,7 +546,7 @@ public void run() { Animation out = new AlphaAnimation(mUpdatedView.getAlpha(), 0.0f); out.setDuration(UPDATE_TEXT_ANIMATION_DURATION_MS); - out.setInterpolator(new LinearOutSlowInInterpolator()); + out.setInterpolator(Interpolators.LINEAR_OUT_SLOW_IN_INTERPOLATOR); out.setFillAfter(true); mUpdatedView.startAnimation(out); } @@ -717,7 +717,7 @@ // to avoid restarting a previous or current fade in animation. Animation in = new AlphaAnimation(mUpdatedView.getAlpha(), 1.0f); in.setDuration(UPDATE_TEXT_ANIMATION_DURATION_MS); - in.setInterpolator(new LinearOutSlowInInterpolator()); + in.setInterpolator(Interpolators.LINEAR_OUT_SLOW_IN_INTERPOLATOR); in.setFillAfter(true); mUpdatedView.startAnimation(in);
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/payments/ui/PaymentRequestUI.java b/chrome/android/java/src/org/chromium/chrome/browser/payments/ui/PaymentRequestUI.java index 78873e1..c178d38 100644 --- a/chrome/android/java/src/org/chromium/chrome/browser/payments/ui/PaymentRequestUI.java +++ b/chrome/android/java/src/org/chromium/chrome/browser/payments/ui/PaymentRequestUI.java
@@ -18,7 +18,6 @@ import android.graphics.Bitmap; import android.os.Handler; import android.support.v4.view.ViewCompat; -import android.support.v4.view.animation.LinearOutSlowInInterpolator; import android.text.SpannableString; import android.text.TextUtils; import android.text.method.LinkMovementMethod; @@ -46,6 +45,7 @@ import org.chromium.chrome.browser.payments.ui.PaymentRequestSection.SectionSeparator; import org.chromium.chrome.browser.ui.widget.FadingEdgeScrollView; import org.chromium.chrome.browser.ui.widget.animation.FocusAnimator; +import org.chromium.chrome.browser.ui.widget.animation.Interpolators; import org.chromium.chrome.browser.widget.prefeditor.EditableOption; import org.chromium.chrome.browser.widget.prefeditor.EditorDialog; import org.chromium.chrome.browser.widget.prefeditor.EditorObserverForTest; @@ -1203,7 +1203,7 @@ mSheetAnimator = ObjectAnimator.ofFloat( mRequestView, View.TRANSLATION_Y, mAnimatorTranslation, 0); mSheetAnimator.setDuration(DIALOG_ENTER_ANIMATION_MS); - mSheetAnimator.setInterpolator(new LinearOutSlowInInterpolator()); + mSheetAnimator.setInterpolator(Interpolators.LINEAR_OUT_SLOW_IN_INTERPOLATOR); mSheetAnimator.addListener(this); mSheetAnimator.start(); } @@ -1269,7 +1269,7 @@ mSheetAnimator = containerAnimator; mSheetAnimator.setDuration(DIALOG_ENTER_ANIMATION_MS); - mSheetAnimator.setInterpolator(new LinearOutSlowInInterpolator()); + mSheetAnimator.setInterpolator(Interpolators.LINEAR_OUT_SLOW_IN_INTERPOLATOR); mSheetAnimator.addListener(this); mSheetAnimator.start(); }
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/preferences/ChromePreferenceManager.java b/chrome/android/java/src/org/chromium/chrome/browser/preferences/ChromePreferenceManager.java index 73a8819..902e439 100644 --- a/chrome/android/java/src/org/chromium/chrome/browser/preferences/ChromePreferenceManager.java +++ b/chrome/android/java/src/org/chromium/chrome/browser/preferences/ChromePreferenceManager.java
@@ -217,6 +217,12 @@ public static final String NIGHT_MODE_AVAILABLE_KEY = "night_mode_available"; /** + * Whether or not night mode should set "light" as the default option. + * Default value is false. + */ + public static final String NIGHT_MODE_DEFAULT_TO_LIGHT = "night_mode_default_to_light"; + + /** * Whether or not night mode is available for custom tabs. * Default value is false. */ @@ -224,7 +230,8 @@ /** * The current theme setting in the user settings. - * Default value is System default (see {@link ThemePreference.ThemeSetting}). + * Default value is -1. Use NightModeUtils#getThemeSetting() to retrieve current setting or + * default theme. */ public static final String UI_THEME_SETTING_KEY = "ui_theme_setting"; @@ -721,8 +728,18 @@ * @return The value of the preference. */ public int readInt(String key) { + return readInt(key, 0); + } + + /** + * Reads the given int value from the named shared preference. + * @param key The name of the preference to return. + * @param defaultValue The default value to return if the preference is not set. + * @return The value of the preference. + */ + public int readInt(String key, int defaultValue) { try (StrictModeContext ignored = StrictModeContext.allowDiskReads()) { - return mSharedPreferences.getInt(key, 0); + return mSharedPreferences.getInt(key, defaultValue); } }
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/preferences/password/PasswordEntryEditor.java b/chrome/android/java/src/org/chromium/chrome/browser/preferences/password/PasswordEntryEditor.java index b98b8d6..6cd8497 100644 --- a/chrome/android/java/src/org/chromium/chrome/browser/preferences/password/PasswordEntryEditor.java +++ b/chrome/android/java/src/org/chromium/chrome/browser/preferences/password/PasswordEntryEditor.java
@@ -134,7 +134,10 @@ mPasswordLabel.setError(getContext().getString( R.string.pref_edit_dialog_field_required_validation_message)); } else { - // TODO(crbug.com/377410): Save the changes if everything was ok. + PasswordEditingDelegateProvider.getInstance() + .getPasswordEditingDelegate() + .editSavedPasswordEntry( + mUsernameText.getText().toString(), mPasswordText.getText().toString()); getActivity().finish(); } } @@ -144,4 +147,10 @@ super.onSaveInstanceState(savedInstanceState); savedInstanceState.putBoolean(VIEW_BUTTON_PRESSED, mViewButtonPressed); } + + @Override + public void onDestroy() { + super.onDestroy(); + PasswordEditingDelegateProvider.getInstance().getPasswordEditingDelegate().destroy(); + } } \ No newline at end of file
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/preferences/password/PasswordEntryViewer.java b/chrome/android/java/src/org/chromium/chrome/browser/preferences/password/PasswordEntryViewer.java index e212d36..86cb1b4 100644 --- a/chrome/android/java/src/org/chromium/chrome/browser/preferences/password/PasswordEntryViewer.java +++ b/chrome/android/java/src/org/chromium/chrome/browser/preferences/password/PasswordEntryViewer.java
@@ -199,6 +199,9 @@ if (mCopyButtonPressed) copyPassword(); } PasswordManagerHandlerProvider.getInstance().addObserver(this); + PasswordManagerHandlerProvider.getInstance() + .getPasswordManagerHandler() + .updatePasswordLists(); } @Override @@ -434,13 +437,13 @@ @Override public void passwordListAvailable(int count) { if (mException) return; - TextView passwordsLinkTextView = mView.findViewById(R.id.passwords_link); + TextView passwordTextView = mView.findViewById(R.id.password_entry_viewer_password); SavedPasswordEntry SavedPasswordEntry = PasswordManagerHandlerProvider.getInstance() .getPasswordManagerHandler() .getSavedPasswordEntry(mID); setRowText(R.id.url_row, SavedPasswordEntry.getUrl()); setRowText(R.id.username_row, SavedPasswordEntry.getUserName()); - passwordsLinkTextView.setText(SavedPasswordEntry.getPassword()); + passwordTextView.setText(SavedPasswordEntry.getPassword()); } @Override
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/preferences/themes/ThemePreferences.java b/chrome/android/java/src/org/chromium/chrome/browser/preferences/themes/ThemePreferences.java index 34d0cb1..51dc3a7a 100644 --- a/chrome/android/java/src/org/chromium/chrome/browser/preferences/themes/ThemePreferences.java +++ b/chrome/android/java/src/org/chromium/chrome/browser/preferences/themes/ThemePreferences.java
@@ -16,6 +16,7 @@ import org.chromium.chrome.R; import org.chromium.chrome.browser.ChromeFeatureList; +import org.chromium.chrome.browser.night_mode.NightModeUtils; import org.chromium.chrome.browser.preferences.ChromePreferenceManager; import org.chromium.chrome.browser.preferences.PreferenceUtils; import org.chromium.ui.UiUtils; @@ -52,9 +53,9 @@ ChromePreferenceManager chromePreferenceManager = ChromePreferenceManager.getInstance(); RadioButtonGroupThemePreference radioButtonGroupThemePreference = (RadioButtonGroupThemePreference) findPreference(PREF_UI_THEME_PREF); - radioButtonGroupThemePreference.initialize( - chromePreferenceManager.readInt(UI_THEME_SETTING_KEY), + radioButtonGroupThemePreference.initialize(NightModeUtils.getThemeSetting(), chromePreferenceManager.readBoolean(DARKEN_WEBSITES_ENABLED_KEY, false)); + radioButtonGroupThemePreference.setOnPreferenceChangeListener((preference, newValue) -> { if (ChromeFeatureList.isEnabled( ChromeFeatureList.DARKEN_WEBSITES_CHECKBOX_IN_THEMES_SETTING)) {
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/searchwidget/SearchActivityLocationBarLayout.java b/chrome/android/java/src/org/chromium/chrome/browser/searchwidget/SearchActivityLocationBarLayout.java index 60cc561..2c168922 100644 --- a/chrome/android/java/src/org/chromium/chrome/browser/searchwidget/SearchActivityLocationBarLayout.java +++ b/chrome/android/java/src/org/chromium/chrome/browser/searchwidget/SearchActivityLocationBarLayout.java
@@ -92,8 +92,10 @@ mPendingSearchPromoDecision = false; getAutocompleteCoordinator().setShouldPreventOmniboxAutocomplete( mPendingSearchPromoDecision); - if (!TextUtils.isEmpty(mUrlCoordinator.getTextWithAutocomplete())) { - mAutocompleteCoordinator.onTextChangedForAutocomplete(); + String textWithAutocomplete = mUrlCoordinator.getTextWithAutocomplete(); + if (!TextUtils.isEmpty(textWithAutocomplete)) { + mAutocompleteCoordinator.onTextChanged( + mUrlCoordinator.getTextWithoutAutocomplete(), textWithAutocomplete); } if (mPendingBeginQuery) {
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/snackbar/SnackbarView.java b/chrome/android/java/src/org/chromium/chrome/browser/snackbar/SnackbarView.java index ef23602..ca70786 100644 --- a/chrome/android/java/src/org/chromium/chrome/browser/snackbar/SnackbarView.java +++ b/chrome/android/java/src/org/chromium/chrome/browser/snackbar/SnackbarView.java
@@ -19,7 +19,6 @@ import android.view.View.OnClickListener; import android.view.View.OnLayoutChangeListener; import android.view.ViewGroup; -import android.view.animation.DecelerateInterpolator; import android.widget.FrameLayout; import android.widget.ImageView; import android.widget.TextView; @@ -29,6 +28,7 @@ import org.chromium.base.ApiCompatibilityUtils; import org.chromium.chrome.R; import org.chromium.chrome.browser.ChromeActivity; +import org.chromium.chrome.browser.ui.widget.animation.Interpolators; import org.chromium.ui.base.DeviceFormFactor; import org.chromium.ui.interpolators.BakedBezierInterpolator; @@ -114,7 +114,7 @@ mContainerView.removeOnLayoutChangeListener(this); mContainerView.setTranslationY(getYPositionForMoveAnimation()); Animator animator = ObjectAnimator.ofFloat(mContainerView, View.TRANSLATION_Y, 0); - animator.setInterpolator(new DecelerateInterpolator()); + animator.setInterpolator(Interpolators.DECELERATE_INTERPOLATOR); animator.setDuration(mAnimationDuration); startAnimatorOnSurfaceView(animator); } @@ -135,7 +135,7 @@ }); Animator moveAnimator = ObjectAnimator.ofFloat( mContainerView, View.TRANSLATION_Y, getYPositionForMoveAnimation()); - moveAnimator.setInterpolator(new DecelerateInterpolator()); + moveAnimator.setInterpolator(Interpolators.DECELERATE_INTERPOLATOR); Animator fadeOut = ObjectAnimator.ofFloat(mContainerView, View.ALPHA, 0f); fadeOut.setInterpolator(BakedBezierInterpolator.FADE_OUT_CURVE);
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/suggestions/SuggestionsRecyclerView.java b/chrome/android/java/src/org/chromium/chrome/browser/suggestions/SuggestionsRecyclerView.java index cba965f8..cc634e39 100644 --- a/chrome/android/java/src/org/chromium/chrome/browser/suggestions/SuggestionsRecyclerView.java +++ b/chrome/android/java/src/org/chromium/chrome/browser/suggestions/SuggestionsRecyclerView.java
@@ -15,7 +15,6 @@ import android.graphics.Canvas; import android.os.Build; import android.support.v4.view.ViewCompat; -import android.support.v4.view.animation.FastOutLinearInInterpolator; import android.support.v7.view.ContextThemeWrapper; import android.support.v7.widget.LinearLayoutManager; import android.support.v7.widget.RecyclerView; @@ -36,6 +35,7 @@ import org.chromium.chrome.browser.ntp.cards.NewTabPageAdapter; import org.chromium.chrome.browser.ntp.cards.NewTabPageViewHolder; import org.chromium.chrome.browser.ntp.cards.ScrollToLoadListener; +import org.chromium.chrome.browser.ui.widget.animation.Interpolators; import org.chromium.chrome.browser.ui.widget.displaystyle.UiConfig; import java.util.ArrayList; @@ -50,7 +50,8 @@ * New Tab page receives focus when clicked. */ public class SuggestionsRecyclerView extends RecyclerView { - private static final Interpolator DISMISS_INTERPOLATOR = new FastOutLinearInInterpolator(); + private static final Interpolator DISMISS_INTERPOLATOR = + Interpolators.FAST_OUT_LINEAR_IN_INTERPOLATOR; private static final int DISMISS_ANIMATION_TIME_MS = 300; private final GestureDetector mGestureDetector;
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/tab/InterceptNavigationDelegateImpl.java b/chrome/android/java/src/org/chromium/chrome/browser/tab/InterceptNavigationDelegateImpl.java index a4b190a2..8aac964 100644 --- a/chrome/android/java/src/org/chromium/chrome/browser/tab/InterceptNavigationDelegateImpl.java +++ b/chrome/android/java/src/org/chromium/chrome/browser/tab/InterceptNavigationDelegateImpl.java
@@ -239,14 +239,7 @@ public void maybeUpdateNavigationHistory() { WebContents webContents = mTab.getWebContents(); if (mClearAllForwardHistoryRequired && webContents != null) { - NavigationController navigationController = - webContents.getNavigationController(); - int lastCommittedEntryIndex = getLastCommittedEntryIndex(); - while (navigationController.canGoForward()) { - boolean ret = navigationController.removeEntryAtIndex( - lastCommittedEntryIndex + 1); - assert ret; - } + webContents.getNavigationController().pruneForwardEntries(); } else if (mShouldClearRedirectHistoryForTabClobbering && webContents != null) { // http://crbug/479056: Even if we clobber the current tab, we want to remove
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/toolbar/MenuButton.java b/chrome/android/java/src/org/chromium/chrome/browser/toolbar/MenuButton.java index f7ea38be..dc1b414 100644 --- a/chrome/android/java/src/org/chromium/chrome/browser/toolbar/MenuButton.java +++ b/chrome/android/java/src/org/chromium/chrome/browser/toolbar/MenuButton.java
@@ -14,7 +14,6 @@ import android.util.AttributeSet; import android.view.View; import android.view.ViewGroup; -import android.view.animation.LinearInterpolator; import android.widget.FrameLayout; import android.widget.ImageButton; import android.widget.ImageView; @@ -29,6 +28,7 @@ import org.chromium.chrome.browser.appmenu.AppMenuButtonHelper; import org.chromium.chrome.browser.omaha.UpdateMenuItemHelper; import org.chromium.chrome.browser.omaha.UpdateMenuItemHelper.MenuButtonState; +import org.chromium.chrome.browser.ui.widget.animation.Interpolators; import org.chromium.chrome.browser.util.FeatureUtilities; import org.chromium.chrome.browser.widget.PulseDrawable; import org.chromium.ui.interpolators.BakedBezierInterpolator; @@ -324,7 +324,7 @@ // Create menu button ObjectAnimator. ObjectAnimator menuButtonFadeAnimator = ObjectAnimator.ofFloat(menuButton, View.ALPHA, 0.f); - menuButtonFadeAnimator.setInterpolator(new LinearInterpolator()); + menuButtonFadeAnimator.setInterpolator(Interpolators.LINEAR_INTERPOLATOR); // Create AnimatorSet and listeners. AnimatorSet set = new AnimatorSet();
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/toolbar/top/TabSwitcherModeTTPhone.java b/chrome/android/java/src/org/chromium/chrome/browser/toolbar/top/TabSwitcherModeTTPhone.java index 8fe04f4..e35d0a9 100644 --- a/chrome/android/java/src/org/chromium/chrome/browser/toolbar/top/TabSwitcherModeTTPhone.java +++ b/chrome/android/java/src/org/chromium/chrome/browser/toolbar/top/TabSwitcherModeTTPhone.java
@@ -13,7 +13,6 @@ import android.util.AttributeSet; import android.view.View; import android.view.ViewStub; -import android.view.animation.LinearInterpolator; import androidx.annotation.Nullable; @@ -32,6 +31,7 @@ import org.chromium.chrome.browser.toolbar.NewTabButton; import org.chromium.chrome.browser.toolbar.TabCountProvider; import org.chromium.chrome.browser.ui.widget.animation.CancelAwareAnimatorListener; +import org.chromium.chrome.browser.ui.widget.animation.Interpolators; import org.chromium.chrome.browser.util.ColorUtils; import org.chromium.chrome.browser.util.FeatureUtilities; import org.chromium.ui.UiUtils; @@ -169,7 +169,7 @@ if (showZoomingAnimation && inTabSwitcherMode) { mVisiblityAnimator.setStartDelay(duration); } - mVisiblityAnimator.setInterpolator(new LinearInterpolator()); + mVisiblityAnimator.setInterpolator(Interpolators.LINEAR_INTERPOLATOR); // TODO(https://crbug.com/914868): Use consistent logic here for setting clickable/enabled // on mIncognitoToggleTabLayout & mNewTabButton?
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/toolbar/top/ToolbarPhone.java b/chrome/android/java/src/org/chromium/chrome/browser/toolbar/top/ToolbarPhone.java index 758ae39d..89c8e6e 100644 --- a/chrome/android/java/src/org/chromium/chrome/browser/toolbar/top/ToolbarPhone.java +++ b/chrome/android/java/src/org/chromium/chrome/browser/toolbar/top/ToolbarPhone.java
@@ -25,7 +25,6 @@ import android.os.SystemClock; import android.support.v4.graphics.drawable.DrawableCompat; import android.support.v4.view.ViewCompat; -import android.support.v4.view.animation.FastOutSlowInInterpolator; import android.support.v7.graphics.drawable.DrawableWrapper; import android.util.AttributeSet; import android.util.Property; @@ -38,8 +37,6 @@ import android.view.ViewGroup; import android.view.ViewStub; import android.view.ViewTreeObserver; -import android.view.animation.Interpolator; -import android.view.animation.LinearInterpolator; import android.widget.FrameLayout; import android.widget.ImageButton; import android.widget.ImageView; @@ -72,6 +69,7 @@ import org.chromium.chrome.browser.toolbar.TabSwitcherDrawable; import org.chromium.chrome.browser.toolbar.top.TopToolbarCoordinator.UrlExpansionObserver; import org.chromium.chrome.browser.ui.widget.animation.CancelAwareAnimatorListener; +import org.chromium.chrome.browser.ui.widget.animation.Interpolators; import org.chromium.chrome.browser.util.ColorUtils; import org.chromium.chrome.browser.util.FeatureUtilities; import org.chromium.chrome.browser.util.MathUtils; @@ -126,9 +124,6 @@ static final int LOCATION_BAR_TRANSPARENT_BACKGROUND_ALPHA = 51; - private static final Interpolator NTP_SEARCH_BOX_EXPANSION_INTERPOLATOR = - new FastOutSlowInInterpolator(); - private TabCountProvider mTabCountProvider; protected LocationBarPhone mLocationBar; @@ -1168,8 +1163,9 @@ // Linearly interpolate between the bounds of the search box on the NTP and the omnibox // background bounds. |shrinkage| is the scaling factor for the offset -- if it's 1, we are // shrinking the omnibox down to the size of the search box. - float shrinkage = - 1f - NTP_SEARCH_BOX_EXPANSION_INTERPOLATOR.getInterpolation(mUrlExpansionPercent); + float shrinkage = 1f + - Interpolators.FAST_OUT_SLOW_IN_INTERPOLATOR.getInterpolation( + mUrlExpansionPercent); int leftBoundDifference = mNtpSearchBoxBounds.left - mLocationBarBackgroundBounds.left; int rightBoundDifference = mNtpSearchBoxBounds.right - mLocationBarBackgroundBounds.right; @@ -1685,7 +1681,7 @@ ObjectAnimator.ofFloat(this, mTabSwitcherModePercentProperty, 1.f); enterAnimation.setDuration( TopToolbarCoordinator.TAB_SWITCHER_MODE_NORMAL_ANIMATION_DURATION_MS); - enterAnimation.setInterpolator(new LinearInterpolator()); + enterAnimation.setInterpolator(Interpolators.LINEAR_INTERPOLATOR); return enterAnimation; } @@ -1696,7 +1692,7 @@ exitAnimation.setDuration(animateNormalToolbar ? TopToolbarCoordinator.TAB_SWITCHER_MODE_NORMAL_ANIMATION_DURATION_MS : TAB_SWITCHER_MODE_EXIT_FADE_ANIMATION_DURATION_MS); - exitAnimation.setInterpolator(new LinearInterpolator()); + exitAnimation.setInterpolator(Interpolators.LINEAR_INTERPOLATOR); exitAnimation.addListener(new CancelAwareAnimatorListener() { @Override public void onEnd(Animator animation) {
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/util/FeatureUtilities.java b/chrome/android/java/src/org/chromium/chrome/browser/util/FeatureUtilities.java index 7918529..aa2b11c 100644 --- a/chrome/android/java/src/org/chromium/chrome/browser/util/FeatureUtilities.java +++ b/chrome/android/java/src/org/chromium/chrome/browser/util/FeatureUtilities.java
@@ -76,6 +76,7 @@ private static Boolean sIsAdaptiveToolbarEnabled; private static Boolean sIsLabeledBottomToolbarEnabled; private static Boolean sIsNightModeAvailable; + private static Boolean sNightModeDefaultToLight; private static Boolean sIsNightModeForCustomTabsAvailable; private static Boolean sShouldPrioritizeBootstrapTasks; private static Boolean sIsGridTabSwitcherEnabled; @@ -174,6 +175,7 @@ cacheAdaptiveToolbarEnabled(); cacheLabeledBottomToolbarEnabled(); cacheNightModeAvailable(); + cacheNightModeDefaultToLight(); cacheNightModeForCustomTabsAvailable(); cacheDownloadAutoResumptionEnabledInNative(); cachePrioritizeBootstrapTasks(); @@ -419,6 +421,50 @@ } /** + * Cache whether or not to default to the light theme when the night mode feature is enabled. + */ + public static void cacheNightModeDefaultToLight() { + // Do not cache on Q (where defaulting to light theme does not apply) or if night mode is + // not enabled. + if (BuildInfo.isAtLeastQ() + || !ChromeFeatureList.isEnabled(ChromeFeatureList.ANDROID_NIGHT_MODE)) { + return; + } + + String lightModeDefaultParam = "default_light_theme"; + boolean lightModeAsDefault = ChromeFeatureList.getFieldTrialParamByFeatureAsBoolean( + ChromeFeatureList.ANDROID_NIGHT_MODE, lightModeDefaultParam, false); + + ChromePreferenceManager.getInstance().writeBoolean( + ChromePreferenceManager.NIGHT_MODE_DEFAULT_TO_LIGHT, lightModeAsDefault); + } + + /** + * @return Whether or not to default to the light theme when the night mode feature is enabled. + */ + public static boolean isNightModeDefaultToLight() { + if (BuildInfo.isAtLeastQ()) sNightModeDefaultToLight = false; + + if (sNightModeDefaultToLight == null) { + ChromePreferenceManager prefManager = ChromePreferenceManager.getInstance(); + + sNightModeDefaultToLight = prefManager.readBoolean( + ChromePreferenceManager.NIGHT_MODE_DEFAULT_TO_LIGHT, false); + } + + return sNightModeDefaultToLight; + } + + /** + * Toggles whether the night mode experiment is enabled for testing. Should be reset back to + * null after the test has finished. + */ + @VisibleForTesting + public static void setNightModeDefaultToLightForTesting(@Nullable Boolean available) { + sNightModeDefaultToLight = available; + } + + /** * Cache whether or not night mode is available for custom tabs (i.e. night mode experiment is * enabled), so the value is immediately available on next start-up. */
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/webapps/WebappActivity.java b/chrome/android/java/src/org/chromium/chrome/browser/webapps/WebappActivity.java index 0582903..639fa7c 100644 --- a/chrome/android/java/src/org/chromium/chrome/browser/webapps/WebappActivity.java +++ b/chrome/android/java/src/org/chromium/chrome/browser/webapps/WebappActivity.java
@@ -408,9 +408,6 @@ * If immersive mode is not supported, this method no-ops. */ private void enterImmersiveMode() { - // Immersive mode is only supported in API 19+. - if (Build.VERSION.SDK_INT < Build.VERSION_CODES.KITKAT) return; - if (mSetImmersiveRunnable == null) { final View decor = getWindow().getDecorView();
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/webapps/addtohomescreen/AddToHomescreenView.java b/chrome/android/java/src/org/chromium/chrome/browser/webapps/addtohomescreen/AddToHomescreenView.java index 400c755d..0966014 100644 --- a/chrome/android/java/src/org/chromium/chrome/browser/webapps/addtohomescreen/AddToHomescreenView.java +++ b/chrome/android/java/src/org/chromium/chrome/browser/webapps/addtohomescreen/AddToHomescreenView.java
@@ -112,7 +112,7 @@ // title is the title of the page. mProgressBarView = view.findViewById(R.id.spinny); mIconView = (ImageView) view.findViewById(R.id.icon); - mShortcutTitleInput = (EditText) view.findViewById(R.id.text); + mShortcutTitleInput = view.findViewById(R.id.text); mAppLayout = (LinearLayout) view.findViewById(R.id.app_info); mAppNameView = (TextView) mAppLayout.findViewById(R.id.name);
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/widget/ChromeTextInputLayout.java b/chrome/android/java/src/org/chromium/chrome/browser/widget/ChromeTextInputLayout.java index 6225f78..c868616 100644 --- a/chrome/android/java/src/org/chromium/chrome/browser/widget/ChromeTextInputLayout.java +++ b/chrome/android/java/src/org/chromium/chrome/browser/widget/ChromeTextInputLayout.java
@@ -15,7 +15,6 @@ import android.support.v4.view.ViewCompat; import android.support.v4.view.ViewPropertyAnimatorListenerAdapter; import android.support.v4.view.accessibility.AccessibilityNodeInfoCompat; -import android.support.v4.view.animation.FastOutSlowInInterpolator; import android.text.Editable; import android.text.TextUtils; import android.text.TextWatcher; @@ -24,7 +23,6 @@ import android.view.View; import android.view.ViewGroup; import android.view.accessibility.AccessibilityEvent; -import android.view.animation.Interpolator; import android.widget.EditText; import android.widget.FrameLayout; import android.widget.LinearLayout; @@ -35,6 +33,7 @@ import org.chromium.base.ApiCompatibilityUtils; import org.chromium.chrome.R; +import org.chromium.chrome.browser.ui.widget.animation.Interpolators; import org.chromium.ui.base.LocalizationUtils; import java.lang.annotation.Retention; @@ -77,7 +76,6 @@ private HashSet<OnEditTextFocusChangeListener> mListeners = new HashSet<>(); private CharSequence mHint; - private Interpolator mInterpolator; private boolean mShouldDisplayError; private @LabelStatus int mLabelStatus; @@ -149,7 +147,6 @@ new int[] {getColorAttribute(context, R.attr.colorControlActivated), mLabel.getCurrentTextColor()})); - mInterpolator = new FastOutSlowInInterpolator(); setImportantForAccessibility(IMPORTANT_FOR_ACCESSIBILITY_YES); ViewCompat.setAccessibilityDelegate(this, new AccessibilityDelegate()); } @@ -331,7 +328,7 @@ mLabelStatus = LabelStatus.COLLAPSED; } }) - .setInterpolator(mInterpolator) + .setInterpolator(Interpolators.FAST_OUT_SLOW_IN_INTERPOLATOR) .start(); } else { mLabel.setTranslationY(mCollapsedLabelTranslationY); @@ -358,7 +355,7 @@ mLabelStatus = LabelStatus.EXPANDED; } }) - .setInterpolator(mInterpolator) + .setInterpolator(Interpolators.FAST_OUT_SLOW_IN_INTERPOLATOR) .start(); } else { mLabel.setScaleX(mExpandedTextScale);
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/widget/ContextMenuDialog.java b/chrome/android/java/src/org/chromium/chrome/browser/widget/ContextMenuDialog.java index 2e97766..38c41b7 100644 --- a/chrome/android/java/src/org/chromium/chrome/browser/widget/ContextMenuDialog.java +++ b/chrome/android/java/src/org/chromium/chrome/browser/widget/ContextMenuDialog.java
@@ -8,7 +8,6 @@ import android.graphics.Color; import android.graphics.Rect; import android.graphics.drawable.ColorDrawable; -import android.support.v4.view.animation.LinearOutSlowInInterpolator; import android.view.MotionEvent; import android.view.View; import android.view.View.OnLayoutChangeListener; @@ -20,6 +19,7 @@ import android.view.animation.ScaleAnimation; import org.chromium.chrome.browser.ui.widget.AlwaysDismissedDialog; +import org.chromium.chrome.browser.ui.widget.animation.Interpolators; /** * ContextMenuDialog is a subclass of AlwaysDismissedDialog that ensures that the proper scale @@ -166,7 +166,7 @@ long duration = isEnterAnimation ? ENTER_ANIMATION_DURATION_MS : EXIT_ANIMATION_DURATION_MS; animation.setDuration(duration); - animation.setInterpolator(new LinearOutSlowInInterpolator()); + animation.setInterpolator(Interpolators.LINEAR_OUT_SLOW_IN_INTERPOLATOR); return animation; } }
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/widget/PulseDrawable.java b/chrome/android/java/src/org/chromium/chrome/browser/widget/PulseDrawable.java index 3b0919f93..8e02339 100644 --- a/chrome/android/java/src/org/chromium/chrome/browser/widget/PulseDrawable.java +++ b/chrome/android/java/src/org/chromium/chrome/browser/widget/PulseDrawable.java
@@ -14,7 +14,6 @@ import android.graphics.drawable.Animatable; import android.graphics.drawable.Drawable; import android.os.SystemClock; -import android.support.v4.view.animation.FastOutSlowInInterpolator; import android.support.v4.view.animation.PathInterpolatorCompat; import android.view.animation.Interpolator; @@ -23,6 +22,7 @@ import org.chromium.base.ApiCompatibilityUtils; import org.chromium.chrome.R; +import org.chromium.chrome.browser.ui.widget.animation.Interpolators; import org.chromium.chrome.browser.util.MathUtils; /** @@ -150,7 +150,7 @@ }; return new PulseDrawable( - context, new FastOutSlowInInterpolator(), painter, pulseEndAuthority); + context, Interpolators.FAST_OUT_SLOW_IN_INTERPOLATOR, painter, pulseEndAuthority); } /**
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/widget/bottomsheet/BottomSheet.java b/chrome/android/java/src/org/chromium/chrome/browser/widget/bottomsheet/BottomSheet.java index 09ce7b4..279c59e5 100644 --- a/chrome/android/java/src/org/chromium/chrome/browser/widget/bottomsheet/BottomSheet.java +++ b/chrome/android/java/src/org/chromium/chrome/browser/widget/bottomsheet/BottomSheet.java
@@ -9,7 +9,6 @@ import android.animation.ValueAnimator; import android.content.Context; import android.graphics.Color; -import android.graphics.PorterDuff.Mode; import android.graphics.Rect; import android.os.Build; import android.util.AttributeSet; @@ -24,7 +23,6 @@ import androidx.annotation.IntDef; import androidx.annotation.Nullable; -import org.chromium.base.ApiCompatibilityUtils; import org.chromium.base.ObserverList; import org.chromium.base.Supplier; import org.chromium.base.VisibleForTesting; @@ -516,7 +514,7 @@ mToolbarHolder = (TouchRestrictingFrameLayout) findViewById(R.id.bottom_sheet_toolbar_container); - setBackground(mToolbarHolder); + mToolbarHolder.setBackgroundResource(R.drawable.top_round); mDefaultToolbarView = mToolbarHolder.findViewById(R.id.bottom_sheet_toolbar); @@ -525,7 +523,7 @@ mBottomSheetContentContainer = (TouchRestrictingFrameLayout) findViewById(R.id.bottom_sheet_content); mBottomSheetContentContainer.setBottomSheet(this); - setBackground(mBottomSheetContentContainer); + mBottomSheetContentContainer.setBackgroundResource(R.drawable.top_round); // Listen to height changes on the root. root.addOnLayoutChangeListener(new View.OnLayoutChangeListener() { @@ -653,18 +651,6 @@ mSheetContainer.removeView(this); } - /** - * Sets the background with round corner drawable, adjusts the color for dark mode. - * @param view View in BottomSheet to set the drawable to. - */ - private static void setBackground(View view) { - view.setBackgroundResource(R.drawable.top_round); - view.getBackground().setColorFilter( - ApiCompatibilityUtils.getColor( - view.getContext().getResources(), org.chromium.ui.R.color.sheet_bg_color), - Mode.MULTIPLY); - } - @Override public void onWindowFocusChanged(boolean hasWindowFocus) { super.onWindowFocusChanged(hasWindowFocus);
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/widget/prefeditor/EditorDialog.java b/chrome/android/java/src/org/chromium/chrome/browser/widget/prefeditor/EditorDialog.java index 963a970..704cca8 100644 --- a/chrome/android/java/src/org/chromium/chrome/browser/widget/prefeditor/EditorDialog.java +++ b/chrome/android/java/src/org/chromium/chrome/browser/widget/prefeditor/EditorDialog.java
@@ -16,8 +16,6 @@ import android.graphics.drawable.Drawable; import android.os.Handler; import android.support.v4.view.MarginLayoutParamsCompat; -import android.support.v4.view.animation.FastOutLinearInInterpolator; -import android.support.v4.view.animation.LinearOutSlowInInterpolator; import android.support.v7.widget.Toolbar.OnMenuItemClickListener; import android.text.InputFilter; import android.text.Spanned; @@ -51,6 +49,7 @@ import org.chromium.chrome.browser.ui.widget.AlwaysDismissedDialog; import org.chromium.chrome.browser.ui.widget.FadingEdgeScrollView; import org.chromium.chrome.browser.ui.widget.TintedDrawable; +import org.chromium.chrome.browser.ui.widget.animation.Interpolators; import org.chromium.ui.KeyboardVisibilityDelegate; import java.util.ArrayList; @@ -310,7 +309,7 @@ mDialogInOutAnimator = animatorSet; mDialogInOutAnimator.setDuration(DIALOG_EXIT_ANIMATION_MS); - mDialogInOutAnimator.setInterpolator(new FastOutLinearInInterpolator()); + mDialogInOutAnimator.setInterpolator(Interpolators.FAST_OUT_LINEAR_IN_INTERPOLATOR); mDialogInOutAnimator.addListener(new AnimatorListenerAdapter() { @Override public void onAnimationEnd(Animator animation) { @@ -562,7 +561,7 @@ mDialogInOutAnimator = animatorSet; mDialogInOutAnimator.setDuration(DIALOG_ENTER_ANIMATION_MS); - mDialogInOutAnimator.setInterpolator(new LinearOutSlowInInterpolator()); + mDialogInOutAnimator.setInterpolator(Interpolators.LINEAR_OUT_SLOW_IN_INTERPOLATOR); mDialogInOutAnimator.addListener(new AnimatorListenerAdapter() { @Override public void onAnimationEnd(Animator animation) {
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/widget/selection/SelectableListToolbar.java b/chrome/android/java/src/org/chromium/chrome/browser/widget/selection/SelectableListToolbar.java index 503e49f7..4a5d656 100644 --- a/chrome/android/java/src/org/chromium/chrome/browser/widget/selection/SelectableListToolbar.java +++ b/chrome/android/java/src/org/chromium/chrome/browser/widget/selection/SelectableListToolbar.java
@@ -32,6 +32,7 @@ import android.widget.TextView.OnEditorActionListener; import androidx.annotation.CallSuper; +import androidx.annotation.IntDef; import androidx.annotation.StringRes; import org.chromium.base.ApiCompatibilityUtils; @@ -51,6 +52,8 @@ import org.chromium.ui.KeyboardVisibilityDelegate; import org.chromium.ui.UiUtils; +import java.lang.annotation.Retention; +import java.lang.annotation.RetentionPolicy; import java.util.List; /** @@ -79,6 +82,14 @@ void onEndSearch(); } + @IntDef({ViewType.NORMAL_VIEW, ViewType.SELECTION_VIEW, ViewType.SEARCH_VIEW}) + @Retention(RetentionPolicy.SOURCE) + public @interface ViewType { + int NORMAL_VIEW = 0; + int SELECTION_VIEW = 1; + int SEARCH_VIEW = 2; + } + /** No navigation button is displayed. **/ public static final int NAVIGATION_BUTTON_NONE = 0; /** Button to navigate back. This calls {@link #onNavigationBack()}. **/ @@ -133,6 +144,9 @@ private int mHideInfoStringId; private int mExtraMenuItemId; + // current view type that SelectableListToolbar is showing + private int mViewType; + /** * Constructor for inflating from XML. */ @@ -527,6 +541,10 @@ } protected void showNormalView() { + // hide overflow menu explicitly: crbug.com/999269 + hideOverflowMenu(); + + mViewType = ViewType.NORMAL_VIEW; getMenu().setGroupVisible(mNormalGroupResId, true); getMenu().setGroupVisible(mSelectedGroupResId, false); if (mHasSearchView) { @@ -546,6 +564,8 @@ } protected void showSelectionView(List<E> selectedItems, boolean wasSelectionEnabled) { + mViewType = ViewType.SELECTION_VIEW; + getMenu().setGroupVisible(mNormalGroupResId, false); getMenu().setGroupVisible(mSelectedGroupResId, true); getMenu().setGroupEnabled(mSelectedGroupResId, !selectedItems.isEmpty()); @@ -563,6 +583,8 @@ } private void showSearchViewInternal() { + mViewType = ViewType.SEARCH_VIEW; + getMenu().setGroupVisible(mNormalGroupResId, false); getMenu().setGroupVisible(mSelectedGroupResId, false); mNumberRollView.setVisibility(View.GONE); @@ -757,4 +779,9 @@ child.setFocusableInTouchMode(true); } } + + @VisibleForTesting + public @ViewType int getCurrentViewType() { + return mViewType; + } }
diff --git a/chrome/android/java/strings/android_chrome_strings.grd b/chrome/android/java/strings/android_chrome_strings.grd index 66f11c55..aa9e21f 100644 --- a/chrome/android/java/strings/android_chrome_strings.grd +++ b/chrome/android/java/strings/android_chrome_strings.grd
@@ -4020,6 +4020,13 @@ Test Dummy </message> + <message name="IDS_EXTRA_ICU_MODULE_TITLE" + desc="Text shown when the extra ICU module is referenced in install start, success, + failure UI (e.g. in IDS_MODULE_INSTALL_START_TEXT, which will expand to + 'Installing Extra ICU for Chrome…')."> + Extra ICU + </message> + </messages> </release> </grit>
diff --git a/chrome/android/javatests/src/org/chromium/chrome/browser/bookmarks/BookmarkReorderTest.java b/chrome/android/javatests/src/org/chromium/chrome/browser/bookmarks/BookmarkReorderTest.java index 6ce7938..01d74356 100644 --- a/chrome/android/javatests/src/org/chromium/chrome/browser/bookmarks/BookmarkReorderTest.java +++ b/chrome/android/javatests/src/org/chromium/chrome/browser/bookmarks/BookmarkReorderTest.java
@@ -13,6 +13,8 @@ import static org.chromium.chrome.browser.ViewHighlighterTestUtils.checkHighlightPulse; import android.support.test.filters.MediumTest; +import android.support.test.filters.SmallTest; +import android.support.v7.widget.RecyclerView.AdapterDataObserver; import android.support.v7.widget.RecyclerView.ViewHolder; import android.view.View; @@ -28,8 +30,11 @@ import org.chromium.chrome.R; import org.chromium.chrome.browser.ChromeFeatureList; import org.chromium.chrome.browser.ChromeSwitches; +import org.chromium.chrome.browser.bookmarks.BookmarkBridge.BookmarkModelObserver; +import org.chromium.chrome.browser.bookmarks.BookmarkPromoHeader.PromoState; import org.chromium.chrome.browser.night_mode.NightModeTestUtils; import org.chromium.chrome.browser.ui.widget.ListMenuButton; +import org.chromium.chrome.browser.widget.selection.SelectableListToolbar.ViewType; import org.chromium.chrome.test.ChromeJUnit4RunnerDelegate; import org.chromium.chrome.test.util.BookmarkTestUtil; import org.chromium.chrome.test.util.browser.Features; @@ -96,6 +101,8 @@ // Callback occurs when Item "test" is selected. CriteriaHelper.pollUiThread(test::isChecked, "Expected item \"test\" to become selected"); + Assert.assertEquals("Expected bookmark toolbar to be selection mode", + mManager.getToolbarForTests().getCurrentViewType(), ViewType.SELECTION_VIEW); Assert.assertEquals("Expected more button of selected item to be gone when drag is active.", View.GONE, testMoreButton.getVisibility()); Assert.assertEquals( @@ -210,10 +217,10 @@ mBookmarkModel.addObserver(bookmarkModelObserver); }); - View foo = mItemsContainer.findViewHolderForAdapterPosition(3).itemView; - Assert.assertEquals("Wrong bookmark item selected.", TEST_PAGE_TITLE_FOO, - ((BookmarkItemRow) foo).getTitle()); - toggleSelectionAndEndAnimation(fooId, (BookmarkRow) foo); + BookmarkRow foo = + (BookmarkRow) mItemsContainer.findViewHolderForAdapterPosition(3).itemView; + Assert.assertEquals("Wrong bookmark item selected.", TEST_PAGE_TITLE_FOO, foo.getTitle()); + toggleSelectionAndEndAnimation(fooId, foo); // Starts as last bookmark (2nd index) and ends as 0th bookmark (promo header not included). TestThreadUtils.runOnUiThreadBlocking(() -> { @@ -228,6 +235,7 @@ mBookmarkModel.getChildIDs(mBookmarkModel.getDefaultFolder(), true, true); // Exclude partner bookmarks folder Assert.assertEquals(expected, observed.subList(0, 3)); + Assert.assertTrue("The selected item should stay selected", foo.isItemSelected()); }); } @@ -275,11 +283,11 @@ mBookmarkModel.addObserver(bookmarkModelObserver); }); - View test = mItemsContainer.findViewHolderForAdapterPosition(1).itemView; - Assert.assertEquals("Wrong bookmark item selected.", TEST_FOLDER_TITLE, - ((BookmarkFolderRow) test).getTitle()); + BookmarkFolderRow test = + (BookmarkFolderRow) mItemsContainer.findViewHolderForAdapterPosition(1).itemView; + Assert.assertEquals("Wrong bookmark item selected.", TEST_FOLDER_TITLE, test.getTitle()); - toggleSelectionAndEndAnimation(testId, (BookmarkRow) test); + toggleSelectionAndEndAnimation(testId, test); // Starts as 0th bookmark (not counting promo header) and ends as last (index 3). TestThreadUtils.runOnUiThreadBlocking(() -> { @@ -294,6 +302,7 @@ mBookmarkModel.getChildIDs(mBookmarkModel.getDefaultFolder(), true, true); // Exclude partner bookmarks folder Assert.assertEquals(expected, observed.subList(0, 4)); + Assert.assertTrue("The selected item should stay selected", test.isItemSelected()); }); } @@ -337,11 +346,11 @@ mBookmarkModel.addObserver(bookmarkModelObserver); }); - View test = mItemsContainer.findViewHolderForAdapterPosition(1).itemView; - Assert.assertEquals("Wrong bookmark item selected.", TEST_FOLDER_TITLE, - ((BookmarkFolderRow) test).getTitle()); + BookmarkFolderRow test = + (BookmarkFolderRow) mItemsContainer.findViewHolderForAdapterPosition(1).itemView; + Assert.assertEquals("Wrong bookmark item selected.", TEST_FOLDER_TITLE, test.getTitle()); - toggleSelectionAndEndAnimation(testId, (BookmarkRow) test); + toggleSelectionAndEndAnimation(testId, test); // Starts as 0th bookmark (not counting promo header) and ends at the 1st index. TestThreadUtils.runOnUiThreadBlocking(() -> { @@ -356,6 +365,7 @@ mBookmarkModel.getChildIDs(mBookmarkModel.getDefaultFolder(), true, true); // Exclude partner bookmarks folder Assert.assertEquals(expected, observed.subList(0, 3)); + Assert.assertTrue("The selected item should stay selected", test.isItemSelected()); }); } @@ -734,6 +744,135 @@ checkHighlightOff(itemASecondView)); } + @Test + @SmallTest + public void testAddBookmarkInBackgroundWithSelection() throws Exception { + BookmarkId id = addBookmark(TEST_PAGE_TITLE_FOO, mTestPageFoo); + BookmarkPromoHeader.forcePromoStateForTests(PromoState.PROMO_NONE); + openBookmarkManager(); + Assert.assertEquals(1, getAdapter().getItemCount()); + BookmarkRow row = + (BookmarkRow) mItemsContainer.findViewHolderForAdapterPosition(0).itemView; + toggleSelectionAndEndAnimation(id, row); + CallbackHelper helper = new CallbackHelper(); + getAdapter().registerAdapterDataObserver(new AdapterDataObserver() { + @Override + public void onChanged() { + helper.notifyCalled(); + } + }); + + TestThreadUtils.runOnUiThreadBlocking(() -> { + mBookmarkModel.addBookmark( + mBookmarkModel.getDefaultFolder(), 1, TEST_PAGE_TITLE_GOOGLE, mTestPage); + }); + + helper.waitForCallback(0, 1); + RecyclerViewTestUtils.waitForStableRecyclerView(mItemsContainer); + TestThreadUtils.runOnUiThreadBlocking(() -> { + Assert.assertTrue(isItemPresentInBookmarkList(TEST_PAGE_TITLE_FOO)); + Assert.assertTrue(isItemPresentInBookmarkList(TEST_PAGE_TITLE_GOOGLE)); + Assert.assertEquals(2, getAdapter().getItemCount()); + Assert.assertTrue("The selected row should be kept selected", row.isItemSelected()); + }); + } + + @Test + @SmallTest + public void testDeleteAllSelectedBookmarksInBackground() throws Exception { + // selected on bookmark and then remove that in background + // in the meantime, the toolbar changes from selection mode to normal mode + BookmarkId fooId = addBookmark(TEST_PAGE_TITLE_FOO, mTestPageFoo); + BookmarkId googleId = addBookmark(TEST_PAGE_TITLE_GOOGLE, mTestPage); + BookmarkId aId = addBookmark(TEST_TITLE_A, TEST_URL_A); + BookmarkPromoHeader.forcePromoStateForTests(PromoState.PROMO_NONE); + openBookmarkManager(); + Assert.assertEquals(3, getAdapter().getItemCount()); + BookmarkRow row = + (BookmarkRow) mItemsContainer.findViewHolderForAdapterPosition(1).itemView; + toggleSelectionAndEndAnimation(googleId, row); + CallbackHelper helper = new CallbackHelper(); + mManager.getSelectionDelegate().addObserver((x) -> { helper.notifyCalled(); }); + + removeBookmark(googleId); + + RecyclerViewTestUtils.waitForStableRecyclerView(mItemsContainer); + helper.waitForCallback(0, 1); + TestThreadUtils.runOnUiThreadBlocking(() -> { + Assert.assertFalse( + "Item is not deleted", isItemPresentInBookmarkList(TEST_PAGE_TITLE_GOOGLE)); + Assert.assertEquals(2, getReorderAdapter().getItemCount()); + Assert.assertEquals("Bookmark View should be back to normal view", + mManager.getToolbarForTests().getCurrentViewType(), ViewType.NORMAL_VIEW); + }); + } + + @Test + @SmallTest + public void testDeleteSomeSelectedBookmarksInBackground() throws Exception { + // selected on bookmarks and then remove one of them in background + // in the meantime, the toolbar stays in selection mode + BookmarkId fooId = addBookmark(TEST_PAGE_TITLE_FOO, mTestPageFoo); + BookmarkId googleId = addBookmark(TEST_PAGE_TITLE_GOOGLE, mTestPage); + BookmarkId aId = addBookmark(TEST_TITLE_A, TEST_URL_A); + BookmarkPromoHeader.forcePromoStateForTests(PromoState.PROMO_NONE); + openBookmarkManager(); + Assert.assertEquals(3, getAdapter().getItemCount()); + BookmarkRow row = + (BookmarkRow) mItemsContainer.findViewHolderForAdapterPosition(1).itemView; + toggleSelectionAndEndAnimation(googleId, row); + BookmarkRow aRow = + (BookmarkRow) mItemsContainer.findViewHolderForAdapterPosition(0).itemView; + toggleSelectionAndEndAnimation(aId, aRow); + CallbackHelper helper = new CallbackHelper(); + mManager.getSelectionDelegate().addObserver((x) -> { helper.notifyCalled(); }); + + removeBookmark(googleId); + + RecyclerViewTestUtils.waitForStableRecyclerView(mItemsContainer); + helper.waitForCallback(0, 1); + TestThreadUtils.runOnUiThreadBlocking(() -> { + Assert.assertFalse( + "Item is not deleted", isItemPresentInBookmarkList(TEST_PAGE_TITLE_GOOGLE)); + Assert.assertEquals(2, getReorderAdapter().getItemCount()); + Assert.assertTrue("Item selected should not be cleared", aRow.isItemSelected()); + Assert.assertEquals("Should stay in selection mode because there is one selected", + mManager.getToolbarForTests().getCurrentViewType(), ViewType.SELECTION_VIEW); + }); + } + + @Test + @SmallTest + public void testUpdateSelectedBookmarkInBackground() throws Exception { + BookmarkId id = addBookmark(TEST_PAGE_TITLE_FOO, mTestPageFoo); + BookmarkPromoHeader.forcePromoStateForTests(PromoState.PROMO_NONE); + openBookmarkManager(); + Assert.assertEquals(1, getAdapter().getItemCount()); + BookmarkRow row = + (BookmarkRow) mItemsContainer.findViewHolderForAdapterPosition(0).itemView; + toggleSelectionAndEndAnimation(id, row); + CallbackHelper helper = new CallbackHelper(); + TestThreadUtils.runOnUiThreadBlocking( + () -> mBookmarkModel.addObserver(new BookmarkModelObserver() { + @Override + public void bookmarkModelChanged() { + helper.notifyCalled(); + } + })); + + TestThreadUtils.runOnUiThreadBlocking( + () -> mBookmarkModel.setBookmarkTitle(id, TEST_PAGE_TITLE_GOOGLE)); + + helper.waitForCallback(0, 1); + RecyclerViewTestUtils.waitForStableRecyclerView(mItemsContainer); + TestThreadUtils.runOnUiThreadBlocking(() -> { + Assert.assertFalse(isItemPresentInBookmarkList(TEST_PAGE_TITLE_FOO)); + Assert.assertTrue(isItemPresentInBookmarkList(TEST_PAGE_TITLE_GOOGLE)); + Assert.assertEquals(1, getAdapter().getItemCount()); + Assert.assertTrue("The selected row should stay selected", row.isItemSelected()); + }); + } + @Override protected void openBookmarkManager() throws InterruptedException { super.openBookmarkManager();
diff --git a/chrome/android/javatests/src/org/chromium/chrome/browser/bookmarks/BookmarkTest.java b/chrome/android/javatests/src/org/chromium/chrome/browser/bookmarks/BookmarkTest.java index 5b910a8..d2faf5a 100644 --- a/chrome/android/javatests/src/org/chromium/chrome/browser/bookmarks/BookmarkTest.java +++ b/chrome/android/javatests/src/org/chromium/chrome/browser/bookmarks/BookmarkTest.java
@@ -161,7 +161,7 @@ } } - private boolean isItemPresentInBookmarkList(final String expectedTitle) { + protected boolean isItemPresentInBookmarkList(final String expectedTitle) { return TestThreadUtils.runOnUiThreadBlockingNoException(new Callable<Boolean>() { @Override public Boolean call() throws Exception { @@ -531,7 +531,7 @@ () -> mBookmarkModel.addFolder(mBookmarkModel.getDefaultFolder(), 0, title)); } - private void removeBookmark(final BookmarkId bookmarkId) { + protected void removeBookmark(final BookmarkId bookmarkId) { TestThreadUtils.runOnUiThreadBlocking(() -> mBookmarkModel.deleteBookmark(bookmarkId)); }
diff --git a/chrome/android/javatests/src/org/chromium/chrome/browser/omnibox/UrlBarTest.java b/chrome/android/javatests/src/org/chromium/chrome/browser/omnibox/UrlBarTest.java index 82cfcf8f..972072e 100644 --- a/chrome/android/javatests/src/org/chromium/chrome/browser/omnibox/UrlBarTest.java +++ b/chrome/android/javatests/src/org/chromium/chrome/browser/omnibox/UrlBarTest.java
@@ -271,9 +271,9 @@ final CallbackHelper autocompleteHelper = new CallbackHelper(); final AtomicReference<String> requestedAutocompleteText = new AtomicReference<String>(); final AtomicBoolean didPreventInlineAutocomplete = new AtomicBoolean(); - mUrlBar.setUrlTextChangeListener(() -> { + mUrlBar.setUrlTextChangeListener((textWithoutAutocomplete, textWithAutocomplete) -> { autocompleteHelper.notifyCalled(); - requestedAutocompleteText.set(mUrlBar.getTextWithoutAutocomplete()); + requestedAutocompleteText.set(textWithoutAutocomplete); didPreventInlineAutocomplete.set(!mUrlBar.shouldAutocomplete()); mUrlBar.setUrlTextChangeListener(null); }); @@ -378,7 +378,7 @@ public void testSendCursorPosition() throws InterruptedException, TimeoutException { final CallbackHelper autocompleteHelper = new CallbackHelper(); final AtomicInteger cursorPositionUsed = new AtomicInteger(); - mUrlBar.setUrlTextChangeListener(() -> { + mUrlBar.setUrlTextChangeListener((textWithoutAutocomplete, textWithAutocomplete) -> { int cursorPosition = mUrlBar.getSelectionEnd() == mUrlBar.getSelectionStart() ? mUrlBar.getSelectionStart() : -1; @@ -456,7 +456,7 @@ final CallbackHelper autocompleteHelper = new CallbackHelper(); final AtomicBoolean didPreventInlineAutocomplete = new AtomicBoolean(); - mUrlBar.setUrlTextChangeListener(() -> { + mUrlBar.setUrlTextChangeListener((textWithoutAutocomplete, textWithAutocomplete) -> { if (!TextUtils.equals(textToBeEntered, mUrlBar.getTextWithoutAutocomplete())) return; didPreventInlineAutocomplete.set(!mUrlBar.shouldAutocomplete()); autocompleteHelper.notifyCalled(); @@ -489,7 +489,7 @@ final CallbackHelper autocompleteHelper = new CallbackHelper(); final AtomicBoolean didPreventInlineAutocomplete = new AtomicBoolean(); - mUrlBar.setUrlTextChangeListener(() -> { + mUrlBar.setUrlTextChangeListener((textWithoutAutocomplete, textWithAutocomplete) -> { if (!TextUtils.equals("test", mUrlBar.getTextWithoutAutocomplete())) return; didPreventInlineAutocomplete.set(!mUrlBar.shouldAutocomplete()); autocompleteHelper.notifyCalled(); @@ -555,7 +555,8 @@ public void testBatchModeChangesTriggerCorrectSuggestions() throws InterruptedException { final AtomicReference<String> requestedAutocompleteText = new AtomicReference<String>(); mUrlBar.setUrlTextChangeListener( - () -> { requestedAutocompleteText.set(mUrlBar.getTextWithoutAutocomplete()); }); + (textWithoutAutocomplete, textWithAutocomplete) + -> requestedAutocompleteText.set(mUrlBar.getTextWithoutAutocomplete())); toggleFocusAndIgnoreImeOperations(mUrlBar, true);
diff --git a/chrome/android/javatests/src/org/chromium/chrome/browser/preferences/password/SavePasswordsPreferencesTest.java b/chrome/android/javatests/src/org/chromium/chrome/browser/preferences/password/SavePasswordsPreferencesTest.java index 9e548ed..d14af979 100644 --- a/chrome/android/javatests/src/org/chromium/chrome/browser/preferences/password/SavePasswordsPreferencesTest.java +++ b/chrome/android/javatests/src/org/chromium/chrome/browser/preferences/password/SavePasswordsPreferencesTest.java
@@ -37,6 +37,8 @@ import static org.hamcrest.Matchers.not; import static org.hamcrest.Matchers.nullValue; import static org.hamcrest.Matchers.sameInstance; +import static org.mockito.Mockito.timeout; +import static org.mockito.Mockito.verify; import static org.chromium.chrome.test.util.ViewUtils.VIEW_GONE; import static org.chromium.chrome.test.util.ViewUtils.VIEW_INVISIBLE; @@ -74,17 +76,19 @@ import org.hamcrest.Matcher; import org.junit.After; import org.junit.Assert; -import org.junit.Ignore; import org.junit.Rule; import org.junit.Test; import org.junit.rules.TestRule; import org.junit.runner.RunWith; +import org.mockito.Mock; +import org.mockito.MockitoAnnotations; import org.chromium.base.Callback; import org.chromium.base.CollectionUtil; import org.chromium.base.IntStringCallback; import org.chromium.base.test.BaseJUnit4ClassRunner; import org.chromium.base.test.util.Feature; +import org.chromium.base.test.util.ScalableTimeout; import org.chromium.chrome.R; import org.chromium.chrome.browser.ChromeFeatureList; import org.chromium.chrome.browser.history.HistoryActivity; @@ -101,6 +105,7 @@ import org.chromium.chrome.test.util.browser.Features; import org.chromium.components.signin.ChromeSigninController; import org.chromium.components.sync.ModelType; +import org.chromium.content_public.browser.test.util.CriteriaHelper; import org.chromium.content_public.browser.test.util.TestThreadUtils; import java.io.File; @@ -119,6 +124,9 @@ @RunWith(BaseJUnit4ClassRunner.class) public class SavePasswordsPreferencesTest { private static final long UI_UPDATING_TIMEOUT_MS = 3000; + @Mock + private PasswordEditingDelegate mMockPasswordEditingDelegate; + @Rule public final ChromeBrowserTestRule mBrowserTestRule = new ChromeBrowserTestRule(); @@ -225,6 +233,15 @@ @Override public void showPasswordEntryEditingView(Context context, int index) { mLastEntryIndex = index; + Bundle fragmentArgs = new Bundle(); + fragmentArgs.putString( + PasswordEntryEditor.CREDENTIAL_URL, getSavedPasswordEntry(index).getUrl()); + fragmentArgs.putString(PasswordEntryEditor.CREDENTIAL_NAME, + getSavedPasswordEntry(index).getUserName()); + fragmentArgs.putString(PasswordEntryEditor.CREDENTIAL_PASSWORD, + getSavedPasswordEntry(index).getPassword()); + PreferencesLauncher.launchSettingsPage( + context, PasswordEntryEditor.class, fragmentArgs); } } @@ -256,6 +273,10 @@ */ private final ManualCallbackDelayer mManualDelayer = new ManualCallbackDelayer(); + public SavePasswordsPreferencesTest() { + MockitoAnnotations.initMocks(this); + } + private void overrideProfileSyncService( final boolean usingPassphrase, final boolean syncingPasswords) { TestThreadUtils.runOnUiThreadBlocking(() -> { @@ -723,6 +744,8 @@ @Features.EnableFeatures(ChromeFeatureList.PASSWORD_EDITING_ANDROID) public void testSelectedStoredPasswordIndexIsSameAsInShowPasswordEntryEditingView() throws Exception { + PasswordEditingDelegateProvider.getInstance().setPasswordEditingDelegate( + mMockPasswordEditingDelegate); setPasswordSourceWithMultipleEntries( // Initialize preferences new SavedPasswordEntry[] {new SavedPasswordEntry("https://example.com", "example user", "example password"), @@ -746,6 +769,8 @@ @Feature({"Preferences"}) @Features.EnableFeatures(ChromeFeatureList.PASSWORD_EDITING_ANDROID) public void testPasswordDataDisplayedInEditingActivity() throws Exception { + PasswordEditingDelegateProvider.getInstance().setPasswordEditingDelegate( + mMockPasswordEditingDelegate); Bundle fragmentArgs = new Bundle(); fragmentArgs.putString(PasswordEntryEditor.CREDENTIAL_URL, "https://example.com"); fragmentArgs.putString(PasswordEntryEditor.CREDENTIAL_NAME, "test user"); @@ -759,17 +784,16 @@ } /** - * Check that the changes of password data in the password editing activity are preserved and - * shown in the password viewing activity and in the list of passwords after the save button - * was clicked. + * Check that the password editing method from the PasswordEditingDelegate was called when the + * save button in the password editing activity was clicked. */ - // TODO(izuzic): Remove @Ignore when saving of changes is enabled again. - @Ignore("The test is ignored because saving the changes of credentials is currently disabled.") @Test @SmallTest @Feature({"Preferences"}) @Features.EnableFeatures(ChromeFeatureList.PASSWORD_EDITING_ANDROID) - public void testChangeOfStoredPasswordDataIsPreserved() throws Exception { + public void testPasswordEditingMethodWasCalled() throws Exception { + PasswordEditingDelegateProvider.getInstance().setPasswordEditingDelegate( + mMockPasswordEditingDelegate); setPasswordSource(new SavedPasswordEntry("https://example.com", "test user", "password")); PreferencesTest.startPreferences(InstrumentationRegistry.getInstrumentation(), @@ -783,6 +807,38 @@ Espresso.onView(withSaveMenuIdOrText()).perform(click()); + verify(mMockPasswordEditingDelegate).editSavedPasswordEntry("test user new", "password"); + + // Verify that the delegate was destroyed when the password editing activity finished. + waitForEvent().destroy(); + } + + /** + * Check that the changes of password data are shown in the password viewing activity and in the + * list of passwords after the save button was clicked. + */ + @Test + @SmallTest + @Feature({"Preferences"}) + @Features.EnableFeatures(ChromeFeatureList.PASSWORD_EDITING_ANDROID) + public void testChangeOfStoredPasswordDataIsPropagated() throws Exception { + PasswordEditingDelegateProvider.getInstance().setPasswordEditingDelegate( + mMockPasswordEditingDelegate); + setPasswordSource(new SavedPasswordEntry("https://example.com", "test user", "password")); + + PreferencesTest.startPreferences(InstrumentationRegistry.getInstrumentation(), + SavePasswordsPreferences.class.getName()); + + Espresso.onView(withText(containsString("test user"))).perform(click()); + + Espresso.onView(withEditMenuIdOrText()).perform(click()); + + // Performing a change of saved credentials. + mHandler.mSavedPasswords.set( + 0, new SavedPasswordEntry("https://example.com", "test user new", "password")); + + Espresso.onView(withSaveMenuIdOrText()).perform(click()); + // Check if the password viewing activity has the updated data. Espresso.onView(withText("test user new")).check(matches(isDisplayed())); @@ -800,6 +856,8 @@ @Feature({"Preferences"}) @Features.EnableFeatures(ChromeFeatureList.PASSWORD_EDITING_ANDROID) public void testStoredPasswordCanBeUnmaskedAndMaskedAgain() throws Exception { + PasswordEditingDelegateProvider.getInstance().setPasswordEditingDelegate( + mMockPasswordEditingDelegate); Bundle fragmentArgs = new Bundle(); fragmentArgs.putString(SavePasswordsPreferences.PASSWORD_LIST_NAME, "test user"); fragmentArgs.putString(SavePasswordsPreferences.PASSWORD_LIST_URL, "https://example.com"); @@ -2137,4 +2195,9 @@ allOf(withId(R.id.search_src_text), withText("Zeu")))); Espresso.onView(withId(R.id.search_src_text)).check(matches(withText("Zeu"))); } + + PasswordEditingDelegate waitForEvent() { + return verify(mMockPasswordEditingDelegate, + timeout(ScalableTimeout.scaleTimeout(CriteriaHelper.DEFAULT_MAX_TIME_TO_POLL))); + } }
diff --git a/chrome/android/javatests/src/org/chromium/chrome/browser/preferences/themes/ThemePreferencesTest.java b/chrome/android/javatests/src/org/chromium/chrome/browser/preferences/themes/ThemePreferencesTest.java index cd987bb..a246619d 100644 --- a/chrome/android/javatests/src/org/chromium/chrome/browser/preferences/themes/ThemePreferencesTest.java +++ b/chrome/android/javatests/src/org/chromium/chrome/browser/preferences/themes/ThemePreferencesTest.java
@@ -14,27 +14,50 @@ import org.junit.Test; import org.junit.runner.RunWith; +import org.chromium.base.BuildInfo; +import org.chromium.base.test.params.ParameterAnnotations; +import org.chromium.base.test.params.ParameterSet; +import org.chromium.base.test.params.ParameterizedRunner; import org.chromium.base.test.util.Feature; import org.chromium.chrome.R; +import org.chromium.chrome.browser.night_mode.NightModeUtils; import org.chromium.chrome.browser.preferences.ChromePreferenceManager; import org.chromium.chrome.browser.preferences.Preferences; import org.chromium.chrome.browser.preferences.PreferencesTest; import org.chromium.chrome.browser.preferences.themes.ThemePreferences.ThemeSetting; +import org.chromium.chrome.browser.util.FeatureUtilities; import org.chromium.chrome.browser.widget.RadioButtonWithDescription; -import org.chromium.chrome.test.ChromeJUnit4ClassRunner; +import org.chromium.chrome.test.ChromeJUnit4RunnerDelegate; import org.chromium.chrome.test.ui.DummyUiActivityTestCase; import org.chromium.chrome.test.util.browser.Features; import org.chromium.content_public.browser.test.util.TestThreadUtils; +import java.util.Arrays; +import java.util.List; + /** * Tests for ThemePreferences. */ -@RunWith(ChromeJUnit4ClassRunner.class) +// clang-format off @Features.EnableFeatures(ANDROID_NIGHT_MODE) +@RunWith(ParameterizedRunner.class) +@ParameterAnnotations.UseRunnerDelegate(ChromeJUnit4RunnerDelegate.class) public class ThemePreferencesTest extends DummyUiActivityTestCase { + // clang-format on + @ParameterAnnotations.ClassParameter + private static List<ParameterSet> sClassParams = + Arrays.asList(new ParameterSet().value(false).name("DefaultLightDisabled"), + new ParameterSet().value(true).name("DefaultLightEnabled")); + + private boolean mDefaultToLight; private ThemePreferences mFragment; private RadioButtonGroupThemePreference mPreference; + public ThemePreferencesTest(boolean defaultToLight) { + mDefaultToLight = defaultToLight; + FeatureUtilities.setNightModeDefaultToLightForTesting(defaultToLight); + } + @Override public void setUpTest() throws Exception { super.setUpTest(); @@ -49,6 +72,7 @@ @Override public void tearDownTest() throws Exception { ChromePreferenceManager.getInstance().removeKey(UI_THEME_SETTING_KEY); + FeatureUtilities.setNightModeDefaultToLightForTesting(null); super.tearDownTest(); } @@ -57,6 +81,20 @@ @Feature({"Themes"}) public void testSelectThemes() { TestThreadUtils.runOnUiThreadBlocking(() -> { + // Default to light parameter is only applicable pre-Q. + if (mDefaultToLight && BuildInfo.isAtLeastQ()) { + Assert.assertFalse("Q should not default to light.", + FeatureUtilities.isNightModeDefaultToLight()); + return; + } + + int expectedDefaultTheme = + mDefaultToLight ? ThemeSetting.LIGHT : ThemeSetting.SYSTEM_DEFAULT; + Assert.assertEquals("Incorrect default theme setting.", expectedDefaultTheme, + NightModeUtils.getThemeSetting()); + assertButtonCheckedCorrectly( + mDefaultToLight ? "Light" : "System default", expectedDefaultTheme); + // Select System default Assert.assertEquals(R.id.system_default, getButton(0).getId()); selectButton(0);
diff --git a/chrome/android/junit/src/org/chromium/chrome/browser/night_mode/GlobalNightModeStateControllerTest.java b/chrome/android/junit/src/org/chromium/chrome/browser/night_mode/GlobalNightModeStateControllerTest.java index c9c3897..1ab2fe3a 100644 --- a/chrome/android/junit/src/org/chromium/chrome/browser/night_mode/GlobalNightModeStateControllerTest.java +++ b/chrome/android/junit/src/org/chromium/chrome/browser/night_mode/GlobalNightModeStateControllerTest.java
@@ -17,6 +17,8 @@ import static org.chromium.base.ApplicationState.HAS_STOPPED_ACTIVITIES; import static org.chromium.chrome.browser.preferences.ChromePreferenceManager.UI_THEME_SETTING_KEY; +import android.os.Build; + import org.junit.After; import org.junit.Before; import org.junit.Test; @@ -27,8 +29,10 @@ import org.robolectric.annotation.Config; import org.chromium.base.test.BaseRobolectricTestRunner; +import org.chromium.base.test.util.DisableIf; import org.chromium.chrome.browser.preferences.ChromePreferenceManager; import org.chromium.chrome.browser.preferences.themes.ThemePreferences; +import org.chromium.chrome.browser.util.FeatureUtilities; /** * Unit tests for {@link GlobalNightModeStateController}. @@ -101,6 +105,18 @@ } @Test + @DisableIf.Build(sdk_is_greater_than = Build.VERSION_CODES.P) + public void testUpdateNightMode_PowerSaveMode_DefaultsToLight() { + FeatureUtilities.setNightModeDefaultToLightForTesting(true); + + // Enable power save mode and verify night mode is not enabled. + setIsPowerSaveMode(true); + assertFalse(mGlobalNightModeStateController.isInNightMode()); + + FeatureUtilities.setNightModeDefaultToLightForTesting(null); + } + + @Test public void testUpdateNightMode_SystemNightMode() { // Enable system night mode and verify night mode is enabled. setSystemNightMode(true); @@ -112,6 +128,18 @@ } @Test + @DisableIf.Build(sdk_is_greater_than = Build.VERSION_CODES.P) + public void testUpdateNightMode_SystemNightMode_DefaultsToLight() { + FeatureUtilities.setNightModeDefaultToLightForTesting(true); + + // Enable system night mode and verify night mode is not enabled. + setSystemNightMode(true); + assertFalse(mGlobalNightModeStateController.isInNightMode()); + + FeatureUtilities.setNightModeDefaultToLightForTesting(null); + } + + @Test public void testUpdateNightMode_Preference() { // Set preference to dark theme and verify night mode is enabled. ChromePreferenceManager.getInstance().writeInt(
diff --git a/chrome/android/junit/src/org/chromium/chrome/browser/omnibox/UrlBarMediatorUnitTest.java b/chrome/android/junit/src/org/chromium/chrome/browser/omnibox/UrlBarMediatorUnitTest.java index 669b7f4..b3486dff 100644 --- a/chrome/android/junit/src/org/chromium/chrome/browser/omnibox/UrlBarMediatorUnitTest.java +++ b/chrome/android/junit/src/org/chromium/chrome/browser/omnibox/UrlBarMediatorUnitTest.java
@@ -11,9 +11,12 @@ import android.text.SpannableStringBuilder; import org.junit.Assert; +import org.junit.Before; import org.junit.Test; import org.junit.runner.RunWith; +import org.mockito.Mock; import org.mockito.Mockito; +import org.mockito.MockitoAnnotations; import org.robolectric.RuntimeEnvironment; import org.robolectric.annotation.Config; @@ -28,6 +31,16 @@ @RunWith(BaseRobolectricTestRunner.class) @Config(manifest = Config.NONE) public class UrlBarMediatorUnitTest { + @Mock + UrlBar.UrlTextChangeListener mMockListener; + @Mock + UrlBar.UrlTextChangeListener mAnotherMockListener; + + @Before + public void setUp() { + MockitoAnnotations.initMocks(this); + } + @Test public void setUrlData_SendsUpdates() { PropertyModel model = new PropertyModel(UrlBarProperties.ALL_KEYS); @@ -250,6 +263,24 @@ mediator.getReplacementCutCopyText("www.test.com/foo", 0, 16)); } + @Test + public void urlTextChangeListenerCompositeObserver() { + PropertyModel model = new PropertyModel(UrlBarProperties.ALL_KEYS); + UrlBarMediator mediator = new UrlBarMediator(model); + mediator.addUrlTextChangeListener(mMockListener); + + String text = "foo"; + String textWithAutocomplete = "foo.bar"; + mediator.onTextChanged(text, textWithAutocomplete); + Mockito.verify(mMockListener, Mockito.times(1)).onTextChanged(text, textWithAutocomplete); + + mediator.addUrlTextChangeListener(mAnotherMockListener); + mediator.onTextChanged(text, textWithAutocomplete); + Mockito.verify(mMockListener, Mockito.times(2)).onTextChanged(text, textWithAutocomplete); + Mockito.verify(mAnotherMockListener, Mockito.times(1)) + .onTextChanged(text, textWithAutocomplete); + } + private static SpannableStringBuilder spannable(String text) { return new SpannableStringBuilder(text); }
diff --git a/chrome/android/junit/src/org/chromium/chrome/browser/omnibox/status/StatusMediatorUnitTest.java b/chrome/android/junit/src/org/chromium/chrome/browser/omnibox/status/StatusMediatorUnitTest.java new file mode 100644 index 0000000..3e697c5 --- /dev/null +++ b/chrome/android/junit/src/org/chromium/chrome/browser/omnibox/status/StatusMediatorUnitTest.java
@@ -0,0 +1,134 @@ +// Copyright 2019 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +package org.chromium.chrome.browser.omnibox.status; + +import android.content.res.Resources; +import android.graphics.Bitmap; + +import org.junit.Assert; +import org.junit.Before; +import org.junit.Test; +import org.junit.runner.RunWith; +import org.mockito.ArgumentCaptor; +import org.mockito.Captor; +import org.mockito.Mock; +import org.mockito.Mockito; +import org.mockito.MockitoAnnotations; +import org.robolectric.annotation.Config; + +import org.chromium.base.Callback; +import org.chromium.base.test.BaseRobolectricTestRunner; +import org.chromium.chrome.R; +import org.chromium.chrome.browser.ChromeFeatureList; +import org.chromium.chrome.test.util.browser.Features; +import org.chromium.ui.modelutil.PropertyModel; + +/** + * Unit tests for {@link StatusMediator}. + */ +@RunWith(BaseRobolectricTestRunner.class) +@Config(manifest = Config.NONE) +public final class StatusMediatorUnitTest { + private static final String TEST_SEARCH_URL = "https://www.test.com"; + + @Mock + Resources mResources; + @Mock + StatusMediator.StatusMediatorDelegate mDelegate; + @Mock + Bitmap mBitmap; + @Captor + ArgumentCaptor<Callback<Bitmap>> mCallbackCaptor; + + PropertyModel mModel; + StatusMediator mMediator; + + @Before + public void setUp() { + MockitoAnnotations.initMocks(this); + + mModel = new PropertyModel(StatusProperties.ALL_KEYS); + mMediator = new StatusMediator(mModel, mResources); + mMediator.setDelegateForTesting(mDelegate); + } + + @Test + @Features.EnableFeatures(ChromeFeatureList.OMNIBOX_SEARCH_ENGINE_LOGO) + public void searchEngineLogo_showGoogleLogo() { + setupSearchEngineLogoForTesting(false, true, false); + + mMediator.setUrlHasFocus(true); + mMediator.setShowIconsWhenUrlFocused(true); + mMediator.updateSearchEngineStatusIcon(true, true, TEST_SEARCH_URL); + Assert.assertEquals( + R.drawable.ic_logo_googleg_24dp, mModel.get(StatusProperties.STATUS_ICON_RES)); + } + + @Test + @Features.EnableFeatures(ChromeFeatureList.OMNIBOX_SEARCH_ENGINE_LOGO) + public void searchEngineLogo_showGoogleLogo_searchLoupeEverywhere() { + setupSearchEngineLogoForTesting(false, true, true); + + mMediator.setUrlHasFocus(true); + mMediator.setShowIconsWhenUrlFocused(true); + mMediator.updateSearchEngineStatusIcon(true, true, TEST_SEARCH_URL); + Assert.assertEquals(R.drawable.ic_search, mModel.get(StatusProperties.STATUS_ICON_RES)); + } + + @Test + @Features.EnableFeatures(ChromeFeatureList.OMNIBOX_SEARCH_ENGINE_LOGO) + public void searchEngineLogo_showNonGoogleLogo() { + setupSearchEngineLogoForTesting(false, false, false); + + mMediator.setUrlHasFocus(true); + mMediator.setShowIconsWhenUrlFocused(true); + + // Clear invocations since the setup methods call updateLocationBarIcon. + Mockito.clearInvocations(mDelegate); + mMediator.updateSearchEngineStatusIcon(true, false, TEST_SEARCH_URL); + Assert.assertEquals(R.drawable.ic_search, mModel.get(StatusProperties.STATUS_ICON_RES)); + Mockito.verify(mDelegate, Mockito.times(1)) + .getSearchEngineLogoFavicon(Mockito.any(), Mockito.any()); + mCallbackCaptor.getValue().onResult(mBitmap); + Assert.assertEquals(mBitmap, mModel.get(StatusProperties.STATUS_ICON)); + } + + @Test + @Features.EnableFeatures(ChromeFeatureList.OMNIBOX_SEARCH_ENGINE_LOGO) + public void searchEngineLogo_showNonGoogleLogo_searchLoupeEverywhere() { + setupSearchEngineLogoForTesting(false, false, true); + + mMediator.setUrlHasFocus(true); + mMediator.setShowIconsWhenUrlFocused(true); + + // Clear invocations since the setup methods call updateLocationBarIcon. + Mockito.clearInvocations(mDelegate); + mMediator.updateSearchEngineStatusIcon(true, false, TEST_SEARCH_URL); + Assert.assertEquals(R.drawable.ic_search, mModel.get(StatusProperties.STATUS_ICON_RES)); + Mockito.verify(mDelegate, Mockito.times(0)) + .getSearchEngineLogoFavicon(Mockito.any(), Mockito.any()); + } + + @Test + @Features.EnableFeatures(ChromeFeatureList.OMNIBOX_SEARCH_ENGINE_LOGO) + public void searchEngineLogo_onTextChanged_globeReplacesIconWhenTextIsSite() { + setupSearchEngineLogoForTesting(true, false, false); + + mMediator.setUrlHasFocus(true); + mMediator.setShowIconsWhenUrlFocused(true); + mMediator.onTextChanged("", "testing"); + Assert.assertEquals(R.drawable.ic_globe_24dp, mModel.get(StatusProperties.STATUS_ICON_RES)); + } + + private void setupSearchEngineLogoForTesting( + boolean validUrl, boolean showGoogle, boolean loupeEverywhere) { + Mockito.doReturn(validUrl).when(mDelegate).isUrlValid(Mockito.any()); + Mockito.doReturn(true).when(mDelegate).shouldShowSearchEngineLogo(); + Mockito.doReturn(loupeEverywhere).when(mDelegate).shouldShowSearchLoupeEverywhere(); + Mockito.doNothing().when(mDelegate).getSearchEngineLogoFavicon( + Mockito.any(), mCallbackCaptor.capture()); + mMediator.updateSearchEngineStatusIcon(true, showGoogle, TEST_SEARCH_URL); + } +}
diff --git a/chrome/android/modules/chrome_feature_modules.gni b/chrome/android/modules/chrome_feature_modules.gni index b311304..b815f12 100644 --- a/chrome/android/modules/chrome_feature_modules.gni +++ b/chrome/android/modules/chrome_feature_modules.gni
@@ -8,6 +8,7 @@ import("//chrome/android/features/dev_ui/dev_ui_module.gni") import("//chrome/android/features/tab_ui/tab_ui_module.gni") import("//chrome/android/modules/buildflags.gni") +import("//chrome/android/modules/extra_icu/extra_icu_module.gni") import("//chrome/android/modules/test_dummy/test_dummy_module.gni") import("//device/vr/buildflags/buildflags.gni") @@ -35,7 +36,10 @@ # Each new module needs to add a desc to one of the lists below. # Modules shipped in Chrome Modern (Android L+). -chrome_modern_module_descs = [ test_dummy_module_desc ] +chrome_modern_module_descs = [ + test_dummy_module_desc, + extra_icu_module_desc, +] if (enable_vr) { chrome_modern_module_descs += [ vr_module_desc ] }
diff --git a/chrome/android/modules/extra_icu/extra_icu_module.gni b/chrome/android/modules/extra_icu/extra_icu_module.gni new file mode 100644 index 0000000..732dca1 --- /dev/null +++ b/chrome/android/modules/extra_icu/extra_icu_module.gni
@@ -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. + +extra_icu_module_desc = { + name = "extra_icu" + android_manifest = + "//chrome/android/modules/extra_icu/internal/java/AndroidManifest.xml" + java_deps = [ + "//chrome/android/modules/extra_icu/internal:icudtl_extra_assets", + "//chrome/android/modules/extra_icu/internal:java", + ] +}
diff --git a/chrome/android/modules/extra_icu/internal/BUILD.gn b/chrome/android/modules/extra_icu/internal/BUILD.gn new file mode 100644 index 0000000..0b041aa4 --- /dev/null +++ b/chrome/android/modules/extra_icu/internal/BUILD.gn
@@ -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. + +import("//build/config/android/rules.gni") + +android_library("java") { + java_files = + [ "java/src/org/chromium/chrome/modules/extra_icu/ExtraIcuImpl.java" ] + deps = [ + "//base:base_java", + "//chrome/android/modules/extra_icu/public:java", + ] +} + +android_assets("icudtl_extra_assets") { + sources = [ + "//third_party/icu/android_small/icudtl_extra.dat", + ] + disable_compression = true +}
diff --git a/chrome/android/modules/extra_icu/internal/java/AndroidManifest.xml b/chrome/android/modules/extra_icu/internal/java/AndroidManifest.xml new file mode 100644 index 0000000..c7aab1c --- /dev/null +++ b/chrome/android/modules/extra_icu/internal/java/AndroidManifest.xml
@@ -0,0 +1,17 @@ +<?xml version="1.0" encoding="utf-8"?> +<!-- Copyright 2019 The Chromium Authors. All rights reserved. + Use of this source code is governed by a BSD-style license that can be + found in the LICENSE file. --> +<manifest xmlns:android="http://schemas.android.com/apk/res/android" + xmlns:dist="http://schemas.android.com/apk/distribution" + featureSplit="extra_icu"> + + <!-- Always install extra ICU module on first Chrome install or update. --> + <dist:module + dist:onDemand="false" + dist:title="@string/extra_icu_module_title"> + <dist:fusing dist:include="false" /> + </dist:module> + + <application /> +</manifest>
diff --git a/chrome/android/modules/extra_icu/internal/java/src/org/chromium/chrome/modules/extra_icu/ExtraIcuImpl.java b/chrome/android/modules/extra_icu/internal/java/src/org/chromium/chrome/modules/extra_icu/ExtraIcuImpl.java new file mode 100644 index 0000000..041da1ed --- /dev/null +++ b/chrome/android/modules/extra_icu/internal/java/src/org/chromium/chrome/modules/extra_icu/ExtraIcuImpl.java
@@ -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. + +package org.chromium.chrome.modules.extra_icu; + +import org.chromium.base.annotations.UsedByReflection; + +/** Interface implementation inside the module. */ +@UsedByReflection("ExtraIcuModule") +public class ExtraIcuImpl implements ExtraIcu {}
diff --git a/chrome/android/modules/extra_icu/provider/BUILD.gn b/chrome/android/modules/extra_icu/provider/BUILD.gn new file mode 100644 index 0000000..ce7c348 --- /dev/null +++ b/chrome/android/modules/extra_icu/provider/BUILD.gn
@@ -0,0 +1,29 @@ +# 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/android/rules.gni") + +android_library("java") { + deps = [ + "//base:base_java", + "//chrome/android/modules/extra_icu/public:java", + ] + java_files = [ "java/src/org/chromium/chrome/modules/extra_icu/ExtraIcuModuleProvider.java" ] +} + +generate_jni("jni_headers") { + sources = [ + "java/src/org/chromium/chrome/modules/extra_icu/ExtraIcuModuleProvider.java", + ] +} + +source_set("native") { + deps = [ + ":jni_headers", + ] + sources = [ + "module_provider.cc", + "module_provider.h", + ] +}
diff --git a/chrome/android/modules/extra_icu/provider/java/src/org/chromium/chrome/modules/extra_icu/ExtraIcuModuleProvider.java b/chrome/android/modules/extra_icu/provider/java/src/org/chromium/chrome/modules/extra_icu/ExtraIcuModuleProvider.java new file mode 100644 index 0000000..9a3adf02 --- /dev/null +++ b/chrome/android/modules/extra_icu/provider/java/src/org/chromium/chrome/modules/extra_icu/ExtraIcuModuleProvider.java
@@ -0,0 +1,20 @@ +// 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.modules.extra_icu; + +import org.chromium.base.annotations.CalledByNative; +import org.chromium.base.annotations.JNINamespace; + +/** Java side of the extra ICU module installer. */ +@JNINamespace("extra_icu") +public class ExtraIcuModuleProvider { + /** Returns true if the extra ICU module is installed. */ + @CalledByNative + private static boolean isModuleInstalled() { + return ExtraIcuModule.isInstalled(); + } + + private ExtraIcuModuleProvider() {} +}
diff --git a/chrome/android/modules/extra_icu/provider/module_provider.cc b/chrome/android/modules/extra_icu/provider/module_provider.cc new file mode 100644 index 0000000..f2ec1fc --- /dev/null +++ b/chrome/android/modules/extra_icu/provider/module_provider.cc
@@ -0,0 +1,16 @@ +// Copyright 2019 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#include "chrome/android/modules/extra_icu/provider/module_provider.h" +#include "chrome/android/modules/extra_icu/provider/jni_headers/ExtraIcuModuleProvider_jni.h" + +namespace extra_icu { + +// static +bool ModuleProvider::IsModuleInstalled() { + return Java_ExtraIcuModuleProvider_isModuleInstalled( + base::android::AttachCurrentThread()); +} + +} // namespace extra_icu
diff --git a/chrome/android/modules/extra_icu/provider/module_provider.h b/chrome/android/modules/extra_icu/provider/module_provider.h new file mode 100644 index 0000000..b3c0bc8 --- /dev/null +++ b/chrome/android/modules/extra_icu/provider/module_provider.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 CHROME_ANDROID_MODULES_EXTRA_ICU_PROVIDER_MODULE_PROVIDER_H_ +#define CHROME_ANDROID_MODULES_EXTRA_ICU_PROVIDER_MODULE_PROVIDER_H_ + +namespace extra_icu { + +// Native side of the extra ICU module installer. +class ModuleProvider { + public: + // Returns true if the extra ICU module is installed. + static bool IsModuleInstalled(); +}; + +} // namespace extra_icu + +#endif // CHROME_ANDROID_MODULES_EXTRA_ICU_PROVIDER_MODULE_PROVIDER_H_
diff --git a/chrome/android/modules/extra_icu/public/BUILD.gn b/chrome/android/modules/extra_icu/public/BUILD.gn new file mode 100644 index 0000000..7a9a943 --- /dev/null +++ b/chrome/android/modules/extra_icu/public/BUILD.gn
@@ -0,0 +1,16 @@ +# Copyright 2019 The Chromium Authors. All rights reserved. +# Use of this source code is governed by a BSD-style license that can be +# found in the LICENSE file. + +import("//build/config/android/rules.gni") + +android_library("java") { + java_files = + [ "java/src/org/chromium/chrome/modules/extra_icu/ExtraIcu.java" ] + deps = [ + "//components/module_installer/android:module_installer_java", + "//components/module_installer/android:module_interface_java", + ] + annotation_processor_deps = + [ "//components/module_installer/android:module_interface_processor" ] +}
diff --git a/chrome/android/modules/extra_icu/public/java/src/org/chromium/chrome/modules/extra_icu/ExtraIcu.java b/chrome/android/modules/extra_icu/public/java/src/org/chromium/chrome/modules/extra_icu/ExtraIcu.java new file mode 100644 index 0000000..13beb9a9 --- /dev/null +++ b/chrome/android/modules/extra_icu/public/java/src/org/chromium/chrome/modules/extra_icu/ExtraIcu.java
@@ -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. + +package org.chromium.chrome.modules.extra_icu; + +import org.chromium.components.module_installer.ModuleInterface; + +/** Interface into the extra ICU module. Only used to check whether module is installed. */ +@ModuleInterface(module = "extra_icu", impl = "org.chromium.chrome.modules.extra_icu.ExtraIcuImpl") +public interface ExtraIcu {}
diff --git a/chrome/android/webapk/shell_apk/AndroidManifest.xml b/chrome/android/webapk/shell_apk/AndroidManifest.xml index 1aa5ee6..ccfd7ad 100644 --- a/chrome/android/webapk/shell_apk/AndroidManifest.xml +++ b/chrome/android/webapk/shell_apk/AndroidManifest.xml
@@ -20,12 +20,10 @@ package="{{{manifest_package}}}" android:versionCode="{{{version_code}}}" android:versionName="{{{version_name}}}" > - - <uses-permission android:name="android.permission.VIBRATE"></uses-permission> {{{raw_manifest_tags}}} <uses-sdk - android:minSdkVersion="16" + android:minSdkVersion="19" android:targetSdkVersion="28" /> <application
diff --git a/chrome/android/webapk/shell_apk/BUILD.gn b/chrome/android/webapk/shell_apk/BUILD.gn index e21dd83..49284bb7 100644 --- a/chrome/android/webapk/shell_apk/BUILD.gn +++ b/chrome/android/webapk/shell_apk/BUILD.gn
@@ -75,7 +75,7 @@ "//chrome/android/webapk/libs/common:common_java", "//chrome/android/webapk/libs/common:splash_java", ] - min_sdk_version = 16 + min_sdk_version = 19 } } @@ -92,7 +92,7 @@ "src/org/chromium/webapk/shell_apk/WebApkServiceImplWrapper.java", ] deps += [ ":compiled_in_runtime_library_java" ] - min_sdk_version = 16 + min_sdk_version = 19 } } @@ -178,7 +178,7 @@ android_manifest = _manifest_output android_manifest_dep = ":$_manifest_target_name" - min_sdk_version = 16 + min_sdk_version = 19 target_sdk_version = 28 never_incremental = true enable_multidex = false
diff --git a/chrome/android/webapk/shell_apk/current_version/current_version.gni b/chrome/android/webapk/shell_apk/current_version/current_version.gni index 04977b6..b24b291 100644 --- a/chrome/android/webapk/shell_apk/current_version/current_version.gni +++ b/chrome/android/webapk/shell_apk/current_version/current_version.gni
@@ -12,4 +12,4 @@ # //chrome/android/webapk/shell_apk:webapk is changed. This includes # Java files, Android resource files and AndroidManifest.xml. Does not affect # Chrome.apk -current_shell_apk_version = 106 +current_shell_apk_version = 107
diff --git a/chrome/android/webapk/shell_apk/src/org/chromium/webapk/shell_apk/ChooseHostBrowserDialog.java b/chrome/android/webapk/shell_apk/src/org/chromium/webapk/shell_apk/ChooseHostBrowserDialog.java index 6736966..bdafce16 100644 --- a/chrome/android/webapk/shell_apk/src/org/chromium/webapk/shell_apk/ChooseHostBrowserDialog.java +++ b/chrome/android/webapk/shell_apk/src/org/chromium/webapk/shell_apk/ChooseHostBrowserDialog.java
@@ -201,8 +201,8 @@ Resources res = mContext.getResources(); ImageView icon = (ImageView) convertView.findViewById(R.id.browser_icon); TextView name = (TextView) convertView.findViewById(R.id.browser_name); - WebApkUtils.setPaddingInPixel( - name, res.getDimensionPixelSize(R.dimen.list_column_padding), 0, 0, 0); + name.setPaddingRelative( + res.getDimensionPixelSize(R.dimen.list_column_padding), 0, 0, 0); BrowserItem item = mBrowsers.get(position); name.setEnabled(item.supportsWebApks());
diff --git a/chrome/android/webapk/shell_apk/src/org/chromium/webapk/shell_apk/InstallHostBrowserDialog.java b/chrome/android/webapk/shell_apk/src/org/chromium/webapk/shell_apk/InstallHostBrowserDialog.java index 6e02a854..5ce8f6a 100644 --- a/chrome/android/webapk/shell_apk/src/org/chromium/webapk/shell_apk/InstallHostBrowserDialog.java +++ b/chrome/android/webapk/shell_apk/src/org/chromium/webapk/shell_apk/InstallHostBrowserDialog.java
@@ -49,7 +49,7 @@ TextView name = (TextView) view.findViewById(R.id.browser_name); name.setText(hostBrowserApplicationName); - WebApkUtils.setPaddingInPixel(name, + name.setPaddingRelative( context.getResources().getDimensionPixelSize(R.dimen.list_column_padding), 0, 0, 0); OnDismissListenerCanceler onDismissCanceler = new OnDismissListenerCanceler();
diff --git a/chrome/android/webapk/shell_apk/src/org/chromium/webapk/shell_apk/WebApkUtils.java b/chrome/android/webapk/shell_apk/src/org/chromium/webapk/shell_apk/WebApkUtils.java index 0971d90a..b872bfa 100644 --- a/chrome/android/webapk/shell_apk/src/org/chromium/webapk/shell_apk/WebApkUtils.java +++ b/chrome/android/webapk/shell_apk/src/org/chromium/webapk/shell_apk/WebApkUtils.java
@@ -148,19 +148,6 @@ } /** - * Android uses padding_left under API level 17 and uses padding_start after that. - * If we set the padding in resource file, android will create duplicated resource xml - * with the padding to be different. - */ - public static void setPaddingInPixel(View view, int start, int top, int end, int bottom) { - if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.JELLY_BEAN_MR1) { - view.setPaddingRelative(start, top, end, bottom); - } else { - view.setPadding(start, top, end, bottom); - } - } - - /** * Imitates Chrome's @style/AlertDialogContent. We set the style via Java instead of via * specifying the style in the XML to avoid having layout files in both layout-v17/ and in * layout/. @@ -173,11 +160,11 @@ TypedValue.COMPLEX_UNIT_PX, res.getDimension(R.dimen.headline_size_medium)); int dialogContentPadding = res.getDimensionPixelSize(R.dimen.dialog_content_padding); int titleBottomPadding = res.getDimensionPixelSize(R.dimen.title_bottom_padding); - setPaddingInPixel(titleView, dialogContentPadding, dialogContentPadding, + titleView.setPaddingRelative(dialogContentPadding, dialogContentPadding, dialogContentPadding, titleBottomPadding); int dialogContentTopPadding = res.getDimensionPixelSize(R.dimen.dialog_content_top_padding); - setPaddingInPixel(contentView, dialogContentPadding, dialogContentTopPadding, + contentView.setPaddingRelative(dialogContentPadding, dialogContentTopPadding, dialogContentPadding, dialogContentPadding); }
diff --git a/chrome/app/chrome_main_delegate.cc b/chrome/app/chrome_main_delegate.cc index 86d865d..f400a329 100644 --- a/chrome/app/chrome_main_delegate.cc +++ b/chrome/app/chrome_main_delegate.cc
@@ -141,7 +141,8 @@ #include "base/environment.h" #endif -#if defined(OS_MACOSX) || defined(OS_WIN) || defined(OS_ANDROID) +#if defined(OS_MACOSX) || defined(OS_WIN) || defined(OS_ANDROID) || \ + defined(OS_LINUX) #include "chrome/browser/policy/policy_path_parser.h" #include "components/crash/content/app/crashpad.h" #endif @@ -645,8 +646,11 @@ #if defined(OS_WIN) && !defined(CHROME_MULTIPLE_DLL_BROWSER) v8_crashpad_support::SetUp(); #endif + #if defined(OS_LINUX) - breakpad::SetFirstChanceExceptionHandler(v8::TryHandleWebAssemblyTrapPosix); + if (!crash_reporter::IsCrashpadEnabled()) { + breakpad::SetFirstChanceExceptionHandler(v8::TryHandleWebAssemblyTrapPosix); + } #endif #if defined(OS_POSIX) @@ -1008,7 +1012,13 @@ base::android::InitJavaExceptionReporterForChildProcess(); } #else // !defined(OS_ANDROID) - breakpad::InitCrashReporter(process_type); + if (crash_reporter::IsCrashpadEnabled()) { + crash_reporter::InitializeCrashpad(process_type.empty(), process_type); + crash_reporter::SetFirstChanceExceptionHandler( + v8::TryHandleWebAssemblyTrapPosix); + } else { + breakpad::InitCrashReporter(process_type); + } #endif // defined(OS_ANDROID) } #endif // defined(OS_POSIX) && !defined(OS_MACOSX) @@ -1141,7 +1151,13 @@ base::CommandLine::ForCurrentProcess(); std::string process_type = command_line->GetSwitchValueASCII(switches::kProcessType); - breakpad::InitCrashReporter(process_type); + if (crash_reporter::IsCrashpadEnabled()) { + crash_reporter::InitializeCrashpad(false, process_type); + crash_reporter::SetFirstChanceExceptionHandler( + v8::TryHandleWebAssemblyTrapPosix); + } else { + breakpad::InitCrashReporter(process_type); + } // Reset the command line for the newly spawned process. crash_keys::SetCrashKeysFromCommandLine(*command_line);
diff --git a/chrome/browser/BUILD.gn b/chrome/browser/BUILD.gn index f026f7d..6271da4 100644 --- a/chrome/browser/BUILD.gn +++ b/chrome/browser/BUILD.gn
@@ -845,6 +845,10 @@ "native_window_notification_source.h", "navigation_predictor/navigation_predictor.cc", "navigation_predictor/navigation_predictor.h", + "navigation_predictor/navigation_predictor_keyed_service.cc", + "navigation_predictor/navigation_predictor_keyed_service.h", + "navigation_predictor/navigation_predictor_keyed_service_factory.cc", + "navigation_predictor/navigation_predictor_keyed_service_factory.h", "net/chrome_cookie_notification_details.h", "net/chrome_mojo_proxy_resolver_factory.cc", "net/chrome_mojo_proxy_resolver_factory.h", @@ -1376,8 +1380,6 @@ "previews/previews_lite_page_decider.h", "previews/previews_lite_page_infobar_delegate.cc", "previews/previews_lite_page_infobar_delegate.h", - "previews/previews_lite_page_navigation_throttle.cc", - "previews/previews_lite_page_navigation_throttle.h", "previews/previews_lite_page_predictor.cc", "previews/previews_lite_page_predictor.h", "previews/previews_lite_page_redirect_url_loader.cc", @@ -2891,6 +2893,7 @@ ":explore_sites_proto", ":usage_stats_proto", "//chrome/android:jni_headers", + "//chrome/android/modules/extra_icu/provider:native", "//chrome/browser/android/thin_webview/internal", "//chrome/browser/android/webapk:proto", "//chrome/services/media_gallery_util/public/cpp", @@ -3986,8 +3989,6 @@ if (is_win || is_mac) { # Sources (generally "desktop OS importers") used only on Mac & Windows. sources += [ - "crash_upload_list/crash_upload_list_crashpad.cc", - "crash_upload_list/crash_upload_list_crashpad.h", "recovery/recovery_install_global_error.cc", "recovery/recovery_install_global_error.h", "recovery/recovery_install_global_error_factory.cc", @@ -4134,6 +4135,8 @@ if (is_win || is_mac || is_linux) { sources += [ + "crash_upload_list/crash_upload_list_crashpad.cc", + "crash_upload_list/crash_upload_list_crashpad.h", "payments/chrome_payment_request_delegate.cc", "payments/chrome_payment_request_delegate.h", "payments/payment_request_display_manager_factory.cc",
diff --git a/chrome/browser/DEPS b/chrome/browser/DEPS index de68e005..9d9e185c 100644 --- a/chrome/browser/DEPS +++ b/chrome/browser/DEPS
@@ -4,6 +4,7 @@ "+chrome/android/chrome_jni_headers", "+chrome/android/features/autofill_assistant/jni_headers", "+chrome/android/features/dev_ui", + "+chrome/android/modules", "+chrome/android/public/profiles/jni_headers", "+chrome/app", "+chrome/chrome_watcher",
diff --git a/chrome/browser/about_flags.cc b/chrome/browser/about_flags.cc index 2a4ca23..90d4dc1bd 100644 --- a/chrome/browser/about_flags.cc +++ b/chrome/browser/about_flags.cc
@@ -148,6 +148,7 @@ #include "third_party/blink/public/common/features.h" #include "third_party/blink/public/common/forcedark/forcedark_switches.h" #include "third_party/leveldatabase/leveldb_features.h" +#include "ui/accessibility/accessibility_features.h" #include "ui/accessibility/accessibility_switches.h" #include "ui/base/ui_base_features.h" #include "ui/base/ui_base_switches.h" @@ -1286,6 +1287,12 @@ }; #if defined(OS_ANDROID) +const FeatureEntry::FeatureParam kAndroidNightModeDefaultToLightConstant[] = { + {"default_light_theme", "true"}}; +const FeatureEntry::FeatureVariation kAndroidNightModeFeatureVariations[] = { + {"(default to light theme)", kAndroidNightModeDefaultToLightConstant, + base::size(kAndroidNightModeDefaultToLightConstant), nullptr}}; + const FeatureEntry::FeatureParam kOmniboxSearchEngineLogoRoundedEdgesVariationConstant[] = { {"rounded_edges", "true"}}; @@ -1711,7 +1718,7 @@ SINGLE_VALUE_TYPE(chromeos::switches::kShelfHoverPreviews)}, {"shelf-scrollable", flag_descriptions::kShelfScrollableName, flag_descriptions::kShelfScrollableDescription, kOsCrOS, - SINGLE_VALUE_TYPE(chromeos::switches::kShelfScrollable)}, + FEATURE_VALUE_TYPE(chromeos::features::kShelfScrollable)}, {"show-bluetooth-debug-log-toggle", flag_descriptions::kShowBluetoothDebugLogToggleName, flag_descriptions::kShowBluetoothDebugLogToggleDescription, kOsCrOS, @@ -2072,11 +2079,6 @@ flag_descriptions::kEnableLitePageServerPreviewsName, flag_descriptions::kEnableLitePageServerPreviewsDescription, kOsAndroid, FEATURE_VALUE_TYPE(previews::features::kLitePageServerPreviews)}, - {"enable-url-loader-lite-page-server-previews", - flag_descriptions::kEnableURLLoaderLitePageServerPreviewsName, - flag_descriptions::kEnableURLLoaderLitePageServerPreviewsName, kOsAndroid, - FEATURE_VALUE_TYPE( - previews::features::kHTTPSServerPreviewsUsingURLLoader)}, #endif // OS_ANDROID #if defined(OS_CHROMEOS) || defined(OS_LINUX) {"enable-save-data", flag_descriptions::kEnableSaveDataName, @@ -2422,7 +2424,9 @@ #if BUILDFLAG(ENABLE_ANDROID_NIGHT_MODE) {"enable-android-night-mode", flag_descriptions::kAndroidNightModeName, flag_descriptions::kAndroidNightModeDescription, kOsAndroid, - FEATURE_VALUE_TYPE(chrome::android::kAndroidNightMode)}, + FEATURE_WITH_PARAMS_VALUE_TYPE(chrome::android::kAndroidNightMode, + kAndroidNightModeFeatureVariations, + "AndroidNightMode")}, #endif // BUILDFLAG(ENABLE_ANDROID_NIGHT_MODE) #endif // OS_ANDROID #if defined(OS_LINUX) && !defined(OS_CHROMEOS) @@ -2930,6 +2934,11 @@ flag_descriptions::kOmniboxZeroSuggestionsOnNTPRealboxDescription, kOsDesktop, FEATURE_VALUE_TYPE(omnibox::kZeroSuggestionsOnNTPRealbox)}, + {"omnibox-zero-suggestions-on-serp", + flag_descriptions::kOmniboxZeroSuggestionsOnSERPName, + flag_descriptions::kOmniboxZeroSuggestionsOnSERPDescription, kOsDesktop, + FEATURE_VALUE_TYPE(omnibox::kZeroSuggestionsOnSERP)}, + {"omnibox-material-design-weather-icons", flag_descriptions::kOmniboxMaterialDesignWeatherIconsName, flag_descriptions::kOmniboxMaterialDesignWeatherIconsDescription, @@ -3460,6 +3469,11 @@ kOsDesktop, FEATURE_VALUE_TYPE(features::kExperimentalAccessibilityLabels)}, + {"enable-accessibility-expose-display-none", + flag_descriptions::kAccessibilityExposeDisplayNoneName, + flag_descriptions::kAccessibilityExposeDisplayNoneDescription, kOsAll, + FEATURE_VALUE_TYPE(features::kEnableAccessibilityExposeDisplayNone)}, + {"enable-accessibility-object-model", flag_descriptions::kEnableAccessibilityObjectModelName, flag_descriptions::kEnableAccessibilityObjectModelDescription, kOsAll,
diff --git a/chrome/browser/android/chrome_feature_list.cc b/chrome/browser/android/chrome_feature_list.cc index f30aa40..ec3a4e6 100644 --- a/chrome/browser/android/chrome_feature_list.cc +++ b/chrome/browser/android/chrome_feature_list.cc
@@ -223,7 +223,6 @@ &password_manager::features::kPasswordManagerOnboardingAndroid, &password_manager::features::kLeakDetection, &safe_browsing::kCaptureSafetyNetId, - &safe_browsing::kSendOnFocusPing, &signin::kMiceFeature, &switches::kSyncManualStartAndroid, &unified_consent::kUnifiedConsent,
diff --git a/chrome/browser/android/tab_web_contents_delegate_android.cc b/chrome/browser/android/tab_web_contents_delegate_android.cc index fd35f41..2a79a24 100644 --- a/chrome/browser/android/tab_web_contents_delegate_android.cc +++ b/chrome/browser/android/tab_web_contents_delegate_android.cc
@@ -7,6 +7,9 @@ #include <stddef.h> #include <memory> +#include <string> +#include <utility> +#include <vector> #include "base/android/jni_android.h" #include "base/android/jni_string.h" @@ -332,11 +335,8 @@ nav_params.source_contents = source; nav_params.window_action = NavigateParams::SHOW_WINDOW; nav_params.user_gesture = params.user_gesture; - if ((params.disposition == WindowOpenDisposition::NEW_POPUP || - params.disposition == WindowOpenDisposition::NEW_FOREGROUND_TAB || - params.disposition == WindowOpenDisposition::NEW_BACKGROUND_TAB || - params.disposition == WindowOpenDisposition::NEW_WINDOW) && - MaybeBlockPopup(source, base::Optional<GURL>(), &nav_params, ¶ms, + if (ConsiderForPopupBlocking(params.disposition) && + MaybeBlockPopup(source, nullptr, &nav_params, ¶ms, blink::mojom::WindowFeatures())) { return nullptr; }
diff --git a/chrome/browser/android/vr/arcore_device/arcore.h b/chrome/browser/android/vr/arcore_device/arcore.h index 6de97776..5870424 100644 --- a/chrome/browser/android/vr/arcore_device/arcore.h +++ b/chrome/browser/android/vr/arcore_device/arcore.h
@@ -55,12 +55,12 @@ const mojom::XRRayPtr& ray, std::vector<mojom::XRHitResultPtr>* hit_results) = 0; - virtual base::Optional<int32_t> CreateAnchor( + virtual base::Optional<uint32_t> CreateAnchor( const mojom::VRPosePtr& pose) = 0; - virtual base::Optional<int32_t> CreateAnchor(const mojom::VRPosePtr& pose, - int32_t plane_id) = 0; + virtual base::Optional<uint32_t> CreateAnchor(const mojom::VRPosePtr& pose, + uint32_t plane_id) = 0; - virtual void DetachAnchor(int32_t anchor_id) = 0; + virtual void DetachAnchor(uint32_t anchor_id) = 0; virtual void Pause() = 0; virtual void Resume() = 0;
diff --git a/chrome/browser/android/vr/arcore_device/arcore_gl.cc b/chrome/browser/android/vr/arcore_device/arcore_gl.cc index 61ae8c56..2b6d3fb 100644 --- a/chrome/browser/android/vr/arcore_device/arcore_gl.cc +++ b/chrome/browser/android/vr/arcore_device/arcore_gl.cc
@@ -580,7 +580,7 @@ CreateAnchorCallback callback) { DVLOG(2) << __func__; - base::Optional<int32_t> maybe_anchor_id = arcore_->CreateAnchor(anchor_pose); + base::Optional<uint32_t> maybe_anchor_id = arcore_->CreateAnchor(anchor_pose); if (maybe_anchor_id) { std::move(callback).Run(device::mojom::CreateAnchorResult::SUCCESS, @@ -591,11 +591,11 @@ } void ArCoreGl::CreatePlaneAnchor(mojom::VRPosePtr anchor_pose, - int32_t plane_id, + uint32_t plane_id, CreatePlaneAnchorCallback callback) { DVLOG(2) << __func__; - base::Optional<int32_t> maybe_anchor_id = + base::Optional<uint32_t> maybe_anchor_id = arcore_->CreateAnchor(anchor_pose, plane_id); if (maybe_anchor_id) { @@ -606,7 +606,7 @@ } } -void ArCoreGl::DetachAnchor(int32_t anchor_id) { +void ArCoreGl::DetachAnchor(uint32_t anchor_id) { DVLOG(2) << __func__; arcore_->DetachAnchor(anchor_id);
diff --git a/chrome/browser/android/vr/arcore_device/arcore_gl.h b/chrome/browser/android/vr/arcore_device/arcore_gl.h index e283a1f..da95ffe3 100644 --- a/chrome/browser/android/vr/arcore_device/arcore_gl.h +++ b/chrome/browser/android/vr/arcore_device/arcore_gl.h
@@ -111,10 +111,10 @@ void CreateAnchor(mojom::VRPosePtr anchor_pose, CreateAnchorCallback callback) override; void CreatePlaneAnchor(mojom::VRPosePtr anchor_pose, - int32_t plane_id, + uint32_t plane_id, CreatePlaneAnchorCallback callback) override; - void DetachAnchor(int32_t anchor_id) override; + void DetachAnchor(uint32_t anchor_id) override; // mojom::XRSessionController void SetFrameDataRestricted(bool restricted) override;
diff --git a/chrome/browser/android/vr/arcore_device/arcore_impl.cc b/chrome/browser/android/vr/arcore_device/arcore_impl.cc index fb80f464..fa0cdb33 100644 --- a/chrome/browser/android/vr/arcore_device/arcore_impl.cc +++ b/chrome/browser/android/vr/arcore_device/arcore_impl.cc
@@ -319,7 +319,7 @@ return; } - int32_t anchor_id; + AnchorId anchor_id; bool created; std::tie(anchor_id, created) = *maybe_anchor_id_and_created; @@ -327,16 +327,17 @@ << "Anchor creation is app-initiated - we should never encounter an " "anchor that was created outside of `ArCoreImpl::CreateAnchor()`."; - result.push_back(mojom::XRAnchorData::New(anchor_id, std::move(pose))); + result.push_back( + mojom::XRAnchorData::New(anchor_id.GetUnsafeValue(), std::move(pose))); }); return result; } -std::vector<int32_t> ArCoreImpl::GetAllAnchorIds() { +std::vector<uint32_t> ArCoreImpl::GetAllAnchorIds() { EnsureArCoreAnchorsList(); - std::vector<int32_t> result; + std::vector<uint32_t> result; ArSession_getAllAnchors(arcore_session_.get(), arcore_anchors_.get()); @@ -349,7 +350,7 @@ return; } - int32_t anchor_id; + AnchorId anchor_id; bool created; std::tie(anchor_id, created) = *maybe_anchor_id_and_created; @@ -440,12 +441,12 @@ return; } - int32_t plane_id; + PlaneId plane_id; bool created; std::tie(plane_id, created) = *maybe_plane_id_and_created; result.push_back(mojom::XRPlaneData::New( - plane_id, + plane_id.GetUnsafeValue(), mojo::ConvertTo<device::mojom::XRPlaneOrientation>(plane_type), std::move(pose), std::move(vertices))); }); @@ -453,17 +454,16 @@ return result; } -std::vector<int32_t> ArCoreImpl::GetAllPlaneIds() { +std::vector<uint32_t> ArCoreImpl::GetAllPlaneIds() { EnsureArCorePlanesList(); - std::vector<int32_t> result; + std::vector<uint32_t> result; ArTrackableType plane_tracked_type = AR_TRACKABLE_PLANE; ArSession_getAllTrackables(arcore_session_.get(), plane_tracked_type, arcore_planes_.get()); - std::unordered_map<int32_t, - device::internal::ScopedArCoreObject<ArTrackable*>> + std::map<PlaneId, device::internal::ScopedArCoreObject<ArTrackable*>> plane_id_to_plane_object; ForEachArCorePlane([this, &plane_id_to_plane_object, &result]( @@ -477,7 +477,7 @@ return; } - int32_t plane_id; + PlaneId plane_id; bool created; std::tie(plane_id, created) = *maybe_plane_id_and_created; @@ -496,8 +496,8 @@ mojom::XRPlaneDetectionDataPtr ArCoreImpl::GetDetectedPlanesData() { TRACE_EVENT0("gpu", __FUNCTION__); - std::vector<mojom::XRPlaneDataPtr> updated_planes = GetUpdatedPlanesData(); - std::vector<int32_t> all_plane_ids = GetAllPlaneIds(); + auto updated_planes = GetUpdatedPlanesData(); + auto all_plane_ids = GetAllPlaneIds(); return mojom::XRPlaneDetectionData::New(all_plane_ids, std::move(updated_planes)); @@ -512,38 +512,38 @@ return mojom::XRAnchorsData::New(all_anchor_ids, std::move(updated_anchors)); } -base::Optional<std::pair<int32_t, bool>> ArCoreImpl::CreateOrGetPlaneId( +base::Optional<std::pair<PlaneId, bool>> ArCoreImpl::CreateOrGetPlaneId( void* plane_address) { auto it = ar_plane_address_to_id_.find(plane_address); if (it != ar_plane_address_to_id_.end()) { return std::make_pair(it->second, false); } - if (next_id_ == std::numeric_limits<int32_t>::max()) { + if (next_id_ == std::numeric_limits<uint32_t>::max()) { return base::nullopt; } - int32_t current_id = next_id_++; + uint32_t current_id = next_id_++; ar_plane_address_to_id_.emplace(plane_address, current_id); - return std::make_pair(current_id, true); + return std::make_pair(PlaneId(current_id), true); } -base::Optional<std::pair<int32_t, bool>> ArCoreImpl::CreateOrGetAnchorId( +base::Optional<std::pair<AnchorId, bool>> ArCoreImpl::CreateOrGetAnchorId( void* anchor_address) { auto it = ar_anchor_address_to_id_.find(anchor_address); if (it != ar_anchor_address_to_id_.end()) { return std::make_pair(it->second, false); } - if (next_id_ == std::numeric_limits<int32_t>::max()) { + if (next_id_ == std::numeric_limits<uint32_t>::max()) { return base::nullopt; } - int32_t current_id = next_id_++; + uint32_t current_id = next_id_++; ar_anchor_address_to_id_.emplace(anchor_address, current_id); - return std::make_pair(current_id, true); + return std::make_pair(AnchorId(current_id), true); } void ArCoreImpl::Pause() { @@ -717,7 +717,7 @@ return true; } -base::Optional<int32_t> ArCoreImpl::CreateAnchor( +base::Optional<uint32_t> ArCoreImpl::CreateAnchor( const device::mojom::VRPosePtr& pose) { DCHECK(pose); @@ -734,7 +734,7 @@ return base::nullopt; } - int32_t anchor_id; + AnchorId anchor_id; bool created; std::tie(anchor_id, created) = *maybe_anchor_id_and_created; @@ -743,17 +743,17 @@ anchor_id_to_anchor_object_[anchor_id] = std::move(ar_anchor); - return anchor_id; + return anchor_id.GetUnsafeValue(); } -base::Optional<int32_t> ArCoreImpl::CreateAnchor( +base::Optional<uint32_t> ArCoreImpl::CreateAnchor( const device::mojom::VRPosePtr& pose, - int32_t plane_id) { + uint32_t plane_id) { DCHECK(pose); auto ar_pose = GetArPoseFromMojomPose(arcore_session_.get(), pose); - auto it = plane_id_to_plane_object_.find(plane_id); + auto it = plane_id_to_plane_object_.find(PlaneId(plane_id)); if (it == plane_id_to_plane_object_.end()) { return base::nullopt; } @@ -769,7 +769,7 @@ return base::nullopt; } - int32_t anchor_id; + AnchorId anchor_id; bool created; std::tie(anchor_id, created) = *maybe_anchor_id_and_created; @@ -778,11 +778,11 @@ anchor_id_to_anchor_object_[anchor_id] = std::move(ar_anchor); - return anchor_id; + return anchor_id.GetUnsafeValue(); } -void ArCoreImpl::DetachAnchor(int32_t anchor_id) { - auto it = anchor_id_to_anchor_object_.find(anchor_id); +void ArCoreImpl::DetachAnchor(uint32_t anchor_id) { + auto it = anchor_id_to_anchor_object_.find(AnchorId(anchor_id)); if (it == anchor_id_to_anchor_object_.end()) { return; }
diff --git a/chrome/browser/android/vr/arcore_device/arcore_impl.h b/chrome/browser/android/vr/arcore_device/arcore_impl.h index ed47b1f..21fd467b 100644 --- a/chrome/browser/android/vr/arcore_device/arcore_impl.h +++ b/chrome/browser/android/vr/arcore_device/arcore_impl.h
@@ -8,6 +8,7 @@ #include "base/macros.h" #include "base/optional.h" #include "base/scoped_generic.h" +#include "base/util/type_safety/id_type.h" #include "chrome/browser/android/vr/arcore_device/arcore.h" #include "chrome/browser/android/vr/arcore_device/arcore_sdk.h" #include "device/vr/public/mojom/vr_service.mojom.h" @@ -88,6 +89,9 @@ } // namespace internal +using PlaneId = util::IdTypeU32<class PlaneTag>; +using AnchorId = util::IdTypeU32<class AnchorTag>; + // This class should be created and accessed entirely on a Gl thread. class ArCoreImpl : public ArCore { public: @@ -114,12 +118,12 @@ bool RequestHitTest(const mojom::XRRayPtr& ray, std::vector<mojom::XRHitResultPtr>* hit_results) override; - base::Optional<int32_t> CreateAnchor( + base::Optional<uint32_t> CreateAnchor( const device::mojom::VRPosePtr& pose) override; - base::Optional<int32_t> CreateAnchor(const device::mojom::VRPosePtr& pose, - int32_t plane_id) override; + base::Optional<uint32_t> CreateAnchor(const device::mojom::VRPosePtr& pose, + uint32_t plane_id) override; - void DetachAnchor(int32_t anchor_id) override; + void DetachAnchor(uint32_t anchor_id) override; private: bool IsOnGlThread(); @@ -162,7 +166,7 @@ // planes already have an ID assigned. The result includes freshly assigned // IDs for newly detected planes along with previously known IDs for updated // and unchanged planes. It excludes planes that are no longer being tracked. - std::vector<int32_t> GetAllPlaneIds(); + std::vector<uint32_t> GetAllPlaneIds(); // Returns vector containing information about all anchors updated in the // current frame. @@ -170,23 +174,22 @@ // The result will contain IDs of all anchors still tracked in the current // frame. - std::vector<int32_t> GetAllAnchorIds(); + std::vector<uint32_t> GetAllAnchorIds(); - int32_t next_id_ = 1; - std::unordered_map<void*, int32_t> ar_plane_address_to_id_; - std::unordered_map<int32_t, - device::internal::ScopedArCoreObject<ArTrackable*>> + uint32_t next_id_ = 1; + std::map<void*, PlaneId> ar_plane_address_to_id_; + std::map<PlaneId, device::internal::ScopedArCoreObject<ArTrackable*>> plane_id_to_plane_object_; - std::unordered_map<void*, int32_t> ar_anchor_address_to_id_; - std::unordered_map<int32_t, device::internal::ScopedArCoreObject<ArAnchor*>> + std::map<void*, AnchorId> ar_anchor_address_to_id_; + std::map<AnchorId, device::internal::ScopedArCoreObject<ArAnchor*>> anchor_id_to_anchor_object_; // Returns tuple containing plane id and a boolean signifying that the plane // was created. The result will be a nullopt in case the ID should be assigned // but next ID would result in an integer overflow. - base::Optional<std::pair<int32_t, bool>> CreateOrGetPlaneId( + base::Optional<std::pair<PlaneId, bool>> CreateOrGetPlaneId( void* plane_address); - base::Optional<std::pair<int32_t, bool>> CreateOrGetAnchorId( + base::Optional<std::pair<AnchorId, bool>> CreateOrGetAnchorId( void* anchor_address); // Executes |fn| for each still tracked, non-subsumed plane present in
diff --git a/chrome/browser/android/vr/arcore_device/fake_arcore.cc b/chrome/browser/android/vr/arcore_device/fake_arcore.cc index 8f973002..c3919a2 100644 --- a/chrome/browser/android/vr/arcore_device/fake_arcore.cc +++ b/chrome/browser/android/vr/arcore_device/fake_arcore.cc
@@ -225,13 +225,13 @@ mojom::XRPlaneData::New(1, device::mojom::XRPlaneOrientation::HORIZONTAL, std::move(pose), std::move(vertices))); - return mojom::XRPlaneDetectionData::New(std::vector<int32_t>{1}, + return mojom::XRPlaneDetectionData::New(std::vector<uint32_t>{1}, std::move(result)); } mojom::XRAnchorsDataPtr FakeArCore::GetAnchorsData() { std::vector<mojom::XRAnchorDataPtr> result; - std::vector<int32_t> result_ids; + std::vector<uint32_t> result_ids; for (auto& anchor_id_and_data : anchors_) { mojom::VRPosePtr pose = mojom::VRPose::New(); @@ -246,13 +246,14 @@ return mojom::XRAnchorsData::New(std::move(result_ids), std::move(result)); } -base::Optional<int32_t> FakeArCore::CreateAnchor(const mojom::VRPosePtr& pose, - int32_t plane_id) { +base::Optional<uint32_t> FakeArCore::CreateAnchor(const mojom::VRPosePtr& pose, + uint32_t plane_id) { // TODO(992035): Fix this when implementing tests. return CreateAnchor(pose); } -base::Optional<int32_t> FakeArCore::CreateAnchor(const mojom::VRPosePtr& pose) { +base::Optional<uint32_t> FakeArCore::CreateAnchor( + const mojom::VRPosePtr& pose) { DCHECK(pose); gfx::Point3F position = @@ -274,7 +275,7 @@ return anchor_id; } -void FakeArCore::DetachAnchor(int32_t anchor_id) { +void FakeArCore::DetachAnchor(uint32_t anchor_id) { auto count = anchors_.erase(anchor_id); DCHECK_EQ(1u, count); }
diff --git a/chrome/browser/android/vr/arcore_device/fake_arcore.h b/chrome/browser/android/vr/arcore_device/fake_arcore.h index 6e92972..6735393f 100644 --- a/chrome/browser/android/vr/arcore_device/fake_arcore.h +++ b/chrome/browser/android/vr/arcore_device/fake_arcore.h
@@ -40,11 +40,11 @@ mojom::XRPlaneDetectionDataPtr GetDetectedPlanesData() override; mojom::XRAnchorsDataPtr GetAnchorsData() override; - base::Optional<int32_t> CreateAnchor( + base::Optional<uint32_t> CreateAnchor( const device::mojom::VRPosePtr& pose) override; - base::Optional<int32_t> CreateAnchor(const device::mojom::VRPosePtr& pose, - int32_t plane_id) override; - void DetachAnchor(int32_t anchor_id) override; + base::Optional<uint32_t> CreateAnchor(const device::mojom::VRPosePtr& pose, + uint32_t plane_id) override; + void DetachAnchor(uint32_t anchor_id) override; void SetCameraAspect(float aspect) { camera_aspect_ = aspect; } @@ -63,8 +63,8 @@ gfx::Quaternion orientation; }; - int32_t next_id_ = 100; - std::unordered_map<int32_t, FakeAnchorData> anchors_; + uint32_t next_id_ = 100; + std::unordered_map<uint32_t, FakeAnchorData> anchors_; DISALLOW_COPY_AND_ASSIGN(FakeArCore); };
diff --git a/chrome/browser/apps/platform_apps/shortcut_manager.cc b/chrome/browser/apps/platform_apps/shortcut_manager.cc index bf82f7d..c2e7b96 100644 --- a/chrome/browser/apps/platform_apps/shortcut_manager.cc +++ b/chrome/browser/apps/platform_apps/shortcut_manager.cc
@@ -26,7 +26,6 @@ #include "content/public/browser/browser_task_traits.h" #include "content/public/browser/browser_thread.h" #include "content/public/common/content_switches.h" -#include "extensions/browser/extension_registry.h" #include "extensions/browser/extension_system.h" #include "extensions/common/extension_set.h" @@ -72,9 +71,7 @@ } AppShortcutManager::AppShortcutManager(Profile* profile) - : profile_(profile), - is_profile_attributes_storage_observer_(false), - extension_registry_observer_(this) { + : profile_(profile), is_profile_attributes_storage_observer_(false) { // Use of g_browser_process requires that we are either on the UI thread, or // there are no threads initialized (such as in unit tests). DCHECK(!content::BrowserThread::IsThreadInitialized(
diff --git a/chrome/browser/apps/platform_apps/shortcut_manager.h b/chrome/browser/apps/platform_apps/shortcut_manager.h index d2583a0..fad39152 100644 --- a/chrome/browser/apps/platform_apps/shortcut_manager.h +++ b/chrome/browser/apps/platform_apps/shortcut_manager.h
@@ -10,15 +10,12 @@ #include "base/scoped_observer.h" #include "chrome/browser/profiles/profile_attributes_storage.h" #include "components/keyed_service/core/keyed_service.h" +#include "extensions/browser/extension_registry.h" #include "extensions/browser/extension_registry_observer.h" #include "extensions/common/extension.h" class Profile; -namespace extensions { -class ExtensionRegistry; -} - namespace user_prefs { class PrefRegistrySyncable; } @@ -60,7 +57,7 @@ ScopedObserver<extensions::ExtensionRegistry, extensions::ExtensionRegistryObserver> - extension_registry_observer_; + extension_registry_observer_{this}; base::WeakPtrFactory<AppShortcutManager> weak_ptr_factory_{this};
diff --git a/chrome/browser/autocomplete/shortcuts_extensions_manager.cc b/chrome/browser/autocomplete/shortcuts_extensions_manager.cc index 51a01b7..5f6cf3a1 100644 --- a/chrome/browser/autocomplete/shortcuts_extensions_manager.cc +++ b/chrome/browser/autocomplete/shortcuts_extensions_manager.cc
@@ -7,11 +7,10 @@ #include "chrome/browser/autocomplete/shortcuts_backend_factory.h" #include "chrome/browser/profiles/profile.h" #include "components/omnibox/browser/shortcuts_backend.h" -#include "extensions/browser/extension_registry.h" #include "extensions/common/extension.h" ShortcutsExtensionsManager::ShortcutsExtensionsManager(Profile* profile) - : registry_observer_(this), profile_(profile) { + : profile_(profile) { DCHECK(profile_); registry_observer_.Add(extensions::ExtensionRegistry::Get(profile_)); }
diff --git a/chrome/browser/autocomplete/shortcuts_extensions_manager.h b/chrome/browser/autocomplete/shortcuts_extensions_manager.h index 4f60a5b..8f876d6 100644 --- a/chrome/browser/autocomplete/shortcuts_extensions_manager.h +++ b/chrome/browser/autocomplete/shortcuts_extensions_manager.h
@@ -8,14 +8,11 @@ #include "base/macros.h" #include "base/scoped_observer.h" #include "base/supports_user_data.h" +#include "extensions/browser/extension_registry.h" #include "extensions/browser/extension_registry_observer.h" class Profile; -namespace extensions { -class ExtensionRegistry; -} - // This class manages the removal of shortcuts associated with an extension when // that extension is unloaded. class ShortcutsExtensionsManager @@ -34,7 +31,7 @@ private: ScopedObserver<extensions::ExtensionRegistry, extensions::ExtensionRegistryObserver> - registry_observer_; + registry_observer_{this}; Profile* profile_; DISALLOW_COPY_AND_ASSIGN(ShortcutsExtensionsManager);
diff --git a/chrome/browser/banners/app_banner_manager_desktop.cc b/chrome/browser/banners/app_banner_manager_desktop.cc index 1b55b61..3c5c5dd0 100644 --- a/chrome/browser/banners/app_banner_manager_desktop.cc +++ b/chrome/browser/banners/app_banner_manager_desktop.cc
@@ -13,7 +13,6 @@ #include "chrome/browser/banners/app_banner_settings_helper.h" #include "chrome/browser/profiles/profile.h" #include "chrome/browser/ui/web_applications/web_app_dialog_utils.h" -#include "chrome/browser/web_applications/components/app_registrar.h" #include "chrome/browser/web_applications/components/web_app_constants.h" #include "chrome/browser/web_applications/components/web_app_helpers.h" #include "chrome/browser/web_applications/extensions/bookmark_app_util.h" @@ -55,7 +54,7 @@ AppBannerManagerDesktop::AppBannerManagerDesktop( content::WebContents* web_contents) - : AppBannerManager(web_contents), registrar_observer_(this) { + : AppBannerManager(web_contents) { Profile* profile = Profile::FromBrowserContext(web_contents->GetBrowserContext()); extension_registry_ = extensions::ExtensionRegistry::Get(profile);
diff --git a/chrome/browser/banners/app_banner_manager_desktop.h b/chrome/browser/banners/app_banner_manager_desktop.h index 0f5132b8..80ad977 100644 --- a/chrome/browser/banners/app_banner_manager_desktop.h +++ b/chrome/browser/banners/app_banner_manager_desktop.h
@@ -9,6 +9,7 @@ #include "base/macros.h" #include "base/memory/weak_ptr.h" +#include "base/scoped_observer.h" #include "chrome/browser/banners/app_banner_manager.h" #include "chrome/browser/web_applications/components/app_registrar.h" #include "chrome/browser/web_applications/components/app_registrar_observer.h" @@ -82,7 +83,7 @@ extensions::ExtensionRegistry* extension_registry_; ScopedObserver<web_app::AppRegistrar, web_app::AppRegistrarObserver> - registrar_observer_; + registrar_observer_{this}; base::WeakPtrFactory<AppBannerManagerDesktop> weak_factory_{this};
diff --git a/chrome/browser/browsing_data/browsing_data_history_observer_service.cc b/chrome/browser/browsing_data/browsing_data_history_observer_service.cc index 8c237ea9..2b3b5a7c 100644 --- a/chrome/browser/browsing_data/browsing_data_history_observer_service.cc +++ b/chrome/browser/browsing_data/browsing_data_history_observer_service.cc
@@ -9,7 +9,6 @@ #include "chrome/browser/profiles/profile.h" #include "chrome/browser/sessions/tab_restore_service_factory.h" #include "chrome/common/buildflags.h" -#include "components/history/core/browser/history_service.h" #include "components/keyed_service/content/browser_context_dependency_manager.h" #if BUILDFLAG(ENABLE_SESSION_SERVICE) @@ -18,7 +17,7 @@ BrowsingDataHistoryObserverService::BrowsingDataHistoryObserverService( Profile* profile) - : profile_(profile), history_observer_(this) { + : profile_(profile) { auto* history_service = HistoryServiceFactory::GetForProfile( profile, ServiceAccessType::EXPLICIT_ACCESS); if (history_service)
diff --git a/chrome/browser/browsing_data/browsing_data_history_observer_service.h b/chrome/browser/browsing_data/browsing_data_history_observer_service.h index 75b0167..f96f9590 100644 --- a/chrome/browser/browsing_data/browsing_data_history_observer_service.h +++ b/chrome/browser/browsing_data/browsing_data_history_observer_service.h
@@ -6,6 +6,7 @@ #define CHROME_BROWSER_BROWSING_DATA_BROWSING_DATA_HISTORY_OBSERVER_SERVICE_H_ #include "base/scoped_observer.h" +#include "components/history/core/browser/history_service.h" #include "components/history/core/browser/history_service_observer.h" #include "components/keyed_service/content/browser_context_keyed_service_factory.h" #include "components/keyed_service/core/keyed_service.h" @@ -50,7 +51,7 @@ Profile* profile_; ScopedObserver<history::HistoryService, history::HistoryServiceObserver> - history_observer_; + history_observer_{this}; DISALLOW_COPY_AND_ASSIGN(BrowsingDataHistoryObserverService); };
diff --git a/chrome/browser/chrome_browser_main.cc b/chrome/browser/chrome_browser_main.cc index 60585f96..613647d8 100644 --- a/chrome/browser/chrome_browser_main.cc +++ b/chrome/browser/chrome_browser_main.cc
@@ -227,6 +227,7 @@ #if defined(OS_LINUX) #include "components/crash/content/app/breakpad_linux.h" +#include "components/crash/content/app/crashpad.h" #endif #if defined(OS_MACOSX) @@ -1089,7 +1090,9 @@ #if defined(OS_LINUX) || defined(OS_OPENBSD) // Set the product channel for crash reports. - breakpad::SetChannelCrashKey(chrome::GetChannelName()); + if (!crash_reporter::IsCrashpadEnabled()) { + breakpad::SetChannelCrashKey(chrome::GetChannelName()); + } #endif // defined(OS_LINUX) || defined(OS_OPENBSD) #if defined(OS_MACOSX)
diff --git a/chrome/browser/chrome_browser_main_linux.cc b/chrome/browser/chrome_browser_main_linux.cc index 452bca5e..39db450 100644 --- a/chrome/browser/chrome_browser_main_linux.cc +++ b/chrome/browser/chrome_browser_main_linux.cc
@@ -18,6 +18,7 @@ #include "chrome/browser/browser_process.h" #include "chrome/grit/chromium_strings.h" #include "components/crash/content/app/breakpad_linux.h" +#include "components/crash/content/app/crashpad.h" #include "components/metrics/metrics_service.h" #include "content/public/browser/browser_task_traits.h" #include "device/bluetooth/dbus/bluez_dbus_manager.h" @@ -91,8 +92,10 @@ void ChromeBrowserMainPartsLinux::PostProfileInit() { ChromeBrowserMainPartsPosix::PostProfileInit(); - g_browser_process->metrics_service()->RecordBreakpadRegistration( - breakpad::IsCrashReporterEnabled()); + bool enabled = (crash_reporter::IsCrashpadEnabled() && + crash_reporter::GetUploadsEnabled()) || + breakpad::IsCrashReporterEnabled(); + g_browser_process->metrics_service()->RecordBreakpadRegistration(enabled); } void ChromeBrowserMainPartsLinux::PostMainMessageLoopStart() {
diff --git a/chrome/browser/chrome_content_browser_client.cc b/chrome/browser/chrome_content_browser_client.cc index 10bc86f..0900af1 100644 --- a/chrome/browser/chrome_content_browser_client.cc +++ b/chrome/browser/chrome_content_browser_client.cc
@@ -100,7 +100,6 @@ #include "chrome/browser/prerender/prerender_util.h" #include "chrome/browser/previews/previews_content_util.h" #include "chrome/browser/previews/previews_lite_page_decider.h" -#include "chrome/browser/previews/previews_lite_page_navigation_throttle.h" #include "chrome/browser/previews/previews_lite_page_url_loader_interceptor.h" #include "chrome/browser/previews/previews_service.h" #include "chrome/browser/previews/previews_service_factory.h" @@ -463,6 +462,11 @@ #include "chrome/browser/browser_switcher/browser_switcher_navigation_throttle.h" #endif +#if defined(OS_LINUX) +#include "components/crash/content/app/crash_switches.h" +#include "components/crash/content/app/crashpad.h" +#endif + #if defined(OS_POSIX) && !defined(OS_MACOSX) #if !defined(OS_ANDROID) #include "base/debug/leak_annotations.h" @@ -813,6 +817,12 @@ } int GetCrashSignalFD(const base::CommandLine& command_line) { + if (crash_reporter::IsCrashpadEnabled()) { + int fd; + pid_t pid; + return crash_reporter::GetHandlerSocket(&fd, &pid) ? fd : -1; + } + // Extensions have the same process type as renderers. if (command_line.HasSwitch(extensions::switches::kExtensionProcess)) { static breakpad::CrashHandlerHostLinux* crash_handler = nullptr; @@ -2029,7 +2039,21 @@ #if defined(OS_ANDROID) bool enable_crash_reporter = true; #else - bool enable_crash_reporter = breakpad::IsCrashReporterEnabled(); + bool enable_crash_reporter = false; + if (crash_reporter::IsCrashpadEnabled()) { + command_line->AppendSwitch(crash_reporter::kEnableCrashpad); + enable_crash_reporter = true; + + int fd; + pid_t pid; + if (crash_reporter::GetHandlerSocket(&fd, &pid)) { + command_line->AppendSwitchASCII( + crash_reporter::switches::kCrashpadHandlerPid, + base::NumberToString(pid)); + } + } else { + enable_crash_reporter = breakpad::IsCrashReporterEnabled(); + } #endif if (enable_crash_reporter) { std::string switch_value; @@ -2990,12 +3014,9 @@ frame_name, disposition, features, user_gesture, opener_suppressed); NavigateParams nav_params = blocked_params.CreateNavigateParams(web_contents); - if (MaybeBlockPopup(web_contents, opener_top_level_frame_url, &nav_params, - nullptr /*=open_url_params*/, - blocked_params.features())) { - return false; - } - return true; + return !MaybeBlockPopup(web_contents, &opener_top_level_frame_url, + &nav_params, nullptr /*=open_url_params*/, + blocked_params.features()); } content::SpeechRecognitionManagerDelegate* @@ -3446,8 +3467,8 @@ // Handler to rewrite Preview's Server Lite Page, to show the original URL to // the user. - handler->AddHandlerPair(&HandlePreviewsLitePageURLRewrite, - &HandlePreviewsLitePageURLRewriteReverse); + handler->AddHandlerPair(&previews::HandlePreviewsLitePageURLRewrite, + &previews::HandlePreviewsLitePageURLRewriteReverse); } base::FilePath ChromeContentBrowserClient::GetDefaultDownloadDirectory() { @@ -4881,7 +4902,7 @@ // |network_loader_factory| and have interceptors create one themselves. // https://crbug.com/931786 if (base::FeatureList::IsEnabled( - previews::features::kHTTPSServerPreviewsUsingURLLoader)) { + previews::features::kLitePageServerPreviews)) { interceptors.push_back( std::make_unique<previews::PreviewsLitePageURLLoaderInterceptor>( network_loader_factory,
diff --git a/chrome/browser/chromeos/extensions/autotest_private/autotest_private_api.cc b/chrome/browser/chromeos/extensions/autotest_private/autotest_private_api.cc index acc6d52..eadcf18 100644 --- a/chrome/browser/chromeos/extensions/autotest_private/autotest_private_api.cc +++ b/chrome/browser/chromeos/extensions/autotest_private/autotest_private_api.cc
@@ -1661,8 +1661,6 @@ if (!err_msg.empty()) return RespondNow(Error(err_msg)); - // |NOT_READY| means service not running; - // |STOPPED| means service running; auto new_state = params->enabled ? ash::mojom::AssistantState::READY : ash::mojom::AssistantState::NOT_READY; if (ash::AssistantState::Get()->assistant_state() == new_state)
diff --git a/chrome/browser/chromeos/login/wizard_controller.cc b/chrome/browser/chromeos/login/wizard_controller.cc index c0666042..d54f43a 100644 --- a/chrome/browser/chromeos/login/wizard_controller.cc +++ b/chrome/browser/chromeos/login/wizard_controller.cc
@@ -148,6 +148,7 @@ #include "components/arc/arc_util.h" #include "components/arc/session/arc_bridge_service.h" #include "components/crash/content/app/breakpad_linux.h" +#include "components/crash/content/app/crashpad.h" #include "components/prefs/pref_registry_simple.h" #include "components/prefs/pref_service.h" #include "components/session_manager/core/session_manager.h" @@ -1117,6 +1118,11 @@ void WizardController::OnChangedMetricsReportingState(bool enabled) { StatsReportingController::Get()->SetEnabled( ProfileManager::GetActiveUserProfile(), enabled); + if (crash_reporter::IsCrashpadEnabled()) { + crash_reporter::SetUploadConsent(enabled); + return; + } + if (!enabled) return; #if BUILDFLAG(GOOGLE_CHROME_BRANDING)
diff --git a/chrome/browser/content_settings/sound_content_setting_observer.cc b/chrome/browser/content_settings/sound_content_setting_observer.cc index 101c0f48..67de4ba4 100644 --- a/chrome/browser/content_settings/sound_content_setting_observer.cc +++ b/chrome/browser/content_settings/sound_content_setting_observer.cc
@@ -10,7 +10,6 @@ #include "chrome/browser/content_settings/tab_specific_content_settings.h" #include "chrome/browser/profiles/profile.h" #include "chrome/common/pref_names.h" -#include "components/content_settings/core/browser/host_content_settings_map.h" #include "components/content_settings/core/common/content_settings_utils.h" #include "components/pref_registry/pref_registry_syncable.h" #include "components/prefs/pref_service.h" @@ -29,9 +28,7 @@ SoundContentSettingObserver::SoundContentSettingObserver( content::WebContents* contents) - : content::WebContentsObserver(contents), - logged_site_muted_ukm_(false), - observer_(this) { + : content::WebContentsObserver(contents), logged_site_muted_ukm_(false) { Profile* profile = Profile::FromBrowserContext(web_contents()->GetBrowserContext()); host_content_settings_map_ =
diff --git a/chrome/browser/content_settings/sound_content_setting_observer.h b/chrome/browser/content_settings/sound_content_setting_observer.h index d9998d4..0844f68 100644 --- a/chrome/browser/content_settings/sound_content_setting_observer.h +++ b/chrome/browser/content_settings/sound_content_setting_observer.h
@@ -8,13 +8,12 @@ #include "base/scoped_observer.h" #include "build/build_config.h" #include "components/content_settings/core/browser/content_settings_observer.h" +#include "components/content_settings/core/browser/host_content_settings_map.h" #include "components/content_settings/core/common/content_settings.h" #include "components/prefs/pref_change_registrar.h" #include "content/public/browser/web_contents_observer.h" #include "content/public/browser/web_contents_user_data.h" -class HostContentSettingsMap; - class SoundContentSettingObserver : public content::WebContentsObserver, public content::WebContentsUserData<SoundContentSettingObserver>, @@ -72,7 +71,8 @@ HostContentSettingsMap* host_content_settings_map_; - ScopedObserver<HostContentSettingsMap, content_settings::Observer> observer_; + ScopedObserver<HostContentSettingsMap, content_settings::Observer> observer_{ + this}; WEB_CONTENTS_USER_DATA_KEY_DECL();
diff --git a/chrome/browser/content_settings/tab_specific_content_settings.cc b/chrome/browser/content_settings/tab_specific_content_settings.cc index f775ad2..1071597 100644 --- a/chrome/browser/content_settings/tab_specific_content_settings.cc +++ b/chrome/browser/content_settings/tab_specific_content_settings.cc
@@ -34,7 +34,6 @@ #include "components/content_settings/core/browser/content_settings_info.h" #include "components/content_settings/core/browser/content_settings_registry.h" #include "components/content_settings/core/browser/content_settings_utils.h" -#include "components/content_settings/core/browser/host_content_settings_map.h" #include "components/prefs/pref_service.h" #include "content/public/browser/browser_thread.h" #include "content/public/browser/navigation_controller.h" @@ -112,8 +111,7 @@ previous_protocol_handler_(ProtocolHandler::EmptyProtocolHandler()), pending_protocol_handler_setting_(CONTENT_SETTING_DEFAULT), load_plugins_link_enabled_(true), - microphone_camera_state_(MICROPHONE_CAMERA_NOT_ACCESSED), - observer_(this) { + microphone_camera_state_(MICROPHONE_CAMERA_NOT_ACCESSED) { ClearContentSettingsExceptForNavigationRelatedSettings(); ClearNavigationRelatedContentSettings();
diff --git a/chrome/browser/content_settings/tab_specific_content_settings.h b/chrome/browser/content_settings/tab_specific_content_settings.h index 95277f2..aa45d1e 100644 --- a/chrome/browser/content_settings/tab_specific_content_settings.h +++ b/chrome/browser/content_settings/tab_specific_content_settings.h
@@ -21,14 +21,13 @@ #include "chrome/common/custom_handlers/protocol_handler.h" #include "components/content_settings/core/browser/content_settings_observer.h" #include "components/content_settings/core/browser/content_settings_usages_state.h" +#include "components/content_settings/core/browser/host_content_settings_map.h" #include "components/content_settings/core/common/content_settings.h" #include "components/content_settings/core/common/content_settings_types.h" #include "content/public/browser/web_contents_observer.h" #include "content/public/browser/web_contents_user_data.h" #include "net/cookies/canonical_cookie.h" -class HostContentSettingsMap; - namespace content { class NavigationHandle; } @@ -453,7 +452,8 @@ std::string media_stream_requested_video_device_; // Observer to watch for content settings changed. - ScopedObserver<HostContentSettingsMap, content_settings::Observer> observer_; + ScopedObserver<HostContentSettingsMap, content_settings::Observer> observer_{ + this}; // Stores content settings changed by the user via page info since the last // navigation. Used to determine whether to display the settings in page info.
diff --git a/chrome/browser/crash_upload_list/crash_upload_list.cc b/chrome/browser/crash_upload_list/crash_upload_list.cc index a2073c0..6df26e5 100644 --- a/chrome/browser/crash_upload_list/crash_upload_list.cc +++ b/chrome/browser/crash_upload_list/crash_upload_list.cc
@@ -11,7 +11,9 @@ #else #include "base/files/file_path.h" #include "base/path_service.h" +#include "chrome/browser/crash_upload_list/crash_upload_list_crashpad.h" #include "chrome/common/chrome_paths.h" +#include "components/crash/content/app/crashpad.h" #include "components/upload_list/crash_upload_list.h" #include "components/upload_list/text_log_upload_list.h" #endif @@ -32,6 +34,9 @@ .AppendASCII(CrashUploadList::kReporterLogFilename); return new CrashUploadListAndroid(upload_log_path); #else + if (crash_reporter::IsCrashpadEnabled()) { + return new CrashUploadListCrashpad(); + } base::FilePath crash_dir_path; base::PathService::Get(chrome::DIR_CRASH_DUMPS, &crash_dir_path); base::FilePath upload_log_path =
diff --git a/chrome/browser/download/download_request_limiter.cc b/chrome/browser/download/download_request_limiter.cc index d0a0e209..d319114 100644 --- a/chrome/browser/download/download_request_limiter.cc +++ b/chrome/browser/download/download_request_limiter.cc
@@ -18,7 +18,6 @@ #include "chrome/browser/profiles/profile.h" #include "chrome/browser/tab_contents/tab_util.h" #include "components/content_settings/core/browser/content_settings_details.h" -#include "components/content_settings/core/browser/host_content_settings_map.h" #include "content/public/browser/browser_context.h" #include "content/public/browser/browser_task_traits.h" #include "content/public/browser/browser_thread.h" @@ -104,8 +103,7 @@ ui_status_(DownloadRequestLimiter::DOWNLOAD_UI_DEFAULT), origin_(url::Origin::Create(contents->GetVisibleURL())), download_count_(0), - download_seen_(false), - observer_(this) { + download_seen_(false) { observer_.Add(GetContentSettings(contents)); NavigationEntry* last_entry = contents->GetController().GetLastCommittedEntry();
diff --git a/chrome/browser/download/download_request_limiter.h b/chrome/browser/download/download_request_limiter.h index 90285fb..21e945f2 100644 --- a/chrome/browser/download/download_request_limiter.h +++ b/chrome/browser/download/download_request_limiter.h
@@ -19,13 +19,12 @@ #include "base/memory/weak_ptr.h" #include "base/scoped_observer.h" #include "components/content_settings/core/browser/content_settings_observer.h" +#include "components/content_settings/core/browser/host_content_settings_map.h" #include "components/content_settings/core/common/content_settings.h" #include "content/public/browser/web_contents.h" #include "content/public/browser/web_contents_observer.h" #include "url/origin.h" -class HostContentSettingsMap; - namespace content { class WebContents; } @@ -215,7 +214,7 @@ DownloadStatusMap download_status_map_; ScopedObserver<HostContentSettingsMap, content_settings::Observer> - observer_; + observer_{this}; // Weak pointer factory for generating a weak pointer to pass to the // infobar. User responses to the throttling prompt will be returned
diff --git a/chrome/browser/extensions/api/autofill_private/autofill_private_api.cc b/chrome/browser/extensions/api/autofill_private/autofill_private_api.cc index 60e9da0d..08f5ecc3 100644 --- a/chrome/browser/extensions/api/autofill_private/autofill_private_api.cc +++ b/chrome/browser/extensions/api/autofill_private/autofill_private_api.cc
@@ -71,6 +71,19 @@ list->Remove(index, nullptr); } +autofill::AutofillManager* GetAutofillManager( + content::WebContents* web_contents) { + if (!web_contents) { + return nullptr; + } + autofill::ContentAutofillDriver* autofill_driver = + autofill::ContentAutofillDriverFactory::FromWebContents(web_contents) + ->DriverForFrame(web_contents->GetMainFrame()); + if (!autofill_driver) + return nullptr; + return autofill_driver->autofill_manager(); +} + } // namespace namespace extensions { @@ -471,17 +484,13 @@ autofill::PersonalDataManager* personal_data = autofill::PersonalDataManagerFactory::GetForProfile( chrome_details_.GetProfile()); - // Get the web contents to get autofill manager. - content::WebContents* web_contents = GetSenderWebContents(); - if (!personal_data || !personal_data->IsDataLoaded() || !web_contents) + if (!personal_data || !personal_data->IsDataLoaded()) return RespondNow(Error(kErrorDataUnavailable)); // Get the AutofillManager from the web contents. AutofillManager has a // pointer to its AutofillClient which owns FormDataImporter. autofill::AutofillManager* autofill_manager = - autofill::ContentAutofillDriverFactory::FromWebContents(web_contents) - ->DriverForFrame(web_contents->GetMainFrame()) - ->autofill_manager(); + GetAutofillManager(GetSenderWebContents()); if (!autofill_manager || !autofill_manager->client()) return RespondNow(Error(kErrorDataUnavailable)); @@ -529,4 +538,36 @@ return RespondNow(NoArguments()); } +//////////////////////////////////////////////////////////////////////////////// +// AutofillPrivateSetCreditCardFIDOAuthEnabledStateFunction + +AutofillPrivateSetCreditCardFIDOAuthEnabledStateFunction:: + AutofillPrivateSetCreditCardFIDOAuthEnabledStateFunction() + : chrome_details_(this) {} + +AutofillPrivateSetCreditCardFIDOAuthEnabledStateFunction:: + ~AutofillPrivateSetCreditCardFIDOAuthEnabledStateFunction() {} + +ExtensionFunction::ResponseAction +AutofillPrivateSetCreditCardFIDOAuthEnabledStateFunction::Run() { + // Getting CreditCardAccessManager from WebContents. + autofill::AutofillManager* autofill_manager = + GetAutofillManager(GetSenderWebContents()); + if (!autofill_manager) + return RespondNow(Error(kErrorDataUnavailable)); + autofill::CreditCardAccessManager* credit_card_access_manager = + autofill_manager->credit_card_access_manager(); + if (!credit_card_access_manager) + return RespondNow(Error(kErrorDataUnavailable)); + + std::unique_ptr< + api::autofill_private::SetCreditCardFIDOAuthEnabledState::Params> + parameters = api::autofill_private::SetCreditCardFIDOAuthEnabledState:: + Params::Create(*args_); + EXTENSION_FUNCTION_VALIDATE(parameters.get()); + + credit_card_access_manager->OnSettingsPageFIDOAuthToggled( + parameters->enabled); + return RespondNow(NoArguments()); +} } // namespace extensions
diff --git a/chrome/browser/extensions/api/autofill_private/autofill_private_api.h b/chrome/browser/extensions/api/autofill_private/autofill_private_api.h index 5b42cd4..0594f14 100644 --- a/chrome/browser/extensions/api/autofill_private/autofill_private_api.h +++ b/chrome/browser/extensions/api/autofill_private/autofill_private_api.h
@@ -208,6 +208,27 @@ DISALLOW_COPY_AND_ASSIGN(AutofillPrivateLogServerCardLinkClickedFunction); }; +class AutofillPrivateSetCreditCardFIDOAuthEnabledStateFunction + : public ExtensionFunction { + public: + AutofillPrivateSetCreditCardFIDOAuthEnabledStateFunction(); + DECLARE_EXTENSION_FUNCTION( + "autofillPrivate.setCreditCardFIDOAuthEnabledState", + AUTOFILLPRIVATE_SETCREDITCARDFIDOAUTHENABLEDSTATE) + + protected: + ~AutofillPrivateSetCreditCardFIDOAuthEnabledStateFunction() override; + + // ExtensionFunction overrides. + ResponseAction Run() override; + + private: + ChromeExtensionFunctionDetails chrome_details_; + + DISALLOW_COPY_AND_ASSIGN( + AutofillPrivateSetCreditCardFIDOAuthEnabledStateFunction); +}; + } // namespace extensions #endif // CHROME_BROWSER_EXTENSIONS_API_AUTOFILL_PRIVATE_AUTOFILL_PRIVATE_API_H_
diff --git a/chrome/browser/extensions/api/settings_private/prefs_util.cc b/chrome/browser/extensions/api/settings_private/prefs_util.cc index 89f6c0f..a6d8c66 100644 --- a/chrome/browser/extensions/api/settings_private/prefs_util.cc +++ b/chrome/browser/extensions/api/settings_private/prefs_util.cc
@@ -151,6 +151,8 @@ settings_api::PrefType::PREF_TYPE_BOOLEAN; (*s_whitelist)[autofill::prefs::kAutofillCreditCardEnabled] = settings_api::PrefType::PREF_TYPE_BOOLEAN; + (*s_whitelist)[autofill::prefs::kAutofillCreditCardFIDOAuthEnabled] = + settings_api::PrefType::PREF_TYPE_BOOLEAN; (*s_whitelist)[payments::kCanMakePaymentEnabled] = settings_api::PrefType::PREF_TYPE_BOOLEAN; (*s_whitelist)[bookmarks::prefs::kShowBookmarkBar] =
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 f6a205e0..b4e07f4 100644 --- a/chrome/browser/extensions/api/web_request/web_request_apitest.cc +++ b/chrome/browser/extensions/api/web_request/web_request_apitest.cc
@@ -526,25 +526,31 @@ } }; -// TODO(https://crbug.com/1003598): Flake on multiple platforms. +// Note: this is flaky on multiple platforms (crbug.com/1003598). Temporarily +// enabled to find flakiness cause. IN_PROC_BROWSER_TEST_P(ExtensionWebRequestApiAuthRequiredTest, - DISABLED_WebRequestAuthRequired) { + WebRequestAuthRequired) { CancelLoginDialog login_dialog_helper; ASSERT_TRUE(StartEmbeddedTestServer()); + + // Pass "debug" as a custom arg to debug test flakiness. ASSERT_TRUE(RunExtensionSubtestWithArgAndFlags( - "webrequest", "test_auth_required.html", nullptr, GetFlags())) + "webrequest", "test_auth_required.html", "debug", GetFlags())) << message_; } -// TODO(https://crbug.com/1003598): Flake on multiple platforms. +// Note: this is flaky on multiple platforms (crbug.com/1003598). Temporarily +// enabled to find flakiness cause. IN_PROC_BROWSER_TEST_P(ExtensionWebRequestApiAuthRequiredTest, - DISABLED_WebRequestAuthRequiredAsync) { + WebRequestAuthRequiredAsync) { CancelLoginDialog login_dialog_helper; ASSERT_TRUE(StartEmbeddedTestServer()); + + // Pass "debug" as a custom arg to debug test flakiness. ASSERT_TRUE(RunExtensionSubtestWithArgAndFlags( - "webrequest", "test_auth_required_async.html", nullptr, GetFlags())) + "webrequest", "test_auth_required_async.html", "debug", GetFlags())) << message_; }
diff --git a/chrome/browser/file_select_helper.cc b/chrome/browser/file_select_helper.cc index e005ae13..8b0be6cfe5 100644 --- a/chrome/browser/file_select_helper.cc +++ b/chrome/browser/file_select_helper.cc
@@ -30,7 +30,6 @@ #include "content/public/browser/render_frame_host.h" #include "content/public/browser/render_process_host.h" #include "content/public/browser/render_view_host.h" -#include "content/public/browser/render_widget_host.h" #include "content/public/browser/render_widget_host_view.h" #include "content/public/browser/storage_partition.h" #include "content/public/browser/web_contents.h" @@ -150,8 +149,7 @@ select_file_dialog_(), select_file_types_(), dialog_type_(ui::SelectFileDialog::SELECT_OPEN_FILE), - dialog_mode_(FileChooserParams::Mode::kOpen), - observer_(this) {} + dialog_mode_(FileChooserParams::Mode::kOpen) {} FileSelectHelper::~FileSelectHelper() { // There may be pending file dialogs, we need to tell them that we've gone @@ -197,7 +195,7 @@ base::TaskShutdownBehavior::CONTINUE_ON_SHUTDOWN}, base::BindOnce(&FileSelectHelper::ProcessSelectedFilesMac, this, files)); #else - NotifyRenderFrameHostAndEnd(files); + ConvertToFileChooserFileInfoList(files); #endif // defined(OS_MACOSX) } @@ -226,7 +224,7 @@ base::TaskShutdownBehavior::CONTINUE_ON_SHUTDOWN}, base::BindOnce(&FileSelectHelper::ProcessSelectedFilesMac, this, files)); #else - NotifyRenderFrameHostAndEnd(files); + ConvertToFileChooserFileInfoList(files); #endif // defined(OS_MACOSX) } @@ -257,7 +255,7 @@ std::vector<ui::SelectedFileInfo> selected_files) { ShowFolderUploadConfirmationDialog( path, - base::BindOnce(&FileSelectHelper::NotifyRenderFrameHostAndEnd, this), + base::BindOnce(&FileSelectHelper::ConvertToFileChooserFileInfoList, this), std::move(selected_files), web_contents_); } @@ -297,12 +295,10 @@ } } -void FileSelectHelper::NotifyRenderFrameHostAndEnd( +void FileSelectHelper::ConvertToFileChooserFileInfoList( const std::vector<ui::SelectedFileInfo>& files) { - if (!render_frame_host_) { - RunFileChooserEnd(); + if (AbortIfWebContentsDestroyed()) return; - } #if defined(OS_CHROMEOS) if (!files.empty()) { @@ -319,9 +315,8 @@ ->GetFileSystemContext(); file_manager::util::ConvertSelectedFileInfoListToFileChooserFileInfoList( file_system_context, site_instance->GetSiteURL(), files, - base::BindOnce( - &FileSelectHelper::NotifyRenderFrameHostAndEndAfterConversion, - this)); + base::BindOnce(&FileSelectHelper::PerformSafeBrowsingDeepScanIfNeeded, + this)); return; } #endif // defined(OS_CHROMEOS) @@ -334,11 +329,62 @@ base::FilePath(file.display_name).AsUTF16Unsafe()))); } - NotifyRenderFrameHostAndEndAfterConversion(std::move(chooser_files)); + PerformSafeBrowsingDeepScanIfNeeded(std::move(chooser_files)); } -void FileSelectHelper::NotifyRenderFrameHostAndEndAfterConversion( +void FileSelectHelper::PerformSafeBrowsingDeepScanIfNeeded( std::vector<FileChooserFileInfoPtr> list) { + if (AbortIfWebContentsDestroyed()) + return; + +#if BUILDFLAG(FULL_SAFE_BROWSING) + safe_browsing::DeepScanningDialogDelegate::Data data; + if (safe_browsing::DeepScanningDialogDelegate::IsEnabled( + profile_, render_frame_host_->GetLastCommittedURL(), &data)) { + data.paths.reserve(list.size()); + for (const auto& file : list) + data.paths.push_back(file->get_native_file()->file_path); + + safe_browsing::DeepScanningDialogDelegate::ShowForWebContents( + web_contents_, std::move(data), + base::BindOnce(&FileSelectHelper::DeepScanCompletionCallback, this, + std::move(list))); + } else { + NotifyListenerAndEnd(std::move(list)); + } +#else + NotifyListenerAndEnd(std::move(list)); +#endif // BUILDFLAG(FULL_SAFE_BROWSING) +} + +#if BUILDFLAG(FULL_SAFE_BROWSING) +void FileSelectHelper::DeepScanCompletionCallback( + std::vector<blink::mojom::FileChooserFileInfoPtr> list, + const safe_browsing::DeepScanningDialogDelegate::Data& data, + const safe_browsing::DeepScanningDialogDelegate::Result& result) { + if (AbortIfWebContentsDestroyed()) + return; + + DCHECK_EQ(data.text.size(), result.text_results.size()); + DCHECK_EQ(data.paths.size(), result.paths_results.size()); + DCHECK_EQ(list.size(), result.paths_results.size()); + + // Remove any files that did not pass the deep scan. + size_t i = 0; + for (auto it = list.begin(); it != list.end(); ++i) { + if (!result.paths_results[i]) { + it = list.erase(it); + } else { + ++it; + } + } + + NotifyListenerAndEnd(std::move(list)); +} +#endif // BUILDFLAG(FULL_SAFE_BROWSING) + +void FileSelectHelper::NotifyListenerAndEnd( + std::vector<blink::mojom::FileChooserFileInfoPtr> list) { listener_->FileSelected(std::move(list), base_dir_, dialog_mode_); listener_.reset(); @@ -365,11 +411,24 @@ } bool FileSelectHelper::AbortIfWebContentsDestroyed() { - if (render_frame_host_ && web_contents_) - return false; + if (abort_on_missing_web_contents_in_tests_ && + (render_frame_host_ == nullptr || web_contents_ == nullptr)) { + RunFileChooserEnd(); + return true; + } - RunFileChooserEnd(); - return true; + return false; +} + +void FileSelectHelper::SetFileSelectListenerForTesting( + std::unique_ptr<content::FileSelectListener> listener) { + DCHECK(listener); + DCHECK(!listener_); + listener_ = std::move(listener); +} + +void FileSelectHelper::DontAbortOnMissingWebContentsForTesting() { + abort_on_missing_web_contents_in_tests_ = false; } std::unique_ptr<ui::SelectFileDialog::FileTypeInfo>
diff --git a/chrome/browser/file_select_helper.h b/chrome/browser/file_select_helper.h index e02b4da..dbd6f9c 100644 --- a/chrome/browser/file_select_helper.h +++ b/chrome/browser/file_select_helper.h
@@ -16,12 +16,17 @@ #include "build/build_config.h" #include "components/safe_browsing/buildflags.h" #include "content/public/browser/browser_thread.h" +#include "content/public/browser/render_widget_host.h" #include "content/public/browser/render_widget_host_observer.h" #include "content/public/browser/web_contents_observer.h" #include "net/base/directory_lister.h" #include "third_party/blink/public/mojom/choosers/file_chooser.mojom.h" #include "ui/shell_dialogs/select_file_dialog.h" +#if BUILDFLAG(FULL_SAFE_BROWSING) +#include "chrome/browser/safe_browsing/cloud_content_scanning/deep_scanning_dialog_delegate.h" +#endif + class Profile; namespace content { @@ -71,6 +76,17 @@ FRIEND_TEST_ALL_PREFIXES(FileSelectHelperTest, ZipPackage); FRIEND_TEST_ALL_PREFIXES(FileSelectHelperTest, GetSanitizedFileName); FRIEND_TEST_ALL_PREFIXES(FileSelectHelperTest, LastSelectedDirectory); + FRIEND_TEST_ALL_PREFIXES(FileSelectHelperTest, + DeepScanCompletionCallback_NoFiles); + FRIEND_TEST_ALL_PREFIXES(FileSelectHelperTest, + DeepScanCompletionCallback_OneOKFile); + FRIEND_TEST_ALL_PREFIXES(FileSelectHelperTest, + DeepScanCompletionCallback_TwoOKFiles); + FRIEND_TEST_ALL_PREFIXES(FileSelectHelperTest, + DeepScanCompletionCallback_TwoBadFiles); + FRIEND_TEST_ALL_PREFIXES(FileSelectHelperTest, + DeepScanCompletionCallback_OKBadFiles); + explicit FileSelectHelper(Profile* profile); ~FileSelectHelper() override; @@ -158,15 +174,55 @@ static base::FilePath ZipPackage(const base::FilePath& path); #endif // defined(OS_MACOSX) - // Utility method that passes |files| to the FileSelectListener, and ends the - // file chooser. - // TODO(tkent): Remove 'RenderFrameHost' from the name. - void NotifyRenderFrameHostAndEnd( + // This function is the start of a call chain that may or may not be async + // depending on the platform and features enabled. The call to this method + // is made after the user has chosen the file(s) in the UI in order to + // process and filter the list before returning the final result to the + // caller. The call chain is as follows: + // + // ConvertToFileChooserFileInfoList: converts a vector of SelectedFileInfo + // into a vector of FileChooserFileInfoPtr and then calls + // PerformSafeBrowsingDeepScanIfNeeded(). On chromeos, the conversion is + // performed asynchronously. + // + // PerformSafeBrowsingDeepScanIfNeeded: if the deep scanning feature is + // enabled and it is determined by enterprise policy that scans are required, + // starts the scans and sets DeepScanCompletionCallback() as the async + // callback. If deep scanning is not enabled or is not supported on the + // platform, this function calls NotifyListenerAndEnd() directly. + // + // DeepScanCompletionCallback: processes the results of the deep scan. Any + // files that did not pass the scan are removed from the list. Ends by + // calling NotifyListenerAndEnd(). + // + // NotifyListenerAndEnd: Informs the listener of the final list of files to + // use and performs any required cleanup. + // + // Because the state of the web contents may change at each asynchronous + // step, calls are make to AbortIfWebContentsDestroyed() to check if, for + // example, the tab has been closed or the contents navigated. In these + // cases the file selection is aborted and the state cleaned up. + void ConvertToFileChooserFileInfoList( const std::vector<ui::SelectedFileInfo>& files); - // Sends the result to the FileSelectListener, and call |RunFileChooserEnd|. - // TODO(tkent): Remove 'RenderFrameHost' from the name. - void NotifyRenderFrameHostAndEndAfterConversion( + // Checks to see if scans are required for the specified files. + void PerformSafeBrowsingDeepScanIfNeeded( + std::vector<blink::mojom::FileChooserFileInfoPtr> list); + +#if BUILDFLAG(FULL_SAFE_BROWSING) + // Callback used to receive the results of a deep scan. + void DeepScanCompletionCallback( + std::vector<blink::mojom::FileChooserFileInfoPtr> list, + const safe_browsing::DeepScanningDialogDelegate::Data& data, + const safe_browsing::DeepScanningDialogDelegate::Result& result); +#endif + + // Finish the PerformSafeBrowsingDeepScanIfNeeded() handling after the + // deep scanning checks have been performed. Deep scanning may change the + // list of files chosen by the user, so the list of files passed here may be + // a subset of of the files passed to + // PerformSafeBrowsingDeepScanIfNeeded(). + void NotifyListenerAndEnd( std::vector<blink::mojom::FileChooserFileInfoPtr> list); // Schedules the deletion of the files in |temporary_files_| and clears the @@ -180,6 +236,11 @@ // if the file chooser operation shouldn't proceed. bool AbortIfWebContentsDestroyed(); + void SetFileSelectListenerForTesting( + std::unique_ptr<content::FileSelectListener> listener); + + void DontAbortOnMissingWebContentsForTesting(); + // Helper method to get allowed extensions for select file dialog from // the specified accept types as defined in the spec: // http://whatwg.org/html/number-state.html#attr-input-accept @@ -241,12 +302,15 @@ std::unique_ptr<ActiveDirectoryEnumeration> directory_enumeration_; ScopedObserver<content::RenderWidgetHost, content::RenderWidgetHostObserver> - observer_; + observer_{this}; // Temporary files only used on OSX. This class is responsible for deleting // these files when they are no longer needed. std::vector<base::FilePath> temporary_files_; + // Set to false in unit tests since there is no WebContents. + bool abort_on_missing_web_contents_in_tests_ = true; + DISALLOW_COPY_AND_ASSIGN(FileSelectHelper); };
diff --git a/chrome/browser/file_select_helper_contacts_android.cc b/chrome/browser/file_select_helper_contacts_android.cc index 63c0844..a42f7da0 100644 --- a/chrome/browser/file_select_helper_contacts_android.cc +++ b/chrome/browser/file_select_helper_contacts_android.cc
@@ -54,7 +54,7 @@ std::vector<ui::SelectedFileInfo> files; if (temp_file.empty()) { - NotifyRenderFrameHostAndEnd(files); + ConvertToFileChooserFileInfoList(files); return; } @@ -72,5 +72,5 @@ return; } - NotifyRenderFrameHostAndEnd(files); + ConvertToFileChooserFileInfoList(files); }
diff --git a/chrome/browser/file_select_helper_mac.mm b/chrome/browser/file_select_helper_mac.mm index 18f463a..b4e18f5 100644 --- a/chrome/browser/file_select_helper_mac.mm +++ b/chrome/browser/file_select_helper_mac.mm
@@ -142,5 +142,5 @@ } } - NotifyRenderFrameHostAndEnd(files); + ConvertToFileChooserFileInfoList(files); }
diff --git a/chrome/browser/file_select_helper_unittest.cc b/chrome/browser/file_select_helper_unittest.cc index 921f0144..8ea1aafd 100644 --- a/chrome/browser/file_select_helper_unittest.cc +++ b/chrome/browser/file_select_helper_unittest.cc
@@ -17,11 +17,61 @@ #include "chrome/browser/file_select_helper.h" #include "chrome/common/chrome_paths.h" #include "chrome/test/base/testing_profile.h" +#include "content/public/browser/file_select_listener.h" #include "content/public/test/browser_task_environment.h" #include "testing/gtest/include/gtest/gtest.h" +#include "ui/shell_dialogs/selected_file_info.h" using blink::mojom::FileChooserParams; +#if BUILDFLAG(FULL_SAFE_BROWSING) +namespace { + +// A listener that remembers the list of files chosen. The |files| argument +// to the ctor must outlive the listener. +class TestFileSelectListener : public content::FileSelectListener { + public: + explicit TestFileSelectListener( + std::vector<blink::mojom::FileChooserFileInfoPtr>* files) + : files_(files) {} + + private: + // content::FileSelectListener overrides. + void FileSelected(std::vector<blink::mojom::FileChooserFileInfoPtr> files, + const base::FilePath& base_dir, + blink::mojom::FileChooserParams::Mode mode) override { + *files_ = std::move(files); + } + void FileSelectionCanceled() override {} + + std::vector<blink::mojom::FileChooserFileInfoPtr>* files_; +}; + +// Fill in the arguments to be passed to the DeepScanCompletionCallback() +// method based on a list of paths and the desired result for each path. +// This function simulates a path either passing the deep scan (status of true) +// or failing (status of false). +void PrepareDeepScanCompletionCallbackArgs( + std::vector<base::FilePath> paths, + std::vector<bool> status, + std::vector<blink::mojom::FileChooserFileInfoPtr>* orig_files, + safe_browsing::DeepScanningDialogDelegate::Data* data, + safe_browsing::DeepScanningDialogDelegate::Result* result) { + DCHECK_EQ(status.size(), paths.size()); + + for (auto& path : paths) { + orig_files->push_back(blink::mojom::FileChooserFileInfo::NewNativeFile( + blink::mojom::NativeFileInfo::New(path, + path.BaseName().AsUTF16Unsafe()))); + } + + data->paths = std::move(paths); + result->paths_results = std::move(status); +} + +} // namespace +#endif // BUILDFLAG(FULL_SAFE_BROWSING) + class FileSelectHelperTest : public testing::Test { public: FileSelectHelperTest() {} @@ -182,3 +232,130 @@ file_select_helper->MultiFilesSelected(dirs, params); EXPECT_EQ(dir_path_1, profile.last_selected_directory()); } + +// The following tests depend on the full safe browsing feature set. +#if BUILDFLAG(FULL_SAFE_BROWSING) + +TEST_F(FileSelectHelperTest, DeepScanCompletionCallback_NoFiles) { + content::BrowserTaskEnvironment task_environment; + TestingProfile profile; + scoped_refptr<FileSelectHelper> file_select_helper = + new FileSelectHelper(&profile); + + std::vector<blink::mojom::FileChooserFileInfoPtr> files; + auto listener = std::make_unique<TestFileSelectListener>(&files); + file_select_helper->SetFileSelectListenerForTesting(std::move(listener)); + file_select_helper->DontAbortOnMissingWebContentsForTesting(); + + std::vector<blink::mojom::FileChooserFileInfoPtr> orig_files; + safe_browsing::DeepScanningDialogDelegate::Data data; + safe_browsing::DeepScanningDialogDelegate::Result result; + file_select_helper->AddRef(); // Normally called by RunFileChooser(). + file_select_helper->DeepScanCompletionCallback(std::move(orig_files), data, + result); + + EXPECT_EQ(0u, files.size()); +} + +TEST_F(FileSelectHelperTest, DeepScanCompletionCallback_OneOKFile) { + content::BrowserTaskEnvironment task_environment; + TestingProfile profile; + scoped_refptr<FileSelectHelper> file_select_helper = + new FileSelectHelper(&profile); + + std::vector<blink::mojom::FileChooserFileInfoPtr> files; + auto listener = std::make_unique<TestFileSelectListener>(&files); + file_select_helper->SetFileSelectListenerForTesting(std::move(listener)); + file_select_helper->DontAbortOnMissingWebContentsForTesting(); + + std::vector<blink::mojom::FileChooserFileInfoPtr> orig_files; + safe_browsing::DeepScanningDialogDelegate::Data data; + safe_browsing::DeepScanningDialogDelegate::Result result; + PrepareDeepScanCompletionCallbackArgs({data_dir_.AppendASCII("foo")}, {true}, + &orig_files, &data, &result); + + file_select_helper->AddRef(); // Normally called by RunFileChooser(). + file_select_helper->DeepScanCompletionCallback(std::move(orig_files), data, + result); + + EXPECT_EQ(1u, files.size()); +} + +TEST_F(FileSelectHelperTest, DeepScanCompletionCallback_TwoOKFiles) { + content::BrowserTaskEnvironment task_environment; + TestingProfile profile; + scoped_refptr<FileSelectHelper> file_select_helper = + new FileSelectHelper(&profile); + + std::vector<blink::mojom::FileChooserFileInfoPtr> files; + auto listener = std::make_unique<TestFileSelectListener>(&files); + file_select_helper->SetFileSelectListenerForTesting(std::move(listener)); + file_select_helper->DontAbortOnMissingWebContentsForTesting(); + + std::vector<blink::mojom::FileChooserFileInfoPtr> orig_files; + safe_browsing::DeepScanningDialogDelegate::Data data; + safe_browsing::DeepScanningDialogDelegate::Result result; + PrepareDeepScanCompletionCallbackArgs( + {data_dir_.AppendASCII("foo"), data_dir_.AppendASCII("bar")}, + {true, true}, &orig_files, &data, &result); + + file_select_helper->AddRef(); // Normally called by RunFileChooser(). + file_select_helper->DeepScanCompletionCallback(std::move(orig_files), data, + result); + + EXPECT_EQ(2u, files.size()); +} + +TEST_F(FileSelectHelperTest, DeepScanCompletionCallback_TwoBadFiles) { + content::BrowserTaskEnvironment task_environment; + TestingProfile profile; + scoped_refptr<FileSelectHelper> file_select_helper = + new FileSelectHelper(&profile); + + std::vector<blink::mojom::FileChooserFileInfoPtr> files; + auto listener = std::make_unique<TestFileSelectListener>(&files); + file_select_helper->SetFileSelectListenerForTesting(std::move(listener)); + file_select_helper->DontAbortOnMissingWebContentsForTesting(); + + std::vector<blink::mojom::FileChooserFileInfoPtr> orig_files; + safe_browsing::DeepScanningDialogDelegate::Data data; + safe_browsing::DeepScanningDialogDelegate::Result result; + PrepareDeepScanCompletionCallbackArgs( + {data_dir_.AppendASCII("foo"), data_dir_.AppendASCII("bar")}, + {false, false}, &orig_files, &data, &result); + + file_select_helper->AddRef(); // Normally called by RunFileChooser(). + file_select_helper->DeepScanCompletionCallback(std::move(orig_files), data, + result); + + EXPECT_EQ(0u, files.size()); +} + +TEST_F(FileSelectHelperTest, DeepScanCompletionCallback_OKBadFiles) { + content::BrowserTaskEnvironment task_environment; + TestingProfile profile; + scoped_refptr<FileSelectHelper> file_select_helper = + new FileSelectHelper(&profile); + + std::vector<blink::mojom::FileChooserFileInfoPtr> files; + auto listener = std::make_unique<TestFileSelectListener>(&files); + file_select_helper->SetFileSelectListenerForTesting(std::move(listener)); + file_select_helper->DontAbortOnMissingWebContentsForTesting(); + + std::vector<blink::mojom::FileChooserFileInfoPtr> orig_files; + safe_browsing::DeepScanningDialogDelegate::Data data; + safe_browsing::DeepScanningDialogDelegate::Result result; + PrepareDeepScanCompletionCallbackArgs( + {data_dir_.AppendASCII("foo"), data_dir_.AppendASCII("bar")}, + {false, true}, &orig_files, &data, &result); + + file_select_helper->AddRef(); // Normally called by RunFileChooser(). + file_select_helper->DeepScanCompletionCallback(std::move(orig_files), data, + result); + + ASSERT_EQ(1u, files.size()); + EXPECT_EQ(data_dir_.AppendASCII("bar"), + files[0]->get_native_file()->file_path); +} + +#endif // BUILDFLAG(FULL_SAFE_BROWSING)
diff --git a/chrome/browser/flag-metadata.json b/chrome/browser/flag-metadata.json index 35f8a2ff..be915391 100644 --- a/chrome/browser/flag-metadata.json +++ b/chrome/browser/flag-metadata.json
@@ -807,6 +807,11 @@ "expiry_milestone": 89 }, { + "name": "enable-accessibility-expose-display-none", + "owners": [ "adettenb@microsoft.com", "//third_party/blink/renderer/modules/accessibility/OWNERS", "//ui/accessibility/OWNERS" ], + "expiry_milestone": 82 + }, + { "name": "enable-accessibility-image-descriptions", "owners": [ "//ui/accessibility/OWNERS" ], "expiry_milestone": 77 @@ -1822,11 +1827,6 @@ "expiry_milestone": 82 }, { - "name": "enable-url-loader-lite-page-server-previews", - "owners": [ "//components/data_reduction_proxy/OWNERS" ], - "expiry_milestone": 79 - }, - { "name": "enable-usbguard", "owners": [ "allenwebb", "mnissler", "jorgelo" ], "expiry_milestone": 80 @@ -2734,6 +2734,11 @@ "expiry_milestone": 85 }, { + "name": "omnibox-zero-suggestions-on-serp", + "owners": [ "tommycli", "pnoland" ], + "expiry_milestone": 85 + }, + { "name": "on-the-fly-mhtml-hash-computation", "owners": [ "mtlieuu", "offline-dev@chromium.org" ], "expiry_milestone": 76
diff --git a/chrome/browser/flag_descriptions.cc b/chrome/browser/flag_descriptions.cc index 929544e4..ed244f6 100644 --- a/chrome/browser/flag_descriptions.cc +++ b/chrome/browser/flag_descriptions.cc
@@ -22,6 +22,12 @@ const char kAcceleratedVideoEncodeDescription[] = "Hardware-accelerated video encode where available."; +const char kAccessibilityExposeDisplayNoneName[] = + "Expose 'display: none' nodes for accessibility"; +const char kAccessibilityExposeDisplayNoneDescription[] = + "Expose 'display: none' nodes that have an HTML ID to the browser process " + "accessibility tree."; + const char kAccessibilityInternalsPageImprovementsName[] = "Accessibility internals page improvements"; const char kAccessibilityInternalsPageImprovementsDescription[] = @@ -697,13 +703,6 @@ "to a Google-owned domain that serves a pre-rendered version of the " "original page. Also known as Lite Page Redirect Previews."; -const char kEnableURLLoaderLitePageServerPreviewsName[] = - "Lite Page Server Previews using URL Loader"; -const char kEnableURLLoaderLitePageServerPreviewsDescription[] = - "Enable using a network service URL Loader for Lite Page Server Previews. " - "This requires enable-lite-page-server-previews to be enabled along with " - "network-service."; - const char kEnablePreviewsCoinFlipName[] = "Enable Previews Coin Flip"; const char kEnablePreviewsCoinFlipDescription[] = "Enable coin flip experimentation of Previews."; @@ -1476,6 +1475,12 @@ const char kOmniboxZeroSuggestionsOnNTPRealboxDescription[] = "Offer suggestions when the real search box on New Tab Page is focused."; +const char kOmniboxZeroSuggestionsOnSERPName[] = + "Omnibox Zero Suggestions on SERP / On-Focus Query Refinement"; +const char kOmniboxZeroSuggestionsOnSERPDescription[] = + "Offer query refinement suggestions when the URL bar (omnibox) is focused " + "on the default search provider's search results page (SERP)."; + const char kOnlyNewPasswordFormParsingName[] = "Use only new password form parsing"; const char kOnlyNewPasswordFormParsingDescription[] =
diff --git a/chrome/browser/flag_descriptions.h b/chrome/browser/flag_descriptions.h index dc94503..6992e056 100644 --- a/chrome/browser/flag_descriptions.h +++ b/chrome/browser/flag_descriptions.h
@@ -53,6 +53,9 @@ extern const char kAcceleratedVideoEncodeName[]; extern const char kAcceleratedVideoEncodeDescription[]; +extern const char kAccessibilityExposeDisplayNoneName[]; +extern const char kAccessibilityExposeDisplayNoneDescription[]; + extern const char kAccessibilityInternalsPageImprovementsName[]; extern const char kAccessibilityInternalsPageImprovementsDescription[]; @@ -422,9 +425,6 @@ extern const char kEnableLitePageServerPreviewsName[]; extern const char kEnableLitePageServerPreviewsDescription[]; -extern const char kEnableURLLoaderLitePageServerPreviewsName[]; -extern const char kEnableURLLoaderLitePageServerPreviewsDescription[]; - extern const char kBuiltInModuleAllName[]; extern const char kBuiltInModuleAllDescription[]; @@ -891,6 +891,9 @@ extern const char kOmniboxZeroSuggestionsOnNTPRealboxName[]; extern const char kOmniboxZeroSuggestionsOnNTPRealboxDescription[]; +extern const char kOmniboxZeroSuggestionsOnSERPName[]; +extern const char kOmniboxZeroSuggestionsOnSERPDescription[]; + extern const char kOnTheFlyMhtmlHashComputationName[]; extern const char kOnTheFlyMhtmlHashComputationDescription[];
diff --git a/chrome/browser/google/google_update_settings_posix.cc b/chrome/browser/google/google_update_settings_posix.cc index 7671541..76cd73c 100644 --- a/chrome/browser/google/google_update_settings_posix.cc +++ b/chrome/browser/google/google_update_settings_posix.cc
@@ -13,10 +13,7 @@ #include "base/task/lazy_task_runner.h" #include "build/build_config.h" #include "chrome/common/chrome_paths.h" - -#if defined(OS_MACOSX) #include "components/crash/content/app/crashpad.h" -#endif namespace { @@ -81,6 +78,10 @@ bool GoogleUpdateSettings::SetCollectStatsConsent(bool consented) { #if defined(OS_MACOSX) crash_reporter::SetUploadConsent(consented); +#elif defined(OS_LINUX) + if (crash_reporter::IsCrashpadEnabled()) { + crash_reporter::SetUploadConsent(consented); + } #endif base::FilePath consent_dir;
diff --git a/chrome/browser/media/webrtc/display_media_access_handler_unittest.cc b/chrome/browser/media/webrtc/display_media_access_handler_unittest.cc index 5f0f9800..0fa5aa3 100644 --- a/chrome/browser/media/webrtc/display_media_access_handler_unittest.cc +++ b/chrome/browser/media/webrtc/display_media_access_handler_unittest.cc
@@ -11,6 +11,7 @@ #include "base/bind.h" #include "base/macros.h" #include "base/run_loop.h" +#include "build/build_config.h" #include "chrome/browser/media/webrtc/fake_desktop_media_picker_factory.h" #include "chrome/test/base/chrome_render_view_host_test_harness.h" #include "content/public/browser/browser_context.h" @@ -22,6 +23,10 @@ #include "third_party/blink/public/common/mediastream/media_stream_request.h" #include "third_party/blink/public/mojom/mediastream/media_stream.mojom-shared.h" +#if defined(OS_MACOSX) +#include "base/mac/mac_util.h" +#endif + class DisplayMediaAccessHandlerTest : public ChromeRenderViewHostTestHarness { public: DisplayMediaAccessHandlerTest() {} @@ -96,6 +101,16 @@ ProcessRequest(content::DesktopMediaID(content::DesktopMediaID::TYPE_SCREEN, content::DesktopMediaID::kFakeId), &result, &devices, false /* request_audio */); +#if defined(OS_MACOSX) + // Starting from macOS 10.15, screen capture requires system permissions + // that are disabled by default. + if (base::mac::IsAtLeastOS10_15()) { + EXPECT_EQ(blink::mojom::MediaStreamRequestResult::PERMISSION_DENIED, + result); + return; + } +#endif + EXPECT_EQ(blink::mojom::MediaStreamRequestResult::OK, result); EXPECT_EQ(1u, devices.size()); EXPECT_EQ(blink::mojom::MediaStreamType::DISPLAY_VIDEO_CAPTURE, @@ -110,6 +125,15 @@ content::DesktopMediaID::kFakeId, true /* audio_share */); ProcessRequest(fake_media_id, &result, &devices, true /* request_audio */); +#if defined(OS_MACOSX) + // Starting from macOS 10.15, screen capture requires system permissions + // that are disabled by default. + if (base::mac::IsAtLeastOS10_15()) { + EXPECT_EQ(blink::mojom::MediaStreamRequestResult::PERMISSION_DENIED, + result); + return; + } +#endif EXPECT_EQ(blink::mojom::MediaStreamRequestResult::OK, result); EXPECT_EQ(2u, devices.size()); EXPECT_EQ(blink::mojom::MediaStreamType::DISPLAY_VIDEO_CAPTURE, @@ -232,6 +256,16 @@ wait_loop[0].Run(); EXPECT_TRUE(test_flags[0].picker_created); EXPECT_TRUE(test_flags[0].picker_deleted); +#if defined(OS_MACOSX) + // Starting from macOS 10.15, screen capture requires system permissions + // that are disabled by default. + if (base::mac::IsAtLeastOS10_15()) { + EXPECT_EQ(blink::mojom::MediaStreamRequestResult::PERMISSION_DENIED, + result); + access_handler_.reset(); + return; + } +#endif EXPECT_EQ(blink::mojom::MediaStreamRequestResult::OK, result); EXPECT_EQ(1u, devices.size()); EXPECT_EQ(blink::mojom::MediaStreamType::DISPLAY_VIDEO_CAPTURE,
diff --git a/chrome/browser/media/webrtc/webrtc_getdisplaymedia_browsertest.cc b/chrome/browser/media/webrtc/webrtc_getdisplaymedia_browsertest.cc index 2f94ddd57..85d08ce 100644 --- a/chrome/browser/media/webrtc/webrtc_getdisplaymedia_browsertest.cc +++ b/chrome/browser/media/webrtc/webrtc_getdisplaymedia_browsertest.cc
@@ -13,6 +13,10 @@ #include "content/public/test/browser_test_utils.h" #include "media/base/media_switches.h" +#if defined(OS_MACOSX) +#include "base/mac/mac_util.h" +#endif + namespace { static const char kMainHtmlPage[] = "/webrtc/webrtc_getdisplaymedia_test.html"; @@ -39,7 +43,14 @@ tab->GetMainFrame(), base::StringPrintf("runGetDisplayMedia(%s);", constraints.c_str()), &result)); +#if defined(OS_MACOSX) + // Starting from macOS 10.15, screen capture requires system permissions + // that are disabled by default. + EXPECT_EQ(result, base::mac::IsAtMostOS10_14() ? "getdisplaymedia-success" + : "getdisplaymedia-failure"); +#else EXPECT_EQ(result, "getdisplaymedia-success"); +#endif } };
diff --git a/chrome/browser/metrics/browser_window_histogram_helper.cc b/chrome/browser/metrics/browser_window_histogram_helper.cc index 86e17c3..b37677f 100644 --- a/chrome/browser/metrics/browser_window_histogram_helper.cc +++ b/chrome/browser/metrics/browser_window_histogram_helper.cc
@@ -5,7 +5,6 @@ #include "chrome/browser/metrics/browser_window_histogram_helper.h" #include "components/startup_metric_utils/browser/startup_metric_utils.h" -#include "ui/compositor/compositor.h" BrowserWindowHistogramHelper::~BrowserWindowHistogramHelper() {} @@ -24,8 +23,7 @@ } BrowserWindowHistogramHelper::BrowserWindowHistogramHelper( - ui::Compositor* compositor) - : scoped_observer_(this) { + ui::Compositor* compositor) { startup_metric_utils::RecordBrowserWindowFirstPaint(base::TimeTicks::Now()); #if defined(OS_MACOSX)
diff --git a/chrome/browser/metrics/browser_window_histogram_helper.h b/chrome/browser/metrics/browser_window_histogram_helper.h index c0bd5aac..648f3823 100644 --- a/chrome/browser/metrics/browser_window_histogram_helper.h +++ b/chrome/browser/metrics/browser_window_histogram_helper.h
@@ -10,6 +10,7 @@ #include "base/macros.h" #include "base/scoped_observer.h" #include "base/time/time.h" +#include "ui/compositor/compositor.h" #include "ui/compositor/compositor_observer.h" // Class that encapsulates logic of recording @@ -37,7 +38,7 @@ void OnCompositingEnded(ui::Compositor* compositor) override; void OnCompositingShuttingDown(ui::Compositor* compositor) override; - ScopedObserver<ui::Compositor, ui::CompositorObserver> scoped_observer_; + ScopedObserver<ui::Compositor, ui::CompositorObserver> scoped_observer_{this}; DISALLOW_COPY_AND_ASSIGN(BrowserWindowHistogramHelper); };
diff --git a/chrome/browser/metrics/chrome_browser_main_extra_parts_metrics.cc b/chrome/browser/metrics/chrome_browser_main_extra_parts_metrics.cc index 2854f1f3..b9a94ee1 100644 --- a/chrome/browser/metrics/chrome_browser_main_extra_parts_metrics.cc +++ b/chrome/browser/metrics/chrome_browser_main_extra_parts_metrics.cc
@@ -553,7 +553,15 @@ "Disabled" #endif ); + // Log once here at browser start rather than at each renderer launch. + ChromeMetricsServiceAccessor::RegisterSyntheticFieldTrial("ChromeWinMultiDll", +#if defined(CHROME_MULTIPLE_DLL_BROWSER) + "Enabled" +#else + "Disabled" #endif + ); +#endif // defined(OS_WIN) } void ChromeBrowserMainExtraPartsMetrics::PostBrowserStart() {
diff --git a/chrome/browser/metrics/subprocess_metrics_provider.cc b/chrome/browser/metrics/subprocess_metrics_provider.cc index e966058..c41867f4 100644 --- a/chrome/browser/metrics/subprocess_metrics_provider.cc +++ b/chrome/browser/metrics/subprocess_metrics_provider.cc
@@ -20,7 +20,6 @@ #include "content/public/browser/child_process_data.h" #include "content/public/browser/notification_service.h" #include "content/public/browser/notification_types.h" -#include "content/public/browser/render_process_host.h" namespace { @@ -30,8 +29,7 @@ } // namespace -SubprocessMetricsProvider::SubprocessMetricsProvider() - : scoped_observer_(this) { +SubprocessMetricsProvider::SubprocessMetricsProvider() { base::StatisticsRecorder::RegisterHistogramProvider( weak_ptr_factory_.GetWeakPtr()); content::BrowserChildProcessObserver::Add(this);
diff --git a/chrome/browser/metrics/subprocess_metrics_provider.h b/chrome/browser/metrics/subprocess_metrics_provider.h index b995346..4401c69 100644 --- a/chrome/browser/metrics/subprocess_metrics_provider.h +++ b/chrome/browser/metrics/subprocess_metrics_provider.h
@@ -8,8 +8,8 @@ #include <memory> #include <set> -#include "base/gtest_prod_util.h" #include "base/containers/id_map.h" +#include "base/gtest_prod_util.h" #include "base/memory/weak_ptr.h" #include "base/metrics/statistics_recorder.h" #include "base/scoped_observer.h" @@ -18,6 +18,7 @@ #include "content/public/browser/browser_child_process_observer.h" #include "content/public/browser/notification_observer.h" #include "content/public/browser/notification_registrar.h" +#include "content/public/browser/render_process_host.h" #include "content/public/browser/render_process_host_observer.h" namespace base { @@ -105,8 +106,8 @@ AllocatorByIdMap allocators_by_id_; // Track all observed render processes to un-observe them on exit. - ScopedObserver<content::RenderProcessHost, SubprocessMetricsProvider> - scoped_observer_; + ScopedObserver<content::RenderProcessHost, content::RenderProcessHostObserver> + scoped_observer_{this}; base::WeakPtrFactory<SubprocessMetricsProvider> weak_ptr_factory_{this};
diff --git a/chrome/browser/navigation_predictor/navigation_predictor.cc b/chrome/browser/navigation_predictor/navigation_predictor.cc index d2e3f0a..c1fe980 100644 --- a/chrome/browser/navigation_predictor/navigation_predictor.cc +++ b/chrome/browser/navigation_predictor/navigation_predictor.cc
@@ -14,6 +14,8 @@ #include "base/optional.h" #include "base/rand_util.h" #include "base/system/sys_info.h" +#include "chrome/browser/navigation_predictor/navigation_predictor_keyed_service.h" +#include "chrome/browser/navigation_predictor/navigation_predictor_keyed_service_factory.h" #include "chrome/browser/predictors/loading_predictor.h" #include "chrome/browser/predictors/loading_predictor_factory.h" #include "chrome/browser/prerender/prerender_handle.h" @@ -189,10 +191,10 @@ blink::features::kNavigationPredictor, "viewport_width_scale", 0)), - sum_link_scales_( - ratio_area_scale_ + is_in_iframe_scale_ + is_same_host_scale_ + - contains_image_scale_ + is_url_incremented_scale_ + - area_rank_scale_ + ratio_distance_root_top_scale_), + sum_link_scales_(ratio_area_scale_ + is_in_iframe_scale_ + + is_same_host_scale_ + contains_image_scale_ + + is_url_incremented_scale_ + area_rank_scale_ + + ratio_distance_root_top_scale_), sum_page_scales_(link_total_scale_ + iframe_link_total_scale_ + increment_link_total_scale_ + same_origin_link_total_scale_ + image_link_total_scale_ + @@ -219,14 +221,19 @@ normalize_navigation_scores_(base::GetFieldTrialParamByFeatureAsBool( blink::features::kNavigationPredictor, "normalize_scores", - true)) { + true)), + render_frame_host_(render_frame_host) { DCHECK(browser_context_); DETACH_FROM_SEQUENCE(sequence_checker_); DCHECK_LE(0, preconnect_origin_score_threshold_); + DCHECK(render_frame_host_); if (!IsMainFrame(render_frame_host)) return; + if (browser_context_->IsOffTheRecord()) + return; + ukm_recorder_ = ukm::UkmRecorder::Get(); content::WebContents* web_contents = @@ -476,8 +483,9 @@ anchor_element_builder.SetIsURLIncrementedByOne( navigation_score->is_url_incremented_by_one); anchor_element_builder.SetContainsImage(navigation_score->contains_image); - anchor_element_builder.SetSameOrigin(navigation_score->url.GetOrigin() == - document_origin_.GetURL()); + anchor_element_builder.SetSameOrigin( + url::Origin::Create(navigation_score->url) == + url::Origin::Create(document_url_)); // Convert the ratio area and ratio distance from [0,1] to [0,100]. int percent_ratio_area = @@ -837,8 +845,8 @@ std::sort(navigation_scores.begin(), navigation_scores.end(), [](const auto& a, const auto& b) { return a->score > b->score; }); - document_origin_ = url::Origin::Create(metrics[0]->source_url); - MaybeTakeActionOnLoad(document_origin_, navigation_scores); + document_url_ = metrics[0]->source_url; + MaybeTakeActionOnLoad(document_url_, navigation_scores); // Store navigation scores in |navigation_scores_map_| for fast look up upon // clicks. @@ -938,8 +946,23 @@ } } +void NavigationPredictor::NotifyPredictionUpdated( + const std::vector<std::unique_ptr<NavigationScore>>& + sorted_navigation_scores) { + NavigationPredictorKeyedService* service = + NavigationPredictorKeyedServiceFactory::GetForProfile( + Profile::FromBrowserContext(browser_context_)); + DCHECK(service); + std::vector<GURL> top_urls; + top_urls.reserve(sorted_navigation_scores.size()); + for (const auto& nav_score : sorted_navigation_scores) { + top_urls.push_back(nav_score->url); + } + service->OnPredictionUpdated(render_frame_host_, document_url_, top_urls); +} + void NavigationPredictor::MaybeTakeActionOnLoad( - const url::Origin& document_origin, + const GURL& document_url, const std::vector<std::unique_ptr<NavigationScore>>& sorted_navigation_scores) { DCHECK(!browser_context_->IsOffTheRecord()); @@ -952,10 +975,12 @@ DCHECK(!preconnect_origin_.has_value()); DCHECK(!prefetch_url_.has_value()); + NotifyPredictionUpdated(sorted_navigation_scores); + // Try prefetch first. - prefetch_url_ = GetUrlToPrefetch(document_origin, sorted_navigation_scores); + prefetch_url_ = GetUrlToPrefetch(document_url, sorted_navigation_scores); if (prefetch_url_.has_value()) { - DCHECK_EQ(document_origin.host(), prefetch_url_->host()); + DCHECK_EQ(document_url.host(), prefetch_url_->host()); MaybePreconnectNow(Action::kPrefetch); MaybePrefetch(); return; @@ -963,9 +988,9 @@ // Compute preconnect origin only if there is no valid prefetch URL. preconnect_origin_ = - GetOriginToPreconnect(document_origin, sorted_navigation_scores); + GetOriginToPreconnect(document_url, sorted_navigation_scores); if (preconnect_origin_.has_value()) { - DCHECK_EQ(document_origin.host(), preconnect_origin_->host()); + DCHECK_EQ(document_url.host(), preconnect_origin_->host()); MaybePreconnectNow(Action::kPreconnect); return; } @@ -1006,7 +1031,7 @@ } base::Optional<GURL> NavigationPredictor::GetUrlToPrefetch( - const url::Origin& document_origin, + const GURL& document_url, const std::vector<std::unique_ptr<NavigationScore>>& sorted_navigation_scores) const { // Currently, prefetch is disabled on low-end devices since prefetch may @@ -1033,7 +1058,8 @@ // Only the same origin URLs are eligible for prefetching. If the URL with // the highest score is from a different origin, then we skip prefetching // since same origin URLs are not likely to be clicked. - if (url::Origin::Create(url_to_prefetch) != document_origin) { + if (url::Origin::Create(url_to_prefetch) != + url::Origin::Create(document_url)) { return base::nullopt; } @@ -1046,7 +1072,7 @@ } base::Optional<url::Origin> NavigationPredictor::GetOriginToPreconnect( - const url::Origin& document_origin, + const GURL& document_url, const std::vector<std::unique_ptr<NavigationScore>>& sorted_navigation_scores) const { // On search engine results page, next navigation is likely to be a different @@ -1058,7 +1084,7 @@ if (base::GetFieldTrialParamByFeatureAsBool( blink::features::kNavigationPredictor, "preconnect_skip_link_scores", true)) { - return document_origin; + return url::Origin::Create(document_url); } // Compute preconnect score for each origins: Multiple anchor elements on @@ -1117,8 +1143,9 @@ // Connect to the origin with highest score provided the origin is same // as the document origin. - if (sorted_preconnect_scores[0].origin != document_origin) + if (sorted_preconnect_scores[0].origin != url::Origin::Create(document_url)) { return base::nullopt; + } // If the prediction score of the highest scoring origin is less than the // threshold, then return.
diff --git a/chrome/browser/navigation_predictor/navigation_predictor.h b/chrome/browser/navigation_predictor/navigation_predictor.h index 9df4558..f3037c2 100644 --- a/chrome/browser/navigation_predictor/navigation_predictor.h +++ b/chrome/browser/navigation_predictor/navigation_predictor.h
@@ -150,7 +150,7 @@ // action to take, or decide not to do anything. Example actions including // preresolve, preload, prerendering, etc. void MaybeTakeActionOnLoad( - const url::Origin& document_origin, + const GURL& document_url, const std::vector<std::unique_ptr<NavigationScore>>& sorted_navigation_scores); @@ -162,12 +162,12 @@ virtual void Prefetch(prerender::PrerenderManager* prerender_manager); base::Optional<GURL> GetUrlToPrefetch( - const url::Origin& document_origin, + const GURL& document_url, const std::vector<std::unique_ptr<NavigationScore>>& sorted_navigation_scores) const; base::Optional<url::Origin> GetOriginToPreconnect( - const url::Origin& document_origin, + const GURL& document_url, const std::vector<std::unique_ptr<NavigationScore>>& sorted_navigation_scores) const; @@ -208,6 +208,11 @@ // |ratio_area|. int GetLinearBucketForRatioArea(int value) const; + // Notifies the keyed service of the updated predicted navigation. + void NotifyPredictionUpdated( + const std::vector<std::unique_ptr<NavigationScore>>& + sorted_navigation_scores); + // Used to get keyed services. content::BrowserContext* const browser_context_; @@ -309,8 +314,11 @@ // UKM recorder ukm::UkmRecorder* ukm_recorder_ = nullptr; - // The origin of the current page. - url::Origin document_origin_; + // The URL of the current page. + GURL document_url_; + + // Render frame host of the current page. + const content::RenderFrameHost* render_frame_host_; SEQUENCE_CHECKER(sequence_checker_);
diff --git a/chrome/browser/navigation_predictor/navigation_predictor_browsertest.cc b/chrome/browser/navigation_predictor/navigation_predictor_browsertest.cc index b17881b..2eb423c 100644 --- a/chrome/browser/navigation_predictor/navigation_predictor_browsertest.cc +++ b/chrome/browser/navigation_predictor/navigation_predictor_browsertest.cc
@@ -9,6 +9,8 @@ #include "base/test/scoped_feature_list.h" #include "chrome/browser/metrics/subprocess_metrics_provider.h" #include "chrome/browser/navigation_predictor/navigation_predictor.h" +#include "chrome/browser/navigation_predictor/navigation_predictor_keyed_service.h" +#include "chrome/browser/navigation_predictor/navigation_predictor_keyed_service_factory.h" #include "chrome/browser/prerender/prerender_manager.h" #include "chrome/browser/prerender/prerender_manager_factory.h" #include "chrome/browser/search_engines/template_url_service_factory.h" @@ -73,6 +75,17 @@ } } +// Verifies that all URLs specified in |expected_urls| are present in +// |urls_from_observed_prediction|. Ordering of URLs is NOT verified. +void VerifyURLsPresent(const std::vector<GURL>& urls_from_observed_prediction, + const std::vector<std::string>& expected_urls) { + for (const auto& expected_url : expected_urls) { + EXPECT_NE(urls_from_observed_prediction.end(), + std::find(urls_from_observed_prediction.begin(), + urls_from_observed_prediction.end(), expected_url)); + } +} + } // namespace class NavigationPredictorBrowserTest @@ -135,6 +148,57 @@ DISALLOW_COPY_AND_ASSIGN(NavigationPredictorBrowserTest); }; +class TestObserver : public NavigationPredictorKeyedService::Observer { + public: + TestObserver() {} + ~TestObserver() override {} + + base::Optional<NavigationPredictorKeyedService::Prediction> last_prediction() + const { + return last_prediction_; + } + + size_t count_predictions() const { return count_predictions_; } + + // Waits until the count if received notifications is at least + // |expected_notifications_count|. + void WaitUntilNotificationsCountReached(size_t expected_notifications_count) { + // Ensure that |wait_loop_| is null implying there is no ongoing wait. + ASSERT_FALSE(!!wait_loop_); + + if (count_predictions_ >= expected_notifications_count) + return; + expected_notifications_count_ = expected_notifications_count; + wait_loop_ = std::make_unique<base::RunLoop>(); + wait_loop_->Run(); + wait_loop_.reset(); + } + + private: + void OnPredictionUpdated( + const base::Optional<NavigationPredictorKeyedService::Prediction>& + prediction) override { + ++count_predictions_; + last_prediction_ = prediction; + if (wait_loop_ && count_predictions_ >= expected_notifications_count_) { + wait_loop_->Quit(); + } + } + + // Count of prediction notifications received so far. + size_t count_predictions_ = 0u; + + // last prediction received. + base::Optional<NavigationPredictorKeyedService::Prediction> last_prediction_; + + // If |wait_loop_| is non-null, then it quits as soon as count of received + // notifications are at least |expected_notifications_count_|. + std::unique_ptr<base::RunLoop> wait_loop_; + base::Optional<size_t> expected_notifications_count_; + + DISALLOW_COPY_AND_ASSIGN(TestObserver); +}; + IN_PROC_BROWSER_TEST_F(NavigationPredictorBrowserTest, Pipeline) { base::HistogramTester histogram_tester; @@ -855,3 +919,158 @@ histogram_tester.ExpectUniqueSample( "AnchorElementMetrics.Visible.NumberOfAnchorElementsAfterMerge", 3, 1); } + +// Test that navigation score of anchor elements can be calculated on page load +// and the predicted URLs for the next navigation are dispatched to the single +// observer. +IN_PROC_BROWSER_TEST_F(NavigationPredictorBrowserTest, + NavigationScoreSingleObserver) { + TestObserver observer; + + NavigationPredictorKeyedService* service = + NavigationPredictorKeyedServiceFactory::GetForProfile( + browser()->profile()); + EXPECT_NE(nullptr, service); + service->AddObserver(&observer); + + base::HistogramTester histogram_tester; + + const GURL& url = GetTestURL("/simple_page_with_anchors.html"); + ui_test_utils::NavigateToURL(browser(), url); + WaitForLayout(); + observer.WaitUntilNotificationsCountReached(1); + + histogram_tester.ExpectTotalCount( + "AnchorElementMetrics.Visible.HighestNavigationScore", 1); + service->RemoveObserver(&observer); + + EXPECT_EQ(1u, observer.count_predictions()); + EXPECT_EQ(url, observer.last_prediction()->source_document_url()); + EXPECT_EQ(2u, observer.last_prediction()->sorted_predicted_urls().size()); + EXPECT_NE( + observer.last_prediction()->sorted_predicted_urls().end(), + std::find(observer.last_prediction()->sorted_predicted_urls().begin(), + observer.last_prediction()->sorted_predicted_urls().end(), + "https://google.com/")); + EXPECT_NE( + observer.last_prediction()->sorted_predicted_urls().end(), + std::find(observer.last_prediction()->sorted_predicted_urls().begin(), + observer.last_prediction()->sorted_predicted_urls().end(), + "https://example.com/")); + + // Doing another navigation after removing the observer should not cause a + // crash. + ui_test_utils::NavigateToURL(browser(), url); + WaitForLayout(); + EXPECT_EQ(1u, observer.count_predictions()); +} + +// Same as NavigationScoreSingleObserver test but with more than one observer. +IN_PROC_BROWSER_TEST_F(NavigationPredictorBrowserTest, + NavigationScore_TwoObservers) { + TestObserver observer_1; + TestObserver observer_2; + + NavigationPredictorKeyedService* service = + NavigationPredictorKeyedServiceFactory::GetForProfile( + browser()->profile()); + service->AddObserver(&observer_1); + service->AddObserver(&observer_2); + + base::HistogramTester histogram_tester; + + const GURL& url = GetTestURL("/simple_page_with_anchors.html"); + ui_test_utils::NavigateToURL(browser(), url); + WaitForLayout(); + observer_1.WaitUntilNotificationsCountReached(1); + observer_2.WaitUntilNotificationsCountReached(1); + + histogram_tester.ExpectTotalCount( + "AnchorElementMetrics.Visible.HighestNavigationScore", 1); + service->RemoveObserver(&observer_1); + + EXPECT_EQ(1u, observer_1.count_predictions()); + EXPECT_EQ(url, observer_1.last_prediction()->source_document_url()); + EXPECT_EQ(2u, observer_1.last_prediction()->sorted_predicted_urls().size()); + VerifyURLsPresent(observer_1.last_prediction()->sorted_predicted_urls(), + {"https://google.com/", "https://example.com/"}); + EXPECT_EQ(1u, observer_2.count_predictions()); + EXPECT_EQ(url, observer_2.last_prediction()->source_document_url()); + + // Only |observer_2| should get the notification since |observer_1| has + // been removed from receiving the notifications. + ui_test_utils::NavigateToURL(browser(), url); + WaitForLayout(); + observer_2.WaitUntilNotificationsCountReached(2); + EXPECT_EQ(1u, observer_1.count_predictions()); + EXPECT_EQ(2u, observer_2.count_predictions()); + VerifyURLsPresent(observer_2.last_prediction()->sorted_predicted_urls(), + {"https://google.com/", "https://example.com/"}); +} + +// Test that the navigation predictor keyed service is null for incognito +// profiles. +IN_PROC_BROWSER_TEST_F(NavigationPredictorBrowserTest, Incognito) { + Browser* incognito = CreateIncognitoBrowser(); + NavigationPredictorKeyedService* incognito_service = + NavigationPredictorKeyedServiceFactory::GetForProfile( + incognito->profile()); + EXPECT_EQ(nullptr, incognito_service); +} + +// Verify that the observers are notified of predictions on search results page. +IN_PROC_BROWSER_TEST_F(NavigationPredictorBrowserTest, + DISABLE_ON_CHROMEOS(ObserverNotifiedOnSearchPage)) { + TestObserver observer; + + NavigationPredictorKeyedService* service = + NavigationPredictorKeyedServiceFactory::GetForProfile( + browser()->profile()); + service->AddObserver(&observer); + + static const char kShortName[] = "test"; + static const char kSearchURL[] = + "/anchors_different_area.html?q={searchTerms}"; + + // Force Preconnect on + std::map<std::string, std::string> parameters; + base::test::ScopedFeatureList feature_list; + feature_list.InitAndEnableFeatureWithParameters( + blink::features::kNavigationPredictor, parameters); + + // Set up default search engine. + TemplateURLService* model = + TemplateURLServiceFactory::GetForProfile(browser()->profile()); + ASSERT_TRUE(model); + search_test_utils::WaitForTemplateURLServiceToLoad(model); + ASSERT_TRUE(model->loaded()); + + TemplateURLData data; + data.SetShortName(base::ASCIIToUTF16(kShortName)); + data.SetKeyword(data.short_name()); + data.SetURL(GetTestURL(kSearchURL).spec()); + + TemplateURL* template_url = model->Add(std::make_unique<TemplateURL>(data)); + ASSERT_TRUE(template_url); + model->SetUserSelectedDefaultSearchProvider(template_url); + + base::HistogramTester histogram_tester; + + EXPECT_EQ(0u, observer.count_predictions()); + + // This page only has non-same host links. + const GURL& url = GetTestURL("/anchors_different_area.html?q=cats"); + ui_test_utils::NavigateToURL(browser(), url); + WaitForLayout(); + observer.WaitUntilNotificationsCountReached(1u); + + histogram_tester.ExpectUniqueSample("NavigationPredictor.OnDSE.ActionTaken", + NavigationPredictor::Action::kNone, 1); + EXPECT_EQ(1u, observer.count_predictions()); + EXPECT_EQ(url, observer.last_prediction()->source_document_url()); + EXPECT_EQ(5u, observer.last_prediction()->sorted_predicted_urls().size()); + VerifyURLsPresent( + observer.last_prediction()->sorted_predicted_urls(), + {"https://example.com/2", "https://google.com/", "https://example.com/1", + "https://example.com/", "https://dummy.com/"}); +}
diff --git a/chrome/browser/navigation_predictor/navigation_predictor_keyed_service.cc b/chrome/browser/navigation_predictor/navigation_predictor_keyed_service.cc new file mode 100644 index 0000000..61ef5570 --- /dev/null +++ b/chrome/browser/navigation_predictor/navigation_predictor_keyed_service.cc
@@ -0,0 +1,73 @@ +// 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/navigation_predictor/navigation_predictor_keyed_service.h" + +#include "base/compiler_specific.h" +#include "content/public/browser/browser_context.h" +#include "content/public/browser/browser_thread.h" + +NavigationPredictorKeyedService::Prediction::Prediction( + const content::RenderFrameHost* render_frame_host, + const GURL& source_document_url, + const std::vector<GURL>& sorted_predicted_urls) + : render_frame_host_(render_frame_host), + source_document_url_(source_document_url), + sorted_predicted_urls_(sorted_predicted_urls) { + // |render_frame_host_| will be used by consumers in future. + ALLOW_UNUSED_LOCAL(render_frame_host_); +} + +NavigationPredictorKeyedService::Prediction::Prediction( + const NavigationPredictorKeyedService::Prediction& other) = default; + +NavigationPredictorKeyedService::Prediction& +NavigationPredictorKeyedService::Prediction::operator=( + const NavigationPredictorKeyedService::Prediction& other) = default; + +NavigationPredictorKeyedService::Prediction::~Prediction() = default; + +GURL NavigationPredictorKeyedService::Prediction::source_document_url() const { + return source_document_url_; +} + +std::vector<GURL> +NavigationPredictorKeyedService::Prediction::sorted_predicted_urls() const { + return sorted_predicted_urls_; +} + +NavigationPredictorKeyedService::NavigationPredictorKeyedService( + content::BrowserContext* browser_context) { + DCHECK_CURRENTLY_ON(content::BrowserThread::UI); + DCHECK(!browser_context->IsOffTheRecord()); +} + +NavigationPredictorKeyedService::~NavigationPredictorKeyedService() { + DCHECK_CURRENTLY_ON(content::BrowserThread::UI); +} + +void NavigationPredictorKeyedService::OnPredictionUpdated( + const content::RenderFrameHost* render_frame_host, + const GURL& document_url, + const std::vector<GURL>& sorted_predicted_urls) { + DCHECK_CURRENTLY_ON(content::BrowserThread::UI); + last_prediction_ = + Prediction(render_frame_host, document_url, sorted_predicted_urls); + for (auto& observer : observer_list_) { + observer.OnPredictionUpdated(last_prediction_); + } +} + +void NavigationPredictorKeyedService::AddObserver(Observer* observer) { + DCHECK_CURRENTLY_ON(content::BrowserThread::UI); + observer_list_.AddObserver(observer); + if (last_prediction_.has_value()) { + observer->OnPredictionUpdated(last_prediction_); + } +} + +void NavigationPredictorKeyedService::RemoveObserver(Observer* observer) { + DCHECK_CURRENTLY_ON(content::BrowserThread::UI); + observer_list_.RemoveObserver(observer); +}
diff --git a/chrome/browser/navigation_predictor/navigation_predictor_keyed_service.h b/chrome/browser/navigation_predictor/navigation_predictor_keyed_service.h new file mode 100644 index 0000000..538b381a --- /dev/null +++ b/chrome/browser/navigation_predictor/navigation_predictor_keyed_service.h
@@ -0,0 +1,95 @@ +// Copyright 2019 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#ifndef CHROME_BROWSER_NAVIGATION_PREDICTOR_NAVIGATION_PREDICTOR_KEYED_SERVICE_H_ +#define CHROME_BROWSER_NAVIGATION_PREDICTOR_NAVIGATION_PREDICTOR_KEYED_SERVICE_H_ + +#include <vector> + +#include "base/macros.h" +#include "base/observer_list.h" +#include "base/optional.h" +#include "base/single_thread_task_runner.h" +#include "components/keyed_service/core/keyed_service.h" +#include "url/gurl.h" + +namespace content { +class BrowserContext; +class RenderFrameHost; +} // namespace content + +// Keyed service that can be used to receive notifications about the URLs for +// the next predicted navigation. +class NavigationPredictorKeyedService : public KeyedService { + public: + // Stores the next set of URLs that the user is expected to navigate to. + class Prediction { + public: + Prediction(const content::RenderFrameHost* render_frame_host, + const GURL& source_document_url, + const std::vector<GURL>& sorted_predicted_urls); + Prediction(const Prediction& other); + Prediction& operator=(const Prediction& other); + ~Prediction(); + GURL source_document_url() const; + std::vector<GURL> sorted_predicted_urls() const; + + private: + // |render_frame_host_| from where the navigation may happen. May be + // nullptr. + const content::RenderFrameHost* render_frame_host_; + + // Current URL of the document from where the navigtion may happen. + GURL source_document_url_; + + // Ordered set of URLs that the user is expected to navigate to next. The + // URLs are in the decreasing order of click probability. + std::vector<GURL> sorted_predicted_urls_; + }; + + // Observer class can be implemented to receive notifications about the + // predicted URLs for the next navigation. OnPredictionUpdated() is called + // every time a new prediction is available. Prediction includes the source + // document as well as the ordered list of URLs that the user may navigate to + // next. OnPredictionUpdated() may be called multiple times for the same + // source document URL. + class Observer { + public: + virtual void OnPredictionUpdated( + const base::Optional<Prediction>& prediction) = 0; + + protected: + Observer() {} + virtual ~Observer() {} + }; + + explicit NavigationPredictorKeyedService( + content::BrowserContext* browser_context); + ~NavigationPredictorKeyedService() override; + + // |document_url| may be invalid. Called by navigation predictor. + void OnPredictionUpdated(const content::RenderFrameHost* render_frame_host, + const GURL& document_url, + const std::vector<GURL>& sorted_predicted_urls); + + // Adds |observer| as the observer for next predicted navigation. When + // |observer| is added via AddObserver, it's immediately notified of the last + // known prediction. + void AddObserver(Observer* observer); + + // Removes |observer| as the observer for next predicted navigation. + void RemoveObserver(Observer* observer); + + private: + // List of observers are currently registered to receive notifications for the + // next predicted navigations. + base::ObserverList<Observer>::Unchecked observer_list_; + + // Last known prediction. + base::Optional<Prediction> last_prediction_; + + DISALLOW_COPY_AND_ASSIGN(NavigationPredictorKeyedService); +}; + +#endif // CHROME_BROWSER_NAVIGATION_PREDICTOR_NAVIGATION_PREDICTOR_KEYED_SERVICE_H_
diff --git a/chrome/browser/navigation_predictor/navigation_predictor_keyed_service_factory.cc b/chrome/browser/navigation_predictor/navigation_predictor_keyed_service_factory.cc new file mode 100644 index 0000000..35281fd2 --- /dev/null +++ b/chrome/browser/navigation_predictor/navigation_predictor_keyed_service_factory.cc
@@ -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. + +#include "chrome/browser/navigation_predictor/navigation_predictor_keyed_service_factory.h" + +#include "chrome/browser/navigation_predictor/navigation_predictor_keyed_service.h" +#include "chrome/browser/profiles/profile.h" +#include "components/keyed_service/content/browser_context_dependency_manager.h" +#include "content/public/browser/browser_context.h" + +namespace { + +base::LazyInstance<NavigationPredictorKeyedServiceFactory>::DestructorAtExit + g_navigation_predictor_keyed_service_factory = LAZY_INSTANCE_INITIALIZER; + +} // namespace + +// static +NavigationPredictorKeyedService* +NavigationPredictorKeyedServiceFactory::GetForProfile(Profile* profile) { + return static_cast<NavigationPredictorKeyedService*>( + GetInstance()->GetServiceForBrowserContext(profile, true)); +} + +// static +NavigationPredictorKeyedServiceFactory* +NavigationPredictorKeyedServiceFactory::GetInstance() { + return g_navigation_predictor_keyed_service_factory.Pointer(); +} + +NavigationPredictorKeyedServiceFactory::NavigationPredictorKeyedServiceFactory() + : BrowserContextKeyedServiceFactory( + "NavigationPredictorKeyedService", + BrowserContextDependencyManager::GetInstance()) {} + +NavigationPredictorKeyedServiceFactory:: + ~NavigationPredictorKeyedServiceFactory() {} + +KeyedService* NavigationPredictorKeyedServiceFactory::BuildServiceInstanceFor( + content::BrowserContext* context) const { + return new NavigationPredictorKeyedService(context); +}
diff --git a/chrome/browser/navigation_predictor/navigation_predictor_keyed_service_factory.h b/chrome/browser/navigation_predictor/navigation_predictor_keyed_service_factory.h new file mode 100644 index 0000000..89a4c9a --- /dev/null +++ b/chrome/browser/navigation_predictor/navigation_predictor_keyed_service_factory.h
@@ -0,0 +1,44 @@ +// Copyright 2019 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#ifndef CHROME_BROWSER_NAVIGATION_PREDICTOR_NAVIGATION_PREDICTOR_KEYED_SERVICE_FACTORY_H_ +#define CHROME_BROWSER_NAVIGATION_PREDICTOR_NAVIGATION_PREDICTOR_KEYED_SERVICE_FACTORY_H_ + +#include "base/lazy_instance.h" +#include "base/macros.h" +#include "components/keyed_service/content/browser_context_keyed_service_factory.h" + +namespace content { +class BrowserContext; +} + +class NavigationPredictorKeyedService; +class Profile; + +// LazyInstance that owns all NavigationPredictorKeyedServices and associates +// them with Profiles. +class NavigationPredictorKeyedServiceFactory + : public BrowserContextKeyedServiceFactory { + public: + // Gets the NavigationPredictorKeyedService instance for |profile|. + static NavigationPredictorKeyedService* GetForProfile(Profile* profile); + + // Gets the LazyInstance that owns all NavigationPredictorKeyedServices. + static NavigationPredictorKeyedServiceFactory* GetInstance(); + + private: + friend struct base::LazyInstanceTraitsBase< + NavigationPredictorKeyedServiceFactory>; + + NavigationPredictorKeyedServiceFactory(); + ~NavigationPredictorKeyedServiceFactory() override; + + // BrowserContextKeyedServiceFactory: + KeyedService* BuildServiceInstanceFor( + content::BrowserContext* context) const override; + + DISALLOW_COPY_AND_ASSIGN(NavigationPredictorKeyedServiceFactory); +}; + +#endif // CHROME_BROWSER_NAVIGATION_PREDICTOR_NAVIGATION_PREDICTOR_KEYED_SERVICE_FACTORY_H_
diff --git a/chrome/browser/net/profile_network_context_service.cc b/chrome/browser/net/profile_network_context_service.cc index a0dd2bd1..8861d30 100644 --- a/chrome/browser/net/profile_network_context_service.cc +++ b/chrome/browser/net/profile_network_context_service.cc
@@ -31,7 +31,6 @@ #include "chrome/common/chrome_switches.h" #include "chrome/common/pref_names.h" #include "components/certificate_transparency/pref_names.h" -#include "components/content_settings/core/browser/cookie_settings.h" #include "components/content_settings/core/browser/host_content_settings_map.h" #include "components/data_reduction_proxy/core/common/data_reduction_proxy_params.h" #include "components/language/core/browser/pref_names.h" @@ -129,9 +128,7 @@ } // namespace ProfileNetworkContextService::ProfileNetworkContextService(Profile* profile) - : profile_(profile), - proxy_config_monitor_(profile), - cookie_settings_observer_(this) { + : profile_(profile), proxy_config_monitor_(profile) { PrefService* profile_prefs = profile->GetPrefs(); quic_allowed_.Init( prefs::kQuicAllowed, profile_prefs,
diff --git a/chrome/browser/net/profile_network_context_service.h b/chrome/browser/net/profile_network_context_service.h index ad43b67..6ebf38e 100644 --- a/chrome/browser/net/profile_network_context_service.h +++ b/chrome/browser/net/profile_network_context_service.h
@@ -132,8 +132,9 @@ PrefChangeRegistrar pref_change_registrar_; scoped_refptr<content_settings::CookieSettings> cookie_settings_; - ScopedObserver<content_settings::CookieSettings, ProfileNetworkContextService> - cookie_settings_observer_; + ScopedObserver<content_settings::CookieSettings, + content_settings::CookieSettings::Observer> + cookie_settings_observer_{this}; // Used to post schedule CT policy updates base::OneShotTimer ct_policy_update_timer_;
diff --git a/chrome/browser/notifications/notification_system_observer.cc b/chrome/browser/notifications/notification_system_observer.cc index 48cf5ca9..a2e7ef8f 100644 --- a/chrome/browser/notifications/notification_system_observer.cc +++ b/chrome/browser/notifications/notification_system_observer.cc
@@ -11,12 +11,11 @@ #include "chrome/browser/profiles/profile.h" #include "chrome/browser/profiles/profile_manager.h" #include "content/public/browser/notification_service.h" -#include "extensions/browser/extension_registry.h" #include "extensions/common/extension.h" NotificationSystemObserver::NotificationSystemObserver( NotificationUIManager* ui_manager) - : ui_manager_(ui_manager), extension_registry_observer_(this) { + : ui_manager_(ui_manager) { DCHECK(ui_manager_); registrar_.Add(this, chrome::NOTIFICATION_APP_TERMINATING, content::NotificationService::AllSources());
diff --git a/chrome/browser/notifications/notification_system_observer.h b/chrome/browser/notifications/notification_system_observer.h index f206c37..fc6319b 100644 --- a/chrome/browser/notifications/notification_system_observer.h +++ b/chrome/browser/notifications/notification_system_observer.h
@@ -9,16 +9,13 @@ #include "base/scoped_observer.h" #include "content/public/browser/notification_observer.h" #include "content/public/browser/notification_registrar.h" +#include "extensions/browser/extension_registry.h" #include "extensions/browser/extension_registry_observer.h" namespace content { class BrowserContext; } -namespace extensions { -class ExtensionRegistry; -} - class NotificationUIManager; // The content::NotificationObserver observes system status change and sends @@ -49,7 +46,7 @@ ScopedObserver<extensions::ExtensionRegistry, extensions::ExtensionRegistryObserver> - extension_registry_observer_; + extension_registry_observer_{this}; DISALLOW_COPY_AND_ASSIGN(NotificationSystemObserver); };
diff --git a/chrome/browser/page_load_metrics/observers/use_counter/ukm_features.cc b/chrome/browser/page_load_metrics/observers/use_counter/ukm_features.cc index d1d8c0e5..9d33ac2 100644 --- a/chrome/browser/page_load_metrics/observers/use_counter/ukm_features.cc +++ b/chrome/browser/page_load_metrics/observers/use_counter/ukm_features.cc
@@ -133,6 +133,9 @@ WebFeature::kBaseWithCrossOriginHref, WebFeature::kWakeLockAcquireScreenLock, WebFeature::kWakeLockAcquireSystemLock, + WebFeature::kThirdPartyServiceWorker, + WebFeature::kThirdPartySharedWorker, + WebFeature::kThirdPartyBroadcastChannel, })); return *opt_in_features; }
diff --git a/chrome/browser/password_manager/chrome_password_manager_client.cc b/chrome/browser/password_manager/chrome_password_manager_client.cc index 78686cf6..b0a2dbd 100644 --- a/chrome/browser/password_manager/chrome_password_manager_client.cc +++ b/chrome/browser/password_manager/chrome_password_manager_client.cc
@@ -201,7 +201,6 @@ password_feature_manager_( ProfileSyncServiceFactory::GetForProfile(profile_)), httpauth_manager_(this), -// TODO(crbug.com/706392): Fix password reuse detection for Android. #if defined(SYNC_PASSWORD_REUSE_DETECTION_ENABLED) password_reuse_detection_manager_(this), #endif @@ -640,7 +639,6 @@ if (!navigation_handle->IsSameDocument()) content_credential_manager_.DisconnectBinding(); -// TODO(crbug.com/706392): Fix password reuse detection for Android. #if defined(SYNC_PASSWORD_REUSE_DETECTION_ENABLED) password_reuse_detection_manager_.DidNavigateMainFrame(GetMainFrameURL()); #endif // defined(SYNC_PASSWORD_REUSE_DETECTION_ENABLED)
diff --git a/chrome/browser/password_manager/chrome_password_manager_client.h b/chrome/browser/password_manager/chrome_password_manager_client.h index d260d99..ce4cc700 100644 --- a/chrome/browser/password_manager/chrome_password_manager_client.h +++ b/chrome/browser/password_manager/chrome_password_manager_client.h
@@ -250,13 +250,14 @@ content::NavigationHandle* navigation_handle) override; void DidFinishNavigation( content::NavigationHandle* navigation_handle) override; +// TODO(crbug.com/1006430): Paste event is not captured on Android. #if !defined(OS_ANDROID) void OnPaste() override; #endif void RenderFrameCreated(content::RenderFrameHost* render_frame_host) override; -// TODO(crbug.com/706392): Fix password reuse detection for Android. +// Key events are triggered by Ime text committed event on Android. #if !defined(OS_ANDROID) // content::RenderWidgetHost::InputEventObserver overrides. void OnInputEvent(const blink::WebInputEvent&) override; @@ -300,7 +301,6 @@ const password_manager::PasswordFeatureManagerImpl password_feature_manager_; password_manager::HttpAuthManagerImpl httpauth_manager_; -// TODO(crbug.com/706392): Fix password reuse detection for Android. #if defined(SYNC_PASSWORD_REUSE_DETECTION_ENABLED) password_manager::PasswordReuseDetectionManager password_reuse_detection_manager_;
diff --git a/chrome/browser/policy/e2e_test/.vpython b/chrome/browser/policy/e2e_test/.vpython index 3b319d1..bc935fa 100644 --- a/chrome/browser/policy/e2e_test/.vpython +++ b/chrome/browser/policy/e2e_test/.vpython
@@ -11,7 +11,8 @@ wheel: < name: "infra/celab/celab/windows-amd64" - version: "MxUQe6cwcaLhKIoFnrYyH5Nn6mq0qMD7lxaPld0bqgoC" + # Source: https://ci.chromium.org/p/celab/builders/ci/Windows/b8902045658105865392 + version: "mHamQ8UpCgqQTQZyuKIFVlvYy3KSkDCsUSGXQtL5E-YC" > # googleapiclient
diff --git a/chrome/browser/policy/e2e_test/infra/chrome_ent_test_case.py b/chrome/browser/policy/e2e_test/infra/chrome_ent_test_case.py index 27554cb..fec0453a 100644 --- a/chrome/browser/policy/e2e_test/infra/chrome_ent_test_case.py +++ b/chrome/browser/policy/e2e_test/infra/chrome_ent_test_case.py
@@ -32,6 +32,7 @@ - mini_installer.exe, and - *.msi """ + self.RunCommand(instance_name, r'md -Force c:\temp') file_name = self.UploadFile(instance_name, FLAGS.chrome_installer, r'c:\temp') @@ -96,32 +97,24 @@ "-Key %s -ValueName %s") % (key, policy_name) self.clients[instance_name].RunPowershell(cmd) - def _installChocolatey(self, instance_name): - cmd = "Set-ExecutionPolicy Bypass -Scope Process -Force; iex ((New-Object System.Net.WebClient).DownloadString('https://chocolatey.org/install.ps1'))" - self.clients[instance_name].RunPowershell(cmd) - - def InstallPackage(self, instance_name, package_name, package_version): - cmd = r'c:\ProgramData\chocolatey\bin\choco install %s -y --version %s' % ( - package_name, package_version) - self.RunCommand(instance_name, cmd) - def InstallWebDriver(self, instance_name): - self._installChocolatey(instance_name) - self.InstallPackage(instance_name, 'python2', '2.7.15') - self.RunCommand( - instance_name, - r'c:\Python27\python.exe -m pip install selenium absl-py pywin32') + self.InstallPipPackagesLatest(instance_name, + ['selenium', 'absl-py', 'pywin32']) + + temp_dir = 'C:\\temp\\' if FLAGS.chromedriver is None: - # chromedriver flag is not specified. In this case, install the chocolatey - # package - self.InstallPackage(instance_name, 'chromedriver', '74.0.3729.60') + # chromedriver flag is not specified. Install the chocolatey package. + self.InstallChocolateyPackage(instance_name, 'chromedriver', + '74.0.3729.60') + self.RunCommand( + instance_name, "copy %s %s" % + (r"C:\ProgramData\chocolatey\lib\chromedriver\tools\chromedriver.exe", + temp_dir)) else: - self.UploadFile(instance_name, FLAGS.chromedriver, - 'C:/ProgramData/chocolatey/lib/chromedriver/tools/') + self.UploadFile(instance_name, FLAGS.chromedriver, temp_dir) dir = os.path.dirname(os.path.abspath(__file__)) - self.UploadFile(instance_name, os.path.join(dir, 'test_util.py'), - r'c:\temp') + self.UploadFile(instance_name, os.path.join(dir, 'test_util.py'), temp_dir) def RunWebDriverTest(self, instance_name, test_file, args=[]): """Runs a python webdriver test on an instance. @@ -133,6 +126,8 @@ Returns: the output.""" + self.EnsurePythonInstalled(instance_name) + # upload the test file_name = self.UploadFile(instance_name, test_file, r'c:\temp') @@ -153,6 +148,8 @@ Returns: the output.""" + self.EnsurePythonInstalled(instance_name) + # upload the test file_name = self.UploadFile(instance_name, test_file, r'c:\temp') @@ -184,10 +181,8 @@ def EnableUITest(self, instance_name): """Configures the instance so that UI tests can be run on it.""" self.InstallWebDriver(instance_name) - self.InstallPackage(instance_name, 'sysinternals', '2019.9.5') - self.RunCommand( - instance_name, - r'c:\Python27\python.exe -m pip install pywinauto requests') + self.InstallChocolateyPackageLatest(instance_name, 'sysinternals') + self.InstallPipPackagesLatest(instance_name, ['pywinauto', 'requests']) password = self._generatePassword() user_name = 'ui_user'
diff --git a/chrome/browser/policy/e2e_test/infra/test_util.py b/chrome/browser/policy/e2e_test/infra/test_util.py index 50e93d2..f08eed66 100644 --- a/chrome/browser/policy/e2e_test/infra/test_util.py +++ b/chrome/browser/policy/e2e_test/infra/test_util.py
@@ -63,6 +63,6 @@ os.environ["CHROME_LOG_FILE"] = r"c:\temp\chrome_log.txt" return webdriver.Chrome( - "C:/ProgramData/chocolatey/lib/chromedriver/tools/chromedriver.exe", + executable_path=r"C:\temp\chromedriver.exe", service_args=["--verbose", r"--log-path=c:\temp\chromedriver.log"], chrome_options=chrome_options)
diff --git a/chrome/browser/policy/e2e_test/tests/bookmarkbar_enabled/bookmarkbar_webdriver.py b/chrome/browser/policy/e2e_test/tests/bookmarkbar_enabled/bookmarkbar_webdriver.py index 500f0aa..76d089f 100644 --- a/chrome/browser/policy/e2e_test/tests/bookmarkbar_enabled/bookmarkbar_webdriver.py +++ b/chrome/browser/policy/e2e_test/tests/bookmarkbar_enabled/bookmarkbar_webdriver.py
@@ -2,20 +2,16 @@ # Use of this source code is governed by a BSD-style license that can be # found in the LICENSE file. -from selenium import webdriver from pywinauto.application import Application from pywinauto.findwindows import ElementNotFoundError -import os +from selenium import webdriver + +import test_util options = webdriver.ChromeOptions() options.add_argument("--force-renderer-accessibility") -os.environ["CHROME_LOG_FILE"] = r"c:\temp\chrome_log.txt" - -driver = webdriver.Chrome( - "C:/ProgramData/chocolatey/lib/chromedriver/tools/chromedriver.exe", - chrome_options=options, - service_args=["--verbose", r"--log-path=c:\temp\chromedriver.log"]) +driver = test_util.create_chrome_webdriver(chrome_options=options) try: app = Application(backend="uia")
diff --git a/chrome/browser/policy/e2e_test/tests/default_search_provider/default_search_provider_webdriver.py b/chrome/browser/policy/e2e_test/tests/default_search_provider/default_search_provider_webdriver.py index aa0bbda..6a7684d 100644 --- a/chrome/browser/policy/e2e_test/tests/default_search_provider/default_search_provider_webdriver.py +++ b/chrome/browser/policy/e2e_test/tests/default_search_provider/default_search_provider_webdriver.py
@@ -2,20 +2,16 @@ # Use of this source code is governed by a BSD-style license that can be # found in the LICENSE file. -from selenium import webdriver from pywinauto.application import Application -import os +from selenium import webdriver + +import test_util # Set up ChromeDriver options = webdriver.ChromeOptions() options.add_argument("--force-renderer-accessibility") -os.environ["CHROME_LOG_FILE"] = r"c:\temp\chrome_log.txt" - -driver = webdriver.Chrome( - "C:/ProgramData/chocolatey/lib/chromedriver/tools/chromedriver.exe", - chrome_options=options, - service_args=["--verbose", r"--log-path=c:\temp\chromedriver.log"]) +driver = test_util.create_chrome_webdriver(chrome_options=options) try: app = Application(backend="uia")
diff --git a/chrome/browser/policy/e2e_test/tests/force_google_safe_search/force_google_safe_search_webdriver_test.py b/chrome/browser/policy/e2e_test/tests/force_google_safe_search/force_google_safe_search_webdriver_test.py index eba78c53..078225e 100644 --- a/chrome/browser/policy/e2e_test/tests/force_google_safe_search/force_google_safe_search_webdriver_test.py +++ b/chrome/browser/policy/e2e_test/tests/force_google_safe_search/force_google_safe_search_webdriver_test.py
@@ -2,18 +2,13 @@ # Use of this source code is governed by a BSD-style license that can be # found in the LICENSE file. -import os - -from selenium import webdriver from selenium.webdriver.common.by import By from selenium.webdriver.support import expected_conditions as EC from selenium.webdriver.support.ui import WebDriverWait -os.environ["CHROME_LOG_FILE"] = r"c:\temp\chrome_log.txt" +import test_util -driver = webdriver.Chrome( - "C:/ProgramData/chocolatey/lib/chromedriver/tools/chromedriver.exe", - service_args=["--verbose", r"--log-path=c:\temp\chromedriver.log"]) +driver = test_util.create_chrome_webdriver() driver.get('http://www.google.com/xhtml') # wait for page to be loaded
diff --git a/chrome/browser/policy/e2e_test/tests/homepage/get_homepage_url.py b/chrome/browser/policy/e2e_test/tests/homepage/get_homepage_url.py index 7bb3f5e..af07d707 100644 --- a/chrome/browser/policy/e2e_test/tests/homepage/get_homepage_url.py +++ b/chrome/browser/policy/e2e_test/tests/homepage/get_homepage_url.py
@@ -2,12 +2,11 @@ # Use of this source code is governed by a BSD-style license that can be # found in the LICENSE file. -from selenium import webdriver -import os from pywinauto.application import Application -driver = webdriver.Chrome( - "C:/ProgramData/chocolatey/lib/chromedriver/tools/chromedriver.exe") +import test_util + +driver = test_util.create_chrome_webdriver() try: app = Application(backend="uia")
diff --git a/chrome/browser/policy/e2e_test/tests/install_extension.py b/chrome/browser/policy/e2e_test/tests/install_extension.py index 4188ddc..fd22bdb 100644 --- a/chrome/browser/policy/e2e_test/tests/install_extension.py +++ b/chrome/browser/policy/e2e_test/tests/install_extension.py
@@ -2,10 +2,12 @@ # Use of this source code is governed by a BSD-style license that can be # found in the LICENSE file. -from selenium import webdriver -import os import time + from absl import app, flags +from selenium import webdriver + +import test_util FLAGS = flags.FLAGS @@ -35,12 +37,7 @@ #https://bugs.chromium.org/p/chromedriver/issues/detail?id=2930 chrome_options.add_experimental_option("useAutomationExtension", False) - os.environ["CHROME_LOG_FILE"] = r"c:\temp\chrome_log.txt" - - driver = webdriver.Chrome( - "C:/ProgramData/chocolatey/lib/chromedriver/tools/chromedriver.exe", - service_args=["--verbose", r"--log-path=c:\temp\chromedriver.log"], - chrome_options=chrome_options) + driver = test_util.create_chrome_webdriver(chrome_options=chrome_options) driver.implicitly_wait(FLAGS.wait) driver.get(FLAGS.url)
diff --git a/chrome/browser/policy/e2e_test/tests/popups_allowed/popup_allowed_webdriver_test.py b/chrome/browser/policy/e2e_test/tests/popups_allowed/popup_allowed_webdriver_test.py index 5029678..57df013 100644 --- a/chrome/browser/policy/e2e_test/tests/popups_allowed/popup_allowed_webdriver_test.py +++ b/chrome/browser/policy/e2e_test/tests/popups_allowed/popup_allowed_webdriver_test.py
@@ -4,14 +4,12 @@ from selenium import webdriver +import test_util + testSite = "http://www.popuptest.com/popuptest1.html" options = webdriver.ChromeOptions() options.add_experimental_option('excludeSwitches', ['disable-popup-blocking']) -exe_path = "C:/ProgramData/chocolatey/lib/chromedriver/tools/chromedriver.exe" -driver = webdriver.Chrome( - exe_path, - chrome_options=options, - service_args=["--verbose", r"--log-path=c:\temp\chromedriver.log"]) +driver = test_util.create_chrome_webdriver(chrome_options=options) driver.implicitly_wait(5) driver.get(testSite) handles = driver.window_handles
diff --git a/chrome/browser/policy/e2e_test/tests/restore_on_startup/restore_on_startup_webdriver_test.py b/chrome/browser/policy/e2e_test/tests/restore_on_startup/restore_on_startup_webdriver_test.py index 76a78d3..2127046 100644 --- a/chrome/browser/policy/e2e_test/tests/restore_on_startup/restore_on_startup_webdriver_test.py +++ b/chrome/browser/policy/e2e_test/tests/restore_on_startup/restore_on_startup_webdriver_test.py
@@ -2,13 +2,14 @@ # Use of this source code is governed by a BSD-style license that can be # found in the LICENSE file. -import time -import test_util import json +import time + from absl import app, flags -from selenium import webdriver from selenium.webdriver.chrome.options import Options +import test_util + FLAGS = flags.FLAGS flags.DEFINE_enum( @@ -26,12 +27,7 @@ def _create_driver(): chrome_options = Options() chrome_options.add_argument(r'user-data-dir=%s' % FLAGS.user_data_dir) - driver = webdriver.Chrome( - executable_path= - "C:/ProgramData/chocolatey/lib/chromedriver/tools/chromedriver.exe", - chrome_options=chrome_options, - service_args=["--verbose", r"--log-path=c:\temp\chromedriver.log"]) - return driver + return test_util.create_chrome_webdriver(chrome_options=chrome_options) def _get_urls(driver):
diff --git a/chrome/browser/policy/e2e_test/tests/user_data_dir/user_data_dir_webdriver.py b/chrome/browser/policy/e2e_test/tests/user_data_dir/user_data_dir_webdriver.py index 756b27a..77f8386 100644 --- a/chrome/browser/policy/e2e_test/tests/user_data_dir/user_data_dir_webdriver.py +++ b/chrome/browser/policy/e2e_test/tests/user_data_dir/user_data_dir_webdriver.py
@@ -2,9 +2,12 @@ # Use of this source code is governed by a BSD-style license that can be # found in the LICENSE file. -from selenium import webdriver import os + from absl import app, flags +from selenium import webdriver + +import test_util FLAGS = flags.FLAGS flags.DEFINE_string('user_data_dir', None, 'Need specify user data dir to test') @@ -25,12 +28,8 @@ options = webdriver.ChromeOptions() # Add option for connecting chromedriver with Chrome options.add_experimental_option("debuggerAddress", "localhost:9222") - os.environ["CHROME_LOG_FILE"] = r"c:\temp\chrome_log.txt" - driver = webdriver.Chrome( - "C:/ProgramData/chocolatey/lib/chromedriver/tools/chromedriver.exe", - chrome_options=options, - service_args=["--verbose", r"--log-path=c:\temp\chromedriver.log"]) + driver = test_util.create_chrome_webdriver(chrome_options=options) try: # Verify User Data Dir in chrome://policy page
diff --git a/chrome/browser/predictors/autocomplete_action_predictor.cc b/chrome/browser/predictors/autocomplete_action_predictor.cc index 2e1391a..cb7d23a 100644 --- a/chrome/browser/predictors/autocomplete_action_predictor.cc +++ b/chrome/browser/predictors/autocomplete_action_predictor.cc
@@ -25,7 +25,6 @@ #include "chrome/browser/prerender/prerender_manager.h" #include "chrome/browser/prerender/prerender_manager_factory.h" #include "chrome/browser/profiles/profile.h" -#include "components/history/core/browser/history_service.h" #include "components/history/core/browser/in_memory_database.h" #include "components/omnibox/browser/autocomplete_match.h" #include "components/omnibox/browser/autocomplete_result.h" @@ -74,8 +73,7 @@ : profile_(profile), main_profile_predictor_(NULL), incognito_predictor_(NULL), - initialized_(false), - history_service_observer_(this) { + initialized_(false) { if (profile_->IsOffTheRecord()) { main_profile_predictor_ = AutocompleteActionPredictorFactory::GetForProfile( profile_->GetOriginalProfile());
diff --git a/chrome/browser/predictors/autocomplete_action_predictor.h b/chrome/browser/predictors/autocomplete_action_predictor.h index 085a6677..fbaffeb 100644 --- a/chrome/browser/predictors/autocomplete_action_predictor.h +++ b/chrome/browser/predictors/autocomplete_action_predictor.h
@@ -18,6 +18,7 @@ #include "base/scoped_observer.h" #include "base/strings/string16.h" #include "chrome/browser/predictors/autocomplete_action_predictor_table.h" +#include "components/history/core/browser/history_service.h" #include "components/history/core/browser/history_service_observer.h" #include "components/history/core/browser/history_types.h" #include "components/keyed_service/core/keyed_service.h" @@ -40,7 +41,6 @@ } namespace history { -class HistoryService; class URLDatabase; } @@ -280,7 +280,7 @@ bool initialized_; ScopedObserver<history::HistoryService, history::HistoryServiceObserver> - history_service_observer_; + history_service_observer_{this}; DISALLOW_COPY_AND_ASSIGN(AutocompleteActionPredictor); };
diff --git a/chrome/browser/predictors/resource_prefetch_predictor.cc b/chrome/browser/predictors/resource_prefetch_predictor.cc index 451e0e7..1ccbca4 100644 --- a/chrome/browser/predictors/resource_prefetch_predictor.cc +++ b/chrome/browser/predictors/resource_prefetch_predictor.cc
@@ -22,7 +22,6 @@ #include "chrome/browser/predictors/predictors_features.h" #include "chrome/browser/profiles/profile.h" #include "components/history/core/browser/history_database.h" -#include "components/history/core/browser/history_service.h" #include "components/history/core/browser/url_utils.h" #include "content/public/browser/browser_thread.h" #include "content/public/browser/web_contents.h" @@ -223,8 +222,7 @@ config_(config), initialization_state_(NOT_INITIALIZED), tables_(PredictorDatabaseFactory::GetForProfile(profile) - ->resource_prefetch_tables()), - history_service_observer_(this) { + ->resource_prefetch_tables()) { DCHECK_CURRENTLY_ON(BrowserThread::UI); }
diff --git a/chrome/browser/predictors/resource_prefetch_predictor.h b/chrome/browser/predictors/resource_prefetch_predictor.h index d05c0246..09a8d0ed 100644 --- a/chrome/browser/predictors/resource_prefetch_predictor.h +++ b/chrome/browser/predictors/resource_prefetch_predictor.h
@@ -25,6 +25,7 @@ #include "chrome/browser/predictors/navigation_id.h" #include "chrome/browser/predictors/resource_prefetch_predictor_tables.h" #include "components/history/core/browser/history_db_task.h" +#include "components/history/core/browser/history_service.h" #include "components/history/core/browser/history_service_observer.h" #include "components/history/core/browser/history_types.h" #include "components/keyed_service/core/keyed_service.h" @@ -276,7 +277,7 @@ std::unique_ptr<OriginDataMap> origin_data_; ScopedObserver<history::HistoryService, history::HistoryServiceObserver> - history_service_observer_; + history_service_observer_{this}; // Indicates if all predictors data should be deleted after the // initialization is completed.
diff --git a/chrome/browser/previews/previews_content_util.cc b/chrome/browser/previews/previews_content_util.cc index 828f0fc5..90562de 100644 --- a/chrome/browser/previews/previews_content_util.cc +++ b/chrome/browser/previews/previews_content_util.cc
@@ -19,7 +19,6 @@ #include "chrome/browser/data_reduction_proxy/data_reduction_proxy_chrome_settings.h" #include "chrome/browser/data_reduction_proxy/data_reduction_proxy_chrome_settings_factory.h" #include "chrome/browser/previews/previews_lite_page_decider.h" -#include "chrome/browser/previews/previews_lite_page_navigation_throttle.h" #include "chrome/browser/previews/previews_lite_page_url_loader_interceptor.h" #include "chrome/browser/previews/previews_offline_helper.h" #include "chrome/browser/previews/previews_service.h" @@ -99,8 +98,7 @@ Profile::FromBrowserContext(web_contents->GetBrowserContext())) .get(); ContentSetting setting; - GURL previews_url = - PreviewsLitePageNavigationThrottle::GetPreviewsURLForURL(url); + GURL previews_url = GetLitePageRedirectURLForURL(url); cookie_settings->GetCookieSetting(previews_url, previews_url, nullptr, &setting); if (!content_settings::CookieSettingsBase::IsAllowed(setting)) { @@ -162,7 +160,7 @@ // This should always be last. if (previews::params::IsInLitePageRedirectControl()) { previews::PreviewsUserData::ServerLitePageInfo* info = - PreviewsLitePageNavigationThrottle::GetOrCreateServerLitePageInfo( + PreviewsLitePageURLLoaderInterceptor::GetOrCreateServerLitePageInfo( navigation_handle, decider); info->status = previews::ServerLitePageStatus::kControl; return false; @@ -432,9 +430,7 @@ // Check if a LITE_PAGE_REDIRECT preview was actually served. if (previews_state & content::LITE_PAGE_REDIRECT_ON) { if (IsLitePageRedirectPreviewURL(url)) { - if (navigation_handle && - base::FeatureList::IsEnabled( - previews::features::kHTTPSServerPreviewsUsingURLLoader)) { + if (navigation_handle) { previews_data->set_server_lite_page_info( CreateServerLitePageInfoFromNavigationHandle(navigation_handle)); }
diff --git a/chrome/browser/previews/previews_lite_page_browsertest.cc b/chrome/browser/previews/previews_lite_page_browsertest.cc index b73af598..8f5ed51 100644 --- a/chrome/browser/previews/previews_lite_page_browsertest.cc +++ b/chrome/browser/previews/previews_lite_page_browsertest.cc
@@ -36,7 +36,6 @@ #include "chrome/browser/infobars/mock_infobar_service.h" #include "chrome/browser/metrics/subprocess_metrics_provider.h" #include "chrome/browser/previews/previews_lite_page_decider.h" -#include "chrome/browser/previews/previews_lite_page_navigation_throttle.h" #include "chrome/browser/previews/previews_lite_page_url_loader_interceptor.h" #include "chrome/browser/previews/previews_service.h" #include "chrome/browser/previews/previews_service_factory.h" @@ -307,7 +306,6 @@ scoped_feature_list_.InitWithFeatures( {previews::features::kPreviews, - previews::features::kHTTPSServerPreviewsUsingURLLoader, optimization_guide::features::kOptimizationHints, previews::features::kResourceLoadingHints, data_reduction_proxy::features:: @@ -437,9 +435,7 @@ const GURL virtual_url = entry->GetVirtualURL(); // The loaded url should be the previews version of the virtual url. - EXPECT_EQ( - loaded_url, - PreviewsLitePageNavigationThrottle::GetPreviewsURLForURL(virtual_url)); + EXPECT_EQ(loaded_url, previews::GetLitePageRedirectURLForURL(virtual_url)); EXPECT_FALSE(virtual_url.DomainIs(previews_server_url().host()) && virtual_url.EffectiveIntPort() == @@ -1017,8 +1013,8 @@ // server. base::HistogramTester histogram_tester; ui_test_utils::NavigateToURL( - browser(), PreviewsLitePageNavigationThrottle::GetPreviewsURLForURL( - HttpsLitePageURL(kSuccess))); + browser(), + previews::GetLitePageRedirectURLForURL(HttpsLitePageURL(kSuccess))); VerifyPreviewNotLoaded(); } @@ -1427,8 +1423,7 @@ { base::RunLoop loop; history_service->QueryURL( - PreviewsLitePageNavigationThrottle::GetPreviewsURLForURL( - HttpsLitePageURL(kSuccess)), + previews::GetLitePageRedirectURLForURL(HttpsLitePageURL(kSuccess)), false /* want_visits */, base::BindLambdaForTesting([&](history::QueryURLResult result) { EXPECT_FALSE(result.success); @@ -1559,8 +1554,7 @@ } ] )text", - PreviewsLitePageNavigationThrottle::GetPreviewsURLForURL( - HttpsLitePageURL(kSuccess)) + previews::GetLitePageRedirectURLForURL(HttpsLitePageURL(kSuccess)) .spec() .c_str()));
diff --git a/chrome/browser/previews/previews_lite_page_decider.cc b/chrome/browser/previews/previews_lite_page_decider.cc index 1be6316..fa883e07 100644 --- a/chrome/browser/previews/previews_lite_page_decider.cc +++ b/chrome/browser/previews/previews_lite_page_decider.cc
@@ -18,7 +18,6 @@ #include "chrome/browser/predictors/loading_predictor.h" #include "chrome/browser/predictors/loading_predictor_factory.h" #include "chrome/browser/previews/previews_lite_page_infobar_delegate.h" -#include "chrome/browser/previews/previews_lite_page_navigation_throttle.h" #include "chrome/browser/previews/previews_service.h" #include "chrome/browser/previews/previews_service_factory.h" #include "chrome/browser/previews/previews_ui_tab_helper.h"
diff --git a/chrome/browser/previews/previews_lite_page_navigation_throttle.cc b/chrome/browser/previews/previews_lite_page_navigation_throttle.cc deleted file mode 100644 index 0446820f..0000000 --- a/chrome/browser/previews/previews_lite_page_navigation_throttle.cc +++ /dev/null
@@ -1,152 +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 "chrome/browser/previews/previews_lite_page_navigation_throttle.h" - -#include <stdint.h> -#include <string> - -#include "base/metrics/histogram_macros.h" -#include "base/optional.h" -#include "base/strings/safe_sprintf.h" -#include "base/strings/string_number_conversions.h" -#include "base/strings/string_util.h" -#include "base/strings/stringprintf.h" -#include "base/time/time.h" -#include "chrome/browser/data_reduction_proxy/data_reduction_proxy_chrome_settings.h" -#include "chrome/browser/data_reduction_proxy/data_reduction_proxy_chrome_settings_factory.h" -#include "chrome/browser/previews/previews_lite_page_decider.h" -#include "chrome/browser/previews/previews_ui_tab_helper.h" -#include "chrome/browser/renderer_host/chrome_navigation_ui_data.h" -#include "components/base32/base32.h" -#include "components/data_reduction_proxy/core/browser/data_reduction_proxy_request_options.h" -#include "components/data_reduction_proxy/core/common/data_reduction_proxy_headers.h" -#include "components/data_reduction_proxy/core/common/data_reduction_proxy_params.h" -#include "components/data_reduction_proxy/core/common/data_reduction_proxy_switches.h" -#include "components/previews/core/previews_experiments.h" -#include "components/previews/core/previews_lite_page_redirect.h" -#include "content/public/browser/browser_context.h" -#include "content/public/browser/navigation_handle.h" -#include "content/public/browser/web_contents.h" -#include "crypto/sha2.h" -#include "net/base/escape.h" -#include "net/base/url_util.h" -#include "net/http/http_util.h" - -bool HandlePreviewsLitePageURLRewrite( - GURL* url, - content::BrowserContext* browser_context) { - // Don't change the |url|, just register our interest in reversing it before - // it is displayed to the user in |HandlePreviewsLitePageURLRewriteReverse|. - // Without returning true here, |HandlePreviewsLitePageURLRewriteReverse| - // would not be called. - - auto* data_reduction_proxy_settings = - DataReductionProxyChromeSettingsFactory::GetForBrowserContext( - browser_context); - - if (!data_reduction_proxy_settings) - return false; - - return data_reduction_proxy_settings->IsDataReductionProxyEnabled() && - previews::params::IsLitePageServerPreviewsEnabled(); -} - -bool HandlePreviewsLitePageURLRewriteReverse( - GURL* url, - content::BrowserContext* browser_context) { - std::string original_url; - if (previews::ExtractOriginalURLFromLitePageRedirectURL(*url, - &original_url)) { - *url = GURL(original_url); - return true; - } - return false; -} - -// static -GURL PreviewsLitePageNavigationThrottle::GetPreviewsURLForURL( - const GURL& original_url) { - DCHECK(original_url.is_valid()); - const std::string experiment_id = - data_reduction_proxy::params::GetDataSaverServerExperiments(); - - std::string experiment_query; - if (!experiment_id.empty()) { - experiment_query = - "&x=" + net::EscapeQueryParamValue(experiment_id, true /* use_plus */); - } - std::string fragment; - if (original_url.has_ref()) { - fragment = "#" + original_url.ref(); - } - - // Strip out the fragment so that it is not sent to the server. - std::string origin_hash = base::ToLowerASCII(base32::Base32Encode( - crypto::SHA256HashString( - original_url.scheme() + "://" + original_url.host() + ":" + - base::NumberToString(original_url.EffectiveIntPort())), - base32::Base32EncodePolicy::OMIT_PADDING)); - GURL previews_host = previews::params::GetLitePagePreviewsDomainURL(); - GURL previews_url = GURL( - previews_host.scheme() + "://" + origin_hash + "." + - previews_host.host() + - (previews_host.has_port() ? (":" + previews_host.port()) : "") + "/p?u=" + - net::EscapeQueryParamValue(original_url.GetAsReferrer().spec(), - true /* use_plus */) + - experiment_query + fragment); - DCHECK(previews_url.is_valid()); - DCHECK_EQ(previews_host.scheme(), previews_url.scheme()); - return previews_url; -} - -// static -previews::PreviewsUserData::ServerLitePageInfo* -PreviewsLitePageNavigationThrottle::GetOrCreateServerLitePageInfo( - content::NavigationHandle* navigation_handle, - PreviewsLitePageDecider* decider) { - PreviewsUITabHelper* ui_tab_helper = - PreviewsUITabHelper::FromWebContents(navigation_handle->GetWebContents()); - if (!ui_tab_helper) - return nullptr; - - previews::PreviewsUserData* previews_data = - ui_tab_helper->GetPreviewsUserData(navigation_handle); - if (!previews_data) - return nullptr; - - if (previews_data->server_lite_page_info()) { - return previews_data->server_lite_page_info(); - } - - previews_data->set_server_lite_page_info( - std::make_unique<previews::PreviewsUserData::ServerLitePageInfo>()); - - DataReductionProxyChromeSettings* drp_settings = - DataReductionProxyChromeSettingsFactory::GetForBrowserContext( - navigation_handle->GetWebContents()->GetBrowserContext()); - base::Optional<std::string> session_id; - if (drp_settings) { - session_id = data_reduction_proxy::DataReductionProxyRequestOptions:: - GetSessionKeyFromRequestHeaders(drp_settings->GetProxyRequestHeaders()); - } - - previews::PreviewsUserData::ServerLitePageInfo* info = - previews_data->server_lite_page_info(); - info->original_navigation_start = navigation_handle->NavigationStart(); - if (session_id.has_value()) - info->drp_session_key = session_id.value(); - - const ChromeNavigationUIData* chrome_navigation_ui_data = - static_cast<const ChromeNavigationUIData*>( - navigation_handle->GetNavigationUIData()); - if (chrome_navigation_ui_data) - info->page_id = chrome_navigation_ui_data->data_reduction_proxy_page_id(); - // The page id may not be set in some corner cases (like forward navigation), - // so make sure it gets set here. - if (info->page_id == 0U) - info->page_id = decider->GeneratePageID(); - - return info; -}
diff --git a/chrome/browser/previews/previews_lite_page_navigation_throttle.h b/chrome/browser/previews/previews_lite_page_navigation_throttle.h deleted file mode 100644 index 8c76215..0000000 --- a/chrome/browser/previews/previews_lite_page_navigation_throttle.h +++ /dev/null
@@ -1,50 +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 CHROME_BROWSER_PREVIEWS_PREVIEWS_LITE_PAGE_NAVIGATION_THROTTLE_H_ -#define CHROME_BROWSER_PREVIEWS_PREVIEWS_LITE_PAGE_NAVIGATION_THROTTLE_H_ - -#include "components/previews/content/previews_user_data.h" -#include "content/public/browser/navigation_handle.h" -#include "url/gurl.h" - -namespace content { -class BrowserContext; -} // namespace content - -class PreviewsLitePageDecider; - -// If the given URL is a LitePage Preview URL, this returns true but does not -// change the |url|. This will set |update_virtual_url_with_url| on -// NavigationEntry so that |HandlePreviewsLitePageURLRewriteReverse| is called -// when the navigation finishes. -// Note: This means the virtual URL will not be set during the navigation load. -// This is handled separately in UI on Android. -bool HandlePreviewsLitePageURLRewrite(GURL* url, - content::BrowserContext* browser_context); - -// Handles translating the given Lite Page URL to the original URL. Returns true -// if the given |url| was a preview, otherwise returns false and does not change -// |url|. -bool HandlePreviewsLitePageURLRewriteReverse( - GURL* url, - content::BrowserContext* browser_context); - -class PreviewsLitePageNavigationThrottle { - public: - // Returns the URL for a preview given by the url. - static GURL GetPreviewsURLForURL(const GURL& original_url); - - // Gets the ServerLitePageInfo struct from an existing attempted lite page - // navigation, if there is one. If not, returns a new ServerLitePageInfo - // initialized with metadata from navigation_handle() and |this| that is owned - // by the PreviewsUserData associated with navigation_handle(). - static previews::PreviewsUserData::ServerLitePageInfo* - GetOrCreateServerLitePageInfo(content::NavigationHandle* navigation_handle, - PreviewsLitePageDecider* manager); - - DISALLOW_COPY_AND_ASSIGN(PreviewsLitePageNavigationThrottle); -}; - -#endif // CHROME_BROWSER_PREVIEWS_PREVIEWS_LITE_PAGE_NAVIGATION_THROTTLE_H_
diff --git a/chrome/browser/previews/previews_lite_page_navigation_throttle_unittest.cc b/chrome/browser/previews/previews_lite_page_navigation_throttle_unittest.cc deleted file mode 100644 index 286078e..0000000 --- a/chrome/browser/previews/previews_lite_page_navigation_throttle_unittest.cc +++ /dev/null
@@ -1,149 +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 "chrome/browser/previews/previews_lite_page_navigation_throttle.h" - -#include <map> -#include <memory> - -#include "base/command_line.h" -#include "base/memory/ptr_util.h" -#include "base/metrics/field_trial.h" -#include "base/metrics/field_trial_params.h" -#include "base/test/scoped_feature_list.h" -#include "base/test/task_environment.h" -#include "chrome/browser/previews/previews_lite_page_decider.h" -#include "chrome/test/base/chrome_render_view_host_test_harness.h" -#include "components/data_reduction_proxy/core/common/data_reduction_proxy_features.h" -#include "components/data_reduction_proxy/core/common/data_reduction_proxy_params.h" -#include "components/data_reduction_proxy/core/common/data_reduction_proxy_switches.h" -#include "components/previews/core/previews_features.h" -#include "components/variations/variations_associated_data.h" -#include "content/public/browser/navigation_handle.h" -#include "net/http/http_util.h" -#include "testing/gtest/include/gtest/gtest.h" -#include "url/gurl.h" - -TEST(PreviewsLitePageNavigationThrottleTest, TestGetPreviewsURL) { - struct TestCase { - std::string previews_host; - std::string original_url; - std::string expected_previews_url; - std::string experiment_variation; - std::string experiment_cmd_line; - }; - const TestCase kTestCases[]{ - // Use https://play.golang.org/p/HUM2HxmUTOW to compute - // |expected_previews_url|. - { - "https://previews.host.com", - "https://original.host.com/path/path/path?query=yes", - "https://shta44dh4bi7rc6fnpjnkrtytwlabygjhk53v2trlot2wddylwua." - "previews.host.com/p?u=" - "https%3A%2F%2Foriginal.host.com%2Fpath%2Fpath%2Fpath%3Fquery%3Dyes", - "", - "", - }, - { - "https://previews.host.com", - "http://original.host.com/path/path/path?query=yes", - "https://6p7dar4ju6r4ynz7x3pucmlcltuqsf7z5auhvckzln7voglkt56q." - "previews.host.com/p?u=" - "http%3A%2F%2Foriginal.host.com%2Fpath%2Fpath%2Fpath%3Fquery%3Dyes", - "", - }, - { - "https://previews.host.com", - "https://original.host.com:1443/path/path/path?query=yes", - "https://mil6oxtqb4zpsbmutm4d7wrx5nlr6tzlxjp7y44u55zqhzsdzjpq." - "previews.host.com/p?u=https%3A%2F%2Foriginal.host.com%3A1443" - "%2Fpath%2Fpath%2Fpath%3Fquery%3Dyes", - "", - "", - }, - { - "https://previews.host.com:1443", - "http://original.host.com/path/path/path?query=yes", - "https://6p7dar4ju6r4ynz7x3pucmlcltuqsf7z5auhvckzln7voglkt56q." - "previews.host.com:1443/p?u=" - "http%3A%2F%2Foriginal.host.com%2Fpath%2Fpath%2Fpath%3Fquery%3Dyes", - "", - "", - }, - { - "https://previews.host.com:1443", - "https://original.host.com:1443/path/path/path?query=yes", - "https://mil6oxtqb4zpsbmutm4d7wrx5nlr6tzlxjp7y44u55zqhzsdzjpq." - "previews.host.com:1443/p?u=https%3A%2F%2Foriginal.host.com%3A1443" - "%2Fpath%2Fpath%2Fpath%3Fquery%3Dyes", - "", - "", - }, - { - "https://previews.host.com", - "https://original.host.com/path/path/path?query=yes#fragment", - "https://shta44dh4bi7rc6fnpjnkrtytwlabygjhk53v2trlot2wddylwua." - "previews.host.com/p?u=" - "https%3A%2F%2Foriginal.host.com%2Fpath%2Fpath%2Fpath%3Fquery%3Dyes" - "#fragment", - "", - "", - }, - { - "https://previews.host.com", - "https://original.host.com/path/path/path?query=yes", - "https://shta44dh4bi7rc6fnpjnkrtytwlabygjhk53v2trlot2wddylwua." - "previews.host.com/p?u=" - "https%3A%2F%2Foriginal.host.com%2Fpath%2Fpath%2Fpath%3Fquery%3Dyes" - "&x=variation_experiment", - "variation_experiment", - "", - }, - { - // Ensure that the command line experiment takes precedence over the - // one provided by variations. - "https://previews.host.com", - "https://original.host.com/path/path/path?query=yes", - "https://shta44dh4bi7rc6fnpjnkrtytwlabygjhk53v2trlot2wddylwua." - "previews.host.com/p?u=" - "https%3A%2F%2Foriginal.host.com%2Fpath%2Fpath%2Fpath%3Fquery%3Dyes" - "&x=cmdline_experiment", - "variation_experiment", - "cmdline_experiment", - }, - { - "https://previews.host.com", - "https://[::1]:12345", - "https://2ikmbopbfxagkb7uer2vgfxmbzu2vw4qq3d3ixe3h2hfhgcabvua." - "previews.host.com/p?u=https%3A%2F%2F%5B%3A%3A1%5D%3A12345%2F", - "", - "", - }, - }; - - for (const TestCase& test_case : kTestCases) { - variations::testing::ClearAllVariationParams(); - - base::CommandLine::ForCurrentProcess()->AppendSwitchASCII( - data_reduction_proxy::switches::kDataReductionProxyExperiment, - test_case.experiment_cmd_line); - - base::test::ScopedFeatureList scoped_feature_list; - std::map<std::string, std::string> server_experiment_params; - server_experiment_params[data_reduction_proxy::params:: - GetDataSaverServerExperimentsOptionName()] = - test_case.experiment_variation; - - scoped_feature_list.InitWithFeaturesAndParameters( - {{data_reduction_proxy::features::kDataReductionProxyServerExperiments, - {server_experiment_params}}, - {previews::features::kLitePageServerPreviews, - {{"previews_host", test_case.previews_host}}}}, - {}); - - EXPECT_EQ(PreviewsLitePageNavigationThrottle::GetPreviewsURLForURL( - GURL(test_case.original_url)), - GURL(test_case.expected_previews_url)); - } -}
diff --git a/chrome/browser/previews/previews_lite_page_predictor.cc b/chrome/browser/previews/previews_lite_page_predictor.cc index 57eb008bb..0159478 100644 --- a/chrome/browser/previews/previews_lite_page_predictor.cc +++ b/chrome/browser/previews/previews_lite_page_predictor.cc
@@ -15,7 +15,7 @@ #include "chrome/browser/data_reduction_proxy/data_reduction_proxy_chrome_settings_factory.h" #include "chrome/browser/predictors/loading_predictor.h" #include "chrome/browser/predictors/loading_predictor_factory.h" -#include "chrome/browser/previews/previews_lite_page_navigation_throttle.h" +#include "chrome/browser/previews/previews_lite_page_url_loader_interceptor.h" #include "chrome/browser/previews/previews_service.h" #include "chrome/browser/previews/previews_service_factory.h" #include "chrome/browser/profiles/profile.h" @@ -157,7 +157,7 @@ if (previews::ExtractOriginalURLFromLitePageRedirectURL(url, &original_url)) return GURL(original_url); - return PreviewsLitePageNavigationThrottle::GetPreviewsURLForURL(url); + return previews::GetLitePageRedirectURLForURL(url); } void PreviewsLitePagePredictor::MaybeToggleTimer(
diff --git a/chrome/browser/previews/previews_lite_page_predictor_unittest.cc b/chrome/browser/previews/previews_lite_page_predictor_unittest.cc index 96f618f..cb38bb2 100644 --- a/chrome/browser/previews/previews_lite_page_predictor_unittest.cc +++ b/chrome/browser/previews/previews_lite_page_predictor_unittest.cc
@@ -8,7 +8,7 @@ #include "base/test/metrics/histogram_tester.h" #include "base/test/scoped_feature_list.h" -#include "chrome/browser/previews/previews_lite_page_navigation_throttle.h" +#include "chrome/browser/previews/previews_lite_page_url_loader_interceptor.h" #include "chrome/test/base/chrome_render_view_host_test_harness.h" #include "components/previews/core/previews_features.h" #include "content/public/browser/web_contents.h" @@ -143,8 +143,7 @@ content::WebContentsTester::For(web_contents()) ->NavigateAndCommit( - PreviewsLitePageNavigationThrottle::GetPreviewsURLForURL( - GURL(kTestUrl))); + previews::GetLitePageRedirectURLForURL(GURL(kTestUrl))); EXPECT_TRUE(predictor()->ShouldActOnPage(nullptr)); histogram_tester.ExpectUniqueSample( @@ -193,8 +192,7 @@ content::WebContentsTester::For(web_contents()) ->NavigateAndCommit( - PreviewsLitePageNavigationThrottle::GetPreviewsURLForURL( - GURL(kTestUrl))); + previews::GetLitePageRedirectURLForURL(GURL(kTestUrl))); EXPECT_TRUE(predictor()->ShouldActOnPage(nullptr)); }
diff --git a/chrome/browser/previews/previews_lite_page_redirect_url_loader.cc b/chrome/browser/previews/previews_lite_page_redirect_url_loader.cc index 024cf52..ddcb548 100644 --- a/chrome/browser/previews/previews_lite_page_redirect_url_loader.cc +++ b/chrome/browser/previews/previews_lite_page_redirect_url_loader.cc
@@ -10,7 +10,7 @@ #include "base/bind.h" #include "base/memory/ptr_util.h" #include "base/strings/stringprintf.h" -#include "chrome/browser/previews/previews_lite_page_navigation_throttle.h" +#include "chrome/browser/previews/previews_lite_page_url_loader_interceptor.h" #include "chrome/browser/profiles/profile.h" #include "components/previews/core/previews_experiments.h" #include "components/previews/core/previews_lite_page_redirect.h" @@ -132,8 +132,8 @@ DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_); GURL original_url = modified_resource_request_.url; - GURL lite_page_url = PreviewsLitePageNavigationThrottle::GetPreviewsURLForURL( - modified_resource_request_.url); + GURL lite_page_url = + GetLitePageRedirectURLForURL(modified_resource_request_.url); CreateRedirectInformation(lite_page_url);
diff --git a/chrome/browser/previews/previews_lite_page_url_loader_interceptor.cc b/chrome/browser/previews/previews_lite_page_url_loader_interceptor.cc index 8eaf20d..270bd7126d 100644 --- a/chrome/browser/previews/previews_lite_page_url_loader_interceptor.cc +++ b/chrome/browser/previews/previews_lite_page_url_loader_interceptor.cc
@@ -4,25 +4,45 @@ #include "chrome/browser/previews/previews_lite_page_url_loader_interceptor.h" +#include <stdint.h> #include <string> #include <utility> #include "base/bind.h" #include "base/metrics/histogram_macros.h" +#include "base/optional.h" #include "base/stl_util.h" +#include "base/strings/safe_sprintf.h" +#include "base/strings/string_number_conversions.h" +#include "base/strings/string_util.h" +#include "base/strings/stringprintf.h" +#include "base/time/time.h" #include "chrome/browser/data_reduction_proxy/data_reduction_proxy_chrome_settings.h" #include "chrome/browser/data_reduction_proxy/data_reduction_proxy_chrome_settings_factory.h" +#include "chrome/browser/previews/previews_lite_page_decider.h" +#include "chrome/browser/previews/previews_ui_tab_helper.h" #include "chrome/browser/profiles/profile_io_data.h" +#include "chrome/browser/renderer_host/chrome_navigation_ui_data.h" +#include "components/base32/base32.h" #include "components/data_reduction_proxy/core/browser/data_reduction_proxy_request_options.h" #include "components/data_reduction_proxy/core/browser/data_reduction_proxy_service.h" #include "components/data_reduction_proxy/core/common/data_reduction_proxy_headers.h" #include "components/data_reduction_proxy/core/common/data_reduction_proxy_params.h" +#include "components/data_reduction_proxy/core/common/data_reduction_proxy_switches.h" +#include "components/previews/core/previews_experiments.h" #include "components/previews/core/previews_features.h" #include "components/previews/core/previews_lite_page_redirect.h" +#include "content/public/browser/browser_context.h" #include "content/public/browser/browser_thread.h" +#include "content/public/browser/navigation_handle.h" +#include "content/public/browser/web_contents.h" #include "content/public/common/previews_state.h" #include "content/public/common/resource_type.h" +#include "crypto/sha2.h" +#include "net/base/escape.h" +#include "net/base/url_util.h" #include "net/http/http_request_headers.h" +#include "net/http/http_util.h" #include "net/nqe/effective_connection_type.h" namespace previews { @@ -83,6 +103,71 @@ reason); } +bool HandlePreviewsLitePageURLRewrite( + GURL* url, + content::BrowserContext* browser_context) { + // Don't change the |url|, just register our interest in reversing it before + // it is displayed to the user in |HandlePreviewsLitePageURLRewriteReverse|. + // Without returning true here, |HandlePreviewsLitePageURLRewriteReverse| + // would not be called. + + auto* data_reduction_proxy_settings = + DataReductionProxyChromeSettingsFactory::GetForBrowserContext( + browser_context); + + if (!data_reduction_proxy_settings) + return false; + + return data_reduction_proxy_settings->IsDataReductionProxyEnabled() && + previews::params::IsLitePageServerPreviewsEnabled(); +} + +bool HandlePreviewsLitePageURLRewriteReverse( + GURL* url, + content::BrowserContext* browser_context) { + std::string original_url; + if (previews::ExtractOriginalURLFromLitePageRedirectURL(*url, + &original_url)) { + *url = GURL(original_url); + return true; + } + return false; +} + +GURL GetLitePageRedirectURLForURL(const GURL& original_url) { + DCHECK(original_url.is_valid()); + const std::string experiment_id = + data_reduction_proxy::params::GetDataSaverServerExperiments(); + + std::string experiment_query; + if (!experiment_id.empty()) { + experiment_query = + "&x=" + net::EscapeQueryParamValue(experiment_id, true /* use_plus */); + } + std::string fragment; + if (original_url.has_ref()) { + fragment = "#" + original_url.ref(); + } + + // Strip out the fragment so that it is not sent to the server. + std::string origin_hash = base::ToLowerASCII(base32::Base32Encode( + crypto::SHA256HashString( + original_url.scheme() + "://" + original_url.host() + ":" + + base::NumberToString(original_url.EffectiveIntPort())), + base32::Base32EncodePolicy::OMIT_PADDING)); + GURL previews_host = previews::params::GetLitePagePreviewsDomainURL(); + GURL previews_url = GURL( + previews_host.scheme() + "://" + origin_hash + "." + + previews_host.host() + + (previews_host.has_port() ? (":" + previews_host.port()) : "") + "/p?u=" + + net::EscapeQueryParamValue(original_url.GetAsReferrer().spec(), + true /* use_plus */) + + experiment_query + fragment); + DCHECK(previews_url.is_valid()); + DCHECK_EQ(previews_host.scheme(), previews_url.scheme()); + return previews_url; +} + PreviewsLitePageURLLoaderInterceptor::PreviewsLitePageURLLoaderInterceptor( const scoped_refptr<network::SharedURLLoaderFactory>& network_loader_factory, @@ -94,6 +179,56 @@ PreviewsLitePageURLLoaderInterceptor::~PreviewsLitePageURLLoaderInterceptor() {} +// static +PreviewsUserData::ServerLitePageInfo* +PreviewsLitePageURLLoaderInterceptor::GetOrCreateServerLitePageInfo( + content::NavigationHandle* navigation_handle, + PreviewsLitePageDecider* decider) { + PreviewsUITabHelper* ui_tab_helper = + PreviewsUITabHelper::FromWebContents(navigation_handle->GetWebContents()); + if (!ui_tab_helper) + return nullptr; + + previews::PreviewsUserData* previews_data = + ui_tab_helper->GetPreviewsUserData(navigation_handle); + if (!previews_data) + return nullptr; + + if (previews_data->server_lite_page_info()) { + return previews_data->server_lite_page_info(); + } + + previews_data->set_server_lite_page_info( + std::make_unique<previews::PreviewsUserData::ServerLitePageInfo>()); + + DataReductionProxyChromeSettings* drp_settings = + DataReductionProxyChromeSettingsFactory::GetForBrowserContext( + navigation_handle->GetWebContents()->GetBrowserContext()); + base::Optional<std::string> session_id; + if (drp_settings) { + session_id = data_reduction_proxy::DataReductionProxyRequestOptions:: + GetSessionKeyFromRequestHeaders(drp_settings->GetProxyRequestHeaders()); + } + + previews::PreviewsUserData::ServerLitePageInfo* info = + previews_data->server_lite_page_info(); + info->original_navigation_start = navigation_handle->NavigationStart(); + if (session_id.has_value()) + info->drp_session_key = session_id.value(); + + const ChromeNavigationUIData* chrome_navigation_ui_data = + static_cast<const ChromeNavigationUIData*>( + navigation_handle->GetNavigationUIData()); + if (chrome_navigation_ui_data) + info->page_id = chrome_navigation_ui_data->data_reduction_proxy_page_id(); + // The page id may not be set in some corner cases (like forward navigation), + // so make sure it gets set here. + if (info->page_id == 0U) + info->page_id = decider->GeneratePageID(); + + return info; +} + void PreviewsLitePageURLLoaderInterceptor::MaybeCreateLoader( const network::ResourceRequest& tentative_resource_request, content::BrowserContext* browser_context,
diff --git a/chrome/browser/previews/previews_lite_page_url_loader_interceptor.h b/chrome/browser/previews/previews_lite_page_url_loader_interceptor.h index 7d2a0f3..9ecd2f46 100644 --- a/chrome/browser/previews/previews_lite_page_url_loader_interceptor.h +++ b/chrome/browser/previews/previews_lite_page_url_loader_interceptor.h
@@ -14,11 +14,19 @@ #include "base/sequence_checker.h" #include "chrome/browser/previews/previews_lite_page_redirect_url_loader.h" #include "chrome/browser/previews/previews_lite_page_serving_url_loader.h" +#include "components/previews/content/previews_user_data.h" #include "content/public/browser/url_loader_request_interceptor.h" #include "net/http/http_request_headers.h" #include "services/network/public/cpp/shared_url_loader_factory.h" #include "url/gurl.h" +namespace content { +class BrowserContext; +class NavigationHandle; +} // namespace content + +class PreviewsLitePageDecider; + namespace previews { // Reasons that a navigation is blacklisted from a lite page redirect preview. @@ -100,6 +108,25 @@ void LogLitePageRedirectIneligibleReason( LitePageRedirectIneligibleReason reason); +// If the given URL is a LitePage Preview URL, this returns true but does not +// change the |url|. This will set |update_virtual_url_with_url| on +// NavigationEntry so that |HandlePreviewsLitePageURLRewriteReverse| is called +// when the navigation finishes. +// Note: This means the virtual URL will not be set during the navigation load. +// This is handled separately in UI on Android. +bool HandlePreviewsLitePageURLRewrite(GURL* url, + content::BrowserContext* browser_context); + +// Handles translating the given Lite Page URL to the original URL. Returns true +// if the given |url| was a preview, otherwise returns false and does not change +// |url|. +bool HandlePreviewsLitePageURLRewriteReverse( + GURL* url, + content::BrowserContext* browser_context); + +// Returns the URL for a preview given by the url. +GURL GetLitePageRedirectURLForURL(const GURL& original_url); + // A class that attempts to intercept requests and fetch the Lite Page version // of the request. Its lifetime matches that of the content/ navigation loader // code. Currently, not fully implemented. @@ -113,6 +140,14 @@ int frame_tree_node_id); ~PreviewsLitePageURLLoaderInterceptor() override; + // Gets the ServerLitePageInfo struct from an existing attempted lite page + // navigation, if there is one. If not, returns a new ServerLitePageInfo + // initialized with metadata from navigation_handle() and |this| that is owned + // by the PreviewsUserData associated with navigation_handle(). + static PreviewsUserData::ServerLitePageInfo* GetOrCreateServerLitePageInfo( + content::NavigationHandle* navigation_handle, + PreviewsLitePageDecider* manager); + // content::URLLaoderRequestInterceptor: void MaybeCreateLoader( const network::ResourceRequest& tentative_resource_request,
diff --git a/chrome/browser/previews/previews_lite_page_url_loader_interceptor_unittest.cc b/chrome/browser/previews/previews_lite_page_url_loader_interceptor_unittest.cc index 6c750a4..4667d59 100644 --- a/chrome/browser/previews/previews_lite_page_url_loader_interceptor_unittest.cc +++ b/chrome/browser/previews/previews_lite_page_url_loader_interceptor_unittest.cc
@@ -4,27 +4,40 @@ #include "chrome/browser/previews/previews_lite_page_url_loader_interceptor.h" +#include <map> #include <memory> #include <string> #include "base/bind.h" +#include "base/command_line.h" +#include "base/memory/ptr_util.h" +#include "base/metrics/field_trial.h" +#include "base/metrics/field_trial_params.h" #include "base/optional.h" #include "base/run_loop.h" #include "base/test/metrics/histogram_tester.h" #include "base/test/scoped_feature_list.h" -#include "chrome/browser/previews/previews_lite_page_navigation_throttle.h" +#include "base/test/task_environment.h" +#include "chrome/browser/previews/previews_lite_page_decider.h" +#include "chrome/test/base/chrome_render_view_host_test_harness.h" +#include "components/data_reduction_proxy/core/common/data_reduction_proxy_features.h" +#include "components/data_reduction_proxy/core/common/data_reduction_proxy_params.h" +#include "components/data_reduction_proxy/core/common/data_reduction_proxy_switches.h" #include "components/previews/core/previews_features.h" +#include "components/variations/variations_associated_data.h" #include "content/public/browser/browser_thread.h" #include "content/public/browser/url_loader_request_interceptor.h" #include "content/public/common/previews_state.h" #include "content/public/common/resource_type.h" #include "content/public/test/browser_task_environment.h" #include "net/http/http_status_code.h" +#include "net/http/http_util.h" #include "net/url_request/url_request_status.h" #include "services/network/public/cpp/weak_wrapper_shared_url_loader_factory.h" #include "services/network/test/test_url_loader_factory.h" #include "services/network/test/test_utils.h" #include "testing/gtest/include/gtest/gtest.h" +#include "url/gurl.h" // TODO(crbug.com/961073): Fix memory leaks in tests and re-enable on LSAN. #ifdef LEAK_SANITIZER @@ -144,9 +157,8 @@ request.resource_type = static_cast<int>(content::ResourceType::kMainFrame); request.method = "GET"; - SetFakeResponse( - PreviewsLitePageNavigationThrottle::GetPreviewsURLForURL(request.url), - "Fake Body", net::HTTP_OK, net::URLRequestStatus::SUCCESS); + SetFakeResponse(GetLitePageRedirectURLForURL(request.url), "Fake Body", + net::HTTP_OK, net::URLRequestStatus::SUCCESS); SetProbeResponse(request.url.GetOrigin(), net::HTTP_OK, net::URLRequestStatus::SUCCESS); @@ -175,9 +187,8 @@ request.resource_type = static_cast<int>(content::ResourceType::kMainFrame); request.method = "GET"; - SetFakeResponse( - PreviewsLitePageNavigationThrottle::GetPreviewsURLForURL(request.url), - "Fake Body", net::HTTP_OK, net::URLRequestStatus::SUCCESS); + SetFakeResponse(GetLitePageRedirectURLForURL(request.url), "Fake Body", + net::HTTP_OK, net::URLRequestStatus::SUCCESS); SetProbeResponse(request.url.GetOrigin(), net::HTTP_OK, net::URLRequestStatus::FAILED); @@ -203,10 +214,8 @@ request.resource_type = static_cast<int>(content::ResourceType::kMainFrame); request.method = "GET"; request.previews_state = content::LITE_PAGE_REDIRECT_ON; - SetFakeResponse( - PreviewsLitePageNavigationThrottle::GetPreviewsURLForURL(request.url), - "Fake Body", net::HTTP_TEMPORARY_REDIRECT, - net::URLRequestStatus::SUCCESS); + SetFakeResponse(GetLitePageRedirectURLForURL(request.url), "Fake Body", + net::HTTP_TEMPORARY_REDIRECT, net::URLRequestStatus::SUCCESS); SetProbeResponse(request.url.GetOrigin(), net::HTTP_OK, net::URLRequestStatus::SUCCESS); @@ -230,10 +239,9 @@ request.resource_type = static_cast<int>(content::ResourceType::kMainFrame); request.method = "GET"; request.previews_state = content::LITE_PAGE_REDIRECT_ON; - SetFakeResponse( - PreviewsLitePageNavigationThrottle::GetPreviewsURLForURL(request.url), - "Fake Body", net::HTTP_SERVICE_UNAVAILABLE, - net::URLRequestStatus::SUCCESS); + SetFakeResponse(GetLitePageRedirectURLForURL(request.url), "Fake Body", + net::HTTP_SERVICE_UNAVAILABLE, + net::URLRequestStatus::SUCCESS); SetProbeResponse(request.url.GetOrigin(), net::HTTP_OK, net::URLRequestStatus::SUCCESS); @@ -258,9 +266,8 @@ request.resource_type = static_cast<int>(content::ResourceType::kMainFrame); request.method = "GET"; request.previews_state = content::LITE_PAGE_REDIRECT_ON; - SetFakeResponse( - PreviewsLitePageNavigationThrottle::GetPreviewsURLForURL(request.url), - "Fake Body", net::HTTP_FORBIDDEN, net::URLRequestStatus::SUCCESS); + SetFakeResponse(GetLitePageRedirectURLForURL(request.url), "Fake Body", + net::HTTP_FORBIDDEN, net::URLRequestStatus::SUCCESS); SetProbeResponse(request.url.GetOrigin(), net::HTTP_OK, net::URLRequestStatus::SUCCESS); @@ -284,9 +291,8 @@ request.resource_type = static_cast<int>(content::ResourceType::kMainFrame); request.method = "GET"; request.previews_state = content::LITE_PAGE_REDIRECT_ON; - SetFakeResponse( - PreviewsLitePageNavigationThrottle::GetPreviewsURLForURL(request.url), - "Fake Body", net::HTTP_OK, net::URLRequestStatus::FAILED); + SetFakeResponse(GetLitePageRedirectURLForURL(request.url), "Fake Body", + net::HTTP_OK, net::URLRequestStatus::FAILED); SetProbeResponse(request.url.GetOrigin(), net::HTTP_OK, net::URLRequestStatus::SUCCESS); @@ -303,6 +309,128 @@ EXPECT_TRUE(callback_was_empty().value()); } +TEST(PreviewsGetLitePageRedirectURL, TestGetPreviewsURL) { + struct TestCase { + std::string previews_host; + std::string original_url; + std::string expected_previews_url; + std::string experiment_variation; + std::string experiment_cmd_line; + }; + const TestCase kTestCases[]{ + // Use https://play.golang.org/p/HUM2HxmUTOW to compute + // |expected_previews_url|. + { + "https://previews.host.com", + "https://original.host.com/path/path/path?query=yes", + "https://shta44dh4bi7rc6fnpjnkrtytwlabygjhk53v2trlot2wddylwua." + "previews.host.com/p?u=" + "https%3A%2F%2Foriginal.host.com%2Fpath%2Fpath%2Fpath%3Fquery%3Dyes", + "", + "", + }, + { + "https://previews.host.com", + "http://original.host.com/path/path/path?query=yes", + "https://6p7dar4ju6r4ynz7x3pucmlcltuqsf7z5auhvckzln7voglkt56q." + "previews.host.com/p?u=" + "http%3A%2F%2Foriginal.host.com%2Fpath%2Fpath%2Fpath%3Fquery%3Dyes", + "", + }, + { + "https://previews.host.com", + "https://original.host.com:1443/path/path/path?query=yes", + "https://mil6oxtqb4zpsbmutm4d7wrx5nlr6tzlxjp7y44u55zqhzsdzjpq." + "previews.host.com/p?u=https%3A%2F%2Foriginal.host.com%3A1443" + "%2Fpath%2Fpath%2Fpath%3Fquery%3Dyes", + "", + "", + }, + { + "https://previews.host.com:1443", + "http://original.host.com/path/path/path?query=yes", + "https://6p7dar4ju6r4ynz7x3pucmlcltuqsf7z5auhvckzln7voglkt56q." + "previews.host.com:1443/p?u=" + "http%3A%2F%2Foriginal.host.com%2Fpath%2Fpath%2Fpath%3Fquery%3Dyes", + "", + "", + }, + { + "https://previews.host.com:1443", + "https://original.host.com:1443/path/path/path?query=yes", + "https://mil6oxtqb4zpsbmutm4d7wrx5nlr6tzlxjp7y44u55zqhzsdzjpq." + "previews.host.com:1443/p?u=https%3A%2F%2Foriginal.host.com%3A1443" + "%2Fpath%2Fpath%2Fpath%3Fquery%3Dyes", + "", + "", + }, + { + "https://previews.host.com", + "https://original.host.com/path/path/path?query=yes#fragment", + "https://shta44dh4bi7rc6fnpjnkrtytwlabygjhk53v2trlot2wddylwua." + "previews.host.com/p?u=" + "https%3A%2F%2Foriginal.host.com%2Fpath%2Fpath%2Fpath%3Fquery%3Dyes" + "#fragment", + "", + "", + }, + { + "https://previews.host.com", + "https://original.host.com/path/path/path?query=yes", + "https://shta44dh4bi7rc6fnpjnkrtytwlabygjhk53v2trlot2wddylwua." + "previews.host.com/p?u=" + "https%3A%2F%2Foriginal.host.com%2Fpath%2Fpath%2Fpath%3Fquery%3Dyes" + "&x=variation_experiment", + "variation_experiment", + "", + }, + { + // Ensure that the command line experiment takes precedence over the + // one provided by variations. + "https://previews.host.com", + "https://original.host.com/path/path/path?query=yes", + "https://shta44dh4bi7rc6fnpjnkrtytwlabygjhk53v2trlot2wddylwua." + "previews.host.com/p?u=" + "https%3A%2F%2Foriginal.host.com%2Fpath%2Fpath%2Fpath%3Fquery%3Dyes" + "&x=cmdline_experiment", + "variation_experiment", + "cmdline_experiment", + }, + { + "https://previews.host.com", + "https://[::1]:12345", + "https://2ikmbopbfxagkb7uer2vgfxmbzu2vw4qq3d3ixe3h2hfhgcabvua." + "previews.host.com/p?u=https%3A%2F%2F%5B%3A%3A1%5D%3A12345%2F", + "", + "", + }, + }; + + for (const TestCase& test_case : kTestCases) { + variations::testing::ClearAllVariationParams(); + + base::CommandLine::ForCurrentProcess()->AppendSwitchASCII( + data_reduction_proxy::switches::kDataReductionProxyExperiment, + test_case.experiment_cmd_line); + + base::test::ScopedFeatureList scoped_feature_list; + std::map<std::string, std::string> server_experiment_params; + server_experiment_params[data_reduction_proxy::params:: + GetDataSaverServerExperimentsOptionName()] = + test_case.experiment_variation; + + scoped_feature_list.InitWithFeaturesAndParameters( + {{data_reduction_proxy::features::kDataReductionProxyServerExperiments, + {server_experiment_params}}, + {previews::features::kLitePageServerPreviews, + {{"previews_host", test_case.previews_host}}}}, + {}); + + EXPECT_EQ(GetLitePageRedirectURLForURL(GURL(test_case.original_url)), + GURL(test_case.expected_previews_url)); + } +} + } // namespace } // namespace previews
diff --git a/chrome/browser/previews/previews_ui_tab_helper_unittest.cc b/chrome/browser/previews/previews_ui_tab_helper_unittest.cc index c2866ab..565fc31 100644 --- a/chrome/browser/previews/previews_ui_tab_helper_unittest.cc +++ b/chrome/browser/previews/previews_ui_tab_helper_unittest.cc
@@ -18,7 +18,7 @@ #include "chrome/browser/data_reduction_proxy/data_reduction_proxy_chrome_settings.h" #include "chrome/browser/data_reduction_proxy/data_reduction_proxy_chrome_settings_factory.h" #include "chrome/browser/previews/previews_https_notification_infobar_decider.h" -#include "chrome/browser/previews/previews_lite_page_navigation_throttle.h" +#include "chrome/browser/previews/previews_lite_page_url_loader_interceptor.h" #include "chrome/browser/previews/previews_service.h" #include "chrome/browser/previews/previews_service_factory.h" #include "chrome/test/base/chrome_render_view_host_test_harness.h" @@ -89,9 +89,7 @@ previews_user_data->SetCommittedPreviewsType(previews_type); } - void SimulateWillProcessResponse() { - SimulateCommit(); - } + void SimulateWillProcessResponse() { SimulateCommit(); } void SimulateCommit() { test_handle_->set_has_committed(true); @@ -326,8 +324,7 @@ base::RunLoop().RunUntilIdle(); GURL original_url("https://porgs.com"); - GURL previews_url = - PreviewsLitePageNavigationThrottle::GetPreviewsURLForURL(original_url); + GURL previews_url = previews::GetLitePageRedirectURLForURL(original_url); content::WebContentsTester::For(web_contents()) ->NavigateAndCommit(previews_url);
diff --git a/chrome/browser/resource_coordinator/local_site_characteristics_data_store.cc b/chrome/browser/resource_coordinator/local_site_characteristics_data_store.cc index 735c183..4db5771 100644 --- a/chrome/browser/resource_coordinator/local_site_characteristics_data_store.cc +++ b/chrome/browser/resource_coordinator/local_site_characteristics_data_store.cc
@@ -13,7 +13,6 @@ #include "chrome/browser/resource_coordinator/local_site_characteristics_data_reader.h" #include "chrome/browser/resource_coordinator/local_site_characteristics_data_writer.h" #include "chrome/browser/resource_coordinator/tab_manager_features.h" -#include "components/history/core/browser/history_service.h" #include "components/history/core/browser/url_row.h" #include "url/gurl.h" @@ -35,7 +34,7 @@ LocalSiteCharacteristicsDataStore::LocalSiteCharacteristicsDataStore( Profile* profile) - : history_observer_(this), profile_(profile) { + : profile_(profile) { DCHECK(base::FeatureList::IsEnabled(features::kSiteCharacteristicsDatabase)); database_ = std::make_unique<LevelDBSiteCharacteristicsDatabase>(
diff --git a/chrome/browser/resource_coordinator/local_site_characteristics_data_store.h b/chrome/browser/resource_coordinator/local_site_characteristics_data_store.h index 913a82f6..de68f331 100644 --- a/chrome/browser/resource_coordinator/local_site_characteristics_data_store.h +++ b/chrome/browser/resource_coordinator/local_site_characteristics_data_store.h
@@ -14,6 +14,7 @@ #include "chrome/browser/resource_coordinator/local_site_characteristics_data_store_inspector.h" #include "chrome/browser/resource_coordinator/site_characteristics_data_store.h" #include "chrome/browser/resource_coordinator/site_characteristics_data_writer.h" +#include "components/history/core/browser/history_service.h" #include "components/history/core/browser/history_service_observer.h" class Profile; @@ -97,8 +98,8 @@ // pointer. LocalSiteCharacteristicsMap origin_data_map_; - ScopedObserver<history::HistoryService, LocalSiteCharacteristicsDataStore> - history_observer_; + ScopedObserver<history::HistoryService, history::HistoryServiceObserver> + history_observer_{this}; std::unique_ptr<LocalSiteCharacteristicsDatabase> database_;
diff --git a/chrome/browser/resources/bookmarks/bookmarks.html b/chrome/browser/resources/bookmarks/bookmarks.html index 077405e..5e8532d2 100644 --- a/chrome/browser/resources/bookmarks/bookmarks.html +++ b/chrome/browser/resources/bookmarks/bookmarks.html
@@ -1,5 +1,6 @@ <!doctype html> -<html dir="$i18n{textdirection}" lang="$i18n{language}" class="loading"> +<html dir="$i18n{textdirection}" lang="$i18n{language}" class="loading" + $i18n{a11yenhanced}> <head> <meta charset="utf8"> <title>$i18n{title}</title>
diff --git a/chrome/browser/resources/bookmarks/item.html b/chrome/browser/resources/bookmarks/item.html index 9191430e..6543b57 100644 --- a/chrome/browser/resources/bookmarks/item.html +++ b/chrome/browser/resources/bookmarks/item.html
@@ -29,6 +29,10 @@ background-color: var(--highlight-color); } + :host([is-selected-item_]) cr-icon-button { + --cr-icon-button-focus-color: var(--highlight-color); + } + @media (prefers-color-scheme: dark) { :host([is-selected-item_]), :host([is-selected-item_]) .folder-icon { @@ -103,7 +107,7 @@ <div id="website-url" class="elided-text" title="[[item_.url]]"> [[item_.url]] </div> - <cr-icon-button class$="[[crIcon_]]" + <cr-icon-button class="icon-more-vert" id="menuButton" tabindex="[[ironListTabIndex]]" title="$i18n{moreActionsButtonTitle}"
diff --git a/chrome/browser/resources/bookmarks/item.js b/chrome/browser/resources/bookmarks/item.js index e2f0aa7..667e5de 100644 --- a/chrome/browser/resources/bookmarks/item.js +++ b/chrome/browser/resources/bookmarks/item.js
@@ -17,11 +17,6 @@ ironListTabIndex: Number, - crIcon_: { - type: String, - value: 'icon-more-vert', - }, - /** @private {BookmarkNode} */ item_: { type: Object, @@ -32,7 +27,6 @@ isSelectedItem_: { type: Boolean, reflectToAttribute: true, - observer: 'onIsSelectedItemChanged_', }, /** @private */ @@ -139,12 +133,6 @@ }, /** @private */ - onIsSelectedItemChanged_: function() { - this.crIcon_ = this.isSelectedItem_ ? 'icon-more-vert-light-mode' : - 'icon-more-vert'; - }, - - /** @private */ onItemIdChanged_: function() { // TODO(tsergeant): Add a histogram to measure whether this assertion fails // for real users.
diff --git a/chrome/browser/resources/chromeos/chromevox/chromevox/background/keymaps/next_keymap.json b/chrome/browser/resources/chromeos/chromevox/chromevox/background/keymaps/next_keymap.json index ddee7a20..972d1fb 100644 --- a/chrome/browser/resources/chromeos/chromevox/chromevox/background/keymaps/next_keymap.json +++ b/chrome/browser/resources/chromeos/chromevox/chromevox/background/keymaps/next_keymap.json
@@ -1014,6 +1014,15 @@ "keyCode": [65, 70] } } + }, + { + "command": "readPhoneticPronunciation", + "sequence": { + "cvoxModifier": true, + "keys": { + "keyCode": [65, 67] + } + } } ] }
diff --git a/chrome/browser/resources/chromeos/chromevox/common/command_store.js b/chrome/browser/resources/chromeos/chromevox/common/command_store.js index e0df7ed..957cbb8 100644 --- a/chrome/browser/resources/chromeos/chromevox/common/command_store.js +++ b/chrome/browser/resources/chromeos/chromevox/common/command_store.js
@@ -132,11 +132,8 @@ * false. */ cvox.CommandStore.CMD_WHITELIST = { - 'toggleStickyMode': { - announce: false, - msgId: 'toggle_sticky_mode', - category: 'modifier_keys' - }, + 'toggleStickyMode': + {announce: false, msgId: 'toggle_sticky_mode', category: 'modifier_keys'}, 'passThroughMode': { announce: false, msgId: 'pass_through_key_description', @@ -819,6 +816,12 @@ 'pauseAllMedia': {announce: false, msgId: 'pause_all_media', category: 'information'}, + 'readPhoneticPronunciation': { + announce: true, + msgId: 'read_phonetic_pronunciation', + category: 'information' + }, + // Scrolling actions. 'scrollBackward': {msgId: 'action_scroll_backward_description'}, 'scrollForward': {msgId: 'action_scroll_forward_description'},
diff --git a/chrome/browser/resources/chromeos/chromevox/cvox2/background/background_test.extjs b/chrome/browser/resources/chromeos/chromevox/cvox2/background/background_test.extjs index bf2d058..97b10d5 100644 --- a/chrome/browser/resources/chromeos/chromevox/cvox2/background/background_test.extjs +++ b/chrome/browser/resources/chromeos/chromevox/cvox2/background/background_test.extjs
@@ -1990,7 +1990,6 @@ var button = document.getElementById('button'); var expanded = false; button.addEventListener('click', function(e) { - console.error('Heelooo'); if (expanded) button.setAttribute('aria-expanded', false); else @@ -2018,3 +2017,47 @@ .replay(); }); }); + +TEST_F('ChromeVoxBackgroundTest', 'ReadPhoneticPronunciationTest', function() { + var mockFeedback = this.createMockFeedback(); + this.runWithLoadedTree(function() {/*! + <button>This is a button</button> + <input type="text"></input> + */}, function(root) { + root.find({role: RoleType.BUTTON}).focus(); + mockFeedback.call(doCmd('readPhoneticPronunciation')) + .expectSpeech('T') + .expectSpeech('tango') + .expectSpeech('h') + .expectSpeech('hotel') + .expectSpeech('i') + .expectSpeech('india') + .expectSpeech('s') + .expectSpeech('sierra') + .call(doCmd('nextWord')) + .call(doCmd('readPhoneticPronunciation')) + .expectSpeech('i') + .expectSpeech('india') + .expectSpeech('s') + .expectSpeech('sierra') + .call(doCmd('nextWord')) + .call(doCmd('nextWord')) + .call(doCmd('readPhoneticPronunciation')) + .expectSpeech('b') + .expectSpeech('bravo') + .expectSpeech('u') + .expectSpeech('uniform') + .expectSpeech('t') + .expectSpeech('tango') + .expectSpeech('t') + .expectSpeech('tango') + .expectSpeech('o') + .expectSpeech('oscar') + .expectSpeech('n') + .expectSpeech('november') + .call(doCmd('nextEditText')) + .call(doCmd('readPhoneticPronunciation')) + .expectSpeech('No available text for this item'); + mockFeedback.replay(); + }); +});
diff --git a/chrome/browser/resources/chromeos/chromevox/cvox2/background/command_handler.js b/chrome/browser/resources/chromeos/chromevox/cvox2/background/command_handler.js index ce199d0..5a5c944 100644 --- a/chrome/browser/resources/chromeos/chromevox/cvox2/background/command_handler.js +++ b/chrome/browser/resources/chromeos/chromevox/cvox2/background/command_handler.js
@@ -9,15 +9,16 @@ goog.provide('CommandHandler'); goog.require('ChromeVoxState'); +goog.require('Color'); goog.require('CustomAutomationEvent'); goog.require('LogStore'); goog.require('Output'); +goog.require('PhoneticData'); goog.require('TreeDumper'); goog.require('cvox.ChromeVoxBackground'); goog.require('cvox.ChromeVoxKbHandler'); goog.require('cvox.ChromeVoxPrefs'); goog.require('cvox.CommandStore'); -goog.require('Color'); goog.scope(function() { var AutomationEvent = chrome.automation.AutomationEvent; @@ -896,6 +897,65 @@ .withQueueMode(cvox.QueueMode.CATEGORY_FLUSH) .go(); return false; + case 'readPhoneticPronunciation': + // Get node info. + var node = ChromeVoxState.instance.currentRange.start.node; + var index = ChromeVoxState.instance.currentRange.start.index; + var text = node.name; + // If there is no text to speak, inform the user and return early. + if (!text) { + new Output() + .withString(Msgs.getMsg('empty_name')) + .withQueueMode(cvox.QueueMode.CATEGORY_FLUSH) + .go(); + return false; + } + + // Get word start and end indices. + var wordStarts, wordEnds; + if (node.role == RoleType.INLINE_TEXT_BOX) { + wordStarts = node.wordStarts; + wordEnds = node.wordEnds; + } else { + wordStarts = node.nonInlineTextWordStarts; + wordEnds = node.nonInlineTextWordEnds; + } + // Find the word we want to speak phonetically. If index === -1, then the + // index represents an entire node. If that is the case, we want to find + // the first word in the node's name. We do this by setting index to 0. + if (index === -1) + index = 0; + var word = ''; + for (var z = 0; z < wordStarts.length; ++z) { + if (wordStarts[z] <= index && wordEnds[z] >= index) { + word = text.substring(wordStarts[z], wordEnds[z]); + break; + } + } + + // Get unicode-aware array of characters. + var characterArray = [...word]; + // We currently only load phonetic data for the browser UI language. + var language = chrome.i18n.getUILanguage(); + for (var i = 0; i < characterArray.length; ++i) { + var character = characterArray[i]; + var phoneticText = + PhoneticData.getPhoneticDisambiguation(language, character); + // Speak the character followed by its phonetic disambiguation, if it + // was found. + new Output() + .withString(character) + .withQueueMode( + i === 0 ? cvox.QueueMode.CATEGORY_FLUSH : cvox.QueueMode.QUEUE) + .go(); + if (phoneticText) { + new Output() + .withString(phoneticText) + .withQueueMode(cvox.QueueMode.QUEUE) + .go(); + } + } + return false; default: return true; }
diff --git a/chrome/browser/resources/chromeos/chromevox/cvox2/background/phonetic_data.js b/chrome/browser/resources/chromeos/chromevox/cvox2/background/phonetic_data.js index 55e6b91c..7bd54868 100644 --- a/chrome/browser/resources/chromeos/chromevox/cvox2/background/phonetic_data.js +++ b/chrome/browser/resources/chromeos/chromevox/cvox2/background/phonetic_data.js
@@ -49,9 +49,10 @@ * @return {string} */ PhoneticData.getPhoneticDisambiguation = function(language, character) { - if (!language) + if (!language || !character) return ''; language = language.toLowerCase(); + character = character.toLowerCase(); // If language isn't in the map, try stripping extra information, such as the // country and/or script codes (e.g. "en-us" or "zh-hant-hk") and use only the // language code to do a lookup.
diff --git a/chrome/browser/resources/chromeos/chromevox/strings/chromevox_strings.grd b/chrome/browser/resources/chromeos/chromevox/strings/chromevox_strings.grd index f9a2d552..8665039 100644 --- a/chrome/browser/resources/chromeos/chromevox/strings/chromevox_strings.grd +++ b/chrome/browser/resources/chromeos/chromevox/strings/chromevox_strings.grd
@@ -3709,6 +3709,12 @@ <message desc="Appends language in front of content." name="IDS_CHROMEVOX_LANGUAGE_SWITCH"> <ph name="language">$1<ex>English</ex></ph>: <ph name="content">$2<ex>This is example content</ex></ph> </message> + <message desc="The description of the readPhoneticPronunciation key. Displayed in the ChromeVox menu." name="IDS_CHROMEVOX_READ_PHONETIC_PRONUNCIATION"> + Announce phonetic pronunciation for word + </message> + <message desc="Spoken to inform the user that the node's name is empty" name="IDS_CHROMEVOX_EMPTY_NAME"> + No available text for this item + </message> </messages> </release> </grit>
diff --git a/chrome/browser/resources/chromeos/network_ui/network_ui.js b/chrome/browser/resources/chromeos/network_ui/network_ui.js index 25e9371b..f2178ab 100644 --- a/chrome/browser/resources/chromeos/network_ui/network_ui.js +++ b/chrome/browser/resources/chromeos/network_ui/network_ui.js
@@ -388,7 +388,9 @@ */ const handleDeviceDetail = function(state, selectedId, detailCell) { if (selectedId == 'shill') { - chrome.send('getShillDeviceProperties', [state.type]); + chrome.send( + 'getShillDeviceProperties', + [OncMojo.getNetworkTypeString(state.type)]); } else { showDetail(detailCell, state); }
diff --git a/chrome/browser/resources/downloads/downloads.html b/chrome/browser/resources/downloads/downloads.html index ad88272..5e09e70 100644 --- a/chrome/browser/resources/downloads/downloads.html +++ b/chrome/browser/resources/downloads/downloads.html
@@ -1,5 +1,6 @@ <!doctype html> -<html dir="$i18n{textdirection}" lang="$i18n{language}" class="loading"> +<html dir="$i18n{textdirection}" lang="$i18n{language}" class="loading" + $i18n{a11yenhanced}> <head> <meta charset="utf-8"> <if expr="not optimize_webui">
diff --git a/chrome/browser/resources/extensions/extensions.html b/chrome/browser/resources/extensions/extensions.html index 83ea4fe72..c94fc08 100644 --- a/chrome/browser/resources/extensions/extensions.html +++ b/chrome/browser/resources/extensions/extensions.html
@@ -1,6 +1,6 @@ <!doctype html> <html dir="$i18n{textdirection}" lang="$i18n{language}" - class="loading $i18n{loadTimeClasses}"> + class="loading $i18n{loadTimeClasses}" $i18n{a11yenhanced}> <head> <meta charset="utf8"> <title>$i18n{title}</title>
diff --git a/chrome/browser/resources/history/history.html b/chrome/browser/resources/history/history.html index af0c23e..5fd5f3c 100644 --- a/chrome/browser/resources/history/history.html +++ b/chrome/browser/resources/history/history.html
@@ -1,5 +1,5 @@ <!doctype html> -<html dir="$i18n{textdirection}" lang="$i18n{language}"> +<html dir="$i18n{textdirection}" lang="$i18n{language}" $i18n{a11yenhanced}> <head> <meta charset="utf8"> <title>$i18n{title}</title>
diff --git a/chrome/browser/resources/history/shared_vars.html b/chrome/browser/resources/history/shared_vars.html index ba04f03..ade6397 100644 --- a/chrome/browser/resources/history/shared_vars.html +++ b/chrome/browser/resources/history/shared_vars.html
@@ -23,8 +23,6 @@ --history-item-time-color: #646464; --interactive-color: var(--google-blue-500); --item-height: 44px; - --iron-icon-height: var(--cr-icon-size); - --iron-icon-width: var(--cr-icon-size); --separator-color: rgba(0, 0, 0, 0.08); --side-bar-width: 256px; --sidebar-footer-text-color: var(--google-grey-refresh-700);
diff --git a/chrome/browser/resources/pdf/elements/viewer-zoom-button.html b/chrome/browser/resources/pdf/elements/viewer-zoom-button.html index 000d098..b104fb7 100644 --- a/chrome/browser/resources/pdf/elements/viewer-zoom-button.html +++ b/chrome/browser/resources/pdf/elements/viewer-zoom-button.html
@@ -31,11 +31,12 @@ } cr-icon-button { - --cr-icon-button-size: 36px; + --cr-icon-button-color: var(--paper-grey-700); --cr-icon-button-icon-size: 20px; + --cr-icon-button-size: 36px; + --cr-icon-button-focus-color: rgb(242, 242, 242); background-color: rgb(242, 242, 242); border-radius: 50%; - color: var(--paper-grey-700); overflow: visible; @apply --shadow-elevation-2dp; } @@ -49,9 +50,10 @@ } :host([new-print-preview]) cr-icon-button { + --cr-icon-button-color: white; + --cr-icon-button-focus-color: var(--google-grey-600); --cr-icon-button-size: 32px; background-color: var(--google-grey-600); - color: white; } @media (prefers-color-scheme: light) { @@ -62,8 +64,9 @@ @media (prefers-color-scheme: dark) { :host([new-print-preview]) cr-icon-button { + --cr-icon-button-color: var(--google-grey-200); + --cr-icon-button-focus-color: var(--google-grey-900); background-color: var(--google-grey-900); - color: var(--google-grey-200); } }
diff --git a/chrome/browser/resources/pdf/index.html b/chrome/browser/resources/pdf/index.html index 00d9643..3ddf279 100644 --- a/chrome/browser/resources/pdf/index.html +++ b/chrome/browser/resources/pdf/index.html
@@ -1,5 +1,5 @@ <!doctype html> -<html> +<html $i18n{a11yenhanced}> <head> <meta charset="utf-8"> <script src="chrome://resources/polymer/v1_0/html-imports/html-imports.min.js">
diff --git a/chrome/browser/resources/print_preview/print_preview.html b/chrome/browser/resources/print_preview/print_preview.html index d0e4cf1..b29f602 100644 --- a/chrome/browser/resources/print_preview/print_preview.html +++ b/chrome/browser/resources/print_preview/print_preview.html
@@ -1,6 +1,6 @@ <!doctype html> <html dir="$i18n{textdirection}" lang="$i18n{language}" class="loading" - $i18n{newprintpreviewlayout}> + $i18n{newprintpreviewlayout} $i18n{a11yenhanced}> <head> <meta charset="utf-8"> <if expr="not optimize_webui">
diff --git a/chrome/browser/resources/print_preview/ui/link_container.html b/chrome/browser/resources/print_preview/ui/link_container.html index 3268cb4..2f9274b 100644 --- a/chrome/browser/resources/print_preview/ui/link_container.html +++ b/chrome/browser/resources/print_preview/ui/link_container.html
@@ -62,7 +62,7 @@ hidden$="[[!shouldShowSystemDialogLink_]]" on-click="onSystemDialogClick_"> <div class="label">$i18n{systemDialogOption}</div> - <cr-icon-button actionable class="icon-external" + <cr-icon-button class="icon-external" hidden$="[[openingSystemDialog_]]" disabled="[[systemDialogLinkDisabled_]]" aria-label="$i18n{systemDialogOption}"></cr-icon-button> @@ -73,7 +73,7 @@ <div class="link" id="openPdfInPreviewLink" actionable$="[[!disabled]]" on-click="onOpenInPreviewClick_"> <div class="label">$i18n{openPdfInPreviewOption}</div> - <cr-icon-button actionable class="icon-external" + <cr-icon-button class="icon-external" hidden$="[[openingInPreview_]]" disabled="[[disabled]]" aria-label="$i18n{openPdfInPreviewOption}"></cr-icon-button> <div id="openPdfInPreviewThrobber" hidden$="[[!openingInPreview_]]"
diff --git a/chrome/browser/resources/print_preview/ui/print_preview_vars_css.html b/chrome/browser/resources/print_preview/ui/print_preview_vars_css.html index fd217ed..cf7801b 100644 --- a/chrome/browser/resources/print_preview/ui/print_preview_vars_css.html +++ b/chrome/browser/resources/print_preview/ui/print_preview_vars_css.html
@@ -22,6 +22,10 @@ --destination-item-height: 32px; --preview-area-background-color: var(--google-grey-200); --preview-area-background-color-new: var(--google-grey-refresh-300); + + --iron-icon-fill-color: var(--google-grey-refresh-700); + --iron-icon-height: var(--cr-icon-size); + --iron-icon-width: var(--cr-icon-size); } @media (prefers-color-scheme: dark) { @@ -32,6 +36,7 @@ opacity: var(--cr-disabled-opacity); } --print-preview-settings-border: var(--cr-separator-line); + --iron-icon-fill-color: var(--google-grey-refresh-500); } } </style>
diff --git a/chrome/browser/resources/settings/a11y_page/manage_a11y_page.html b/chrome/browser/resources/settings/a11y_page/manage_a11y_page.html index 92bf3fb3..61c356c 100644 --- a/chrome/browser/resources/settings/a11y_page/manage_a11y_page.html +++ b/chrome/browser/resources/settings/a11y_page/manage_a11y_page.html
@@ -241,7 +241,7 @@ $i18n{a11yWebStore} </div> </div> - <cr-icon-button actionable class="icon-external" + <cr-icon-button class="icon-external" aria-label="$i18n{additionalFeaturesTitle}" aria-describedby="moreFeaturesSecondary"></cr-icon-button> </a>
diff --git a/chrome/browser/resources/settings/android_apps_page/android_apps_subpage.html b/chrome/browser/resources/settings/android_apps_page/android_apps_subpage.html index b7df5505..601a93b 100644 --- a/chrome/browser/resources/settings/android_apps_page/android_apps_subpage.html +++ b/chrome/browser/resources/settings/android_apps_page/android_apps_subpage.html
@@ -16,10 +16,8 @@ <style include="settings-shared"></style> <template is="dom-if" if="[[androidAppsInfo.settingsAppAvailable]]" restamp> - <cr-link-row id="manageApps" icon-class="icon-external" - label="$i18n{androidAppsManageApps}" - on-click="onManageAndroidAppsTap_" external> - </cr-link-row> + <cr-link-row id="manageApps" label="$i18n{androidAppsManageApps}" + on-click="onManageAndroidAppsTap_" external></cr-link-row> </template> <template is="dom-if" if="[[allowRemove_(prefs.arc.enabled.*)]]">
diff --git a/chrome/browser/resources/settings/autofill_page/autofill_section.html b/chrome/browser/resources/settings/autofill_page/autofill_section.html index d781462..e5dc1e7a 100644 --- a/chrome/browser/resources/settings/autofill_page/autofill_section.html +++ b/chrome/browser/resources/settings/autofill_page/autofill_section.html
@@ -73,7 +73,7 @@ </cr-icon-button> </template> <template is="dom-if" if="[[!item.metadata.isLocal]]"> - <cr-icon-button actionable class="icon-external" + <cr-icon-button class="icon-external" on-click="onRemoteEditAddressTap_"></cr-icon-button> </template> </div>
diff --git a/chrome/browser/resources/settings/autofill_page/credit_card_list_entry.html b/chrome/browser/resources/settings/autofill_page/credit_card_list_entry.html index 4f62b13e..1d3bbd05 100644 --- a/chrome/browser/resources/settings/autofill_page/credit_card_list_entry.html +++ b/chrome/browser/resources/settings/autofill_page/credit_card_list_entry.html
@@ -47,9 +47,8 @@ </cr-icon-button> </template> <template is="dom-if" if="[[!showDots_(creditCard.metadata)]]"> - <cr-icon-button actionable class="icon-external" - id="remoteCreditCardLink" on-click="onRemoteEditClick_"> - </cr-icon-button> + <cr-icon-button class="icon-external" id="remoteCreditCardLink" + on-click="onRemoteEditClick_"></cr-icon-button> </template> </div> </div>
diff --git a/chrome/browser/resources/settings/autofill_page/payments_section.html b/chrome/browser/resources/settings/autofill_page/payments_section.html index 5836b23..1de86d2a 100644 --- a/chrome/browser/resources/settings/autofill_page/payments_section.html +++ b/chrome/browser/resources/settings/autofill_page/payments_section.html
@@ -42,6 +42,19 @@ pref="{{prefs.autofill.credit_card_enabled}}"> </settings-toggle-button> <template is="dom-if" + if="[[isUserFIDOVerifiable_( + prefs.autofill.credit_card_enabled.value)]]"> + <settings-toggle-button + class="settings-box first" + id="autofillCreditCardFIDOAuthToggle" + aria-label="$i18n{creditCards}" no-extension-indicator + label="$i18n{enableCreditCardFIDOAuthLabel}" + sub-label="$i18n{enableCreditCardFIDOAuthSublabel}" + pref="{{prefs.autofill.credit_card_fido_auth_enabled}}" + on-click="setFIDOAuthenticationEnabledState_"> + </settings-toggle-button> + </template> + <template is="dom-if" if="[[prefs.autofill.credit_card_enabled.extensionId]]"> <div class="settings-box continuation"> <extension-controlled-indicator class="start"
diff --git a/chrome/browser/resources/settings/autofill_page/payments_section.js b/chrome/browser/resources/settings/autofill_page/payments_section.js index 03d51d2..ef245525 100644 --- a/chrome/browser/resources/settings/autofill_page/payments_section.js +++ b/chrome/browser/resources/settings/autofill_page/payments_section.js
@@ -51,6 +51,11 @@ * Logs that the server cards edit link was clicked. */ logServerCardLinkClicked() {} + + /** + * Enables FIDO authentication for card unmasking. + */ + setCreditCardFIDOAuthEnabledState(enabled) {} } /** @typedef {chrome.autofillPrivate.CreditCardEntry} */ @@ -100,6 +105,11 @@ logServerCardLinkClicked() { chrome.autofillPrivate.logServerCardLinkClicked(); } + + /** @override */ + setCreditCardFIDOAuthEnabledState(enabled) { + chrome.autofillPrivate.setCreditCardFIDOAuthEnabledState(enabled); + } } cr.addSingletonGetter(PaymentsManagerImpl); @@ -126,6 +136,18 @@ }, /** + * Set to true if user can be verified through FIDO authentication. + * @private + */ + userIsFIDOVerifiable_: { + type: Boolean, + value: function() { + return loadTimeData.getBoolean('userIsFIDOVerifiable'); + }, + readOnly: true, + }, + + /** * The model for any credit card related action menus or dialogs. * @private {?chrome.autofillPrivate.CreditCardEntry} */ @@ -311,6 +333,25 @@ }, /** + * @param {boolean} creditCardEnabled + * @return {boolean} Whether or not the user is verifiable through FIDO + * authentication. + * @private + */ + isUserFIDOVerifiable_: function(creditCardEnabled) { + return creditCardEnabled && this.userIsFIDOVerifiable_; + }, + + /** + * Listens for the enable-authentication event, and calls the private API. + * @private + */ + setFIDOAuthenticationEnabledState_: function() { + this.paymentsManager_.setCreditCardFIDOAuthEnabledState( + this.$$('#autofillCreditCardFIDOAuthToggle').checked); + }, + + /** * @param {!Array<!PaymentsManager.CreditCardEntry>} creditCards * @param {boolean} creditCardEnabled * @return {boolean} Whether to show the migration button.
diff --git a/chrome/browser/resources/settings/people_page/sync_page.html b/chrome/browser/resources/settings/people_page/sync_page.html index 51b1cf1..6e3caabc 100644 --- a/chrome/browser/resources/settings/people_page/sync_page.html +++ b/chrome/browser/resources/settings/people_page/sync_page.html
@@ -230,7 +230,7 @@ <div class="start settings-box-text"> $i18n{personalizeGoogleServicesTitle} </div> - <cr-icon-button actionable class="icon-external"></cr-icon-button> + <cr-icon-button class="icon-external"></cr-icon-button> </a> <a id="syncDashboardLink" @@ -241,7 +241,7 @@ <div class="start settings-box-text"> $i18n{manageSyncedDataTitle} </div> - <cr-icon-button actionable class="icon-external"></cr-icon-button> + <cr-icon-button class="icon-external"></cr-icon-button> </a> <div id="encryptionDescription"
diff --git a/chrome/browser/resources/settings/printing_page/cloud_printers.html b/chrome/browser/resources/settings/printing_page/cloud_printers.html index 21bcb4b..fb6f35b 100644 --- a/chrome/browser/resources/settings/printing_page/cloud_printers.html +++ b/chrome/browser/resources/settings/printing_page/cloud_printers.html
@@ -24,7 +24,7 @@ <div class="start"> $i18n{printingManageCloudPrintDevices} </div> - <cr-icon-button actionable class="icon-external" + <cr-icon-button class="icon-external" aria-label="$i18n{printingManageCloudPrintDevices}"></cr-icon-button> </a> </template>
diff --git a/chrome/browser/resources/settings/privacy_page/privacy_page.html b/chrome/browser/resources/settings/privacy_page/privacy_page.html index 11c6038..16dd75c 100644 --- a/chrome/browser/resources/settings/privacy_page/privacy_page.html +++ b/chrome/browser/resources/settings/privacy_page/privacy_page.html
@@ -445,7 +445,7 @@ target="_blank" href="https://www.macromedia.com/support/documentation/en/flashplayer/help/settings_manager07.html"> <div class="start">$i18n{adobeFlashStorage}</div> - <cr-icon-button actionable class="icon-external" + <cr-icon-button class="icon-external" aria-label="$i18n{adobeFlashStorage}"></cr-icon-button> </a> </if>
diff --git a/chrome/browser/resources/settings/settings.html b/chrome/browser/resources/settings/settings.html index 7842e79..55f5804 100644 --- a/chrome/browser/resources/settings/settings.html +++ b/chrome/browser/resources/settings/settings.html
@@ -1,5 +1,6 @@ <!doctype html> -<html dir="$i18n{textdirection}" lang="$i18n{language}" class="loading"> +<html dir="$i18n{textdirection}" lang="$i18n{language}" class="loading" + $i18n{a11yenhanced}> <head> <meta charset="utf-8"> <title>$i18n{settings}</title>
diff --git a/chrome/browser/resources/settings/settings_menu/settings_menu.html b/chrome/browser/resources/settings/settings_menu/settings_menu.html index 0bcf848..5f7a88b 100644 --- a/chrome/browser/resources/settings/settings_menu/settings_menu.html +++ b/chrome/browser/resources/settings/settings_menu/settings_menu.html
@@ -231,7 +231,7 @@ on-click="onExtensionsLinkClick_" title="$i18n{extensionsLinkTooltip}"> <span>$i18n{extensionsPageTitle}</span> - <iron-icon class="cr-icon icon-external" actionable></iron-icon> + <iron-icon icon="cr:open-in-new"></iron-icon> </a> <a id="about-menu" href="/help">$i18n{aboutPageTitle}</a> </iron-selector>
diff --git a/chrome/browser/resources/settings/site_settings_page/site_settings_page.html b/chrome/browser/resources/settings/site_settings_page/site_settings_page.html index b65889b..57afb03b 100644 --- a/chrome/browser/resources/settings/site_settings_page/site_settings_page.html +++ b/chrome/browser/resources/settings/site_settings_page/site_settings_page.html
@@ -193,7 +193,6 @@ <cr-link-row class="hr two-line" data-route="SITE_SETTINGS_SERIAL_PORTS" - icon-class="subpage-arrow" id="serial-ports" label="$i18n{siteSettingsSerialPorts}" on-click="onTapNavigate_" @@ -208,7 +207,7 @@ <template is="dom-if" if="[[enableNativeFileSystemWriteContentSetting_]]"> <cr-link-row class="hr two-line" data-route="SITE_SETTINGS_NATIVE_FILE_SYSTEM_WRITE" - icon-class="subpage-arrow" id="native-file-system-write" + id="native-file-system-write" label="$i18n{siteSettingsNativeFileSystemWrite}" on-click="onTapNavigate_" start-icon="settings:save-original" sub-label="[[defaultSettingLabel_(
diff --git a/chrome/browser/resources/tab_strip/tab.html b/chrome/browser/resources/tab_strip/tab.html index 8e3c886..2cd9c6d 100644 --- a/chrome/browser/resources/tab_strip/tab.html +++ b/chrome/browser/resources/tab_strip/tab.html
@@ -38,13 +38,47 @@ padding-inline-start: 12px; } - #favicon { + #faviconContainer { flex-shrink: 0; height: 16px; margin-inline-end: 8px; + position: relative; width: 16px; } + #loading, + #favicon { + height: 100%; + position: absolute; + width: 100%; + } + + #loading { + -webkit-mask-image: url(chrome://resources/images/throbber_small.svg); + background-color: var(--tabstrip-primary-text-color); + display: none; + } + + #favicon { + background-size: contain; + left: 50%; + top: 50%; + transform: translate(-50%, -50%); + transition: border-radius 250ms; + } + + :host([loading]) #loading, + :host([loading]) #favicon { + display: block; + } + + :host([loading]) #favicon { + border-radius: 50%; + height: calc(100% - 6px); + overflow: hidden; + width: calc(100% - 6px); + } + #titleText { font-size: 100%; font-weight: normal; @@ -135,7 +169,10 @@ <div id="dragImage"> <header id="title"> - <span id="favicon"></span> + <div id="faviconContainer"> + <div id="loading"></div> + <div id="favicon"></div> + </div> <h2 id="titleText"></h2> <button id="close"> <span id="closeIcon"></span>
diff --git a/chrome/browser/resources/tab_strip/tab.js b/chrome/browser/resources/tab_strip/tab.js index 77bbc41d..e302a2eb2 100644 --- a/chrome/browser/resources/tab_strip/tab.js +++ b/chrome/browser/resources/tab_strip/tab.js
@@ -9,6 +9,12 @@ export const DEFAULT_ANIMATION_DURATION = 125; +/** @const @enum {string} */ +const STATUS = { + LOADING: 'loading', + COMPLETE: 'complete', +}; + export class TabElement extends CustomElement { static get template() { return `{__html_template__}`; @@ -65,18 +71,29 @@ /** @param {!Tab} tab */ set tab(tab) { this.toggleAttribute('active', tab.active); + // TODO(johntlee): Update loading status to also be based on whether + // the tab is navigating to a new document. + this.toggleAttribute('loading', tab.status === STATUS.LOADING); this.toggleAttribute('pinned', tab.pinned); if (!this.tab_ || this.tab_.title !== tab.title) { this.titleTextEl_.textContent = tab.title; } - if (tab.favIconUrl && - (!this.tab_ || this.tab_.favIconUrl !== tab.favIconUrl)) { - this.faviconEl_.style.backgroundImage = getFavicon(tab.favIconUrl); - } else if (!this.tab_ || this.tab_.url !== tab.url) { - this.faviconEl_.style.backgroundImage = - getFaviconForPageURL(tab.url, false); + if (tab.favIconUrl) { + if (!this.tab_ || this.tab_.favIconUrl !== tab.favIconUrl) { + this.faviconEl_.style.backgroundImage = getFavicon(tab.favIconUrl); + } + } else { + if (tab.status === STATUS.COMPLETE) { + // If the tab has finished loading and there still is no favicon, + // fallback to a favicon generated by the page URL. This guarantees + // there is always some favicon, even if it's the default icon. + this.faviconEl_.style.backgroundImage = + getFaviconForPageURL(tab.url, false); + } else { + this.faviconEl_.style.backgroundImage = 'none'; + } } // Expose the ID to an attribute to allow easy querySelector use
diff --git a/chrome/browser/resources/tab_strip/tab_list.js b/chrome/browser/resources/tab_strip/tab_list.js index dd05244d..3b98eaa 100644 --- a/chrome/browser/resources/tab_strip/tab_list.js +++ b/chrome/browser/resources/tab_strip/tab_list.js
@@ -369,6 +369,15 @@ const tabElement = this.findTabElement_(tabId); if (tabElement) { + // While a tab may go in and out of a loading state, the Extensions API + // only dispatches |onUpdated| events up until the first time a tab + // reaches a non-loading state. Therefore, the UI should ignore any + // updates to a |status| of a tab unless the API specifically has + // dispatched an event indicating the status has changed. + if (!changeInfo.status) { + tab.status = tabElement.tab.status; + } + tabElement.tab = tab; if (changeInfo.pinned !== undefined) {
diff --git a/chrome/browser/safe_browsing/incident_reporting/last_download_finder.cc b/chrome/browser/safe_browsing/incident_reporting/last_download_finder.cc index 9f4ea6a..1270337 100644 --- a/chrome/browser/safe_browsing/incident_reporting/last_download_finder.cc +++ b/chrome/browser/safe_browsing/incident_reporting/last_download_finder.cc
@@ -26,7 +26,6 @@ #include "chrome/common/safe_browsing/download_type_util.h" #include "chrome/common/safe_browsing/file_type_policies.h" #include "components/history/core/browser/download_constants.h" -#include "components/history/core/browser/history_service.h" #include "components/language/core/browser/pref_names.h" #include "components/language/core/common/locale_util.h" #include "components/prefs/pref_service.h" @@ -257,15 +256,13 @@ return finder; } -LastDownloadFinder::LastDownloadFinder() : history_service_observer_(this) {} +LastDownloadFinder::LastDownloadFinder() = default; LastDownloadFinder::LastDownloadFinder( const DownloadDetailsGetter& download_details_getter, const std::vector<Profile*>& profiles, const LastDownloadCallback& callback) - : download_details_getter_(download_details_getter), - callback_(callback), - history_service_observer_(this) { + : download_details_getter_(download_details_getter), callback_(callback) { // Observe profile lifecycle events so that the finder can begin or abandon // the search in profiles while it is running. notification_registrar_.Add(this,
diff --git a/chrome/browser/safe_browsing/incident_reporting/last_download_finder.h b/chrome/browser/safe_browsing/incident_reporting/last_download_finder.h index bf06622..9b19395 100644 --- a/chrome/browser/safe_browsing/incident_reporting/last_download_finder.h +++ b/chrome/browser/safe_browsing/incident_reporting/last_download_finder.h
@@ -16,6 +16,7 @@ #include "base/scoped_observer.h" #include "chrome/browser/safe_browsing/incident_reporting/download_metadata_manager.h" #include "components/history/core/browser/download_row.h" +#include "components/history/core/browser/history_service.h" #include "components/history/core/browser/history_service_observer.h" #include "content/public/browser/notification_observer.h" #include "content/public/browser/notification_registrar.h" @@ -27,10 +28,6 @@ class NotificationSource; } -namespace history { -class HistoryService; -} - namespace safe_browsing { class ClientIncidentReport_DownloadDetails; @@ -149,7 +146,7 @@ // HistoryServiceObserver ScopedObserver<history::HistoryService, history::HistoryServiceObserver> - history_service_observer_; + history_service_observer_{this}; // A factory for asynchronous operations on profiles' HistoryService. base::WeakPtrFactory<LastDownloadFinder> weak_ptr_factory_{this};
diff --git a/chrome/browser/safe_browsing/safe_browsing_navigation_observer.cc b/chrome/browser/safe_browsing/safe_browsing_navigation_observer.cc index 20f17e9..8360f38 100644 --- a/chrome/browser/safe_browsing/safe_browsing_navigation_observer.cc +++ b/chrome/browser/safe_browsing/safe_browsing_navigation_observer.cc
@@ -14,7 +14,6 @@ #include "chrome/browser/safe_browsing/safe_browsing_service.h" #include "chrome/browser/sessions/session_tab_helper.h" #include "chrome/browser/ui/page_info/page_info_ui.h" -#include "components/content_settings/core/browser/host_content_settings_map.h" #include "content/public/browser/navigation_handle.h" #include "content/public/browser/render_frame_host.h" #include "content/public/browser/render_process_host.h" @@ -107,8 +106,7 @@ : content::WebContentsObserver(contents), manager_(manager), has_user_gesture_(false), - last_user_gesture_timestamp_(base::Time()), - content_settings_observer_(this) { + last_user_gesture_timestamp_(base::Time()) { content_settings_observer_.Add(HostContentSettingsMapFactory::GetForProfile( Profile::FromBrowserContext(web_contents()->GetBrowserContext()))); }
diff --git a/chrome/browser/safe_browsing/safe_browsing_navigation_observer.h b/chrome/browser/safe_browsing/safe_browsing_navigation_observer.h index d3bcfbe0..45f3542 100644 --- a/chrome/browser/safe_browsing/safe_browsing_navigation_observer.h +++ b/chrome/browser/safe_browsing/safe_browsing_navigation_observer.h
@@ -8,6 +8,7 @@ #include "base/scoped_observer.h" #include "base/supports_user_data.h" #include "components/content_settings/core/browser/content_settings_observer.h" +#include "components/content_settings/core/browser/host_content_settings_map.h" #include "components/content_settings/core/common/content_settings.h" #include "components/safe_browsing/proto/csd.pb.h" #include "components/sessions/core/session_id.h" @@ -18,8 +19,6 @@ class NavigationHandle; } -class HostContentSettingsMap; - namespace safe_browsing { class SafeBrowsingNavigationObserverManager; @@ -159,7 +158,7 @@ base::Time last_user_gesture_timestamp_; ScopedObserver<HostContentSettingsMap, content_settings::Observer> - content_settings_observer_; + content_settings_observer_{this}; DISALLOW_COPY_AND_ASSIGN(SafeBrowsingNavigationObserver); };
diff --git a/chrome/browser/search/instant_service.cc b/chrome/browser/search/instant_service.cc index c04aa723..49e945e 100644 --- a/chrome/browser/search/instant_service.cc +++ b/chrome/browser/search/instant_service.cc
@@ -20,7 +20,6 @@ #include "chrome/browser/image_fetcher/image_decoder_impl.h" #include "chrome/browser/ntp_tiles/chrome_most_visited_sites_factory.h" #include "chrome/browser/profiles/profile.h" -#include "chrome/browser/search/background/ntp_background_service.h" #include "chrome/browser/search/background/ntp_background_service_factory.h" #include "chrome/browser/search/chrome_colors/chrome_colors_service.h" #include "chrome/browser/search/instant_io_context.h" @@ -179,8 +178,6 @@ : profile_(profile), most_visited_info_(std::make_unique<InstantMostVisitedInfo>()), pref_service_(profile_->GetPrefs()), - theme_observer_(this), - background_service_observer_(this), native_theme_(ui::NativeTheme::GetInstanceForNativeUi()), background_updated_timestamp_(base::TimeTicks::Now()), clock_(base::DefaultClock::GetInstance()) {
diff --git a/chrome/browser/search/instant_service.h b/chrome/browser/search/instant_service.h index 8bbfbf6..a2de87f 100644 --- a/chrome/browser/search/instant_service.h +++ b/chrome/browser/search/instant_service.h
@@ -17,6 +17,7 @@ #include "base/observer_list.h" #include "base/optional.h" #include "build/build_config.h" +#include "chrome/browser/search/background/ntp_background_service.h" #include "chrome/browser/search/background/ntp_background_service_observer.h" #include "chrome/browser/search/search_provider_observer.h" #include "components/history/core/browser/history_types.h" @@ -38,7 +39,6 @@ class InstantIOContext; class InstantServiceObserver; -class NtpBackgroundService; class Profile; struct CollectionImage; struct InstantMostVisitedInfo; @@ -314,10 +314,11 @@ PrefService* pref_service_; - ScopedObserver<ui::NativeTheme, InstantService> theme_observer_; + ScopedObserver<ui::NativeTheme, ui::NativeThemeObserver> theme_observer_{ + this}; ScopedObserver<NtpBackgroundService, NtpBackgroundServiceObserver> - background_service_observer_; + background_service_observer_{this}; ui::NativeTheme* native_theme_;
diff --git a/chrome/browser/search/local_ntp_source.cc b/chrome/browser/search/local_ntp_source.cc index 1a7423b..0890a24 100644 --- a/chrome/browser/search/local_ntp_source.cc +++ b/chrome/browser/search/local_ntp_source.cc
@@ -27,20 +27,17 @@ #include "chrome/browser/browser_process.h" #include "chrome/browser/profiles/profile.h" #include "chrome/browser/search/background/ntp_background_data.h" -#include "chrome/browser/search/background/ntp_background_service.h" #include "chrome/browser/search/background/ntp_background_service_factory.h" #include "chrome/browser/search/instant_io_context.h" #include "chrome/browser/search/local_ntp_js_integrity.h" #include "chrome/browser/search/ntp_features.h" #include "chrome/browser/search/one_google_bar/one_google_bar_data.h" -#include "chrome/browser/search/one_google_bar/one_google_bar_service.h" #include "chrome/browser/search/one_google_bar/one_google_bar_service_factory.h" #include "chrome/browser/search/promos/promo_data.h" #include "chrome/browser/search/promos/promo_service.h" #include "chrome/browser/search/promos/promo_service_factory.h" #include "chrome/browser/search/search.h" #include "chrome/browser/search/search_suggest/search_suggest_data.h" -#include "chrome/browser/search/search_suggest/search_suggest_service.h" #include "chrome/browser/search/search_suggest/search_suggest_service_factory.h" #include "chrome/browser/search_engines/template_url_service_factory.h" #include "chrome/browser/search_provider_logos/logo_service_factory.h" @@ -771,15 +768,11 @@ : profile_(profile), ntp_background_service_( NtpBackgroundServiceFactory::GetForProfile(profile_)), - ntp_background_service_observer_(this), one_google_bar_service_( OneGoogleBarServiceFactory::GetForProfile(profile_)), - one_google_bar_service_observer_(this), promo_service_(PromoServiceFactory::GetForProfile(profile_)), - promo_service_observer_(this), search_suggest_service_( SearchSuggestServiceFactory::GetForProfile(profile_)), - search_suggest_service_observer_(this), logo_service_(nullptr) { DCHECK_CURRENTLY_ON(content::BrowserThread::UI);
diff --git a/chrome/browser/search/local_ntp_source.h b/chrome/browser/search/local_ntp_source.h index 91c6264..ad6ecead 100644 --- a/chrome/browser/search/local_ntp_source.h +++ b/chrome/browser/search/local_ntp_source.h
@@ -15,9 +15,13 @@ #include "base/scoped_observer.h" #include "base/time/time.h" #include "build/build_config.h" +#include "chrome/browser/search/background/ntp_background_service.h" #include "chrome/browser/search/background/ntp_background_service_observer.h" +#include "chrome/browser/search/one_google_bar/one_google_bar_service.h" #include "chrome/browser/search/one_google_bar/one_google_bar_service_observer.h" +#include "chrome/browser/search/promos/promo_service.h" #include "chrome/browser/search/promos/promo_service_observer.h" +#include "chrome/browser/search/search_suggest/search_suggest_service.h" #include "chrome/browser/search/search_suggest/search_suggest_service_observer.h" #include "components/prefs/pref_registry_simple.h" #include "content/public/browser/url_data_source.h" @@ -28,10 +32,6 @@ struct OneGoogleBarData; struct PromoData; -class NtpBackgroundService; -class OneGoogleBarService; -class PromoService; -class SearchSuggestService; class Profile; namespace search_provider_logos { @@ -137,7 +137,7 @@ NtpBackgroundService* ntp_background_service_; ScopedObserver<NtpBackgroundService, NtpBackgroundServiceObserver> - ntp_background_service_observer_; + ntp_background_service_observer_{this}; base::Optional<base::TimeTicks> pending_one_google_bar_request_; std::vector<content::URLDataSource::GotDataCallback> @@ -146,21 +146,22 @@ OneGoogleBarService* one_google_bar_service_; ScopedObserver<OneGoogleBarService, OneGoogleBarServiceObserver> - one_google_bar_service_observer_; + one_google_bar_service_observer_{this}; base::Optional<base::TimeTicks> pending_promo_request_; std::vector<content::URLDataSource::GotDataCallback> promo_callbacks_; PromoService* promo_service_; - ScopedObserver<PromoService, PromoServiceObserver> promo_service_observer_; + ScopedObserver<PromoService, PromoServiceObserver> promo_service_observer_{ + this}; base::Optional<base::TimeTicks> pending_search_suggest_request_; SearchSuggestService* search_suggest_service_; ScopedObserver<SearchSuggestService, SearchSuggestServiceObserver> - search_suggest_service_observer_; + search_suggest_service_observer_{this}; search_provider_logos::LogoService* logo_service_; std::unique_ptr<DesktopLogoObserver> logo_observer_;
diff --git a/chrome/browser/search/search_engine_base_url_tracker.cc b/chrome/browser/search/search_engine_base_url_tracker.cc index becc1ab..108e6f6 100644 --- a/chrome/browser/search/search_engine_base_url_tracker.cc +++ b/chrome/browser/search/search_engine_base_url_tracker.cc
@@ -6,7 +6,6 @@ #include "components/search_engines/search_terms_data.h" -#include "components/search_engines/template_url_service.h" SearchEngineBaseURLTracker::SearchEngineBaseURLTracker( TemplateURLService* template_url_service, @@ -15,7 +14,6 @@ : template_url_service_(template_url_service), search_terms_data_(std::move(search_terms_data)), base_url_changed_callback_(base_url_changed_callback), - observer_(this), previous_google_base_url_(search_terms_data_->GoogleBaseURLValue()) { DCHECK(template_url_service_);
diff --git a/chrome/browser/search/search_engine_base_url_tracker.h b/chrome/browser/search/search_engine_base_url_tracker.h index 81845969..78d34c6 100644 --- a/chrome/browser/search/search_engine_base_url_tracker.h +++ b/chrome/browser/search/search_engine_base_url_tracker.h
@@ -12,11 +12,11 @@ #include "base/optional.h" #include "base/scoped_observer.h" #include "components/search_engines/template_url_data.h" +#include "components/search_engines/template_url_service.h" #include "components/search_engines/template_url_service_observer.h" #include "url/gurl.h" class SearchTermsData; -class TemplateURLService; // A helper class that watches for changes to the base URL of the default search // engine. Typically this changes when a different DSE is selected. For Google, @@ -48,7 +48,8 @@ std::unique_ptr<SearchTermsData> search_terms_data_; BaseURLChangedCallback base_url_changed_callback_; - ScopedObserver<TemplateURLService, TemplateURLServiceObserver> observer_; + ScopedObserver<TemplateURLService, TemplateURLServiceObserver> observer_{ + this}; // Used to check whether notifications from TemplateURLService indicate a // change that affects the default search provider.
diff --git a/chrome/browser/search_engines/chrome_template_url_service_client.cc b/chrome/browser/search_engines/chrome_template_url_service_client.cc index 8de531d..8edade1 100644 --- a/chrome/browser/search_engines/chrome_template_url_service_client.cc +++ b/chrome/browser/search_engines/chrome_template_url_service_client.cc
@@ -4,13 +4,11 @@ #include "chrome/browser/search_engines/chrome_template_url_service_client.h" -#include "components/history/core/browser/history_service.h" #include "components/search_engines/template_url_service.h" ChromeTemplateURLServiceClient::ChromeTemplateURLServiceClient( history::HistoryService* history_service) : owner_(NULL), - history_service_observer_(this), history_service_(history_service) { // TODO(sky): bug 1166191. The keywords should be moved into the history // db, which will mean we no longer need this notification and the history
diff --git a/chrome/browser/search_engines/chrome_template_url_service_client.h b/chrome/browser/search_engines/chrome_template_url_service_client.h index 8d849393a..8505a559 100644 --- a/chrome/browser/search_engines/chrome_template_url_service_client.h +++ b/chrome/browser/search_engines/chrome_template_url_service_client.h
@@ -7,13 +7,10 @@ #include "base/macros.h" #include "base/scoped_observer.h" +#include "components/history/core/browser/history_service.h" #include "components/history/core/browser/history_service_observer.h" #include "components/search_engines/template_url_service_client.h" -namespace history { -class HistoryService; -} - // ChromeTemplateURLServiceClient provides keyword related history // functionality for TemplateURLService. class ChromeTemplateURLServiceClient : public TemplateURLServiceClient, @@ -42,7 +39,7 @@ private: TemplateURLService* owner_; ScopedObserver<history::HistoryService, history::HistoryServiceObserver> - history_service_observer_; + history_service_observer_{this}; history::HistoryService* history_service_; DISALLOW_COPY_AND_ASSIGN(ChromeTemplateURLServiceClient);
diff --git a/chrome/browser/sessions/session_restore_stats_collector.cc b/chrome/browser/sessions/session_restore_stats_collector.cc index 7ea3a86..eb1d69f7 100644 --- a/chrome/browser/sessions/session_restore_stats_collector.cc +++ b/chrome/browser/sessions/session_restore_stats_collector.cc
@@ -15,7 +15,6 @@ #include "content/public/browser/navigation_entry.h" #include "content/public/browser/notification_service.h" #include "content/public/browser/notification_types.h" -#include "content/public/browser/render_widget_host.h" #include "content/public/browser/render_widget_host_view.h" #include "content/public/browser/web_contents.h" @@ -125,8 +124,7 @@ loading_tab_count_(0u), deferred_tab_count_(0u), tick_clock_(new base::DefaultTickClock()), - reporting_delegate_(std::move(reporting_delegate)), - observer_(this) { + reporting_delegate_(std::move(reporting_delegate)) { this_retainer_ = this; }
diff --git a/chrome/browser/sessions/session_restore_stats_collector.h b/chrome/browser/sessions/session_restore_stats_collector.h index d75d443..b3c1009b 100644 --- a/chrome/browser/sessions/session_restore_stats_collector.h +++ b/chrome/browser/sessions/session_restore_stats_collector.h
@@ -19,11 +19,11 @@ #include "chrome/browser/sessions/session_restore_delegate.h" #include "content/public/browser/notification_observer.h" #include "content/public/browser/notification_registrar.h" +#include "content/public/browser/render_widget_host.h" #include "content/public/browser/render_widget_host_observer.h" namespace content { class NavigationController; -class RenderWidgetHost; } // SessionRestoreStatsCollector observes SessionRestore events ands records UMA @@ -282,8 +282,8 @@ // has deferred tabs remaining from an interrupted session restore. scoped_refptr<SessionRestoreStatsCollector> this_retainer_; - ScopedObserver<content::RenderWidgetHost, SessionRestoreStatsCollector> - observer_; + ScopedObserver<content::RenderWidgetHost, content::RenderWidgetHostObserver> + observer_{this}; DISALLOW_COPY_AND_ASSIGN(SessionRestoreStatsCollector); };
diff --git a/chrome/browser/sessions/session_service_unittest.cc b/chrome/browser/sessions/session_service_unittest.cc index 81a5d4f..da53915 100644 --- a/chrome/browser/sessions/session_service_unittest.cc +++ b/chrome/browser/sessions/session_service_unittest.cc
@@ -35,6 +35,7 @@ #include "chrome/test/base/testing_browser_process.h" #include "chrome/test/base/testing_profile.h" #include "chrome/test/base/testing_profile_manager.h" +#include "components/sessions/content/content_serialized_navigation_builder.h" #include "components/sessions/content/content_test_helper.h" #include "components/sessions/core/serialized_navigation_entry_test_helper.h" #include "components/sessions/core/session_command.h" @@ -873,26 +874,30 @@ SessionID tab_id = SessionID::NewUnique(); ASSERT_NE(window_id, tab_id); - // Create a page state representing a HTTP body without posted passwords. - content::PageState page_state = - content::PageState::CreateForTesting(GURL(), false, "data", NULL); - // Create a TabNavigation containing page_state and representing a POST // request. + std::string post_data = "data"; + std::unique_ptr<content::NavigationEntry> entry1 = + content::NavigationEntry::Create(); + entry1->SetURL(GURL("http://google.com")); + entry1->SetTitle(base::UTF8ToUTF16("title1")); + entry1->SetHasPostData(true); + entry1->SetPostData(network::ResourceRequestBody::CreateFromBytes( + post_data.data(), post_data.size())); SerializedNavigationEntry nav1 = - ContentTestHelper::CreateNavigation("http://google.com", "title"); - SerializedNavigationEntryTestHelper::SetEncodedPageState( - page_state.ToEncodedData(), &nav1); - SerializedNavigationEntryTestHelper::SetHasPostData(true, &nav1); - nav1.set_index(0); + sessions::ContentSerializedNavigationBuilder::FromNavigationEntry( + 0 /* == index*/, entry1.get()); // Create a TabNavigation containing page_state and representing a normal // request. + std::unique_ptr<content::NavigationEntry> entry2 = + content::NavigationEntry::Create(); + entry2->SetURL(GURL("http://google.com/nopost")); + entry2->SetTitle(base::UTF8ToUTF16("title2")); + entry2->SetHasPostData(false); SerializedNavigationEntry nav2 = - ContentTestHelper::CreateNavigation("http://google.com/nopost", "title"); - SerializedNavigationEntryTestHelper::SetEncodedPageState( - page_state.ToEncodedData(), &nav2); - nav2.set_index(1); + sessions::ContentSerializedNavigationBuilder::FromNavigationEntry( + 1 /* == index*/, entry2.get()); helper_.PrepareTabInWindow(window_id, tab_id, 0, true); UpdateNavigation(window_id, tab_id, nav1, true);
diff --git a/chrome/browser/signin/signin_profile_attributes_updater.cc b/chrome/browser/signin/signin_profile_attributes_updater.cc index 076df05d..5417b5fc 100644 --- a/chrome/browser/signin/signin_profile_attributes_updater.cc +++ b/chrome/browser/signin/signin_profile_attributes_updater.cc
@@ -20,9 +20,7 @@ : identity_manager_(identity_manager), signin_error_controller_(signin_error_controller), profile_attributes_storage_(profile_attributes_storage), - profile_path_(profile_path), - identity_manager_observer_(this), - signin_error_controller_observer_(this) { + profile_path_(profile_path) { DCHECK(identity_manager_); DCHECK(signin_error_controller_); DCHECK(profile_attributes_storage_);
diff --git a/chrome/browser/signin/signin_profile_attributes_updater.h b/chrome/browser/signin/signin_profile_attributes_updater.h index 0c77301c..dc368db5 100644 --- a/chrome/browser/signin/signin_profile_attributes_updater.h +++ b/chrome/browser/signin/signin_profile_attributes_updater.h
@@ -51,10 +51,10 @@ SigninErrorController* signin_error_controller_; ProfileAttributesStorage* profile_attributes_storage_; const base::FilePath profile_path_; - ScopedObserver<signin::IdentityManager, SigninProfileAttributesUpdater> - identity_manager_observer_; - ScopedObserver<SigninErrorController, SigninProfileAttributesUpdater> - signin_error_controller_observer_; + ScopedObserver<signin::IdentityManager, signin::IdentityManager::Observer> + identity_manager_observer_{this}; + ScopedObserver<SigninErrorController, SigninErrorController::Observer> + signin_error_controller_observer_{this}; DISALLOW_COPY_AND_ASSIGN(SigninProfileAttributesUpdater); };
diff --git a/chrome/browser/signin/signin_util.cc b/chrome/browser/signin/signin_util.cc index 1c0966c..78baf7f 100644 --- a/chrome/browser/signin/signin_util.cc +++ b/chrome/browser/signin/signin_util.cc
@@ -39,6 +39,7 @@ #include "chrome/browser/ui/browser_list.h" #include "chrome/browser/ui/browser_list_observer.h" #include "chrome/browser/ui/browser_window.h" +#define CAN_DELETE_PROFILE #endif namespace signin_util { @@ -46,10 +47,6 @@ constexpr char kSignoutSettingKey[] = "signout_setting"; -#if defined(OS_WIN) || defined(OS_LINUX) || defined(OS_MACOSX) -#define CAN_DELETE_PROFILE -#endif - #if defined(CAN_DELETE_PROFILE) // Manager that presents the profile will be deleted dialog on the first active // browser window. @@ -67,12 +64,12 @@ Delegate* delegate) : profile_(profile), primary_account_email_(primary_account_email), - delegate_(delegate), - browser_observer_(this) {} - ~DeleteProfileDialogManager() override {} + delegate_(delegate) {} + + ~DeleteProfileDialogManager() override { BrowserList::RemoveObserver(this); } void PresentDialogOnAllBrowserWindows() { - browser_observer_.Add(BrowserList::GetInstance()); + BrowserList::AddObserver(this); Browser* active_browser = chrome::FindLastActiveWithProfile(profile_); if (active_browser) OnBrowserSetLastActive(active_browser); @@ -104,7 +101,6 @@ Profile* profile_; std::string primary_account_email_; Delegate* delegate_; - ScopedObserver<BrowserList, DeleteProfileDialogManager> browser_observer_; DISALLOW_COPY_AND_ASSIGN(DeleteProfileDialogManager); };
diff --git a/chrome/browser/subresource_filter/subresource_filter_content_settings_manager.cc b/chrome/browser/subresource_filter/subresource_filter_content_settings_manager.cc index 256bd83..aaa90cbe 100644 --- a/chrome/browser/subresource_filter/subresource_filter_content_settings_manager.cc +++ b/chrome/browser/subresource_filter/subresource_filter_content_settings_manager.cc
@@ -16,7 +16,6 @@ #include "components/content_settings/core/browser/host_content_settings_map.h" #include "components/content_settings/core/common/content_settings.h" #include "components/content_settings/core/common/content_settings_types.h" -#include "components/history/core/browser/history_service.h" #include "components/keyed_service/core/service_access_type.h" #include "url/gurl.h" @@ -39,8 +38,7 @@ SubresourceFilterContentSettingsManager:: SubresourceFilterContentSettingsManager(Profile* profile) - : history_observer_(this), - settings_map_(HostContentSettingsMapFactory::GetForProfile(profile)), + : settings_map_(HostContentSettingsMapFactory::GetForProfile(profile)), clock_(std::make_unique<base::DefaultClock>(base::DefaultClock())), should_use_smart_ui_(ShouldUseSmartUI()) { DCHECK(profile);
diff --git a/chrome/browser/subresource_filter/subresource_filter_content_settings_manager.h b/chrome/browser/subresource_filter/subresource_filter_content_settings_manager.h index e515d92..ff13379 100644 --- a/chrome/browser/subresource_filter/subresource_filter_content_settings_manager.h +++ b/chrome/browser/subresource_filter/subresource_filter_content_settings_manager.h
@@ -13,6 +13,7 @@ #include "base/time/clock.h" #include "base/time/time.h" #include "components/content_settings/core/common/content_settings.h" +#include "components/history/core/browser/history_service.h" #include "components/history/core/browser/history_service_observer.h" class GURL; @@ -23,10 +24,6 @@ class DictionaryValue; } // namespace base -namespace history { -class HistoryService; -} // namespace history - // This class contains helpers to get/set content and website settings related // to subresource filtering. // TODO(crbug.com/706061): Once observing changes to content settings is robust @@ -83,7 +80,7 @@ std::unique_ptr<base::DictionaryValue> dict); ScopedObserver<history::HistoryService, history::HistoryServiceObserver> - history_observer_; + history_observer_{this}; HostContentSettingsMap* settings_map_;
diff --git a/chrome/browser/sync/test/integration/single_client_device_info_sync_test.cc b/chrome/browser/sync/test/integration/single_client_device_info_sync_test.cc new file mode 100644 index 0000000..ba2a47f --- /dev/null +++ b/chrome/browser/sync/test/integration/single_client_device_info_sync_test.cc
@@ -0,0 +1,232 @@ +// 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 <ostream> +#include <string> + +#include "base/strings/stringprintf.h" +#include "build/build_config.h" +#include "chrome/browser/sync/test/integration/profile_sync_service_harness.h" +#include "chrome/browser/sync/test/integration/status_change_checker.h" +#include "chrome/browser/sync/test/integration/sync_test.h" +#include "chrome/browser/ui/browser.h" +#include "components/sync/base/model_type.h" +#include "components/sync/base/sync_prefs.h" +#include "components/sync/base/time.h" +#include "components/sync/driver/sync_driver_switches.h" +#include "components/sync/protocol/proto_value_conversions.h" +#include "components/sync/protocol/sync.pb.h" +#include "components/sync/test/fake_server/fake_server.h" +#include "components/sync_device_info/device_info_util.h" +#include "testing/gmock/include/gmock/gmock.h" +#include "testing/gtest/include/gtest/gtest.h" +#include "url/gurl.h" + +namespace { + +using testing::ElementsAre; +using testing::IsSupersetOf; + +MATCHER_P(HasCacheGuid, expected_cache_guid, "") { + return arg.specifics().device_info().cache_guid() == expected_cache_guid; +} + +std::string CacheGuidForSuffix(int suffix) { + return base::StringPrintf("cache guid %d", suffix); +} + +std::string ClientNameForSuffix(int suffix) { + return base::StringPrintf("client name %d", suffix); +} + +std::string SyncUserAgentForSuffix(int suffix) { + return base::StringPrintf("sync user agent %d", suffix); +} + +std::string ChromeVersionForSuffix(int suffix) { + return base::StringPrintf("chrome version %d", suffix); +} + +std::string SigninScopedDeviceIdForSuffix(int suffix) { + return base::StringPrintf("signin scoped device id %d", suffix); +} + +sync_pb::DeviceInfoSpecifics CreateSpecifics(int suffix) { + sync_pb::DeviceInfoSpecifics specifics; + specifics.set_cache_guid(CacheGuidForSuffix(suffix)); + specifics.set_client_name(ClientNameForSuffix(suffix)); + specifics.set_device_type(sync_pb::SyncEnums_DeviceType_TYPE_LINUX); + specifics.set_sync_user_agent(SyncUserAgentForSuffix(suffix)); + specifics.set_chrome_version(ChromeVersionForSuffix(suffix)); + specifics.set_signin_scoped_device_id(SigninScopedDeviceIdForSuffix(suffix)); + specifics.set_last_updated_timestamp( + syncer::TimeToProtoTime(base::Time::Now())); + return specifics; +} + +class ServerDeviceInfoMatchChecker : public StatusChangeChecker, + fake_server::FakeServer::Observer { + public: + using Matcher = testing::Matcher<std::vector<sync_pb::SyncEntity>>; + + ServerDeviceInfoMatchChecker(fake_server::FakeServer* fake_server, + const Matcher& matcher) + : fake_server_(fake_server), matcher_(matcher) { + fake_server->AddObserver(this); + } + + ~ServerDeviceInfoMatchChecker() override { + fake_server_->RemoveObserver(this); + } + + // FakeServer::Observer overrides. + void OnCommit(const std::string& committer_id, + syncer::ModelTypeSet committed_model_types) override { + if (committed_model_types.Has(syncer::DEVICE_INFO)) { + CheckExitCondition(); + } + } + + // StatusChangeChecker overrides. + bool IsExitConditionSatisfied() override { + std::vector<sync_pb::SyncEntity> entities = + fake_server_->GetSyncEntitiesByModelType(syncer::DEVICE_INFO); + return testing::Matches(matcher_)(entities); + } + + std::string GetDebugMessage() const override { + std::vector<sync_pb::SyncEntity> entities = + fake_server_->GetSyncEntitiesByModelType(syncer::DEVICE_INFO); + + testing::StringMatchResultListener result_listener; + testing::ExplainMatchResult(matcher_, entities, &result_listener); + return result_listener.str(); + } + + private: + fake_server::FakeServer* const fake_server_; + const Matcher matcher_; + + DISALLOW_COPY_AND_ASSIGN(ServerDeviceInfoMatchChecker); +}; + +class SingleClientDeviceInfoSyncTest : public SyncTest { + public: + SingleClientDeviceInfoSyncTest() : SyncTest(SINGLE_CLIENT) {} + + ~SingleClientDeviceInfoSyncTest() override {} + + std::string GetLocalCacheGuid() { + syncer::SyncPrefs prefs(GetProfile(0)->GetPrefs()); + return prefs.GetCacheGuid(); + } + + // Injects a test DeviceInfo entity to the fake server. + void InjectDeviceInfoEntityToServer(int suffix) { + sync_pb::EntitySpecifics specifics; + *specifics.mutable_device_info() = CreateSpecifics(suffix); + GetFakeServer()->InjectEntity( + syncer::PersistentUniqueClientEntity::CreateFromSpecificsForTesting( + /*non_unique_name=*/"", + /*client_tag=*/ + syncer::DeviceInfoUtil::SpecificsToTag(specifics.device_info()), + specifics, + /*creation_time=*/0, /*last_modified_time=*/0)); + } + + private: + DISALLOW_COPY_AND_ASSIGN(SingleClientDeviceInfoSyncTest); +}; + +IN_PROC_BROWSER_TEST_F(SingleClientDeviceInfoSyncTest, CommitLocalDevice) { + ASSERT_TRUE(SetupSync()); + + // The local device should eventually be committed to the server. + EXPECT_TRUE( + ServerDeviceInfoMatchChecker( + GetFakeServer(), ElementsAre(HasCacheGuid(GetLocalCacheGuid()))) + .Wait()); +} + +IN_PROC_BROWSER_TEST_F(SingleClientDeviceInfoSyncTest, DownloadRemoteDevices) { + InjectDeviceInfoEntityToServer(/*suffix=*/1); + InjectDeviceInfoEntityToServer(/*suffix=*/2); + + ASSERT_TRUE(SetupSync()); + + // The local device may or may not already be committed at this point. + EXPECT_THAT(fake_server_->GetSyncEntitiesByModelType(syncer::DEVICE_INFO), + IsSupersetOf({HasCacheGuid(CacheGuidForSuffix(1)), + HasCacheGuid(CacheGuidForSuffix(2))})); +} + +class SingleClientDeviceInfoWithTransportModeSyncTest + : public SingleClientDeviceInfoSyncTest { + public: + SingleClientDeviceInfoWithTransportModeSyncTest() { + scoped_list_.InitAndEnableFeature(switches::kSyncDeviceInfoInTransportMode); + } + + ~SingleClientDeviceInfoWithTransportModeSyncTest() override {} + + private: + base::test::ScopedFeatureList scoped_list_; + + DISALLOW_COPY_AND_ASSIGN(SingleClientDeviceInfoWithTransportModeSyncTest); +}; + +IN_PROC_BROWSER_TEST_F(SingleClientDeviceInfoWithTransportModeSyncTest, + CommitLocalDevice) { + ASSERT_TRUE(SetupClients()); + +#if defined(OS_CHROMEOS) + // On ChromeOS, Sync-the-feature gets started automatically once a primary + // account is signed in. To prevent that, explicitly set SyncRequested to + // false. + GetSyncService(0)->GetUserSettings()->SetSyncRequested(false); +#endif // defined(OS_CHROMEOS) + + // Setup a primary account, but don't actually enable Sync-the-feature (so + // that Sync will start in transport mode). + ASSERT_TRUE(GetClient(0)->SignInPrimaryAccount()); + ASSERT_TRUE(GetClient(0)->AwaitSyncTransportActive()); + + ASSERT_FALSE(GetSyncService(0)->IsSyncFeatureEnabled()); + ASSERT_TRUE(GetSyncService(0)->GetActiveDataTypes().Has(syncer::DEVICE_INFO)); + + // The local device should eventually be committed to the server. + EXPECT_TRUE( + ServerDeviceInfoMatchChecker( + GetFakeServer(), ElementsAre(HasCacheGuid(GetLocalCacheGuid()))) + .Wait()); +} + +IN_PROC_BROWSER_TEST_F(SingleClientDeviceInfoWithTransportModeSyncTest, + DownloadRemoteDevices) { + InjectDeviceInfoEntityToServer(/*suffix=*/1); + InjectDeviceInfoEntityToServer(/*suffix=*/2); + + ASSERT_TRUE(SetupClients()); + +#if defined(OS_CHROMEOS) + // On ChromeOS, Sync-the-feature gets started automatically once a primary + // account is signed in. To prevent that, explicitly set SyncRequested to + // false. + GetSyncService(0)->GetUserSettings()->SetSyncRequested(false); +#endif // defined(OS_CHROMEOS) + + // Setup a primary account, but don't actually enable Sync-the-feature (so + // that Sync will start in transport mode). + ASSERT_TRUE(GetClient(0)->SignInPrimaryAccount()); + ASSERT_TRUE(GetClient(0)->AwaitSyncTransportActive()); + + ASSERT_FALSE(GetSyncService(0)->IsSyncFeatureEnabled()); + ASSERT_TRUE(GetSyncService(0)->GetActiveDataTypes().Has(syncer::DEVICE_INFO)); + + EXPECT_THAT(fake_server_->GetSyncEntitiesByModelType(syncer::DEVICE_INFO), + IsSupersetOf({HasCacheGuid(CacheGuidForSuffix(1)), + HasCacheGuid(CacheGuidForSuffix(2))})); +} + +} // namespace
diff --git a/chrome/browser/themes/theme_properties.h b/chrome/browser/themes/theme_properties.h index 75cf802..c3078d9 100644 --- a/chrome/browser/themes/theme_properties.h +++ b/chrome/browser/themes/theme_properties.h
@@ -163,9 +163,13 @@ COLOR_OMNIBOX_RESULTS_BG, COLOR_OMNIBOX_RESULTS_BG_HOVERED, COLOR_OMNIBOX_RESULTS_BG_SELECTED, + COLOR_OMNIBOX_RESULTS_TEXT_SELECTED, COLOR_OMNIBOX_RESULTS_TEXT_DIMMED, + COLOR_OMNIBOX_RESULTS_TEXT_DIMMED_SELECTED, COLOR_OMNIBOX_RESULTS_ICON, + COLOR_OMNIBOX_RESULTS_ICON_SELECTED, COLOR_OMNIBOX_RESULTS_URL, + COLOR_OMNIBOX_RESULTS_URL_SELECTED, COLOR_OMNIBOX_BUBBLE_OUTLINE, COLOR_OMNIBOX_BUBBLE_OUTLINE_EXPERIMENTAL_KEYWORD_MODE, COLOR_OMNIBOX_SECURITY_CHIP_DEFAULT,
diff --git a/chrome/browser/themes/theme_service.cc b/chrome/browser/themes/theme_service.cc index e23230b..2cd05dcf 100644 --- a/chrome/browser/themes/theme_service.cc +++ b/chrome/browser/themes/theme_service.cc
@@ -1105,16 +1105,16 @@ bool custom; }; - auto get_base_color = [&](int id) -> OmniboxColor { - SkColor color; - if (theme_supplier_ && theme_supplier_->GetColor(id, &color)) - return {color, true}; - return {GetDefaultColor(id, incognito), false}; - }; - // These are the only base colors. - const OmniboxColor fg = get_base_color(TP::COLOR_OMNIBOX_TEXT); - const OmniboxColor bg = get_base_color(TP::COLOR_OMNIBOX_BACKGROUND); - const bool dark = IsDark(bg.value); + const bool high_contrast = + theme_supplier_ && theme_supplier_->get_theme_type() == + CustomThemeSupplier::ThemeType::INCREASED_CONTRAST; + + const bool invert = + high_contrast && (id == TP::COLOR_OMNIBOX_RESULTS_BG_SELECTED || + id == TP::COLOR_OMNIBOX_RESULTS_TEXT_SELECTED || + id == TP::COLOR_OMNIBOX_RESULTS_TEXT_DIMMED_SELECTED || + id == TP::COLOR_OMNIBOX_RESULTS_ICON_SELECTED || + id == TP::COLOR_OMNIBOX_RESULTS_URL_SELECTED); // Some utilities from color_utils are reimplemented here to plumb the custom // bit through. @@ -1130,6 +1130,8 @@ }; auto blend_for_min_contrast = [&](OmniboxColor fg, OmniboxColor bg, base::Optional<OmniboxColor> hc_fg = + base::nullopt, + base::Optional<float> contrast_ratio = base::nullopt) -> OmniboxColor { base::Optional<SkColor> hc_fg_arg; bool custom = fg.custom || bg.custom; @@ -1137,17 +1139,37 @@ hc_fg_arg = hc_fg.value().value; custom |= hc_fg.value().custom; } - const bool high_contrast = - theme_supplier_ && - theme_supplier_->get_theme_type() == - CustomThemeSupplier::ThemeType::INCREASED_CONTRAST; - const float contrast_ratio = - high_contrast ? 6.0f : kMinimumReadableContrastRatio; - return {BlendForMinContrast(fg.value, bg.value, hc_fg_arg, contrast_ratio) + return {BlendForMinContrast( + fg.value, bg.value, hc_fg_arg, + contrast_ratio.value_or( + high_contrast ? 6.0f : kMinimumReadableContrastRatio)) .color, custom}; }; + auto get_base_color = [&](int id) -> OmniboxColor { + SkColor color; + if (theme_supplier_ && theme_supplier_->GetColor(id, &color)) + return {color, true}; + return {GetDefaultColor(id, incognito), false}; + }; + // These are the only base colors. + OmniboxColor fg = get_base_color(TP::COLOR_OMNIBOX_TEXT); + OmniboxColor bg = get_base_color(TP::COLOR_OMNIBOX_BACKGROUND); + if (invert) { + // Given a color with some contrast against the opposite endpoint, returns a + // color with that same contrast against the nearby endpoint. + auto invert_color = [&](OmniboxColor fg) -> OmniboxColor { + const auto bg = get_color_with_max_contrast(fg); + const auto inverted_bg = get_color_with_max_contrast(bg); + const float contrast = GetContrastRatio(fg.value, bg.value); + return blend_for_min_contrast(fg, inverted_bg, base::nullopt, contrast); + }; + fg = invert_color(fg); + bg = invert_color(bg); + } + const bool dark = IsDark(bg.value); + auto results_bg_color = [&]() { return get_color_with_max_contrast(fg); }; auto security_chip_color = [&](OmniboxColor color) { return blend_for_min_contrast(color, bg); @@ -1167,6 +1189,7 @@ auto get_omnibox_color_impl = [&](int id) -> base::Optional<OmniboxColor> { switch (id) { case TP::COLOR_OMNIBOX_TEXT: + case TP::COLOR_OMNIBOX_RESULTS_TEXT_SELECTED: return fg; case TP::COLOR_OMNIBOX_BACKGROUND: return bg; @@ -1189,12 +1212,20 @@ case TP::COLOR_OMNIBOX_TEXT_DIMMED: return blend_with_clamped_contrast(bg); case TP::COLOR_OMNIBOX_RESULTS_TEXT_DIMMED: + return blend_with_clamped_contrast(results_bg_color()); + case TP::COLOR_OMNIBOX_RESULTS_TEXT_DIMMED_SELECTED: return blend_with_clamped_contrast(results_bg_selected_color()); case TP::COLOR_OMNIBOX_RESULTS_ICON: - return derive_default_icon_color(fg); + return blend_for_min_contrast(derive_default_icon_color(fg), + results_bg_color()); + case TP::COLOR_OMNIBOX_RESULTS_ICON_SELECTED: + return blend_for_min_contrast(derive_default_icon_color(fg), + results_bg_selected_color()); case TP::COLOR_OMNIBOX_RESULTS_BG_HOVERED: return blend_toward_max_contrast(results_bg_color(), 0x1A); case TP::COLOR_OMNIBOX_RESULTS_URL: + return url_color(results_bg_color()); + case TP::COLOR_OMNIBOX_RESULTS_URL_SELECTED: return url_color(results_bg_selected_color()); case TP::COLOR_OMNIBOX_SECURITY_CHIP_DEFAULT: case TP::COLOR_OMNIBOX_SECURITY_CHIP_SECURE:
diff --git a/chrome/browser/themes/theme_service_unittest.cc b/chrome/browser/themes/theme_service_unittest.cc index 8eb8e64..68974d7 100644 --- a/chrome/browser/themes/theme_service_unittest.cc +++ b/chrome/browser/themes/theme_service_unittest.cc
@@ -6,6 +6,7 @@ #include "base/files/file_util.h" #include "base/macros.h" +#include "base/memory/scoped_refptr.h" #include "base/path_service.h" #include "base/run_loop.h" #include "base/test/task_environment.h" @@ -15,6 +16,7 @@ #include "chrome/browser/extensions/extension_service_test_base.h" #include "chrome/browser/extensions/unpacked_installer.h" #include "chrome/browser/themes/custom_theme_supplier.h" +#include "chrome/browser/themes/increased_contrast_theme_supplier.h" #include "chrome/browser/themes/theme_properties.h" #include "chrome/browser/themes/theme_service_factory.h" #include "chrome/common/buildflags.h" @@ -31,6 +33,8 @@ #include "extensions/browser/uninstall_reason.h" #include "extensions/common/extension.h" #include "testing/gtest/include/gtest/gtest.h" +#include "ui/gfx/color_palette.h" +#include "ui/gfx/color_utils.h" #if BUILDFLAG(ENABLE_SUPERVISED_USERS) #include "chrome/browser/supervised_user/supervised_user_service.h" @@ -112,6 +116,22 @@ return theme_service->get_theme_supplier(); } + void set_theme_supplier(ThemeService* theme_service, + scoped_refptr<CustomThemeSupplier> theme_supplier) { + theme_service->theme_supplier_ = theme_supplier; + } + + SkColor GetOmniboxColor(ThemeService* theme_service, + int id, + bool incognito) const { + bool has_custom_color; + base::Optional<SkColor> color = + theme_service->GetOmniboxColor(id, incognito, &has_custom_color); + EXPECT_FALSE(has_custom_color); + EXPECT_TRUE(color); + return color.value_or(gfx::kPlaceholderColor); + } + void WaitForThemeInstall() { content::WindowedNotificationObserver theme_change_observer( chrome::NOTIFICATION_BROWSER_THEME_CHANGED, @@ -517,4 +537,83 @@ EXPECT_FALSE(service_->IsExtensionEnabled(extension1_id)); } +TEST_F(ThemeServiceTest, OmniboxContrast) { + using TP = ThemeProperties; + ThemeService* theme_service = + ThemeServiceFactory::GetForProfile(profile_.get()); + for (bool dark : {false, true}) { + for (bool high_contrast : {false, true}) { + set_theme_supplier( + theme_service, + high_contrast + ? base::MakeRefCounted<IncreasedContrastThemeSupplier>(dark) + : nullptr); + constexpr int contrasting_ids[][2] = { + {TP::COLOR_OMNIBOX_TEXT, TP::COLOR_OMNIBOX_BACKGROUND}, + {TP::COLOR_OMNIBOX_TEXT, TP::COLOR_OMNIBOX_BACKGROUND_HOVERED}, + {TP::COLOR_OMNIBOX_TEXT, TP::COLOR_OMNIBOX_RESULTS_BG}, + {TP::COLOR_OMNIBOX_TEXT, TP::COLOR_OMNIBOX_RESULTS_BG_HOVERED}, + {TP::COLOR_OMNIBOX_TEXT_DIMMED, TP::COLOR_OMNIBOX_BACKGROUND}, + {TP::COLOR_OMNIBOX_SELECTED_KEYWORD, TP::COLOR_OMNIBOX_RESULTS_BG}, + {TP::COLOR_OMNIBOX_RESULTS_TEXT_SELECTED, + TP::COLOR_OMNIBOX_RESULTS_BG_SELECTED}, + {TP::COLOR_OMNIBOX_RESULTS_TEXT_DIMMED, TP::COLOR_OMNIBOX_RESULTS_BG}, + {TP::COLOR_OMNIBOX_RESULTS_TEXT_SELECTED, + TP::COLOR_OMNIBOX_RESULTS_BG_SELECTED}, + {TP::COLOR_OMNIBOX_RESULTS_ICON, TP::COLOR_OMNIBOX_RESULTS_BG}, + {TP::COLOR_OMNIBOX_RESULTS_ICON, + TP::COLOR_OMNIBOX_RESULTS_BG_HOVERED}, + {TP::COLOR_OMNIBOX_RESULTS_ICON_SELECTED, + TP::COLOR_OMNIBOX_RESULTS_BG_SELECTED}, + {TP::COLOR_OMNIBOX_RESULTS_URL, TP::COLOR_OMNIBOX_RESULTS_BG}, + {TP::COLOR_OMNIBOX_RESULTS_URL_SELECTED, + TP::COLOR_OMNIBOX_RESULTS_BG_SELECTED}, + {TP::COLOR_OMNIBOX_BUBBLE_OUTLINE, TP::COLOR_OMNIBOX_RESULTS_BG}, + {TP::COLOR_OMNIBOX_BUBBLE_OUTLINE_EXPERIMENTAL_KEYWORD_MODE, + TP::COLOR_OMNIBOX_RESULTS_BG}, + {TP::COLOR_OMNIBOX_SECURITY_CHIP_DEFAULT, + TP::COLOR_OMNIBOX_BACKGROUND}, + {TP::COLOR_OMNIBOX_SECURITY_CHIP_DEFAULT, + TP::COLOR_OMNIBOX_BACKGROUND_HOVERED}, + {TP::COLOR_OMNIBOX_SECURITY_CHIP_DEFAULT, + TP::COLOR_OMNIBOX_RESULTS_BG}, + {TP::COLOR_OMNIBOX_SECURITY_CHIP_SECURE, + TP::COLOR_OMNIBOX_BACKGROUND}, + {TP::COLOR_OMNIBOX_SECURITY_CHIP_SECURE, + TP::COLOR_OMNIBOX_BACKGROUND_HOVERED}, + {TP::COLOR_OMNIBOX_SECURITY_CHIP_SECURE, + TP::COLOR_OMNIBOX_RESULTS_BG}, + {TP::COLOR_OMNIBOX_SECURITY_CHIP_DANGEROUS, + TP::COLOR_OMNIBOX_BACKGROUND}, + {TP::COLOR_OMNIBOX_SECURITY_CHIP_DANGEROUS, + TP::COLOR_OMNIBOX_RESULTS_BG}, + // TODO(thomasanderson): Because colors are computed relative to + // non-hovered backgrounds, some colors over hovered backgrounds do + // not have sufficient contrast in all configurations. Computing the + // non-contrasty colors here relative to hovered backgrounds should + // fix this and not reduce contrast of non-hovered backgrounds. + // {TP::COLOR_OMNIBOX_TEXT_DIMMED, + // TP::COLOR_OMNIBOX_BACKGROUND_HOVERED}, + // {TP::COLOR_OMNIBOX_RESULTS_TEXT_DIMMED, + // TP::COLOR_OMNIBOX_RESULTS_BG_HOVERED}, + // {TP::COLOR_OMNIBOX_RESULTS_URL, + // TP::COLOR_OMNIBOX_RESULTS_BG_HOVERED}, + // {TP::COLOR_OMNIBOX_SECURITY_CHIP_DANGEROUS, + // TP::COLOR_OMNIBOX_BACKGROUND_HOVERED}, + }; + auto check_sufficient_contrast = [&](int id1, int id2) { + const float contrast = color_utils::GetContrastRatio( + GetOmniboxColor(theme_service, id1, dark), + GetOmniboxColor(theme_service, id2, dark)); + EXPECT_GE(contrast, color_utils::kMinimumReadableContrastRatio); + }; + for (const int* ids : contrasting_ids) + check_sufficient_contrast(ids[0], ids[1]); + if (high_contrast) + check_sufficient_contrast(TP::COLOR_OMNIBOX_RESULTS_BG_SELECTED, + TP::COLOR_OMNIBOX_RESULTS_BG); + } + } +} + } // namespace theme_service_internal
diff --git a/chrome/browser/touch_to_fill/android/internal/BUILD.gn b/chrome/browser/touch_to_fill/android/internal/BUILD.gn index fef5aae42..d1bedc9 100644 --- a/chrome/browser/touch_to_fill/android/internal/BUILD.gn +++ b/chrome/browser/touch_to_fill/android/internal/BUILD.gn
@@ -22,6 +22,8 @@ "java/src/org/chromium/chrome/browser/touch_to_fill/TouchToFillProperties.java", "java/src/org/chromium/chrome/browser/touch_to_fill/TouchToFillView.java", "java/src/org/chromium/chrome/browser/touch_to_fill/TouchToFillViewBinder.java", + "java/src/org/chromium/chrome/browser/touch_to_fill/helper/ListViewAdapter.java", + "java/src/org/chromium/chrome/browser/touch_to_fill/helper/SimpleListViewMcp.java", ] annotation_processor_deps = [ "//base/android/jni_generator:jni_processor" ]
diff --git a/chrome/browser/touch_to_fill/android/internal/java/res/layout/touch_to_fill_credential_item.xml b/chrome/browser/touch_to_fill/android/internal/java/res/layout/touch_to_fill_credential_item.xml new file mode 100644 index 0000000..6460150 --- /dev/null +++ b/chrome/browser/touch_to_fill/android/internal/java/res/layout/touch_to_fill_credential_item.xml
@@ -0,0 +1,44 @@ +<?xml version="1.0" encoding="utf-8"?> +<!-- Copyright 2019 The Chromium Authors. All rights reserved. + Use of this source code is governed by a BSD-style license that can be + found in the LICENSE file. --> + +<LinearLayout + xmlns:android="http://schemas.android.com/apk/res/android" + android:descendantFocusability="blocksDescendants" + android:layout_width="match_parent" + android:layout_height="wrap_content" + android:minHeight="70dp" + android:gravity="center_vertical" + android:orientation="horizontal" + android:paddingStart="10dp" + android:paddingEnd="10dp"> + <ImageView + android:id="@+id/favicon" + android:layout_width="20dp" + android:layout_height="20dp" + android:importantForAccessibility="no" + android:layout_gravity="center"/> + <LinearLayout + android:layout_width="0dp" + android:layout_height="wrap_content" + android:layout_margin="8dp" + android:layout_marginStart="16dp" + android:layout_weight="1" + android:orientation="vertical"> + <TextView + android:id="@+id/username" + android:layout_width="wrap_content" + android:layout_height="wrap_content" + android:ellipsize="end" + android:singleLine="true" + android:textAppearance="@style/TextAppearance.BlackTitle1" /> + <TextView + android:id="@+id/password" + android:layout_width="wrap_content" + android:layout_height="wrap_content" + android:ellipsize="end" + android:singleLine="true" + android:textAppearance="@style/TextAppearance.BlackBody" /> + </LinearLayout> +</LinearLayout> \ No newline at end of file
diff --git a/chrome/browser/touch_to_fill/android/internal/java/src/org/chromium/chrome/browser/touch_to_fill/TouchToFillCoordinator.java b/chrome/browser/touch_to_fill/android/internal/java/src/org/chromium/chrome/browser/touch_to_fill/TouchToFillCoordinator.java index f03bc4e..d6e9c681 100644 --- a/chrome/browser/touch_to_fill/android/internal/java/src/org/chromium/chrome/browser/touch_to_fill/TouchToFillCoordinator.java +++ b/chrome/browser/touch_to_fill/android/internal/java/src/org/chromium/chrome/browser/touch_to_fill/TouchToFillCoordinator.java
@@ -4,11 +4,15 @@ package org.chromium.chrome.browser.touch_to_fill; +import static org.chromium.chrome.browser.touch_to_fill.TouchToFillProperties.CREDENTIAL_LIST; + import android.content.Context; import org.chromium.base.Callback; import org.chromium.base.VisibleForTesting; import org.chromium.chrome.browser.touch_to_fill.data.Credential; +import org.chromium.chrome.browser.touch_to_fill.helper.ListViewAdapter; +import org.chromium.chrome.browser.touch_to_fill.helper.SimpleListViewMcp; import org.chromium.chrome.browser.widget.bottomsheet.BottomSheetController; import org.chromium.ui.modelutil.PropertyModel; import org.chromium.ui.modelutil.PropertyModelChangeProcessor; @@ -44,5 +48,9 @@ @VisibleForTesting static void setUpModelChangeProcessors(PropertyModel model, TouchToFillView view) { PropertyModelChangeProcessor.create(model, view, TouchToFillViewBinder::bind); + view.setCredentialListAdapter( + new ListViewAdapter<>(new SimpleListViewMcp<>(model.get(CREDENTIAL_LIST), + TouchToFillViewBinder::bindCredentialView), + TouchToFillViewBinder::createCredentialView)); } }
diff --git a/chrome/browser/touch_to_fill/android/internal/java/src/org/chromium/chrome/browser/touch_to_fill/TouchToFillView.java b/chrome/browser/touch_to_fill/android/internal/java/src/org/chromium/chrome/browser/touch_to_fill/TouchToFillView.java index c28fdc9..8d297be6 100644 --- a/chrome/browser/touch_to_fill/android/internal/java/src/org/chromium/chrome/browser/touch_to_fill/TouchToFillView.java +++ b/chrome/browser/touch_to_fill/android/internal/java/src/org/chromium/chrome/browser/touch_to_fill/TouchToFillView.java
@@ -8,7 +8,10 @@ import android.support.annotation.Nullable; import android.view.LayoutInflater; import android.view.View; +import android.widget.AdapterView; import android.widget.LinearLayout; +import android.widget.ListAdapter; +import android.widget.ListView; import android.widget.TextView; import org.chromium.chrome.browser.widget.bottomsheet.BottomSheet; @@ -24,6 +27,7 @@ class TouchToFillView implements BottomSheet.BottomSheetContent { private final Context mContext; private final BottomSheetController mBottomSheetController; + private final ListView mCredentialListView; private final LinearLayout mContentView; private TouchToFillProperties.ViewEventListener mEventListener; @@ -47,6 +51,8 @@ mBottomSheetController = bottomSheetController; mContentView = (LinearLayout) LayoutInflater.from(mContext).inflate( R.layout.touch_to_fill_sheet, null); + mCredentialListView = mContentView.findViewById(R.id.credential_list); + mCredentialListView.setOnItemClickListener(this::onItemSelected); } /** @@ -83,6 +89,16 @@ mContext.getString(R.string.touch_to_fill_sheet_subtitle), formattedUrl)); } + void setCredentialListAdapter(ListAdapter adapter) { + mCredentialListView.setAdapter(adapter); + } + + private void onItemSelected(AdapterView<?> adapterView, View view, int i, long l) { + assert adapterView == mCredentialListView : "Use this click handler only for credentials!"; + assert mEventListener != null; + mEventListener.onSelectItemAt(i); + } + @Override public void destroy() { mBottomSheetController.getBottomSheet().removeObserver(mBottomSheetObserver);
diff --git a/chrome/browser/touch_to_fill/android/internal/java/src/org/chromium/chrome/browser/touch_to_fill/TouchToFillViewBinder.java b/chrome/browser/touch_to_fill/android/internal/java/src/org/chromium/chrome/browser/touch_to_fill/TouchToFillViewBinder.java index 33d3469..f9d7ee7 100644 --- a/chrome/browser/touch_to_fill/android/internal/java/src/org/chromium/chrome/browser/touch_to_fill/TouchToFillViewBinder.java +++ b/chrome/browser/touch_to_fill/android/internal/java/src/org/chromium/chrome/browser/touch_to_fill/TouchToFillViewBinder.java
@@ -9,6 +9,13 @@ import static org.chromium.chrome.browser.touch_to_fill.TouchToFillProperties.VIEW_EVENT_LISTENER; import static org.chromium.chrome.browser.touch_to_fill.TouchToFillProperties.VISIBLE; +import android.text.method.PasswordTransformationMethod; +import android.view.LayoutInflater; +import android.view.View; +import android.view.ViewGroup; +import android.widget.TextView; + +import org.chromium.chrome.browser.touch_to_fill.data.Credential; import org.chromium.ui.modelutil.PropertyKey; import org.chromium.ui.modelutil.PropertyModel; @@ -18,6 +25,31 @@ */ class TouchToFillViewBinder { /** + * Factory used to create a new View inside the ListView inside the TouchToFillView. + * @param parent The parent {@link ViewGroup} of the new item. + */ + static View createCredentialView(ViewGroup parent) { + return LayoutInflater.from(parent.getContext()) + .inflate(R.layout.touch_to_fill_credential_item, parent, false); + } + + /** + * Called whenever a credential is bound to this view holder. Please note that this method + * might be called on the same list entry repeatedly, so make sure to always set a default for + * unused fields. + * @param view The view to be bound. + * @param credential The {@link Credential} whose data needs to be displayed. + */ + static void bindCredentialView(View view, Credential credential) { + TextView usernameText = view.findViewById(R.id.username); + usernameText.setText(credential.getUsername()); + + TextView passwordText = view.findViewById(R.id.password); + passwordText.setText(credential.getPassword()); + passwordText.setTransformationMethod(new PasswordTransformationMethod()); + } + + /** * Called whenever a property in the given model changes. It updates the given view accordingly. * @param model The observed {@link PropertyModel}. Its data need to be reflected in the view. * @param view The {@link TouchToFillView} to update.
diff --git a/chrome/browser/touch_to_fill/android/internal/java/src/org/chromium/chrome/browser/touch_to_fill/helper/ListViewAdapter.java b/chrome/browser/touch_to_fill/android/internal/java/src/org/chromium/chrome/browser/touch_to_fill/helper/ListViewAdapter.java new file mode 100644 index 0000000..ae745a1c --- /dev/null +++ b/chrome/browser/touch_to_fill/android/internal/java/src/org/chromium/chrome/browser/touch_to_fill/helper/ListViewAdapter.java
@@ -0,0 +1,170 @@ +// 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.touch_to_fill.helper; + +import android.database.DataSetObserver; +import android.support.annotation.Nullable; +import android.view.View; +import android.view.ViewGroup; +import android.widget.ListAdapter; + +import org.chromium.ui.modelutil.ListObservable; + +import java.util.HashSet; +import java.util.Set; + +/** + * This Adapter creates Views of type {@link V} for a {@link android.widget.ListView} and binds + * items of type {@link T} to each of the created views. It defers most tasks to a {@link Delegate}. + * + * Construct with a {@link SimpleListViewMcp} to update a ListView according to a list model. + * + * @param <T> The item type inside the observed list. It's passed to the {@link Delegate}. + * @param <V> The view type of a single list entry as created by the {@link ViewFactory}. + */ +public class ListViewAdapter<T, V extends View> + implements ListObservable.ListObserver<Void>, ListAdapter { + private final Delegate<T, V> mDelegate; + private final ViewFactory<V> mViewFactory; + private final Set<DataSetObserver> mObservers = new HashSet<>(); + + /** + * This delegates decouples the ListViewAdapter from the underlying model and handles all tasks + * for which the model might be necessary. + * @param <T> The item type inside the observed list. + * @param <V> The view type of a single list entry as created by the {@link ViewFactory}. + */ + public interface Delegate<T, V extends View> { + /** + * Returns the list item at the given position. + * @param pos The position inside the list to retrieve the item for. + * @return An item of type {@link T}. + */ + T getItemAt(int pos); + + /** + * @return The total number of items in the observed list. + */ + int getItemCount(); + + /** + * Binds the data of the given item to the given View. + * @param view A View inside the ListView of type {@link V}. + * @param item An Item inside the observed list of type {@link T}. + */ + void onBindView(V view, T item); + } + + /** + * Subclasses of this interface create the View that represents an item in a ListView. + * @param <V> The type of {@link View} this factory creates. + */ + public interface ViewFactory<V extends View> { + /** + * Creates a View used in a ListView and attaches it to the given parent. + * @param parent The parent of the newly created View. + * @return A {@link View} that represents an item in a ListView. + */ + V create(ViewGroup parent); + } + + /** + * Creates a new ListViewAdapter. + * @param delegate The {@link Delegate} to bind views and query for list information. + * @param viewFactory The {@link ViewFactory} used to create new views for the ListView. + */ + public ListViewAdapter(Delegate<T, V> delegate, ViewFactory<V> viewFactory) { + mDelegate = delegate; + mViewFactory = viewFactory; + } + + @Override + public void onItemMoved(ListObservable source, int curIndex, int newIndex) { + notifyObserversChanged(); + } + + @Override + public void onItemRangeChanged( + ListObservable source, int index, int count, @Nullable Void payload) { + notifyObserversChanged(); + } + + @Override + public void onItemRangeInserted(ListObservable source, int index, int count) { + notifyObserversChanged(); + } + + @Override + public void onItemRangeRemoved(ListObservable source, int index, int count) { + notifyObserversChanged(); + } + + private void notifyObserversChanged() { + for (DataSetObserver observer : mObservers) observer.onChanged(); + } + + @Override + public void registerDataSetObserver(DataSetObserver dataSetObserver) { + mObservers.add(dataSetObserver); + } + + @Override + public void unregisterDataSetObserver(DataSetObserver dataSetObserver) { + mObservers.remove(dataSetObserver); + } + + @Override + public int getCount() { + return mDelegate.getItemCount(); + } + + @Override + public Object getItem(int i) { + return mDelegate.getItemAt(i); + } + + @Override + public long getItemId(int i) { + return i; + } + + @Override + public boolean hasStableIds() { + return false; + } + + @Override + @SuppressWarnings("unchecked") + public View getView(int pos, View view, ViewGroup parent) { + if (view == null) view = mViewFactory.create(parent); + mDelegate.onBindView((V) view, mDelegate.getItemAt(pos)); + return view; + } + + @Override + public int getItemViewType(int i) { + return 0; // Always the same view type. + } + + @Override + public int getViewTypeCount() { + return 1; // Always the same view type. + } + + @Override + public boolean isEmpty() { + return mDelegate.getItemCount() == 0; + } + + @Override + public boolean areAllItemsEnabled() { + return true; // There are no disabled items yet. + } + + @Override + public boolean isEnabled(int i) { + return true; // There are no disabled items yet. + } +}
diff --git a/chrome/browser/touch_to_fill/android/internal/java/src/org/chromium/chrome/browser/touch_to_fill/helper/SimpleListViewMcp.java b/chrome/browser/touch_to_fill/android/internal/java/src/org/chromium/chrome/browser/touch_to_fill/helper/SimpleListViewMcp.java new file mode 100644 index 0000000..0bbfccc9f --- /dev/null +++ b/chrome/browser/touch_to_fill/android/internal/java/src/org/chromium/chrome/browser/touch_to_fill/helper/SimpleListViewMcp.java
@@ -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. + +package org.chromium.chrome.browser.touch_to_fill.helper; + +import android.view.View; + +import org.chromium.ui.modelutil.ForwardingListObservable; +import org.chromium.ui.modelutil.ListModel; + +// TODO(fhorschig): Ask org.chromium.ui.modelutil OWNERS whether this should be shared. +/** + * Observes a {@link ListModel} and forwards any changes. It implements the + * {@link ListViewAdapter.Delegate} so it can be used to bind views as needed by a + * {@link android.widget.ListView} that ends up displaying the observed Entries. + * + * @param <T> The item type inside the passed ListModel. It's passed to the {@link ViewBinder}. + * @param <V> The view type of a single list entry. + */ +public class SimpleListViewMcp<T, V extends View> + extends ForwardingListObservable<Void> implements ListViewAdapter.Delegate<T, V> { + private final ListModel<T> mModel; + private final ViewBinder<T, V> mViewBinder; + + /** + * Subclasses of this interface bind a given item to a given view. + * @param <T> The item type of a list entry. + * @param <V> The view type of a single list entry. + */ + public interface ViewBinder<T, V extends View> { + /** + * Binds a given item to a given view. That means, the item properties are mapped to view + * properties. No logic should happen in here. + * @param view The view that holds the data of a list entry. + * @param item The item describing a single list entry. + */ + void bind(V view, T item); + } + + /** + * This creates a new Model Change Processor that observes the given model. + * @param model The {@Link ListModel} to be observed. + * @param viewBinder The {@link ViewBinder} used to bind items to views inside the ListView. + */ + public SimpleListViewMcp(ListModel<T> model, ViewBinder<T, V> viewBinder) { + mModel = model; + mViewBinder = viewBinder; + model.addObserver(this); + } + + @Override + public void onBindView(V view, T item) { + mViewBinder.bind(view, item); + } + + @Override + public T getItemAt(int pos) { + return mModel.get(pos); + } + + @Override + public int getItemCount() { + return mModel.size(); + } +} \ No newline at end of file
diff --git a/chrome/browser/touch_to_fill/android/javatests/src/org/chromium/chrome/browser/touch_to_fill/TouchToFillViewTest.java b/chrome/browser/touch_to_fill/android/javatests/src/org/chromium/chrome/browser/touch_to_fill/TouchToFillViewTest.java index 2c9d86ec..aa2b3c53 100644 --- a/chrome/browser/touch_to_fill/android/javatests/src/org/chromium/chrome/browser/touch_to_fill/TouchToFillViewTest.java +++ b/chrome/browser/touch_to_fill/android/javatests/src/org/chromium/chrome/browser/touch_to_fill/TouchToFillViewTest.java
@@ -4,15 +4,21 @@ package org.chromium.chrome.browser.touch_to_fill; +import static org.hamcrest.Matchers.instanceOf; import static org.hamcrest.Matchers.is; +import static org.junit.Assert.assertNotNull; import static org.junit.Assert.assertThat; +import static org.mockito.Mockito.timeout; import static org.mockito.Mockito.verify; +import static org.chromium.chrome.browser.touch_to_fill.TouchToFillProperties.CREDENTIAL_LIST; import static org.chromium.chrome.browser.touch_to_fill.TouchToFillProperties.FORMATTED_URL; import static org.chromium.chrome.browser.touch_to_fill.TouchToFillProperties.VISIBLE; import static org.chromium.content_public.browser.test.util.CriteriaHelper.pollUiThread; import android.support.test.filters.MediumTest; +import android.text.method.PasswordTransformationMethod; +import android.widget.ListView; import android.widget.TextView; import org.junit.Before; @@ -23,14 +29,20 @@ import org.mockito.MockitoAnnotations; import org.chromium.base.test.util.CommandLineFlags; +import org.chromium.base.test.util.ScalableTimeout; import org.chromium.chrome.browser.ChromeActivity; import org.chromium.chrome.browser.ChromeSwitches; +import org.chromium.chrome.browser.touch_to_fill.data.Credential; import org.chromium.chrome.browser.widget.bottomsheet.BottomSheet.SheetState; import org.chromium.chrome.test.ChromeJUnit4ClassRunner; import org.chromium.chrome.test.ChromeTabbedActivityTestRule; +import org.chromium.content_public.browser.test.util.CriteriaHelper; import org.chromium.content_public.browser.test.util.TestThreadUtils; +import org.chromium.content_public.browser.test.util.TouchCommon; import org.chromium.ui.modelutil.PropertyModel; +import java.util.Arrays; + /** * View tests for the Touch To Fill component ensure that model changes are reflected in the sheet. */ @@ -95,6 +107,46 @@ @Test @MediumTest + public void testCredentialsChangedByModel() { + TestThreadUtils.runOnUiThreadBlocking(() -> { + mTouchToFillView.setVisible(true); + mModel.get(CREDENTIAL_LIST) + .addAll(Arrays.asList(new Credential("Ana", "S3cr3t", null, false), + new Credential("Bob", "***", "m.example.xyz", true))); + }); + + pollUiThread(() -> getBottomSheetState() == SheetState.FULL); + assertThat(getCredentials().getChildCount(), is(2)); + assertThat(getCredentialNameAt(0).getText(), is("Ana")); + assertThat(getCredentialPasswordAt(0).getText(), is("S3cr3t")); + assertThat(getCredentialPasswordAt(0).getTransformationMethod(), + instanceOf(PasswordTransformationMethod.class)); + assertThat(getCredentialNameAt(1).getText(), is("Bob")); + assertThat(getCredentialPasswordAt(1).getText(), is("***")); + assertThat(getCredentialPasswordAt(1).getTransformationMethod(), + instanceOf(PasswordTransformationMethod.class)); + } + + @Test + @MediumTest + public void testCredentialsAreClickable() { + TestThreadUtils.runOnUiThreadBlocking(() -> { + mModel.get(CREDENTIAL_LIST) + .addAll(Arrays.asList(new Credential("Carl", "G3h3!m", "", false), + new Credential("Bob", "***", "m.example.xyz", true))); + mModel.set(VISIBLE, true); + }); + pollUiThread(() -> getBottomSheetState() == SheetState.FULL); + + assertNotNull(getCredentials().getChildAt(1)); + + TouchCommon.singleClickView(getCredentials().getChildAt(1)); + + waitForEvent().onSelectItemAt(1); + } + + @Test + @MediumTest public void testDismissesWhenHidden() { TestThreadUtils.runOnUiThreadBlocking(() -> mModel.set(VISIBLE, true)); pollUiThread(() -> getBottomSheetState() == SheetState.FULL); @@ -115,4 +167,21 @@ pollUiThread(() -> getActivity().getBottomSheet() != null); return getActivity().getBottomSheet().getSheetState(); } + + private ListView getCredentials() { + return mTouchToFillView.getContentView().findViewById(R.id.credential_list); + } + + private TextView getCredentialNameAt(int index) { + return getCredentials().getChildAt(index).findViewById(R.id.username); + } + + private TextView getCredentialPasswordAt(int index) { + return getCredentials().getChildAt(index).findViewById(R.id.password); + } + + TouchToFillProperties.ViewEventListener waitForEvent() { + return verify(mMockListener, + timeout(ScalableTimeout.scaleTimeout(CriteriaHelper.DEFAULT_MAX_TIME_TO_POLL))); + } } \ No newline at end of file
diff --git a/chrome/browser/ui/android/widget/BUILD.gn b/chrome/browser/ui/android/widget/BUILD.gn index 4051c34..fe306dc 100644 --- a/chrome/browser/ui/android/widget/BUILD.gn +++ b/chrome/browser/ui/android/widget/BUILD.gn
@@ -20,6 +20,7 @@ "java/src/org/chromium/chrome/browser/ui/widget/animation/AnimatorProperties.java", "java/src/org/chromium/chrome/browser/ui/widget/animation/CancelAwareAnimatorListener.java", "java/src/org/chromium/chrome/browser/ui/widget/animation/FocusAnimator.java", + "java/src/org/chromium/chrome/browser/ui/widget/animation/Interpolators.java", "java/src/org/chromium/chrome/browser/ui/widget/displaystyle/DisplayStyleObserver.java", "java/src/org/chromium/chrome/browser/ui/widget/displaystyle/DisplayStyleObserverAdapter.java", "java/src/org/chromium/chrome/browser/ui/widget/displaystyle/HorizontalDisplayStyle.java", @@ -35,6 +36,7 @@ deps = [ ":ui_widget_java_resources", "//base:base_java", + "//third_party/android_deps:android_support_v4_java", "//third_party/android_deps:android_support_v7_appcompat_java", "//third_party/android_deps:com_android_support_design_java", "//third_party/android_deps:com_android_support_interpolator_java",
diff --git a/chrome/browser/ui/android/widget/java/src/org/chromium/chrome/browser/ui/widget/animation/FocusAnimator.java b/chrome/browser/ui/android/widget/java/src/org/chromium/chrome/browser/ui/widget/animation/FocusAnimator.java index 27b4a1de..4c900e8a 100644 --- a/chrome/browser/ui/android/widget/java/src/org/chromium/chrome/browser/ui/widget/animation/FocusAnimator.java +++ b/chrome/browser/ui/android/widget/java/src/org/chromium/chrome/browser/ui/widget/animation/FocusAnimator.java
@@ -9,7 +9,6 @@ import android.animation.AnimatorSet; import android.animation.ValueAnimator; import android.animation.ValueAnimator.AnimatorUpdateListener; -import android.support.v4.view.animation.LinearOutSlowInInterpolator; import android.view.View; import android.view.View.OnLayoutChangeListener; import android.view.ViewGroup; @@ -139,7 +138,7 @@ // Set up and kick off the animation. AnimatorSet animator = new AnimatorSet(); animator.setDuration(ANIMATION_LENGTH_MS); - animator.setInterpolator(new LinearOutSlowInInterpolator()); + animator.setInterpolator(Interpolators.LINEAR_OUT_SLOW_IN_INTERPOLATOR); animator.playTogether(animators); animator.addListener(new AnimatorListenerAdapter() { @Override
diff --git a/chrome/browser/ui/android/widget/java/src/org/chromium/chrome/browser/ui/widget/animation/Interpolators.java b/chrome/browser/ui/android/widget/java/src/org/chromium/chrome/browser/ui/widget/animation/Interpolators.java new file mode 100644 index 0000000..96f8bd12 --- /dev/null +++ b/chrome/browser/ui/android/widget/java/src/org/chromium/chrome/browser/ui/widget/animation/Interpolators.java
@@ -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. + +package org.chromium.chrome.browser.ui.widget.animation; + +import android.support.v4.view.animation.FastOutLinearInInterpolator; +import android.support.v4.view.animation.FastOutSlowInInterpolator; +import android.support.v4.view.animation.LinearOutSlowInInterpolator; +import android.view.animation.AccelerateInterpolator; +import android.view.animation.DecelerateInterpolator; +import android.view.animation.LinearInterpolator; + +/** Reference to one of each standard interpolator to avoid allocations. */ +public class Interpolators { + public static final AccelerateInterpolator ACCELERATE_INTERPOLATOR = + new AccelerateInterpolator(); + public static final DecelerateInterpolator DECELERATE_INTERPOLATOR = + new DecelerateInterpolator(); + public static final FastOutLinearInInterpolator FAST_OUT_LINEAR_IN_INTERPOLATOR = + new FastOutLinearInInterpolator(); + public static final FastOutSlowInInterpolator FAST_OUT_SLOW_IN_INTERPOLATOR = + new FastOutSlowInInterpolator(); + public static final LinearInterpolator LINEAR_INTERPOLATOR = new LinearInterpolator(); + public static final LinearOutSlowInInterpolator LINEAR_OUT_SLOW_IN_INTERPOLATOR = + new LinearOutSlowInInterpolator(); +}
diff --git a/chrome/browser/ui/ash/launcher/launcher_app_service_app_updater.cc b/chrome/browser/ui/ash/launcher/launcher_app_service_app_updater.cc index a061653..8d406ed 100644 --- a/chrome/browser/ui/ash/launcher/launcher_app_service_app_updater.cc +++ b/chrome/browser/ui/ash/launcher/launcher_app_service_app_updater.cc
@@ -7,8 +7,8 @@ #include "chrome/browser/apps/app_service/app_service_proxy.h" #include "chrome/browser/apps/app_service/app_service_proxy_factory.h" #include "chrome/browser/profiles/profile.h" -#include "chrome/services/app_service/public/cpp/app_registry_cache.h" #include "chrome/services/app_service/public/cpp/app_update.h" +#include "chrome/services/app_service/public/mojom/types.mojom.h" LauncherAppServiceAppUpdater::LauncherAppServiceAppUpdater( Delegate* delegate, @@ -17,6 +17,10 @@ apps::AppServiceProxy* proxy = apps::AppServiceProxyFactory::GetForProfile( Profile::FromBrowserContext(browser_context)); if (proxy) { + proxy->AppRegistryCache().ForEachApp([this](const apps::AppUpdate& update) { + if (update.Readiness() == apps::mojom::Readiness::kReady) + this->installed_apps_.insert(update.AppId()); + }); Observe(&proxy->AppRegistryCache()); } }
diff --git a/chrome/browser/ui/blocked_content/popup_blocker.cc b/chrome/browser/ui/blocked_content/popup_blocker.cc index 950bc0db..1c1646b82 100644 --- a/chrome/browser/ui/blocked_content/popup_blocker.cc +++ b/chrome/browser/ui/blocked_content/popup_blocker.cc
@@ -4,6 +4,8 @@ #include "chrome/browser/ui/blocked_content/popup_blocker.h" +#include <string> + #include "base/command_line.h" #include "base/logging.h" #include "chrome/browser/content_settings/host_content_settings_map_factory.h" @@ -16,6 +18,7 @@ #include "components/content_settings/core/common/content_settings.h" #include "components/safe_browsing/triggers/ad_popup_trigger.h" #include "content/public/browser/page_navigator.h" +#include "content/public/browser/render_frame_host.h" #include "content/public/browser/web_contents.h" namespace { @@ -23,7 +26,7 @@ // If the popup should be blocked, returns the reason why it was blocked. // Otherwise returns kNotBlocked. PopupBlockType ShouldBlockPopup(content::WebContents* web_contents, - const base::Optional<GURL>& opener_url, + const GURL* opener_url, bool user_gesture, const content::OpenURLParams* open_url_params) { if (base::CommandLine::ForCurrentProcess()->HasSwitch( @@ -38,7 +41,7 @@ // the active entry is the page to be loaded as we navigate away from the // unloading page. const GURL& url = - opener_url ? opener_url.value() : web_contents->GetLastCommittedURL(); + opener_url ? *opener_url : web_contents->GetLastCommittedURL(); Profile* profile = Profile::FromBrowserContext(web_contents->GetBrowserContext()); if (url.is_valid() && @@ -68,41 +71,8 @@ return PopupBlockType::kNotBlocked; } -} // namespace - -bool ConsiderForPopupBlocking(WindowOpenDisposition disposition) { - return disposition == WindowOpenDisposition::NEW_POPUP || - disposition == WindowOpenDisposition::NEW_FOREGROUND_TAB || - disposition == WindowOpenDisposition::NEW_BACKGROUND_TAB || - disposition == WindowOpenDisposition::NEW_WINDOW; -} - -bool MaybeBlockPopup(content::WebContents* web_contents, - const base::Optional<GURL>& opener_url, - NavigateParams* params, - const content::OpenURLParams* open_url_params, - const blink::mojom::WindowFeatures& window_features) { - DCHECK(web_contents); - DCHECK(!open_url_params || - open_url_params->user_gesture == params->user_gesture); - PopupBlockerTabHelper::LogAction(PopupBlockerTabHelper::Action::kInitiated); - - PopupBlockType block_type = ShouldBlockPopup( - web_contents, opener_url, params->user_gesture, open_url_params); - auto* popup_blocker = PopupBlockerTabHelper::FromWebContents(web_contents); - if (popup_blocker && block_type != PopupBlockType::kNotBlocked) { - popup_blocker->AddBlockedPopup(params, window_features, block_type); - if (safe_browsing::AdPopupTrigger::FromWebContents(web_contents)) { - content::RenderFrameHost* source_frame = - GetSourceFrameForPopup(params, open_url_params, web_contents); - safe_browsing::AdPopupTrigger::FromWebContents(web_contents) - ->PopupWasBlocked(source_frame); - } - return true; - } - return false; -} - +// Tries to get the opener from either the |params| or |open_url_params|, +// otherwise uses the focused frame from |web_contents| as a proxy. content::RenderFrameHost* GetSourceFrameForPopup( NavigateParams* params, const content::OpenURLParams* open_url_params, @@ -122,3 +92,42 @@ // and is used as a fallback in case opener information is not available. return web_contents->GetFocusedFrame(); } + +} // namespace + +bool ConsiderForPopupBlocking(WindowOpenDisposition disposition) { + return disposition == WindowOpenDisposition::NEW_POPUP || + disposition == WindowOpenDisposition::NEW_FOREGROUND_TAB || + disposition == WindowOpenDisposition::NEW_BACKGROUND_TAB || + disposition == WindowOpenDisposition::NEW_WINDOW; +} + +bool MaybeBlockPopup(content::WebContents* web_contents, + const GURL* opener_url, + NavigateParams* params, + const content::OpenURLParams* open_url_params, + const blink::mojom::WindowFeatures& window_features) { + DCHECK(web_contents); + DCHECK(!open_url_params || + open_url_params->user_gesture == params->user_gesture); + PopupBlockerTabHelper::LogAction(PopupBlockerTabHelper::Action::kInitiated); + + // Check |popup_blocker| first since it is cheaper than ShouldBlockPopup(). + auto* popup_blocker = PopupBlockerTabHelper::FromWebContents(web_contents); + if (!popup_blocker) + return false; + + PopupBlockType block_type = ShouldBlockPopup( + web_contents, opener_url, params->user_gesture, open_url_params); + if (block_type == PopupBlockType::kNotBlocked) + return false; + + popup_blocker->AddBlockedPopup(params, window_features, block_type); + auto* trigger = safe_browsing::AdPopupTrigger::FromWebContents(web_contents); + if (trigger) { + content::RenderFrameHost* source_frame = + GetSourceFrameForPopup(params, open_url_params, web_contents); + trigger->PopupWasBlocked(source_frame); + } + return true; +}
diff --git a/chrome/browser/ui/blocked_content/popup_blocker.h b/chrome/browser/ui/blocked_content/popup_blocker.h index c926be6..cbebb84e 100644 --- a/chrome/browser/ui/blocked_content/popup_blocker.h +++ b/chrome/browser/ui/blocked_content/popup_blocker.h
@@ -5,8 +5,6 @@ #ifndef CHROME_BROWSER_UI_BLOCKED_CONTENT_POPUP_BLOCKER_H_ #define CHROME_BROWSER_UI_BLOCKED_CONTENT_POPUP_BLOCKER_H_ -#include "base/optional.h" -#include "content/public/browser/render_frame_host.h" #include "third_party/blink/public/mojom/window_features/window_features.mojom.h" #include "ui/base/window_open_disposition.h" #include "url/gurl.h" @@ -38,22 +36,15 @@ // |blocked_popups_| container. // // |opener_url| is an optional parameter used to compute how the popup -// permission will behave. If it is not set the current committed URL will be +// permission will behave. If it is nullptr, the current committed URL will be // used instead. // // If this function returns true, then the contents of |params| is moved to // |blocked_popups_|. bool MaybeBlockPopup(content::WebContents* web_contents, - const base::Optional<GURL>& opener_url, + const GURL* opener_url, NavigateParams* params, const content::OpenURLParams* open_url_params, const blink::mojom::WindowFeatures& window_features); -// Tries to get the opener from either the |params| or |open_url_params|, -// otherwise uses the focused frame from |web_contents| as a proxy. -content::RenderFrameHost* GetSourceFrameForPopup( - NavigateParams* params, - const content::OpenURLParams* open_url_params, - content::WebContents* web_contents); - #endif // CHROME_BROWSER_UI_BLOCKED_CONTENT_POPUP_BLOCKER_H_
diff --git a/chrome/browser/ui/blocked_content/safe_browsing_triggered_popup_blocker_unittest.cc b/chrome/browser/ui/blocked_content/safe_browsing_triggered_popup_blocker_unittest.cc index 73d4a641..cda6776 100644 --- a/chrome/browser/ui/blocked_content/safe_browsing_triggered_popup_blocker_unittest.cc +++ b/chrome/browser/ui/blocked_content/safe_browsing_triggered_popup_blocker_unittest.cc
@@ -242,7 +242,7 @@ nav_params.FillNavigateParamsFromOpenURLParams(params); nav_params.source_contents = web_contents(); nav_params.user_gesture = true; - MaybeBlockPopup(web_contents(), base::nullopt, &nav_params, ¶ms, + MaybeBlockPopup(web_contents(), nullptr, &nav_params, ¶ms, blink::mojom::WindowFeatures()); EXPECT_EQ(1u, PopupBlockerTabHelper::FromWebContents(web_contents()) @@ -270,7 +270,7 @@ nav_params.FillNavigateParamsFromOpenURLParams(params); nav_params.source_contents = web_contents(); nav_params.user_gesture = true; - MaybeBlockPopup(web_contents(), base::nullopt, &nav_params, ¶ms, + MaybeBlockPopup(web_contents(), nullptr, &nav_params, ¶ms, blink::mojom::WindowFeatures()); EXPECT_EQ(0u, PopupBlockerTabHelper::FromWebContents(web_contents())
diff --git a/chrome/browser/ui/browser.cc b/chrome/browser/ui/browser.cc index 24515ab..3d5d9ac0 100644 --- a/chrome/browser/ui/browser.cc +++ b/chrome/browser/ui/browser.cc
@@ -1415,8 +1415,8 @@ nav_params.blob_url_loader_factory = params.blob_url_loader_factory; nav_params.href_translate = params.href_translate; bool is_popup = source && ConsiderForPopupBlocking(params.disposition); - if (is_popup && MaybeBlockPopup(source, base::Optional<GURL>(), &nav_params, - ¶ms, blink::mojom::WindowFeatures())) { + if (is_popup && MaybeBlockPopup(source, nullptr, &nav_params, ¶ms, + blink::mojom::WindowFeatures())) { return nullptr; }
diff --git a/chrome/browser/ui/content_settings/content_setting_bubble_model_unittest.cc b/chrome/browser/ui/content_settings/content_setting_bubble_model_unittest.cc index 738b00a..0260cc80 100644 --- a/chrome/browser/ui/content_settings/content_setting_bubble_model_unittest.cc +++ b/chrome/browser/ui/content_settings/content_setting_bubble_model_unittest.cc
@@ -1245,7 +1245,7 @@ for (size_t i = 1; i <= kItemCount; i++) { NavigateParams navigate_params = params.CreateNavigateParams(web_contents()); - EXPECT_TRUE(MaybeBlockPopup(web_contents(), url, &navigate_params, + EXPECT_TRUE(MaybeBlockPopup(web_contents(), &url, &navigate_params, nullptr /*=open_url_params*/, params.features())); EXPECT_EQ(i, list_items.size());
diff --git a/chrome/browser/ui/login/login_handler_browsertest.cc b/chrome/browser/ui/login/login_handler_browsertest.cc index 796ed3d9..ac929c60 100644 --- a/chrome/browser/ui/login/login_handler_browsertest.cc +++ b/chrome/browser/ui/login/login_handler_browsertest.cc
@@ -1694,6 +1694,52 @@ EXPECT_EQ(expected_title, auth_supplied_title_watcher.WaitAndGetTitle()); } +// Tests that when HTTP Auth committed interstitials are enabled, showing a +// login prompt in a new window opened from window.open() does not +// crash. Regression test for https://crbug.com/1005096. +IN_PROC_BROWSER_TEST_F(LoginPromptBrowserTest, PromptWithNoVisibleEntry) { + ASSERT_TRUE(embedded_test_server()->Start()); + + content::WebContents* contents = + browser()->tab_strip_model()->GetActiveWebContents(); + + ui_test_utils::NavigateToURL(browser(), GURL("about:blank")); + + // Open a new window via JavaScript and navigate it to a page that delivers an + // auth prompt. + GURL test_page = embedded_test_server()->GetURL(kAuthBasicPage); + ASSERT_NE(false, content::EvalJs(contents, "w = window.open();")); + content::WebContents* opened_contents = + browser()->tab_strip_model()->GetWebContentsAt(1); + NavigationController* opened_controller = &opened_contents->GetController(); + ASSERT_FALSE(opened_controller->GetVisibleEntry()); + LoginPromptBrowserTestObserver observer; + observer.Register(content::Source<NavigationController>(opened_controller)); + WindowedAuthNeededObserver auth_needed_waiter(opened_controller); + ASSERT_NE(false, content::EvalJs(contents, "w.location.href = '" + + test_page.spec() + "';")); + + // Test that the login prompt displays above an empty page. + EXPECT_EQ( + "<head></head><body></body>", + content::EvalJs(opened_contents, "document.documentElement.innerHTML")); + + auth_needed_waiter.Wait(); + ASSERT_EQ(1u, observer.handlers().size()); + + // Test that credentials are handled correctly. + WindowedAuthSuppliedObserver auth_supplied_waiter(opened_controller); + LoginHandler* handler = *observer.handlers().begin(); + SetAuthFor(handler); + auth_supplied_waiter.Wait(); + + base::string16 expected_title = ExpectedTitleFromAuth( + base::ASCIIToUTF16("basicuser"), base::ASCIIToUTF16("secret")); + content::TitleWatcher auth_supplied_title_watcher(opened_contents, + expected_title); + EXPECT_EQ(expected_title, auth_supplied_title_watcher.WaitAndGetTitle()); +} + // Tests that FTP auth challenges appear over a blank committed interstitial. IN_PROC_BROWSER_TEST_F(LoginPromptBrowserTest, FtpAuth) { net::SpawnedTestServer ftp_server(
diff --git a/chrome/browser/ui/login/login_tab_helper.cc b/chrome/browser/ui/login/login_tab_helper.cc index 9e6df4c..c0d6c23 100644 --- a/chrome/browser/ui/login/login_tab_helper.cc +++ b/chrome/browser/ui/login/login_tab_helper.cc
@@ -159,8 +159,17 @@ content::NavigationHandle* navigation_handle) { // If the user has just cancelled the auth prompt for this navigation, then // the page is being refreshed to retrieve the 401 body from the server, so - // allow the refresh to proceed. - if (web_contents()->GetController().GetVisibleEntry()->GetUniqueID() == + // allow the refresh to proceed. The entry to compare against is the pending + // entry, because while refreshing after cancelling the prompt, the page that + // showed the prompt will be the pending entry until the refresh + // commits. Comparing against GetVisibleEntry() would also work, but it's less + // specific and not guaranteed to exist in all cases (e.g., in the case of + // navigating a window just opened via window.open()). + // + // TODO(https://crbug.com/1006955): if this line is crashing, the assumption + // that GetPendingEntry() must be non-null is incorrect, in which case a null + // check should be added here. + if (web_contents()->GetController().GetPendingEntry()->GetUniqueID() == navigation_entry_id_with_cancelled_prompt_) { // Note the navigation handle ID so that when this refresh navigation // finishes, DidFinishNavigation declines to show another login prompt. We
diff --git a/chrome/browser/ui/omnibox/omnibox_theme.cc b/chrome/browser/ui/omnibox/omnibox_theme.cc index a35ba09..57330f1 100644 --- a/chrome/browser/ui/omnibox/omnibox_theme.cc +++ b/chrome/browser/ui/omnibox/omnibox_theme.cc
@@ -18,6 +18,7 @@ namespace { int GetThemePropertyId(OmniboxPart part, OmniboxPartState state) { + const bool selected = state == OmniboxPartState::SELECTED; switch (part) { case OmniboxPart::LOCATION_BAR_BACKGROUND: return state == OmniboxPartState::HOVERED @@ -39,16 +40,21 @@ } case OmniboxPart::LOCATION_BAR_CLEAR_ALL: case OmniboxPart::LOCATION_BAR_TEXT_DEFAULT: - case OmniboxPart::RESULTS_TEXT_DEFAULT: return TP::COLOR_OMNIBOX_TEXT; + case OmniboxPart::RESULTS_TEXT_DEFAULT: + return selected ? TP::COLOR_OMNIBOX_RESULTS_TEXT_SELECTED + : TP::COLOR_OMNIBOX_TEXT; case OmniboxPart::LOCATION_BAR_TEXT_DIMMED: return TP::COLOR_OMNIBOX_TEXT_DIMMED; case OmniboxPart::RESULTS_TEXT_DIMMED: - return TP::COLOR_OMNIBOX_RESULTS_TEXT_DIMMED; + return selected ? TP::COLOR_OMNIBOX_RESULTS_TEXT_DIMMED_SELECTED + : TP::COLOR_OMNIBOX_RESULTS_TEXT_DIMMED; case OmniboxPart::RESULTS_ICON: - return TP::COLOR_OMNIBOX_RESULTS_ICON; + return selected ? TP::COLOR_OMNIBOX_RESULTS_ICON_SELECTED + : TP::COLOR_OMNIBOX_RESULTS_ICON; case OmniboxPart::RESULTS_TEXT_URL: - return TP::COLOR_OMNIBOX_RESULTS_URL; + return selected ? TP::COLOR_OMNIBOX_RESULTS_URL_SELECTED + : TP::COLOR_OMNIBOX_RESULTS_URL; case OmniboxPart::LOCATION_BAR_BUBBLE_OUTLINE: return OmniboxFieldTrial::IsExperimentalKeywordModeEnabled() ? TP::COLOR_OMNIBOX_BUBBLE_OUTLINE_EXPERIMENTAL_KEYWORD_MODE
diff --git a/chrome/browser/ui/send_tab_to_self/send_tab_to_self_sub_menu_model.cc b/chrome/browser/ui/send_tab_to_self/send_tab_to_self_sub_menu_model.cc index e48a9da..4aa8693 100644 --- a/chrome/browser/ui/send_tab_to_self/send_tab_to_self_sub_menu_model.cc +++ b/chrome/browser/ui/send_tab_to_self/send_tab_to_self_sub_menu_model.cc
@@ -162,7 +162,7 @@ int index) { ValidDeviceItem item(device_name, cache_guid); int command_id = - (menu_type_ == kTab) ? kShareTabCommandId : kShareLinkCommandId + index; + ((menu_type_ == kTab) ? kShareTabCommandId : kShareLinkCommandId) + index; InsertItemAt(index, command_id, base::UTF8ToUTF16(device_name)); valid_device_items_.push_back(item); }
diff --git a/chrome/browser/ui/send_tab_to_self/send_tab_to_self_sub_menu_model_unittest.cc b/chrome/browser/ui/send_tab_to_self/send_tab_to_self_sub_menu_model_unittest.cc new file mode 100644 index 0000000..03bd063 --- /dev/null +++ b/chrome/browser/ui/send_tab_to_self/send_tab_to_self_sub_menu_model_unittest.cc
@@ -0,0 +1,121 @@ +// 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/send_tab_to_self/send_tab_to_self_sub_menu_model.h" + +#include "chrome/browser/sync/send_tab_to_self_sync_service_factory.h" +#include "chrome/test/base/browser_with_test_window_test.h" +#include "components/send_tab_to_self/send_tab_to_self_sync_service.h" +#include "components/send_tab_to_self/test_send_tab_to_self_model.h" +#include "testing/gmock/include/gmock/gmock.h" + +namespace send_tab_to_self { + +namespace { + +using testing::_; +using testing::Return; +using testing::SaveArg; + +class SendTabToSelfModelMock : public TestSendTabToSelfModel { + public: + SendTabToSelfModelMock() = default; + ~SendTabToSelfModelMock() override = default; + + MOCK_METHOD0(GetTargetDeviceInfoSortedList, std::vector<TargetDeviceInfo>()); + + MOCK_METHOD4(AddEntry, + const SendTabToSelfEntry*(const GURL&, + const std::string&, + base::Time, + const std::string&)); + + bool IsReady() override { return true; } +}; + +class TestSendTabToSelfSyncService : public SendTabToSelfSyncService { + public: + TestSendTabToSelfSyncService() = default; + ~TestSendTabToSelfSyncService() override = default; + + SendTabToSelfModel* GetSendTabToSelfModel() override { + return &send_tab_to_self_model_mock_; + } + + protected: + SendTabToSelfModelMock send_tab_to_self_model_mock_; +}; + +std::unique_ptr<KeyedService> BuildTestSendTabToSelfSyncService( + content::BrowserContext* context) { + return std::make_unique<TestSendTabToSelfSyncService>(); +} + +TargetDeviceInfo BuildTargetDeviceInfo(const std::string& device_name, + const std::string& cache_guid) { + return TargetDeviceInfo(device_name, cache_guid, + sync_pb::SyncEnums_DeviceType_TYPE_OTHER, + base::Time()); +} + +class SendTabToSelfSubMenuModelTest : public BrowserWithTestWindowTest { + public: + SendTabToSelfSubMenuModelTest() = default; + ~SendTabToSelfSubMenuModelTest() override = default; + + void SetUp() override { + BrowserWithTestWindowTest::SetUp(); + + // Set up all test conditions to let ShouldOfferFeature() return true. + GURL url("https://www.test.com"); + AddTab(browser(), url); + NavigateAndCommitActiveTabWithTitle(browser(), url, + base::ASCIIToUTF16("test")); + } + + void SetUpTestService() { + SendTabToSelfSyncServiceFactory::GetInstance()->SetTestingFactory( + browser()->profile(), + base::BindRepeating(&BuildTestSendTabToSelfSyncService)); + } + + SendTabToSelfModelMock* GetSendTabToSelfModelMock() { + return static_cast<SendTabToSelfModelMock*>( + SendTabToSelfSyncServiceFactory::GetForProfile(browser()->profile()) + ->GetSendTabToSelfModel()); + } +}; + +TEST_F(SendTabToSelfSubMenuModelTest, ExecuteCommandTab) { + SetUpTestService(); + + SendTabToSelfModelMock* model_mock = GetSendTabToSelfModelMock(); + std::vector<TargetDeviceInfo> devices = { + BuildTargetDeviceInfo("device0", "0"), + BuildTargetDeviceInfo("device1", "1"), + BuildTargetDeviceInfo("device2", "2")}; + + EXPECT_CALL(*model_mock, GetTargetDeviceInfoSortedList()) + .WillOnce(Return(devices)); + SendTabToSelfSubMenuModel sub_menu_model( + browser()->tab_strip_model()->GetActiveWebContents(), + send_tab_to_self::SendTabToSelfMenuType::kTab); + + std::string device_guid; + EXPECT_CALL(*model_mock, AddEntry(_, _, _, _)) + .WillRepeatedly( + DoAll(SaveArg<3>(&device_guid), testing::Return(nullptr))); + + // Check that all devices can be selected. + for (int i = 0; i < (int)devices.size(); i++) { + device_guid = std::string(); + sub_menu_model.ExecuteCommand(SendTabToSelfSubMenuModel::kMinCommandId + i, + -1); + EXPECT_EQ(devices[i].cache_guid, device_guid) << "for index: " << i; + } +} + +} // namespace + +} // namespace send_tab_to_self
diff --git a/chrome/browser/ui/toolbar/app_menu_model.cc b/chrome/browser/ui/toolbar/app_menu_model.cc index ed269047..63f9f4ae8 100644 --- a/chrome/browser/ui/toolbar/app_menu_model.cc +++ b/chrome/browser/ui/toolbar/app_menu_model.cc
@@ -883,17 +883,12 @@ } void AppMenuModel::CreateZoomMenu() { - // WARNING: Mac does not use the ButtonMenuItemModel, but instead defines the - // layout for this menu item in AppMenu.xib. It does, however, use the - // command_id value from AddButtonItem() to identify this special item. zoom_menu_item_model_.reset(new ui::ButtonMenuItemModel(IDS_ZOOM_MENU, this)); zoom_menu_item_model_->AddGroupItemWithStringId(IDC_ZOOM_MINUS, IDS_ZOOM_MINUS2); zoom_menu_item_model_->AddGroupItemWithStringId(IDC_ZOOM_PLUS, IDS_ZOOM_PLUS2); - // TODO(https://crbug.com/957391): Remove the former IDR_ parameter here once - // the change to remove it from the model (crrev.com/1816118) is in. - zoom_menu_item_model_->AddItemWithImage(IDC_FULLSCREEN, -1); + zoom_menu_item_model_->AddImageItem(IDC_FULLSCREEN); AddButtonItem(IDC_ZOOM_MENU, zoom_menu_item_model_.get()); }
diff --git a/chrome/browser/ui/views/first_run_dialog.cc b/chrome/browser/ui/views/first_run_dialog.cc index d3e55388..6b0d433 100644 --- a/chrome/browser/ui/views/first_run_dialog.cc +++ b/chrome/browser/ui/views/first_run_dialog.cc
@@ -17,6 +17,7 @@ #include "chrome/common/url_constants.h" #include "chrome/grit/chromium_strings.h" #include "chrome/grit/generated_resources.h" +#include "components/crash/content/app/crashpad.h" #include "components/strings/grit/components_strings.h" #include "ui/aura/env.h" #include "ui/aura/window.h" @@ -37,8 +38,14 @@ namespace { void InitCrashReporterIfEnabled(bool enabled) { +#if defined(OS_WIN) if (enabled) breakpad::InitCrashReporter(std::string()); +#elif defined(OS_LINUX) + if (!crash_reporter::IsCrashpadEnabled() && enabled) { + breakpad::InitCrashReporter(std::string()); + } +#endif } } // namespace
diff --git a/chrome/browser/ui/views/global_media_controls/media_toolbar_button_view.cc b/chrome/browser/ui/views/global_media_controls/media_toolbar_button_view.cc index 7846131..2dfdfc6 100644 --- a/chrome/browser/ui/views/global_media_controls/media_toolbar_button_view.cc +++ b/chrome/browser/ui/views/global_media_controls/media_toolbar_button_view.cc
@@ -68,14 +68,18 @@ void MediaToolbarButtonView::Enable() { SetEnabled(true); - UpdateIcon(); InformIPHOfButtonEnabled(); +#if defined(OS_MACOSX) + UpdateIcon(); +#endif // defined(OS_MACOSX) } void MediaToolbarButtonView::Disable() { SetEnabled(false); - UpdateIcon(); InformIPHOfButtonDisabledorHidden(); +#if defined(OS_MACOSX) + UpdateIcon(); +#endif // defined(OS_MACOSX) } SkColor MediaToolbarButtonView::GetInkDropBaseColor() const { @@ -85,6 +89,9 @@ } void MediaToolbarButtonView::UpdateIcon() { + if (!GetWidget()) + return; + const gfx::VectorIcon& icon = ::vector_icons::kQueueMusicIcon; const SkColor normal_color =
diff --git a/chrome/browser/ui/views/status_icons/status_icon_linux_dbus.cc b/chrome/browser/ui/views/status_icons/status_icon_linux_dbus.cc index 6b4ae8f..3a9ef14 100644 --- a/chrome/browser/ui/views/status_icons/status_icon_linux_dbus.cc +++ b/chrome/browser/ui/views/status_icons/status_icon_linux_dbus.cc
@@ -10,17 +10,23 @@ #include <string> #include "base/bind.h" +#include "base/environment.h" +#include "base/files/file_util.h" #include "base/logging.h" #include "base/memory/ref_counted_memory.h" +#include "base/nix/xdg_util.h" #include "base/numerics/checked_math.h" #include "base/process/process.h" #include "base/strings/string_number_conversions.h" #include "base/strings/utf_string_conversions.h" +#include "base/task/post_task.h" +#include "base/task_runner_util.h" #include "components/dbus/menu/menu.h" #include "components/dbus/properties/dbus_properties.h" #include "components/dbus/properties/success_barrier_callback.h" #include "components/dbus/properties/types.h" #include "components/dbus/thread_linux/dbus_thread_linux.h" +#include "content/public/browser/browser_thread.h" #include "dbus/bus.h" #include "dbus/exported_object.h" #include "dbus/message.h" @@ -71,6 +77,7 @@ const char kPropertyAttentionMovieName[] = "AttentionMovieName"; const char kPropertyCategory[] = "Category"; const char kPropertyIconName[] = "IconName"; +const char kPropertyIconThemePath[] = "IconThemePath"; const char kPropertyId[] = "Id"; const char kPropertyOverlayIconName[] = "OverlayIconName"; const char kPropertyStatus[] = "Status"; @@ -82,6 +89,7 @@ // Signals. const char kSignalNewIcon[] = "NewIcon"; +const char kSignalNewIconThemePath[] = "NewIconThemePath"; const char kSignalNewToolTip[] = "NewToolTip"; // Property values. @@ -131,9 +139,56 @@ DbusString(text), DbusString("")); } +bool ShouldWriteIconToFile() { + auto env = base::Environment::Create(); + switch (base::nix::GetDesktopEnvironment(env.get())) { + case base::nix::DESKTOP_ENVIRONMENT_GNOME: + // gnome-shell-extension-appindicator doesn't downsize icons when they're + // given as DBus pixmaps. But it does when icons are given as files. + case base::nix::DESKTOP_ENVIRONMENT_PANTHEON: + // wingpanel-indicator-ayatana only supports file icons. + return true; + case base::nix::DESKTOP_ENVIRONMENT_OTHER: + case base::nix::DESKTOP_ENVIRONMENT_CINNAMON: + case base::nix::DESKTOP_ENVIRONMENT_KDE3: + case base::nix::DESKTOP_ENVIRONMENT_KDE4: + case base::nix::DESKTOP_ENVIRONMENT_KDE5: + case base::nix::DESKTOP_ENVIRONMENT_UNITY: + case base::nix::DESKTOP_ENVIRONMENT_XFCE: + return false; + } + NOTREACHED(); + return false; +} + +base::FilePath WriteIconFile(size_t icon_file_id, + scoped_refptr<base::RefCountedMemory> data) { + // Some StatusNotifierHosts require both the theme directory and icon name to + // change in order to update, so we need a new temporary directory and a + // unique base name for the file. + base::FilePath temp_dir; + if (!base::CreateNewTempDirectory("", &temp_dir)) + return {}; + + base::FilePath file_path = temp_dir.Append( + "status_icon_" + base::NumberToString(icon_file_id) + ".png"); + if (!base::WriteFile(file_path, data->front_as<char>(), data->size())) { + base::DeleteFile(temp_dir, true); + return {}; + } + + return file_path; +} + } // namespace -StatusIconLinuxDbus::StatusIconLinuxDbus() { +StatusIconLinuxDbus::StatusIconLinuxDbus() + : should_write_icon_to_file_(ShouldWriteIconToFile()), + icon_task_runner_(base::CreateSequencedTaskRunner( + {base::ThreadPool(), base::MayBlock(), + base::TaskPriority::USER_VISIBLE, + base::TaskShutdownBehavior::BLOCK_SHUTDOWN})) { + DCHECK_CURRENTLY_ON(content::BrowserThread::UI); dbus::Bus::Options bus_options; bus_options.bus_type = dbus::Bus::SESSION; bus_options.connection_type = dbus::Bus::PRIVATE; @@ -142,22 +197,13 @@ CheckStatusNotifierWatcherHasOwner(); } -StatusIconLinuxDbus::~StatusIconLinuxDbus() { - bus_->GetDBusTaskRunner()->PostTask( - FROM_HERE, base::BindOnce(&dbus::Bus::ShutdownAndBlock, bus_)); -} - void StatusIconLinuxDbus::SetIcon(const gfx::ImageSkia& image) { - if (!properties_) - return; - - properties_->SetProperty(kInterfaceStatusNotifierItem, kPropertyIconPixmap, - MakeDbusImage(image), true, false); - dbus::Signal signal(kInterfaceStatusNotifierItem, kSignalNewIcon); - item_->SendSignal(&signal); + DCHECK_CURRENTLY_ON(content::BrowserThread::UI); + SetIconImpl(image, true); } void StatusIconLinuxDbus::SetToolTip(const base::string16& tool_tip) { + DCHECK_CURRENTLY_ON(content::BrowserThread::UI); if (!properties_) return; @@ -171,10 +217,12 @@ } void StatusIconLinuxDbus::UpdatePlatformContextMenu(ui::MenuModel* model) { + DCHECK_CURRENTLY_ON(content::BrowserThread::UI); UpdateMenuImpl(model, true); } void StatusIconLinuxDbus::RefreshPlatformContextMenu() { + DCHECK_CURRENTLY_ON(content::BrowserThread::UI); // This codepath gets called for property changes like changed labels or // icons, but also for layout changes like deleted items. // TODO(thomasanderson): Split this into two methods so we can avoid @@ -183,11 +231,20 @@ } void StatusIconLinuxDbus::ExecuteCommand(int command_id, int event_flags) { + DCHECK_CURRENTLY_ON(content::BrowserThread::UI); DCHECK_EQ(command_id, 0); delegate_->OnClick(); } +StatusIconLinuxDbus::~StatusIconLinuxDbus() { + DCHECK_CURRENTLY_ON(content::BrowserThread::UI); + bus_->GetDBusTaskRunner()->PostTask( + FROM_HERE, base::BindOnce(&dbus::Bus::ShutdownAndBlock, bus_)); + CleanupIconFile(); +} + void StatusIconLinuxDbus::CheckStatusNotifierWatcherHasOwner() { + DCHECK_CURRENTLY_ON(content::BrowserThread::UI); dbus::ObjectProxy* bus_proxy = bus_->GetObjectProxy(DBUS_SERVICE_DBUS, dbus::ObjectPath(DBUS_PATH_DBUS)); dbus::MethodCall method_call(DBUS_INTERFACE_DBUS, kMethodNameHasOwner); @@ -200,6 +257,7 @@ } void StatusIconLinuxDbus::OnNameHasOwnerResponse(dbus::Response* response) { + DCHECK_CURRENTLY_ON(content::BrowserThread::UI); dbus::MessageReader reader(response); bool owned = false; if (!response || !reader.PopBool(&owned) || !owned) { @@ -221,6 +279,7 @@ } void StatusIconLinuxDbus::OnHostRegisteredResponse(dbus::Response* response) { + DCHECK_CURRENTLY_ON(content::BrowserThread::UI); if (!response) { delegate_->OnImplInitializationFailed(); return; @@ -242,6 +301,7 @@ void StatusIconLinuxDbus::OnOwnership(const std::string& service_name, bool success) { + DCHECK_CURRENTLY_ON(content::BrowserThread::UI); if (!success) { delegate_->OnImplInitializationFailed(); return; @@ -291,27 +351,28 @@ set_property(kPropertyAttentionIconName, DbusString("")); set_property(kPropertyAttentionMovieName, DbusString("")); set_property(kPropertyCategory, DbusString(kPropertyValueCategory)); - set_property(kPropertyIconName, DbusString("")); set_property(kPropertyId, DbusString(PropertyIdFromId(service_id_))); set_property(kPropertyOverlayIconName, DbusString("")); set_property(kPropertyStatus, DbusString(kPropertyValueStatus)); set_property(kPropertyTitle, DbusString("")); set_property(kPropertyAttentionIconPixmap, DbusArray<DbusStruct<DbusInt32, DbusInt32, DbusByteArray>>()); - set_property(kPropertyIconPixmap, MakeDbusImage(delegate_->GetImage())); set_property(kPropertyOverlayIconPixmap, DbusArray<DbusStruct<DbusInt32, DbusInt32, DbusByteArray>>()); set_property(kPropertyToolTip, MakeDbusToolTip(base::UTF16ToUTF8(delegate_->GetToolTip()))); + SetIconImpl(delegate_->GetImage(), false); } void StatusIconLinuxDbus::OnExported(const std::string& interface_name, const std::string& method_name, bool success) { + DCHECK_CURRENTLY_ON(content::BrowserThread::UI); barrier_.Run(success); } void StatusIconLinuxDbus::OnInitialized(bool success) { + DCHECK_CURRENTLY_ON(content::BrowserThread::UI); if (!success) { delegate_->OnImplInitializationFailed(); return; @@ -327,6 +388,7 @@ } void StatusIconLinuxDbus::OnRegistered(dbus::Response* response) { + DCHECK_CURRENTLY_ON(content::BrowserThread::UI); if (!response) delegate_->OnImplInitializationFailed(); } @@ -334,6 +396,7 @@ void StatusIconLinuxDbus::OnActivate( dbus::MethodCall* method_call, dbus::ExportedObject::ResponseSender sender) { + DCHECK_CURRENTLY_ON(content::BrowserThread::UI); delegate_->OnClick(); sender.Run(dbus::Response::FromMethodCall(method_call)); } @@ -341,6 +404,7 @@ void StatusIconLinuxDbus::OnContextMenu( dbus::MethodCall* method_call, dbus::ExportedObject::ResponseSender sender) { + DCHECK_CURRENTLY_ON(content::BrowserThread::UI); dbus::MessageReader reader(method_call); int32_t x; int32_t y; @@ -364,6 +428,7 @@ void StatusIconLinuxDbus::OnScroll( dbus::MethodCall* method_call, dbus::ExportedObject::ResponseSender sender) { + DCHECK_CURRENTLY_ON(content::BrowserThread::UI); // Ignore scroll events. sender.Run(dbus::Response::FromMethodCall(method_call)); } @@ -371,6 +436,7 @@ void StatusIconLinuxDbus::OnSecondaryActivate( dbus::MethodCall* method_call, dbus::ExportedObject::ResponseSender sender) { + DCHECK_CURRENTLY_ON(content::BrowserThread::UI); // Intentionally ignore secondary activations. In the future, we may decide // to run the same handler as regular activations. sender.Run(dbus::Response::FromMethodCall(method_call)); @@ -378,6 +444,7 @@ void StatusIconLinuxDbus::UpdateMenuImpl(ui::MenuModel* model, bool send_signal) { + DCHECK_CURRENTLY_ON(content::BrowserThread::UI); if (!menu_) return; @@ -398,3 +465,56 @@ menu_->SetModel(concat_menu_.get(), send_signal); menu_runner_.reset(); } + +void StatusIconLinuxDbus::SetIconImpl(const gfx::ImageSkia& image, + bool send_signals) { + DCHECK_CURRENTLY_ON(content::BrowserThread::UI); + if (!properties_) + return; + + if (should_write_icon_to_file_) { + base::PostTaskAndReplyWithResult( + icon_task_runner_.get(), FROM_HERE, + base::BindOnce(WriteIconFile, icon_file_id_++, + gfx::Image(image).As1xPNGBytes()), + base::BindOnce(&StatusIconLinuxDbus::OnIconFileWritten, this)); + } else { + properties_->SetProperty(kInterfaceStatusNotifierItem, kPropertyIconPixmap, + MakeDbusImage(image), send_signals, false); + if (send_signals) { + dbus::Signal signal(kInterfaceStatusNotifierItem, kSignalNewIcon); + item_->SendSignal(&signal); + } + } +} + +void StatusIconLinuxDbus::OnIconFileWritten(const base::FilePath& icon_file) { + DCHECK_CURRENTLY_ON(content::BrowserThread::UI); + CleanupIconFile(); + icon_file_ = icon_file; + if (icon_file_.empty()) + return; + + properties_->SetProperty(kInterfaceStatusNotifierItem, kPropertyIconThemePath, + DbusString(icon_file_.DirName().value()), false); + properties_->SetProperty( + kInterfaceStatusNotifierItem, kPropertyIconName, + DbusString(icon_file_.BaseName().RemoveExtension().value()), false); + + dbus::Signal new_icon_theme_path_signal(kInterfaceStatusNotifierItem, + kSignalNewIconThemePath); + dbus::MessageWriter writer(&new_icon_theme_path_signal); + writer.AppendString(icon_file_.DirName().value()); + item_->SendSignal(&new_icon_theme_path_signal); + dbus::Signal new_icon_signal(kInterfaceStatusNotifierItem, kSignalNewIcon); + item_->SendSignal(&new_icon_signal); +} + +void StatusIconLinuxDbus::CleanupIconFile() { + DCHECK_CURRENTLY_ON(content::BrowserThread::UI); + if (!icon_file_.empty()) { + icon_task_runner_->PostTask( + FROM_HERE, (base::BindOnce(base::IgnoreResult(&base::DeleteFile), + icon_file_.DirName(), true))); + } +}
diff --git a/chrome/browser/ui/views/status_icons/status_icon_linux_dbus.h b/chrome/browser/ui/views/status_icons/status_icon_linux_dbus.h index 67121638..5e686af33 100644 --- a/chrome/browser/ui/views/status_icons/status_icon_linux_dbus.h +++ b/chrome/browser/ui/views/status_icons/status_icon_linux_dbus.h
@@ -8,8 +8,11 @@ #include <string> #include "base/callback_forward.h" +#include "base/files/file_path.h" #include "base/macros.h" +#include "base/memory/ref_counted.h" #include "base/memory/weak_ptr.h" +#include "base/sequenced_task_runner.h" #include "chrome/browser/ui/views/status_icons/concat_menu_model.h" #include "dbus/bus.h" #include "dbus/exported_object.h" @@ -29,10 +32,10 @@ // A status icon following the StatusNotifierItem specification. // https://www.freedesktop.org/wiki/Specifications/StatusNotifierItem/StatusNotifierItem/ class StatusIconLinuxDbus : public views::StatusIconLinux, - public ui::SimpleMenuModel::Delegate { + public ui::SimpleMenuModel::Delegate, + public base::RefCounted<StatusIconLinuxDbus> { public: StatusIconLinuxDbus(); - ~StatusIconLinuxDbus() override; // StatusIcon: void SetIcon(const gfx::ImageSkia& image) override; @@ -44,6 +47,10 @@ void ExecuteCommand(int command_id, int event_flags) override; private: + friend class base::RefCounted<StatusIconLinuxDbus>; + + ~StatusIconLinuxDbus() override; + // Step 0: send the request to verify that the StatusNotifierWatcher service // is owned. void CheckStatusNotifierWatcherHasOwner(); @@ -85,6 +92,12 @@ void UpdateMenuImpl(ui::MenuModel* model, bool send_signal); + void SetIconImpl(const gfx::ImageSkia& image, bool send_signals); + + void OnIconFileWritten(const base::FilePath& icon_file); + + void CleanupIconFile(); + scoped_refptr<dbus::Bus> bus_; int service_id_ = 0; @@ -111,6 +124,11 @@ // our own menu. std::unique_ptr<views::MenuRunner> menu_runner_; + const bool should_write_icon_to_file_; + const scoped_refptr<base::SequencedTaskRunner> icon_task_runner_; + size_t icon_file_id_ = 0; + base::FilePath icon_file_; + base::WeakPtrFactory<StatusIconLinuxDbus> weak_factory_{this}; DISALLOW_COPY_AND_ASSIGN(StatusIconLinuxDbus);
diff --git a/chrome/browser/ui/views/status_icons/status_icon_linux_wrapper.cc b/chrome/browser/ui/views/status_icons/status_icon_linux_wrapper.cc index 1e1ca5c..070f1cf 100644 --- a/chrome/browser/ui/views/status_icons/status_icon_linux_wrapper.cc +++ b/chrome/browser/ui/views/status_icons/status_icon_linux_wrapper.cc
@@ -8,6 +8,7 @@ #include "base/feature_list.h" #include "base/memory/ptr_util.h" +#include "base/memory/scoped_refptr.h" #include "chrome/browser/ui/ui_features.h" #include "ui/message_center/public/cpp/notifier_id.h" #include "ui/views/linux_ui/linux_ui.h" @@ -42,11 +43,11 @@ } // namespace StatusIconLinuxWrapper::StatusIconLinuxWrapper( - std::unique_ptr<views::StatusIconLinux> status_icon, + views::StatusIconLinux* status_icon, StatusIconType status_icon_type, const gfx::ImageSkia& image, const base::string16& tool_tip) - : status_icon_(std::move(status_icon)), + : status_icon_(status_icon), status_icon_type_(status_icon_type), image_(GetBestImageRep(image)), tool_tip_(tool_tip), @@ -54,6 +55,28 @@ status_icon_->SetDelegate(this); } +#if defined(USE_DBUS) +StatusIconLinuxWrapper::StatusIconLinuxWrapper( + scoped_refptr<StatusIconLinuxDbus> status_icon, + const gfx::ImageSkia& image, + const base::string16& tool_tip) + : StatusIconLinuxWrapper(status_icon.get(), kTypeDbus, image, tool_tip) { + status_icon_dbus_ = status_icon; +} +#endif + +StatusIconLinuxWrapper::StatusIconLinuxWrapper( + std::unique_ptr<views::StatusIconLinux> status_icon, + StatusIconType status_icon_type, + const gfx::ImageSkia& image, + const base::string16& tool_tip) + : StatusIconLinuxWrapper(status_icon.get(), + status_icon_type, + image, + tool_tip) { + status_icon_linux_ = std::move(status_icon); +} + StatusIconLinuxWrapper::~StatusIconLinuxWrapper() { if (menu_model_) menu_model_->RemoveObserver(this); @@ -103,7 +126,9 @@ switch (status_icon_type_) { case kTypeDbus: #if defined(USE_X11) - status_icon_ = std::make_unique<StatusIconLinuxX11>(); + status_icon_dbus_.reset(); + status_icon_linux_ = std::make_unique<StatusIconLinuxX11>(); + status_icon_ = status_icon_linux_.get(); status_icon_type_ = kTypeX11; status_icon_->SetDelegate(this); return; @@ -113,7 +138,8 @@ FALLTHROUGH; #endif case kTypeX11: - status_icon_.reset(); + status_icon_linux_.reset(); + status_icon_ = nullptr; status_icon_type_ = kTypeOther; if (menu_model_) menu_model_->RemoveObserver(this); @@ -136,7 +162,7 @@ if (base::FeatureList::IsEnabled(features::kEnableDbusAndX11StatusIcons)) { #if defined(USE_DBUS) return base::WrapUnique(new StatusIconLinuxWrapper( - std::make_unique<StatusIconLinuxDbus>(), kTypeDbus, image, tool_tip)); + base::MakeRefCounted<StatusIconLinuxDbus>(), image, tool_tip)); #elif defined(USE_X11) return base::WrapUnique(new StatusIconLinuxWrapper( std::make_unique<StatusIconLinuxX11>(), kTypeX11, image, tool_tip));
diff --git a/chrome/browser/ui/views/status_icons/status_icon_linux_wrapper.h b/chrome/browser/ui/views/status_icons/status_icon_linux_wrapper.h index 6542b57e4..3e6feee6 100644 --- a/chrome/browser/ui/views/status_icons/status_icon_linux_wrapper.h +++ b/chrome/browser/ui/views/status_icons/status_icon_linux_wrapper.h
@@ -8,10 +8,13 @@ #include <memory> #include "base/macros.h" +#include "base/memory/scoped_refptr.h" #include "chrome/browser/status_icons/desktop_notification_balloon.h" #include "chrome/browser/status_icons/status_icon.h" #include "ui/views/linux_ui/status_icon_linux.h" +class StatusIconLinuxDbus; + // Wrapper class for StatusIconLinux that implements the standard StatusIcon // interface. Also handles callbacks from StatusIconLinux. class StatusIconLinuxWrapper : public StatusIcon, @@ -59,6 +62,15 @@ // A status icon wrapper should only be created by calling // CreateWrappedStatusIcon(). + StatusIconLinuxWrapper(views::StatusIconLinux* status_icon, + StatusIconType status_icon_type, + const gfx::ImageSkia& image, + const base::string16& tool_tip); +#if defined(USE_DBUS) + StatusIconLinuxWrapper(scoped_refptr<StatusIconLinuxDbus> status_icon, + const gfx::ImageSkia& image, + const base::string16& tool_tip); +#endif StatusIconLinuxWrapper(std::unique_ptr<views::StatusIconLinux> status_icon, StatusIconType status_icon_type, const gfx::ImageSkia& image, @@ -67,7 +79,14 @@ // Notification balloon. DesktopNotificationBalloon notification_; - std::unique_ptr<views::StatusIconLinux> status_icon_; + // The status icon may be ref-counted (via |status_icon_dbus_|) or owned by + // |this| (via |status_icon_linux_|). Either way, |status_icon_| points to + // the underlying object. +#if defined(USE_DBUS) + scoped_refptr<StatusIconLinuxDbus> status_icon_dbus_; +#endif + std::unique_ptr<views::StatusIconLinux> status_icon_linux_; + views::StatusIconLinux* status_icon_; StatusIconType status_icon_type_; gfx::ImageSkia image_;
diff --git a/chrome/browser/ui/views/tabs/new_tab_button.cc b/chrome/browser/ui/views/tabs/new_tab_button.cc index a59048b..89e1946 100644 --- a/chrome/browser/ui/views/tabs/new_tab_button.cc +++ b/chrome/browser/ui/views/tabs/new_tab_button.cc
@@ -132,11 +132,6 @@ return kClassName; } -void NewTabButton::Layout() { - views::ImageButton::Layout(); - ink_drop_container_->SetBoundsRect(GetLocalBounds()); -} - void NewTabButton::AddLayerBeneathView(ui::Layer* new_layer) { ink_drop_container_->AddLayerBeneathView(new_layer); } @@ -145,6 +140,14 @@ ink_drop_container_->RemoveLayerBeneathView(old_layer); } +void NewTabButton::OnBoundsChanged(const gfx::Rect& previous_bounds) { + ImageButton::OnBoundsChanged(previous_bounds); + ink_drop_container_->SetBoundsRect(GetLocalBounds()); + SetProperty( + views::kHighlightPathKey, + new SkPath(GetBorderPath(GetContentsBounds().origin(), 1.0f, false))); +} + #if defined(OS_WIN) void NewTabButton::OnMouseReleased(const ui::MouseEvent& event) { if (!event.IsOnlyRightMouseButton()) { @@ -184,13 +187,6 @@ PaintPlusIcon(canvas); } -void NewTabButton::OnBoundsChanged(const gfx::Rect& previous_bounds) { - ImageButton::OnBoundsChanged(previous_bounds); - SetProperty( - views::kHighlightPathKey, - new SkPath(GetBorderPath(GetContentsBounds().origin(), 1.0f, false))); -} - gfx::Size NewTabButton::CalculatePreferredSize() const { gfx::Size size = kButtonSize; const auto insets = GetInsets();
diff --git a/chrome/browser/ui/views/tabs/new_tab_button.h b/chrome/browser/ui/views/tabs/new_tab_button.h index b53bac3e..20e2de9 100644 --- a/chrome/browser/ui/views/tabs/new_tab_button.h +++ b/chrome/browser/ui/views/tabs/new_tab_button.h
@@ -61,10 +61,13 @@ // views::View: const char* GetClassName() const override; - void Layout() override; void AddLayerBeneathView(ui::Layer* new_layer) override; void RemoveLayerBeneathView(ui::Layer* old_layer) override; + protected: + // views::View: + void OnBoundsChanged(const gfx::Rect& previous_bounds) override; + private: // views::ImageButton: #if defined(OS_WIN) @@ -73,7 +76,6 @@ void OnGestureEvent(ui::GestureEvent* event) override; void NotifyClick(const ui::Event& event) override; void PaintButtonContents(gfx::Canvas* canvas) override; - void OnBoundsChanged(const gfx::Rect& previous_bounds) override; gfx::Size CalculatePreferredSize() const override; // views::MaskedTargeterDelegate:
diff --git a/chrome/browser/ui/views/tabs/tab_close_button.cc b/chrome/browser/ui/views/tabs/tab_close_button.cc index 767f5ab..0c99bea 100644 --- a/chrome/browser/ui/views/tabs/tab_close_button.cc +++ b/chrome/browser/ui/views/tabs/tab_close_button.cc
@@ -24,6 +24,7 @@ #include "ui/gfx/paint_vector_icon.h" #include "ui/views/animation/ink_drop.h" #include "ui/views/animation/ink_drop_mask.h" +#include "ui/views/layout/layout_provider.h" #include "ui/views/rect_based_targeting_utils.h" #include "ui/views/view_class_properties.h" @@ -71,6 +72,10 @@ color_utils::GetColorWithMaxContrast(background_color)); } +const char* TabCloseButton::GetClassName() const { + return "TabCloseButton"; +} + views::View* TabCloseButton::GetTooltipHandlerForPoint( const gfx::Point& point) { // Tab close button has no children, so tooltip handler should be the same @@ -90,16 +95,16 @@ return !event.IsMiddleMouseButton() && handled; } -void TabCloseButton::OnMouseMoved(const ui::MouseEvent& event) { - mouse_event_callback_.Run(this, event); - Button::OnMouseMoved(event); -} - void TabCloseButton::OnMouseReleased(const ui::MouseEvent& event) { mouse_event_callback_.Run(this, event); Button::OnMouseReleased(event); } +void TabCloseButton::OnMouseMoved(const ui::MouseEvent& event) { + mouse_event_callback_.Run(this, event); + Button::OnMouseMoved(event); +} + void TabCloseButton::OnGestureEvent(ui::GestureEvent* event) { // Consume all gesture events here so that the parent (Tab) does not // start consuming gestures. @@ -107,18 +112,6 @@ event->SetHandled(); } -const char* TabCloseButton::GetClassName() const { - return "TabCloseButton"; -} - -void TabCloseButton::Layout() { - ImageButton::Layout(); - auto path = std::make_unique<SkPath>(); - gfx::Point center = GetContentsBounds().CenterPoint(); - path->addCircle(center.x(), center.y(), GetWidth() / 2); - SetProperty(views::kHighlightPathKey, path.release()); -} - gfx::Size TabCloseButton::CalculatePreferredSize() const { int width = GetWidth(); gfx::Size size(width, width); @@ -127,10 +120,23 @@ return size; } +void TabCloseButton::OnBoundsChanged(const gfx::Rect& previous_bounds) { + ImageButton::OnBoundsChanged(previous_bounds); + auto path = std::make_unique<SkPath>(); + const gfx::Rect bounds = GetContentsBounds(); + const gfx::Point center = bounds.CenterPoint(); + const int radius = views::LayoutProvider::Get()->GetCornerRadiusMetric( + views::EMPHASIS_MAXIMUM, bounds.size()); + path->addCircle(center.x(), center.y(), radius); + SetProperty(views::kHighlightPathKey, path.release()); +} + std::unique_ptr<views::InkDropMask> TabCloseButton::CreateInkDropMask() const { + const gfx::Rect bounds = GetContentsBounds(); + const int radius = views::LayoutProvider::Get()->GetCornerRadiusMetric( + views::EMPHASIS_MAXIMUM, bounds.size()); return std::make_unique<views::CircleInkDropMask>( - size(), GetMirroredRect(GetContentsBounds()).CenterPoint(), - GetWidth() / 2); + size(), GetMirroredRect(bounds).CenterPoint(), radius); } void TabCloseButton::PaintButtonContents(gfx::Canvas* canvas) {
diff --git a/chrome/browser/ui/views/tabs/tab_close_button.h b/chrome/browser/ui/views/tabs/tab_close_button.h index 9aa7a1a..ccf1e6b 100644 --- a/chrome/browser/ui/views/tabs/tab_close_button.h +++ b/chrome/browser/ui/views/tabs/tab_close_button.h
@@ -38,17 +38,18 @@ void SetIconColors(SkColor foreground_color, SkColor background_color); // views::ImageButton: + const char* GetClassName() const override; View* GetTooltipHandlerForPoint(const gfx::Point& point) override; bool OnMousePressed(const ui::MouseEvent& event) override; - void OnMouseMoved(const ui::MouseEvent& event) override; void OnMouseReleased(const ui::MouseEvent& event) override; + void OnMouseMoved(const ui::MouseEvent& event) override; void OnGestureEvent(ui::GestureEvent* event) override; - const char* GetClassName() const override; - void Layout() override; - gfx::Size CalculatePreferredSize() const override; std::unique_ptr<views::InkDropMask> CreateInkDropMask() const override; protected: + // views::ImageButton: + gfx::Size CalculatePreferredSize() const override; + void OnBoundsChanged(const gfx::Rect& previous_bounds) override; void PaintButtonContents(gfx::Canvas* canvas) override; private:
diff --git a/chrome/browser/ui/webui/chromeos/add_supervision/add_supervision_handler.cc b/chrome/browser/ui/webui/chromeos/add_supervision/add_supervision_handler.cc index 2be869c..3d8c942d 100644 --- a/chrome/browser/ui/webui/chromeos/add_supervision/add_supervision_handler.cc +++ b/chrome/browser/ui/webui/chromeos/add_supervision/add_supervision_handler.cc
@@ -16,6 +16,7 @@ #include "chrome/browser/supervised_user/supervised_user_service.h" #include "chrome/browser/supervised_user/supervised_user_service_factory.h" #include "chrome/browser/ui/app_list/arc/arc_app_utils.h" +#include "chrome/browser/ui/webui/chromeos/add_supervision/add_supervision.mojom.h" #include "chrome/browser/ui/webui/chromeos/add_supervision/add_supervision_handler_utils.h" #include "chrome/browser/ui/webui/chromeos/add_supervision/add_supervision_metrics_recorder.h" #include "chrome/services/app_service/public/cpp/app_registry_cache.h" @@ -25,17 +26,20 @@ #include "components/user_manager/user_manager.h" #include "content/public/browser/web_ui.h" #include "google_apis/gaia/gaia_constants.h" +#include "mojo/public/cpp/bindings/pending_receiver.h" +#include "mojo/public/cpp/bindings/receiver.h" namespace chromeos { AddSupervisionHandler::AddSupervisionHandler( - add_supervision::mojom::AddSupervisionHandlerRequest request, + mojo::PendingReceiver<add_supervision::mojom::AddSupervisionHandler> + receiver, content::WebUI* web_ui, signin::IdentityManager* identity_manager, Delegate* delegate) : web_ui_(web_ui), identity_manager_(identity_manager), - binding_(this, std::move(request)), + receiver_(this, std::move(receiver)), delegate_(delegate) {} AddSupervisionHandler::~AddSupervisionHandler() = default;
diff --git a/chrome/browser/ui/webui/chromeos/add_supervision/add_supervision_handler.h b/chrome/browser/ui/webui/chromeos/add_supervision/add_supervision_handler.h index f6faafb..8310d5b 100644 --- a/chrome/browser/ui/webui/chromeos/add_supervision/add_supervision_handler.h +++ b/chrome/browser/ui/webui/chromeos/add_supervision/add_supervision_handler.h
@@ -9,7 +9,8 @@ #include "base/macros.h" #include "base/memory/weak_ptr.h" #include "chrome/browser/ui/webui/chromeos/add_supervision/add_supervision.mojom.h" -#include "mojo/public/cpp/bindings/binding.h" +#include "mojo/public/cpp/bindings/pending_receiver.h" +#include "mojo/public/cpp/bindings/receiver.h" namespace content { class WebUI; @@ -39,7 +40,8 @@ // |delegate| is owned by the caller and its lifetime must outlive |this|. AddSupervisionHandler( - add_supervision::mojom::AddSupervisionHandlerRequest request, + mojo::PendingReceiver<add_supervision::mojom::AddSupervisionHandler> + receiver, content::WebUI* web_ui, signin::IdentityManager* identity_manager, Delegate* delegate); @@ -64,7 +66,7 @@ signin::IdentityManager* identity_manager_; std::unique_ptr<signin::AccessTokenFetcher> oauth2_access_token_fetcher_; - mojo::Binding<add_supervision::mojom::AddSupervisionHandler> binding_; + mojo::Receiver<add_supervision::mojom::AddSupervisionHandler> receiver_; Delegate* delegate_;
diff --git a/chrome/browser/ui/webui/chromeos/add_supervision/add_supervision_ui.cc b/chrome/browser/ui/webui/chromeos/add_supervision/add_supervision_ui.cc index d920540..6579db4 100644 --- a/chrome/browser/ui/webui/chromeos/add_supervision/add_supervision_ui.cc +++ b/chrome/browser/ui/webui/chromeos/add_supervision/add_supervision_ui.cc
@@ -15,6 +15,7 @@ #include "chrome/browser/supervised_user/supervised_user_service.h" #include "chrome/browser/supervised_user/supervised_user_service_factory.h" #include "chrome/browser/ui/views/chrome_web_dialog_view.h" +#include "chrome/browser/ui/webui/chromeos/add_supervision/add_supervision.mojom.h" #include "chrome/browser/ui/webui/chromeos/add_supervision/add_supervision_handler_utils.h" #include "chrome/browser/ui/webui/chromeos/add_supervision/add_supervision_metrics_recorder.h" #include "chrome/browser/ui/webui/chromeos/add_supervision/confirm_signout_dialog.h" @@ -24,7 +25,7 @@ #include "components/google/core/common/google_util.h" #include "content/public/browser/web_ui.h" #include "content/public/browser/web_ui_data_source.h" -#include "mojo/public/cpp/bindings/binding.h" +#include "mojo/public/cpp/bindings/pending_receiver.h" #include "ui/base/resource/resource_bundle.h" #include "ui/resources/grit/ui_resources.h" #include "ui/web_dialogs/web_dialog_delegate.h" @@ -160,14 +161,15 @@ } void AddSupervisionUI::BindAddSupervisionHandler( - add_supervision::mojom::AddSupervisionHandlerRequest request) { + mojo::PendingReceiver<add_supervision::mojom::AddSupervisionHandler> + receiver) { signin::IdentityManager* identity_manager = test_identity_manager_ ? test_identity_manager_ : IdentityManagerFactory::GetForProfile(Profile::FromWebUI(web_ui())); mojo_api_handler_ = std::make_unique<AddSupervisionHandler>( - std::move(request), web_ui(), identity_manager, this); + std::move(receiver), web_ui(), identity_manager, this); } void AddSupervisionUI::SetUpResources() {
diff --git a/chrome/browser/ui/webui/chromeos/add_supervision/add_supervision_ui.h b/chrome/browser/ui/webui/chromeos/add_supervision/add_supervision_ui.h index 1c91c5e..a05b13f 100644 --- a/chrome/browser/ui/webui/chromeos/add_supervision/add_supervision_ui.h +++ b/chrome/browser/ui/webui/chromeos/add_supervision/add_supervision_ui.h
@@ -11,6 +11,7 @@ #include "chrome/browser/ui/webui/chromeos/add_supervision/add_supervision.mojom.h" #include "chrome/browser/ui/webui/chromeos/add_supervision/add_supervision_handler.h" #include "chrome/browser/ui/webui/chromeos/system_web_dialog_delegate.h" +#include "mojo/public/cpp/bindings/pending_receiver.h" #include "ui/base/ui_base_types.h" #include "ui/gfx/native_widget_types.h" #include "ui/views/controls/label.h" @@ -68,7 +69,8 @@ private: void BindAddSupervisionHandler( - add_supervision::mojom::AddSupervisionHandlerRequest request); + mojo::PendingReceiver<add_supervision::mojom::AddSupervisionHandler> + receiver); void SetUpResources(); GURL GetAddSupervisionURL();
diff --git a/chrome/browser/ui/webui/crashes_ui.cc b/chrome/browser/ui/webui/crashes_ui.cc index d150c2c..ade6add 100644 --- a/chrome/browser/ui/webui/crashes_ui.cc +++ b/chrome/browser/ui/webui/crashes_ui.cc
@@ -37,6 +37,10 @@ #include "chromeos/dbus/debug_daemon_client.h" #endif +#if defined(OS_LINUX) +#include "components/crash/content/app/crashpad.h" +#endif + using content::WebContents; using content::WebUIMessageHandler; @@ -168,20 +172,23 @@ system_crash_reporter = true; #endif - bool upload_list = crash_reporting_enabled; - bool support_manual_uploads = false; - + bool using_crashpad = false; #if defined(OS_WIN) || defined(OS_MACOSX) || defined(OS_ANDROID) - // Maunal uploads currently are supported only for Crashpad-using platforms - // and Android, and only if crash uploads are not disabled by policy. - support_manual_uploads = - crash_reporting_enabled || !IsMetricsReportingPolicyManaged(); - - // Show crash reports regardless of |crash_reporting_enabled| so that users - // can manually upload those reports. - upload_list = true; + using_crashpad = true; +#elif defined(OS_LINUX) + using_crashpad = crash_reporter::IsCrashpadEnabled(); #endif + // Manual uploads currently are supported only for Crashpad-using platforms + // and only if crash uploads are not disabled by policy. + bool support_manual_uploads = + using_crashpad && + (crash_reporting_enabled || !IsMetricsReportingPolicyManaged()); + + // Show crash reports regardless of |crash_reporting_enabled| when using + // Crashpad so that users can manually upload those reports. + bool upload_list = using_crashpad || crash_reporting_enabled; + base::ListValue crash_list; if (upload_list) crash_reporter::UploadListToValue(upload_list_.get(), &crash_list);
diff --git a/chrome/browser/ui/webui/settings/chromeos/os_settings_ui.cc b/chrome/browser/ui/webui/settings/chromeos/os_settings_ui.cc index 8740d7a..46dc4431 100644 --- a/chrome/browser/ui/webui/settings/chromeos/os_settings_ui.cc +++ b/chrome/browser/ui/webui/settings/chromeos/os_settings_ui.cc
@@ -157,7 +157,8 @@ html_source->AddResourcePath("app-management/image_info.mojom-lite.js", IDR_APP_MANAGEMENT_IMAGE_INFO_MOJO_LITE_JS); - ::settings::AddLocalizedStrings(html_source, profile); + ::settings::AddLocalizedStrings(html_source, profile, + web_ui->GetWebContents()); auto plural_string_handler = std::make_unique<PluralStringHandler>(); plural_string_handler->AddLocalizedString("profileLabel",
diff --git a/chrome/browser/ui/webui/settings/search_engines_handler.cc b/chrome/browser/ui/webui/settings/search_engines_handler.cc index 37eab48..6f0374d 100644 --- a/chrome/browser/ui/webui/settings/search_engines_handler.cc +++ b/chrome/browser/ui/webui/settings/search_engines_handler.cc
@@ -108,8 +108,7 @@ list_controller_.table_model()->IndexOfTemplateURL(default_engine); // Build the first list (default search engines). - std::unique_ptr<base::ListValue> defaults = - std::make_unique<base::ListValue>(); + auto defaults = std::make_unique<base::ListValue>(); int last_default_engine_index = list_controller_.table_model()->last_search_engine_index(); @@ -122,7 +121,7 @@ } // Build the second list (other search engines). - std::unique_ptr<base::ListValue> others = std::make_unique<base::ListValue>(); + auto others = std::make_unique<base::ListValue>(); int last_other_engine_index = list_controller_.table_model()->last_other_engine_index(); @@ -135,8 +134,7 @@ } // Build the third list (omnibox extensions). - std::unique_ptr<base::ListValue> extensions = - std::make_unique<base::ListValue>(); + auto extensions = std::make_unique<base::ListValue>(); int engine_count = list_controller_.table_model()->RowCount(); // Sanity check for https://crbug.com/781703. @@ -146,8 +144,7 @@ extensions->Append(CreateDictionaryForEngine(i, i == default_index)); } - std::unique_ptr<base::DictionaryValue> search_engines_info( - new base::DictionaryValue); + auto search_engines_info = std::make_unique<base::DictionaryValue>(); search_engines_info->Set("defaults", std::move(defaults)); search_engines_info->Set("others", std::move(others)); search_engines_info->Set("extensions", std::move(extensions)); @@ -185,7 +182,7 @@ // chrome/browser/resources/settings/search_engines_page/ // in @typedef for SearchEngine. Please update it whenever you add or remove // any keys here. - std::unique_ptr<base::DictionaryValue> dict(new base::DictionaryValue()); + auto dict = std::make_unique<base::DictionaryValue>(); dict->SetInteger("id", template_url->id()); dict->SetString("name", template_url->short_name()); dict->SetString("displayName",
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 c006d1ef..1c69a5fa 100644 --- a/chrome/browser/ui/webui/settings/settings_localized_strings_provider.cc +++ b/chrome/browser/ui/webui/settings/settings_localized_strings_provider.cc
@@ -33,7 +33,11 @@ #include "chrome/grit/chromium_strings.h" #include "chrome/grit/generated_resources.h" #include "chrome/grit/locale_settings.h" +#include "components/autofill/content/browser/content_autofill_driver.h" +#include "components/autofill/content/browser/content_autofill_driver_factory.h" #include "components/autofill/core/browser/autofill_experiments.h" +#include "components/autofill/core/browser/autofill_manager.h" +#include "components/autofill/core/browser/payments/credit_card_access_manager.h" #include "components/autofill/core/browser/payments/payments_service_url.h" #include "components/autofill/core/browser/payments/payments_util.h" #include "components/autofill/core/browser/personal_data_manager.h" @@ -1701,8 +1705,37 @@ base::size(kLocalizedStrings)); } +bool isUserFIDOVerifiable(autofill::PersonalDataManager* personal_data, + content::WebContents* web_contents) { + if (personal_data->GetSyncSigninState() != + autofill::AutofillSyncSigninState:: + kSignedInAndWalletSyncTransportEnabled && + personal_data->GetSyncSigninState() != + autofill::AutofillSyncSigninState::kSignedInAndSyncFeatureEnabled) { + return false; + } + + autofill::ContentAutofillDriverFactory* autofill_driver_factory = + autofill::ContentAutofillDriverFactory::FromWebContents(web_contents); + if (!autofill_driver_factory) + return false; + autofill::ContentAutofillDriver* autofill_driver = + autofill_driver_factory->DriverForFrame(web_contents->GetMainFrame()); + if (!autofill_driver) + return false; + autofill::AutofillManager* autofill_manager = + autofill_driver->autofill_manager(); + if (!autofill_manager) + return false; + + return autofill_manager->credit_card_access_manager() + ->GetOrCreateFIDOAuthenticator() + ->IsUserVerifiable(); +} + void AddAutofillStrings(content::WebUIDataSource* html_source, - Profile* profile) { + Profile* profile, + content::WebContents* web_contents) { static constexpr LocalizedString kLocalizedStrings[] = { {"autofillPageTitle", IDS_SETTINGS_AUTOFILL}, {"passwords", IDS_SETTINGS_PASSWORDS}, @@ -1715,6 +1748,9 @@ {"enableCreditCardsLabel", IDS_AUTOFILL_ENABLE_CREDIT_CARDS_TOGGLE_LABEL}, {"enableCreditCardsSublabel", IDS_AUTOFILL_ENABLE_CREDIT_CARDS_TOGGLE_SUBLABEL}, + {"enableCreditCardFIDOAuthLabel", IDS_ENABLE_CREDIT_CARD_FIDO_AUTH_LABEL}, + {"enableCreditCardFIDOAuthSublabel", + IDS_ENABLE_CREDIT_CARD_FIDO_AUTH_SUBLABEL}, {"addresses", IDS_AUTOFILL_ADDRESSES}, {"addressesTitle", IDS_AUTOFILL_ADDRESSES_SETTINGS_TITLE}, {"addAddressTitle", IDS_SETTINGS_AUTOFILL_ADDRESSES_ADD_TITLE}, @@ -1822,15 +1858,17 @@ #else // !defined(OS_CHROMEOS) is_guest_mode = profile->IsOffTheRecord(); #endif // defined(OS_CHROMEOS) + autofill::PersonalDataManager* personal_data = + autofill::PersonalDataManagerFactory::GetForProfile(profile); html_source->AddBoolean( "migrationEnabled", - !is_guest_mode && - autofill::IsCreditCardMigrationEnabled( - autofill::PersonalDataManagerFactory::GetForProfile(profile), - profile->GetPrefs(), - ProfileSyncServiceFactory::GetForProfile(profile), - /*is_test_mode=*/false, - /*log_manager=*/nullptr)); + !is_guest_mode && autofill::IsCreditCardMigrationEnabled( + personal_data, profile->GetPrefs(), + ProfileSyncServiceFactory::GetForProfile(profile), + /*is_test_mode=*/false, + /*log_manager=*/nullptr)); + html_source->AddBoolean("userIsFIDOVerifiable", + isUserFIDOVerifiable(personal_data, web_contents)); html_source->AddBoolean( "passwordsLeakDetectionEnabled", @@ -3339,10 +3377,11 @@ } // namespace void AddLocalizedStrings(content::WebUIDataSource* html_source, - Profile* profile) { + Profile* profile, + content::WebContents* web_contents) { AddA11yStrings(html_source); AddAboutStrings(html_source); - AddAutofillStrings(html_source, profile); + AddAutofillStrings(html_source, profile, web_contents); AddAppearanceStrings(html_source, profile); #if defined(OS_WIN) && BUILDFLAG(GOOGLE_CHROME_BRANDING)
diff --git a/chrome/browser/ui/webui/settings/settings_localized_strings_provider.h b/chrome/browser/ui/webui/settings/settings_localized_strings_provider.h index 1642eb7..a72290f4 100644 --- a/chrome/browser/ui/webui/settings/settings_localized_strings_provider.h +++ b/chrome/browser/ui/webui/settings/settings_localized_strings_provider.h
@@ -9,6 +9,7 @@ namespace content { class WebUIDataSource; +class WebContents; } namespace settings { @@ -17,7 +18,8 @@ // causes |html_source| to expose a strings.js file from its source which // contains a mapping from string's name to its translated value. void AddLocalizedStrings(content::WebUIDataSource* html_source, - Profile* profile); + Profile* profile, + content::WebContents* web_contents); } // namespace settings
diff --git a/chrome/browser/ui/webui/settings/settings_ui.cc b/chrome/browser/ui/webui/settings/settings_ui.cc index f0337c52..d20ae17 100644 --- a/chrome/browser/ui/webui/settings/settings_ui.cc +++ b/chrome/browser/ui/webui/settings/settings_ui.cc
@@ -47,7 +47,6 @@ #include "chrome/browser/ui/webui/settings/settings_security_key_handler.h" #include "chrome/browser/ui/webui/settings/settings_startup_pages_handler.h" #include "chrome/browser/ui/webui/settings/site_settings_handler.h" -#include "chrome/common/chrome_features.h" #include "chrome/common/pref_names.h" #include "chrome/common/url_constants.h" #include "chrome/grit/settings_resources.h" @@ -271,10 +270,6 @@ AccountConsistencyModeManager::IsDiceEnabledForProfile(profile)); #endif // !defined(OS_CHROMEOS) - html_source->AddBoolean( - "a11yEnhancements", - base::FeatureList::IsEnabled(features::kWebUIA11yEnhancements)); - html_source->AddBoolean("unifiedConsentEnabled", unified_consent::IsUnifiedConsentFeatureEnabled()); @@ -339,7 +334,7 @@ html_source->SetDefaultResource(IDR_SETTINGS_SETTINGS_HTML); #endif - AddLocalizedStrings(html_source, profile); + AddLocalizedStrings(html_source, profile, web_ui->GetWebContents()); ManagedUIHandler::Initialize(web_ui, html_source);
diff --git a/chrome/browser/vr/BUILD.gn b/chrome/browser/vr/BUILD.gn index ffbf1706..46b0cf6 100644 --- a/chrome/browser/vr/BUILD.gn +++ b/chrome/browser/vr/BUILD.gn
@@ -763,6 +763,7 @@ # Tests. sources += [ "webxr_vr_consent_dialog_browser_test.cc", + "webxr_vr_frame_loop_browser_test.cc", "webxr_vr_frame_pose_browser_test.cc", "webxr_vr_indicators_browser_test.cc", "webxr_vr_input_browser_test.cc",
diff --git a/chrome/browser/vr/webxr_vr_frame_loop_browser_test.cc b/chrome/browser/vr/webxr_vr_frame_loop_browser_test.cc new file mode 100644 index 0000000..4fd6200 --- /dev/null +++ b/chrome/browser/vr/webxr_vr_frame_loop_browser_test.cc
@@ -0,0 +1,108 @@ +// Copyright 2019 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#include <memory> + +#include "base/environment.h" +#include "base/run_loop.h" +#include "chrome/browser/vr/test/mock_xr_device_hook_base.h" +#include "chrome/browser/vr/test/multi_class_browser_test.h" +#include "chrome/browser/vr/test/ui_utils.h" +#include "chrome/browser/vr/test/webxr_vr_browser_test.h" + +namespace vr { + +namespace { + +class MyXRMock : public MockXRDeviceHookBase { + public: + void OnFrameSubmitted( + device_test::mojom::SubmittedFrameDataPtr frame_data, + device_test::mojom::XRTestHook::OnFrameSubmittedCallback callback) final; + + // The test waits for a submitted frame before returning. + void WaitForFrames(int count) { + DCHECK(!wait_loop_); + wait_frame_count_ = num_frames_submitted_ + count; + + base::RunLoop* wait_loop = + new base::RunLoop(base::RunLoop::Type::kNestableTasksAllowed); + wait_loop_ = wait_loop; + wait_loop->Run(); + delete wait_loop; + } + + int FramesSubmitted() const { return num_frames_submitted_; } + + private: + // Set to null on background thread after calling Quit(), so we can ensure we + // only call Quit once. + base::RunLoop* wait_loop_ = nullptr; + + int wait_frame_count_ = 0; + int num_frames_submitted_ = 0; +}; + +void MyXRMock::OnFrameSubmitted( + device_test::mojom::SubmittedFrameDataPtr frame_data, + device_test::mojom::XRTestHook::OnFrameSubmittedCallback callback) { + num_frames_submitted_++; + if (num_frames_submitted_ >= wait_frame_count_ && wait_frame_count_ > 0 && + wait_loop_) { + wait_loop_->Quit(); + wait_loop_ = nullptr; + } + + std::move(callback).Run(); +} + +} // namespace + +WEBXR_VR_ALL_RUNTIMES_BROWSER_TEST_F(TestNoStalledFrameLoop) { + MyXRMock my_mock; + + // Load the test page, and enter presentation. + t->LoadUrlAndAwaitInitialization( + t->GetFileUrlForHtmlTestFile("webxr_no_stalled_frame_loop")); + t->EnterSessionWithUserGestureOrFail(); + + // Wait for 2 frames to be submitted back to the device, but the js frame loop + // should've only been called once. + my_mock.WaitForFrames(2); + ASSERT_TRUE(t->RunJavaScriptAndExtractBoolOrFail("frame_count === 1")); + + // Now restart the frame loop and wait for another frame to get submitted. + t->RunJavaScriptOrFail("setBaseLayer()"); + t->PollJavaScriptBooleanOrFail("frame_count >= 2", + XrBrowserTestBase::kPollTimeoutMedium); + + t->AssertNoJavaScriptErrors(); +} + +WEBXR_VR_ALL_RUNTIMES_BROWSER_TEST_F(TestLateSetOfBaseLayer) { + MyXRMock my_mock; + + // Load the test page, and enter presentation. + t->LoadUrlAndAwaitInitialization( + t->GetFileUrlForHtmlTestFile("webxr_set_base_layer_late")); + t->EnterSessionWithUserGestureOrFail(); + + // Poll and have the javascript yield for 500 ms. This should give us enough + // time for any frame requests that were going to propagate to propagate. + t->RunJavaScriptOrFail("delayMilliseconds(500)"); + t->PollJavaScriptBooleanOrFail("delay_ended"); + + // No frames should have been submitted to either the JS or the runtime. + ASSERT_TRUE(t->RunJavaScriptAndExtractBoolOrFail("frame_count === 0")); + ASSERT_EQ(my_mock.FramesSubmitted(), 0); + + // Now restart the frame loop and wait for a frame to get submitted. + t->RunJavaScriptOrFail("setBaseLayer()"); + t->PollJavaScriptBooleanOrFail("frame_count >= 1", + XrBrowserTestBase::kPollTimeoutMedium); + + t->AssertNoJavaScriptErrors(); +} + +} // namespace vr
diff --git a/chrome/browser/web_applications/components/app_registrar.cc b/chrome/browser/web_applications/components/app_registrar.cc index 63fb5f73a..b5c625e8 100644 --- a/chrome/browser/web_applications/components/app_registrar.cc +++ b/chrome/browser/web_applications/components/app_registrar.cc
@@ -28,7 +28,7 @@ observers_.AddObserver(observer); } -void AppRegistrar::RemoveObserver(const AppRegistrarObserver* observer) { +void AppRegistrar::RemoveObserver(AppRegistrarObserver* observer) { observers_.RemoveObserver(observer); }
diff --git a/chrome/browser/web_applications/components/app_registrar.h b/chrome/browser/web_applications/components/app_registrar.h index 9582181..f4334f4d 100644 --- a/chrome/browser/web_applications/components/app_registrar.h +++ b/chrome/browser/web_applications/components/app_registrar.h
@@ -94,7 +94,7 @@ bool IsLocallyInstalled(const GURL& start_url) const; void AddObserver(AppRegistrarObserver* observer); - void RemoveObserver(const AppRegistrarObserver* observer); + void RemoveObserver(AppRegistrarObserver* observer); void NotifyWebAppInstalled(const AppId& app_id);
diff --git a/chrome/common/chrome_features.cc b/chrome/common/chrome_features.cc index 5eec67c..4cf3935 100644 --- a/chrome/common/chrome_features.cc +++ b/chrome/common/chrome_features.cc
@@ -826,10 +826,6 @@ // Compress remote-bound WebRTC event logs (if used; see kWebRtcRemoteEventLog). const base::Feature kWebRtcRemoteEventLogGzipped{ "WebRtcRemoteEventLogGzipped", base::FEATURE_ENABLED_BY_DEFAULT}; - -// Enable WebUI accessibility enhancements for review and testing. -const base::Feature kWebUIA11yEnhancements{"WebUIA11yEnhancements", - base::FEATURE_DISABLED_BY_DEFAULT}; #endif // Whether to enable "dark mode" enhancements in Mac Mojave or Windows 10 for
diff --git a/chrome/common/chrome_features.h b/chrome/common/chrome_features.h index dcbdee9..1395ff2 100644 --- a/chrome/common/chrome_features.h +++ b/chrome/common/chrome_features.h
@@ -518,8 +518,6 @@ extern const base::Feature kWebRtcRemoteEventLog; COMPONENT_EXPORT(CHROME_FEATURES) extern const base::Feature kWebRtcRemoteEventLogGzipped; -COMPONENT_EXPORT(CHROME_FEATURES) -extern const base::Feature kWebUIA11yEnhancements; #endif COMPONENT_EXPORT(CHROME_FEATURES) extern const base::Feature kWebUIDarkMode;
diff --git a/chrome/common/extensions/api/autofill_private.idl b/chrome/common/extensions/api/autofill_private.idl index b41477f7..b2709a5 100644 --- a/chrome/common/extensions/api/autofill_private.idl +++ b/chrome/common/extensions/api/autofill_private.idl
@@ -239,6 +239,9 @@ // Logs that the server cards edit link was clicked. static void logServerCardLinkClicked(); + + // Enables or disables FIDO Authentication for credit card unmasking. + static void setCreditCardFIDOAuthEnabledState(boolean enabled); }; interface Events {
diff --git a/chrome/installer/linux/BUILD.gn b/chrome/installer/linux/BUILD.gn index 709552f..44a5594 100644 --- a/chrome/installer/linux/BUILD.gn +++ b/chrome/installer/linux/BUILD.gn
@@ -29,6 +29,7 @@ packaging_files_executables = [ "$root_out_dir/chrome", "$root_out_dir/chrome_sandbox", + "$root_out_dir/crashpad_handler", ] packaging_files_shlibs = [] @@ -352,6 +353,7 @@ "//chrome:packed_resources", "//chrome/browser/resources/media/mei_preload:component", "//sandbox/linux:chrome_sandbox", + "//third_party/crashpad/crashpad/handler:crashpad_handler", ] if (enable_nacl) { public_deps += [
diff --git a/chrome/installer/linux/common/installer.include b/chrome/installer/linux/common/installer.include index b145f85..27393586 100644 --- a/chrome/installer/linux/common/installer.include +++ b/chrome/installer/linux/common/installer.include
@@ -140,6 +140,13 @@ STRIPPEDFILE="${BUILDDIR}/${PROGNAME}.stripped" install -m 755 "${STRIPPEDFILE}" "${STAGEDIR}/${INSTALLDIR}/${PROGNAME}" + # crashpad + buildfile="${BUILDDIR}/crashpad_handler" + strippedfile="${buildfile}.stripped" + debugfile="${buildfile}.debug" + "${BUILDDIR}/installer/common/eu-strip" -o "${strippedfile}" -f "${debugfile}" "${buildfile}" + install -m 755 "${strippedfile}" "${STAGEDIR}/${INSTALLDIR}/crashpad_handler" + # resources install -m 644 "${BUILDDIR}/resources.pak" "${STAGEDIR}/${INSTALLDIR}/" # TODO(mmoss): This has broken a couple times on adding new .pak files. Maybe
diff --git a/chrome/installer/mac/BUILD.gn b/chrome/installer/mac/BUILD.gn index 121a2db1..8b293d4 100644 --- a/chrome/installer/mac/BUILD.gn +++ b/chrome/installer/mac/BUILD.gn
@@ -7,6 +7,7 @@ import("//build/util/branding.gni") import("//build/util/version.gni") import("//chrome/process_version_rc_template.gni") +import("mac_signing_sources.gni") group("mac") { public_deps = [ @@ -34,18 +35,6 @@ ] } -_mac_signing_sources = [ - "signing/__init__.py", - "signing/commands.py", - "signing/chromium_config.py", - "signing/config.py", - "signing/model.py", - "signing/modification.py", - "signing/notarize.py", - "signing/pipeline.py", - "signing/signing.py", -] - copy("copy_signing") { visibility = [ ":copies" ] @@ -53,7 +42,7 @@ ":sign_config", ] - sources = _mac_signing_sources + sources = mac_signing_sources if (is_chrome_branded) { sources += [ "internal/internal_config.py" ] @@ -119,7 +108,7 @@ } group("mac_signing_tests") { - data = _mac_signing_sources + [ + data = mac_signing_sources + [ "signing/commands_test.py", "signing/model_test.py", "signing/modification_test.py",
diff --git a/chrome/installer/mac/mac_signing_sources.gni b/chrome/installer/mac/mac_signing_sources.gni new file mode 100644 index 0000000..5b86d51 --- /dev/null +++ b/chrome/installer/mac/mac_signing_sources.gni
@@ -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. + +mac_signing_sources = [ + "signing/__init__.py", + "signing/commands.py", + "signing/chromium_config.py", + "signing/config.py", + "signing/model.py", + "signing/modification.py", + "signing/notarize.py", + "signing/pipeline.py", + "signing/signing.py", +]
diff --git a/chrome/renderer/v8_unwinder_unittest.cc b/chrome/renderer/v8_unwinder_unittest.cc index 0bf58c8..0d52efc2 100644 --- a/chrome/renderer/v8_unwinder_unittest.cc +++ b/chrome/renderer/v8_unwinder_unittest.cc
@@ -6,6 +6,8 @@ #include <algorithm> #include <memory> +#include <utility> +#include <vector> #include "base/bind.h" #include "base/callback.h" @@ -178,8 +180,7 @@ // Checks that unwinding from C++ through JavaScript and back into C++ succeeds. // NB: unwinding is only supported for 64 bit Windows and OS X. -#if (defined(OS_WIN) && defined(ARCH_CPU_64_BITS)) || \ - (defined(OS_MACOSX) && !defined(OS_IOS)) +#if (defined(OS_WIN) && defined(ARCH_CPU_64_BITS)) || defined(OS_MACOSX) #define MAYBE_UnwindThroughV8Frames UnwindThroughV8Frames #else #define MAYBE_UnwindThroughV8Frames DISABLED_UnwindThroughV8Frames
diff --git a/chrome/test/BUILD.gn b/chrome/test/BUILD.gn index 76d9c00..f0beace 100644 --- a/chrome/test/BUILD.gn +++ b/chrome/test/BUILD.gn
@@ -3167,7 +3167,6 @@ "../browser/previews/previews_content_util_unittest.cc", "../browser/previews/previews_lite_page_decider_unittest.cc", "../browser/previews/previews_lite_page_infobar_delegate_unittest.cc", - "../browser/previews/previews_lite_page_navigation_throttle_unittest.cc", "../browser/previews/previews_lite_page_predictor_unittest.cc", "../browser/previews/previews_lite_page_url_loader_interceptor_unittest.cc", "../browser/previews/previews_offline_helper_unittest.cc", @@ -3846,6 +3845,7 @@ "../browser/ui/search/search_ipc_router_policy_unittest.cc", "../browser/ui/search/search_ipc_router_unittest.cc", "../browser/ui/search/search_tab_helper_unittest.cc", + "../browser/ui/send_tab_to_self/send_tab_to_self_sub_menu_model_unittest.cc", "../browser/ui/serial/serial_chooser_controller_unittest.cc", "../browser/ui/tab_contents/tab_contents_iterator_unittest.cc", "../browser/ui/tabs/pinned_tab_codec_unittest.cc", @@ -6012,6 +6012,7 @@ "../browser/sync/test/integration/single_client_autofill_profile_sync_test.cc", "../browser/sync/test/integration/single_client_bookmarks_sync_test.cc", "../browser/sync/test/integration/single_client_custom_passphrase_sync_test.cc", + "../browser/sync/test/integration/single_client_device_info_sync_test.cc", "../browser/sync/test/integration/single_client_dictionary_sync_test.cc", "../browser/sync/test/integration/single_client_directory_sync_test.cc", "../browser/sync/test/integration/single_client_extensions_sync_test.cc",
diff --git a/chrome/test/data/extensions/api_test/webrequest/framework.js b/chrome/test/data/extensions/api_test/webrequest/framework.js index dd854dd..edfd83db 100644 --- a/chrome/test/data/extensions/api_test/webrequest/framework.js +++ b/chrome/test/data/extensions/api_test/webrequest/framework.js
@@ -43,7 +43,7 @@ // This is a debugging aid to print all received events as well as the // information whether they were expected. -var logAllRequests = false; +var debug = false; // Runs the |tests| using the |tab| as a default tab. function runTestsForTab(tests, tab) { @@ -60,7 +60,14 @@ // Creates an "about:blank" tab and runs |tests| with this tab as default. function runTests(tests) { chrome.test.getConfig(function(config) { + if (config.customArg == 'debug') + debug = true; + var waitForAboutBlank = function(_, info, tab) { + if (debug) { + console.log("tabs.OnUpdated received in waitForAboutBlank: " + + JSON.stringify(info) + " " + JSON.stringify(tab)); + } if (info.status == "complete" && tab.url == "about:blank") { chrome.tabs.onUpdated.removeListener(waitForAboutBlank); runTestsForTab(tests, tab); @@ -119,6 +126,10 @@ function navigateAndWait(url, callback) { var done = chrome.test.listenForever(chrome.tabs.onUpdated, function (_, info, tab) { + if (debug) { + console.log("tabs.OnUpdated received in navigateAndWait: " + + JSON.stringify(info) + " " + JSON.stringify(tab)); + } if (tab.id == tabId && info.status == "complete") { if (callback) callback(tab); done(); @@ -372,8 +383,9 @@ var retval; var retval_function; if (matchingExpectedEvent) { - if (logAllRequests) { - console.log("Expected: " + name + ": " + JSON.stringify(details)); + if (debug) { + console.log("Expected event received: " + name + ": " + + JSON.stringify(details)); } capturedEventData.push( {label: matchingExpectedEvent.label, event: name, details: details}); @@ -387,8 +399,9 @@ retval = matchingExpectedEvent.retval; retval_function = matchingExpectedEvent.retval_function; } else { - if (logAllRequests) { - console.log('NOT Expected: ' + name + ': ' + JSON.stringify(details)); + if (debug) { + console.log('NOT Expected event received: ' + name + ': ' + + JSON.stringify(details)); } capturedUnexpectedData.push({event: name, details: details}); }
diff --git a/chrome/test/data/pdf/basic_test.js b/chrome/test/data/pdf/basic_test.js index ffe9f34..eba0c6ca0 100644 --- a/chrome/test/data/pdf/basic_test.js +++ b/chrome/test/data/pdf/basic_test.js
@@ -67,7 +67,7 @@ // Clicking on the plugin should close the bookmarks menu. chrome.test.assertFalse(dropdown.dropdownOpen); - MockInteractions.tap(dropdown.$.button); + dropdown.$.button.click(); chrome.test.assertTrue(dropdown.dropdownOpen); // Generate pointer event manually, as MockInteractions doesn't include // this. @@ -75,7 +75,7 @@ chrome.test.assertFalse(dropdown.dropdownOpen, "Clicking plugin closes dropdown"); - MockInteractions.tap(dropdown.$.button); + dropdown.$.button.click(); chrome.test.assertTrue(dropdown.dropdownOpen); MockInteractions.pressAndReleaseKeyOn(document, ESC_KEY); chrome.test.assertFalse(dropdown.dropdownOpen,
diff --git a/chrome/test/data/pdf/bookmarks_test.js b/chrome/test/data/pdf/bookmarks_test.js index f244b15b..cf6ba76 100644 --- a/chrome/test/data/pdf/bookmarks_test.js +++ b/chrome/test/data/pdf/bookmarks_test.js
@@ -60,7 +60,7 @@ var rootBookmarks = bookmarkContent.shadowRoot.querySelectorAll('viewer-bookmark'); chrome.test.assertEq(3, rootBookmarks.length, "three root bookmarks"); - MockInteractions.tap(rootBookmarks[0].$.expand); + rootBookmarks[0].$.expand.click(); Polymer.dom.flush(); @@ -96,7 +96,7 @@ lastXChange = undefined; lastYChange = undefined; lastUriNavigation = undefined; - MockInteractions.tap(tapTarget); + tapTarget.click(); chrome.test.assertEq(expectedEvent.page, lastPageChange); chrome.test.assertEq(expectedEvent.x, lastXChange); chrome.test.assertEq(expectedEvent.y, lastYChange);
diff --git a/chrome/test/data/pdf/material_elements_test.js b/chrome/test/data/pdf/material_elements_test.js index 6492926..fd5c7fd 100644 --- a/chrome/test/data/pdf/material_elements_test.js +++ b/chrome/test/data/pdf/material_elements_test.js
@@ -35,8 +35,8 @@ * past document bounds. */ function testPageSelectorChange() { - var selector = - Polymer.Base.create('viewer-page-selector', {docLength: 1234}); + var selector = document.createElement('viewer-page-selector'); + selector.docLength = 1234; document.body.appendChild(selector); var input = selector.pageSelector; @@ -75,8 +75,8 @@ * Test that viewer-page-selector changes in response to setting docLength. */ function testPageSelectorDocLength() { - var selector = - Polymer.Base.create('viewer-page-selector', {docLength: 1234}); + var selector = document.createElement('viewer-page-selector'); + selector.docLength = 1234; document.body.appendChild(selector); chrome.test.assertEq('1234', selector.$.pagelength.textContent); chrome.test.assertEq( @@ -88,23 +88,22 @@ * Test that clicking the dropdown icon opens/closes the dropdown. */ function testToolbarDropdownShowHide() { - var dropdown = Polymer.Base.create('viewer-toolbar-dropdown', { - header: 'Test Menu', - closedIcon: 'closedIcon', - openIcon: 'openIcon' - }); + var dropdown = document.createElement('viewer-toolbar-dropdown'); + dropdown.header = 'Test Menu'; + dropdown.closedIcon = 'closedIcon'; + dropdown.openIcon = 'openIcon'; document.body.appendChild(dropdown); const button = dropdown.$.button; chrome.test.assertFalse(dropdown.dropdownOpen); chrome.test.assertEq('closedIcon,cr:arrow-drop-down', button.ironIcon); - MockInteractions.tap(button); + button.click(); chrome.test.assertTrue(dropdown.dropdownOpen); chrome.test.assertEq('openIcon,cr:arrow-drop-down', button.ironIcon); - MockInteractions.tap(button); + button.click(); chrome.test.assertFalse(dropdown.dropdownOpen); @@ -134,7 +133,7 @@ bookmarkContent.shadowRoot.querySelectorAll('viewer-bookmark'); chrome.test.assertEq(1, rootBookmarks.length, "one root bookmark"); var rootBookmark = rootBookmarks[0]; - MockInteractions.tap(rootBookmark.$.expand); + rootBookmark.$.expand.click(); Polymer.dom.flush(); @@ -149,10 +148,10 @@ lastPageChange = e.detail.page; }); - MockInteractions.tap(rootBookmark.$.item); + rootBookmark.$.item.click(); chrome.test.assertEq(1, lastPageChange); - MockInteractions.tap(subBookmarks[1].$.item); + subBookmarks[1].$.item.click(); chrome.test.assertEq(3, lastPageChange); chrome.test.succeed(); @@ -180,17 +179,17 @@ chrome.test.assertTrue(button.ironIcon.endsWith(fitPageIcon)); // Tap 1: Fire fit-to-changed(FIT_TO_PAGE), show fit-to-width. - MockInteractions.tap(button); + button.click(); fitToEventChecker.assertEvent(FittingType.FIT_TO_PAGE, true); chrome.test.assertTrue(button.ironIcon.endsWith(fitWidthIcon)); // Tap 2: Fire fit-to-changed(FIT_TO_WIDTH), show fit-to-page. - MockInteractions.tap(button); + button.click(); fitToEventChecker.assertEvent(FittingType.FIT_TO_WIDTH, true); chrome.test.assertTrue(button.ironIcon.endsWith(fitPageIcon)); // Tap 3: Fire fit-to-changed(FIT_TO_PAGE) again. - MockInteractions.tap(button); + button.click(); fitToEventChecker.assertEvent(FittingType.FIT_TO_PAGE, true); chrome.test.assertTrue(button.ironIcon.endsWith(fitWidthIcon)); @@ -206,7 +205,7 @@ chrome.test.assertTrue(button.ironIcon.endsWith(fitPageIcon)); // Tap 4: Fire fit-to-changed(FIT_TO_PAGE) again. - MockInteractions.tap(button); + button.click(); fitToEventChecker.assertEvent(FittingType.FIT_TO_PAGE, true); chrome.test.assertTrue(button.ironIcon.endsWith(fitWidthIcon)); @@ -233,7 +232,7 @@ chrome.test.assertTrue(button.ironIcon.endsWith(fitWidthIcon)); // Tap 1: Fire fit-to-changed(FIT_TO_WIDTH). - MockInteractions.tap(button); + button.click(); fitToEventChecker.assertEvent(FittingType.FIT_TO_WIDTH, true); chrome.test.assertTrue(button.ironIcon.endsWith(fitPageIcon)); @@ -248,7 +247,7 @@ chrome.test.assertTrue(button.ironIcon.endsWith(fitWidthIcon)); // Tap 2: Fire fit-to-changed(FIT_TO_WIDTH). - MockInteractions.tap(button); + button.click(); fitToEventChecker.assertEvent(FittingType.FIT_TO_WIDTH, true); chrome.test.assertTrue(button.ironIcon.endsWith(fitPageIcon)); @@ -275,12 +274,12 @@ chrome.test.assertTrue(button.ironIcon.endsWith(fitPageIcon)); // Tap 1: Fire fit-to-changed(FIT_TO_PAGE). - MockInteractions.tap(button); + button.click(); fitToEventChecker.assertEvent(FittingType.FIT_TO_PAGE, true); chrome.test.assertTrue(button.ironIcon.endsWith(fitWidthIcon)); // Tap 2: Fire fit-to-changed(FIT_TO_WIDTH). - MockInteractions.tap(button); + button.click(); fitToEventChecker.assertEvent(FittingType.FIT_TO_WIDTH, true); chrome.test.assertTrue(button.ironIcon.endsWith(fitPageIcon)); @@ -290,7 +289,7 @@ chrome.test.assertTrue(button.ironIcon.endsWith(fitPageIcon)); // Tap 3: Fire fit-to-changed(FIT_TO_PAGE). - MockInteractions.tap(button); + button.click(); fitToEventChecker.assertEvent(FittingType.FIT_TO_PAGE, true); chrome.test.assertTrue(button.ironIcon.endsWith(fitWidthIcon));
diff --git a/chrome/test/data/pdf/toolbar_manager_test.js b/chrome/test/data/pdf/toolbar_manager_test.js index 2e2b041..124a600 100644 --- a/chrome/test/data/pdf/toolbar_manager_test.js +++ b/chrome/test/data/pdf/toolbar_manager_test.js
@@ -123,8 +123,8 @@ */ function testToolbarKeyboardNavigation() { var mockWindow = new MockWindow(1920, 1080); - var toolbar = - Polymer.Base.create('viewer-pdf-toolbar', {loadProgress: 100}); + var toolbar = document.createElement('viewer-pdf-toolbar'); + toolbar.loadProgress = 100; document.body.appendChild(toolbar); var zoomToolbar = document.createElement('viewer-zoom-toolbar'); document.body.appendChild(zoomToolbar); @@ -218,8 +218,8 @@ */ function testToolbarTouchInteraction() { var mockWindow = new MockWindow(1920, 1080); - var toolbar = - Polymer.Base.create('viewer-pdf-toolbar', {loadProgress: 100}); + var toolbar = document.createElement('viewer-pdf-toolbar'); + toolbar.loadProgress = 100; document.body.appendChild(toolbar); var zoomToolbar = document.createElement('viewer-zoom-toolbar'); document.body.appendChild(zoomToolbar);
diff --git a/chrome/test/data/webui/cr_elements/cr_drawer_tests.js b/chrome/test/data/webui/cr_elements/cr_drawer_tests.js index 977b8133..e5f7347 100644 --- a/chrome/test/data/webui/cr_elements/cr_drawer_tests.js +++ b/chrome/test/data/webui/cr_elements/cr_drawer_tests.js
@@ -7,7 +7,6 @@ // // #import {eventToPromise} from 'chrome://test/test_util.m.js'; // #import {flush} from 'chrome://resources/polymer/v3_0/polymer/polymer_bundled.min.js'; -// #import {tap} from 'chrome://resources/polymer/v3_0/iron-test-helpers/mock-interactions.js'; // clang-format on suite('cr-drawer', function() { @@ -37,7 +36,7 @@ assertTrue(drawer.open); // Clicking the content does not close the drawer. - MockInteractions.tap(document.querySelector('.drawer-content')); + document.querySelector('.drawer-content').click(); const whenClosed = test_util.eventToPromise('close', drawer); drawer.$.dialog.dispatchEvent(new MouseEvent('click', { @@ -60,7 +59,7 @@ }); }); - test('tapping icon closes drawer', async () => { + test('clicking icon closes drawer', async () => { // Create a drawer with an icon and open it. document.body.innerHTML = ` <cr-drawer id="drawer" align="ltr" icon-name="menu" icon-title="close"> @@ -71,8 +70,8 @@ drawer.openDrawer(); await test_util.eventToPromise('cr-drawer-opened', drawer); - // Tapping the icon closes the drawer. - MockInteractions.tap(drawer.$.iconButton); + // Clicking the icon closes the drawer. + drawer.$.iconButton.click(); await test_util.eventToPromise('close', drawer); assertFalse(drawer.open); assertTrue(drawer.wasCanceled());
diff --git a/chrome/test/data/webui/cr_elements/cr_profile_avatar_selector_tests.js b/chrome/test/data/webui/cr_elements/cr_profile_avatar_selector_tests.js index a47fa0c..4d7acdc 100644 --- a/chrome/test/data/webui/cr_elements/cr_profile_avatar_selector_tests.js +++ b/chrome/test/data/webui/cr_elements/cr_profile_avatar_selector_tests.js
@@ -63,7 +63,7 @@ const items = getGridItems(); // Simulate tapping the third avatar. - MockInteractions.tap(items[2]); + items[2].click(); assertEquals( 'chrome://avatar3.png', avatarSelector.selectedAvatar.url); assertFalse(items[0].classList.contains('iron-selected'));
diff --git a/chrome/test/data/webui/cr_elements/cr_toggle_test.js b/chrome/test/data/webui/cr_elements/cr_toggle_test.js index 83aa110..dc058f6 100644 --- a/chrome/test/data/webui/cr_elements/cr_toggle_test.js +++ b/chrome/test/data/webui/cr_elements/cr_toggle_test.js
@@ -4,7 +4,7 @@ // clang-format off // #import 'chrome://resources/cr_elements/cr_toggle/cr_toggle.m.js'; -// #import {keyEventOn, tap} from 'chrome://resources/polymer/v3_0/iron-test-helpers/mock-interactions.js'; +// #import {keyEventOn} from 'chrome://resources/polymer/v3_0/iron-test-helpers/mock-interactions.js'; // #import {eventToPromise} from 'chrome://test/test_util.m.js'; // clang-format on @@ -89,7 +89,7 @@ } toggle.dispatchEvent( new PointerEvent('pointerup', {pointerId: 1, clientX: xEnd})); - MockInteractions.tap(toggle); + toggle.click(); } // Test that the control is toggled when the |checked| attribute is
diff --git a/chrome/test/data/webui/cr_elements/cr_toolbar_search_field_tests.js b/chrome/test/data/webui/cr_elements/cr_toolbar_search_field_tests.js index 2d11201..3907a0a1 100644 --- a/chrome/test/data/webui/cr_elements/cr_toolbar_search_field_tests.js +++ b/chrome/test/data/webui/cr_elements/cr_toolbar_search_field_tests.js
@@ -6,7 +6,7 @@ // #import 'chrome://resources/cr_elements/cr_toolbar/cr_toolbar_search_field.m.js'; // // #import {flush} from 'chrome://resources/polymer/v3_0/polymer/polymer_bundled.min.js'; -// #import {blur, pressAndReleaseKeyOn, tap} from 'chrome://resources/polymer/v3_0/iron-test-helpers/mock-interactions.js'; +// #import {blur, pressAndReleaseKeyOn} from 'chrome://resources/polymer/v3_0/iron-test-helpers/mock-interactions.js'; // clang-format on /** @fileoverview Suite of tests for cr-toolbar-search-field. */ @@ -85,7 +85,7 @@ const clearSearch = field.$$('#clearSearch'); clearSearch.focus(); - MockInteractions.tap(clearSearch); + clearSearch.click(); assertTrue(field.showingSearch); assertEquals('', field.getValue()); assertEquals(field.$.searchInput, field.root.activeElement); @@ -98,7 +98,7 @@ Polymer.dom.flush(); assertEquals('query1', field.getValue()); - MockInteractions.tap(field.$$('#clearSearch')); + field.$$('#clearSearch').click(); assertTrue(field.showingSearch); assertEquals('', field.getValue());
diff --git a/chrome/test/data/webui/settings/payments_section_test.js b/chrome/test/data/webui/settings/payments_section_test.js index 1de01370..5eb49068 100644 --- a/chrome/test/data/webui/settings/payments_section_test.js +++ b/chrome/test/data/webui/settings/payments_section_test.js
@@ -7,11 +7,17 @@ test('testAutofillExtensionIndicator', function() { // Initializing with fake prefs const section = document.createElement('settings-payments-section'); - section.prefs = {autofill: {credit_card_enabled: {}}}; + section.prefs = { + autofill: {credit_card_enabled: {}, credit_card_fido_auth_enabled: {}} + }; document.body.appendChild(section); assertFalse(!!section.$$('#autofillExtensionIndicator')); - section.set('prefs.autofill.credit_card_enabled.extensionId', 'test-id'); + section.set( + 'prefs.autofill.credit_card_enabled.extensionId', 'test-id-1'); + section.set( + 'prefs.autofill.credit_card_fido_auth_enabled.extensionId', + 'test-id-2'); Polymer.dom.flush(); assertTrue(!!section.$$('#autofillExtensionIndicator')); @@ -442,5 +448,42 @@ assertFalse(section.$$('#migrateCreditCards').hidden); }); + + test('verifyFIDOAuthToggleShownIfUserIsVerifiable', function() { + // Set |userIsFIDOVerifiable| to true. + loadTimeData.overrideValues({userIsFIDOVerifiable: true}); + const section = + createPaymentsSection([], {credit_card_enabled: {value: true}}); + + assertTrue(!!section.$$('#autofillCreditCardFIDOAuthToggle')); + }); + + test('verifyFIDOAuthToggleNotShownIfUserIsNotVerifiable', function() { + // Set |userIsFIDOVerifiable| to false. + loadTimeData.overrideValues({userIsFIDOVerifiable: false}); + const section = + createPaymentsSection([], {credit_card_enabled: {value: true}}); + assertFalse(!!section.$$('#autofillCreditCardFIDOAuthToggle')); + }); + + test('verifyFIDOAuthToggleCheckedIfOptedIn', function() { + // Set FIDO auth pref value to true. + loadTimeData.overrideValues({userIsFIDOVerifiable: true}); + const section = createPaymentsSection([], { + credit_card_enabled: {value: true}, + credit_card_fido_auth_enabled: {value: true} + }); + assertTrue(section.$$('#autofillCreditCardFIDOAuthToggle').checked); + }); + + test('verifyFIDOAuthToggleUncheckedIfOptedOut', function() { + // Set FIDO auth pref value to false. + loadTimeData.overrideValues({userIsFIDOVerifiable: true}); + const section = createPaymentsSection([], { + credit_card_enabled: {value: true}, + credit_card_fido_auth_enabled: {value: false} + }); + assertFalse(section.$$('#autofillCreditCardFIDOAuthToggle').checked); + }); }); });
diff --git a/chrome/test/data/webui/tab_strip/tab_test.js b/chrome/test/data/webui/tab_strip/tab_test.js index 32df3c0d..6131e3c 100644 --- a/chrome/test/data/webui/tab_strip/tab_test.js +++ b/chrome/test/data/webui/tab_strip/tab_test.js
@@ -14,6 +14,7 @@ const tab = { id: 1001, + status: 'complete', title: 'My title', }; @@ -63,6 +64,13 @@ assertFalse(tabElement.hasAttribute('pinned')); }); + test('toggles a [loading] attribute when loading', () => { + tabElement.tab = Object.assign({}, tab, {status: 'loading'}); + assertTrue(tabElement.hasAttribute('loading')); + tabElement.tab = Object.assign({}, tab, {status: 'complete'}); + assertFalse(tabElement.hasAttribute('loading')); + }); + test('clicking on the element activates the tab', () => { tabElement.click(); return testTabsApiProxy.whenCalled('activateTab', tabId => { @@ -104,6 +112,15 @@ getFaviconForPageURL(expectedPageUrl, false)); }); + test( + 'removes the favicon if the tab is loading and there is no favicon URL', + () => { + delete tab.favIconUrl; + tabElement.tab = Object.assign({}, tab, {status: 'loading'}); + const faviconElement = tabElement.shadowRoot.querySelector('#favicon'); + assertEquals(faviconElement.style.backgroundImage, 'none'); + }); + test('hides the thumbnail if there is no source yet', () => { const thumbnailImage = tabElement.shadowRoot.querySelector('#thumbnailImg'); assertFalse(thumbnailImage.hasAttribute('src'));
diff --git a/chrome/test/data/xr/e2e_test_files/html/webxr_no_stalled_frame_loop.html b/chrome/test/data/xr/e2e_test_files/html/webxr_no_stalled_frame_loop.html new file mode 100644 index 0000000..5f438c00 --- /dev/null +++ b/chrome/test/data/xr/e2e_test_files/html/webxr_no_stalled_frame_loop.html
@@ -0,0 +1,36 @@ +<!doctype html> +<!-- +WebXR page that only submits one frame. +--> +<html> + <head> + <link rel="stylesheet" type="text/css" href="../resources/webxr_e2e.css"> + </head> + <body> + <canvas id="webgl-canvas"></canvas> + <script src="../resources/webxr_e2e.js"></script> + <script src="../resources/webxr_boilerplate.js"></script> + <script src="../../../../../../third_party/blink/web_tests/resources/testharness.js"></script> + <script> + var frame_count = 0; + var frame_expected = true; + onImmersiveXRFrameCallback = function() { + assert_true(frame_expected); + frame_count++; + + if (frame_count === 1) { + // No need to request an animationFrame because it should've been + // requested previously. + sessionInfos[sessionTypes.IMMERSIVE].session.updateRenderState({ baseLayer: null }); + frame_expected = false; + } + }; + + function setBaseLayer() { + let session = sessionInfos[sessionTypes.IMMERSIVE].session; + session.updateRenderState({ baseLayer: new XRWebGLLayer(session, gl) }); + frame_expected = true; + } + </script> + </body> +</html>
diff --git a/chrome/test/data/xr/e2e_test_files/html/webxr_set_base_layer_late.html b/chrome/test/data/xr/e2e_test_files/html/webxr_set_base_layer_late.html new file mode 100644 index 0000000..67cb91a --- /dev/null +++ b/chrome/test/data/xr/e2e_test_files/html/webxr_set_base_layer_late.html
@@ -0,0 +1,36 @@ +<!doctype html> +<!-- +WebXR page that only submits one frame. +--> +<html> + <head> + <link rel="stylesheet" type="text/css" href="../resources/webxr_e2e.css"> + </head> + <body> + <canvas id="webgl-canvas"></canvas> + <script src="../resources/webxr_e2e.js"></script> + <script src="../resources/webxr_boilerplate.js"></script> + <script src="../../../../../../third_party/blink/web_tests/resources/testharness.js"></script> + <script> + shouldSetBaseLayer = false; + var frame_count = 0; + var frame_expected = false; + var delay_ended = false; + onImmersiveXRFrameCallback = function() { + assert_true(frame_expected); + frame_count++; + }; + + function setBaseLayer() { + let session = sessionInfos[sessionTypes.IMMERSIVE].session; + session.updateRenderState({ baseLayer: new XRWebGLLayer(session, gl) }); + frame_expected = true; + } + + function delayMilliseconds(waitTime) { + delay_ended = false; + window.setTimeout(() => { delay_ended = true }, waitTime); + } + </script> + </body> +</html>
diff --git a/chrome/test/data/xr/e2e_test_files/resources/webxr_boilerplate.js b/chrome/test/data/xr/e2e_test_files/resources/webxr_boilerplate.js index 405c5b9..905b52f 100644 --- a/chrome/test/data/xr/e2e_test_files/resources/webxr_boilerplate.js +++ b/chrome/test/data/xr/e2e_test_files/resources/webxr_boilerplate.js
@@ -24,6 +24,7 @@ var shouldSubmitFrame = true; var hasPresentedFrame = false; var arSessionRequestWouldTriggerPermissionPrompt = null; +var shouldSetBaseLayer = true; var sessionTypes = Object.freeze({ IMMERSIVE: 1, @@ -164,7 +165,10 @@ onSessionStartedCallback(session); } - session.updateRenderState({ baseLayer: new XRWebGLLayer(session, gl) }); + if (shouldSetBaseLayer) { + session.updateRenderState({ baseLayer: new XRWebGLLayer(session, gl) }); + } + session.requestReferenceSpace(referenceSpaceMap[sessionType]) .then( (refSpace) => { sessionInfos[sessionType].currentRefSpace = refSpace;
diff --git a/chrome/tools/build/chromeos/FILES.cfg b/chrome/tools/build/chromeos/FILES.cfg index 76fe0da0..23ba4d2a 100644 --- a/chrome/tools/build/chromeos/FILES.cfg +++ b/chrome/tools/build/chromeos/FILES.cfg
@@ -41,6 +41,10 @@ 'buildtype': ['dev', 'official'], }, { + 'filename': 'crashpad_handler', + 'buildtype': ['dev', 'official'], + }, + { 'filename': 'icudtl.dat', 'buildtype': ['dev', 'official'], },
diff --git a/chrome/tools/build/linux/FILES.cfg b/chrome/tools/build/linux/FILES.cfg index 602432a..ca79c7d6 100644 --- a/chrome/tools/build/linux/FILES.cfg +++ b/chrome/tools/build/linux/FILES.cfg
@@ -48,6 +48,10 @@ 'buildtype': ['dev', 'official'], }, { + 'filename': 'crashpad_handler', + 'buildtype': ['dev', 'official'], + }, + { 'filename': 'icudtl.dat', 'buildtype': ['dev', 'official'], }, @@ -167,6 +171,12 @@ 'archive': 'breakpad-info.zip', }, { + 'filename': 'crashpad.breakpad.x64', + 'arch': ['64bit'], + 'buildtype': ['official'], + 'archive': 'breakpad-info.zip', + }, + { 'filename': 'swiftshader_libegl.breakpad.x64', 'arch': ['64bit'], 'buildtype': ['official'],
diff --git a/chromecast/browser/accessibility/accessibility_manager.cc b/chromecast/browser/accessibility/accessibility_manager.cc index fa3f7dfe..b4480ae 100644 --- a/chromecast/browser/accessibility/accessibility_manager.cc +++ b/chromecast/browser/accessibility/accessibility_manager.cc
@@ -7,6 +7,7 @@ #include "chromecast/graphics/accessibility/focus_ring_controller.h" #include "chromecast/graphics/accessibility/fullscreen_magnification_controller.h" #include "chromecast/graphics/cast_window_manager_aura.h" +#include "chromecast/graphics/cast_window_tree_host_aura.h" #include "ui/aura/window.h" #include "ui/aura/window_tree_host.h" #include "ui/wm/public/activation_client.h"
diff --git a/chromecast/graphics/BUILD.gn b/chromecast/graphics/BUILD.gn index bb0aaa0..d6d28fc 100644 --- a/chromecast/graphics/BUILD.gn +++ b/chromecast/graphics/BUILD.gn
@@ -53,6 +53,8 @@ "cast_touch_event_gate.h", "cast_window_manager_aura.cc", "cast_window_manager_aura.h", + "cast_window_tree_host_aura.cc", + "cast_window_tree_host_aura.h", "gestures/cast_system_gesture_dispatcher.cc", "gestures/cast_system_gesture_dispatcher.h", "gestures/cast_system_gesture_event_handler.cc",
diff --git a/chromecast/graphics/cast_external_begin_frame_source.cc b/chromecast/graphics/cast_external_begin_frame_source.cc index 5d305d76..f38eccc 100644 --- a/chromecast/graphics/cast_external_begin_frame_source.cc +++ b/chromecast/graphics/cast_external_begin_frame_source.cc
@@ -6,6 +6,7 @@ #include "base/time/time.h" #include "chromecast/graphics/cast_window_manager_aura.h" +#include "chromecast/graphics/cast_window_tree_host_aura.h" namespace chromecast { namespace {
diff --git a/chromecast/graphics/cast_window_manager_aura.cc b/chromecast/graphics/cast_window_manager_aura.cc index 3ab7e3fd..ea8865a0 100644 --- a/chromecast/graphics/cast_window_manager_aura.cc +++ b/chromecast/graphics/cast_window_manager_aura.cc
@@ -10,6 +10,7 @@ #include "chromecast/graphics/cast_focus_client_aura.h" #include "chromecast/graphics/cast_touch_activity_observer.h" #include "chromecast/graphics/cast_touch_event_gate.h" +#include "chromecast/graphics/cast_window_tree_host_aura.h" #include "chromecast/graphics/gestures/cast_system_gesture_event_handler.h" #include "chromecast/graphics/gestures/side_swipe_detector.h" #include "ui/aura/client/default_capture_client.h" @@ -17,9 +18,7 @@ #include "ui/aura/client/screen_position_client.h" #include "ui/aura/env.h" #include "ui/aura/layout_manager.h" -#include "ui/aura/null_window_targeter.h" #include "ui/aura/window.h" -#include "ui/aura/window_tree_host_platform.h" #include "ui/base/ime/init/input_method_factory.h" #include "ui/base/ime/input_method.h" #include "ui/display/display.h" @@ -81,39 +80,6 @@ } } -} // namespace - -CastWindowTreeHost::CastWindowTreeHost( - bool enable_input, - ui::PlatformWindowInitProperties properties, - bool use_external_frame_control) - : WindowTreeHostPlatform(std::move(properties), - nullptr, - nullptr, - use_external_frame_control), - enable_input_(enable_input) { - if (!enable_input) - window()->SetEventTargeter(std::make_unique<aura::NullWindowTargeter>()); -} - -CastWindowTreeHost::~CastWindowTreeHost() {} - -void CastWindowTreeHost::DispatchEvent(ui::Event* event) { - if (!enable_input_) { - return; - } - - WindowTreeHostPlatform::DispatchEvent(event); -} - -gfx::Rect CastWindowTreeHost::GetTransformedRootWindowBoundsInPixels( - const gfx::Size& host_size_in_pixels) const { - gfx::RectF new_bounds(WindowTreeHost::GetTransformedRootWindowBoundsInPixels( - host_size_in_pixels)); - new_bounds.set_origin(gfx::PointF()); - return gfx::ToEnclosingRect(new_bounds); -} - // A layout manager owned by the root window. class CastLayoutManager : public aura::LayoutManager { public: @@ -218,6 +184,8 @@ SetChildBoundsDirect(child, requested_bounds); } +} // namespace + CastWindowManagerAura::CastWindowManagerAura(bool enable_input) : enable_input_(enable_input) {} @@ -248,7 +216,7 @@ LOG(INFO) << "Starting window manager, bounds: " << host_bounds.ToString(); CHECK(aura::Env::GetInstance()); - window_tree_host_ = std::make_unique<CastWindowTreeHost>( + window_tree_host_ = std::make_unique<CastWindowTreeHostAura>( enable_input_, std::move(properties)); window_tree_host_->InitHost(); aura::Window* tree_window = window_tree_host_->window(); @@ -296,7 +264,7 @@ } } -CastWindowTreeHost* CastWindowManagerAura::window_tree_host() const { +CastWindowTreeHostAura* CastWindowManagerAura::window_tree_host() const { DCHECK(window_tree_host_); return window_tree_host_.get(); }
diff --git a/chromecast/graphics/cast_window_manager_aura.h b/chromecast/graphics/cast_window_manager_aura.h index f73a73c6..8b62f6b7 100644 --- a/chromecast/graphics/cast_window_manager_aura.h +++ b/chromecast/graphics/cast_window_manager_aura.h
@@ -28,27 +28,7 @@ class CastSystemGestureEventHandler; class CastSystemGestureDispatcher; class SideSwipeDetector; - -// An aura::WindowTreeHost that correctly converts input events. -class CastWindowTreeHost : public aura::WindowTreeHostPlatform { - public: - CastWindowTreeHost(bool enable_input, - ui::PlatformWindowInitProperties properties, - bool use_external_frame_control = false); - ~CastWindowTreeHost() override; - - // aura::WindowTreeHostPlatform implementation: - void DispatchEvent(ui::Event* event) override; - - // aura::WindowTreeHost implementation - gfx::Rect GetTransformedRootWindowBoundsInPixels( - const gfx::Size& size_in_pixels) const override; - - private: - const bool enable_input_; - - DISALLOW_COPY_AND_ASSIGN(CastWindowTreeHost); -}; +class CastWindowTreeHostAura; class CastWindowManagerAura : public CastWindowManager, public aura::client::WindowParentingClient { @@ -56,10 +36,6 @@ explicit CastWindowManagerAura(bool enable_input); ~CastWindowManagerAura() override; - aura::client::CaptureClient* capture_client() const { - return capture_client_.get(); - } - void Setup(); void OnWindowOrderChanged(std::vector<WindowId> window_order); @@ -72,27 +48,26 @@ void InjectEvent(ui::Event* event) override; void AddObserver(Observer* observer) override; void RemoveObserver(Observer* observer) override; - - // aura::client::WindowParentingClient implementation: - aura::Window* GetDefaultParent(aura::Window* window, - const gfx::Rect& bounds) override; - void AddGestureHandler(CastGestureHandler* handler) override; - void RemoveGestureHandler(CastGestureHandler* handler) override; - - CastWindowTreeHost* window_tree_host() const; - - CastGestureHandler* GetGestureHandler() const; - void SetTouchInputDisabled(bool disabled) override; void AddTouchActivityObserver(CastTouchActivityObserver* observer) override; void RemoveTouchActivityObserver( CastTouchActivityObserver* observer) override; + // aura::client::WindowParentingClient implementation: + aura::Window* GetDefaultParent(aura::Window* window, + const gfx::Rect& bounds) override; + + CastWindowTreeHostAura* window_tree_host() const; + CastGestureHandler* GetGestureHandler() const; + aura::client::CaptureClient* capture_client() const { + return capture_client_.get(); + } + private: const bool enable_input_; - std::unique_ptr<CastWindowTreeHost> window_tree_host_; + std::unique_ptr<CastWindowTreeHostAura> window_tree_host_; std::unique_ptr<aura::client::DefaultCaptureClient> capture_client_; std::unique_ptr<CastFocusClientAura> focus_client_; std::unique_ptr<aura::client::ScreenPositionClient> screen_position_client_;
diff --git a/chromecast/graphics/cast_window_tree_host_aura.cc b/chromecast/graphics/cast_window_tree_host_aura.cc new file mode 100644 index 0000000..82000ec --- /dev/null +++ b/chromecast/graphics/cast_window_tree_host_aura.cc
@@ -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. + +#include "chromecast/graphics/cast_window_tree_host_aura.h" + +#include "ui/aura/null_window_targeter.h" +#include "ui/platform_window/platform_window_init_properties.h" + +namespace chromecast { + +CastWindowTreeHostAura::CastWindowTreeHostAura( + bool enable_input, + ui::PlatformWindowInitProperties properties, + bool use_external_frame_control) + : WindowTreeHostPlatform(std::move(properties), + nullptr, + nullptr, + use_external_frame_control), + enable_input_(enable_input) { + if (!enable_input) + window()->SetEventTargeter(std::make_unique<aura::NullWindowTargeter>()); +} + +CastWindowTreeHostAura::~CastWindowTreeHostAura() {} + +void CastWindowTreeHostAura::DispatchEvent(ui::Event* event) { + if (!enable_input_) { + return; + } + + WindowTreeHostPlatform::DispatchEvent(event); +} + +gfx::Rect CastWindowTreeHostAura::GetTransformedRootWindowBoundsInPixels( + const gfx::Size& host_size_in_pixels) const { + gfx::RectF new_bounds(WindowTreeHost::GetTransformedRootWindowBoundsInPixels( + host_size_in_pixels)); + new_bounds.set_origin(gfx::PointF()); + return gfx::ToEnclosingRect(new_bounds); +} + +} // namespace chromecast
diff --git a/chromecast/graphics/cast_window_tree_host_aura.h b/chromecast/graphics/cast_window_tree_host_aura.h new file mode 100644 index 0000000..c7adc4c --- /dev/null +++ b/chromecast/graphics/cast_window_tree_host_aura.h
@@ -0,0 +1,35 @@ +// Copyright 2019 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#ifndef CHROMECAST_GRAPHICS_CAST_WINDOW_TREE_HOST_AURA_H_ +#define CHROMECAST_GRAPHICS_CAST_WINDOW_TREE_HOST_AURA_H_ + +#include "ui/aura/window_tree_host_platform.h" + +namespace chromecast { + +// An aura::WindowTreeHost that correctly converts input events. +class CastWindowTreeHostAura : public aura::WindowTreeHostPlatform { + public: + CastWindowTreeHostAura(bool enable_input, + ui::PlatformWindowInitProperties properties, + bool use_external_frame_control = false); + ~CastWindowTreeHostAura() override; + + // aura::WindowTreeHostPlatform implementation: + void DispatchEvent(ui::Event* event) override; + + // aura::WindowTreeHost implementation + gfx::Rect GetTransformedRootWindowBoundsInPixels( + const gfx::Size& size_in_pixels) const override; + + private: + const bool enable_input_; + + DISALLOW_COPY_AND_ASSIGN(CastWindowTreeHostAura); +}; + +} // namespace chromecast + +#endif // CHROMECAST_GRAPHICS_CAST_WINDOW_TREE_HOST_AURA_H_ \ No newline at end of file
diff --git a/chromecast/renderer/media/key_systems_cast.cc b/chromecast/renderer/media/key_systems_cast.cc index 321dff7..21166af 100644 --- a/chromecast/renderer/media/key_systems_cast.cc +++ b/chromecast/renderer/media/key_systems_cast.cc
@@ -127,20 +127,20 @@ codecs |= ::media::EME_CODEC_HEVC; #endif // BUILDFLAG(ENABLE_PLATFORM_HEVC) -#if BUILDFLAG(ENABLE_DOLBY_VISION_DEMUXING) +#if BUILDFLAG(ENABLE_PLATFORM_DOLBY_VISION) codecs |= ::media::EME_CODEC_DOLBY_VISION_AVC; #if BUILDFLAG(ENABLE_PLATFORM_HEVC) codecs |= ::media::EME_CODEC_DOLBY_VISION_HEVC; #endif // BUILDFLAG(ENABLE_PLATFORM_HEVC) -#endif // BUILDFLAG(ENABLE_DOLBY_VISION_DEMUXING) +#endif // BUILDFLAG(ENABLE_PLATFORM_DOLBY_VISION) -#if BUILDFLAG(ENABLE_AC3_EAC3_AUDIO_DEMUXING) +#if BUILDFLAG(ENABLE_PLATFORM_AC3_EAC3_AUDIO) codecs |= ::media::EME_CODEC_AC3 | ::media::EME_CODEC_EAC3; -#endif // BUILDFLAG(ENABLE_AC3_EAC3_AUDIO_DEMUXING) +#endif // BUILDFLAG(ENABLE_PLATFORM_AC3_EAC3_AUDIO) -#if BUILDFLAG(ENABLE_MPEG_H_AUDIO_DEMUXING) +#if BUILDFLAG(ENABLE_PLATFORM_MPEG_H_AUDIO) codecs |= ::media::EME_CODEC_MPEG_H_AUDIO; -#endif // BUILDFLAG(ENABLE_MPEG_H_AUDIO_DEMUXING) +#endif // BUILDFLAG(ENABLE_PLATFORM_MPEG_H_AUDIO) return codecs; }
diff --git a/chromeos/constants/chromeos_features.cc b/chromeos/constants/chromeos_features.cc index 0388894..b6de9a7 100644 --- a/chromeos/constants/chromeos_features.cc +++ b/chromeos/constants/chromeos_features.cc
@@ -157,6 +157,10 @@ const base::Feature kReleaseNotes{"ReleaseNotes", base::FEATURE_ENABLED_BY_DEFAULT}; +// Enables or disables the scrollable shelf. +const base::Feature kShelfScrollable{"ShelfScrollable", + base::FEATURE_ENABLED_BY_DEFAULT}; + // Enables or disables a toggle to enable Bluetooth debug logs. const base::Feature kShowBluetoothDebugLogToggle{ "ShowBluetoothDebugLogToggle", base::FEATURE_DISABLED_BY_DEFAULT};
diff --git a/chromeos/constants/chromeos_features.h b/chromeos/constants/chromeos_features.h index 2f3a61c..8fd0609 100644 --- a/chromeos/constants/chromeos_features.h +++ b/chromeos/constants/chromeos_features.h
@@ -76,6 +76,8 @@ COMPONENT_EXPORT(CHROMEOS_CONSTANTS) extern const base::Feature kReleaseNotes; COMPONENT_EXPORT(CHROMEOS_CONSTANTS) +extern const base::Feature kShelfScrollable; +COMPONENT_EXPORT(CHROMEOS_CONSTANTS) extern const base::Feature kShowBluetoothDebugLogToggle; COMPONENT_EXPORT(CHROMEOS_CONSTANTS) extern const base::Feature kShowBluetoothDeviceBattery;
diff --git a/chromeos/constants/chromeos_switches.cc b/chromeos/constants/chromeos_switches.cc index 7883c18..5342fe9 100644 --- a/chromeos/constants/chromeos_switches.cc +++ b/chromeos/constants/chromeos_switches.cc
@@ -8,6 +8,7 @@ #include "base/command_line.h" #include "base/metrics/field_trial.h" +#include "chromeos/constants/chromeos_features.h" #include "third_party/icu/source/common/unicode/locid.h" namespace chromeos { @@ -457,9 +458,6 @@ // App window previews when hovering over the shelf. const char kShelfHoverPreviews[] = "shelf-hover-previews"; -// Scrollable list of apps on the shelf. -const char kShelfScrollable[] = "shelf-scrollable"; - // If true, files in Android internal storage will be shown in Files app. const char kShowAndroidFilesInFilesApp[] = "show-android-files-in-files-app"; @@ -560,7 +558,8 @@ // If we're showing the new shelf design, also enable scrollable shelf. if (ShouldShowShelfHotseat()) return true; - return base::CommandLine::ForCurrentProcess()->HasSwitch(kShelfScrollable); + + return base::FeatureList::IsEnabled(features::kShelfScrollable); } bool ShouldTetherHostScansIgnoreWiredConnections() {
diff --git a/chromeos/constants/chromeos_switches.h b/chromeos/constants/chromeos_switches.h index fa8c2c29..082b81f0 100644 --- a/chromeos/constants/chromeos_switches.h +++ b/chromeos/constants/chromeos_switches.h
@@ -184,7 +184,6 @@ COMPONENT_EXPORT(CHROMEOS_CONSTANTS) extern const char kSamlPasswordChangeUrl[]; COMPONENT_EXPORT(CHROMEOS_CONSTANTS) extern const char kShelfHoverPreviews[]; COMPONENT_EXPORT(CHROMEOS_CONSTANTS) extern const char kShelfHotseat[]; -COMPONENT_EXPORT(CHROMEOS_CONSTANTS) extern const char kShelfScrollable[]; COMPONENT_EXPORT(CHROMEOS_CONSTANTS) extern const char kShowAndroidFilesInFilesApp[]; COMPONENT_EXPORT(CHROMEOS_CONSTANTS) extern const char kShowLoginDevOverlay[];
diff --git a/chromeos/dbus/concierge_client.cc b/chromeos/dbus/concierge_client.cc index eee532fd..5220b44 100644 --- a/chromeos/dbus/concierge_client.cc +++ b/chromeos/dbus/concierge_client.cc
@@ -16,9 +16,9 @@ #include "third_party/cros_system_api/dbus/service_constants.h" #include "third_party/cros_system_api/dbus/vm_concierge/dbus-constants.h" -namespace chromeos { +namespace concierge = vm_tools::concierge; -using namespace vm_tools::concierge; +namespace chromeos { class ConciergeClientImpl : public ConciergeClient { public: @@ -66,27 +66,25 @@ return is_disk_import_progress_signal_connected_; } - void CreateDiskImage( - const vm_tools::concierge::CreateDiskImageRequest& request, - DBusMethodCallback<vm_tools::concierge::CreateDiskImageResponse> callback) - override { - CallMethod(kCreateDiskImageMethod, request, std::move(callback)); + void CreateDiskImage(const concierge::CreateDiskImageRequest& request, + DBusMethodCallback<concierge::CreateDiskImageResponse> + callback) override { + CallMethod(concierge::kCreateDiskImageMethod, request, std::move(callback)); } - void DestroyDiskImage( - const vm_tools::concierge::DestroyDiskImageRequest& request, - DBusMethodCallback<vm_tools::concierge::DestroyDiskImageResponse> - callback) override { - CallMethod(kDestroyDiskImageMethod, request, std::move(callback)); + void DestroyDiskImage(const concierge::DestroyDiskImageRequest& request, + DBusMethodCallback<concierge::DestroyDiskImageResponse> + callback) override { + CallMethod(concierge::kDestroyDiskImageMethod, request, + std::move(callback)); } - void ImportDiskImage( - base::ScopedFD fd, - const vm_tools::concierge::ImportDiskImageRequest& request, - DBusMethodCallback<vm_tools::concierge::ImportDiskImageResponse> callback) - override { - dbus::MethodCall method_call(vm_tools::concierge::kVmConciergeInterface, - vm_tools::concierge::kImportDiskImageMethod); + void ImportDiskImage(base::ScopedFD fd, + const concierge::ImportDiskImageRequest& request, + DBusMethodCallback<concierge::ImportDiskImageResponse> + callback) override { + dbus::MethodCall method_call(concierge::kVmConciergeInterface, + concierge::kImportDiskImageMethod); dbus::MessageWriter writer(&method_call); if (!writer.AppendProtoAsArrayOfBytes(request)) { @@ -101,65 +99,64 @@ concierge_proxy_->CallMethod( &method_call, dbus::ObjectProxy::TIMEOUT_USE_DEFAULT, base::BindOnce(&ConciergeClientImpl::OnDBusProtoResponse< - vm_tools::concierge::ImportDiskImageResponse>, + concierge::ImportDiskImageResponse>, weak_ptr_factory_.GetWeakPtr(), std::move(callback))); } void CancelDiskImageOperation( - const vm_tools::concierge::CancelDiskImageRequest& request, - DBusMethodCallback<vm_tools::concierge::CancelDiskImageResponse> callback) + const concierge::CancelDiskImageRequest& request, + DBusMethodCallback<concierge::CancelDiskImageResponse> callback) override { - CallMethod(kCancelDiskImageMethod, request, std::move(callback)); + CallMethod(concierge::kCancelDiskImageMethod, request, std::move(callback)); } - void DiskImageStatus( - const vm_tools::concierge::DiskImageStatusRequest& request, - DBusMethodCallback<vm_tools::concierge::DiskImageStatusResponse> callback) - override { - CallMethod(kDiskImageStatusMethod, request, std::move(callback)); + void DiskImageStatus(const concierge::DiskImageStatusRequest& request, + DBusMethodCallback<concierge::DiskImageStatusResponse> + callback) override { + CallMethod(concierge::kDiskImageStatusMethod, request, std::move(callback)); } - void ListVmDisks(const vm_tools::concierge::ListVmDisksRequest& request, - DBusMethodCallback<vm_tools::concierge::ListVmDisksResponse> - callback) override { - CallMethod(kListVmDisksMethod, request, std::move(callback)); + void ListVmDisks( + const concierge::ListVmDisksRequest& request, + DBusMethodCallback<concierge::ListVmDisksResponse> callback) override { + CallMethod(concierge::kListVmDisksMethod, request, std::move(callback)); } - void StartTerminaVm(const vm_tools::concierge::StartVmRequest& request, - DBusMethodCallback<vm_tools::concierge::StartVmResponse> - callback) override { + void StartTerminaVm( + const concierge::StartVmRequest& request, + DBusMethodCallback<concierge::StartVmResponse> callback) override { // TODO(nverne): revert to TIMEOUT_USE_DEFAULT when StartVm no longer // requires unnecessary long running crypto calculations. constexpr int kStartVmTimeoutMs = 160 * 1000; - CallMethod(kStartVmMethod, request, std::move(callback), kStartVmTimeoutMs); + CallMethod(concierge::kStartVmMethod, request, std::move(callback), + kStartVmTimeoutMs); } - void StopVm(const vm_tools::concierge::StopVmRequest& request, - DBusMethodCallback<vm_tools::concierge::StopVmResponse> callback) - override { - CallMethod(kStopVmMethod, request, std::move(callback)); + void StopVm(const concierge::StopVmRequest& request, + DBusMethodCallback<concierge::StopVmResponse> callback) override { + CallMethod(concierge::kStopVmMethod, request, std::move(callback)); } - void GetVmInfo(const vm_tools::concierge::GetVmInfoRequest& request, - DBusMethodCallback<vm_tools::concierge::GetVmInfoResponse> - callback) override { - CallMethod(kGetVmInfoMethod, request, std::move(callback)); + void GetVmInfo( + const concierge::GetVmInfoRequest& request, + DBusMethodCallback<concierge::GetVmInfoResponse> callback) override { + CallMethod(concierge::kGetVmInfoMethod, request, std::move(callback)); } void GetVmEnterpriseReportingInfo( - const vm_tools::concierge::GetVmEnterpriseReportingInfoRequest& request, - DBusMethodCallback< - vm_tools::concierge::GetVmEnterpriseReportingInfoResponse> callback) - override { - CallMethod(kGetVmEnterpriseReportingInfoMethod, request, + const concierge::GetVmEnterpriseReportingInfoRequest& request, + DBusMethodCallback<concierge::GetVmEnterpriseReportingInfoResponse> + callback) override { + CallMethod(concierge::kGetVmEnterpriseReportingInfoMethod, request, std::move(callback)); } void SetVmCpuRestriction( - const vm_tools::concierge::SetVmCpuRestrictionRequest& request, - DBusMethodCallback<vm_tools::concierge::SetVmCpuRestrictionResponse> - callback) override { - CallMethod(kSetVmCpuRestrictionMethod, request, std::move(callback)); + const concierge::SetVmCpuRestrictionRequest& request, + DBusMethodCallback<concierge::SetVmCpuRestrictionResponse> callback) + override { + CallMethod(concierge::kSetVmCpuRestrictionMethod, request, + std::move(callback)); } void WaitForServiceToBeAvailable( @@ -169,19 +166,19 @@ } void GetContainerSshKeys( - const vm_tools::concierge::ContainerSshKeysRequest& request, - DBusMethodCallback<vm_tools::concierge::ContainerSshKeysResponse> - callback) override { - CallMethod(kGetContainerSshKeysMethod, request, std::move(callback)); + const concierge::ContainerSshKeysRequest& request, + DBusMethodCallback<concierge::ContainerSshKeysResponse> callback) + override { + CallMethod(concierge::kGetContainerSshKeysMethod, request, + std::move(callback)); } - void AttachUsbDevice( - base::ScopedFD fd, - const vm_tools::concierge::AttachUsbDeviceRequest& request, - DBusMethodCallback<vm_tools::concierge::AttachUsbDeviceResponse> callback) - override { - dbus::MethodCall method_call(vm_tools::concierge::kVmConciergeInterface, - vm_tools::concierge::kAttachUsbDeviceMethod); + void AttachUsbDevice(base::ScopedFD fd, + const concierge::AttachUsbDeviceRequest& request, + DBusMethodCallback<concierge::AttachUsbDeviceResponse> + callback) override { + dbus::MethodCall method_call(concierge::kVmConciergeInterface, + concierge::kAttachUsbDeviceMethod); dbus::MessageWriter writer(&method_call); if (!writer.AppendProtoAsArrayOfBytes(request)) { @@ -196,64 +193,59 @@ concierge_proxy_->CallMethod( &method_call, dbus::ObjectProxy::TIMEOUT_USE_DEFAULT, base::BindOnce(&ConciergeClientImpl::OnDBusProtoResponse< - vm_tools::concierge::AttachUsbDeviceResponse>, + concierge::AttachUsbDeviceResponse>, weak_ptr_factory_.GetWeakPtr(), std::move(callback))); } - void DetachUsbDevice( - const vm_tools::concierge::DetachUsbDeviceRequest& request, - DBusMethodCallback<vm_tools::concierge::DetachUsbDeviceResponse> callback) - override { - CallMethod(kDetachUsbDeviceMethod, request, std::move(callback)); + void DetachUsbDevice(const concierge::DetachUsbDeviceRequest& request, + DBusMethodCallback<concierge::DetachUsbDeviceResponse> + callback) override { + CallMethod(concierge::kDetachUsbDeviceMethod, request, std::move(callback)); } void ListUsbDevices( - const vm_tools::concierge::ListUsbDeviceRequest& request, - DBusMethodCallback<vm_tools::concierge::ListUsbDeviceResponse> callback) - override { - CallMethod(kListUsbDeviceMethod, request, std::move(callback)); + const concierge::ListUsbDeviceRequest& request, + DBusMethodCallback<concierge::ListUsbDeviceResponse> callback) override { + CallMethod(concierge::kListUsbDeviceMethod, request, std::move(callback)); } - void StartArcVm(const vm_tools::concierge::StartArcVmRequest& request, - DBusMethodCallback<vm_tools::concierge::StartVmResponse> - callback) override { - CallMethod(kStartArcVmMethod, request, std::move(callback)); + void StartArcVm( + const concierge::StartArcVmRequest& request, + DBusMethodCallback<concierge::StartVmResponse> callback) override { + CallMethod(concierge::kStartArcVmMethod, request, std::move(callback)); } protected: void Init(dbus::Bus* bus) override { concierge_proxy_ = bus->GetObjectProxy( - vm_tools::concierge::kVmConciergeServiceName, - dbus::ObjectPath(vm_tools::concierge::kVmConciergeServicePath)); + concierge::kVmConciergeServiceName, + dbus::ObjectPath(concierge::kVmConciergeServicePath)); if (!concierge_proxy_) { LOG(ERROR) << "Unable to get dbus proxy for " - << vm_tools::concierge::kVmConciergeServiceName; + << concierge::kVmConciergeServiceName; } concierge_proxy_->ConnectToSignal( - vm_tools::concierge::kVmConciergeInterface, - vm_tools::concierge::kVmStartedSignal, + concierge::kVmConciergeInterface, concierge::kVmStartedSignal, base::BindRepeating(&ConciergeClientImpl::OnVmStartedSignal, weak_ptr_factory_.GetWeakPtr()), base::BindOnce(&ConciergeClientImpl::OnSignalConnected, weak_ptr_factory_.GetWeakPtr())); concierge_proxy_->ConnectToSignal( - vm_tools::concierge::kVmConciergeInterface, - vm_tools::concierge::kVmStoppedSignal, + concierge::kVmConciergeInterface, concierge::kVmStoppedSignal, base::BindRepeating(&ConciergeClientImpl::OnVmStoppedSignal, weak_ptr_factory_.GetWeakPtr()), base::BindOnce(&ConciergeClientImpl::OnSignalConnected, weak_ptr_factory_.GetWeakPtr())); concierge_proxy_->ConnectToSignal( - vm_tools::concierge::kVmConciergeInterface, - vm_tools::concierge::kContainerStartupFailedSignal, + concierge::kVmConciergeInterface, + concierge::kContainerStartupFailedSignal, base::BindRepeating( &ConciergeClientImpl::OnContainerStartupFailedSignal, weak_ptr_factory_.GetWeakPtr()), base::BindOnce(&ConciergeClientImpl::OnSignalConnected, weak_ptr_factory_.GetWeakPtr())); concierge_proxy_->ConnectToSignal( - vm_tools::concierge::kVmConciergeInterface, - vm_tools::concierge::kDiskImageProgressSignal, + concierge::kVmConciergeInterface, concierge::kDiskImageProgressSignal, base::BindRepeating(&ConciergeClientImpl::OnDiskImageProgress, weak_ptr_factory_.GetWeakPtr()), base::BindOnce(&ConciergeClientImpl::OnSignalConnected, @@ -266,7 +258,7 @@ const RequestProto& request, DBusMethodCallback<ResponseProto> callback, int timeout_ms = dbus::ObjectProxy::TIMEOUT_USE_DEFAULT) { - dbus::MethodCall method_call(kVmConciergeInterface, method_name); + dbus::MethodCall method_call(concierge::kVmConciergeInterface, method_name); dbus::MessageWriter writer(&method_call); if (!writer.AppendProtoAsArrayOfBytes(request)) { @@ -300,11 +292,10 @@ } void OnVmStartedSignal(dbus::Signal* signal) { - DCHECK_EQ(signal->GetInterface(), - vm_tools::concierge::kVmConciergeInterface); - DCHECK_EQ(signal->GetMember(), vm_tools::concierge::kVmStartedSignal); + DCHECK_EQ(signal->GetInterface(), concierge::kVmConciergeInterface); + DCHECK_EQ(signal->GetMember(), concierge::kVmStartedSignal); - vm_tools::concierge::VmStartedSignal vm_started_signal; + concierge::VmStartedSignal vm_started_signal; dbus::MessageReader reader(signal); if (!reader.PopArrayOfBytesAsProto(&vm_started_signal)) { LOG(ERROR) << "Failed to parse proto from DBus Signal"; @@ -316,11 +307,10 @@ } void OnVmStoppedSignal(dbus::Signal* signal) { - DCHECK_EQ(signal->GetInterface(), - vm_tools::concierge::kVmConciergeInterface); - DCHECK_EQ(signal->GetMember(), vm_tools::concierge::kVmStoppedSignal); + DCHECK_EQ(signal->GetInterface(), concierge::kVmConciergeInterface); + DCHECK_EQ(signal->GetMember(), concierge::kVmStoppedSignal); - vm_tools::concierge::VmStoppedSignal vm_stopped_signal; + concierge::VmStoppedSignal vm_stopped_signal; dbus::MessageReader reader(signal); if (!reader.PopArrayOfBytesAsProto(&vm_stopped_signal)) { LOG(ERROR) << "Failed to parse proto from DBus Signal"; @@ -332,12 +322,10 @@ } void OnContainerStartupFailedSignal(dbus::Signal* signal) { - DCHECK_EQ(signal->GetInterface(), - vm_tools::concierge::kVmConciergeInterface); - DCHECK_EQ(signal->GetMember(), - vm_tools::concierge::kContainerStartupFailedSignal); + DCHECK_EQ(signal->GetInterface(), concierge::kVmConciergeInterface); + DCHECK_EQ(signal->GetMember(), concierge::kContainerStartupFailedSignal); - vm_tools::concierge::ContainerStartedSignal container_startup_failed_signal; + concierge::ContainerStartedSignal container_startup_failed_signal; dbus::MessageReader reader(signal); if (!reader.PopArrayOfBytesAsProto(&container_startup_failed_signal)) { LOG(ERROR) << "Failed to parse proto from DBus Signal"; @@ -350,13 +338,10 @@ } void OnDiskImageProgress(dbus::Signal* signal) { - DCHECK_EQ(signal->GetInterface(), - vm_tools::concierge::kVmConciergeInterface); - DCHECK_EQ(signal->GetMember(), - vm_tools::concierge::kDiskImageProgressSignal); + DCHECK_EQ(signal->GetInterface(), concierge::kVmConciergeInterface); + DCHECK_EQ(signal->GetMember(), concierge::kDiskImageProgressSignal); - vm_tools::concierge::DiskImageStatusResponse - disk_image_status_response_signal; + concierge::DiskImageStatusResponse disk_image_status_response_signal; dbus::MessageReader reader(signal); if (!reader.PopArrayOfBytesAsProto(&disk_image_status_response_signal)) { LOG(ERROR) << "Failed to parse proto from DBus Signal"; @@ -371,18 +356,17 @@ void OnSignalConnected(const std::string& interface_name, const std::string& signal_name, bool is_connected) { - DCHECK_EQ(interface_name, vm_tools::concierge::kVmConciergeInterface); + DCHECK_EQ(interface_name, concierge::kVmConciergeInterface); if (!is_connected) LOG(ERROR) << "Failed to connect to signal: " << signal_name; - if (signal_name == vm_tools::concierge::kVmStartedSignal) { + if (signal_name == concierge::kVmStartedSignal) { is_vm_started_signal_connected_ = is_connected; - } else if (signal_name == vm_tools::concierge::kVmStoppedSignal) { + } else if (signal_name == concierge::kVmStoppedSignal) { is_vm_stopped_signal_connected_ = is_connected; - } else if (signal_name == - vm_tools::concierge::kContainerStartupFailedSignal) { + } else if (signal_name == concierge::kContainerStartupFailedSignal) { is_container_startup_failed_signal_connected_ = is_connected; - } else if (signal_name == vm_tools::concierge::kDiskImageProgressSignal) { + } else if (signal_name == concierge::kDiskImageProgressSignal) { is_disk_import_progress_signal_connected_ = is_connected; } else { NOTREACHED();
diff --git a/chromeos/dbus/fake_vm_plugin_dispatcher_client.cc b/chromeos/dbus/fake_vm_plugin_dispatcher_client.cc index d2d55151..c1507d88 100644 --- a/chromeos/dbus/fake_vm_plugin_dispatcher_client.cc +++ b/chromeos/dbus/fake_vm_plugin_dispatcher_client.cc
@@ -9,8 +9,6 @@ #include "base/bind.h" #include "base/threading/thread_task_runner_handle.h" -using namespace vm_tools::plugin_dispatcher; - namespace chromeos { FakeVmPluginDispatcherClient::FakeVmPluginDispatcherClient() = default; @@ -26,43 +24,48 @@ } void FakeVmPluginDispatcherClient::StartVm( - const StartVmRequest& request, - DBusMethodCallback<StartVmResponse> callback) { + const vm_tools::plugin_dispatcher::StartVmRequest& request, + DBusMethodCallback<vm_tools::plugin_dispatcher::StartVmResponse> callback) { start_vm_called_ = true; base::ThreadTaskRunnerHandle::Get()->PostTask( FROM_HERE, base::BindOnce(std::move(callback), start_vm_response_)); } void FakeVmPluginDispatcherClient::ListVms( - const ListVmRequest& request, - DBusMethodCallback<ListVmResponse> callback) { + const vm_tools::plugin_dispatcher::ListVmRequest& request, + DBusMethodCallback<vm_tools::plugin_dispatcher::ListVmResponse> callback) { list_vms_called_ = true; base::ThreadTaskRunnerHandle::Get()->PostTask( FROM_HERE, base::BindOnce(std::move(callback), list_vms_response_)); } void FakeVmPluginDispatcherClient::StopVm( - const StopVmRequest& request, - DBusMethodCallback<StopVmResponse> callback) { + const vm_tools::plugin_dispatcher::StopVmRequest& request, + DBusMethodCallback<vm_tools::plugin_dispatcher::StopVmResponse> callback) { stop_vm_called_ = true; base::ThreadTaskRunnerHandle::Get()->PostTask( - FROM_HERE, base::BindOnce(std::move(callback), StopVmResponse())); + FROM_HERE, base::BindOnce(std::move(callback), + vm_tools::plugin_dispatcher::StopVmResponse())); } void FakeVmPluginDispatcherClient::SuspendVm( - const SuspendVmRequest& request, - DBusMethodCallback<SuspendVmResponse> callback) { + const vm_tools::plugin_dispatcher::SuspendVmRequest& request, + DBusMethodCallback<vm_tools::plugin_dispatcher::SuspendVmResponse> + callback) { suspend_vm_called_ = true; base::ThreadTaskRunnerHandle::Get()->PostTask( - FROM_HERE, base::BindOnce(std::move(callback), SuspendVmResponse())); + FROM_HERE, + base::BindOnce(std::move(callback), + vm_tools::plugin_dispatcher::SuspendVmResponse())); } void FakeVmPluginDispatcherClient::ShowVm( - const ShowVmRequest& request, - DBusMethodCallback<ShowVmResponse> callback) { + const vm_tools::plugin_dispatcher::ShowVmRequest& request, + DBusMethodCallback<vm_tools::plugin_dispatcher::ShowVmResponse> callback) { show_vm_called_ = true; base::ThreadTaskRunnerHandle::Get()->PostTask( - FROM_HERE, base::BindOnce(std::move(callback), ShowVmResponse())); + FROM_HERE, base::BindOnce(std::move(callback), + vm_tools::plugin_dispatcher::ShowVmResponse())); } void FakeVmPluginDispatcherClient::WaitForServiceToBeAvailable(
diff --git a/chromeos/dbus/vm_plugin_dispatcher_client.cc b/chromeos/dbus/vm_plugin_dispatcher_client.cc index e791779b..1a40e444 100644 --- a/chromeos/dbus/vm_plugin_dispatcher_client.cc +++ b/chromeos/dbus/vm_plugin_dispatcher_client.cc
@@ -16,9 +16,9 @@ #include "third_party/cros_system_api/dbus/service_constants.h" #include "third_party/cros_system_api/dbus/vm_plugin_dispatcher/dbus-constants.h" -namespace chromeos { +namespace dispatcher = vm_tools::plugin_dispatcher; -using namespace vm_tools::plugin_dispatcher; +namespace chromeos { class VmPluginDispatcherClientImpl : public VmPluginDispatcherClient { public: @@ -34,29 +34,34 @@ observer_list_.RemoveObserver(observer); } - void StartVm(const StartVmRequest& request, - DBusMethodCallback<StartVmResponse> callback) override { - CallMethod(kStartVmMethod, request, std::move(callback)); + void StartVm( + const dispatcher::StartVmRequest& request, + DBusMethodCallback<dispatcher::StartVmResponse> callback) override { + CallMethod(dispatcher::kStartVmMethod, request, std::move(callback)); } - void ListVms(const ListVmRequest& request, - DBusMethodCallback<ListVmResponse> callback) override { - CallMethod(kListVmsMethod, request, std::move(callback)); + void ListVms( + const dispatcher::ListVmRequest& request, + DBusMethodCallback<dispatcher::ListVmResponse> callback) override { + CallMethod(dispatcher::kListVmsMethod, request, std::move(callback)); } - void StopVm(const StopVmRequest& request, - DBusMethodCallback<StopVmResponse> callback) override { - CallMethod(kStopVmMethod, request, std::move(callback)); + void StopVm( + const dispatcher::StopVmRequest& request, + DBusMethodCallback<dispatcher::StopVmResponse> callback) override { + CallMethod(dispatcher::kStopVmMethod, request, std::move(callback)); } - void SuspendVm(const SuspendVmRequest& request, - DBusMethodCallback<SuspendVmResponse> callback) override { - CallMethod(kSuspendVmMethod, request, std::move(callback)); + void SuspendVm( + const dispatcher::SuspendVmRequest& request, + DBusMethodCallback<dispatcher::SuspendVmResponse> callback) override { + CallMethod(dispatcher::kSuspendVmMethod, request, std::move(callback)); } - void ShowVm(const ShowVmRequest& request, - DBusMethodCallback<ShowVmResponse> callback) override { - CallMethod(kShowVmMethod, request, std::move(callback)); + void ShowVm( + const dispatcher::ShowVmRequest& request, + DBusMethodCallback<dispatcher::ShowVmResponse> callback) override { + CallMethod(dispatcher::kShowVmMethod, request, std::move(callback)); } void WaitForServiceToBeAvailable( @@ -68,17 +73,17 @@ protected: void Init(dbus::Bus* bus) override { - vm_plugin_dispatcher_proxy_ = - bus->GetObjectProxy(kVmPluginDispatcherServiceName, - dbus::ObjectPath(kVmPluginDispatcherServicePath)); + vm_plugin_dispatcher_proxy_ = bus->GetObjectProxy( + dispatcher::kVmPluginDispatcherServiceName, + dbus::ObjectPath(dispatcher::kVmPluginDispatcherServicePath)); if (!vm_plugin_dispatcher_proxy_) { LOG(ERROR) << "Unable to get dbus proxy for " - << kVmPluginDispatcherServiceName; + << dispatcher::kVmPluginDispatcherServiceName; } vm_plugin_dispatcher_proxy_->ConnectToSignal( - vm_tools::plugin_dispatcher::kVmPluginDispatcherInterface, - vm_tools::plugin_dispatcher::kVmStateChangedSignal, + dispatcher::kVmPluginDispatcherInterface, + dispatcher::kVmStateChangedSignal, base::BindRepeating( &VmPluginDispatcherClientImpl::OnVmStateChangedSignal, weak_ptr_factory_.GetWeakPtr()), @@ -91,7 +96,8 @@ void CallMethod(const std::string& method_name, const RequestProto& request, DBusMethodCallback<ResponseProto> callback) { - dbus::MethodCall method_call(kVmPluginDispatcherInterface, method_name); + dbus::MethodCall method_call(dispatcher::kVmPluginDispatcherInterface, + method_name); dbus::MessageWriter writer(&method_call); if (!writer.AppendProtoAsArrayOfBytes(request)) { @@ -126,12 +132,10 @@ } void OnVmStateChangedSignal(dbus::Signal* signal) { - DCHECK_EQ(signal->GetInterface(), - vm_tools::plugin_dispatcher::kVmPluginDispatcherInterface); - DCHECK_EQ(signal->GetMember(), - vm_tools::plugin_dispatcher::kVmStateChangedSignal); + DCHECK_EQ(signal->GetInterface(), dispatcher::kVmPluginDispatcherInterface); + DCHECK_EQ(signal->GetMember(), dispatcher::kVmStateChangedSignal); - vm_tools::plugin_dispatcher::VmStateChangedSignal vm_state_changed_signal; + dispatcher::VmStateChangedSignal vm_state_changed_signal; dbus::MessageReader reader(signal); if (!reader.PopArrayOfBytesAsProto(&vm_state_changed_signal)) { LOG(ERROR) << "Failed to parse proto from DBus Signal"; @@ -146,8 +150,7 @@ void OnSignalConnected(const std::string& interface_name, const std::string& signal_name, bool is_connected) { - DCHECK_EQ(interface_name, - vm_tools::plugin_dispatcher::kVmPluginDispatcherInterface); + DCHECK_EQ(interface_name, dispatcher::kVmPluginDispatcherInterface); if (!is_connected) LOG(ERROR) << "Failed to connect to signal: " << signal_name; }
diff --git a/chromeos/network/client_cert_util.cc b/chromeos/network/client_cert_util.cc index d8c2434..0db2405 100644 --- a/chromeos/network/client_cert_util.cc +++ b/chromeos/network/client_cert_util.cc
@@ -45,15 +45,14 @@ if (identity) cert_config->policy_identity = *identity; - using namespace ::onc::client_cert; const std::string* client_cert_type = - dict_with_client_cert.FindStringKey(kClientCertType); + dict_with_client_cert.FindStringKey(::onc::client_cert::kClientCertType); if (client_cert_type) cert_config->client_cert_type = *client_cert_type; - if (cert_config->client_cert_type == kPattern) { + if (cert_config->client_cert_type == ::onc::client_cert::kPattern) { const base::Value* pattern_value = dict_with_client_cert.FindKeyOfType( - kClientCertPattern, base::Value::Type::DICTIONARY); + ::onc::client_cert::kClientCertPattern, base::Value::Type::DICTIONARY); if (pattern_value) { base::Optional<OncCertificatePattern> pattern = OncCertificatePattern::ReadFromONCDictionary(*pattern_value); @@ -63,9 +62,9 @@ } cert_config->pattern = pattern.value(); } - } else if (cert_config->client_cert_type == kRef) { + } else if (cert_config->client_cert_type == ::onc::client_cert::kRef) { const base::Value* client_cert_ref_key = - dict_with_client_cert.FindKeyOfType(kClientCertRef, + dict_with_client_cert.FindKeyOfType(::onc::client_cert::kClientCertRef, base::Value::Type::STRING); if (client_cert_ref_key) cert_config->guid = client_cert_ref_key->GetString(); @@ -242,18 +241,16 @@ void OncToClientCertConfig(::onc::ONCSource onc_source, const base::DictionaryValue& network_config, ClientCertConfig* cert_config) { - using namespace ::onc; - *cert_config = ClientCertConfig(); const base::DictionaryValue* dict_with_client_cert = NULL; const base::DictionaryValue* wifi = NULL; - network_config.GetDictionaryWithoutPathExpansion(network_config::kWiFi, + network_config.GetDictionaryWithoutPathExpansion(::onc::network_config::kWiFi, &wifi); if (wifi) { const base::DictionaryValue* eap = NULL; - wifi->GetDictionaryWithoutPathExpansion(wifi::kEAP, &eap); + wifi->GetDictionaryWithoutPathExpansion(::onc::wifi::kEAP, &eap); if (!eap) return; @@ -262,12 +259,13 @@ } const base::DictionaryValue* vpn = NULL; - network_config.GetDictionaryWithoutPathExpansion(network_config::kVPN, &vpn); + network_config.GetDictionaryWithoutPathExpansion(::onc::network_config::kVPN, + &vpn); if (vpn) { const base::DictionaryValue* openvpn = NULL; - vpn->GetDictionaryWithoutPathExpansion(vpn::kOpenVPN, &openvpn); + vpn->GetDictionaryWithoutPathExpansion(::onc::vpn::kOpenVPN, &openvpn); const base::DictionaryValue* ipsec = NULL; - vpn->GetDictionaryWithoutPathExpansion(vpn::kIPsec, &ipsec); + vpn->GetDictionaryWithoutPathExpansion(::onc::vpn::kIPsec, &ipsec); if (openvpn) { dict_with_client_cert = openvpn; cert_config->location = CONFIG_TYPE_OPENVPN; @@ -280,11 +278,11 @@ } const base::DictionaryValue* ethernet = NULL; - network_config.GetDictionaryWithoutPathExpansion(network_config::kEthernet, - ðernet); + network_config.GetDictionaryWithoutPathExpansion( + ::onc::network_config::kEthernet, ðernet); if (ethernet) { const base::DictionaryValue* eap = NULL; - ethernet->GetDictionaryWithoutPathExpansion(wifi::kEAP, &eap); + ethernet->GetDictionaryWithoutPathExpansion(::onc::wifi::kEAP, &eap); if (!eap) return; dict_with_client_cert = eap;
diff --git a/chromeos/network/onc/onc_normalizer.cc b/chromeos/network/onc/onc_normalizer.cc index c51931f..f34a6aee 100644 --- a/chromeos/network/onc/onc_normalizer.cc +++ b/chromeos/network/onc/onc_normalizer.cc
@@ -93,26 +93,27 @@ } // namespace void Normalizer::NormalizeCertificate(base::DictionaryValue* cert) { - using namespace ::onc::certificate; - std::string type; cert->GetStringWithoutPathExpansion(::onc::certificate::kType, &type); - RemoveEntryUnless(cert, kPKCS12, type == kClient); - RemoveEntryUnless(cert, kTrustBits, type == kServer || type == kAuthority); - RemoveEntryUnless(cert, kX509, type == kServer || type == kAuthority); + RemoveEntryUnless(cert, ::onc::certificate::kPKCS12, + type == ::onc::certificate::kClient); + RemoveEntryUnless(cert, ::onc::certificate::kTrustBits, + type == ::onc::certificate::kServer || + type == ::onc::certificate::kAuthority); + RemoveEntryUnless(cert, ::onc::certificate::kX509, + type == ::onc::certificate::kServer || + type == ::onc::certificate::kAuthority); } void Normalizer::NormalizeEthernet(base::DictionaryValue* ethernet) { - using namespace ::onc::ethernet; - std::string auth; - ethernet->GetStringWithoutPathExpansion(kAuthentication, &auth); - RemoveEntryUnless(ethernet, kEAP, auth == k8021X); + ethernet->GetStringWithoutPathExpansion(::onc::ethernet::kAuthentication, + &auth); + RemoveEntryUnless(ethernet, ::onc::ethernet::kEAP, + auth == ::onc::ethernet::k8021X); } void Normalizer::NormalizeEAP(base::DictionaryValue* eap) { - using namespace ::onc::eap; - std::string clientcert_type; eap->GetStringWithoutPathExpansion(::onc::client_cert::kClientCertType, &clientcert_type); @@ -124,23 +125,27 @@ clientcert_type == ::onc::client_cert::kRef); std::string outer; - eap->GetStringWithoutPathExpansion(kOuter, &outer); - RemoveEntryUnless(eap, kAnonymousIdentity, - outer == kPEAP || outer == kEAP_TTLS); - RemoveEntryUnless(eap, kInner, - outer == kPEAP || outer == kEAP_TTLS || outer == kEAP_FAST); + eap->GetStringWithoutPathExpansion(::onc::eap::kOuter, &outer); + RemoveEntryUnless( + eap, ::onc::eap::kAnonymousIdentity, + outer == ::onc::eap::kPEAP || outer == ::onc::eap::kEAP_TTLS); + RemoveEntryUnless(eap, ::onc::eap::kInner, + outer == ::onc::eap::kPEAP || + outer == ::onc::eap::kEAP_TTLS || + outer == ::onc::eap::kEAP_FAST); } void Normalizer::NormalizeIPsec(base::DictionaryValue* ipsec) { - using namespace ::onc::ipsec; - std::string auth_type; - ipsec->GetStringWithoutPathExpansion(kAuthenticationType, &auth_type); - RemoveEntryUnless( - ipsec, ::onc::client_cert::kClientCertType, auth_type == kCert); - RemoveEntryUnless(ipsec, kServerCARef, auth_type == kCert); - RemoveEntryUnless(ipsec, kPSK, auth_type == kPSK); - RemoveEntryUnless(ipsec, ::onc::vpn::kSaveCredentials, auth_type == kPSK); + ipsec->GetStringWithoutPathExpansion(::onc::ipsec::kAuthenticationType, + &auth_type); + RemoveEntryUnless(ipsec, ::onc::client_cert::kClientCertType, + auth_type == ::onc::ipsec::kCert); + RemoveEntryUnless(ipsec, ::onc::ipsec::kServerCARef, + auth_type == ::onc::ipsec::kCert); + RemoveEntryUnless(ipsec, ::onc::ipsec::kPSK, auth_type == ::onc::ipsec::kPSK); + RemoveEntryUnless(ipsec, ::onc::vpn::kSaveCredentials, + auth_type == ::onc::ipsec::kPSK); std::string clientcert_type; ipsec->GetStringWithoutPathExpansion(::onc::client_cert::kClientCertType, @@ -153,10 +158,11 @@ clientcert_type == ::onc::client_cert::kRef); int ike_version = -1; - ipsec->GetIntegerWithoutPathExpansion(kIKEVersion, &ike_version); - RemoveEntryUnless(ipsec, kEAP, ike_version == 2); - RemoveEntryUnless(ipsec, kGroup, ike_version == 1); - RemoveEntryUnless(ipsec, kXAUTH, ike_version == 1); + ipsec->GetIntegerWithoutPathExpansion(::onc::ipsec::kIKEVersion, + &ike_version); + RemoveEntryUnless(ipsec, ::onc::ipsec::kEAP, ike_version == 2); + RemoveEntryUnless(ipsec, ::onc::ipsec::kGroup, ike_version == 1); + RemoveEntryUnless(ipsec, ::onc::ipsec::kXAUTH, ike_version == 1); } void Normalizer::NormalizeNetworkConfiguration(base::DictionaryValue* network) { @@ -216,35 +222,38 @@ } void Normalizer::NormalizeProxySettings(base::DictionaryValue* proxy) { - using namespace ::onc::proxy; - std::string type; proxy->GetStringWithoutPathExpansion(::onc::proxy::kType, &type); - RemoveEntryUnless(proxy, kManual, type == kManual); - RemoveEntryUnless(proxy, kExcludeDomains, type == kManual); - RemoveEntryUnless(proxy, kPAC, type == kPAC); + RemoveEntryUnless(proxy, ::onc::proxy::kManual, + type == ::onc::proxy::kManual); + RemoveEntryUnless(proxy, ::onc::proxy::kExcludeDomains, + type == ::onc::proxy::kManual); + RemoveEntryUnless(proxy, ::onc::proxy::kPAC, type == ::onc::proxy::kPAC); } void Normalizer::NormalizeVPN(base::DictionaryValue* vpn) { - using namespace ::onc::vpn; - std::string type; vpn->GetStringWithoutPathExpansion(::onc::vpn::kType, &type); - RemoveEntryUnless(vpn, kOpenVPN, type == kOpenVPN); - RemoveEntryUnless(vpn, kIPsec, type == kIPsec || type == kTypeL2TP_IPsec); - RemoveEntryUnless(vpn, kL2TP, type == kTypeL2TP_IPsec); - RemoveEntryUnless(vpn, kThirdPartyVpn, type == kThirdPartyVpn); - RemoveEntryUnless(vpn, kArcVpn, type == kArcVpn); + RemoveEntryUnless(vpn, ::onc::vpn::kOpenVPN, type == ::onc::vpn::kOpenVPN); + RemoveEntryUnless( + vpn, ::onc::vpn::kIPsec, + type == ::onc::vpn::kIPsec || type == ::onc::vpn::kTypeL2TP_IPsec); + RemoveEntryUnless(vpn, ::onc::vpn::kL2TP, + type == ::onc::vpn::kTypeL2TP_IPsec); + RemoveEntryUnless(vpn, ::onc::vpn::kThirdPartyVpn, + type == ::onc::vpn::kThirdPartyVpn); + RemoveEntryUnless(vpn, ::onc::vpn::kArcVpn, type == ::onc::vpn::kArcVpn); } void Normalizer::NormalizeWiFi(base::DictionaryValue* wifi) { - using namespace ::onc::wifi; - std::string security; wifi->GetStringWithoutPathExpansion(::onc::wifi::kSecurity, &security); - RemoveEntryUnless(wifi, kEAP, security == kWEP_8021X || security == kWPA_EAP); - RemoveEntryUnless(wifi, kPassphrase, - security == kWEP_PSK || security == kWPA_PSK); + RemoveEntryUnless( + wifi, ::onc::wifi::kEAP, + security == ::onc::wifi::kWEP_8021X || security == ::onc::wifi::kWPA_EAP); + RemoveEntryUnless( + wifi, ::onc::wifi::kPassphrase, + security == ::onc::wifi::kWEP_PSK || security == ::onc::wifi::kWPA_PSK); FillInHexSSIDField(wifi); }
diff --git a/chromeos/network/onc/onc_utils.cc b/chromeos/network/onc/onc_utils.cc index a573cbd0..95e3d39 100644 --- a/chromeos/network/onc/onc_utils.cc +++ b/chromeos/network/onc/onc_utils.cc
@@ -57,8 +57,6 @@ #include "url/gurl.h" #include "url/url_constants.h" -using namespace ::onc; - namespace chromeos { namespace onc { @@ -148,8 +146,10 @@ if (FieldIsCredential(object_signature, field_name)) { // If it's the password field and the substitution string is used, don't // mask it. - if (&object_signature == &kEAPSignature && field_name == eap::kPassword && - onc_value.GetString() == substitutes::kPasswordPlaceholderVerbatim) { + if (&object_signature == &kEAPSignature && + field_name == ::onc::eap::kPassword && + onc_value.GetString() == + ::onc::substitutes::kPasswordPlaceholderVerbatim) { return Mapper::MapField(field_name, object_signature, onc_value, found_unknown_field, error); } @@ -175,15 +175,15 @@ DCHECK(entry_is_dictionary); std::string guid; - cert->GetStringWithoutPathExpansion(certificate::kGUID, &guid); + cert->GetStringWithoutPathExpansion(::onc::certificate::kGUID, &guid); std::string cert_type; - cert->GetStringWithoutPathExpansion(certificate::kType, &cert_type); - if (cert_type != certificate::kServer && - cert_type != certificate::kAuthority) { + cert->GetStringWithoutPathExpansion(::onc::certificate::kType, &cert_type); + if (cert_type != ::onc::certificate::kServer && + cert_type != ::onc::certificate::kAuthority) { continue; } std::string x509_data; - cert->GetStringWithoutPathExpansion(certificate::kX509, &x509_data); + cert->GetStringWithoutPathExpansion(::onc::certificate::kX509, &x509_data); std::string der = DecodePEM(x509_data); std::string pem; @@ -335,39 +335,30 @@ const OncValueSignature& signature, base::DictionaryValue* onc_object) { if (&signature == &kCertificatePatternSignature) { - if (!ResolveCertRefList(certs_by_guid, - client_cert::kIssuerCARef, - client_cert::kIssuerCAPEMs, - onc_object)) { + if (!ResolveCertRefList(certs_by_guid, ::onc::client_cert::kIssuerCARef, + ::onc::client_cert::kIssuerCAPEMs, onc_object)) { return false; } } else if (&signature == &kEAPSignature) { - if (!ResolveCertRefsOrRefToList(certs_by_guid, - eap::kServerCARefs, - eap::kServerCARef, - eap::kServerCAPEMs, - onc_object)) { + if (!ResolveCertRefsOrRefToList(certs_by_guid, ::onc::eap::kServerCARefs, + ::onc::eap::kServerCARef, + ::onc::eap::kServerCAPEMs, onc_object)) { return false; } } else if (&signature == &kIPsecSignature) { - if (!ResolveCertRefsOrRefToList(certs_by_guid, - ipsec::kServerCARefs, - ipsec::kServerCARef, - ipsec::kServerCAPEMs, - onc_object)) { + if (!ResolveCertRefsOrRefToList(certs_by_guid, ::onc::ipsec::kServerCARefs, + ::onc::ipsec::kServerCARef, + ::onc::ipsec::kServerCAPEMs, onc_object)) { return false; } } else if (&signature == &kIPsecSignature || &signature == &kOpenVPNSignature) { - if (!ResolveSingleCertRef(certs_by_guid, - openvpn::kServerCertRef, - openvpn::kServerCertPEM, - onc_object) || - !ResolveCertRefsOrRefToList(certs_by_guid, - openvpn::kServerCARefs, - openvpn::kServerCARef, - openvpn::kServerCAPEMs, - onc_object)) { + if (!ResolveSingleCertRef(certs_by_guid, ::onc::openvpn::kServerCertRef, + ::onc::openvpn::kServerCertPEM, onc_object) || + !ResolveCertRefsOrRefToList( + certs_by_guid, ::onc::openvpn::kServerCARefs, + ::onc::openvpn::kServerCARef, ::onc::openvpn::kServerCAPEMs, + onc_object)) { return false; } } @@ -683,22 +674,23 @@ int iterations; std::string ciphertext; - if (!GetString(root, encrypted::kCiphertext, &ciphertext) || - !GetString(root, encrypted::kCipher, &cipher) || - !GetString(root, encrypted::kHMAC, &hmac) || - !GetString(root, encrypted::kHMACMethod, &hmac_method) || - !GetString(root, encrypted::kIV, &initial_vector) || - !GetInt(root, encrypted::kIterations, &iterations) || - !GetString(root, encrypted::kSalt, &salt) || - !GetString(root, encrypted::kStretch, &stretch_method) || - !GetString(root, toplevel_config::kType, &onc_type) || - onc_type != toplevel_config::kEncryptedConfiguration) { + if (!GetString(root, ::onc::encrypted::kCiphertext, &ciphertext) || + !GetString(root, ::onc::encrypted::kCipher, &cipher) || + !GetString(root, ::onc::encrypted::kHMAC, &hmac) || + !GetString(root, ::onc::encrypted::kHMACMethod, &hmac_method) || + !GetString(root, ::onc::encrypted::kIV, &initial_vector) || + !GetInt(root, ::onc::encrypted::kIterations, &iterations) || + !GetString(root, ::onc::encrypted::kSalt, &salt) || + !GetString(root, ::onc::encrypted::kStretch, &stretch_method) || + !GetString(root, ::onc::toplevel_config::kType, &onc_type) || + onc_type != ::onc::toplevel_config::kEncryptedConfiguration) { NET_LOG(ERROR) << "Encrypted ONC malformed."; return nullptr; } - if (hmac_method != encrypted::kSHA1 || cipher != encrypted::kAES256 || - stretch_method != encrypted::kPBKDF2) { + if (hmac_method != ::onc::encrypted::kSHA1 || + cipher != ::onc::encrypted::kAES256 || + stretch_method != ::onc::encrypted::kPBKDF2) { NET_LOG(ERROR) << "Encrypted ONC unsupported encryption scheme."; return nullptr; } @@ -767,17 +759,17 @@ return new_root; } -std::string GetSourceAsString(ONCSource source) { +std::string GetSourceAsString(::onc::ONCSource source) { switch (source) { - case ONC_SOURCE_UNKNOWN: + case ::onc::ONC_SOURCE_UNKNOWN: return "unknown"; - case ONC_SOURCE_NONE: + case ::onc::ONC_SOURCE_NONE: return "none"; - case ONC_SOURCE_DEVICE_POLICY: + case ::onc::ONC_SOURCE_DEVICE_POLICY: return "device policy"; - case ONC_SOURCE_USER_POLICY: + case ::onc::ONC_SOURCE_USER_POLICY: return "user policy"; - case ONC_SOURCE_USER_IMPORT: + case ::onc::ONC_SOURCE_USER_IMPORT: return "user import"; } NOTREACHED() << "unknown ONC source " << source; @@ -788,11 +780,11 @@ const VariableExpander& variable_expander, base::DictionaryValue* onc_object) { if (&signature == &kEAPSignature) { - ExpandField(eap::kAnonymousIdentity, variable_expander, onc_object); - ExpandField(eap::kIdentity, variable_expander, onc_object); + ExpandField(::onc::eap::kAnonymousIdentity, variable_expander, onc_object); + ExpandField(::onc::eap::kIdentity, variable_expander, onc_object); } else if (&signature == &kL2TPSignature || &signature == &kOpenVPNSignature) { - ExpandField(vpn::kUsername, variable_expander, onc_object); + ExpandField(::onc::vpn::kUsername, variable_expander, onc_object); } // Recurse into nested objects. @@ -896,7 +888,7 @@ } bool ParseAndValidateOncForImport(const std::string& onc_blob, - ONCSource onc_source, + ::onc::ONCSource onc_source, const std::string& passphrase, base::ListValue* network_configs, base::DictionaryValue* global_network_config, @@ -919,8 +911,8 @@ // Check and see if this is an encrypted ONC file. If so, decrypt it. std::string onc_type; - if (GetString(*toplevel_onc, toplevel_config::kType, &onc_type) && - onc_type == toplevel_config::kEncryptedConfiguration) { + if (GetString(*toplevel_onc, ::onc::toplevel_config::kType, &onc_type) && + onc_type == ::onc::toplevel_config::kEncryptedConfiguration) { toplevel_onc = Decrypt(passphrase, *toplevel_onc); if (!toplevel_onc) { LOG(ERROR) << "Couldn't decrypt the ONC from " @@ -929,8 +921,8 @@ } } - bool from_policy = (onc_source == ONC_SOURCE_USER_POLICY || - onc_source == ONC_SOURCE_DEVICE_POLICY); + bool from_policy = (onc_source == ::onc::ONC_SOURCE_USER_POLICY || + onc_source == ::onc::ONC_SOURCE_DEVICE_POLICY); // Validate the ONC dictionary. We are liberal and ignore unknown field // names and ignore invalid field names in kRecommended arrays. @@ -965,7 +957,7 @@ if (certificates) { base::Value* validated_certs = toplevel_onc->FindKeyOfType( - toplevel_config::kCertificates, base::Value::Type::LIST); + ::onc::toplevel_config::kCertificates, base::Value::Type::LIST); if (validated_certs) certificates->GetList().swap(validated_certs->GetList()); } @@ -975,7 +967,7 @@ // value of the function (which is supposed to aggregate validation issues in // all segments of the ONC blob). base::Value* validated_networks = toplevel_onc->FindKeyOfType( - toplevel_config::kNetworkConfigurations, base::Value::Type::LIST); + ::onc::toplevel_config::kNetworkConfigurations, base::Value::Type::LIST); base::ListValue* validated_networks_list; if (validated_networks && validated_networks->GetAsList(&validated_networks_list)) { @@ -997,7 +989,7 @@ if (global_network_config) { base::Value* validated_global_config = toplevel_onc->FindKeyOfType( - toplevel_config::kGlobalNetworkConfiguration, + ::onc::toplevel_config::kGlobalNetworkConfiguration, base::Value::Type::DICTIONARY); if (validated_global_config) { base::DictionaryValue* validated_global_config_dict = nullptr;
diff --git a/chromeos/network/onc/onc_validator.cc b/chromeos/network/onc/onc_validator.cc index 682aefe..5ccc595 100644 --- a/chromeos/network/onc/onc_validator.cc +++ b/chromeos/network/onc/onc_validator.cc
@@ -30,11 +30,6 @@ // According to the IEEE 802.11 standard the SSID is a series of 0 to 32 octets. const int kMaximumSSIDLengthInBytes = 32; -template <typename T, size_t N> -std::vector<T> toVector(T const (&array)[N]) { - return std::vector<T>(array, array + N); -} - void AddKeyToList(const char* key, base::Value::ListStorage& list) { base::Value key_value(key); if (!base::Contains(list, key_value)) @@ -332,23 +327,28 @@ bool Validator::ValidateClientCertFields(bool allow_cert_type_none, base::DictionaryValue* result) { - using namespace ::onc::client_cert; - const char* const kValidCertTypes[] = {kRef, kPattern, kPKCS11Id}; - std::vector<const char*> valid_cert_types(toVector(kValidCertTypes)); + std::vector<const char*> valid_cert_types = {::onc::client_cert::kRef, + ::onc::client_cert::kPattern, + ::onc::client_cert::kPKCS11Id}; if (allow_cert_type_none) - valid_cert_types.push_back(kClientCertTypeNone); - if (FieldExistsAndHasNoValidValue(*result, kClientCertType, valid_cert_types)) + valid_cert_types.push_back(::onc::client_cert::kClientCertTypeNone); + if (FieldExistsAndHasNoValidValue( + *result, ::onc::client_cert::kClientCertType, valid_cert_types)) return false; - std::string cert_type = GetStringFromDict(*result, kClientCertType); + std::string cert_type = + GetStringFromDict(*result, ::onc::client_cert::kClientCertType); bool all_required_exist = true; - if (cert_type == kPattern) - all_required_exist &= RequireField(*result, kClientCertPattern); - else if (cert_type == kRef) - all_required_exist &= RequireField(*result, kClientCertRef); - else if (cert_type == kPKCS11Id) - all_required_exist &= RequireField(*result, kClientCertPKCS11Id); + if (cert_type == ::onc::client_cert::kPattern) + all_required_exist &= + RequireField(*result, ::onc::client_cert::kClientCertPattern); + else if (cert_type == ::onc::client_cert::kRef) + all_required_exist &= + RequireField(*result, ::onc::client_cert::kClientCertRef); + else if (cert_type == ::onc::client_cert::kPKCS11Id) + all_required_exist &= + RequireField(*result, ::onc::client_cert::kClientCertPKCS11Id); return !error_on_missing_field_ || all_required_exist; } @@ -609,12 +609,11 @@ } bool Validator::ValidateToplevelConfiguration(base::DictionaryValue* result) { - using namespace ::onc::toplevel_config; - - const char* const kValidTypes[] = {kUnencryptedConfiguration, - kEncryptedConfiguration}; - const std::vector<const char*> valid_types(toVector(kValidTypes)); - if (FieldExistsAndHasNoValidValue(*result, kType, valid_types)) + const std::vector<const char*> valid_types = { + ::onc::toplevel_config::kUnencryptedConfiguration, + ::onc::toplevel_config::kEncryptedConfiguration}; + if (FieldExistsAndHasNoValidValue(*result, ::onc::toplevel_config::kType, + valid_types)) return false; if (IsGlobalNetworkConfigInUserImport(*result)) @@ -624,48 +623,49 @@ } bool Validator::ValidateNetworkConfiguration(base::DictionaryValue* result) { - using namespace ::onc::network_config; - - const std::string* onc_type = result->FindStringKey(kType); + const std::string* onc_type = + result->FindStringKey(::onc::network_config::kType); if (onc_type && *onc_type == ::onc::network_type::kWimaxDeprecated) { AddValidationIssue(/*is_error=*/false, "WiMax is deprecated"); return true; } - const char* const kValidTypes[] = { + const std::vector<const char*> valid_types = { ::onc::network_type::kEthernet, ::onc::network_type::kVPN, ::onc::network_type::kWiFi, ::onc::network_type::kCellular, ::onc::network_type::kTether, }; - const std::vector<const char*> valid_types(toVector(kValidTypes)); - const char* const kValidIPConfigTypes[] = {kIPConfigTypeDHCP, - kIPConfigTypeStatic}; - const std::vector<const char*> valid_ipconfig_types( - toVector(kValidIPConfigTypes)); - if (FieldExistsAndHasNoValidValue(*result, kType, valid_types) || - FieldExistsAndHasNoValidValue(*result, kIPAddressConfigType, + const std::vector<const char*> valid_ipconfig_types = { + ::onc::network_config::kIPConfigTypeDHCP, + ::onc::network_config::kIPConfigTypeStatic}; + if (FieldExistsAndHasNoValidValue(*result, ::onc::network_config::kType, + valid_types) || + FieldExistsAndHasNoValidValue(*result, + ::onc::network_config::kIPAddressConfigType, valid_ipconfig_types) || - FieldExistsAndHasNoValidValue(*result, kNameServersConfigType, - valid_ipconfig_types) || - FieldExistsAndIsEmpty(*result, kGUID)) { + FieldExistsAndHasNoValidValue( + *result, ::onc::network_config::kNameServersConfigType, + valid_ipconfig_types) || + FieldExistsAndIsEmpty(*result, ::onc::network_config::kGUID)) { return false; } - if (!CheckGuidIsUniqueAndAddToSet(*result, kGUID, &network_guids_)) + if (!CheckGuidIsUniqueAndAddToSet(*result, ::onc::network_config::kGUID, + &network_guids_)) return false; - bool all_required_exist = RequireField(*result, kGUID); + bool all_required_exist = RequireField(*result, ::onc::network_config::kGUID); bool remove = false; result->GetBooleanWithoutPathExpansion(::onc::kRemove, &remove); if (!remove) { - all_required_exist &= - RequireField(*result, kName) && RequireField(*result, kType); + all_required_exist &= RequireField(*result, ::onc::network_config::kName) && + RequireField(*result, ::onc::network_config::kType); if (!NetworkHasCorrectStaticIPConfig(result)) return false; - std::string type = GetStringFromDict(*result, kType); + std::string type = GetStringFromDict(*result, ::onc::network_config::kType); // Prohibit anything but WiFi and Ethernet for device-level policy (which // corresponds to shared networks). See also http://crosbug.com/28741. @@ -702,30 +702,26 @@ } bool Validator::ValidateEthernet(base::DictionaryValue* result) { - using namespace ::onc::ethernet; - - const char* const kValidAuthentications[] = {kAuthenticationNone, k8021X}; - const std::vector<const char*> valid_authentications( - toVector(kValidAuthentications)); - if (FieldExistsAndHasNoValidValue( - *result, kAuthentication, valid_authentications)) { + const std::vector<const char*> valid_authentications = { + ::onc::ethernet::kAuthenticationNone, ::onc::ethernet::k8021X}; + if (FieldExistsAndHasNoValidValue(*result, ::onc::ethernet::kAuthentication, + valid_authentications)) { return false; } bool all_required_exist = true; - std::string auth = GetStringFromDict(*result, kAuthentication); - if (auth == k8021X) - all_required_exist &= RequireField(*result, kEAP); + std::string auth = + GetStringFromDict(*result, ::onc::ethernet::kAuthentication); + if (auth == ::onc::ethernet::k8021X) + all_required_exist &= RequireField(*result, ::onc::ethernet::kEAP); return !error_on_missing_field_ || all_required_exist; } bool Validator::ValidateIPConfig(base::DictionaryValue* result, bool require_fields) { - using namespace ::onc::ipconfig; - - const char* const kValidTypes[] = {kIPv4, kIPv6}; - const std::vector<const char*> valid_types(toVector(kValidTypes)); + const std::vector<const char*> valid_types = {::onc::ipconfig::kIPv4, + ::onc::ipconfig::kIPv6}; if (FieldExistsAndHasNoValidValue( *result, ::onc::ipconfig::kType, valid_types)) return false; @@ -733,22 +729,25 @@ std::string type = GetStringFromDict(*result, ::onc::ipconfig::kType); int lower_bound = 1; // In case of missing type, choose higher upper_bound. - int upper_bound = (type == kIPv4) ? 32 : 128; - if (FieldExistsAndIsNotInRange( - *result, kRoutingPrefix, lower_bound, upper_bound)) { + int upper_bound = (type == ::onc::ipconfig::kIPv4) ? 32 : 128; + if (FieldExistsAndIsNotInRange(*result, ::onc::ipconfig::kRoutingPrefix, + lower_bound, upper_bound)) { return false; } bool all_required_exist = true; if (require_fields) { - all_required_exist &= RequireField(*result, kIPAddress); - all_required_exist &= RequireField(*result, kRoutingPrefix); - all_required_exist &= RequireField(*result, kGateway); - } else { - all_required_exist &= FieldShouldExistOrBeRecommended(*result, kIPAddress); + all_required_exist &= RequireField(*result, ::onc::ipconfig::kIPAddress); all_required_exist &= - FieldShouldExistOrBeRecommended(*result, kRoutingPrefix); - all_required_exist &= FieldShouldExistOrBeRecommended(*result, kGateway); + RequireField(*result, ::onc::ipconfig::kRoutingPrefix); + all_required_exist &= RequireField(*result, ::onc::ipconfig::kGateway); + } else { + all_required_exist &= + FieldShouldExistOrBeRecommended(*result, ::onc::ipconfig::kIPAddress); + all_required_exist &= FieldShouldExistOrBeRecommended( + *result, ::onc::ipconfig::kRoutingPrefix); + all_required_exist &= + FieldShouldExistOrBeRecommended(*result, ::onc::ipconfig::kGateway); } return !error_on_missing_field_ || all_required_exist; @@ -756,101 +755,98 @@ bool Validator::NetworkHasCorrectStaticIPConfig( base::DictionaryValue* network) { - using namespace ::onc::network_config; - using namespace ::onc::ipconfig; - bool must_have_ip_config = FieldIsSetToValueOrRecommended( - *network, kIPAddressConfigType, base::Value(kIPConfigTypeStatic)); + *network, ::onc::network_config::kIPAddressConfigType, + base::Value(::onc::network_config::kIPConfigTypeStatic)); bool must_have_nameservers = FieldIsSetToValueOrRecommended( - *network, kNameServersConfigType, base::Value(kIPConfigTypeStatic)); + *network, ::onc::network_config::kNameServersConfigType, + base::Value(::onc::network_config::kIPConfigTypeStatic)); if (!must_have_ip_config && !must_have_nameservers) return true; - if (!RequireField(*network, kStaticIPConfig)) + if (!RequireField(*network, ::onc::network_config::kStaticIPConfig)) return false; base::DictionaryValue* static_ip_config = nullptr; - network->GetDictionary(kStaticIPConfig, &static_ip_config); + network->GetDictionary(::onc::network_config::kStaticIPConfig, + &static_ip_config); bool valid = true; // StaticIPConfig should have all fields required by the corresponding // IPAddressConfigType and NameServersConfigType values. if (must_have_ip_config) valid &= ValidateIPConfig(static_ip_config, false /* require_fields */); if (must_have_nameservers) - valid &= FieldShouldExistOrBeRecommended(*static_ip_config, kNameServers); + valid &= FieldShouldExistOrBeRecommended(*static_ip_config, + ::onc::ipconfig::kNameServers); return valid; } bool Validator::ValidateWiFi(base::DictionaryValue* result) { - using namespace ::onc::wifi; - - const char* const kValidSecurities[] = {kSecurityNone, kWEP_PSK, kWEP_8021X, - kWPA_PSK, kWPA_EAP}; - const std::vector<const char*> valid_securities(toVector(kValidSecurities)); - if (FieldExistsAndHasNoValidValue(*result, kSecurity, valid_securities)) + const std::vector<const char*> valid_securities = { + ::onc::wifi::kSecurityNone, ::onc::wifi::kWEP_PSK, + ::onc::wifi::kWEP_8021X, ::onc::wifi::kWPA_PSK, ::onc::wifi::kWPA_EAP}; + if (FieldExistsAndHasNoValidValue(*result, ::onc::wifi::kSecurity, + valid_securities)) return false; if (!ValidateSSIDAndHexSSID(result)) return false; - bool all_required_exist = RequireField(*result, kSecurity); + bool all_required_exist = RequireField(*result, ::onc::wifi::kSecurity); // One of {kSSID, kHexSSID} must be present. - if (!result->HasKey(kSSID)) - all_required_exist &= RequireField(*result, kHexSSID); - if (!result->HasKey(kHexSSID)) - all_required_exist &= RequireField(*result, kSSID); + if (!result->HasKey(::onc::wifi::kSSID)) + all_required_exist &= RequireField(*result, ::onc::wifi::kHexSSID); + if (!result->HasKey(::onc::wifi::kHexSSID)) + all_required_exist &= RequireField(*result, ::onc::wifi::kSSID); - std::string security = GetStringFromDict(*result, kSecurity); - if (security == kWEP_8021X || security == kWPA_EAP) - all_required_exist &= RequireField(*result, kEAP); - else if (security == kWEP_PSK || security == kWPA_PSK) - all_required_exist &= RequireField(*result, kPassphrase); + std::string security = GetStringFromDict(*result, ::onc::wifi::kSecurity); + if (security == ::onc::wifi::kWEP_8021X || security == ::onc::wifi::kWPA_EAP) + all_required_exist &= RequireField(*result, ::onc::wifi::kEAP); + else if (security == ::onc::wifi::kWEP_PSK || + security == ::onc::wifi::kWPA_PSK) + all_required_exist &= RequireField(*result, ::onc::wifi::kPassphrase); return !error_on_missing_field_ || all_required_exist; } bool Validator::ValidateVPN(base::DictionaryValue* result) { - using namespace ::onc::vpn; - - const char* const kValidTypes[] = {kIPsec, kTypeL2TP_IPsec, kOpenVPN, - kThirdPartyVpn, kArcVpn}; - const std::vector<const char*> valid_types(toVector(kValidTypes)); + const std::vector<const char*> valid_types = { + ::onc::vpn::kIPsec, ::onc::vpn::kTypeL2TP_IPsec, ::onc::vpn::kOpenVPN, + ::onc::vpn::kThirdPartyVpn, ::onc::vpn::kArcVpn}; if (FieldExistsAndHasNoValidValue(*result, ::onc::vpn::kType, valid_types)) return false; bool all_required_exist = RequireField(*result, ::onc::vpn::kType); std::string type = GetStringFromDict(*result, ::onc::vpn::kType); - if (type == kOpenVPN) { - all_required_exist &= RequireField(*result, kOpenVPN); - } else if (type == kIPsec) { - all_required_exist &= RequireField(*result, kIPsec); - } else if (type == kTypeL2TP_IPsec) { - all_required_exist &= - RequireField(*result, kIPsec) && RequireField(*result, kL2TP); - } else if (type == kThirdPartyVpn) { - all_required_exist &= RequireField(*result, kThirdPartyVpn); - } else if (type == kArcVpn) { - all_required_exist &= RequireField(*result, kArcVpn); + if (type == ::onc::vpn::kOpenVPN) { + all_required_exist &= RequireField(*result, ::onc::vpn::kOpenVPN); + } else if (type == ::onc::vpn::kIPsec) { + all_required_exist &= RequireField(*result, ::onc::vpn::kIPsec); + } else if (type == ::onc::vpn::kTypeL2TP_IPsec) { + all_required_exist &= RequireField(*result, ::onc::vpn::kIPsec) && + RequireField(*result, ::onc::vpn::kL2TP); + } else if (type == ::onc::vpn::kThirdPartyVpn) { + all_required_exist &= RequireField(*result, ::onc::vpn::kThirdPartyVpn); + } else if (type == ::onc::vpn::kArcVpn) { + all_required_exist &= RequireField(*result, ::onc::vpn::kArcVpn); } return !error_on_missing_field_ || all_required_exist; } bool Validator::ValidateIPsec(base::DictionaryValue* result) { - using namespace ::onc::ipsec; - - const char* const kValidAuthentications[] = {kPSK, kCert}; - const std::vector<const char*> valid_authentications( - toVector(kValidAuthentications)); - if (FieldExistsAndHasNoValidValue( - *result, kAuthenticationType, valid_authentications) || - FieldExistsAndIsEmpty(*result, kServerCARefs)) { + const std::vector<const char*> valid_authentications = {::onc::ipsec::kPSK, + ::onc::ipsec::kCert}; + if (FieldExistsAndHasNoValidValue(*result, ::onc::ipsec::kAuthenticationType, + valid_authentications) || + FieldExistsAndIsEmpty(*result, ::onc::ipsec::kServerCARefs)) { return false; } - if (!OnlyOneFieldSet(*result, kServerCARefs, kServerCARef)) + if (!OnlyOneFieldSet(*result, ::onc::ipsec::kServerCARefs, + ::onc::ipsec::kServerCARef)) return false; if (!ValidateClientCertFields(false, // don't allow ClientCertType None @@ -858,25 +854,29 @@ return false; } - bool all_required_exist = RequireField(*result, kAuthenticationType) && - RequireField(*result, kIKEVersion); - std::string auth = GetStringFromDict(*result, kAuthenticationType); - bool has_server_ca_cert = - result->HasKey(kServerCARefs) || result->HasKey(kServerCARef); - if (auth == kCert) { + bool all_required_exist = + RequireField(*result, ::onc::ipsec::kAuthenticationType) && + RequireField(*result, ::onc::ipsec::kIKEVersion); + std::string auth = + GetStringFromDict(*result, ::onc::ipsec::kAuthenticationType); + bool has_server_ca_cert = result->HasKey(::onc::ipsec::kServerCARefs) || + result->HasKey(::onc::ipsec::kServerCARef); + if (auth == ::onc::ipsec::kCert) { all_required_exist &= RequireField(*result, ::onc::client_cert::kClientCertType); if (!has_server_ca_cert) { all_required_exist = false; std::ostringstream msg; - msg << "The required field '" << kServerCARefs << "' is missing."; + msg << "The required field '" << ::onc::ipsec::kServerCARefs + << "' is missing."; AddValidationIssue(error_on_missing_field_, msg.str()); } } else if (has_server_ca_cert) { std::ostringstream msg; - msg << "Field '" << kServerCARefs << "' (or '" << kServerCARef - << "') can only be set if '" << kAuthenticationType << "' is set to '" - << kCert << "'."; + msg << "Field '" << ::onc::ipsec::kServerCARefs << "' (or '" + << ::onc::ipsec::kServerCARef << "') can only be set if '" + << ::onc::ipsec::kAuthenticationType << "' is set to '" + << ::onc::ipsec::kCert << "'."; AddValidationIssue(true /* is_error */, msg.str()); return false; } @@ -885,31 +885,24 @@ } bool Validator::ValidateOpenVPN(base::DictionaryValue* result) { - using namespace ::onc::openvpn; - - const char* const kValidAuthRetryValues[] = {::onc::openvpn::kNone, kInteract, - kNoInteract}; - const std::vector<const char*> valid_auth_retry_values( - toVector(kValidAuthRetryValues)); - const char* const kValidCertTlsValues[] = {::onc::openvpn::kNone, - ::onc::openvpn::kServer}; - const std::vector<const char*> valid_cert_tls_values( - toVector(kValidCertTlsValues)); - const char* const kValidUserAuthTypes[] = { - ::onc::openvpn_user_auth_type::kNone, - ::onc::openvpn_user_auth_type::kOTP, + const std::vector<const char*> valid_auth_retry_values = { + ::onc::openvpn::kNone, ::onc::openvpn::kInteract, + ::onc::openvpn::kNoInteract}; + const std::vector<const char*> valid_cert_tls_values = { + ::onc::openvpn::kNone, ::onc::openvpn::kServer}; + const std::vector<const char*> valid_user_auth_types = { + ::onc::openvpn_user_auth_type::kNone, ::onc::openvpn_user_auth_type::kOTP, ::onc::openvpn_user_auth_type::kPassword, ::onc::openvpn_user_auth_type::kPasswordAndOTP}; - const std::vector<const char*> valid_user_auth_types( - toVector(kValidUserAuthTypes)); - if (FieldExistsAndHasNoValidValue( - *result, kAuthRetry, valid_auth_retry_values) || - FieldExistsAndHasNoValidValue( - *result, kRemoteCertTLS, valid_cert_tls_values) || - FieldExistsAndHasNoValidValue( - *result, kUserAuthenticationType, valid_user_auth_types) || - FieldExistsAndIsEmpty(*result, kServerCARefs)) { + if (FieldExistsAndHasNoValidValue(*result, ::onc::openvpn::kAuthRetry, + valid_auth_retry_values) || + FieldExistsAndHasNoValidValue(*result, ::onc::openvpn::kRemoteCertTLS, + valid_cert_tls_values) || + FieldExistsAndHasNoValidValue(*result, + ::onc::openvpn::kUserAuthenticationType, + valid_user_auth_types) || + FieldExistsAndIsEmpty(*result, ::onc::openvpn::kServerCARefs)) { return false; } @@ -944,7 +937,8 @@ } } - if (!OnlyOneFieldSet(*result, kServerCARefs, kServerCARef)) + if (!OnlyOneFieldSet(*result, ::onc::openvpn::kServerCARefs, + ::onc::openvpn::kServerCARef)) return false; if (!ValidateClientCertFields(true /* allow ClientCertType None */, result)) @@ -971,30 +965,30 @@ } bool Validator::ValidateVerifyX509(base::DictionaryValue* result) { - using namespace ::onc::verify_x509; + const std::vector<const char*> valid_types = { + ::onc::verify_x509::types::kName, ::onc::verify_x509::types::kNamePrefix, + ::onc::verify_x509::types::kSubject}; - const char* const kValidTypes[] = {types::kName, types::kNamePrefix, - types::kSubject}; - const std::vector<const char*> valid_types(toVector(kValidTypes)); - - if (FieldExistsAndHasNoValidValue(*result, kType, valid_types)) + if (FieldExistsAndHasNoValidValue(*result, ::onc::verify_x509::kType, + valid_types)) return false; - bool all_required_exist = RequireField(*result, kName); + bool all_required_exist = RequireField(*result, ::onc::verify_x509::kName); return !error_on_missing_field_ || all_required_exist; } bool Validator::ValidateCertificatePattern(base::DictionaryValue* result) { - using namespace ::onc::client_cert; - bool all_required_exist = true; - if (!result->HasKey(kSubject) && !result->HasKey(kIssuer) && - !result->HasKey(kIssuerCARef)) { + if (!result->HasKey(::onc::client_cert::kSubject) && + !result->HasKey(::onc::client_cert::kIssuer) && + !result->HasKey(::onc::client_cert::kIssuerCARef)) { all_required_exist = false; std::ostringstream msg; - msg << "None of the fields '" << kSubject << "', '" << kIssuer << "', and '" - << kIssuerCARef << "' is present, but at least one is required."; + msg << "None of the fields '" << ::onc::client_cert::kSubject << "', '" + << ::onc::client_cert::kIssuer << "', and '" + << ::onc::client_cert::kIssuerCARef + << "' is present, but at least one is required."; AddValidationIssue(error_on_missing_field_, msg.str()); } @@ -1003,102 +997,104 @@ bool Validator::ValidateGlobalNetworkConfiguration( base::DictionaryValue* result) { - using namespace ::onc::global_network_config; - using namespace ::onc::network_config; - // Validate that kDisableNetworkTypes, kAllowOnlyPolicyNetworksToConnect and // kBlacklistedHexSSIDs are only allowed in device policy. - if (!IsInDevicePolicy(result, kDisableNetworkTypes) || - !IsInDevicePolicy(result, kAllowOnlyPolicyNetworksToConnect) || - !IsInDevicePolicy(result, kAllowOnlyPolicyNetworksToConnectIfAvailable) || - !IsInDevicePolicy(result, kBlacklistedHexSSIDs)) { + if (!IsInDevicePolicy(result, + ::onc::global_network_config::kDisableNetworkTypes) || + !IsInDevicePolicy( + result, + ::onc::global_network_config::kAllowOnlyPolicyNetworksToConnect) || + !IsInDevicePolicy(result, + ::onc::global_network_config:: + kAllowOnlyPolicyNetworksToConnectIfAvailable) || + !IsInDevicePolicy(result, + ::onc::global_network_config::kBlacklistedHexSSIDs)) { return false; } // Ensure the list contains only legitimate network type identifiers. - const char* const kValidNetworkTypeValues[] = {kCellular, kEthernet, kWiFi, - kWimaxDeprecated, kTether}; - const std::vector<const char*> valid_network_type_values( - toVector(kValidNetworkTypeValues)); - if (!ListFieldContainsValidValues(*result, kDisableNetworkTypes, - valid_network_type_values)) { + const std::vector<const char*> valid_network_type_values = { + ::onc::network_config::kCellular, ::onc::network_config::kEthernet, + ::onc::network_config::kWiFi, ::onc::network_config::kWimaxDeprecated, + ::onc::network_config::kTether}; + if (!ListFieldContainsValidValues( + *result, ::onc::global_network_config::kDisableNetworkTypes, + valid_network_type_values)) { return false; } return true; } bool Validator::ValidateProxySettings(base::DictionaryValue* result) { - using namespace ::onc::proxy; - - const char* const kValidTypes[] = {kDirect, kManual, kPAC, kWPAD}; - const std::vector<const char*> valid_types(toVector(kValidTypes)); + const std::vector<const char*> valid_types = { + ::onc::proxy::kDirect, ::onc::proxy::kManual, ::onc::proxy::kPAC, + ::onc::proxy::kWPAD}; if (FieldExistsAndHasNoValidValue(*result, ::onc::proxy::kType, valid_types)) return false; bool all_required_exist = RequireField(*result, ::onc::proxy::kType); std::string type = GetStringFromDict(*result, ::onc::proxy::kType); - if (type == kManual) - all_required_exist &= RequireField(*result, kManual); - else if (type == kPAC) - all_required_exist &= RequireField(*result, kPAC); + if (type == ::onc::proxy::kManual) + all_required_exist &= RequireField(*result, ::onc::proxy::kManual); + else if (type == ::onc::proxy::kPAC) + all_required_exist &= RequireField(*result, ::onc::proxy::kPAC); return !error_on_missing_field_ || all_required_exist; } bool Validator::ValidateProxyLocation(base::DictionaryValue* result) { - using namespace ::onc::proxy; - - bool all_required_exist = - RequireField(*result, kHost) && RequireField(*result, kPort); + bool all_required_exist = RequireField(*result, ::onc::proxy::kHost) && + RequireField(*result, ::onc::proxy::kPort); return !error_on_missing_field_ || all_required_exist; } bool Validator::ValidateEAP(base::DictionaryValue* result) { - using namespace ::onc::eap; + const std::vector<const char*> valid_inner_values = { + ::onc::eap::kAutomatic, ::onc::eap::kGTC, ::onc::eap::kMD5, + ::onc::eap::kMSCHAPv2, ::onc::eap::kPAP}; + const std::vector<const char*> valid_outer_values = { + ::onc::eap::kPEAP, ::onc::eap::kEAP_TLS, ::onc::eap::kEAP_TTLS, + ::onc::eap::kLEAP, ::onc::eap::kEAP_SIM, ::onc::eap::kEAP_FAST, + ::onc::eap::kEAP_AKA}; - const char* const kValidInnerValues[] = { - kAutomatic, kGTC, kMD5, kMSCHAPv2, kPAP}; - const std::vector<const char*> valid_inner_values( - toVector(kValidInnerValues)); - const char* const kValidOuterValues[] = { - kPEAP, kEAP_TLS, kEAP_TTLS, kLEAP, kEAP_SIM, kEAP_FAST, kEAP_AKA}; - const std::vector<const char*> valid_outer_values( - toVector(kValidOuterValues)); - - if (FieldExistsAndHasNoValidValue(*result, kInner, valid_inner_values) || - FieldExistsAndHasNoValidValue(*result, kOuter, valid_outer_values) || - FieldExistsAndIsEmpty(*result, kServerCARefs)) { + if (FieldExistsAndHasNoValidValue(*result, ::onc::eap::kInner, + valid_inner_values) || + FieldExistsAndHasNoValidValue(*result, ::onc::eap::kOuter, + valid_outer_values) || + FieldExistsAndIsEmpty(*result, ::onc::eap::kServerCARefs)) { return false; } - if (!OnlyOneFieldSet(*result, kServerCARefs, kServerCARef)) + if (!OnlyOneFieldSet(*result, ::onc::eap::kServerCARefs, + ::onc::eap::kServerCARef)) return false; if (!ValidateClientCertFields(true /* allow ClientCertType None */, result)) return false; - bool all_required_exist = RequireField(*result, kOuter); + bool all_required_exist = RequireField(*result, ::onc::eap::kOuter); return !error_on_missing_field_ || all_required_exist; } bool Validator::ValidateCertificate(base::DictionaryValue* result) { - using namespace ::onc::certificate; - - const char* const kValidTypes[] = {kClient, kServer, kAuthority}; - const std::vector<const char*> valid_types(toVector(kValidTypes)); - if (FieldExistsAndHasNoValidValue(*result, kType, valid_types) || - FieldExistsAndIsEmpty(*result, kGUID)) { + const std::vector<const char*> valid_types = {::onc::certificate::kClient, + ::onc::certificate::kServer, + ::onc::certificate::kAuthority}; + if (FieldExistsAndHasNoValidValue(*result, ::onc::certificate::kType, + valid_types) || + FieldExistsAndIsEmpty(*result, ::onc::certificate::kGUID)) { return false; } - std::string type = GetStringFromDict(*result, kType); + std::string type = GetStringFromDict(*result, ::onc::certificate::kType); - if (!CheckGuidIsUniqueAndAddToSet(*result, kGUID, &certificate_guids_)) + if (!CheckGuidIsUniqueAndAddToSet(*result, ::onc::certificate::kGUID, + &certificate_guids_)) return false; - bool all_required_exist = RequireField(*result, kGUID); + bool all_required_exist = RequireField(*result, ::onc::certificate::kGUID); bool remove = false; result->GetBooleanWithoutPathExpansion(::onc::kRemove, &remove); @@ -1111,35 +1107,35 @@ return false; } - all_required_exist &= RequireField(*result, kType); + all_required_exist &= RequireField(*result, ::onc::certificate::kType); - if (type == kClient) - all_required_exist &= RequireField(*result, kPKCS12); - else if (type == kServer || type == kAuthority) - all_required_exist &= RequireField(*result, kX509); + if (type == ::onc::certificate::kClient) + all_required_exist &= RequireField(*result, ::onc::certificate::kPKCS12); + else if (type == ::onc::certificate::kServer || + type == ::onc::certificate::kAuthority) + all_required_exist &= RequireField(*result, ::onc::certificate::kX509); return !error_on_missing_field_ || all_required_exist; } bool Validator::ValidateScope(base::DictionaryValue* result) { - using namespace ::onc::scope; - - const char* const kValidTypes[] = {kDefault, kExtension}; - const std::vector<const char*> valid_types(toVector(kValidTypes)); - if (FieldExistsAndHasNoValidValue(*result, kType, valid_types) || - FieldExistsAndIsEmpty(*result, kId)) { + const std::vector<const char*> valid_types = {::onc::scope::kDefault, + ::onc::scope::kExtension}; + if (FieldExistsAndHasNoValidValue(*result, ::onc::scope::kType, + valid_types) || + FieldExistsAndIsEmpty(*result, ::onc::scope::kId)) { return false; } - bool all_required_exist = RequireField(*result, kType); - const std::string* type_string = result->FindStringKey(kType); - if (type_string && *type_string == kExtension) { - all_required_exist &= RequireField(*result, kId); + bool all_required_exist = RequireField(*result, ::onc::scope::kType); + const std::string* type_string = result->FindStringKey(::onc::scope::kType); + if (type_string && *type_string == ::onc::scope::kExtension) { + all_required_exist &= RequireField(*result, ::onc::scope::kId); // Check Id validity for type 'Extension'. - const std::string* id_string = result->FindStringKey(kId); + const std::string* id_string = result->FindStringKey(::onc::scope::kId); if (id_string && !crx_file::id_util::IdIsValid(*id_string)) { std::ostringstream msg; - msg << "Field '" << kId << "' is not a valid extension id."; + msg << "Field '" << ::onc::scope::kId << "' is not a valid extension id."; AddValidationIssue(false /* is_error */, msg.str()); return false; } @@ -1149,18 +1145,20 @@ } bool Validator::ValidateTether(base::DictionaryValue* result) { - using namespace ::onc::tether; - - if (FieldExistsAndIsNotInRange(*result, kBatteryPercentage, 0, 100) || - FieldExistsAndIsNotInRange(*result, kSignalStrength, 0, 100) || - FieldExistsAndIsEmpty(*result, kCarrier)) { + if (FieldExistsAndIsNotInRange(*result, ::onc::tether::kBatteryPercentage, 0, + 100) || + FieldExistsAndIsNotInRange(*result, ::onc::tether::kSignalStrength, 0, + 100) || + FieldExistsAndIsEmpty(*result, ::onc::tether::kCarrier)) { return false; } - bool all_required_exist = RequireField(*result, kHasConnectedToHost); - all_required_exist &= RequireField(*result, kBatteryPercentage); - all_required_exist &= RequireField(*result, kSignalStrength); - all_required_exist &= RequireField(*result, kCarrier); + bool all_required_exist = + RequireField(*result, ::onc::tether::kHasConnectedToHost); + all_required_exist &= + RequireField(*result, ::onc::tether::kBatteryPercentage); + all_required_exist &= RequireField(*result, ::onc::tether::kSignalStrength); + all_required_exist &= RequireField(*result, ::onc::tether::kCarrier); return !error_on_missing_field_ || all_required_exist; }
diff --git a/chromeos/services/network_config/cros_network_config.cc b/chromeos/services/network_config/cros_network_config.cc index d80a4dcd..6d2a3ce 100644 --- a/chromeos/services/network_config/cros_network_config.cc +++ b/chromeos/services/network_config/cros_network_config.cc
@@ -1208,7 +1208,7 @@ cellular->apn_list = GetManagedApnList(cellular_dict->FindKey(::onc::cellular::kAPNList)); cellular->allow_roaming = - GetBoolean(properties, ::onc::cellular::kAllowRoaming); + GetBoolean(cellular_dict, ::onc::cellular::kAllowRoaming); cellular->esn = GetString(cellular_dict, ::onc::cellular::kESN); cellular->family = GetString(cellular_dict, ::onc::cellular::kFamily); cellular->firmware_revision =
diff --git a/components/autofill/core/browser/payments/credit_card_access_manager.cc b/components/autofill/core/browser/payments/credit_card_access_manager.cc index 4cd28db83..f20c3de1 100644 --- a/components/autofill/core/browser/payments/credit_card_access_manager.cc +++ b/components/autofill/core/browser/payments/credit_card_access_manager.cc
@@ -32,7 +32,7 @@ namespace { // Timeout to wait for unmask details from Google Payments in milliseconds. -constexpr int64_t kUnmaskDetailsResponseTimeout = 1000; +constexpr int64_t kUnmaskDetailsResponseTimeoutMs = 1000; // Time to wait between multiple calls to GetUnmaskDetails(). constexpr int64_t kDelayForGetUnmaskDetails = 3 * 60 * 1000; // 3 min @@ -40,7 +40,7 @@ bool WaitForEvent(base::WaitableEvent* event) { event->declare_only_used_while_idle(); return event->TimedWait( - base::TimeDelta::FromMilliseconds(kUnmaskDetailsResponseTimeout)); + base::TimeDelta::FromMilliseconds(kUnmaskDetailsResponseTimeoutMs)); } // Used with PostTaskWithDelay() to signal event after a timeout. @@ -271,21 +271,28 @@ } } -void CreditCardAccessManager::FIDOAuthOptChange(bool opt_in, - base::Value creation_options) { +void CreditCardAccessManager::FIDOAuthOptChange(bool opt_in) { #if defined(OS_IOS) return; #else if (opt_in) { - GetOrCreateFIDOAuthenticator()->Register( - /*card_authorization_token=*/std::string(), - std::move(creation_options)); + GetOrCreateFIDOAuthenticator()->ShowWebauthnOfferDialog( + /*card_authorization_token=*/std::string()); } else { GetOrCreateFIDOAuthenticator()->OptOut(); } #endif } +void CreditCardAccessManager::OnSettingsPageFIDOAuthToggled(bool opt_in) { +#if defined(OS_IOS) + return; +#else + // TODO(crbug/949269): Add a rate limiter to counter spam clicking. + FIDOAuthOptChange(opt_in); +#endif +} + void CreditCardAccessManager::Authenticate(bool did_get_unmask_details) { // Reset now that we have started authentication. ready_to_start_authentication_.Reset();
diff --git a/components/autofill/core/browser/payments/credit_card_access_manager.h b/components/autofill/core/browser/payments/credit_card_access_manager.h index 0307279..70d70d29 100644 --- a/components/autofill/core/browser/payments/credit_card_access_manager.h +++ b/components/autofill/core/browser/payments/credit_card_access_manager.h
@@ -91,8 +91,11 @@ // If |opt_in| = true, opts the user into using FIDO authentication for card // unmasking. Otherwise, opts the user out. If |creation_options| is set, // WebAuthn registration prompt will be invoked to create a new credential. - void FIDOAuthOptChange(bool opt_in, - base::Value creation_options = base::Value()); + void FIDOAuthOptChange(bool opt_in); + + // Makes a call to FIDOAuthOptChange() with |opt_in|. + // TODO(crbug/949269): Add a rate limiter to counter spam clicking. + void OnSettingsPageFIDOAuthToggled(bool opt_in); CreditCardCVCAuthenticator* GetOrCreateCVCAuthenticator();
diff --git a/components/autofill_strings.grdp b/components/autofill_strings.grdp index 5a0fffef..468d1cb 100644 --- a/components/autofill_strings.grdp +++ b/components/autofill_strings.grdp
@@ -220,6 +220,39 @@ <message name="IDS_AUTOFILL_ENABLE_CREDIT_CARDS_TOGGLE_LABEL" desc="Label for a toggle that allows users to control whether credit cards should be saved and forms should be autofilled with it. Sentence-Cased." formatter_data="android_java"> Save and fill payment methods </message> + <!-- WebAuthn titles --> + <if expr="is_macosx"> + <message name="IDS_ENABLE_CREDIT_CARD_FIDO_AUTH_LABEL" desc="The product name of the fingerprint reader on macOS. Label for a toggle that allows users to control whether or not to use FIDO authentication for credit card unmasking. Title-Cased."> + Touch ID + </message> + <message name="IDS_ENABLE_CREDIT_CARD_FIDO_AUTH_SUBLABEL" desc="Sublabel for a toggle that allows users to control whether or not to use FIDO authentication for credit card unmasking on macOS. Sentence-Cased."> + Use Touch ID to verify your saved payment methods. + </message> + </if> + <if expr="is_win"> + <message name="IDS_ENABLE_CREDIT_CARD_FIDO_AUTH_LABEL" desc="The product name of the authentication system on Windows. Label for a toggle that allows users to control whether or not to use FIDO authentication for credit card unmasking. Title-Cased."> + Windows Hello + </message> + <message name="IDS_ENABLE_CREDIT_CARD_FIDO_AUTH_SUBLABEL" desc="Sublabel for a toggle that allows users to control whether or not to use FIDO authentication for credit card unmasking on Windows. Sentence-Cased."> + Use Windows Hello to verify your saved payment methods. + </message> + </if> + <if expr="is_android"> + <message name="IDS_ENABLE_CREDIT_CARD_FIDO_AUTH_LABEL" desc="The authentication mechanism on Android. Label for a toggle that allows users to control whether or not to use FIDO authentication for credit card unmasking. Title-Cased."> + Screen lock + </message> + <message name="IDS_ENABLE_CREDIT_CARD_FIDO_AUTH_SUBLABEL" desc="Sublabel for a toggle that allows users to control whether or not to use FIDO authentication for credit card unmasking for Android. Sentence-Cased."> + Use screen lock to verify your saved payment methods. + </message> + </if> + <if expr="not is_macosx and not is_win and not is_android"> + <message name="IDS_ENABLE_CREDIT_CARD_FIDO_AUTH_LABEL" desc="Label for a toggle that allows users to control whether or not to use FIDO authentication for credit card unmasking. Title-Cased."> + Biometrics + </message> + <message name="IDS_ENABLE_CREDIT_CARD_FIDO_AUTH_SUBLABEL" desc="Sublabel for a toggle that allows users to control whether or not to use FIDO authentication for credit card unmasking. Sentence-Cased."> + This feature is not available on your device. + </message> + </if> </then> <else> <message name="IDS_AUTOFILL_ADDRESSES_SETTINGS_TITLE" desc="Title for the Autofill settings page that allows user to manage their list of saved addresses and Autofill preferences for addresses. Title-Cased.">
diff --git a/components/browser_sync/profile_sync_components_factory_impl.cc b/components/browser_sync/profile_sync_components_factory_impl.cc index fd7d746..8b4002e 100644 --- a/components/browser_sync/profile_sync_components_factory_impl.cc +++ b/components/browser_sync/profile_sync_components_factory_impl.cc
@@ -146,8 +146,16 @@ syncer::RepeatingModelTypeStoreFactory model_type_store_factory = model_type_store_service->GetStoreFactory(); + // TODO(crbug.com/1005651): Consider using a separate delegate for + // transport-only. controllers.push_back(std::make_unique<ModelTypeController>( syncer::DEVICE_INFO, + /*delegate_for_full_sync_mode=*/ + std::make_unique<syncer::ForwardingModelTypeControllerDelegate>( + sync_client_->GetDeviceInfoSyncService() + ->GetControllerDelegate() + .get()), + /*delegate_for_transport_mode=*/ std::make_unique<syncer::ForwardingModelTypeControllerDelegate>( sync_client_->GetDeviceInfoSyncService() ->GetControllerDelegate()
diff --git a/components/cdm/browser/cdm_message_filter_android.cc b/components/cdm/browser/cdm_message_filter_android.cc index 18fa7ee0..1357cf68 100644 --- a/components/cdm/browser/cdm_message_filter_android.cc +++ b/components/cdm/browser/cdm_message_filter_android.cc
@@ -49,7 +49,7 @@ #if BUILDFLAG(ENABLE_PLATFORM_HEVC) {media::EME_CODEC_HEVC, media::kCodecHEVC}, #endif -#if BUILDFLAG(ENABLE_DOLBY_VISION_DEMUXING) +#if BUILDFLAG(ENABLE_PLATFORM_DOLBY_VISION) {media::EME_CODEC_DOLBY_VISION_AVC, media::kCodecDolbyVision}, #if BUILDFLAG(ENABLE_PLATFORM_HEVC) {media::EME_CODEC_DOLBY_VISION_HEVC, media::kCodecDolbyVision}, @@ -68,7 +68,7 @@ const CodecInfo<media::AudioCodec> kMP4AudioCodecsToQuery[] = { #if BUILDFLAG(USE_PROPRIETARY_CODECS) {media::EME_CODEC_AAC, media::kCodecAAC}, -#if BUILDFLAG(ENABLE_AC3_EAC3_AUDIO_DEMUXING) +#if BUILDFLAG(ENABLE_PLATFORM_AC3_EAC3_AUDIO) {media::EME_CODEC_AC3, media::kCodecAC3}, {media::EME_CODEC_EAC3, media::kCodecEAC3}, #endif
diff --git a/components/crash/content/tools/generate_breakpad_symbols.py b/components/crash/content/tools/generate_breakpad_symbols.py index 41895d6..dcf26b7 100755 --- a/components/crash/content/tools/generate_breakpad_symbols.py +++ b/components/crash/content/tools/generate_breakpad_symbols.py
@@ -74,11 +74,14 @@ return result -def GetSharedLibraryDependenciesAndroid(binary): - """Return absolute paths to all shared library dependencies of the binary. +def _GetSharedLibraryDependenciesAndroidOrChromeOS(binary): + """GetSharedLibraryDependencies* suitable for Android or ChromeOS. - This implementation assumes that we're running on a Linux system, but - compiled for Android.""" + Both assume that the host is Linux-based, but the binary being symbolized is + being run on a device with potentially different architectures. Unlike ldd, + readelf plays nice with mixed host/device architectures (e.g. x86-64 host, + arm64 device), so use that. + """ readelf = subprocess.check_output(['readelf', '-d', binary]) lib_re = re.compile('Shared library: \[(.+)\]$') result = [] @@ -92,6 +95,14 @@ return result +def GetSharedLibraryDependenciesAndroid(binary): + """Return absolute paths to all shared library dependencies of the binary. + + This implementation assumes that we're running on a Linux system, but + compiled for Android.""" + return _GetSharedLibraryDependenciesAndroidOrChromeOS(binary) + + def GetDeveloperDirMac(): """Finds a good DEVELOPER_DIR value to run Mac dev tools. @@ -192,6 +203,14 @@ return deps +def GetSharedLibraryDependenciesChromeOS(binary): + """Return absolute paths to all shared library dependencies of the binary. + + This implementation assumes that we're running on a Linux system, but + compiled for ChromeOS.""" + return _GetSharedLibraryDependenciesAndroidOrChromeOS(binary) + + def GetSharedLibraryDependencies(options, binary, exe_path): """Return absolute paths to all shared library dependencies of the binary.""" deps = [] @@ -201,6 +220,8 @@ deps = GetSharedLibraryDependenciesAndroid(binary) elif options.platform == 'darwin': deps = GetSharedLibraryDependenciesMac(binary, exe_path) + elif options.platform == 'chromeos': + deps = GetSharedLibraryDependenciesChromeOS(binary) else: print "Platform not supported." sys.exit(1) @@ -224,7 +245,8 @@ deps = set(GetSharedLibraryDependencies(options, binary, exe_path)) deps.add(binary) return list(deps) - elif options.platform == 'darwin' or options.platform == 'android': + elif (options.platform == 'darwin' or options.platform == 'android' or + options.platform == 'chromeos'): binaries = set([binary]) queue = [binary] while queue:
diff --git a/components/history/core/browser/history_types.h b/components/history/core/browser/history_types.h index c84ce0b..63f801d 100644 --- a/components/history/core/browser/history_types.h +++ b/components/history/core/browser/history_types.h
@@ -425,8 +425,6 @@ MostVisitedURLWithRankList moved; }; -typedef base::RefCountedData<MostVisitedURLList> MostVisitedThreadSafe; - // Map from origins to a count of matching URLs and the last visited time to any // URL under that origin. typedef std::map<GURL, std::pair<int, base::Time>> OriginCountAndLastVisitMap;
diff --git a/components/history/core/browser/top_sites_backend.cc b/components/history/core/browser/top_sites_backend.cc index f1494701..2e50dc11 100644 --- a/components/history/core/browser/top_sites_backend.cc +++ b/components/history/core/browser/top_sites_backend.cc
@@ -46,12 +46,10 @@ void TopSitesBackend::GetMostVisitedSites( GetMostVisitedSitesCallback callback, base::CancelableTaskTracker* tracker) { - scoped_refptr<MostVisitedThreadSafe> sites = new MostVisitedThreadSafe(); - tracker->PostTaskAndReply( + tracker->PostTaskAndReplyWithResult( db_task_runner_.get(), FROM_HERE, - base::BindOnce(&TopSitesBackend::GetMostVisitedSitesOnDBThread, this, - sites), - base::BindOnce(std::move(callback), sites)); + base::BindOnce(&TopSitesBackend::GetMostVisitedSitesOnDBThread, this), + std::move(callback)); } void TopSitesBackend::UpdateTopSites(const TopSitesDelta& delta, @@ -85,13 +83,12 @@ db_.reset(); } -void TopSitesBackend::GetMostVisitedSitesOnDBThread( - scoped_refptr<MostVisitedThreadSafe> sites) { +MostVisitedURLList TopSitesBackend::GetMostVisitedSitesOnDBThread() { DCHECK(db_task_runner_->RunsTasksInCurrentSequence()); - - if (db_) { - db_->GetSites(&(sites->data)); - } + MostVisitedURLList list; + if (db_) + db_->GetSites(&list); + return list; } void TopSitesBackend::UpdateTopSitesOnDBThread(
diff --git a/components/history/core/browser/top_sites_backend.h b/components/history/core/browser/top_sites_backend.h index 38745ab..20e4839a 100644 --- a/components/history/core/browser/top_sites_backend.h +++ b/components/history/core/browser/top_sites_backend.h
@@ -38,7 +38,7 @@ }; using GetMostVisitedSitesCallback = - base::OnceCallback<void(const scoped_refptr<MostVisitedThreadSafe>&)>; + base::OnceCallback<void(MostVisitedURLList)>; TopSitesBackend(); @@ -47,7 +47,7 @@ // Schedules the db to be shutdown. void Shutdown(); - // Fetches MostVisitedThreadSafe. + // Fetches MostVisitedURLList. void GetMostVisitedSites(GetMostVisitedSitesCallback callback, base::CancelableTaskTracker* tracker); @@ -70,8 +70,7 @@ void ShutdownDBOnDBThread(); // Does the work of getting the most visited sites. - void GetMostVisitedSitesOnDBThread( - scoped_refptr<MostVisitedThreadSafe> sites); + MostVisitedURLList GetMostVisitedSitesOnDBThread(); // Updates top sites. void UpdateTopSitesOnDBThread(const TopSitesDelta& delta,
diff --git a/components/history/core/browser/top_sites_impl.cc b/components/history/core/browser/top_sites_impl.cc index 29e814e..d214954 100644 --- a/components/history/core/browser/top_sites_impl.cc +++ b/components/history/core/browser/top_sites_impl.cc
@@ -128,13 +128,11 @@ callback.Run(filtered_urls); } -// Returns the index of |url| in |urls|, or -1 if not found. -static int IndexOf(const MostVisitedURLList& urls, const GURL& url) { - for (size_t i = 0; i < urls.size(); i++) { - if (urls[i].url == url) - return i; - } - return -1; +static bool Contains(const MostVisitedURLList& urls, const GURL& url) { + return std::find_if(urls.begin(), urls.end(), + [&url](const MostVisitedURL& item) { + return item.url == url; + }) != urls.end(); } void TopSitesImpl::SyncWithHistory() { @@ -232,7 +230,7 @@ TopSitesImpl::~TopSitesImpl() = default; void TopSitesImpl::StartQueryForMostVisited() { - const int kDaysOfHistory = 90; + constexpr int kDaysOfHistory = 90; DCHECK(loaded_); timer_.Stop(); @@ -261,26 +259,19 @@ // When we find a match in the old set, we'll reset its index to our special // marker. This allows us to quickly identify the deleted ones in a later // pass. - const size_t kAlreadyFoundMarker = static_cast<size_t>(-1); + constexpr size_t kAlreadyFoundMarker = static_cast<size_t>(-1); int rank = -1; - for (size_t i = 0; i < new_list.size(); i++) { + for (const auto& new_url : new_list) { rank++; - auto found = all_old_urls.find(new_list[i].url); + auto found = all_old_urls.find(new_url.url); if (found == all_old_urls.end()) { - MostVisitedURLWithRank added; - added.url = new_list[i]; - added.rank = rank; - delta->added.push_back(added); + delta->added.emplace_back(MostVisitedURLWithRank{new_url, rank}); } else { DCHECK(found->second != kAlreadyFoundMarker) << "Same URL appears twice in the new list."; int old_rank = found->second; - if (old_rank != rank) { - MostVisitedURLWithRank moved; - moved.url = new_list[i]; - moved.rank = rank; - delta->moved.push_back(moved); - } + if (old_rank != rank) + delta->moved.emplace_back(MostVisitedURLWithRank{new_url, rank}); found->second = kAlreadyFoundMarker; } } @@ -296,8 +287,9 @@ bool TopSitesImpl::AddPrepopulatedPages(MostVisitedURLList* urls) const { bool added = false; for (const auto& prepopulated_page : prepopulated_pages_) { - if (urls->size() < kTopSitesNumber && - IndexOf(*urls, prepopulated_page.most_visited.url) == -1) { + if (urls->size() >= kTopSitesNumber) + break; + if (!Contains(*urls, prepopulated_page.most_visited.url)) { urls->push_back(prepopulated_page.most_visited); added = true; } @@ -305,8 +297,8 @@ return added; } -void TopSitesImpl::ApplyBlacklist(const MostVisitedURLList& urls, - MostVisitedURLList* out) { +MostVisitedURLList TopSitesImpl::ApplyBlacklist( + const MostVisitedURLList& urls) { // Log the number of times ApplyBlacklist is called so we can compute the // average number of blacklisted items per user. const base::DictionaryValue* blacklist = @@ -314,15 +306,15 @@ UMA_HISTOGRAM_BOOLEAN("TopSites.NumberOfApplyBlacklist", true); UMA_HISTOGRAM_COUNTS_100("TopSites.NumberOfBlacklistedItems", (blacklist ? blacklist->size() : 0)); - size_t num_urls = 0; - for (size_t i = 0; i < urls.size(); ++i) { - if (!IsBlacklisted(urls[i].url)) { - if (num_urls >= kTopSitesNumber) - break; - num_urls++; - out->push_back(urls[i]); - } + MostVisitedURLList result; + for (const auto& url : urls) { + if (IsBlacklisted(url.url)) + continue; + if (result.size() >= kTopSitesNumber) + break; + result.push_back(url); } + return result; } // static @@ -332,11 +324,10 @@ return base::MD5String(url.spec()); } -void TopSitesImpl::SetTopSites(const MostVisitedURLList& new_top_sites, +void TopSitesImpl::SetTopSites(MostVisitedURLList top_sites, const CallLocation location) { DCHECK(thread_checker_.CalledOnValidThread()); - MostVisitedURLList top_sites(new_top_sites); AddPrepopulatedPages(&top_sites); TopSitesDelta delta; @@ -373,7 +364,7 @@ // We always do the following steps (setting top sites in cache, and resetting // thread safe cache ...) as this method is invoked during startup at which // point the caches haven't been updated yet. - top_sites_ = top_sites; + top_sites_ = std::move(top_sites); ResetThreadSafeCache(); @@ -409,8 +400,8 @@ } } - for (size_t i = 0; i < pending_callbacks.size(); i++) - pending_callbacks[i].Run(urls); + for (auto& callback : pending_callbacks) + callback.Run(urls); if (history_service_) history_service_observer_.Add(history_service_); @@ -420,9 +411,7 @@ void TopSitesImpl::ResetThreadSafeCache() { base::AutoLock lock(lock_); - MostVisitedURLList filtered; - ApplyBlacklist(top_sites_, &filtered); - thread_safe_cache_ = filtered; + thread_safe_cache_ = ApplyBlacklist(top_sites_); } void TopSitesImpl::ScheduleUpdateTimer() { @@ -433,13 +422,12 @@ &TopSitesImpl::StartQueryForMostVisited); } -void TopSitesImpl::OnGotMostVisitedURLs( - const scoped_refptr<MostVisitedThreadSafe>& sites) { +void TopSitesImpl::OnGotMostVisitedURLs(MostVisitedURLList sites) { DCHECK(thread_checker_.CalledOnValidThread()); // Set |top_sites_| directly so that SetTopSites() diffs correctly. - top_sites_ = sites->data; - SetTopSites(sites->data, CALL_LOCATION_FROM_ON_GOT_MOST_VISITED_URLS); + top_sites_ = sites; + SetTopSites(std::move(sites), CALL_LOCATION_FROM_ON_GOT_MOST_VISITED_URLS); MoveStateToLoaded(); @@ -449,7 +437,7 @@ } void TopSitesImpl::OnTopSitesAvailableFromHistory(MostVisitedURLList pages) { - SetTopSites(pages, CALL_LOCATION_FROM_OTHER_PLACES); + SetTopSites(std::move(pages), CALL_LOCATION_FROM_OTHER_PLACES); } void TopSitesImpl::OnURLsDeleted(HistoryService* history_service,
diff --git a/components/history/core/browser/top_sites_impl.h b/components/history/core/browser/top_sites_impl.h index 1405246b..00da319d 100644 --- a/components/history/core/browser/top_sites_impl.h +++ b/components/history/core/browser/top_sites_impl.h
@@ -125,7 +125,7 @@ // Takes |urls|, produces it's copy in |out| after removing blacklisted URLs. // Also ensures we respect the maximum number TopSites URLs. - void ApplyBlacklist(const MostVisitedURLList& urls, MostVisitedURLList* out); + MostVisitedURLList ApplyBlacklist(const MostVisitedURLList& urls); // Returns an MD5 hash of the URL. Hashing is required for blacklisted URLs. static std::string GetURLHash(const GURL& url); @@ -133,7 +133,7 @@ // Updates URLs in |cache_| and the db (in the background). The URLs in // |new_top_sites| replace those in |cache_|. All mutations to cache_ *must* // go through this. Should be called from the UI thread. - void SetTopSites(const MostVisitedURLList& new_top_sites, + void SetTopSites(MostVisitedURLList new_top_sites, const CallLocation location); // Returns the number of most visited results to request from history. This @@ -153,7 +153,7 @@ // Callback from TopSites with the list of top sites. Should be called from // the UI thread. - void OnGotMostVisitedURLs(const scoped_refptr<MostVisitedThreadSafe>& sites); + void OnGotMostVisitedURLs(MostVisitedURLList sites); // Called when history service returns a list of top URLs. void OnTopSitesAvailableFromHistory(MostVisitedURLList data); @@ -188,7 +188,7 @@ // The pending requests for the top sites list. Can only be non-empty at // startup. After we read the top sites from the DB, we'll always have a // cached list and be able to run callbacks immediately. - PendingCallbacks pending_callbacks_; + PendingCallbacks pending_callbacks_ GUARDED_BY(lock_); // URL List of prepopulated page. const PrepopulatedPageList prepopulated_pages_;
diff --git a/components/history/core/browser/top_sites_impl_unittest.cc b/components/history/core/browser/top_sites_impl_unittest.cc index 66ab67a..ffd99d1 100644 --- a/components/history/core/browser/top_sites_impl_unittest.cc +++ b/components/history/core/browser/top_sites_impl_unittest.cc
@@ -203,7 +203,7 @@ // Wrappers that allow private TopSites functions to be called from the // individual tests without making them all be friends. void SetTopSites(const MostVisitedURLList& new_top_sites) { - top_sites()->SetTopSites(new_top_sites, + top_sites()->SetTopSites(MostVisitedURLList(new_top_sites), TopSitesImpl::CALL_LOCATION_FROM_OTHER_PLACES); }
diff --git a/components/omnibox/browser/document_provider.cc b/components/omnibox/browser/document_provider.cc index fe60814..1fe631d 100644 --- a/components/omnibox/browser/document_provider.cc +++ b/components/omnibox/browser/document_provider.cc
@@ -695,9 +695,6 @@ // Ensure server's suggestions are added with monotonically decreasing scores. int previous_score = INT_MAX; for (size_t i = 0; i < num_results; i++) { - if (matches.size() >= provider_max_matches_) { - break; - } const base::DictionaryValue* result = nullptr; if (!results_list->GetDictionary(i, &result)) { return matches; @@ -716,26 +713,32 @@ int server_score = 0; result->GetInteger("score", &server_score); int score = 0; - if (use_client_score && use_server_score) - score = std::min(client_score, server_score); - else - score = use_client_score ? client_score : server_score; + // Set |score| only if we haven't surpassed |provider_max_matches_| yet. + // Otherwise, score the remaining matches 0 to avoid displaying them except + // when deduped with history, shortcut, or bookmark matches. + if (matches.size() < provider_max_matches_) { + if (use_client_score && use_server_score) + score = std::min(client_score, server_score); + else + score = use_client_score ? client_score : server_score; - if (cap_score_per_rank) { - int score_cap = i < score_caps.size() ? score_caps[i] : score_caps.back(); - score = std::min(score, score_cap); + if (cap_score_per_rank) { + int score_cap = + i < score_caps.size() ? score_caps[i] : score_caps.back(); + score = std::min(score, score_cap); + } + + if (boost_owned) + score = BoostOwned(score, client_->ProfileUserName(), result); + + // Decrement scores if necessary to ensure suggestion order is preserved. + // Don't decrement client scores which don't necessarily rank suggestions + // the same as the server. + if (!use_client_score && score >= previous_score) + score = std::max(previous_score - 1, 0); + previous_score = score; } - if (boost_owned) - score = BoostOwned(score, client_->ProfileUserName(), result); - - // Decrement scores if necessary to ensure suggestion order is preserved. - // Don't decrement client scores which don't necessarily rank suggestions - // the same as the server. - if (!use_client_score && score >= previous_score) - score = std::max(previous_score - 1, 0); - previous_score = score; - AutocompleteMatch match(this, score, false, AutocompleteMatchType::DOCUMENT_SUGGESTION); // Use full URL for displayed text and navigation. Use "originalUrl" for @@ -776,6 +779,8 @@ match.transition = ui::PAGE_TRANSITION_GENERATED; match.RecordAdditionalInfo("client score", client_score); match.RecordAdditionalInfo("server score", server_score); + if (matches.size() >= provider_max_matches_) + match.RecordAdditionalInfo("for deduping only", "true"); const std::string* snippet = result->FindStringPath("snippet.snippet"); if (snippet) match.RecordAdditionalInfo("snippet", *snippet);
diff --git a/components/omnibox/browser/omnibox_field_trial.cc b/components/omnibox/browser/omnibox_field_trial.cc index 547b5a2..c324294 100644 --- a/components/omnibox/browser/omnibox_field_trial.cc +++ b/components/omnibox/browser/omnibox_field_trial.cc
@@ -226,35 +226,27 @@ // static std::vector<std::string> OmniboxFieldTrial::GetZeroSuggestVariants( OmniboxEventProto::PageClassification page_classification) { - std::function<std::vector<std::string>(const std::string&)> split = - [](const std::string& value) { - return base::SplitString(value, ",", base::TRIM_WHITESPACE, - base::SPLIT_WANT_ALL); - }; - - // Note: These checks are necessary because it is not possible to enable - // multiple features using Finch Forcing groups (omnibox::kOnFocusSuggestions - // as well as another feature). Therefore, in order to specify the - // ZeroSuggestVariant parameter in those groups we allow it to be associated - // with the feature that is being force enabled. - if (base::FeatureList::IsEnabled(omnibox::kZeroSuggestionsOnNTP)) { - auto result = internal::GetValueForRuleInContextByFeature( - omnibox::kZeroSuggestionsOnNTP, kZeroSuggestVariantRule, - page_classification); - if (!result.empty()) - return split(result); - } - if (base::FeatureList::IsEnabled(omnibox::kZeroSuggestionsOnNTPRealbox)) { - auto result = internal::GetValueForRuleInContextByFeature( - omnibox::kZeroSuggestionsOnNTPRealbox, kZeroSuggestVariantRule, - page_classification); - if (!result.empty()) - return split(result); + // We check all these features for ZeroSuggestVariant because it's not + // possible to enable multiple features using Finch Forcing groups + // (omnibox::kOnFocusSuggestions as well as another feature). Therefore, in + // order to specify the ZeroSuggestVariant parameter in those groups we allow + // it to be associated with the feature that is being force enabled. + const base::Feature* features_to_check[] = { + &omnibox::kZeroSuggestionsOnNTP, + &omnibox::kZeroSuggestionsOnNTPRealbox, + &omnibox::kZeroSuggestionsOnSERP, + &omnibox::kOnFocusSuggestions, + }; + for (const base::Feature* feature : features_to_check) { + auto parameter_value = internal::GetValueForRuleInContextByFeature( + *feature, kZeroSuggestVariantRule, page_classification); + if (!parameter_value.empty()) { + return base::SplitString(parameter_value, ",", base::TRIM_WHITESPACE, + base::SPLIT_WANT_NONEMPTY); + } } - return split(internal::GetValueForRuleInContextByFeature( - omnibox::kOnFocusSuggestions, kZeroSuggestVariantRule, - page_classification)); + return {}; } bool OmniboxFieldTrial::ShortcutsScoringMaxRelevance(
diff --git a/components/omnibox/browser/url_index_private_data.cc b/components/omnibox/browser/url_index_private_data.cc index 7d6f58f8..43ff57c 100644 --- a/components/omnibox/browser/url_index_private_data.cc +++ b/components/omnibox/browser/url_index_private_data.cc
@@ -291,7 +291,7 @@ row_to_update.set_title(row.title()); RowWordStarts word_starts; AddRowWordsToIndex(row_to_update, &word_starts); - word_starts_map_[row_id] = word_starts; + word_starts_map_[row_id] = std::move(word_starts); } row_was_updated = true; } @@ -801,12 +801,13 @@ new_row.set_typed_count(row.typed_count()); new_row.set_last_visit(row.last_visit()); new_row.set_title(row.title()); - history_info_map_[history_id].url_row = new_row; // Index the words contained in the URL and title of the row. RowWordStarts word_starts; AddRowWordsToIndex(new_row, &word_starts); - word_starts_map_[history_id] = word_starts; + word_starts_map_[history_id] = std::move(word_starts); + + history_info_map_[history_id].url_row = std::move(new_row); // Update the recent visits information or schedule the update // as appropriate.
diff --git a/components/omnibox/common/omnibox_features.cc b/components/omnibox/common/omnibox_features.cc index 6c3ff55..696ccbd 100644 --- a/components/omnibox/common/omnibox_features.cc +++ b/components/omnibox/common/omnibox_features.cc
@@ -297,6 +297,10 @@ const base::Feature kZeroSuggestionsOnNTPRealbox{ "OmniboxZeroSuggestionsOnNTPRealbox", base::FEATURE_DISABLED_BY_DEFAULT}; +// Allow on-focus query refinements to be shown on the default SERP. +const base::Feature kZeroSuggestionsOnSERP{"OmniboxZeroSuggestionsOnSERP", + base::FEATURE_ENABLED_BY_DEFAULT}; + // Feature to provide non personalized head search suggestion from a compact // on device model. const base::Feature kOnDeviceHeadProvider{"OmniboxOnDeviceHeadProvider",
diff --git a/components/omnibox/common/omnibox_features.h b/components/omnibox/common/omnibox_features.h index 9d84320..4910578 100644 --- a/components/omnibox/common/omnibox_features.h +++ b/components/omnibox/common/omnibox_features.h
@@ -56,6 +56,7 @@ extern const base::Feature kOnFocusSuggestions; extern const base::Feature kZeroSuggestionsOnNTP; extern const base::Feature kZeroSuggestionsOnNTPRealbox; +extern const base::Feature kZeroSuggestionsOnSERP; } // namespace omnibox
diff --git a/components/optimization_guide/proto/BUILD.gn b/components/optimization_guide/proto/BUILD.gn index 5340080..7e2c19f 100644 --- a/components/optimization_guide/proto/BUILD.gn +++ b/components/optimization_guide/proto/BUILD.gn
@@ -9,6 +9,7 @@ "common_types.proto", "hint_cache.proto", "hints.proto", + "models.proto", "previews_metadata.proto", ] }
diff --git a/components/optimization_guide/proto/common_types.proto b/components/optimization_guide/proto/common_types.proto index 0f83460..5eb7516 100644 --- a/components/optimization_guide/proto/common_types.proto +++ b/components/optimization_guide/proto/common_types.proto
@@ -36,3 +36,14 @@ // 4G connection. EFFECTIVE_CONNECTION_TYPE_4G = 5; } + +// Context in which the items are requested. +enum RequestContext { + reserved 1; + // Context not specified. + CONTEXT_UNSPECIFIED = 0; + // Requesting items on page navigation. + CONTEXT_PAGE_NAVIGATION = 2; + // Requesting items as part of a batch update. + CONTEXT_BATCH_UPDATE = 3; +}
diff --git a/components/optimization_guide/proto/hints.proto b/components/optimization_guide/proto/hints.proto index 8175f42..01f0d8c 100644 --- a/components/optimization_guide/proto/hints.proto +++ b/components/optimization_guide/proto/hints.proto
@@ -96,16 +96,6 @@ optional int32 nanos = 2; } -// Context in which the hints are requested. -enum RequestContext { - reserved 1; - // Context not specified. - CONTEXT_UNSPECIFIED = 0; - // Requesting hints on page navigation. - CONTEXT_PAGE_NAVIGATION = 2; - // Requesting hints as part of a batch update. - CONTEXT_BATCH_UPDATE = 3; -} enum OptimizationType { TYPE_UNSPECIFIED = 0;
diff --git a/components/optimization_guide/proto/models.proto b/components/optimization_guide/proto/models.proto new file mode 100644 index 0000000..5588fb5 --- /dev/null +++ b/components/optimization_guide/proto/models.proto
@@ -0,0 +1,246 @@ +// 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. + +syntax = "proto2"; +option optimize_for = LITE_RUNTIME; + +package optimization_guide.proto; + +import "common_types.proto"; + +// A generic handle for any type of model. +message Model { + reserved 3; + + oneof model { + DecisionTree decision_tree = 1; + Ensemble ensemble = 2; + } +} + +// An ensemble prediction model consisting of an ordered sequence of models. +// This message can be used to express bagged or boosted models. +message Ensemble { + reserved 2, 3, 4; + + message Member { optional Model submodel = 1; } + repeated Member members = 100; +} + +// A decision tree model with its weight for use if included in an ensemble. +message DecisionTree { + reserved 2; + + repeated TreeNode nodes = 1; + optional float weight = 3; +} + +// A node of a decision tree that is a binary deicison or a leaf. +message TreeNode { + reserved 6, 7; + + // Following fields are provided for convenience and better readability. + // Filling them in is not required. + optional Int32Value node_id = 1; + optional Int32Value depth = 2; + optional Int32Value subtree_size = 3; + + oneof node_type { + BinaryNode binary_node = 4; + Leaf leaf = 5; + } +} + +// A tree node that contains an inequality test that during evaluation +// determines whether to continue the left or right child. +message BinaryNode { + reserved 3, 5; + + optional Int32Value left_child_id = 1; + optional Int32Value right_child_id = 2; + enum Direction { + LEFT = 0; + RIGHT = 1; + } + // When a datapoint satisfies the test, it should be propagated to the left + // child. + optional InequalityTest inequality_left_child_test = 4; +} + +// Vector of values for use within Models. +message Vector { + repeated Value value = 1; +} + +// A leaf node of a decision tree. +message Leaf { + reserved 2, 3; + + optional Vector vector = 1; +} + +// The ID for the features used during evaluation of a Model. +message FeatureId { + reserved 2; + + optional StringValue id = 1; +} + +// The set of inequality operations supported by binary nodes for +// decision tree models. +message InequalityTest { + reserved 4; + + // When the feature is missing, the test's outcome is undefined. + optional FeatureId feature_id = 1; + enum Type { + LESS_OR_EQUAL = 0; + LESS_THAN = 1; + GREATER_OR_EQUAL = 2; + GREATER_THAN = 3; + }; + optional Type type = 2; + optional Value threshold = 3; +} + +// Represents a single value of any type, e.g. 5 or "abc". +message Value { + reserved 5; + + oneof value { + float float_value = 1; + double double_value = 2; + int32 int32_value = 3; + int64 int64_value = 4; + } +} + +// Wrapper message for `int32`. +// +// The JSON representation for `Int32Value` is JSON number. +message Int32Value { + // The int32 value. + optional int32 value = 1; +} + +// Wrapper message for `string`. +// +// The JSON representation for `StringValue` is JSON string. +message StringValue { + // The string value. + optional string value = 1; +} + +// Requests prediction models to be used for a set of optimization targets. +message GetModelsRequest { + // Information about the requested models. + repeated ModelInfo requested_models = 1; + // The set of hosts to get additional metadata for, if applicable. + repeated string hosts = 2; + // Context in which this request is made. + // + // If the context matches one that requires more urgency (i.e. + // CONTEXT_PAGE_NAVIGATION), then no model updates will be returned for the + // requested models. + optional RequestContext request_context = 3; +} + +// Response to the GetModels request. +message GetModelsResponse { + // The models to be used during prediction for the requested optimization + // targets. + repeated PredictionModel models = 1; + // A set of model features and their values for the hosts contained in the + // request to be expected to be consulted with during prediction. + // + // It is not guaranteed that this set will contain an entry for every + // requested host. + repeated HostModelFeatures host_model_features = 2; +} + +// Holds the prediction model for a particular optimization target. +message PredictionModel { + // Information about the model. + optional ModelInfo model_info = 1; + // The model to evaluate for the attached model information. + // + // This will only be set if the model that the client claims it has is stale. + // It is also guaranteed that the value populated as part of this field is one + // that the client claims to support based on the request's client model + // capabilities. + optional Model model = 2; +} + +// Metadata for a prediction model for a specific optimization target. +message ModelInfo { + // The optimization target for which the model predicts. + optional OptimizationTarget optimization_target = 1; + // The version of the model, which is specific to the optimization target. + optional int64 version = 2; + // The set of model features that are supported by the model. + // + // If in the request, this represents the set of features that the client + // understands how to evaluate. If in the response, this represents the set + // of features referenced by the model. + repeated ClientModelFeature supported_model_features = 3; + // The set of model types the requesting client can use to make predictions. + repeated ModelType supported_model_types = 4; +} + +// The scenarios for which the optimization guide has models for. +enum OptimizationTarget { + OPTIMIZATION_TARGET_UNKNOWN = 0; + // Should only be applied when the page load is predicted to be painful. + OPTIMIZATION_TARGET_PAINFUL_PAGE_LOAD = 1; +} + +// The features that only the client can compute during prediction and also +// knows how to evaluate. +enum ClientModelFeature { + CLIENT_MODEL_FEATURE_UNKNOWN = 0; + // The effective connection type for the page load. + CLIENT_MODEL_FEATURE_EFFECTIVE_CONNECTION_TYPE = 1; + // How the current page load transitioned from the previous one. + CLIENT_MODEL_FEATURE_PAGE_TRANSITION = 2; + // The site engagement score of the main frame host for the page load. + CLIENT_MODEL_FEATURE_SITE_ENGAGEMENT_SCORE = 3; + // Whether the origin for the page load matches the origin of the previous + // page load. + CLIENT_MODEL_FEATURE_SAME_ORIGIN_NAVIGATION = 4; + // The mean of the duration from navigation to first contentful paint for the + // session. + CLIENT_MODEL_FEATURE_FIRST_CONTENTFUL_PAINT_SESSION_MEAN = 5; + // The standard deviation of the duration from navigation to first + // contentful paint for the session. + CLIENT_MODEL_FEATURE_FIRST_CONTENTFUL_PAINT_SESSION_STANDARD_DEVIATION = 6; + // The duration from navigation to first contentful paint for the previous + // page load, if applicable. + CLIENT_MODEL_FEATURE_FIRST_CONTENTFUL_PAINT_PREVIOUS_PAGE_LOAD = 7; +} + +// The types of models that can be evaluated. +enum ModelType { + MODEL_TYPE_UNKNOWN = 0; + // A decision tree. + MODEL_TYPE_DECISION_TREE = 1; +} + +// A set of model features and the host that it applies to. +message HostModelFeatures { + // The host that the features should be applied for. + optional string host = 1; + // The set of features and their values that apply to the host. + repeated ModelFeature model_features = 2; +} + +// Information about a feature that is potentially referenced in a model. +message ModelFeature { + // The name of the feature to match if encountered in a model. + optional string feature_name = 1; + // The value of the feature to be used during prediction. + oneof feature_value { + double double_value = 2; + int64 int64_value = 3; + } +}
diff --git a/components/password_manager/core/browser/BUILD.gn b/components/password_manager/core/browser/BUILD.gn index 74ad069..aeddc8ac 100644 --- a/components/password_manager/core/browser/BUILD.gn +++ b/components/password_manager/core/browser/BUILD.gn
@@ -10,8 +10,9 @@ import("//build/config/android/config.gni") } -# TODO(crbug.com/706392): Fix password reuse detection for Android. -password_reuse_detection_support = !is_android && !is_ios +# TODO(crbug.com/1006430): Fix password reuse detection not fully functional on +# Android. +password_reuse_detection_support = !is_ios password_reuse_warning_support = !is_android && !is_ios password_on_focus_ping_support = !is_ios
diff --git a/components/password_manager/core/browser/mock_password_store.h b/components/password_manager/core/browser/mock_password_store.h index e7d690cc..d4d65844 100644 --- a/components/password_manager/core/browser/mock_password_store.h +++ b/components/password_manager/core/browser/mock_password_store.h
@@ -72,7 +72,7 @@ MOCK_METHOD1(AddSiteStatsImpl, void(const InteractionsStats&)); MOCK_METHOD1(RemoveSiteStatsImpl, void(const GURL&)); MOCK_CONST_METHOD0(IsAbleToSavePasswords, bool()); -// TODO(crbug.com/706392): Fix password reuse detection for Android. + #if defined(SYNC_PASSWORD_REUSE_DETECTION_ENABLED) MOCK_METHOD3(CheckReuse, void(const base::string16&,
diff --git a/components/password_manager/core/browser/password_store.cc b/components/password_manager/core/browser/password_store.cc index 9fcaeb8a..2ebfa80 100644 --- a/components/password_manager/core/browser/password_store.cc +++ b/components/password_manager/core/browser/password_store.cc
@@ -65,7 +65,6 @@ } // namespace -// TODO(crbug.com/706392): Fix password reuse detection for Android. #if defined(SYNC_PASSWORD_REUSE_DETECTION_ENABLED) PasswordStore::CheckReuseRequest::CheckReuseRequest( PasswordReuseDetectorConsumer* consumer) @@ -397,7 +396,6 @@ base::Unretained(this))); } -// TODO(crbug.com/706392): Fix password reuse detection for Android. #if defined(SYNC_PASSWORD_REUSE_DETECTION_ENABLED) void PasswordStore::CheckReuse(const base::string16& input, const std::string& domain, @@ -537,7 +535,7 @@ syncable_service_.reset(new PasswordSyncableService(this)); syncable_service_->InjectStartSyncFlare(flare); } -// TODO(crbug.com/706392): Fix password reuse detection for Android. + #if defined(SYNC_PASSWORD_REUSE_DETECTION_ENABLED) reuse_detector_ = new PasswordReuseDetector; @@ -593,7 +591,7 @@ syncable_service_->ActOnPasswordStoreChanges(changes); if (sync_bridge_) sync_bridge_->ActOnPasswordStoreChanges(changes); -// TODO(crbug.com/706392): Fix password reuse detection for Android. + #if defined(SYNC_PASSWORD_REUSE_DETECTION_ENABLED) if (reuse_detector_) reuse_detector_->OnLoginsChanged(changes); @@ -601,7 +599,6 @@ } } -// TODO(crbug.com/706392): Fix password reuse detection for Android. #if defined(SYNC_PASSWORD_REUSE_DETECTION_ENABLED) void PasswordStore::CheckReuseImpl(std::unique_ptr<CheckReuseRequest> request, const base::string16& input, @@ -1060,7 +1057,7 @@ DCHECK(background_task_runner_->RunsTasksInCurrentSequence()); syncable_service_.reset(); sync_bridge_.reset(); -// TODO(crbug.com/706392): Fix password reuse detection for Android. + #if defined(SYNC_PASSWORD_REUSE_DETECTION_ENABLED) delete reuse_detector_; reuse_detector_ = nullptr;
diff --git a/components/password_manager/core/browser/password_store.h b/components/password_manager/core/browser/password_store.h index 4925923..b5e4014 100644 --- a/components/password_manager/core/browser/password_store.h +++ b/components/password_manager/core/browser/password_store.h
@@ -23,7 +23,6 @@ #include "components/password_manager/core/browser/password_store_sync.h" #include "components/sync/model/syncable_service.h" -// TODO(crbug.com/706392): Fix password reuse detection for Android. #if defined(SYNC_PASSWORD_REUSE_DETECTION_ENABLED) #include "components/password_manager/core/browser/hash_password_manager.h" #include "components/password_manager/core/browser/password_manager_metrics_util.h" @@ -264,7 +263,6 @@ std::unique_ptr<syncer::ProxyModelTypeControllerDelegate> CreateSyncControllerDelegate(); -// TODO(crbug.com/706392): Fix password reuse detection for Android. #if defined(SYNC_PASSWORD_REUSE_DETECTION_ENABLED) // Immediately called after |Init()| to retrieve password hash data for // reuse detection. @@ -330,7 +328,6 @@ protected: friend class base::RefCountedThreadSafe<PasswordStore>; -// TODO(crbug.com/706392): Fix password reuse detection for Android. #if defined(SYNC_PASSWORD_REUSE_DETECTION_ENABLED) // Represents a single CheckReuse() request. Implements functionality to // listen to reuse events and propagate them to |consumer| on the sequence on @@ -453,7 +450,6 @@ // been changed. void NotifyLoginsChanged(const PasswordStoreChangeList& changes) override; -// TODO(crbug.com/706392): Fix password reuse detection for Android. #if defined(SYNC_PASSWORD_REUSE_DETECTION_ENABLED) // Saves |username| and a hash of |password| for password reuse checking. // |is_gaia_password| indicates if it is a Gaia account. |event| is used for @@ -675,7 +671,7 @@ std::unique_ptr<PasswordSyncBridge> sync_bridge_; std::unique_ptr<AffiliatedMatchHelper> affiliated_match_helper_; -// TODO(crbug.com/706392): Fix password reuse detection for Android. + #if defined(SYNC_PASSWORD_REUSE_DETECTION_ENABLED) PrefService* prefs_ = nullptr; // PasswordReuseDetector can be only destroyed on the background sequence. It
diff --git a/components/policy/core/common/cloud/cloud_policy_manager.h b/components/policy/core/common/cloud/cloud_policy_manager.h index 285ff64..9626b1b8 100644 --- a/components/policy/core/common/cloud/cloud_policy_manager.h +++ b/components/policy/core/common/cloud/cloud_policy_manager.h
@@ -108,8 +108,6 @@ // policy update notifications are deferred until after it completes. bool waiting_for_policy_refresh_; - scoped_refptr<base::SequencedTaskRunner> io_task_runner_; - DISALLOW_COPY_AND_ASSIGN(CloudPolicyManager); };
diff --git a/components/previews/core/previews_features.cc b/components/previews/core/previews_features.cc index 2578c64..d839a4e 100644 --- a/components/previews/core/previews_features.cc +++ b/components/previews/core/previews_features.cc
@@ -58,11 +58,6 @@ const base::Feature kSlowPageTriggering{"PreviewsSlowPageTriggering", base::FEATURE_DISABLED_BY_DEFAULT}; -// Allows HTTPS previews to be served via a URLLoader when network service is -// enabled. -const base::Feature kHTTPSServerPreviewsUsingURLLoader{ - "HTTPSServerPreviewsUsingURLLoader", base::FEATURE_DISABLED_BY_DEFAULT}; - // Enables the use of a pref to only trigger Offline Previews when there is a // high chance that there is one to serve. const base::Feature kOfflinePreviewsFalsePositivePrevention{
diff --git a/components/previews/core/previews_features.h b/components/previews/core/previews_features.h index c9ca1e7a0..44de706 100644 --- a/components/previews/core/previews_features.h +++ b/components/previews/core/previews_features.h
@@ -17,7 +17,6 @@ extern const base::Feature kResourceLoadingHints; extern const base::Feature kLitePageServerPreviews; extern const base::Feature kSlowPageTriggering; -extern const base::Feature kHTTPSServerPreviewsUsingURLLoader; extern const base::Feature kOfflinePreviewsFalsePositivePrevention; extern const base::Feature kCoinFlipHoldback; extern const base::Feature kExcludedMediaSuffixes;
diff --git a/components/safe_browsing/browser/threat_details.cc b/components/safe_browsing/browser/threat_details.cc index 05bcd3f..5149e91 100644 --- a/components/safe_browsing/browser/threat_details.cc +++ b/components/safe_browsing/browser/threat_details.cc
@@ -8,7 +8,6 @@ #include <stddef.h> #include <stdint.h> -#include <string_view> #include <unordered_set> #include <utility> #include <vector> @@ -18,6 +17,7 @@ #include "base/lazy_instance.h" #include "base/metrics/histogram_macros.h" #include "base/stl_util.h" +#include "base/strings/string_piece.h" #include "base/strings/string_util.h" #include "base/task/post_task.h" #include "components/history/core/browser/history_service.h" @@ -312,7 +312,7 @@ } void DisableBackForwardCache(content::RenderFrameHost* rfh, - std::string_view reason) { + base::StringPiece reason) { content::WebContents::FromRenderFrameHost(rfh) ->GetController() .GetBackForwardCache()
diff --git a/components/safe_browsing/features.cc b/components/safe_browsing/features.cc index 7ffc867d..5311a11 100644 --- a/components/safe_browsing/features.cc +++ b/components/safe_browsing/features.cc
@@ -65,6 +65,16 @@ }; #endif +const base::Feature kSendPasswordReusePing { + "SafeBrowsingSendPasswordReusePing", +#if BUILDFLAG(FULL_SAFE_BROWSING) + base::FEATURE_ENABLED_BY_DEFAULT +}; +#else + base::FEATURE_DISABLED_BY_DEFAULT +}; +#endif + const base::Feature kSendSampledPingsForAllowlistDomains{ "SafeBrowsingSendSampledPingsForAllowlistDomain", base::FEATURE_DISABLED_BY_DEFAULT}; @@ -108,6 +118,7 @@ {&kRealTimeUrlLookupEnabled, true}, {&kRealTimeUrlLookupFetchAllowlist, true}, {&kSendOnFocusPing, true}, + {&kSendPasswordReusePing, true}, {&kSendSampledPingsForAllowlistDomains, false}, {&kSuspiciousSiteTriggerQuotaFeature, true}, {&kThreatDomDetailsTagAndAttributeFeature, false},
diff --git a/components/safe_browsing/features.h b/components/safe_browsing/features.h index 98cef139..7ce0b455 100644 --- a/components/safe_browsing/features.h +++ b/components/safe_browsing/features.h
@@ -57,6 +57,9 @@ // Controls whether Chrome sends on focus ping. extern const base::Feature kSendOnFocusPing; +// Controls whether Chrome sends password reuse ping. +extern const base::Feature kSendPasswordReusePing; + // Controls the daily quota for the suspicious site trigger. extern const base::Feature kSuspiciousSiteTriggerQuotaFeature;
diff --git a/components/safe_browsing/password_protection/password_protection_service.cc b/components/safe_browsing/password_protection/password_protection_service.cc index b870186..3a54056 100644 --- a/components/safe_browsing/password_protection/password_protection_service.cc +++ b/components/safe_browsing/password_protection/password_protection_service.cc
@@ -117,6 +117,9 @@ const std::vector<std::string>& matching_domains, bool password_field_exists) { DCHECK_CURRENTLY_ON(BrowserThread::UI); + if (!base::FeatureList::IsEnabled(safe_browsing::kSendPasswordReusePing)) { + return; + } ReusedPasswordAccountType reused_password_account_type = GetPasswordProtectionReusedPasswordAccountType(password_type, username); RequestOutcome reason;
diff --git a/components/sessions/content/content_serialized_navigation_builder.cc b/components/sessions/content/content_serialized_navigation_builder.cc index 4bd035d..1903311 100644 --- a/components/sessions/content/content_serialized_navigation_builder.cc +++ b/components/sessions/content/content_serialized_navigation_builder.cc
@@ -4,6 +4,8 @@ #include "components/sessions/content/content_serialized_navigation_builder.h" +#include <string> + #include "base/logging.h" #include "components/sessions/content/content_record_password_state.h" #include "components/sessions/content/content_serialized_navigation_driver.h" @@ -88,19 +90,18 @@ ContentSerializedNavigationBuilder::ToNavigationEntry( const SerializedNavigationEntry* navigation, content::BrowserContext* browser_context) { - // TODO(lukasza): https://crbug.com/976055: |initiator_origin| should be - // persisted across session restore. - base::Optional<url::Origin> initiator_origin = base::nullopt; + // The initial values of the NavigationEntry are only temporary - they + // will get cloberred by one of the SetPageState calls below. + // + // This means that things like |navigation->referrer_url| are ignored + // in favor of using the data stored in |navigation->encoded_page_state|. + GURL temporary_url; + content::Referrer temporary_referrer; + base::Optional<url::Origin> temporary_initiator_origin; - network::mojom::ReferrerPolicy policy = - static_cast<network::mojom::ReferrerPolicy>(navigation->referrer_policy_); std::unique_ptr<content::NavigationEntry> entry( content::NavigationController::CreateNavigationEntry( - navigation->virtual_url_, - content::Referrer::SanitizeForRequest( - navigation->virtual_url_, - content::Referrer(navigation->referrer_url_, policy)), - initiator_origin, + temporary_url, temporary_referrer, temporary_initiator_origin, // Use a transition type of reload so that we don't incorrectly // increase the typed count. ui::PAGE_TRANSITION_RELOAD, false, @@ -108,9 +109,46 @@ std::string(), browser_context, nullptr /* blob_url_loader_factory */)); + // In some cases the |encoded_page_state| might be empty - we + // need to gracefully handle such data when it is deserialized. + // + // One case is tests for "foreign" session restore entries, such as + // SessionRestoreTest.RestoreForeignTab. We hypothesise that old session + // restore entries might also contain an empty |encoded_page_state|. + if (navigation->encoded_page_state_.empty()) { + // Ensure that the deserialized/restored content::NavigationEntry (and + // the content::FrameNavigationEntry underneath) has a valid PageState. + entry->SetPageState( + content::PageState::CreateFromURL(navigation->virtual_url_)); + + // The |navigation|-based referrer set below might be inconsistent with the + // referrer embedded inside the PageState set above. Nevertheless, to + // minimize changes to behavior of old session restore entries, we restore + // the deserialized referrer here. + // + // TODO(lukasza): Consider including the |deserialized_referrer| in the + // PageState set above + drop the SetReferrer call below. This will + // slightly change the legacy behavior, but will make PageState and + // Referrer consistent. + content::Referrer referrer(navigation->referrer_url(), + static_cast<network::mojom::ReferrerPolicy>( + navigation->referrer_policy())); + entry->SetReferrer(referrer); + } else { + // Note that PageState covers some of the values inside |navigation| (e.g. + // URL, Referrer). Calling SetPageState will clobber these values in + // content::NavigationEntry (and FrameNavigationEntry(s) below). + entry->SetPageState(content::PageState::CreateFromEncodedData( + navigation->encoded_page_state_)); + + // |navigation|-level referrer information is redundant wrt PageState, but + // they should be consistent / in-sync. + DCHECK_EQ(navigation->referrer_url(), entry->GetReferrer().url); + DCHECK_EQ(navigation->referrer_policy(), + static_cast<int>(entry->GetReferrer().policy)); + } + entry->SetTitle(navigation->title_); - entry->SetPageState(content::PageState::CreateFromEncodedData( - navigation->encoded_page_state_)); entry->SetHasPostData(navigation->has_post_data_); entry->SetPostID(navigation->post_id_); entry->SetOriginalRequestURL(navigation->original_request_url_); @@ -118,6 +156,7 @@ entry->SetTimestamp(navigation->timestamp_); entry->SetHttpStatusCode(navigation->http_status_code_); entry->SetRedirectChain(navigation->redirect_chain_); + entry->SetVirtualURL(navigation->virtual_url_); sessions::NavigationTaskId* navigation_task_id = sessions::NavigationTaskId::Get(entry.get()); navigation_task_id->set_id(navigation->task_id());
diff --git a/components/sessions/content/content_serialized_navigation_builder_unittest.cc b/components/sessions/content/content_serialized_navigation_builder_unittest.cc index d7832d1..d293f061 100644 --- a/components/sessions/content/content_serialized_navigation_builder_unittest.cc +++ b/components/sessions/content/content_serialized_navigation_builder_unittest.cc
@@ -4,6 +4,10 @@ #include "components/sessions/content/content_serialized_navigation_builder.h" +#include <memory> +#include <string> +#include <vector> + #include "base/memory/ptr_util.h" #include "base/strings/utf_string_conversions.h" #include "components/sessions/content/content_record_password_state.h" @@ -64,10 +68,9 @@ navigation_entry->SetReferrer(content::Referrer( test_data::kReferrerURL, static_cast<network::mojom::ReferrerPolicy>(test_data::kReferrerPolicy))); + navigation_entry->SetURL(test_data::kURL); navigation_entry->SetVirtualURL(test_data::kVirtualURL); navigation_entry->SetTitle(test_data::kTitle); - navigation_entry->SetPageState( - content::PageState::CreateFromEncodedData(test_data::kEncodedPageState)); navigation_entry->SetTransitionType(test_data::kTransitionType); navigation_entry->SetHasPostData(test_data::kHasPostData); navigation_entry->SetPostID(test_data::kPostID); @@ -147,7 +150,8 @@ EXPECT_EQ(test_data::kReferrerPolicy, navigation.referrer_policy()); EXPECT_EQ(test_data::kVirtualURL, navigation.virtual_url()); EXPECT_EQ(test_data::kTitle, navigation.title()); - EXPECT_EQ(test_data::kEncodedPageState, navigation.encoded_page_state()); + EXPECT_EQ(navigation_entry->GetPageState().ToEncodedData(), + navigation.encoded_page_state()); EXPECT_TRUE(ui::PageTransitionTypeIncludingQualifiersIs( navigation.transition_type(), test_data::kTransitionType)); EXPECT_EQ(test_data::kHasPostData, navigation.has_post_data()); @@ -188,7 +192,7 @@ ContentSerializedNavigationBuilder::FromNavigationEntry( test_data::kIndex, navigation_entry.get(), ContentSerializedNavigationBuilder::DEFAULT); - EXPECT_EQ(test_data::kEncodedPageState, + EXPECT_EQ(navigation_entry->GetPageState().ToEncodedData(), default_navigation.encoded_page_state()); const SerializedNavigationEntry& excluded_page_state_navigation = @@ -218,9 +222,10 @@ EXPECT_EQ(test_data::kReferrerURL, new_navigation_entry->GetReferrer().url); EXPECT_EQ(test_data::kReferrerPolicy, static_cast<int>(new_navigation_entry->GetReferrer().policy)); + EXPECT_EQ(test_data::kURL, new_navigation_entry->GetURL()); EXPECT_EQ(test_data::kVirtualURL, new_navigation_entry->GetVirtualURL()); EXPECT_EQ(test_data::kTitle, new_navigation_entry->GetTitle()); - EXPECT_EQ(test_data::kEncodedPageState, + EXPECT_EQ(old_navigation_entry->GetPageState().ToEncodedData(), new_navigation_entry->GetPageState().ToEncodedData()); EXPECT_TRUE(ui::PageTransitionTypeIncludingQualifiersIs( new_navigation_entry->GetTransitionType(), ui::PAGE_TRANSITION_RELOAD));
diff --git a/components/sessions/core/serialized_navigation_entry_test_helper.cc b/components/sessions/core/serialized_navigation_entry_test_helper.cc index f5f08bc..8bb74fde 100644 --- a/components/sessions/core/serialized_navigation_entry_test_helper.cc +++ b/components/sessions/core/serialized_navigation_entry_test_helper.cc
@@ -18,7 +18,8 @@ const int kUniqueID = 50; const GURL kReferrerURL = GURL("http://www.referrer.com"); const int kReferrerPolicy = 0; -const GURL kVirtualURL= GURL("http://www.virtual-url.com"); +const GURL kURL = GURL("http://www.url.com"); +const GURL kVirtualURL = GURL("http://www.virtual-url.com"); const base::string16 kTitle = base::ASCIIToUTF16("title"); const std::string kEncodedPageState = "page state"; const ui::PageTransition kTransitionType =
diff --git a/components/sessions/core/serialized_navigation_entry_test_helper.h b/components/sessions/core/serialized_navigation_entry_test_helper.h index 606b235..9e8af07 100644 --- a/components/sessions/core/serialized_navigation_entry_test_helper.h +++ b/components/sessions/core/serialized_navigation_entry_test_helper.h
@@ -2,12 +2,13 @@ // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. -#ifndef COMPONENTS_SESSIONS_SESSION_TYPES_TEST_HELPER_H_ -#define COMPONENTS_SESSIONS_SESSION_TYPES_TEST_HELPER_H_ +#ifndef COMPONENTS_SESSIONS_CORE_SERIALIZED_NAVIGATION_ENTRY_TEST_HELPER_H_ +#define COMPONENTS_SESSIONS_CORE_SERIALIZED_NAVIGATION_ENTRY_TEST_HELPER_H_ #include <stdint.h> #include <string> +#include <vector> #include "base/macros.h" #include "base/strings/string16.h" @@ -28,6 +29,7 @@ extern const int kUniqueID; extern const GURL kReferrerURL; extern const int kReferrerPolicy; +extern const GURL kURL; extern const GURL kVirtualURL; extern const base::string16 kTitle; extern const std::string kEncodedPageState; @@ -63,6 +65,11 @@ const SerializedNavigationEntry& actual); // Creates a SerializedNavigationEntry using the |test_data| constants above. + // + // Note that the returned SerializedNavigationEntry will have a bogus + // PageState and therefore can only be used in limited unit tests (e.g. it + // will most likely hit DCHECKs/NOTREACHEDs when passed to the //content + // layer). static SerializedNavigationEntry CreateNavigationForTest(); static void SetReferrerPolicy(int policy, @@ -97,6 +104,6 @@ DISALLOW_IMPLICIT_CONSTRUCTORS(SerializedNavigationEntryTestHelper); }; -} // sessions +} // namespace sessions -#endif // COMPONENTS_SESSIONS_SESSION_TYPES_TEST_HELPER_H_ +#endif // COMPONENTS_SESSIONS_CORE_SERIALIZED_NAVIGATION_ENTRY_TEST_HELPER_H_
diff --git a/components/sync/driver/profile_sync_service.cc b/components/sync/driver/profile_sync_service.cc index 61b71b8..31c290a 100644 --- a/components/sync/driver/profile_sync_service.cc +++ b/components/sync/driver/profile_sync_service.cc
@@ -1282,6 +1282,11 @@ } } + if (base::FeatureList::IsEnabled( + switches::kSyncDeviceInfoInTransportMode)) { + allowed_types.Put(DEVICE_INFO); + } + types = Intersection(types, allowed_types); configure_context.sync_mode = SyncMode::kTransportOnly; }
diff --git a/components/sync/driver/sync_driver_switches.cc b/components/sync/driver/sync_driver_switches.cc index 54e5a1a..fa7c865d 100644 --- a/components/sync/driver/sync_driver_switches.cc +++ b/components/sync/driver/sync_driver_switches.cc
@@ -77,4 +77,7 @@ const base::Feature kMergeBookmarksUsingGUIDs{ "MergeBookmarksUsingGUIDs", base::FEATURE_DISABLED_BY_DEFAULT}; +const base::Feature kSyncDeviceInfoInTransportMode{ + "SyncDeviceInfoInTransportMode", base::FEATURE_DISABLED_BY_DEFAULT}; + } // namespace switches
diff --git a/components/sync/driver/sync_driver_switches.h b/components/sync/driver/sync_driver_switches.h index 2aabef6..8707b6f 100644 --- a/components/sync/driver/sync_driver_switches.h +++ b/components/sync/driver/sync_driver_switches.h
@@ -35,6 +35,7 @@ extern const base::Feature kSyncWifiConfigurations; extern const base::Feature kUpdateBookmarkGUIDWithNodeReplacement; extern const base::Feature kMergeBookmarksUsingGUIDs; +extern const base::Feature kSyncDeviceInfoInTransportMode; } // namespace switches
diff --git a/components/viz/service/display_embedder/skia_output_device.cc b/components/viz/service/display_embedder/skia_output_device.cc index a33e9f1..2541bb0 100644 --- a/components/viz/service/display_embedder/skia_output_device.cc +++ b/components/viz/service/display_embedder/skia_output_device.cc
@@ -34,6 +34,10 @@ void SkiaOutputDevice::SetDrawRectangle(const gfx::Rect& draw_rectangle) {} +void SkiaOutputDevice::SetGpuVSyncEnabled(bool enabled) { + NOTIMPLEMENTED(); +} + void SkiaOutputDevice::SetEnableDCLayers(bool enable) { NOTIMPLEMENTED(); }
diff --git a/components/viz/service/display_embedder/skia_output_device.h b/components/viz/service/display_embedder/skia_output_device.h index 014432c5..9d95eea2 100644 --- a/components/viz/service/display_embedder/skia_output_device.h +++ b/components/viz/service/display_embedder/skia_output_device.h
@@ -91,7 +91,8 @@ // Set the rectangle that will be drawn into on the surface. virtual void SetDrawRectangle(const gfx::Rect& draw_rectangle); - virtual void SetEnableDCLayers(bool enable); + virtual void SetGpuVSyncEnabled(bool enabled); + virtual void SetEnableDCLayers(bool enabled); virtual void ScheduleDCLayers(std::vector<DCLayerOverlay> dc_layers); const OutputSurface::Capabilities& capabilities() const {
diff --git a/components/viz/service/display_embedder/skia_output_device_gl.cc b/components/viz/service/display_embedder/skia_output_device_gl.cc index a39b7ee..98327f5 100644 --- a/components/viz/service/display_embedder/skia_output_device_gl.cc +++ b/components/viz/service/display_embedder/skia_output_device_gl.cc
@@ -43,6 +43,7 @@ .disable_post_sub_buffers_for_onscreen_surfaces) capabilities_.supports_post_sub_buffer = false; capabilities_.max_frames_pending = gl_surface_->GetBufferCount() - 1; + capabilities_.supports_gpu_vsync = gl_surface_->SupportsGpuVSync(); capabilities_.supports_dc_layers = gl_surface_->SupportsDCLayers(); } @@ -162,6 +163,10 @@ gl_surface_->SetDrawRectangle(draw_rectangle); } +void SkiaOutputDeviceGL::SetGpuVSyncEnabled(bool enabled) { + gl_surface_->SetGpuVSyncEnabled(enabled); +} + void SkiaOutputDeviceGL::SetEnableDCLayers(bool enable) { gl_surface_->SetEnableDCLayers(enable); }
diff --git a/components/viz/service/display_embedder/skia_output_device_gl.h b/components/viz/service/display_embedder/skia_output_device_gl.h index 2088166b..798234e 100644 --- a/components/viz/service/display_embedder/skia_output_device_gl.h +++ b/components/viz/service/display_embedder/skia_output_device_gl.h
@@ -64,6 +64,7 @@ BufferPresentedCallback feedback, std::vector<ui::LatencyInfo> latency_info) override; void SetDrawRectangle(const gfx::Rect& draw_rectangle) override; + void SetGpuVSyncEnabled(bool enabled) override; void SetEnableDCLayers(bool enable) override; void ScheduleDCLayers(std::vector<DCLayerOverlay> dc_layers) override; void EnsureBackbuffer() override;
diff --git a/components/viz/service/display_embedder/skia_output_surface_impl.cc b/components/viz/service/display_embedder/skia_output_surface_impl.cc index fd202cf8..cb773de 100644 --- a/components/viz/service/display_embedder/skia_output_surface_impl.cc +++ b/components/viz/service/display_embedder/skia_output_surface_impl.cc
@@ -218,6 +218,16 @@ update_vsync_parameters_callback_ = std::move(callback); } +void SkiaOutputSurfaceImpl::SetGpuVSyncEnabled(bool enabled) { + auto task = base::BindOnce(&SkiaOutputSurfaceImplOnGpu::SetGpuVSyncEnabled, + base::Unretained(impl_on_gpu_.get()), enabled); + task_sequence_->ScheduleOrRetainTask(std::move(task), {}); +} + +void SkiaOutputSurfaceImpl::SetGpuVSyncCallback(GpuVSyncCallback callback) { + gpu_vsync_callback_ = std::move(callback); +} + void SkiaOutputSurfaceImpl::SetDisplayTransformHint( gfx::OverlayTransform transform) { if (capabilities_.supports_pre_transform) @@ -604,22 +614,25 @@ base::BindOnce(&base::WaitableEvent::Signal, base::Unretained(event))); } - auto did_swap_buffer_complete_callback = base::BindRepeating( - &SkiaOutputSurfaceImpl::DidSwapBuffersComplete, weak_ptr_); - did_swap_buffer_complete_callback = - CreateSafeCallback(dependency_.get(), did_swap_buffer_complete_callback); - auto buffer_presented_callback = - base::BindRepeating(&SkiaOutputSurfaceImpl::BufferPresented, weak_ptr_); - buffer_presented_callback = - CreateSafeCallback(dependency_.get(), buffer_presented_callback); - auto context_lost_callback = - base::BindRepeating(&SkiaOutputSurfaceImpl::ContextLost, weak_ptr_); - context_lost_callback = - CreateSafeCallback(dependency_.get(), context_lost_callback); + auto did_swap_buffer_complete_callback = CreateSafeCallback( + dependency_.get(), + base::BindRepeating(&SkiaOutputSurfaceImpl::DidSwapBuffersComplete, + weak_ptr_)); + auto buffer_presented_callback = CreateSafeCallback( + dependency_.get(), + base::BindRepeating(&SkiaOutputSurfaceImpl::BufferPresented, weak_ptr_)); + auto context_lost_callback = CreateSafeCallback( + dependency_.get(), + base::BindRepeating(&SkiaOutputSurfaceImpl::ContextLost, weak_ptr_)); + auto gpu_vsync_callback = CreateSafeCallback( + dependency_.get(), + base::BindRepeating(&SkiaOutputSurfaceImpl::OnGpuVSync, weak_ptr_)); + impl_on_gpu_ = SkiaOutputSurfaceImplOnGpu::Create( dependency_.get(), renderer_settings_, task_sequence_->GetSequenceId(), - did_swap_buffer_complete_callback, buffer_presented_callback, - context_lost_callback); + std::move(did_swap_buffer_complete_callback), + std::move(buffer_presented_callback), std::move(context_lost_callback), + std::move(gpu_vsync_callback)); if (!impl_on_gpu_) { *result = false; } else { @@ -685,6 +698,13 @@ } } +void SkiaOutputSurfaceImpl::OnGpuVSync(base::TimeTicks timebase, + base::TimeDelta interval) { + DCHECK_CALLED_ON_VALID_THREAD(thread_checker_); + if (gpu_vsync_callback_) + gpu_vsync_callback_.Run(timebase, interval); +} + void SkiaOutputSurfaceImpl::ScheduleGpuTaskForTesting( base::OnceClosure callback, std::vector<gpu::SyncToken> sync_tokens) {
diff --git a/components/viz/service/display_embedder/skia_output_surface_impl.h b/components/viz/service/display_embedder/skia_output_surface_impl.h index e9fa29f..d8fc0f0b 100644 --- a/components/viz/service/display_embedder/skia_output_surface_impl.h +++ b/components/viz/service/display_embedder/skia_output_surface_impl.h
@@ -70,6 +70,8 @@ bool use_stencil) override; void SetUpdateVSyncParametersCallback( UpdateVSyncParametersCallback callback) override; + void SetGpuVSyncEnabled(bool enabled) override; + void SetGpuVSyncCallback(GpuVSyncCallback callback) override; void SetDisplayTransformHint(gfx::OverlayTransform transform) override; gfx::OverlayTransform GetDisplayTransform() override; void SwapBuffers(OutputSurfaceFrame frame) override; @@ -149,6 +151,10 @@ void DidSwapBuffersComplete(gpu::SwapBuffersCompleteParams params, const gfx::Size& pixel_size); void BufferPresented(const gfx::PresentationFeedback& feedback); + + // Provided as a callback for the GPU thread. + void OnGpuVSync(base::TimeTicks timebase, base::TimeDelta interval); + void ScheduleGpuTask(base::OnceClosure callback, std::vector<gpu::SyncToken> sync_tokens); GrBackendFormat GetGrBackendFormatForTexture( @@ -177,6 +183,7 @@ std::unique_ptr<SkiaOutputSurfaceDependency> dependency_; const bool is_using_vulkan_; UpdateVSyncParametersCallback update_vsync_parameters_callback_; + GpuVSyncCallback gpu_vsync_callback_; bool is_displayed_as_overlay_ = false; std::unique_ptr<base::WaitableEvent> initialize_waitable_event_;
diff --git a/components/viz/service/display_embedder/skia_output_surface_impl_on_gpu.cc b/components/viz/service/display_embedder/skia_output_surface_impl_on_gpu.cc index 566dd3f..5af4454 100644 --- a/components/viz/service/display_embedder/skia_output_surface_impl_on_gpu.cc +++ b/components/viz/service/display_embedder/skia_output_surface_impl_on_gpu.cc
@@ -586,14 +586,16 @@ SkiaOutputSurfaceDependency* deps, const RendererSettings& renderer_settings, const gpu::SequenceId sequence_id, - const DidSwapBufferCompleteCallback& did_swap_buffer_complete_callback, - const BufferPresentedCallback& buffer_presented_callback, - const ContextLostCallback& context_lost_callback) { + DidSwapBufferCompleteCallback did_swap_buffer_complete_callback, + BufferPresentedCallback buffer_presented_callback, + ContextLostCallback context_lost_callback, + GpuVSyncCallback gpu_vsync_callback) { TRACE_EVENT0("viz", "SkiaOutputSurfaceImplOnGpu::Create"); auto impl_on_gpu = std::make_unique<SkiaOutputSurfaceImplOnGpu>( util::PassKey<SkiaOutputSurfaceImplOnGpu>(), deps, renderer_settings, - sequence_id, did_swap_buffer_complete_callback, buffer_presented_callback, - context_lost_callback); + sequence_id, std::move(did_swap_buffer_complete_callback), + std::move(buffer_presented_callback), std::move(context_lost_callback), + std::move(gpu_vsync_callback)); if (!impl_on_gpu->Initialize()) impl_on_gpu = nullptr; return impl_on_gpu; @@ -604,9 +606,10 @@ SkiaOutputSurfaceDependency* deps, const RendererSettings& renderer_settings, const gpu::SequenceId sequence_id, - const DidSwapBufferCompleteCallback& did_swap_buffer_complete_callback, - const BufferPresentedCallback& buffer_presented_callback, - const ContextLostCallback& context_lost_callback) + DidSwapBufferCompleteCallback did_swap_buffer_complete_callback, + BufferPresentedCallback buffer_presented_callback, + ContextLostCallback context_lost_callback, + GpuVSyncCallback gpu_vsync_callback) : dependency_(std::move(deps)), feature_info_(dependency_->GetSharedContextState()->feature_info()), sync_point_client_state_( @@ -616,9 +619,11 @@ vulkan_context_provider_(dependency_->GetVulkanContextProvider()), renderer_settings_(renderer_settings), sequence_id_(sequence_id), - did_swap_buffer_complete_callback_(did_swap_buffer_complete_callback), - buffer_presented_callback_(buffer_presented_callback), - context_lost_callback_(context_lost_callback), + did_swap_buffer_complete_callback_( + std::move(did_swap_buffer_complete_callback)), + buffer_presented_callback_(std::move(buffer_presented_callback)), + context_lost_callback_(std::move(context_lost_callback)), + gpu_vsync_callback_(std::move(gpu_vsync_callback)), gpu_preferences_(dependency_->GetGpuPreferences()) { DCHECK_CALLED_ON_VALID_THREAD(thread_checker_); } @@ -1199,6 +1204,10 @@ output_device_->ScheduleDCLayers(std::move(dc_layers)); } +void SkiaOutputSurfaceImplOnGpu::SetGpuVSyncEnabled(bool enabled) { + output_device_->SetGpuVSyncEnabled(enabled); +} + void SkiaOutputSurfaceImplOnGpu::SetCapabilitiesForTesting( const OutputSurface::Capabilities& capabilities) { MakeCurrent(false /* need_fbo0 */); @@ -1390,7 +1399,7 @@ } GpuVSyncCallback SkiaOutputSurfaceImplOnGpu::GetGpuVSyncCallback() { - return base::DoNothing::Repeatedly<base::TimeTicks, base::TimeDelta>(); + return gpu_vsync_callback_; } void SkiaOutputSurfaceImplOnGpu::DidSwapBuffersComplete(
diff --git a/components/viz/service/display_embedder/skia_output_surface_impl_on_gpu.h b/components/viz/service/display_embedder/skia_output_surface_impl_on_gpu.h index fcf28021..ac48dab8 100644 --- a/components/viz/service/display_embedder/skia_output_surface_impl_on_gpu.h +++ b/components/viz/service/display_embedder/skia_output_surface_impl_on_gpu.h
@@ -84,18 +84,20 @@ SkiaOutputSurfaceDependency* deps, const RendererSettings& renderer_settings, const gpu::SequenceId sequence_id, - const DidSwapBufferCompleteCallback& did_swap_buffer_complete_callback, - const BufferPresentedCallback& buffer_presented_callback, - const ContextLostCallback& context_lost_callback); + DidSwapBufferCompleteCallback did_swap_buffer_complete_callback, + BufferPresentedCallback buffer_presented_callback, + ContextLostCallback context_lost_callback, + GpuVSyncCallback gpu_vsync_callback); SkiaOutputSurfaceImplOnGpu( util::PassKey<SkiaOutputSurfaceImplOnGpu> pass_key, SkiaOutputSurfaceDependency* deps, const RendererSettings& renderer_settings, const gpu::SequenceId sequence_id, - const DidSwapBufferCompleteCallback& did_swap_buffer_complete_callback, - const BufferPresentedCallback& buffer_presented_callback, - const ContextLostCallback& context_lost_callback); + DidSwapBufferCompleteCallback did_swap_buffer_complete_callback, + BufferPresentedCallback buffer_presented_callback, + ContextLostCallback context_lost_callback, + GpuVSyncCallback gpu_vsync_callback); ~SkiaOutputSurfaceImplOnGpu() override; gpu::CommandBufferId command_buffer_id() const { @@ -157,6 +159,7 @@ image_contexts); void SetEnableDCLayers(bool enable); void ScheduleDCLayers(std::vector<DCLayerOverlay> dc_layers); + void SetGpuVSyncEnabled(bool enabled); bool was_context_lost() { return context_state_->context_lost(); } @@ -220,6 +223,7 @@ const DidSwapBufferCompleteCallback did_swap_buffer_complete_callback_; const BufferPresentedCallback buffer_presented_callback_; const ContextLostCallback context_lost_callback_; + const GpuVSyncCallback gpu_vsync_callback_; #if defined(USE_OZONE) // This should outlive gl_surface_ and vulkan_surface_.
diff --git a/content/browser/accessibility/accessibility_event_recorder_auralinux.cc b/content/browser/accessibility/accessibility_event_recorder_auralinux.cc index 807203b9..bc640286 100644 --- a/content/browser/accessibility/accessibility_event_recorder_auralinux.cc +++ b/content/browser/accessibility/accessibility_event_recorder_auralinux.cc
@@ -222,12 +222,15 @@ base::NumberToString(g_value_get_double(&property_values->new_value)); } else if (g_strcmp0(property_values->property_name, "accessible-name") == 0) { + const char* new_name = g_value_get_string(&property_values->new_value); log += "NAME-CHANGED:"; - log += g_value_get_string(&property_values->new_value); + log += (new_name) ? new_name : "(null)"; } else if (g_strcmp0(property_values->property_name, "accessible-description") == 0) { + const char* new_description = + g_value_get_string(&property_values->new_value); log += "DESCRIPTION-CHANGED:"; - log += g_value_get_string(&property_values->new_value); + log += (new_description) ? new_description : "(null)"; } else { return; }
diff --git a/content/browser/accessibility/browser_accessibility_manager_win.cc b/content/browser/accessibility/browser_accessibility_manager_win.cc index 1a10aa9..3f515b8 100644 --- a/content/browser/accessibility/browser_accessibility_manager_win.cc +++ b/content/browser/accessibility/browser_accessibility_manager_win.cc
@@ -242,9 +242,17 @@ if (node->IsIgnored()) { FireWinAccessibilityEvent(EVENT_OBJECT_HIDE, node); FireUiaStructureChangedEvent(StructureChangeType_ChildRemoved, node); + if (node->GetRole() == ax::mojom::Role::kMenu) { + FireWinAccessibilityEvent(EVENT_SYSTEM_MENUPOPUPEND, node); + FireUiaAccessibilityEvent(UIA_MenuClosedEventId, node); + } } else { FireWinAccessibilityEvent(EVENT_OBJECT_SHOW, node); FireUiaStructureChangedEvent(StructureChangeType_ChildAdded, node); + if (node->GetRole() == ax::mojom::Role::kMenu) { + FireWinAccessibilityEvent(EVENT_SYSTEM_MENUPOPUPSTART, node); + FireUiaAccessibilityEvent(UIA_MenuOpenedEventId, node); + } } aria_properties_events_.insert(node); break; @@ -411,11 +419,15 @@ return; if (!ShouldFireEventForNode(node)) return; - // Suppress events when |IGNORED_CHANGED| except for related SHOW / HIDE + // Suppress events when |IGNORED_CHANGED| except for related SHOW / HIDE. + // Also include MENUPOPUPSTART / MENUPOPUPEND since a change in the ignored + // state may show / hide a popup by exposing it to the tree or not. if (base::Contains(ignored_changed_nodes_, node)) { switch (win_event_type) { case EVENT_OBJECT_HIDE: case EVENT_OBJECT_SHOW: + case EVENT_SYSTEM_MENUPOPUPEND: + case EVENT_SYSTEM_MENUPOPUPSTART: break; default: return; @@ -443,9 +455,20 @@ return; if (!ShouldFireEventForNode(node)) return; - // Suppress events when |IGNORED_CHANGED| - if (node->IsIgnored() || base::Contains(ignored_changed_nodes_, node)) + // Suppress events when |IGNORED_CHANGED| except for MenuClosed / MenuOpen + // since a change in the ignored state may show / hide a popup by exposing + // it to the tree or not. + if (base::Contains(ignored_changed_nodes_, node)) { + switch (uia_event) { + case UIA_MenuClosedEventId: + case UIA_MenuOpenedEventId: + break; + default: + return; + } + } else if (node->IsIgnored()) { return; + } ::UiaRaiseAutomationEvent(ToBrowserAccessibilityWin(node)->GetCOM(), uia_event);
diff --git a/content/browser/frame_host/back_forward_cache_impl.cc b/content/browser/frame_host/back_forward_cache_impl.cc index a7c0694..3c72b7e 100644 --- a/content/browser/frame_host/back_forward_cache_impl.cc +++ b/content/browser/frame_host/back_forward_cache_impl.cc
@@ -360,7 +360,7 @@ } void BackForwardCacheImpl::DisableForRenderFrameHost(GlobalFrameRoutingId id, - std::string_view reason) { + base::StringPiece reason) { DCHECK_CURRENTLY_ON(BrowserThread::UI); auto* rfh = RenderFrameHostImpl::FromID(id); if (rfh)
diff --git a/content/browser/frame_host/back_forward_cache_impl.h b/content/browser/frame_host/back_forward_cache_impl.h index 5b8e8a2..959a35fd45 100644 --- a/content/browser/frame_host/back_forward_cache_impl.h +++ b/content/browser/frame_host/back_forward_cache_impl.h
@@ -125,7 +125,7 @@ // BackForwardCache: void DisableForRenderFrameHost(GlobalFrameRoutingId id, - std::string_view reason) override; + base::StringPiece reason) override; void DisableForTesting(DisableForTestingReason reason) override; private:
diff --git a/content/browser/frame_host/navigation_controller_android.cc b/content/browser/frame_host/navigation_controller_android.cc index 06f8fed..a279330 100644 --- a/content/browser/frame_host/navigation_controller_android.cc +++ b/content/browser/frame_host/navigation_controller_android.cc
@@ -425,6 +425,12 @@ return navigation_controller_->RemoveEntryAtIndex(index); } +void NavigationControllerAndroid::PruneForwardEntries( + JNIEnv* env, + const JavaParamRef<jobject>& obj) { + return navigation_controller_->PruneForwardEntries(); +} + ScopedJavaLocalRef<jstring> NavigationControllerAndroid::GetEntryExtraData( JNIEnv* env, const JavaParamRef<jobject>& obj,
diff --git a/content/browser/frame_host/navigation_controller_android.h b/content/browser/frame_host/navigation_controller_android.h index 7f01993..261353c 100644 --- a/content/browser/frame_host/navigation_controller_android.h +++ b/content/browser/frame_host/navigation_controller_android.h
@@ -119,6 +119,8 @@ jboolean RemoveEntryAtIndex(JNIEnv* env, const base::android::JavaParamRef<jobject>& obj, jint index); + void PruneForwardEntries(JNIEnv* env, + const base::android::JavaParamRef<jobject>& obj); base::android::ScopedJavaLocalRef<jstring> GetEntryExtraData( JNIEnv* env, const base::android::JavaParamRef<jobject>& obj,
diff --git a/content/browser/frame_host/navigation_controller_impl.cc b/content/browser/frame_host/navigation_controller_impl.cc index 80caf27..d758c75 100644 --- a/content/browser/frame_host/navigation_controller_impl.cc +++ b/content/browser/frame_host/navigation_controller_impl.cc
@@ -102,18 +102,6 @@ nav_controller->delegate()->NotifyNavigationListPruned(details); } -// Ensure the given NavigationEntry has a valid state, so that WebKit does not -// get confused if we navigate back to it. -// -// An empty state is treated as a new navigation by WebKit, which would mean -// losing the navigation entries and generating a new navigation entry after -// this one. We don't want that. To avoid this we create a valid state which -// WebKit will not treat as a new navigation. -void SetPageStateIfEmpty(NavigationEntryImpl* entry) { - if (!entry->GetPageState().IsValid()) - entry->SetPageState(PageState::CreateFromURL(entry->GetURL())); -} - // Configure all the NavigationEntries in entries for restore. This resets // the transition type to reload and makes sure the content state isn't empty. void ConfigureEntriesForRestore( @@ -124,8 +112,6 @@ // the typed count. (*entries)[i]->SetTransitionType(ui::PAGE_TRANSITION_RELOAD); (*entries)[i]->set_restore_type(type); - // NOTE(darin): This code is only needed for backwards compat. - SetPageStateIfEmpty((*entries)[i].get()); } } @@ -901,6 +887,17 @@ return true; } +void NavigationControllerImpl::PruneForwardEntries() { + DiscardNonCommittedEntries(); + int remove_start_index = last_committed_entry_index_ + 1; + int num_removed = int(entries_.size()) - remove_start_index; + if (num_removed <= 0) + return; + entries_.erase(entries_.begin() + remove_start_index, entries_.end()); + NotifyPrunedEntries(this, remove_start_index /* start index */, + num_removed /* count */); +} + void NavigationControllerImpl::UpdateVirtualURLToURL( NavigationEntryImpl* entry, const GURL& new_url) { GURL new_virtual_url(new_url); @@ -2445,10 +2442,8 @@ DiscardNonCommittedEntries(); - int current_size = static_cast<int>(entries_.size()); - // When replacing, don't prune the forward history. - if (replace && current_size > 0) { + if (replace && entries_.size() > 0) { CopyReplacedNavigationEntryDataIfPreviouslyEmpty( entries_[last_committed_entry_index_].get(), entry.get()); entries_[last_committed_entry_index_] = std::move(entry); @@ -2458,20 +2453,7 @@ // We shouldn't see replace == true when there's no committed entries. DCHECK(!replace); - if (current_size > 0) { - // Prune any entries which are in front of the current entry. - int num_pruned = 0; - while (last_committed_entry_index_ < (current_size - 1)) { - num_pruned++; - entries_.pop_back(); - current_size--; - } - if (num_pruned > 0) { // Only notify if we did prune something. - NotifyPrunedEntries(this, - last_committed_entry_index_ + 1 /* start index */, - num_pruned /* count */); - } - } + PruneForwardEntries(); PruneOldestSkippableEntryIfFull(); @@ -2617,10 +2599,7 @@ sandboxed_source_frame_tree_node_id, same_document_loads) && DoesSandboxNavigationStayWithinSubtree( sandboxed_source_frame_tree_node_id, different_document_loads); - UMA_HISTOGRAM_BOOLEAN( - "Navigation.SandboxFrameBackForwardStaysWithinSubtree", - navigates_inside_tree); - // Also count the navigations as web use counters so we can determine + // Count the navigations as web use counters so we can determine // the number of pages that trigger this. FrameTreeNode* sandbox_source_frame_tree_node = FrameTreeNode::GloballyFindByID(sandboxed_source_frame_tree_node_id); @@ -3381,6 +3360,9 @@ } void NavigationControllerImpl::DiscardNonCommittedEntries() { + // Avoid sending a notification if there is nothing to discard. + if (!pending_entry_ && transient_entry_index_ == -1) + return; DiscardPendingEntry(false); DiscardTransientEntry(); if (delegate_)
diff --git a/content/browser/frame_host/navigation_controller_impl.h b/content/browser/frame_host/navigation_controller_impl.h index 52661811..586d6c0 100644 --- a/content/browser/frame_host/navigation_controller_impl.h +++ b/content/browser/frame_host/navigation_controller_impl.h
@@ -80,6 +80,7 @@ void GoToIndex(int index) override; void GoToOffset(int offset) override; bool RemoveEntryAtIndex(int index) override; + void PruneForwardEntries() override; const SessionStorageNamespaceMap& GetSessionStorageNamespaceMap() override; SessionStorageNamespace* GetDefaultSessionStorageNamespace() override; bool NeedsReload() override;
diff --git a/content/browser/frame_host/navigation_controller_impl_browsertest.cc b/content/browser/frame_host/navigation_controller_impl_browsertest.cc index c46ceb9f..8d77399 100644 --- a/content/browser/frame_host/navigation_controller_impl_browsertest.cc +++ b/content/browser/frame_host/navigation_controller_impl_browsertest.cc
@@ -9735,20 +9735,14 @@ // *main(simple2, sandbox#test(simple2))] } - static constexpr const char* kWithinSubtreeHistogram = - "Navigation.SandboxFrameBackForwardStaysWithinSubtree"; - private: base::test::ScopedFeatureList feature_list_; }; -// Tests navigations which occur from a sandboxed frame are tracked -// accordingly in histograms. +// Tests navigations which occur from a sandboxed frame are prevented. IN_PROC_BROWSER_TEST_F(SandboxedNavigationControllerBrowserTest, TopLevelNavigationFromSandboxSource) { - base::HistogramTester histogram; SetupNavigation(); - histogram.ExpectTotalCount(kWithinSubtreeHistogram, 0); FrameTreeNode* root = static_cast<WebContentsImpl*>(shell()->web_contents()) ->GetFrameTree() @@ -9762,29 +9756,21 @@ // Navigate sandbox frame back same-document. EXPECT_TRUE(ExecJs(root->child_at(1), back_script)); EXPECT_TRUE(WaitForLoadStop(shell()->web_contents())); - histogram.ExpectBucketCount(kWithinSubtreeHistogram, true, 1); - histogram.ExpectBucketCount(kWithinSubtreeHistogram, false, 0); EXPECT_EQ(3, controller.GetCurrentEntryIndex()); // Navigate innermost frame back cross-document. EXPECT_TRUE(ExecJs(root->child_at(1), back_script)); EXPECT_TRUE(WaitForLoadStop(shell()->web_contents())); - histogram.ExpectBucketCount(kWithinSubtreeHistogram, true, 2); - histogram.ExpectBucketCount(kWithinSubtreeHistogram, false, 0); EXPECT_EQ(2, controller.GetCurrentEntryIndex()); // Navigate sibling frame back cross-document. It should fail. EXPECT_TRUE(ExecJs(root->child_at(1), back_script)); EXPECT_TRUE(WaitForLoadStop(shell()->web_contents())); - histogram.ExpectBucketCount(kWithinSubtreeHistogram, true, 2); - histogram.ExpectBucketCount(kWithinSubtreeHistogram, false, 1); EXPECT_EQ(2, controller.GetCurrentEntryIndex()); // Try it again and it should fail. EXPECT_TRUE(ExecJs(root->child_at(1), back_script)); EXPECT_TRUE(WaitForLoadStop(shell()->web_contents())); - histogram.ExpectBucketCount(kWithinSubtreeHistogram, true, 2); - histogram.ExpectBucketCount(kWithinSubtreeHistogram, false, 2); EXPECT_EQ(2, controller.GetCurrentEntryIndex()); // Do it browser initiated. Make sure histograms don't change. @@ -9792,8 +9778,6 @@ controller.GoBack(); EXPECT_EQ(1, controller.GetCurrentEntryIndex()); EXPECT_TRUE(WaitForLoadStop(shell()->web_contents())); - histogram.ExpectBucketCount(kWithinSubtreeHistogram, true, 2); - histogram.ExpectBucketCount(kWithinSubtreeHistogram, false, 2); // Go forward to reset state, then a mouse back button navigation. // Using the mouse back button should be allowed because it is a @@ -9816,67 +9800,6 @@ EXPECT_EQ(1, controller.GetCurrentEntryIndex()); } -// Tests navigations that occur inside a doubly nested sandbox -// that affect the parent sandbox are considered outside of tree navigation. -IN_PROC_BROWSER_TEST_F(SandboxedNavigationControllerBrowserTest, - DoublyNestedSandboxConsideredOutsideOfTree) { - base::HistogramTester histogram; - SetupNavigation(); - histogram.ExpectTotalCount(kWithinSubtreeHistogram, 0); - - FrameTreeNode* root = static_cast<WebContentsImpl*>(shell()->web_contents()) - ->GetFrameTree() - ->root(); - - std::string back_script = "history.back();"; - - // Test that a navigation in the innermost frame affecting its parent - // in the same sandbox is considered outside the subtree. - EXPECT_TRUE(ExecJs(root->child_at(1)->child_at(0), back_script)); - histogram.ExpectBucketCount(kWithinSubtreeHistogram, true, 0); - histogram.ExpectBucketCount(kWithinSubtreeHistogram, false, 1); -} - -// Tests navigations that influence a sandboxed frame that originate -// from outside the sandboxed frame are not tracked in histograms. -IN_PROC_BROWSER_TEST_F(SandboxedNavigationControllerBrowserTest, - TopLevelNavigationFromNonSandboxSource) { - base::HistogramTester histogram; - SetupNavigation(); - histogram.ExpectTotalCount(kWithinSubtreeHistogram, 0); - - NavigationControllerImpl& controller = static_cast<NavigationControllerImpl&>( - shell()->web_contents()->GetController()); - FrameTreeNode* root = static_cast<WebContentsImpl*>(shell()->web_contents()) - ->GetFrameTree() - ->root(); - - std::string back_script = "history.back();"; - std::string forward_script = "history.forward();"; - - // Browser initiated back. Make sure histograms don't change. - ASSERT_TRUE(controller.CanGoBack()); - controller.GoBack(); - EXPECT_TRUE(WaitForLoadStop(shell()->web_contents())); - histogram.ExpectTotalCount(kWithinSubtreeHistogram, 0); - - // Browser initiated forward. Make sure histograms don't change. - ASSERT_TRUE(controller.CanGoForward()); - controller.GoForward(); - EXPECT_TRUE(WaitForLoadStop(shell()->web_contents())); - histogram.ExpectTotalCount(kWithinSubtreeHistogram, 0); - - // Navigate sandbox frame back same-document originated from - // the main frame though. - EXPECT_TRUE(ExecJs(root, back_script)); - histogram.ExpectTotalCount(kWithinSubtreeHistogram, 0); - - // Navigate sandbox frame forward same-document originated from - // the main frame though. - EXPECT_TRUE(ExecJs(root, forward_script)); - histogram.ExpectTotalCount(kWithinSubtreeHistogram, 0); -} - class SandboxedNavigationControllerPopupBrowserTest : public NavigationControllerBrowserTest { protected:
diff --git a/content/browser/frame_host/navigation_controller_impl_unittest.cc b/content/browser/frame_host/navigation_controller_impl_unittest.cc index 6e563e5..886aeed5 100644 --- a/content/browser/frame_host/navigation_controller_impl_unittest.cc +++ b/content/browser/frame_host/navigation_controller_impl_unittest.cc
@@ -1071,7 +1071,7 @@ EXPECT_EQ(-1, controller.GetPendingEntryIndex()); EXPECT_TRUE(controller.GetPendingEntry()); EXPECT_EQ(-1, controller.GetLastCommittedEntryIndex()); - EXPECT_EQ(2, delegate->navigation_state_change_count()); + EXPECT_EQ(1, delegate->navigation_state_change_count()); // Certain rare cases can make a direct DidCommitProvisionalLoad call without // going to the browser. Renderer reload of an about:blank is such a case. @@ -1082,7 +1082,7 @@ EXPECT_EQ(-1, controller.GetPendingEntryIndex()); EXPECT_FALSE(controller.GetPendingEntry()); EXPECT_EQ(-1, controller.GetLastCommittedEntryIndex()); - EXPECT_EQ(3, delegate->navigation_state_change_count()); + EXPECT_EQ(2, delegate->navigation_state_change_count()); contents()->SetDelegate(nullptr); } @@ -1109,7 +1109,7 @@ EXPECT_EQ(-1, controller.GetPendingEntryIndex()); EXPECT_TRUE(controller.GetPendingEntry()); EXPECT_EQ(-1, controller.GetLastCommittedEntryIndex()); - EXPECT_EQ(2, delegate->navigation_state_change_count()); + EXPECT_EQ(1, delegate->navigation_state_change_count()); // It may abort before committing, if it's a download or due to a stop or // a new navigation from the user. @@ -1121,7 +1121,7 @@ EXPECT_EQ(-1, controller.GetPendingEntryIndex()); EXPECT_TRUE(controller.GetPendingEntry()); EXPECT_EQ(-1, controller.GetLastCommittedEntryIndex()); - EXPECT_EQ(2, delegate->navigation_state_change_count()); + EXPECT_EQ(1, delegate->navigation_state_change_count()); NavigationEntry* pending_entry = controller.GetPendingEntry(); // Ensure that a reload keeps the same pending entry. @@ -1162,9 +1162,9 @@ EXPECT_EQ(-1, controller.GetPendingEntryIndex()); EXPECT_TRUE(controller.GetPendingEntry()); EXPECT_EQ(0, controller.GetLastCommittedEntryIndex()); - // The delegate should have been notified at least twice: once for the loading - // state change, and once for the url change. - EXPECT_EQ(3, delegate->navigation_state_change_count()); + // The delegate should have been notified twice: once for the loading state + // change, and once for the url change. + EXPECT_EQ(2, delegate->navigation_state_change_count()); // The visible entry should be the last committed URL, not the pending one. EXPECT_EQ(kExistingURL, controller.GetVisibleEntry()->GetURL()); @@ -1188,7 +1188,7 @@ EXPECT_EQ(0, controller.GetLastCommittedEntryIndex()); // The delegate should have been notified twice: once for the loading state // change, and once for the url change. - EXPECT_EQ(5, delegate->navigation_state_change_count()); + EXPECT_EQ(4, delegate->navigation_state_change_count()); // The visible entry should be the last committed URL, not the pending one, // so that no spoof is possible. @@ -2449,7 +2449,6 @@ std::string(), browser_context(), nullptr /* blob_url_loader_factory */); entry->SetTitle(base::ASCIIToUTF16("Title")); - entry->SetPageState(PageState::CreateFromEncodedData("state")); const base::Time timestamp = base::Time::Now(); entry->SetTimestamp(timestamp); entries.push_back(std::move(entry)); @@ -2518,7 +2517,6 @@ std::string(), browser_context(), nullptr /* blob_url_loader_factory */); new_entry->SetTitle(base::ASCIIToUTF16("Title")); - new_entry->SetPageState(PageState::CreateFromEncodedData("state")); entries.push_back(std::move(new_entry)); std::unique_ptr<WebContents> our_contents = WebContents::Create(WebContents::CreateParams(browser_context())); @@ -4840,4 +4838,106 @@ BrowserURLHandlerImpl::GetInstance()->SetFixupHandlerForTesting(nullptr); } +// Tests that calling RemoveForwareEntries() clears all forward entries +// including non-committed entries. +TEST_F(NavigationControllerTest, PruneForwardEntries) { + NavigationControllerImpl& controller = controller_impl(); + const GURL url_0("http://foo/0"); + const GURL url_1("http://foo/1"); + const GURL url_2("http://foo/2"); + const GURL url_3("http://foo/3"); + const GURL url_transient("http://foo/transient"); + + NavigateAndCommit(url_0); + NavigateAndCommit(url_1); + NavigateAndCommit(url_2); + NavigateAndCommit(url_3); + + // Set a WebContentsDelegate to listen for state changes. + std::unique_ptr<TestWebContentsDelegate> delegate( + new TestWebContentsDelegate()); + EXPECT_FALSE(contents()->GetDelegate()); + contents()->SetDelegate(delegate.get()); + + controller.GoBack(); + + // Ensure that non-committed entries are removed even if there are no forward + // entries. + EXPECT_EQ(4, controller.GetEntryCount()); + EXPECT_EQ(2, controller.GetPendingEntryIndex()); + EXPECT_EQ(2, controller.GetCurrentEntryIndex()); + EXPECT_EQ(3, controller.GetLastCommittedEntryIndex()); + int state_change_count = delegate->navigation_state_change_count(); + controller.PruneForwardEntries(); + EXPECT_EQ(4, controller.GetEntryCount()); + EXPECT_EQ(-1, controller.GetPendingEntryIndex()); + EXPECT_EQ(3, controller.GetCurrentEntryIndex()); + EXPECT_EQ(3, controller.GetLastCommittedEntryIndex()); + EXPECT_EQ(0U, navigation_list_pruned_counter_); + EXPECT_EQ(state_change_count + 1, delegate->navigation_state_change_count()); + + controller.GoBack(); + contents()->CommitPendingNavigation(); + controller.GoBack(); + contents()->CommitPendingNavigation(); + controller.GoBack(); + contents()->CommitPendingNavigation(); + controller.GoForward(); + + EXPECT_EQ(1, controller.GetPendingEntryIndex()); + EXPECT_EQ(0, controller.GetLastCommittedEntryIndex()); + // Insert a transient entry before the pending one. + std::unique_ptr<NavigationEntry> transient_entry(new NavigationEntryImpl); + transient_entry->SetURL(url_transient); + controller.SetTransientEntry(std::move(transient_entry)); + + state_change_count = delegate->navigation_state_change_count(); + controller.PruneForwardEntries(); + + EXPECT_EQ(1, controller.GetEntryCount()); + EXPECT_FALSE(controller.CanGoForward()); + EXPECT_FALSE(controller.CanGoBack()); + EXPECT_EQ(0, controller.GetLastCommittedEntryIndex()); + EXPECT_EQ(0, controller.GetCurrentEntryIndex()); + EXPECT_EQ(-1, controller.GetPendingEntryIndex()); + EXPECT_EQ(nullptr, controller.GetPendingEntry()); + EXPECT_EQ(nullptr, controller.GetTransientEntry()); + EXPECT_EQ(url_0, controller.GetVisibleEntry()->GetURL()); + EXPECT_EQ(1U, navigation_list_pruned_counter_); + EXPECT_EQ(1, last_navigation_entry_pruned_details_.index); + EXPECT_EQ(3, last_navigation_entry_pruned_details_.count); + EXPECT_EQ(state_change_count + 1, delegate->navigation_state_change_count()); +} + +// Make sure that cloning a WebContentsImpl and clearing forward entries +// before the first commit doesn't clear all entries. +TEST_F(NavigationControllerTest, PruneForwardEntriesAfterClone) { + NavigationControllerImpl& controller = controller_impl(); + const GURL url1("http://foo1"); + const GURL url2("http://foo2"); + + NavigateAndCommit(url1); + NavigateAndCommit(url2); + + std::unique_ptr<WebContents> clone(controller.GetWebContents()->Clone()); + clone->GetController().LoadIfNecessary(); + + // Set a WebContentsDelegate to listen for state changes after the clone call + // to only count state changes from the PruneForwardEntries call. + std::unique_ptr<TestWebContentsDelegate> delegate( + new TestWebContentsDelegate()); + EXPECT_FALSE(clone->GetDelegate()); + clone->SetDelegate(delegate.get()); + + EXPECT_EQ(1, clone->GetController().GetPendingEntryIndex()); + + clone->GetController().PruneForwardEntries(); + + ASSERT_EQ(2, clone->GetController().GetEntryCount()); + EXPECT_EQ(-1, clone->GetController().GetPendingEntryIndex()); + EXPECT_EQ(url2, clone->GetController().GetVisibleEntry()->GetURL()); + EXPECT_EQ(0U, navigation_list_pruned_counter_); + EXPECT_EQ(1, delegate->navigation_state_change_count()); +} + } // namespace content
diff --git a/content/browser/frame_host/navigation_entry_impl.cc b/content/browser/frame_host/navigation_entry_impl.cc index 7575f08..dce0551 100644 --- a/content/browser/frame_host/navigation_entry_impl.cc +++ b/content/browser/frame_host/navigation_entry_impl.cc
@@ -95,6 +95,12 @@ } } +base::Optional<base::string16> UrlToOptionalString16(const GURL& url) { + if (!url.is_valid()) + return base::nullopt; + return base::UTF8ToUTF16(url.spec()); +} + void RecursivelyGenerateFrameState( NavigationEntryImpl::TreeNode* node, ExplodedFrameState* state, @@ -112,6 +118,35 @@ // Copy the FrameNavigationEntry's frame state into the destination state. *state = frame_state; + // Some data is stored *both* in 1) PageState/ExplodedFrameState and 2) + // FrameNavigationEntry. We want to treat FrameNavigationEntry as the + // authoritative source of the data, so we clobber the ExplodedFrameState with + // the data taken from FrameNavigationEntry. + // + // The following ExplodedFrameState fields do not have an equivalent + // FrameNavigationEntry field: + // - target + // - state_object + // - document_state + // - scroll_restoration_type + // - did_save_scroll_or_scale_state + // - visual_viewport_scroll_offset + // - scroll_offset + // - page_scale_factor + // - http_body (FrameNavigationEntry::GetPostData extracts the body from + // the ExplodedFrameState) + // - scroll_anchor_selector + // - scroll_anchor_offset + // - scroll_anchor_simhash + state->url_string = UrlToOptionalString16(node->frame_entry->url()); + state->referrer = UrlToOptionalString16(node->frame_entry->referrer().url); + state->referrer_policy = node->frame_entry->referrer().policy; + state->item_sequence_number = node->frame_entry->item_sequence_number(); + state->document_sequence_number = + node->frame_entry->document_sequence_number(); + // TODO(lukasza): https://crbug.com/976055: Persist |initiator_origin| in + // the ExplodedFrameState. + // Copy the frame's files into the PageState's |referenced_files|. referenced_files->reserve(referenced_files->size() + exploded_page_state.referenced_files.size()); @@ -374,6 +409,8 @@ } void NavigationEntryImpl::SetPageState(const PageState& state) { + DCHECK(state.IsValid()); + // SetPageState should only be called before the NavigationEntry has been // loaded, such as for restore (when there are no subframe // FrameNavigationEntries yet). However, some callers expect to call this @@ -386,12 +423,10 @@ if (!frame_tree_->children.empty()) frame_tree_->children.clear(); - // If the PageState can't be parsed or has no children, just store it on the - // main frame's FrameNavigationEntry without recursively creating subframe - // entries. + // If the PageState can't be parsed, just store it on the main frame's + // FrameNavigationEntry without recursively creating subframe entries. ExplodedPageState exploded_state; - if (!DecodePageState(state.ToEncodedData(), &exploded_state) || - exploded_state.top.children.size() == 0U) { + if (!DecodePageState(state.ToEncodedData(), &exploded_state)) { frame_tree_->frame_entry->SetPageState(state); return; } @@ -401,14 +436,8 @@ } PageState NavigationEntryImpl::GetPageState() { - // Just return the main frame's state if there are no subframe - // FrameNavigationEntries. - if (frame_tree_->children.size() == 0U) - return frame_tree_->frame_entry->page_state(); - - // When we're using subframe entries, each FrameNavigationEntry has a - // frame-specific PageState. We combine these into an ExplodedPageState tree - // and generate a full PageState from it. + // Each FrameNavigationEntry has a frame-specific PageState. We combine these + // into an ExplodedPageState tree and generate a full PageState from it. ExplodedPageState exploded_state; RecursivelyGenerateFrameState(frame_tree_.get(), &exploded_state.top, &exploded_state.referenced_files);
diff --git a/content/browser/frame_host/navigation_entry_impl_unittest.cc b/content/browser/frame_host/navigation_entry_impl_unittest.cc index 9bbcf168..45cb8cd6 100644 --- a/content/browser/frame_host/navigation_entry_impl_unittest.cc +++ b/content/browser/frame_host/navigation_entry_impl_unittest.cc
@@ -14,6 +14,7 @@ #include "base/time/time.h" #include "build/build_config.h" #include "content/browser/site_instance_impl.h" +#include "content/common/page_state_serialization.h" #include "content/public/browser/ssl_status.h" #include "content/public/test/browser_task_environment.h" #include "content/public/test/test_browser_context.h" @@ -49,6 +50,13 @@ DISALLOW_COPY_AND_ASSIGN(TestSSLStatusData); }; +PageState CreateTestPageState() { + ExplodedPageState exploded_state; + std::string encoded_data; + EncodePageState(exploded_state, &encoded_data); + return PageState::CreateFromEncodedData(encoded_data); +} + } // namespace class NavigationEntryTest : public testing::Test { @@ -231,12 +239,6 @@ entry2_->SetTitle(ASCIIToUTF16("title2")); EXPECT_EQ(ASCIIToUTF16("title2"), entry2_->GetTitle()); - // State - EXPECT_FALSE(entry1_->GetPageState().IsValid()); - EXPECT_FALSE(entry2_->GetPageState().IsValid()); - entry2_->SetPageState(PageState::CreateFromEncodedData("state")); - EXPECT_EQ("state", entry2_->GetPageState().ToEncodedData()); - // Transition type EXPECT_TRUE(ui::PageTransitionTypeIncludingQualifiersIs( entry1_->GetTransitionType(), ui::PAGE_TRANSITION_LINK)); @@ -292,10 +294,21 @@ // Initiator origin. EXPECT_FALSE( entry1_->root_node()->frame_entry->initiator_origin().has_value()); - EXPECT_TRUE( + ASSERT_TRUE( entry2_->root_node()->frame_entry->initiator_origin().has_value()); EXPECT_EQ(url::Origin::Create(GURL("https://initiator.example.com")), entry2_->root_node()->frame_entry->initiator_origin().value()); + + // State. + // + // Note that calling SetPageState may also set some other FNE members + // (referrer, initiator, etc.). This is why it is important to test + // SetPageState/GetPageState last. + PageState test_page_state = CreateTestPageState(); + entry2_->SetPageState(test_page_state); + // TODO(lukasza): https://crbug.com/976055: Once |initiator_origin| is + // persisted across session restore, the test here should verify that + // SetPageState round-trips via GetPageState. } // Test basic Clone behavior.
diff --git a/content/browser/frame_host/navigation_request.cc b/content/browser/frame_host/navigation_request.cc index ea59a44..441f632 100644 --- a/content/browser/frame_host/navigation_request.cc +++ b/content/browser/frame_host/navigation_request.cc
@@ -469,11 +469,20 @@ UMA_HISTOGRAM_BOOLEAN("Navigation.RequiresDedicatedProcess", new_rfh->GetSiteInstance()->RequiresDedicatedProcess()); + if (common_params.url.SchemeIsHTTPOrHTTPS()) { + UMA_HISTOGRAM_BOOLEAN( + "Navigation.RequiresDedicatedProcess.HTTPOrHTTPS", + new_rfh->GetSiteInstance()->RequiresDedicatedProcess()); + } ChildProcessSecurityPolicyImpl* policy = ChildProcessSecurityPolicyImpl::GetInstance(); GURL process_lock = policy->GetOriginLock(new_rfh->GetProcess()->GetID()); UMA_HISTOGRAM_BOOLEAN("Navigation.IsLockedProcess", !process_lock.is_empty()); + if (common_params.url.SchemeIsHTTPOrHTTPS()) { + UMA_HISTOGRAM_BOOLEAN("Navigation.IsLockedProcess.HTTPOrHTTPS", + !process_lock.is_empty()); + } if (common_params.transition & ui::PAGE_TRANSITION_FORWARD_BACK) { UMA_HISTOGRAM_BOOLEAN("Navigation.IsSameProcess.BackForward",
diff --git a/content/browser/indexed_db/database_impl.cc b/content/browser/indexed_db/database_impl.cc index 3f382904..e071f7db 100644 --- a/content/browser/indexed_db/database_impl.cc +++ b/content/browser/indexed_db/database_impl.cc
@@ -105,7 +105,7 @@ int64_t transaction_id, const std::vector<int64_t>& object_store_ids, blink::mojom::IDBTransactionMode mode, - bool relaxed_durability) { + blink::mojom::IDBTransactionDurability durability) { DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_); if (!connection_->IsConnected()) return; @@ -125,7 +125,7 @@ transaction_id, std::set<int64_t>(object_store_ids.begin(), object_store_ids.end()), mode, new IndexedDBBackingStore::Transaction( - connection_->database()->backing_store(), relaxed_durability)); + connection_->database()->backing_store(), durability)); connection_->database()->RegisterAndScheduleTransaction(transaction); dispatcher_host_->CreateAndBindTransactionImpl(
diff --git a/content/browser/indexed_db/database_impl.h b/content/browser/indexed_db/database_impl.h index 92eb2c65..ce181bd 100644 --- a/content/browser/indexed_db/database_impl.h +++ b/content/browser/indexed_db/database_impl.h
@@ -44,12 +44,13 @@ void RenameObjectStore(int64_t transaction_id, int64_t object_store_id, const base::string16& new_name) override; - void CreateTransaction(mojo::PendingAssociatedReceiver< - blink::mojom::IDBTransaction> transaction_receiver, - int64_t transaction_id, - const std::vector<int64_t>& object_store_ids, - blink::mojom::IDBTransactionMode mode, - bool relaxed_durability) override; + void CreateTransaction( + mojo::PendingAssociatedReceiver<blink::mojom::IDBTransaction> + transaction_receiver, + int64_t transaction_id, + const std::vector<int64_t>& object_store_ids, + blink::mojom::IDBTransactionMode mode, + blink::mojom::IDBTransactionDurability durability) override; void Close() override; void VersionChangeIgnored() override; void AddObserver(int64_t transaction_id,
diff --git a/content/browser/indexed_db/indexed_db_backing_store.cc b/content/browser/indexed_db/indexed_db_backing_store.cc index 87ced3c..a57fffd 100644 --- a/content/browser/indexed_db/indexed_db_backing_store.cc +++ b/content/browser/indexed_db/indexed_db_backing_store.cc
@@ -831,9 +831,21 @@ } std::unique_ptr<IndexedDBBackingStore::Transaction> -IndexedDBBackingStore::CreateTransaction(bool relaxed_durability) { - return std::make_unique<IndexedDBBackingStore::Transaction>( - this, relaxed_durability); +IndexedDBBackingStore::CreateTransaction( + blink::mojom::IDBTransactionDurability durability) { + return std::make_unique<IndexedDBBackingStore::Transaction>(this, durability); +} + +// static +bool IndexedDBBackingStore::ShouldSyncOnCommit( + blink::mojom::IDBTransactionDurability durability) { + switch (durability) { + case blink::mojom::IDBTransactionDurability::Default: + case blink::mojom::IDBTransactionDurability::Strict: + return true; + case blink::mojom::IDBTransactionDurability::Relaxed: + return false; + } } leveldb::Status IndexedDBBackingStore::GetCompleteMetadata( @@ -1361,10 +1373,10 @@ int64_t database_id, base::WeakPtr<IndexedDBBackingStore> backing_store, WriteDescriptorVec* blobs, - bool relaxed_durability_, + blink::mojom::IDBTransactionDurability durability, IndexedDBBackingStore::BlobWriteCallback callback) { auto writer = base::WrapRefCounted(new ChainedBlobWriterImpl( - database_id, backing_store, relaxed_durability_, std::move(callback))); + database_id, backing_store, durability, std::move(callback))); writer->blobs_.swap(*blobs); writer->iter_ = writer->blobs_.begin(); backing_store->task_runner()->PostTask( @@ -1406,17 +1418,18 @@ } storage::FlushPolicy GetFlushPolicy() const override { - return relaxed_durability_ ? storage::FlushPolicy::NO_FLUSH_ON_COMPLETION - : storage::FlushPolicy::FLUSH_ON_COMPLETION; + return IndexedDBBackingStore::ShouldSyncOnCommit(durability_) + ? storage::FlushPolicy::FLUSH_ON_COMPLETION + : storage::FlushPolicy::NO_FLUSH_ON_COMPLETION; } private: ChainedBlobWriterImpl(int64_t database_id, base::WeakPtr<IndexedDBBackingStore> backing_store, - bool relaxed_durability, + blink::mojom::IDBTransactionDurability durability, IndexedDBBackingStore::BlobWriteCallback callback) : waiting_for_callback_(false), - relaxed_durability_(relaxed_durability), + durability_(durability), database_id_(database_id), backing_store_(backing_store), callback_(std::move(callback)), @@ -1444,7 +1457,7 @@ } bool waiting_for_callback_; - bool relaxed_durability_; + blink::mojom::IDBTransactionDurability durability_; scoped_refptr<ChainedBlobWriterImpl> self_ref_; WriteDescriptorVec blobs_; WriteDescriptorVec::const_iterator iter_; @@ -2849,13 +2862,13 @@ // |backing_store| can be null in unittests (see FakeTransaction). IndexedDBBackingStore::Transaction::Transaction( IndexedDBBackingStore* backing_store, - bool relaxed_durability) + blink::mojom::IDBTransactionDurability durability) : backing_store_(backing_store), leveldb_factory_(backing_store ? backing_store->leveldb_factory_ : nullptr), database_id_(-1), committing_(false), - relaxed_durability_(relaxed_durability) {} + durability_(durability) {} IndexedDBBackingStore::Transaction::~Transaction() { DCHECK(!committing_); @@ -3079,8 +3092,8 @@ // Actually commit. If this succeeds, the journals will appropriately // reflect pending blob work - dead files that should be deleted // immediately, and live files to monitor. - bool sync_on_commit = !relaxed_durability_; - s = transaction_->Commit(sync_on_commit); + s = transaction_->Commit( + IndexedDBBackingStore::ShouldSyncOnCommit(durability_)); transaction_ = nullptr; if (!s.ok()) { @@ -3149,7 +3162,7 @@ // can be destructed before the callback is triggered. chained_blob_writer_ = ChainedBlobWriterImpl::Create( database_id_, backing_store_->AsWeakPtr(), new_files_to_write, - relaxed_durability_, + durability_, base::BindOnce( [](base::WeakPtr<IndexedDBBackingStore::Transaction> transaction, void* tracing_end_ptr, BlobWriteCallback final_callback,
diff --git a/content/browser/indexed_db/indexed_db_backing_store.h b/content/browser/indexed_db/indexed_db_backing_store.h index 58eec91..e4507e06 100644 --- a/content/browser/indexed_db/indexed_db_backing_store.h +++ b/content/browser/indexed_db/indexed_db_backing_store.h
@@ -137,7 +137,7 @@ class CONTENT_EXPORT Transaction { public: explicit Transaction(IndexedDBBackingStore* backing_store, - bool relaxed_durability); + blink::mojom::IDBTransactionDurability durability); virtual ~Transaction(); virtual void Begin(std::vector<ScopeLock> locks); @@ -300,10 +300,9 @@ // has been bumped, and journal cleaning should be deferred. bool committing_; - // This flag is passed to LevelDBScopes as |sync_on_commit|. - // If |relaxed_durability| is false, the commit flushes to disk. - // If true, it avoids the flush for performance at the cost of durability. - bool relaxed_durability_; + // This flag is passed to LevelDBScopes as |sync_on_commit|, converted + // via ShouldSyncOnCommit. + blink::mojom::IDBTransactionDurability durability_; base::WeakPtrFactory<Transaction> ptr_factory_{this}; @@ -584,12 +583,15 @@ bool is_incognito() const { return backing_store_mode_ == Mode::kInMemory; } virtual std::unique_ptr<Transaction> CreateTransaction( - bool relaxed_durability); + blink::mojom::IDBTransactionDurability durability); base::WeakPtr<IndexedDBBackingStore> AsWeakPtr() { return weak_factory_.GetWeakPtr(); } + static bool ShouldSyncOnCommit( + blink::mojom::IDBTransactionDurability durability); + protected: friend class IndexedDBOriginState;
diff --git a/content/browser/indexed_db/indexed_db_backing_store_unittest.cc b/content/browser/indexed_db/indexed_db_backing_store_unittest.cc index 9922fc6..c4c3fd5 100644 --- a/content/browser/indexed_db/indexed_db_backing_store_unittest.cc +++ b/content/browser/indexed_db/indexed_db_backing_store_unittest.cc
@@ -467,8 +467,7 @@ IndexedDBValue value = value1_; { IndexedDBBackingStore::Transaction transaction1( - backing_store(), - /*relaxed_durability=*/true); + backing_store(), blink::mojom::IDBTransactionDurability::Relaxed); transaction1.Begin(CreateDummyLock()); IndexedDBBackingStore::RecordIdentifier record; leveldb::Status s = backing_store()->PutRecord(&transaction1, 1, 1, @@ -485,8 +484,7 @@ { IndexedDBBackingStore::Transaction transaction2( - backing_store(), - /*relaxed_durability=*/true); + backing_store(), blink::mojom::IDBTransactionDurability::Relaxed); transaction2.Begin(CreateDummyLock()); IndexedDBValue result_value; EXPECT_TRUE(backing_store() @@ -518,7 +516,7 @@ FROM_HERE, base::BindLambdaForTesting([&]() { // Initiate transaction1 - writing blobs. transaction1 = std::make_unique<IndexedDBBackingStore::Transaction>( - backing_store(), /*relaxed_durability=*/true); + backing_store(), blink::mojom::IDBTransactionDurability::Relaxed); transaction1->Begin(CreateDummyLock()); IndexedDBBackingStore::RecordIdentifier record; EXPECT_TRUE( @@ -541,7 +539,7 @@ // Initiate transaction2, reading blobs. IndexedDBBackingStore::Transaction transaction2( - backing_store(), /*relaxed_durability=*/true); + backing_store(), blink::mojom::IDBTransactionDurability::Relaxed); transaction2.Begin(CreateDummyLock()); IndexedDBValue result_value; EXPECT_TRUE(backing_store() @@ -562,7 +560,7 @@ // Initiate transaction3, deleting blobs. transaction3 = std::make_unique<IndexedDBBackingStore::Transaction>( - backing_store(), /*relaxed_durability=*/true); + backing_store(), blink::mojom::IDBTransactionDurability::Relaxed); transaction3->Begin(CreateDummyLock()); EXPECT_TRUE(backing_store() ->DeleteRange(transaction3.get(), 1, 1, @@ -643,7 +641,7 @@ // Initiate transaction1 - write records. transaction1 = std::make_unique<IndexedDBBackingStore::Transaction>( - backing_store(), /*relaxed_durability=*/true); + backing_store(), blink::mojom::IDBTransactionDurability::Relaxed); transaction1->Begin(CreateDummyLock()); IndexedDBBackingStore::RecordIdentifier record; for (size_t i = 0; i < values.size(); ++i) { @@ -670,7 +668,7 @@ // Initiate transaction 2 - delete range. transaction2 = std::make_unique<IndexedDBBackingStore::Transaction>( - backing_store(), /*relaxed_durability=*/true); + backing_store(), blink::mojom::IDBTransactionDurability::Relaxed); transaction2->Begin(CreateDummyLock()); IndexedDBValue result_value; EXPECT_TRUE(backing_store() @@ -762,7 +760,7 @@ // Initiate transaction1 - write records. transaction1 = std::make_unique<IndexedDBBackingStore::Transaction>( - backing_store(), /*relaxed_durability=*/true); + backing_store(), blink::mojom::IDBTransactionDurability::Relaxed); transaction1->Begin(CreateDummyLock()); IndexedDBBackingStore::RecordIdentifier record; @@ -789,7 +787,7 @@ // Initiate transaction 2 - delete range. transaction2 = std::make_unique<IndexedDBBackingStore::Transaction>( - backing_store(), /*relaxed_durability=*/true); + backing_store(), blink::mojom::IDBTransactionDurability::Relaxed); transaction2->Begin(CreateDummyLock()); IndexedDBValue result_value; EXPECT_TRUE(backing_store() @@ -832,7 +830,7 @@ FROM_HERE, base::BindLambdaForTesting([&]() { // Initiate transaction1. transaction1 = std::make_unique<IndexedDBBackingStore::Transaction>( - backing_store(), /*relaxed_durability=*/true); + backing_store(), blink::mojom::IDBTransactionDurability::Relaxed); transaction1->Begin(CreateDummyLock()); IndexedDBBackingStore::RecordIdentifier record1; EXPECT_TRUE( @@ -855,7 +853,7 @@ // Initiate transaction2. transaction2 = std::make_unique<IndexedDBBackingStore::Transaction>( - backing_store(), /*relaxed_durability=*/true); + backing_store(), blink::mojom::IDBTransactionDurability::Relaxed); transaction2->Begin(CreateDummyLock()); IndexedDBBackingStore::RecordIdentifier record2; EXPECT_TRUE( @@ -900,7 +898,7 @@ idb_context_->TaskRunner()->PostTask( FROM_HERE, base::BindLambdaForTesting([&]() { transaction1 = std::make_unique<IndexedDBBackingStore::Transaction>( - backing_store(), /*relaxed_durability=*/true); + backing_store(), blink::mojom::IDBTransactionDurability::Relaxed); transaction1->Begin(CreateDummyLock()); IndexedDBBackingStore::RecordIdentifier record; EXPECT_TRUE( @@ -921,7 +919,7 @@ EXPECT_TRUE(transaction1->CommitPhaseTwo().ok()); IndexedDBBackingStore::Transaction transaction2( - backing_store(), /*relaxed_durability=*/true); + backing_store(), blink::mojom::IDBTransactionDurability::Relaxed); transaction2.Begin(CreateDummyLock()); EXPECT_TRUE( backing_store() @@ -942,7 +940,7 @@ } transaction3 = std::make_unique<IndexedDBBackingStore::Transaction>( - backing_store(), /*relaxed_durability=*/true); + backing_store(), blink::mojom::IDBTransactionDurability::Relaxed); transaction3->Begin(CreateDummyLock()); EXPECT_TRUE(backing_store() ->DeleteRange(transaction3.get(), 1, 1, @@ -1016,8 +1014,7 @@ EncodeIDBKey(index_key, &index_key_raw); { IndexedDBBackingStore::Transaction transaction1( - backing_store(), - /*relaxed_durability=*/true); + backing_store(), blink::mojom::IDBTransactionDurability::Relaxed); transaction1.Begin(CreateDummyLock()); IndexedDBBackingStore::RecordIdentifier record; leveldb::Status s = backing_store()->PutRecord( @@ -1046,8 +1043,7 @@ { IndexedDBBackingStore::Transaction transaction2( - backing_store(), - /*relaxed_durability=*/true); + backing_store(), blink::mojom::IDBTransactionDurability::Relaxed); transaction2.Begin(CreateDummyLock()); IndexedDBValue result_value; leveldb::Status s = backing_store()->GetRecord( @@ -1100,7 +1096,7 @@ IndexedDBValue result_value; IndexedDBBackingStore::Transaction transaction1( - backing_store(), /*relaxed_durability=*/true); + backing_store(), blink::mojom::IDBTransactionDurability::Relaxed); transaction1.Begin(CreateDummyLock()); IndexedDBBackingStore::RecordIdentifier record; @@ -1191,7 +1187,7 @@ database_id = database.id; IndexedDBBackingStore::Transaction transaction( - backing_store(), /*relaxed_durability=*/true); + backing_store(), blink::mojom::IDBTransactionDurability::Relaxed); transaction.Begin(CreateDummyLock()); IndexedDBObjectStoreMetadata object_store; @@ -1392,7 +1388,7 @@ database_id = database.id; IndexedDBBackingStore::Transaction transaction( - backing_store(), /*relaxed_durability=*/true); + backing_store(), blink::mojom::IDBTransactionDurability::Relaxed); transaction.Begin(CreateDummyLock()); IndexedDBObjectStoreMetadata object_store; @@ -1419,7 +1415,7 @@ // Save a value. IndexedDBBackingStore::Transaction transaction1( - backing_store(), /*relaxed_durability=*/true); + backing_store(), blink::mojom::IDBTransactionDurability::Relaxed); transaction1.Begin(CreateDummyLock()); IndexedDBBackingStore::RecordIdentifier record; leveldb::Status s = backing_store()->PutRecord( @@ -1452,7 +1448,7 @@ IndexedDBValue value = value1_; IndexedDBBackingStore::Transaction transaction2( - backing_store(), /*relaxed_durability=*/true); + backing_store(), blink::mojom::IDBTransactionDurability::Relaxed); transaction2.Begin(CreateDummyLock()); IndexedDBValue result_value; EXPECT_TRUE(backing_store() @@ -1519,7 +1515,7 @@ database_id = database.id; IndexedDBBackingStore::Transaction transaction( - backing_store(), /*relaxed_durability=*/true); + backing_store(), blink::mojom::IDBTransactionDurability::Relaxed); transaction.Begin(CreateDummyLock()); IndexedDBObjectStoreMetadata object_store; @@ -1544,7 +1540,7 @@ FROM_HERE, base::BindLambdaForTesting([&]() { // Initiate transaction1 - writing blobs. transaction1 = std::make_unique<IndexedDBBackingStore::Transaction>( - backing_store(), /*relaxed_durability=*/true); + backing_store(), blink::mojom::IDBTransactionDurability::Relaxed); transaction1->Begin(CreateDummyLock()); IndexedDBBackingStore::RecordIdentifier record; EXPECT_TRUE(backing_store()
diff --git a/content/browser/indexed_db/indexed_db_connection_coordinator.cc b/content/browser/indexed_db/indexed_db_connection_coordinator.cc index 97d8039..26d5777 100644 --- a/content/browser/indexed_db/indexed_db_connection_coordinator.cc +++ b/content/browser/indexed_db/indexed_db_connection_coordinator.cc
@@ -288,12 +288,13 @@ std::vector<int64_t> object_store_ids; state_ = RequestState::kPendingTransactionComplete; - bool relaxed_durability = false; IndexedDBTransaction* transaction = connection_->CreateTransaction( pending_->transaction_id, std::set<int64_t>(object_store_ids.begin(), object_store_ids.end()), blink::mojom::IDBTransactionMode::VersionChange, - db_->backing_store()->CreateTransaction(relaxed_durability).release()); + db_->backing_store() + ->CreateTransaction(blink::mojom::IDBTransactionDurability::Strict) + .release()); // Save a WeakPtr<IndexedDBTransaction> for the CreateAndBindTransaction // function to use later.
diff --git a/content/browser/indexed_db/indexed_db_database_unittest.cc b/content/browser/indexed_db/indexed_db_database_unittest.cc index 2606195..617080a 100644 --- a/content/browser/indexed_db/indexed_db_database_unittest.cc +++ b/content/browser/indexed_db/indexed_db_database_unittest.cc
@@ -181,12 +181,12 @@ const int64_t transaction_id = 123; const std::vector<int64_t> scope; - const bool relaxed_durability = true; IndexedDBTransaction* transaction = request->connection()->CreateTransaction( transaction_id, std::set<int64_t>(scope.begin(), scope.end()), blink::mojom::IDBTransactionMode::ReadOnly, - new IndexedDBBackingStore::Transaction(backing_store_.get(), - relaxed_durability)); + new IndexedDBBackingStore::Transaction( + backing_store_.get(), + blink::mojom::IDBTransactionDurability::Relaxed)); db_->RegisterAndScheduleTransaction(transaction); request->connection()->CloseAndReportForceClose();
diff --git a/content/browser/indexed_db/indexed_db_fake_backing_store.cc b/content/browser/indexed_db/indexed_db_fake_backing_store.cc index a753e49..d48f6f6 100644 --- a/content/browser/indexed_db/indexed_db_fake_backing_store.cc +++ b/content/browser/indexed_db/indexed_db_fake_backing_store.cc
@@ -158,7 +158,10 @@ IndexedDBFakeBackingStore::FakeTransaction::FakeTransaction( leveldb::Status result) - : IndexedDBBackingStore::Transaction(nullptr, true), result_(result) {} + : IndexedDBBackingStore::Transaction( + nullptr, + blink::mojom::IDBTransactionDurability::Relaxed), + result_(result) {} void IndexedDBFakeBackingStore::FakeTransaction::Begin( std::vector<ScopeLock> locks) {} leveldb::Status IndexedDBFakeBackingStore::FakeTransaction::CommitPhaseOne( @@ -177,7 +180,8 @@ } std::unique_ptr<IndexedDBBackingStore::Transaction> -IndexedDBFakeBackingStore::CreateTransaction(bool relaxed_durability) { +IndexedDBFakeBackingStore::CreateTransaction( + blink::mojom::IDBTransactionDurability durability) { return std::make_unique<FakeTransaction>(leveldb::Status::OK()); }
diff --git a/content/browser/indexed_db/indexed_db_fake_backing_store.h b/content/browser/indexed_db/indexed_db_fake_backing_store.h index 240fc83..46725de 100644 --- a/content/browser/indexed_db/indexed_db_fake_backing_store.h +++ b/content/browser/indexed_db/indexed_db_fake_backing_store.h
@@ -128,7 +128,7 @@ }; std::unique_ptr<IndexedDBBackingStore::Transaction> CreateTransaction( - bool relaxed_durability) override; + blink::mojom::IDBTransactionDurability durability) override; protected: private:
diff --git a/content/browser/notifications/platform_notification_context_impl.cc b/content/browser/notifications/platform_notification_context_impl.cc index 93ae69a..2a447b7 100644 --- a/content/browser/notifications/platform_notification_context_impl.cc +++ b/content/browser/notifications/platform_notification_context_impl.cc
@@ -438,6 +438,11 @@ return; } + base::Time timestamp = + database_data.notification_data.show_trigger_timestamp.value(); + UMA_HISTOGRAM_LONG_TIMES("Notifications.Triggers.DisplayDelay", + base::Time::Now() - timestamp); + // Remove resources from DB as we don't need them anymore. database_->DeleteNotificationResources(write_database_data.notification_id, write_database_data.origin);
diff --git a/content/browser/notifications/platform_notification_context_trigger_unittest.cc b/content/browser/notifications/platform_notification_context_trigger_unittest.cc index 403973d..d5699cf 100644 --- a/content/browser/notifications/platform_notification_context_trigger_unittest.cc +++ b/content/browser/notifications/platform_notification_context_trigger_unittest.cc
@@ -7,6 +7,7 @@ #include "base/bind.h" #include "base/run_loop.h" #include "base/test/bind_test_util.h" +#include "base/test/metrics/histogram_tester.h" #include "base/test/scoped_feature_list.h" #include "base/time/time.h" #include "content/browser/notifications/notification_trigger_constants.h" @@ -277,4 +278,22 @@ TimeDelta::FromSeconds(kMaximumScheduledNotificationsPerOrigin + 1))); } +TEST_F(PlatformNotificationContextTriggerTest, RecordDisplayDelay) { + base::HistogramTester histogram_tester; + base::TimeDelta trigger_delay = TimeDelta::FromSeconds(10); + base::TimeDelta display_delay = TimeDelta::FromSeconds(8); + + WriteNotificationData("1", Time::Now() + trigger_delay); + ASSERT_EQ(0u, GetDisplayedNotifications().size()); + + // Forward time until after the expected trigger time. + task_environment_.FastForwardBy(trigger_delay + display_delay); + + // Trigger notification |display_delay| after it should have been displayed. + TriggerNotifications(); + + histogram_tester.ExpectUniqueSample("Notifications.Triggers.DisplayDelay", + display_delay.InMilliseconds(), 1); +} + } // namespace content
diff --git a/content/child/BUILD.gn b/content/child/BUILD.gn index 424a4d569..8c5d431 100644 --- a/content/child/BUILD.gn +++ b/content/child/BUILD.gn
@@ -72,6 +72,8 @@ "thread_safe_sender.h", "webthemeengine_impl_android.cc", "webthemeengine_impl_android.h", + "webthemeengine_impl_conversions.cc", + "webthemeengine_impl_conversions.h", "webthemeengine_impl_default.cc", "webthemeengine_impl_default.h", "webthemeengine_impl_mac.h",
diff --git a/content/child/runtime_features.cc b/content/child/runtime_features.cc index 2b3bb2d7..eb46ac8d 100644 --- a/content/child/runtime_features.cc +++ b/content/child/runtime_features.cc
@@ -23,6 +23,7 @@ #include "services/network/public/cpp/features.h" #include "third_party/blink/public/common/features.h" #include "third_party/blink/public/platform/web_runtime_features.h" +#include "ui/accessibility/accessibility_features.h" #include "ui/base/ui_base_features.h" #include "ui/events/blink/blink_features.h" #include "ui/gfx/switches.h" @@ -435,6 +436,10 @@ } #endif + WebRuntimeFeatures::EnableAccessibilityExposeDisplayNone( + base::FeatureList::IsEnabled( + features::kEnableAccessibilityExposeDisplayNone)); + if (command_line.HasSwitch(switches::kEnableAccessibilityObjectModel)) WebRuntimeFeatures::EnableAccessibilityObjectModel(true);
diff --git a/content/child/webthemeengine_impl_conversions.cc b/content/child/webthemeengine_impl_conversions.cc new file mode 100644 index 0000000..db004c1 --- /dev/null +++ b/content/child/webthemeengine_impl_conversions.cc
@@ -0,0 +1,120 @@ +// Copyright 2019 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#include "content/child/webthemeengine_impl_conversions.h" + +namespace content { + +// TODO(https://crbug.com/988434): The mapping functions below are duplicated +// inside Blink and in the Android implementation of WebThemeEngine. They should +// be implemented in one place where dependencies between Blink and +// ui::NativeTheme make sense. +ui::NativeTheme::Part NativeThemePart(blink::WebThemeEngine::Part part) { + switch (part) { + case blink::WebThemeEngine::kPartScrollbarDownArrow: + return ui::NativeTheme::kScrollbarDownArrow; + case blink::WebThemeEngine::kPartScrollbarLeftArrow: + return ui::NativeTheme::kScrollbarLeftArrow; + case blink::WebThemeEngine::kPartScrollbarRightArrow: + return ui::NativeTheme::kScrollbarRightArrow; + case blink::WebThemeEngine::kPartScrollbarUpArrow: + return ui::NativeTheme::kScrollbarUpArrow; + case blink::WebThemeEngine::kPartScrollbarHorizontalThumb: + return ui::NativeTheme::kScrollbarHorizontalThumb; + case blink::WebThemeEngine::kPartScrollbarVerticalThumb: + return ui::NativeTheme::kScrollbarVerticalThumb; + case blink::WebThemeEngine::kPartScrollbarHorizontalTrack: + return ui::NativeTheme::kScrollbarHorizontalTrack; + case blink::WebThemeEngine::kPartScrollbarVerticalTrack: + return ui::NativeTheme::kScrollbarVerticalTrack; + case blink::WebThemeEngine::kPartScrollbarCorner: + return ui::NativeTheme::kScrollbarCorner; + case blink::WebThemeEngine::kPartCheckbox: + return ui::NativeTheme::kCheckbox; + case blink::WebThemeEngine::kPartRadio: + return ui::NativeTheme::kRadio; + case blink::WebThemeEngine::kPartButton: + return ui::NativeTheme::kPushButton; + case blink::WebThemeEngine::kPartTextField: + return ui::NativeTheme::kTextField; + case blink::WebThemeEngine::kPartMenuList: + return ui::NativeTheme::kMenuList; + case blink::WebThemeEngine::kPartSliderTrack: + return ui::NativeTheme::kSliderTrack; + case blink::WebThemeEngine::kPartSliderThumb: + return ui::NativeTheme::kSliderThumb; + case blink::WebThemeEngine::kPartInnerSpinButton: + return ui::NativeTheme::kInnerSpinButton; + case blink::WebThemeEngine::kPartProgressBar: + return ui::NativeTheme::kProgressBar; + default: + return ui::NativeTheme::kScrollbarDownArrow; + } +} + +ui::NativeTheme::ScrollbarOverlayColorTheme +NativeThemeScrollbarOverlayColorTheme( + blink::WebScrollbarOverlayColorTheme theme) { + switch (theme) { + case blink::WebScrollbarOverlayColorTheme:: + kWebScrollbarOverlayColorThemeLight: + return ui::NativeTheme::ScrollbarOverlayColorThemeLight; + case blink::WebScrollbarOverlayColorTheme:: + kWebScrollbarOverlayColorThemeDark: + return ui::NativeTheme::ScrollbarOverlayColorThemeDark; + default: + return ui::NativeTheme::ScrollbarOverlayColorThemeDark; + } +} + +ui::NativeTheme::State NativeThemeState(blink::WebThemeEngine::State state) { + switch (state) { + case blink::WebThemeEngine::kStateDisabled: + return ui::NativeTheme::kDisabled; + case blink::WebThemeEngine::kStateHover: + return ui::NativeTheme::kHovered; + case blink::WebThemeEngine::kStateNormal: + return ui::NativeTheme::kNormal; + case blink::WebThemeEngine::kStatePressed: + return ui::NativeTheme::kPressed; + default: + return ui::NativeTheme::kDisabled; + } +} + +ui::NativeTheme::ColorScheme NativeColorScheme( + blink::WebColorScheme color_scheme) { + switch (color_scheme) { + case blink::WebColorScheme::kLight: + return ui::NativeTheme::ColorScheme::kLight; + case blink::WebColorScheme::kDark: + return ui::NativeTheme::ColorScheme::kDark; + } +} + +ui::NativeTheme::SystemThemeColor NativeSystemThemeColor( + blink::WebThemeEngine::SystemThemeColor theme_color) { + switch (theme_color) { + case blink::WebThemeEngine::SystemThemeColor::kButtonFace: + return ui::NativeTheme::SystemThemeColor::kButtonFace; + case blink::WebThemeEngine::SystemThemeColor::kButtonText: + return ui::NativeTheme::SystemThemeColor::kButtonText; + case blink::WebThemeEngine::SystemThemeColor::kGrayText: + return ui::NativeTheme::SystemThemeColor::kGrayText; + case blink::WebThemeEngine::SystemThemeColor::kHighlight: + return ui::NativeTheme::SystemThemeColor::kHighlight; + case blink::WebThemeEngine::SystemThemeColor::kHighlightText: + return ui::NativeTheme::SystemThemeColor::kHighlightText; + case blink::WebThemeEngine::SystemThemeColor::kHotlight: + return ui::NativeTheme::SystemThemeColor::kHotlight; + case blink::WebThemeEngine::SystemThemeColor::kWindow: + return ui::NativeTheme::SystemThemeColor::kWindow; + case blink::WebThemeEngine::SystemThemeColor::kWindowText: + return ui::NativeTheme::SystemThemeColor::kWindowText; + default: + return ui::NativeTheme::SystemThemeColor::kNotSupported; + } +} + +} // namespace content
diff --git a/content/child/webthemeengine_impl_conversions.h b/content/child/webthemeengine_impl_conversions.h new file mode 100644 index 0000000..fdd2e56 --- /dev/null +++ b/content/child/webthemeengine_impl_conversions.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 CONTENT_CHILD_WEBTHEMEENGINE_IMPL_CONVERSIONS_H_ +#define CONTENT_CHILD_WEBTHEMEENGINE_IMPL_CONVERSIONS_H_ + +#include "content/child/webthemeengine_impl_default.h" +#include "content/common/content_export.h" +#include "ui/native_theme/native_theme.h" + +namespace content { + +CONTENT_EXPORT ui::NativeTheme::Part NativeThemePart( + blink::WebThemeEngine::Part part); + +CONTENT_EXPORT ui::NativeTheme::ScrollbarOverlayColorTheme +NativeThemeScrollbarOverlayColorTheme( + blink::WebScrollbarOverlayColorTheme theme); + +CONTENT_EXPORT ui::NativeTheme::State NativeThemeState( + blink::WebThemeEngine::State state); + +CONTENT_EXPORT ui::NativeTheme::ColorScheme NativeColorScheme( + blink::WebColorScheme color_scheme); + +CONTENT_EXPORT ui::NativeTheme::SystemThemeColor NativeSystemThemeColor( + blink::WebThemeEngine::SystemThemeColor theme_color); + +} // namespace content + +#endif // CONTENT_CHILD_WEBTHEMEENGINE_IMPL_CONVERSIONS_H_
diff --git a/content/child/webthemeengine_impl_default.cc b/content/child/webthemeengine_impl_default.cc index 59e6012..f6bf7200 100644 --- a/content/child/webthemeengine_impl_default.cc +++ b/content/child/webthemeengine_impl_default.cc
@@ -5,6 +5,7 @@ #include "content/child/webthemeengine_impl_default.h" #include "build/build_config.h" +#include "content/child/webthemeengine_impl_conversions.h" #include "skia/ext/platform_canvas.h" #include "third_party/blink/public/platform/web_rect.h" #include "third_party/blink/public/platform/web_size.h" @@ -35,92 +36,6 @@ } // namespace -// TODO(https://crbug.com/988434): The mapping functions below are duplicated -// inside Blink and in the Android implementation of WebThemeEngine. They should -// be implemented in one place where dependencies between Blink and -// ui::NativeTheme make sense. -static ui::NativeTheme::Part NativeThemePart( - WebThemeEngine::Part part) { - switch (part) { - case WebThemeEngine::kPartScrollbarDownArrow: - return ui::NativeTheme::kScrollbarDownArrow; - case WebThemeEngine::kPartScrollbarLeftArrow: - return ui::NativeTheme::kScrollbarLeftArrow; - case WebThemeEngine::kPartScrollbarRightArrow: - return ui::NativeTheme::kScrollbarRightArrow; - case WebThemeEngine::kPartScrollbarUpArrow: - return ui::NativeTheme::kScrollbarUpArrow; - case WebThemeEngine::kPartScrollbarHorizontalThumb: - return ui::NativeTheme::kScrollbarHorizontalThumb; - case WebThemeEngine::kPartScrollbarVerticalThumb: - return ui::NativeTheme::kScrollbarVerticalThumb; - case WebThemeEngine::kPartScrollbarHorizontalTrack: - return ui::NativeTheme::kScrollbarHorizontalTrack; - case WebThemeEngine::kPartScrollbarVerticalTrack: - return ui::NativeTheme::kScrollbarVerticalTrack; - case WebThemeEngine::kPartScrollbarCorner: - return ui::NativeTheme::kScrollbarCorner; - case WebThemeEngine::kPartCheckbox: - return ui::NativeTheme::kCheckbox; - case WebThemeEngine::kPartRadio: - return ui::NativeTheme::kRadio; - case WebThemeEngine::kPartButton: - return ui::NativeTheme::kPushButton; - case WebThemeEngine::kPartTextField: - return ui::NativeTheme::kTextField; - case WebThemeEngine::kPartMenuList: - return ui::NativeTheme::kMenuList; - case WebThemeEngine::kPartSliderTrack: - return ui::NativeTheme::kSliderTrack; - case WebThemeEngine::kPartSliderThumb: - return ui::NativeTheme::kSliderThumb; - case WebThemeEngine::kPartInnerSpinButton: - return ui::NativeTheme::kInnerSpinButton; - case WebThemeEngine::kPartProgressBar: - return ui::NativeTheme::kProgressBar; - default: - return ui::NativeTheme::kScrollbarDownArrow; - } -} - -static ui::NativeTheme::ScrollbarOverlayColorTheme -NativeThemeScrollbarOverlayColorTheme(WebScrollbarOverlayColorTheme theme) { - switch (theme) { - case WebScrollbarOverlayColorTheme::kWebScrollbarOverlayColorThemeLight: - return ui::NativeTheme::ScrollbarOverlayColorThemeLight; - case WebScrollbarOverlayColorTheme::kWebScrollbarOverlayColorThemeDark: - return ui::NativeTheme::ScrollbarOverlayColorThemeDark; - default: - return ui::NativeTheme::ScrollbarOverlayColorThemeDark; - } -} - -static ui::NativeTheme::State NativeThemeState( - WebThemeEngine::State state) { - switch (state) { - case WebThemeEngine::kStateDisabled: - return ui::NativeTheme::kDisabled; - case WebThemeEngine::kStateHover: - return ui::NativeTheme::kHovered; - case WebThemeEngine::kStateNormal: - return ui::NativeTheme::kNormal; - case WebThemeEngine::kStatePressed: - return ui::NativeTheme::kPressed; - default: - return ui::NativeTheme::kDisabled; - } -} - -static ui::NativeTheme::ColorScheme NativeColorScheme( - WebColorScheme color_scheme) { - switch (color_scheme) { - case WebColorScheme::kLight: - return ui::NativeTheme::ColorScheme::kLight; - case WebColorScheme::kDark: - return ui::NativeTheme::ColorScheme::kDark; - } -} - static void GetNativeThemeExtraParams( WebThemeEngine::Part part, WebThemeEngine::State state, @@ -297,6 +212,12 @@ NativeThemePart(part)); } +base::Optional<SkColor> WebThemeEngineDefault::GetSystemColor( + blink::WebThemeEngine::SystemThemeColor system_theme_color) const { + return ui::NativeTheme::GetInstanceForWeb()->GetSystemColorFromMap( + NativeSystemThemeColor(system_theme_color)); +} + #if defined(OS_WIN) // static void WebThemeEngineDefault::cacheScrollBarMetrics(
diff --git a/content/child/webthemeengine_impl_default.h b/content/child/webthemeengine_impl_default.h index 180f15c..80c69f2 100644 --- a/content/child/webthemeengine_impl_default.h +++ b/content/child/webthemeengine_impl_default.h
@@ -28,6 +28,8 @@ bool SupportsNinePatch(Part part) const override; blink::WebSize NinePatchCanvasSize(Part part) const override; blink::WebRect NinePatchAperture(Part part) const override; + base::Optional<SkColor> GetSystemColor(blink::WebThemeEngine::SystemThemeColor + system_theme_color) const override; #if defined(OS_WIN) // Caches the scrollbar metrics. These are retrieved in the browser and passed // to the renderer in blink::mojom::RendererPreferences because the required
diff --git a/content/child/webthemeengine_impl_unittest.cc b/content/child/webthemeengine_impl_unittest.cc new file mode 100644 index 0000000..755ac9f --- /dev/null +++ b/content/child/webthemeengine_impl_unittest.cc
@@ -0,0 +1,126 @@ +// 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/child/webthemeengine_impl_conversions.h" + +#include <vector> +#include "testing/gtest/include/gtest/gtest.h" +#include "third_party/blink/public/platform/web_theme_engine.h" + +namespace content { + +TEST(WebThemeEngineTest, NativeSystemThemeColor) { + std::vector<blink::WebThemeEngine::SystemThemeColor> blink_inputs = { + blink::WebThemeEngine::SystemThemeColor::kButtonFace, + blink::WebThemeEngine::SystemThemeColor::kButtonText, + blink::WebThemeEngine::SystemThemeColor::kGrayText, + blink::WebThemeEngine::SystemThemeColor::kHighlight, + blink::WebThemeEngine::SystemThemeColor::kHighlightText, + blink::WebThemeEngine::SystemThemeColor::kHotlight, + blink::WebThemeEngine::SystemThemeColor::kWindow, + blink::WebThemeEngine::SystemThemeColor::kWindowText}; + + std::vector<ui::NativeTheme::SystemThemeColor> native_theme_outputs = { + ui::NativeTheme::SystemThemeColor::kButtonFace, + ui::NativeTheme::SystemThemeColor::kButtonText, + ui::NativeTheme::SystemThemeColor::kGrayText, + ui::NativeTheme::SystemThemeColor::kHighlight, + ui::NativeTheme::SystemThemeColor::kHighlightText, + ui::NativeTheme::SystemThemeColor::kHotlight, + ui::NativeTheme::SystemThemeColor::kWindow, + ui::NativeTheme::SystemThemeColor::kWindowText}; + + for (size_t i = 0; i < blink_inputs.size(); ++i) + EXPECT_EQ(NativeSystemThemeColor(blink_inputs[i]), native_theme_outputs[i]); +} + +TEST(WebThemeEngineTest, NativeSystemThemePart) { + std::vector<blink::WebThemeEngine::Part> blink_inputs = { + blink::WebThemeEngine::kPartScrollbarDownArrow, + blink::WebThemeEngine::kPartScrollbarLeftArrow, + blink::WebThemeEngine::kPartScrollbarRightArrow, + blink::WebThemeEngine::kPartScrollbarUpArrow, + blink::WebThemeEngine::kPartScrollbarHorizontalThumb, + blink::WebThemeEngine::kPartScrollbarVerticalThumb, + blink::WebThemeEngine::kPartScrollbarHorizontalTrack, + blink::WebThemeEngine::kPartScrollbarVerticalTrack, + blink::WebThemeEngine::kPartScrollbarCorner, + blink::WebThemeEngine::kPartCheckbox, + blink::WebThemeEngine::kPartRadio, + blink::WebThemeEngine::kPartButton, + blink::WebThemeEngine::kPartTextField, + blink::WebThemeEngine::kPartMenuList, + blink::WebThemeEngine::kPartSliderTrack, + blink::WebThemeEngine::kPartSliderThumb, + blink::WebThemeEngine::kPartInnerSpinButton, + blink::WebThemeEngine::kPartProgressBar}; + + std::vector<ui::NativeTheme::Part> native_theme_outputs = { + ui::NativeTheme::kScrollbarDownArrow, + ui::NativeTheme::kScrollbarLeftArrow, + ui::NativeTheme::kScrollbarRightArrow, + ui::NativeTheme::kScrollbarUpArrow, + ui::NativeTheme::kScrollbarHorizontalThumb, + ui::NativeTheme::kScrollbarVerticalThumb, + ui::NativeTheme::kScrollbarHorizontalTrack, + ui::NativeTheme::kScrollbarVerticalTrack, + ui::NativeTheme::kScrollbarCorner, + ui::NativeTheme::kCheckbox, + ui::NativeTheme::kRadio, + ui::NativeTheme::kPushButton, + ui::NativeTheme::kTextField, + ui::NativeTheme::kMenuList, + ui::NativeTheme::kSliderTrack, + ui::NativeTheme::kSliderThumb, + ui::NativeTheme::kInnerSpinButton, + ui::NativeTheme::kProgressBar}; + + for (size_t i = 0; i < blink_inputs.size(); ++i) + EXPECT_EQ(NativeThemePart(blink_inputs[i]), native_theme_outputs[i]); +} + +TEST(WebThemeEngineTest, NativeSystemThemeState) { + std::vector<blink::WebThemeEngine::State> blink_inputs = { + blink::WebThemeEngine::kStateDisabled, + blink::WebThemeEngine::kStateHover, + blink::WebThemeEngine::kStateNormal, + blink::WebThemeEngine::kStatePressed, + }; + + std::vector<ui::NativeTheme::State> native_theme_outputs = { + ui::NativeTheme::kDisabled, ui::NativeTheme::kHovered, + ui::NativeTheme::kNormal, ui::NativeTheme::kPressed}; + + for (size_t i = 0; i < blink_inputs.size(); ++i) + EXPECT_EQ(NativeThemeState(blink_inputs[i]), native_theme_outputs[i]); +} + +TEST(WebThemeEngineTest, NativeColorScheme) { + std::vector<blink::WebColorScheme> blink_inputs = { + blink::WebColorScheme::kLight, blink::WebColorScheme::kDark}; + + std::vector<ui::NativeTheme::ColorScheme> native_theme_outputs = { + ui::NativeTheme::ColorScheme::kLight, + ui::NativeTheme::ColorScheme::kDark}; + + for (size_t i = 0; i < blink_inputs.size(); ++i) + EXPECT_EQ(NativeColorScheme(blink_inputs[i]), native_theme_outputs[i]); +} + +TEST(WebThemeEngineTest, NativeThemeScrollbarOverlayColorTheme) { + std::vector<blink::WebScrollbarOverlayColorTheme> blink_inputs = { + blink::WebScrollbarOverlayColorTheme::kWebScrollbarOverlayColorThemeLight, + blink::WebScrollbarOverlayColorTheme::kWebScrollbarOverlayColorThemeDark}; + + std::vector<ui::NativeTheme::ScrollbarOverlayColorTheme> + native_theme_outputs = {ui::NativeTheme::ScrollbarOverlayColorThemeLight, + ui::NativeTheme::ScrollbarOverlayColorThemeDark}; + + for (size_t i = 0; i < blink_inputs.size(); ++i) { + EXPECT_EQ(NativeThemeScrollbarOverlayColorTheme(blink_inputs[i]), + native_theme_outputs[i]); + } +} + +} // namespace content
diff --git a/content/common/page_state_serialization.cc b/content/common/page_state_serialization.cc index bf884e3..2e0c0c6 100644 --- a/content/common/page_state_serialization.cc +++ b/content/common/page_state_serialization.cc
@@ -1023,6 +1023,7 @@ obj.version = kCurrentVersion; WriteMojoPageState(exploded, &obj); *encoded = obj.GetAsString(); + DCHECK(!encoded->empty()); } void LegacyEncodePageStateForTesting(const ExplodedPageState& exploded,
diff --git a/content/public/android/java/src/org/chromium/content/browser/framehost/NavigationControllerImpl.java b/content/public/android/java/src/org/chromium/content/browser/framehost/NavigationControllerImpl.java index 53a1a08..60999a25 100644 --- a/content/public/android/java/src/org/chromium/content/browser/framehost/NavigationControllerImpl.java +++ b/content/public/android/java/src/org/chromium/content/browser/framehost/NavigationControllerImpl.java
@@ -272,6 +272,13 @@ } @Override + public void pruneForwardEntries() { + if (mNativeNavigationControllerAndroid == 0) return; + NavigationControllerImplJni.get().pruneForwardEntries( + mNativeNavigationControllerAndroid, NavigationControllerImpl.this); + } + + @Override public String getEntryExtraData(int index, String key) { if (mNativeNavigationControllerAndroid == 0) return null; return NavigationControllerImplJni.get().getEntryExtraData( @@ -362,6 +369,8 @@ long nativeNavigationControllerAndroid, NavigationControllerImpl caller); boolean removeEntryAtIndex( long nativeNavigationControllerAndroid, NavigationControllerImpl caller, int index); + void pruneForwardEntries( + long nativeNavigationControllerAndroid, NavigationControllerImpl caller); String getEntryExtraData(long nativeNavigationControllerAndroid, NavigationControllerImpl caller, int index, String key); void setEntryExtraData(long nativeNavigationControllerAndroid,
diff --git a/content/public/android/java/src/org/chromium/content_public/browser/NavigationController.java b/content/public/android/java/src/org/chromium/content_public/browser/NavigationController.java index c01dc1a..fca6a6f 100644 --- a/content/public/android/java/src/org/chromium/content_public/browser/NavigationController.java +++ b/content/public/android/java/src/org/chromium/content_public/browser/NavigationController.java
@@ -173,6 +173,12 @@ public boolean removeEntryAtIndex(int index); /** + * Discards any transient or pending entries, then discards all entries after the current entry + * index. + */ + void pruneForwardEntries(); + + /** * Gets extra data on the {@link NavigationEntry} at {@code index}. * @param index The index of the navigation entry. * @param key The data key.
diff --git a/content/public/browser/back_forward_cache.h b/content/public/browser/back_forward_cache.h index 14babf3..693c41e1 100644 --- a/content/public/browser/back_forward_cache.h +++ b/content/public/browser/back_forward_cache.h
@@ -5,8 +5,7 @@ #ifndef CONTENT_PUBLIC_BROWSER_BACK_FORWARD_CACHE_H_ #define CONTENT_PUBLIC_BROWSER_BACK_FORWARD_CACHE_H_ -#include <string_view> - +#include "base/strings/string_piece.h" #include "content/common/content_export.h" #include "content/public/browser/global_routing_id.h" @@ -43,7 +42,7 @@ // |id|: If no RenderFrameHost can be found for the given id nothing happens. // |reason|: Free form string to be used in logging and metrics. virtual void DisableForRenderFrameHost(GlobalFrameRoutingId id, - std::string_view reason) = 0; + base::StringPiece reason) = 0; // List of reasons the BackForwardCache was disabled for a specific test. If a // test needs to be disabled for a reason not covered below, please add to
diff --git a/content/public/browser/navigation_controller.h b/content/public/browser/navigation_controller.h index 47f66af..df7edc38 100644 --- a/content/public/browser/navigation_controller.h +++ b/content/public/browser/navigation_controller.h
@@ -414,6 +414,10 @@ // Otherwise this call discards any transient or pending entries. virtual bool RemoveEntryAtIndex(int index) = 0; + // Discards any transient or pending entries, then discards all entries after + // the current entry index. + virtual void PruneForwardEntries() = 0; + // Random -------------------------------------------------------------------- // Session storage depends on dom_storage that depends on blink::WebString.
diff --git a/content/public/test/android/javatests/src/org/chromium/content_public/browser/test/mock/MockNavigationController.java b/content/public/test/android/javatests/src/org/chromium/content_public/browser/test/mock/MockNavigationController.java index 9329499..bfb468a 100644 --- a/content/public/test/android/javatests/src/org/chromium/content_public/browser/test/mock/MockNavigationController.java +++ b/content/public/test/android/javatests/src/org/chromium/content_public/browser/test/mock/MockNavigationController.java
@@ -121,6 +121,9 @@ } @Override + public void pruneForwardEntries() {} + + @Override public String getEntryExtraData(int index, String key) { return null; }
diff --git a/content/test/BUILD.gn b/content/test/BUILD.gn index d683aaa..abf86cc 100644 --- a/content/test/BUILD.gn +++ b/content/test/BUILD.gn
@@ -1875,6 +1875,7 @@ "../child/dwrite_font_proxy/dwrite_font_proxy_win_unittest.cc", "../child/dwrite_font_proxy/font_fallback_win_unittest.cc", "../child/font_warmup_win_unittest.cc", + "../child/webthemeengine_impl_unittest.cc", "../common/android/gin_java_bridge_value_unittest.cc", "../common/background_fetch/background_fetch_mojom_traits_unittest.cc", "../common/common_param_traits_unittest.cc",
diff --git a/content/test/gpu/gpu_tests/test_expectations/webgl2_conformance_expectations.txt b/content/test/gpu/gpu_tests/test_expectations/webgl2_conformance_expectations.txt index 8d15097..0beccb6 100644 --- a/content/test/gpu/gpu_tests/test_expectations/webgl2_conformance_expectations.txt +++ b/content/test/gpu/gpu_tests/test_expectations/webgl2_conformance_expectations.txt
@@ -274,6 +274,7 @@ # Passthrough command decoder / Linux / OpenGL / NVIDIA crbug.com/766918 [ opengl linux passthrough nvidia ] conformance2/textures/image_bitmap_from_video/* [ RetryOnFailure ] +crbug.com/965648 [ opengl linux passthrough nvidia ] deqp/functional/gles3/shaderstruct.html [ RetryOnFailure ] ####################
diff --git a/device/vr/openxr/openxr_api_wrapper.cc b/device/vr/openxr/openxr_api_wrapper.cc index 68e8af1..9889f19 100644 --- a/device/vr/openxr/openxr_api_wrapper.cc +++ b/device/vr/openxr/openxr_api_wrapper.cc
@@ -33,6 +33,7 @@ XrResult CreateInstance(XrInstance* instance) { XrInstanceCreateInfo instance_create_info = {XR_TYPE_INSTANCE_CREATE_INFO}; strcpy_s(instance_create_info.applicationInfo.applicationName, "Chromium"); + instance_create_info.applicationInfo.apiVersion = XR_CURRENT_API_VERSION; // xrCreateInstance validates the list of extensions and returns // XR_ERROR_EXTENSION_NOT_PRESENT if an extension is not supported, @@ -683,7 +684,7 @@ return false; XrSpaceLocation location = {XR_TYPE_SPACE_LOCATION}; - if (FAILED(xrLocateSpace(stage_space_, local_space_, + if (FAILED(xrLocateSpace(local_space_, stage_space_, frame_state_.predictedDisplayTime, &location)) || !(location.locationFlags & XR_SPACE_LOCATION_ORIENTATION_VALID_BIT) || !(location.locationFlags & XR_SPACE_LOCATION_POSITION_VALID_BIT)) {
diff --git a/device/vr/openxr/test/fake_openxr_impl_api.cc b/device/vr/openxr/test/fake_openxr_impl_api.cc index a0cebe2..0c26859c 100644 --- a/device/vr/openxr/test/fake_openxr_impl_api.cc +++ b/device/vr/openxr/test/fake_openxr_impl_api.cc
@@ -121,6 +121,9 @@ XrInstance* instance) { DLOG(INFO) << __FUNCTION__; + RETURN_IF(create_info->applicationInfo.apiVersion != XR_CURRENT_API_VERSION, + XR_ERROR_API_VERSION_UNSUPPORTED, "apiVersion unsupported"); + RETURN_IF(create_info->type != XR_TYPE_INSTANCE_CREATE_INFO, XR_ERROR_VALIDATION_FAILURE, "XrInstanceCreateInfo type invalid");
diff --git a/device/vr/public/mojom/vr_service.mojom b/device/vr/public/mojom/vr_service.mojom index 54599020..f8d5c39 100644 --- a/device/vr/public/mojom/vr_service.mojom +++ b/device/vr/public/mojom/vr_service.mojom
@@ -294,7 +294,7 @@ // detected in the real world by the underlying system. struct XRPlaneData { // Unique (per session) identifier of the plane. - int32 id; + uint32 id; // Plane orientation relative to gravity. XRPlaneOrientation orientation; @@ -314,7 +314,7 @@ // present in updated_planes_data. struct XRPlaneDetectionData { // Array with ids of all tracked planes. - array<int32> all_planes_ids; + array<uint32> all_planes_ids; // Array with plane data for all updated planes. Plane is considered updated // if its position or polygon has changed. Updated planes are always a subset @@ -329,7 +329,7 @@ // evolves. struct XRAnchorData { // Unique (per session) identifier of the anchor. - int32 id; + uint32 id; // Pose of the anchor. VRPose pose; @@ -341,7 +341,7 @@ // will not be present in updated_anchors_data. struct XRAnchorsData { // Array with ids of all tracked anchors. - array<int32> all_anchors_ids; + array<uint32> all_anchors_ids; // Array with anchor data for all updated anchors. Updated anchors are always // a subset of all anchors (i.e. for each anchor found in @@ -478,7 +478,7 @@ // |result| will contain status code of the request. |anchor_id| will be valid // only if the |result| is SUCCESS. CreateAnchor(VRPose anchor_pose) => (CreateAnchorResult result, - int32 anchor_id); + uint32 anchor_id); // TODO(https://crbug.com/657632): Switch anchor_id to nullable integer once // that's available. This will allow us to remove CreateAnchorResult if we're // not interested in obtaining detailed error information from the device. @@ -486,14 +486,14 @@ // Issues a request to create an anchor attached to a plane. // |result| will contain status code of the request. |anchor_id| will be valid // only if the |result| is SUCCESS. - CreatePlaneAnchor(VRPose anchor_pose, int32 plane_id) => - (CreateAnchorResult result, int32 anchor_id); + CreatePlaneAnchor(VRPose anchor_pose, uint32 plane_id) => + (CreateAnchorResult result, uint32 anchor_id); // TODO(https://crbug.com/657632): Ditto - make anchor_id a nullable integer.. // Detaches an existing anchor. The |anchor_id| must be a valid id of an // anchor created by one of the CreateAnchor calls, otherwise the call will be // ignored. - DetachAnchor(int32 anchor_id); + DetachAnchor(uint32 anchor_id); }; // Provides a mechanism for a channel to plumb up any button click events
diff --git a/device/vr/windows_mixed_reality/mixed_reality_renderloop.cc b/device/vr/windows_mixed_reality/mixed_reality_renderloop.cc index bbea360..38d41100 100644 --- a/device/vr/windows_mixed_reality/mixed_reality_renderloop.cc +++ b/device/vr/windows_mixed_reality/mixed_reality_renderloop.cc
@@ -271,7 +271,11 @@ // the device of the correct values before it sends the initial info to the // renderer. The frame must be submitted because WMR requires frames to be // submitted in the order they're created. - GetNextFrameData(); + UpdateWMRDataForNextFrame(); + UpdateDisplayInfo(); + main_thread_task_runner_->PostTask( + FROM_HERE, + base::BindOnce(on_display_info_changed_, current_display_info_.Clone())); return SubmitCompositedFrame(); }
diff --git a/docs/mojo_ipc_conversion.md b/docs/mojo_ipc_conversion.md index adb6cb2..6a16d41 100644 --- a/docs/mojo_ipc_conversion.md +++ b/docs/mojo_ipc_conversion.md
@@ -217,13 +217,13 @@ - If the message is sent from a renderer to the browser: - If an existing interface is bound by `RenderFrameHostImpl` and acquired either via `RenderFrame::GetRemoteInterfaces` or - `RenderFrame::GetDocumentInterfaceBroker` and the interface seems + `RenderFrame::GetBrowserInterfaceBroker` and the interface seems to be a good fit for this message, add the equivalent Mojo message to that interface. - - If no such interface exists, consider adding one and exposing it - via a new getter method on `DocumentInterfaceBroker`. See the + - If no such interface exists, consider adding one and registering it + with `RenderFrameHostImpl`'s `BrowserInterfaceBroker`. See the [simple example](/docs/mojo_and_services.md#Example_Defining-a-New-Frame-Interface) - earlier in this document. + in the "Intro to Mojo & Services" document. - If the message is sent from the browser to a renderer, consider adding a Mojo equivalent to the `content.mojom.Frame` interface defined
diff --git a/extensions/browser/extension_function_histogram_value.h b/extensions/browser/extension_function_histogram_value.h index 9f5849b..69d71d8 100644 --- a/extensions/browser/extension_function_histogram_value.h +++ b/extensions/browser/extension_function_histogram_value.h
@@ -1444,6 +1444,7 @@ AUTOTESTPRIVATE_GETARCSTARTTIME = 1381, AUTOTESTPRIVATE_SETOVERVIEWMODESTATE = 1382, AUTOTESTPRIVATE_TAKESCREENSHOTFORDISPLAY = 1383, + AUTOFILLPRIVATE_SETCREDITCARDFIDOAUTHENABLEDSTATE = 1384, // Last entry: Add new entries above, then run: // python tools/metrics/histograms/update_extension_histograms.py ENUM_BOUNDARY
diff --git a/extensions/common/manifest_handlers/csp_info.cc b/extensions/common/manifest_handlers/csp_info.cc index 2479523..c3da391 100644 --- a/extensions/common/manifest_handlers/csp_info.cc +++ b/extensions/common/manifest_handlers/csp_info.cc
@@ -125,8 +125,8 @@ // static const std::string* CSPInfo::GetIsolatedWorldCSP(const Extension& extension) { - // TODO(crbug.com/914224): This should be only called for extensions which can - // have isolated worlds. Figure out the case of TYPE_USER_SCRIPT and add + // TODO(crbug.com/1005978): This should be only called for extensions which + // can have isolated worlds. Figure out the case of TYPE_USER_SCRIPT and add // DCHECK(csp_info). CSPInfo* csp_info = static_cast<CSPInfo*>( extension.GetManifestData(keys::kContentSecurityPolicy)); @@ -163,19 +163,24 @@ // The "content_security_policy" manifest key can either be a string or a // dictionary of the format // "content_security_policy" : { - // "extension_pages" : "" + // "extension_pages": "", + // "sandbox": "", + // "isolated_world": "" // } const base::Value* csp = GetManifestPath(extension, key); + const int kManifestVersion3 = 3; - // TODO(crbug.com/914224): Remove the channel check once the support for the - // dictionary key is launched to other channels. + // TODO(crbug.com/914224): Remove the channel check once support for isolated + // world CSP is implemenented. bool csp_dictionary_supported = extension->GetType() == Manifest::TYPE_EXTENSION && - GetCurrentChannel() == version_info::Channel::UNKNOWN; + (extension->manifest_version() >= kManifestVersion3 || + GetCurrentChannel() == version_info::Channel::UNKNOWN); if (csp_dictionary_supported) { - // CSP key as dictionary is mandatory for manifest v3 extensions. - if (extension->manifest_version() == 3) { + // CSP key as dictionary is mandatory for manifest v3 (and above) + // extensions. + if (extension->manifest_version() >= kManifestVersion3) { if (csp && !csp->is_dict()) { *error = GetInvalidManifestKeyError(key); return false; @@ -204,14 +209,6 @@ bool CSPHandler::ParseCSPDictionary(Extension* extension, base::string16* error) { - if (!ParseExtensionPagesCSP( - extension, error, keys::kContentSecurityPolicy_ExtensionPagesPath, - true /* secure_only */, - GetManifestPath(extension, - keys::kContentSecurityPolicy_ExtensionPagesPath))) { - return false; - } - // keys::kSandboxedPagesCSP shouldn't be used when using // keys::kContentSecurityPolicy as a dictionary. if (extension->manifest()->HasPath(keys::kSandboxedPagesCSP)) { @@ -219,7 +216,12 @@ return false; } - return ParseSandboxCSP( + return ParseExtensionPagesCSP( + extension, error, keys::kContentSecurityPolicy_ExtensionPagesPath, + true /* secure_only */, + GetManifestPath( + extension, keys::kContentSecurityPolicy_ExtensionPagesPath)) && + ParseSandboxCSP( extension, error, keys::kContentSecurityPolicy_SandboxedPagesPath, GetManifestPath( extension, keys::kContentSecurityPolicy_SandboxedPagesPath)) && @@ -376,7 +378,8 @@ } bool CSPHandler::AlwaysParseForType(Manifest::Type type) const { - // TODO(karandeepb): Check if TYPE_USER_SCRIPT needs to be included here. + // TODO(crbug.com/1005978): Check if TYPE_USER_SCRIPT needs to be included + // here. return type == Manifest::TYPE_PLATFORM_APP || type == Manifest::TYPE_EXTENSION || type == Manifest::TYPE_LEGACY_PACKAGED_APP;
diff --git a/extensions/common/manifest_handlers/csp_info.h b/extensions/common/manifest_handlers/csp_info.h index ec7812c..b6220770 100644 --- a/extensions/common/manifest_handlers/csp_info.h +++ b/extensions/common/manifest_handlers/csp_info.h
@@ -64,8 +64,8 @@ CSPHandler(); ~CSPHandler() override; + // ManifestHandler override: bool Parse(Extension* extension, base::string16* error) override; - bool AlwaysParseForType(Manifest::Type type) const override; private: // Parses the "content_security_policy" dictionary in the manifest. @@ -103,6 +103,8 @@ // Helper to set the sandbox content security policy manifest data. void SetSandboxCSP(Extension* extension, std::string sandbox_csp); + // ManifestHandler overrides: + bool AlwaysParseForType(Manifest::Type type) const override; base::span<const char* const> Keys() const override; DISALLOW_COPY_AND_ASSIGN(CSPHandler);
diff --git a/extensions/common/manifest_handlers/csp_info_unittest.cc b/extensions/common/manifest_handlers/csp_info_unittest.cc index 94b8871..8ba33684 100644 --- a/extensions/common/manifest_handlers/csp_info_unittest.cc +++ b/extensions/common/manifest_handlers/csp_info_unittest.cc
@@ -266,8 +266,6 @@ // key is mandatory for manifest v3 extensions and that defaults are applied // correctly. TEST_F(CSPInfoUnitTest, CSPDictionaryMandatoryForV3) { - ScopedCurrentChannel channel(version_info::Channel::UNKNOWN); - LoadAndExpectError("csp_invalid_type_v3.json", GetInvalidManifestKeyError(keys::kContentSecurityPolicy));
diff --git a/ios/build/bots/scripts/test_runner.py b/ios/build/bots/scripts/test_runner.py index 635afc22..b444ff924 100644 --- a/ios/build/bots/scripts/test_runner.py +++ b/ios/build/bots/scripts/test_runner.py
@@ -9,6 +9,7 @@ import sys import collections +import distutils.version import glob import json import logging @@ -147,6 +148,33 @@ 'Sharding has not been implemented!') +def get_device_ios_version(udid): + """Gets device iOS version. + + Args: + udid: (str) iOS device UDID. + + Returns: + Device UDID. + """ + return subprocess.check_output(['ideviceinfo', + '--udid', udid, + '-k', 'ProductVersion']).strip() + + +def is_iOS13_or_higher_device(udid): + """Checks whether device with udid has iOS 13.0+. + + Args: + udid: (str) iOS device UDID. + + Returns: + True for iOS 13.0+ devices otherwise false. + """ + return (distutils.version.LooseVersion(get_device_ios_version(udid)) >= + distutils.version.LooseVersion('13.0')) + + def terminate_process(proc): """Terminates the process. @@ -334,6 +362,24 @@ } +def get_xctest_from_app(app): + """Gets xctest path for an app. + + Args: + app: (str) A path to an app. + + Returns: + The xctest path. + """ + plugins_dir = os.path.join(app, 'PlugIns') + if not os.path.exists(plugins_dir): + return None + for plugin in os.listdir(plugins_dir): + if plugin.endswith('.xctest'): + return os.path.join(plugins_dir, plugin) + return None + + def get_test_names(app_path): """Gets list of tests from test app. @@ -456,6 +502,9 @@ self.test_args = test_args or [] self.test_cases = test_cases or [] self.xctest_path = '' + # TODO(crbug.com/1006881): Separate "running style" from "parser style" + # for XCtests and Gtests. + self.xctest = xctest self.test_results = {} self.test_results['version'] = 3 @@ -464,7 +513,7 @@ # This will be overwritten when the tests complete successfully. self.test_results['interrupted'] = True - if xctest: + if self.xctest: plugins_dir = os.path.join(self.app_path, 'PlugIns') if not os.path.exists(plugins_dir): raise PlugInsNotFoundError(plugins_dir) @@ -583,7 +632,7 @@ GTestResult instance. """ result = gtest_utils.GTestResult(cmd) - if self.xctest_path: + if self.xctest: parser = xctest_utils.XCTestLogParser() else: parser = gtest_utils.GTestLogParser() @@ -627,7 +676,7 @@ returncode = proc.returncode - if self.xctest_path and parser.SystemAlertPresent(): + if self.xctest and parser.SystemAlertPresent(): raise SystemAlertPresentError() LOGGER.debug('Processing test results.') @@ -670,7 +719,7 @@ try: # XCTests cannot currently be resumed at the next test case. - while not self.xctest_path and result.crashed and result.crashed_test: + while not self.xctest and result.crashed and result.crashed_test: # If the app crashes during a specific test case, then resume at the # next test case. This is achieved by filtering out every test case # which has already run. @@ -1517,7 +1566,14 @@ self.udid = subprocess.check_output(['idevice_id', '--list']).rstrip() if len(self.udid.splitlines()) != 1: raise DeviceDetectionError(self.udid) - if xctest: + + is_iOS13 = is_iOS13_or_higher_device(self.udid) + + # GTest-based unittests are invoked via XCTest on iOS 13+ devices + # but produce GTest-style log output that is parsed with a GTestLogParser. + if xctest or is_iOS13: + if is_iOS13: + self.xctest_path = get_xctest_from_app(self.app_path) self.xctestrun_file = tempfile.mkstemp()[1] self.xctestrun_data = { 'TestTargetName': { @@ -1629,6 +1685,12 @@ self.xctestrun_data['TestTargetName'].update( {'OnlyTestIdentifiers': test_filter}) + def get_command_line_args_xctest_unittests(self, filtered_tests): + command_line_args = ['--enable-run-ios-unittests-with-xctest'] + if filtered_tests: + command_line_args.append('--gtest_filter=%s' % filtered_tests) + return command_line_args + def get_launch_command(self, test_filter=None, invert=False): """Returns the command that can be used to launch the test app. @@ -1641,13 +1703,24 @@ A list of strings forming the command to launch the test. """ if self.xctest_path: - self.set_xctest_filters(test_filter, invert) if self.env_vars: self.xctestrun_data['TestTargetName'].update( {'EnvironmentVariables': self.env_vars}) - if self.test_args: + + command_line_args = self.test_args + + if self.xctest: + self.set_xctest_filters(test_filter, invert) + else: + filtered_tests = [] + if test_filter: + filtered_tests = get_gtest_filter(test_filter, invert=invert) + command_line_args.append( + self.get_command_line_args_xctest_unittests(filtered_tests)) + + if command_line_args: self.xctestrun_data['TestTargetName'].update( - {'CommandLineArguments': self.test_args}) + {'CommandLineArguments': command_line_args}) plistlib.writePlist(self.xctestrun_data, self.xctestrun_file) return [ 'xcodebuild',
diff --git a/ios/build/bots/scripts/test_runner_test.py b/ios/build/bots/scripts/test_runner_test.py index f468dc9..8dfa7ca 100755 --- a/ios/build/bots/scripts/test_runner_test.py +++ b/ios/build/bots/scripts/test_runner_test.py
@@ -11,6 +11,7 @@ import mock import os import subprocess +import tempfile import unittest import test_runner @@ -131,6 +132,7 @@ self.mock(os.path, 'exists', lambda _: True) self.mock(test_runner.TestRunner, 'set_sigterm_handler', lambda self, handler: 0) + self.mock(os, 'listdir', lambda _: []) def test_app_not_found(self): """Ensures AppNotFoundError is raised.""" @@ -202,6 +204,7 @@ 'xcode-version', 'xcode-build', 'out-dir', + xctest=True, ) with self.assertRaises(test_runner.AppLaunchError): tr.launch() @@ -229,6 +232,7 @@ 'xcode-version', 'xcode-build', 'out-dir', + xctest=True, ) self.mock(test_runner, 'shard_xctest', shard_xctest) self.mock(test_runner.SimulatorTestRunner, 'run_tests', run_tests) @@ -254,6 +258,7 @@ 'xcode-version', 'xcode-build', 'out-dir', + xctest=True, ) tr.xctest_path = 'fake.xctest' cmd = ['echo', 'System alert view is present, so skipping all tests!'] @@ -532,6 +537,8 @@ lambda _: 'fake-bundle-id') self.mock(os.path, 'abspath', lambda path: '/abs/path/to/%s' % path) self.mock(os.path, 'exists', lambda _: True) + self.mock(os, 'listdir', lambda _: []) + self.mock(tempfile, 'mkstemp', lambda: '/tmp/tmp_file') self.tr = test_runner.DeviceTestRunner( 'fake-app',
diff --git a/ios/chrome/app/main_controller.mm b/ios/chrome/app/main_controller.mm index 36a5e887..026f93f 100644 --- a/ios/chrome/app/main_controller.mm +++ b/ios/chrome/app/main_controller.mm
@@ -2162,9 +2162,9 @@ BOOL showActivityIndicator = NO; if (@available(iOS 13, *)) { - // TODO(crbug.com/632772): Visited links don't clearing doesn't require - // disabling web usage with iOS 13. Stop disabling web usage once iOS 12 - // is not supported. + // TODO(crbug.com/632772): Visited links clearing doesn't require disabling + // web usage with iOS 13. Stop disabling web usage once iOS 12 is not + // supported. showActivityIndicator = disableWebUsageDuringRemoval; disableWebUsageDuringRemoval = NO; }
diff --git a/ios/chrome/browser/ui/authentication/signed_in_accounts_view_controller.mm b/ios/chrome/browser/ui/authentication/signed_in_accounts_view_controller.mm index 180e261..7867755 100644 --- a/ios/chrome/browser/ui/authentication/signed_in_accounts_view_controller.mm +++ b/ios/chrome/browser/ui/authentication/signed_in_accounts_view_controller.mm
@@ -202,10 +202,14 @@ if (!browserState || browserState->IsOffTheRecord()) { return NO; } - AuthenticationService* authService = - AuthenticationServiceFactory::GetForBrowserState(browserState); - return !gSignedInAccountsViewControllerIsShown && - authService->IsAuthenticated() && authService->HaveAccountsChanged(); + // Temporary fix for regression for http://crbug.com/1006744: Disable showing + // the signed-in account modal dialog. + // + // AuthenticationService* authService = + // AuthenticationServiceFactory::GetForBrowserState(browserState); + // return !gSignedInAccountsViewControllerIsShown && + // authService->IsAuthenticated() && authService->HaveAccountsChanged(); + return NO; } #pragma mark Initialization
diff --git a/ios/chrome/browser/ui/authentication/signed_in_accounts_view_controller_unittest.mm b/ios/chrome/browser/ui/authentication/signed_in_accounts_view_controller_unittest.mm index 448a1fc..a5493a1 100644 --- a/ios/chrome/browser/ui/authentication/signed_in_accounts_view_controller_unittest.mm +++ b/ios/chrome/browser/ui/authentication/signed_in_accounts_view_controller_unittest.mm
@@ -59,8 +59,10 @@ // Tests that the signed in accounts view should be presented when the accounts // have changed. +// Temporary disabled for regression for http://crbug.com/1006744: Disable +// showing the signed-in account modal dialog. TEST_F(SignedInAccountsViewControllerTest, - ShouldBePresentedForBrowserStateNecessary) { + DISABLED_ShouldBePresentedForBrowserStateNecessary) { auth_service_->SetHaveAccountsChanged(true); EXPECT_TRUE([SignedInAccountsViewController shouldBePresentedForBrowserState:browser_state_.get()]);
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 3487087..e53fde7 100644 --- a/ios/chrome/browser/ui/browser_view/browser_view_controller.mm +++ b/ios/chrome/browser/ui/browser_view/browser_view_controller.mm
@@ -4389,8 +4389,8 @@ targetDeviceName:[command targetDeviceName]]; } -- (void)showActivityOverlay:(BOOL)shown { - if (!shown) { +- (void)showActivityOverlay:(BOOL)show { + if (!show) { [self.activityOverlayCoordinator stop]; self.activityOverlayCoordinator = nil; } else if (!self.activityOverlayCoordinator) {
diff --git a/ios/chrome/browser/ui/commands/browser_commands.h b/ios/chrome/browser/ui/commands/browser_commands.h index c2c3ae48..4f8e420 100644 --- a/ios/chrome/browser/ui/commands/browser_commands.h +++ b/ios/chrome/browser/ui/commands/browser_commands.h
@@ -112,9 +112,9 @@ // Sends the tab to another of the user's devices using the data in |command|. - (void)sendTabToSelf:(SendTabToSelfCommand*)command; -// Show/Hide the activity indicator overlay that appears over the view to +// Shows/Hides the activity indicator overlay that appears over the view to // prevent interaction with the web page. -- (void)showActivityOverlay:(BOOL)shown; +- (void)showActivityOverlay:(BOOL)show; @end
diff --git a/ios/web/js_messaging/web_frames_manager_impl.mm b/ios/web/js_messaging/web_frames_manager_impl.mm index a3207b11..8cfbed6 100644 --- a/ios/web/js_messaging/web_frames_manager_impl.mm +++ b/ios/web/js_messaging/web_frames_manager_impl.mm
@@ -53,7 +53,7 @@ RemoveAllWebFrames(); // TODO(crbug.com/956516): ScriptMessageHandlers should all be removed // manually using |removeScriptMessageHandlerForName|, however this is not - // possible because of the cases where the webviewconfiguration is purged, + // possible because of the cases where the WKWebViewConfiguration is purged, // in these cases the message router is deleted and it will not have // message handlers for the web view. [message_router removeAllScriptMessageHandlersForWebView:old_web_view];
diff --git a/ios/web/public/web_state/web_state.h b/ios/web/public/web_state/web_state.h new file mode 100644 index 0000000..f19a68b --- /dev/null +++ b/ios/web/public/web_state/web_state.h
@@ -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. + +#ifndef IOS_WEB_PUBLIC_WEB_STATE_WEB_STATE_H_ +#define IOS_WEB_PUBLIC_WEB_STATE_WEB_STATE_H_ + +// TODO(crbug.com/942244): Remove this header after downstream code +// stopped including ios/web/public/web_state/web_state.h + +#import "ios/web/public/web_state.h" + +#endif // IOS_WEB_PUBLIC_WEB_STATE_WEB_STATE_H_
diff --git a/ios/web/public/web_state/web_state_observer.h b/ios/web/public/web_state/web_state_observer.h new file mode 100644 index 0000000..7e200daa --- /dev/null +++ b/ios/web/public/web_state/web_state_observer.h
@@ -0,0 +1,13 @@ +// Copyright 2014 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#ifndef IOS_WEB_PUBLIC_WEB_STATE_WEB_STATE_OBSERVER_H_ +#define IOS_WEB_PUBLIC_WEB_STATE_WEB_STATE_OBSERVER_H_ + +// TODO(crbug.com/942244): Remove this header after downstream code +// stopped including ios/web/public/web_state/web_state.h + +#include "ios/web/public/web_state_observer.h" + +#endif // IOS_WEB_PUBLIC_WEB_STATE_WEB_STATE_OBSERVER_H_
diff --git a/media/BUILD.gn b/media/BUILD.gn index f1bc9679..50361c6 100644 --- a/media/BUILD.gn +++ b/media/BUILD.gn
@@ -20,13 +20,13 @@ flags = [ "ALTERNATE_CDM_STORAGE_ID_KEY=\"$alternate_cdm_storage_id_key\"", "CDM_PLATFORM_SPECIFIC_PATH=\"$cdm_platform_specific_path\"", - "ENABLE_AC3_EAC3_AUDIO_DEMUXING=$enable_ac3_eac3_audio_demuxing", + "ENABLE_PLATFORM_AC3_EAC3_AUDIO=$enable_platform_ac3_eac3_audio", "ENABLE_CBCS_ENCRYPTION_SCHEME=$enable_cbcs_encryption_scheme", "ENABLE_CDM_HOST_VERIFICATION=$enable_cdm_host_verification", "ENABLE_CDM_STORAGE_ID=$enable_cdm_storage_id", "ENABLE_DAV1D_DECODER=$enable_dav1d_decoder", "ENABLE_AV1_DECODER=$enable_av1_decoder", - "ENABLE_DOLBY_VISION_DEMUXING=$enable_dolby_vision_demuxing", + "ENABLE_PLATFORM_DOLBY_VISION=$enable_platform_dolby_vision", "ENABLE_FFMPEG=$media_use_ffmpeg", "ENABLE_FFMPEG_VIDEO_DECODERS=$enable_ffmpeg_video_decoders", "ENABLE_PLATFORM_HEVC=$enable_platform_hevc", @@ -36,7 +36,7 @@ "ENABLE_LOGGING_OVERRIDE=$enable_logging_override", "ENABLE_MEDIA_REMOTING=$enable_media_remoting", "ENABLE_MEDIA_REMOTING_RPC=$enable_media_remoting_rpc", - "ENABLE_MPEG_H_AUDIO_DEMUXING=$enable_mpeg_h_audio_demuxing", + "ENABLE_PLATFORM_MPEG_H_AUDIO=$enable_platform_mpeg_h_audio", "ENABLE_MSE_MPEG2TS_STREAM_PARSER=$enable_mse_mpeg2ts_stream_parser", "USE_PROPRIETARY_CODECS=$proprietary_codecs", ]
diff --git a/media/audio/BUILD.gn b/media/audio/BUILD.gn index b27ebee..de4f3ceb 100644 --- a/media/audio/BUILD.gn +++ b/media/audio/BUILD.gn
@@ -19,6 +19,17 @@ } } +if (is_android) { + generate_stubs("aaudio_stubs") { + extra_header = "android/aaudio_stub_header.fragment" + sigs = [ "android/aaudio.sigs" ] + output_name = "android/aaudio_stubs" + deps = [ + "//base", + ] + } +} + config("platform_config") { defines = [] if (is_chromecast) { @@ -217,6 +228,8 @@ if (is_android) { sources += [ + "android/aaudio_output.cc", + "android/aaudio_output.h", "android/audio_manager_android.cc", "android/audio_manager_android.h", "android/audio_track_output_stream.cc", @@ -231,7 +244,10 @@ "android/opensles_wrapper.cc", ] - deps += [ "//media/base/android:media_jni_headers" ] + deps += [ + ":aaudio_stubs", + "//media/base/android:media_jni_headers", + ] } if (is_linux) {
diff --git a/media/audio/android/aaudio.sigs b/media/audio/android/aaudio.sigs new file mode 100644 index 0000000..2d8e9e4 --- /dev/null +++ b/media/audio/android/aaudio.sigs
@@ -0,0 +1,29 @@ +// 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. + +//------------------------------------------------ +// Functions from AAudio used in media code. +//------------------------------------------------ + +const char * AAudio_convertResultToText(aaudio_result_t returnCode); +aaudio_result_t AAudio_createStreamBuilder(AAudioStreamBuilder** builder); +void AAudioStreamBuilder_setDeviceId(AAudioStreamBuilder* builder, int32_t deviceId); +void AAudioStreamBuilder_setSampleRate(AAudioStreamBuilder* builder, int32_t sampleRate); +void AAudioStreamBuilder_setChannelCount(AAudioStreamBuilder* builder, int32_t channelCount); +void AAudioStreamBuilder_setSamplesPerFrame(AAudioStreamBuilder* builder, int32_t samplesPerFrame); +void AAudioStreamBuilder_setFormat(AAudioStreamBuilder* builder, aaudio_format_t format); +void AAudioStreamBuilder_setDirection(AAudioStreamBuilder* builder, aaudio_direction_t direction); +void AAudioStreamBuilder_setBufferCapacityInFrames(AAudioStreamBuilder* builder, int32_t numFrames); +void AAudioStreamBuilder_setPerformanceMode(AAudioStreamBuilder* builder, aaudio_performance_mode_t mode); +void AAudioStreamBuilder_setFramesPerDataCallback(AAudioStreamBuilder* builder, int32_t numFrames); +void AAudioStreamBuilder_setUsage(AAudioStreamBuilder* builder, aaudio_usage_t usage); +void AAudioStreamBuilder_setDataCallback(AAudioStreamBuilder* builder, AAudioStream_dataCallback callback, void *userData); +void AAudioStreamBuilder_setErrorCallback(AAudioStreamBuilder* builder, AAudioStream_errorCallback callback, void *userData); +aaudio_result_t AAudioStreamBuilder_openStream(AAudioStreamBuilder* builder, AAudioStream** stream); +aaudio_result_t AAudioStreamBuilder_delete(AAudioStreamBuilder* builder); +aaudio_result_t AAudioStream_close(AAudioStream* stream); +aaudio_result_t AAudioStream_requestStart(AAudioStream* stream); +aaudio_result_t AAudioStream_requestStop(AAudioStream* stream); +aaudio_result_t AAudioStream_getTimestamp(AAudioStream* stream, clockid_t clockid, int64_t *framePosition, int64_t *timeNanoseconds); +int64_t AAudioStream_getFramesWritten(AAudioStream* stream); \ No newline at end of file
diff --git a/media/audio/android/aaudio_output.cc b/media/audio/android/aaudio_output.cc new file mode 100644 index 0000000..94d854e --- /dev/null +++ b/media/audio/android/aaudio_output.cc
@@ -0,0 +1,234 @@ +// 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 "media/audio/android/aaudio_output.h" + +#include "base/logging.h" +#include "media/audio/android/aaudio_stubs.h" +#include "media/audio/android/audio_manager_android.h" +#include "media/base/audio_bus.h" + +namespace media { + +static aaudio_data_callback_result_t OnAudioDataRequestedCallback( + AAudioStream* stream, + void* user_data, + void* audio_data, + int32_t num_frames) { + AAudioOutputStream* output_stream = + reinterpret_cast<AAudioOutputStream*>(user_data); + return output_stream->OnAudioDataRequested(audio_data, num_frames); +} + +static void OnStreamErrorCallback(AAudioStream* stream, + void* user_data, + aaudio_result_t error) { + AAudioOutputStream* output_stream = + reinterpret_cast<AAudioOutputStream*>(user_data); + output_stream->OnStreamError(error); +} + +AAudioOutputStream::AAudioOutputStream(AudioManagerAndroid* manager, + const AudioParameters& params, + aaudio_usage_t usage) + : audio_manager_(manager), + params_(params), + usage_(usage), + performance_mode_(AAUDIO_PERFORMANCE_MODE_NONE), + ns_per_frame_(base::Time::kNanosecondsPerSecond / + static_cast<double>(params.sample_rate())) { + DCHECK(manager); + DCHECK(params.IsValid()); + + if (AudioManagerAndroid::SupportsPerformanceModeForOutput()) { + if (params.latency_tag() == AudioLatency::LATENCY_PLAYBACK) + performance_mode_ = AAUDIO_PERFORMANCE_MODE_POWER_SAVING; + else if (params.latency_tag() == AudioLatency::LATENCY_RTC) + performance_mode_ = AAUDIO_PERFORMANCE_MODE_LOW_LATENCY; + } +} + +AAudioOutputStream::~AAudioOutputStream() { + DCHECK_CALLED_ON_VALID_THREAD(thread_checker_); +} + +void AAudioOutputStream::Flush() {} + +bool AAudioOutputStream::Open() { + DCHECK_CALLED_ON_VALID_THREAD(thread_checker_); + + AAudioStreamBuilder* builder; + auto result = AAudio_createStreamBuilder(&builder); + if (AAUDIO_OK != result) + return false; + + // Parameters + AAudioStreamBuilder_setDirection(builder, AAUDIO_DIRECTION_OUTPUT); + AAudioStreamBuilder_setSampleRate(builder, params_.sample_rate()); + AAudioStreamBuilder_setChannelCount(builder, params_.channels()); + AAudioStreamBuilder_setFormat(builder, AAUDIO_FORMAT_PCM_FLOAT); + AAudioStreamBuilder_setUsage(builder, usage_); + AAudioStreamBuilder_setPerformanceMode(builder, performance_mode_); + AAudioStreamBuilder_setBufferCapacityInFrames(builder, + params_.frames_per_buffer()); + AAudioStreamBuilder_setFramesPerDataCallback(builder, + params_.frames_per_buffer()); + + // Callbacks + AAudioStreamBuilder_setDataCallback(builder, OnAudioDataRequestedCallback, + this); + AAudioStreamBuilder_setErrorCallback(builder, OnStreamErrorCallback, this); + + result = AAudioStreamBuilder_openStream(builder, &aaudio_stream_); + + AAudioStreamBuilder_delete(builder); + + if (AAUDIO_OK != result) + return false; + + audio_bus_ = AudioBus::Create(params_); + + return true; +} + +void AAudioOutputStream::Close() { + DCHECK_CALLED_ON_VALID_THREAD(thread_checker_); + + Stop(); + if (aaudio_stream_) { + const auto result = AAudioStream_close(aaudio_stream_); + if (result != AAUDIO_OK) { + DLOG(ERROR) << "Failed to close audio stream, result: " + << AAudio_convertResultToText(result); + } + } + + // Note: This must be last, it will delete |this|. + audio_manager_->ReleaseOutputStream(this); +} + +void AAudioOutputStream::Start(AudioSourceCallback* callback) { + DCHECK_CALLED_ON_VALID_THREAD(thread_checker_); + DCHECK(aaudio_stream_); + + { + base::AutoLock al(lock_); + DCHECK(!callback_); + callback_ = callback; + } + + auto result = AAudioStream_requestStart(aaudio_stream_); + if (result != AAUDIO_OK) { + DLOG(ERROR) << "Failed to start audio stream, result: " + << AAudio_convertResultToText(result); + + // Lock is required in case a previous asynchronous requestStop() still has + // not completed by the time we reach this point. + base::AutoLock al(lock_); + callback_->OnError(); + callback_ = nullptr; + } +} + +void AAudioOutputStream::Stop() { + DCHECK_CALLED_ON_VALID_THREAD(thread_checker_); + + base::AutoLock al(lock_); + if (!callback_ || !aaudio_stream_) + return; + + // Note: This call is asynchronous, so we must clear |callback_| under lock + // below to ensure no further calls occur after Stop(). + auto result = AAudioStream_requestStop(aaudio_stream_); + + if (result != AAUDIO_OK) { + DLOG(ERROR) << "Failed to stop audio stream, result: " + << AAudio_convertResultToText(result); + callback_->OnError(); + } + + callback_ = nullptr; +} + +base::TimeDelta AAudioOutputStream::GetDelay(base::TimeTicks delay_timestamp) { + // Get the time that a known audio frame was presented for playing. + int64_t existing_frame_index; + int64_t existing_frame_pts; + auto result = + AAudioStream_getTimestamp(aaudio_stream_, CLOCK_MONOTONIC, + &existing_frame_index, &existing_frame_pts); + + if (result != AAUDIO_OK) { + DLOG(ERROR) << "Failed to get audio latency, result: " + << AAudio_convertResultToText(result); + return base::TimeDelta(); + } + + // Calculate the number of frames between our known frame and the write index. + const int64_t frame_index_delta = + AAudioStream_getFramesWritten(aaudio_stream_) - existing_frame_index; + + // Calculate the time which the next frame will be presented. + const base::TimeDelta next_frame_pts = base::TimeDelta::FromNanosecondsD( + existing_frame_pts + frame_index_delta * ns_per_frame_); + + // Calculate the latency between write time and presentation time. + return next_frame_pts - (delay_timestamp - base::TimeTicks()); +} + +aaudio_data_callback_result_t AAudioOutputStream::OnAudioDataRequested( + void* audio_data, + int32_t num_frames) { + // TODO(tguilbert): This can be downgraded to a DCHECK after we've launched. + CHECK_EQ(num_frames, audio_bus_->frames()); + + base::AutoLock al(lock_); + if (!callback_) + return AAUDIO_CALLBACK_RESULT_STOP; + + const base::TimeTicks delay_timestamp = base::TimeTicks::Now(); + const base::TimeDelta delay = GetDelay(delay_timestamp); + + const int frames_filled = + callback_->OnMoreData(delay, delay_timestamp, 0, audio_bus_.get()); + + audio_bus_->Scale(muted_ ? 0.0 : volume_); + audio_bus_->ToInterleaved<Float32SampleTypeTraits>( + frames_filled, reinterpret_cast<float*>(audio_data)); + return AAUDIO_CALLBACK_RESULT_CONTINUE; +} + +void AAudioOutputStream::OnStreamError(aaudio_result_t error) { + base::AutoLock al(lock_); + if (callback_) + callback_->OnError(); +} + +void AAudioOutputStream::SetVolume(double volume) { + DCHECK_CALLED_ON_VALID_THREAD(thread_checker_); + + double volume_override = 0; + if (audio_manager_->HasOutputVolumeOverride(&volume_override)) + volume = volume_override; + + if (volume < 0.0 || volume > 1.0) + return; + + base::AutoLock al(lock_); + volume_ = volume; +} + +void AAudioOutputStream::GetVolume(double* volume) { + DCHECK_CALLED_ON_VALID_THREAD(thread_checker_); + base::AutoLock al(lock_); + *volume = volume_; +} + +void AAudioOutputStream::SetMute(bool muted) { + DCHECK_CALLED_ON_VALID_THREAD(thread_checker_); + + base::AutoLock al(lock_); + muted_ = muted; +} +} // namespace media \ No newline at end of file
diff --git a/media/audio/android/aaudio_output.h b/media/audio/android/aaudio_output.h new file mode 100644 index 0000000..c4a81208 --- /dev/null +++ b/media/audio/android/aaudio_output.h
@@ -0,0 +1,76 @@ +// Copyright 2019 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#ifndef MEDIA_AUDIO_ANDROID_AAUDIO_OUTPUT_H_ +#define MEDIA_AUDIO_ANDROID_AAUDIO_OUTPUT_H_ + +#include <aaudio/AAudio.h> + +#include "base/synchronization/lock.h" +#include "base/thread_annotations.h" +#include "base/threading/thread_checker.h" +#include "media/audio/android/muteable_audio_output_stream.h" +#include "media/base/audio_parameters.h" + +namespace media { + +class AudioManagerAndroid; + +class AAudioOutputStream : public MuteableAudioOutputStream { + public: + AAudioOutputStream(AudioManagerAndroid* manager, + const AudioParameters& params, + aaudio_usage_t usage); + ~AAudioOutputStream() override; + + // Implementation of MuteableAudioOutputStream. + bool Open() override; + void Close() override; + void Start(AudioSourceCallback* callback) override; + void Stop() override; + void Flush() override; + void SetVolume(double volume) override; + void GetVolume(double* volume) override; + void SetMute(bool muted) override; + + // Public callbacks. + aaudio_data_callback_result_t OnAudioDataRequested(void* audio_data, + int32_t num_frames); + void OnStreamError(aaudio_result_t error); + + private: + // Returns the amount of unplayed audio relative to |delay_timestamp|. See the + // definition for AudioOutputStream::AudioSourceCallback::OnMoreData() for + // more information on these terms. + base::TimeDelta GetDelay(base::TimeTicks delay_timestamp); + + THREAD_CHECKER(thread_checker_); + + AudioManagerAndroid* const audio_manager_; + const AudioParameters params_; + + aaudio_usage_t usage_; + aaudio_performance_mode_t performance_mode_; + + // Constant used for calculating latency. Amount of nanoseconds per frame. + const double ns_per_frame_; + + std::unique_ptr<AudioBus> audio_bus_; + + AAudioStream* aaudio_stream_ = nullptr; + + // Lock protects all members below which may be read concurrently from the + // audio manager thread and the OS provided audio thread. + base::Lock lock_; + + AudioSourceCallback* callback_ GUARDED_BY(lock_) = nullptr; + bool muted_ GUARDED_BY(lock_) = false; + double volume_ GUARDED_BY(lock_) = 1.0; + + DISALLOW_COPY_AND_ASSIGN(AAudioOutputStream); +}; + +} // namespace media + +#endif // MEDIA_AUDIO_ANDROID_AAUDIO_OUTPUT_H_ \ No newline at end of file
diff --git a/media/audio/android/aaudio_stub_header.fragment b/media/audio/android/aaudio_stub_header.fragment new file mode 100644 index 0000000..01fce79 --- /dev/null +++ b/media/audio/android/aaudio_stub_header.fragment
@@ -0,0 +1,8 @@ +// The extra include header needed in the generated stub file for defining +// various AAudio types. + +extern "C" { + +#include <aaudio/AAudio.h> + +}
diff --git a/media/audio/android/audio_manager_android.cc b/media/audio/android/audio_manager_android.cc index 5d74f7e6..f96d9f8dc7 100644 --- a/media/audio/android/audio_manager_android.cc +++ b/media/audio/android/audio_manager_android.cc
@@ -11,12 +11,16 @@ #include "base/android/jni_string.h" #include "base/android/scoped_java_ref.h" #include "base/bind.h" +#include "base/files/file_path.h" #include "base/logging.h" #include "base/strings/string_number_conversions.h" +#include "media/audio/android/aaudio_output.h" +#include "media/audio/android/aaudio_stubs.h" #include "media/audio/android/audio_track_output_stream.h" #include "media/audio/android/opensles_input.h" #include "media/audio/android/opensles_output.h" #include "media/audio/audio_device_description.h" +#include "media/audio/audio_features.h" #include "media/audio/audio_manager.h" #include "media/audio/fake_audio_input_stream.h" #include "media/base/android/media_jni_headers/AudioManagerAndroid_jni.h" @@ -31,6 +35,13 @@ using base::android::JavaRef; using base::android::ScopedJavaLocalRef; +using media_audio_android::InitializeStubs; +using media_audio_android::kModuleAaudio; +using media_audio_android::StubPathMap; + +static const base::FilePath::CharType kAaudioLib[] = + FILE_PATH_LITERAL("libaaudio.so"); + namespace media { namespace { @@ -47,6 +58,18 @@ } // namespace +static bool InitAAudio() { + StubPathMap paths; + + // Check if the AAudio library is available. + paths[kModuleAaudio].push_back(kAaudioLib); + if (!InitializeStubs(paths)) { + VLOG(1) << "Failed on loading the AAudio library and symbols"; + return false; + } + return true; +} + std::unique_ptr<AudioManager> CreateAudioManager( std::unique_ptr<AudioThread> audio_thread, AudioLogFactory* audio_log_factory) { @@ -225,6 +248,10 @@ const LogCallback& log_callback) { DCHECK_EQ(AudioParameters::AUDIO_PCM_LINEAR, params.format()); DCHECK(GetTaskRunner()->BelongsToCurrentThread()); + + if (UseAAudio()) + return new AAudioOutputStream(this, params, AAUDIO_USAGE_MEDIA); + return new OpenSLESOutputStream(this, params, SL_ANDROID_STREAM_MEDIA); } @@ -235,10 +262,18 @@ DLOG_IF(ERROR, !device_id.empty()) << "Not implemented!"; DCHECK_EQ(AudioParameters::AUDIO_PCM_LOW_LATENCY, params.format()); + if (UseAAudio()) { + const aaudio_usage_t usage = communication_mode_is_on_ + ? AAUDIO_USAGE_VOICE_COMMUNICATION + : AAUDIO_USAGE_MEDIA; + return new AAudioOutputStream(this, params, usage); + } + // Set stream type which matches the current system-wide audio mode used by // the Android audio manager. - const SLint32 stream_type = communication_mode_is_on_ ? - SL_ANDROID_STREAM_VOICE : SL_ANDROID_STREAM_MEDIA; + const SLint32 stream_type = communication_mode_is_on_ + ? SL_ANDROID_STREAM_VOICE + : SL_ANDROID_STREAM_MEDIA; return new OpenSLESOutputStream(this, params, stream_type); } @@ -443,10 +478,26 @@ output_volume_override_ = volume; DCHECK(GetTaskRunner()->BelongsToCurrentThread()); - for (OutputStreams::iterator it = streams_.begin(); - it != streams_.end(); ++it) { + for (OutputStreams::iterator it = streams_.begin(); it != streams_.end(); + ++it) { (*it)->SetVolume(volume); } } +bool AudioManagerAndroid::UseAAudio() { + if (!base::FeatureList::IsEnabled(features::kUseAAudioDriver)) + return false; + + if (base::android::BuildInfo::GetInstance()->sdk_int() < + base::android::SDK_VERSION_P) { + // We need APIs that weren't added until API Level 28. + return false; + } + + if (!is_aaudio_available_.has_value()) + is_aaudio_available_ = InitAAudio(); + + return is_aaudio_available_.value(); +} + } // namespace media
diff --git a/media/audio/android/audio_manager_android.h b/media/audio/android/audio_manager_android.h index df27f8f..cae84442 100644 --- a/media/audio/android/audio_manager_android.h +++ b/media/audio/android/audio_manager_android.h
@@ -107,6 +107,9 @@ void DoSetMuteOnAudioThread(bool muted); void DoSetVolumeOnAudioThread(double volume); + // Returns whether or not we can and should use AAudio. + bool UseAAudio(); + // Java AudioManager instance. base::android::ScopedJavaGlobalRef<jobject> j_audio_manager_; @@ -117,6 +120,8 @@ // input stream is destroyed. Also affects the stream type of output streams. bool communication_mode_is_on_; + base::Optional<bool> is_aaudio_available_; + // If set, overrides volume level on output streams bool output_volume_override_set_; double output_volume_override_;
diff --git a/media/audio/audio_features.cc b/media/audio/audio_features.cc index ad7a952f..77ccae02 100644 --- a/media/audio/audio_features.cc +++ b/media/audio/audio_features.cc
@@ -23,6 +23,13 @@ const base::Feature kDumpOnAudioServiceHang{"DumpOnAudioServiceHang", base::FEATURE_DISABLED_BY_DEFAULT}; +#if defined(OS_ANDROID) +// Enables loading and using AAudio instead of OpenSLES on compatible devices, +// for audio output streams. +const base::Feature kUseAAudioDriver{"UseAAudioDriver", + base::FEATURE_DISABLED_BY_DEFAULT}; +#endif + #if defined(OS_CHROMEOS) const base::Feature kCrOSSystemAEC{"CrOSSystemAEC", base::FEATURE_ENABLED_BY_DEFAULT};
diff --git a/media/audio/audio_features.h b/media/audio/audio_features.h index b219d86..99e29151 100644 --- a/media/audio/audio_features.h +++ b/media/audio/audio_features.h
@@ -14,6 +14,10 @@ MEDIA_EXPORT extern const base::Feature kAudioServiceOutOfProcessKillAtHang; MEDIA_EXPORT extern const base::Feature kDumpOnAudioServiceHang; +#if defined(OS_ANDROID) +MEDIA_EXPORT extern const base::Feature kUseAAudioDriver; +#endif + #if defined(OS_CHROMEOS) MEDIA_EXPORT extern const base::Feature kCrOSSystemAEC; MEDIA_EXPORT extern const base::Feature kCrOSSystemAECDeactivatedGroups;
diff --git a/media/audio/audio_output_unittest.cc b/media/audio/audio_output_unittest.cc index dd67725..f1c544a1 100644 --- a/media/audio/audio_output_unittest.cc +++ b/media/audio/audio_output_unittest.cc
@@ -9,12 +9,14 @@ #include "base/memory/aligned_memory.h" #include "base/run_loop.h" #include "base/test/bind_test_util.h" +#include "base/test/scoped_feature_list.h" #include "base/test/task_environment.h" #include "base/test/test_timeouts.h" #include "base/threading/thread_task_runner_handle.h" #include "base/time/time.h" #include "build/build_config.h" #include "media/audio/audio_device_info_accessor_for_tests.h" +#include "media/audio/audio_features.h" #include "media/audio/audio_io.h" #include "media/audio/audio_manager.h" #include "media/audio/audio_unittest_util.h" @@ -25,13 +27,18 @@ namespace media { -class AudioOutputTest : public ::testing::Test { +class AudioOutputTest : public testing::TestWithParam<bool> { public: AudioOutputTest() { audio_manager_ = AudioManager::CreateForTesting(std::make_unique<TestAudioThread>()); audio_manager_device_info_ = std::make_unique<AudioDeviceInfoAccessorForTests>(audio_manager_.get()); +#if defined(OS_ANDROID) + // The only parameter is used to enable/disable AAudio. + if (GetParam()) + features_.InitAndEnableFeature(features::kUseAAudioDriver); +#endif base::RunLoop().RunUntilIdle(); } ~AudioOutputTest() override { @@ -62,17 +69,20 @@ std::unique_ptr<AudioDeviceInfoAccessorForTests> audio_manager_device_info_; AudioParameters stream_params_; AudioOutputStream* stream_ = nullptr; +#if defined(OS_ANDROID) + base::test::ScopedFeatureList features_; +#endif }; // Test that can it be created and closed. -TEST_F(AudioOutputTest, GetAndClose) { +TEST_P(AudioOutputTest, GetAndClose) { ABORT_AUDIO_TEST_IF_NOT(audio_manager_device_info_->HasAudioOutputDevices()); CreateWithDefaultParameters(); ASSERT_TRUE(stream_); } // Test that it can be opened and closed. -TEST_F(AudioOutputTest, OpenAndClose) { +TEST_P(AudioOutputTest, OpenAndClose) { ABORT_AUDIO_TEST_IF_NOT(audio_manager_device_info_->HasAudioOutputDevices()); CreateWithDefaultParameters(); @@ -81,7 +91,7 @@ } // Verify that Stop() can be called before Start(). -TEST_F(AudioOutputTest, StopBeforeStart) { +TEST_P(AudioOutputTest, StopBeforeStart) { ABORT_AUDIO_TEST_IF_NOT(audio_manager_device_info_->HasAudioOutputDevices()); CreateWithDefaultParameters(); EXPECT_TRUE(stream_->Open()); @@ -89,7 +99,7 @@ } // Verify that Stop() can be called more than once. -TEST_F(AudioOutputTest, StopTwice) { +TEST_P(AudioOutputTest, StopTwice) { ABORT_AUDIO_TEST_IF_NOT(audio_manager_device_info_->HasAudioOutputDevices()); CreateWithDefaultParameters(); EXPECT_TRUE(stream_->Open()); @@ -101,7 +111,7 @@ } // This test produces actual audio for .25 seconds on the default device. -TEST_F(AudioOutputTest, Play200HzTone) { +TEST_P(AudioOutputTest, Play200HzTone) { ABORT_AUDIO_TEST_IF_NOT(audio_manager_device_info_->HasAudioOutputDevices()); stream_params_ = @@ -139,7 +149,7 @@ } // Test that SetVolume() and GetVolume() work as expected. -TEST_F(AudioOutputTest, VolumeControl) { +TEST_P(AudioOutputTest, VolumeControl) { ABORT_AUDIO_TEST_IF_NOT(audio_manager_device_info_->HasAudioOutputDevices()); CreateWithDefaultParameters(); @@ -159,4 +169,14 @@ stream_->Stop(); } +// The test parameter is only relevant on Android. It controls whether or not we +// allow the use of AAudio. +INSTANTIATE_TEST_SUITE_P(Base, AudioOutputTest, testing::Values(false)); + +#if defined(OS_ANDROID) +// Run tests with AAudio enabled. On Android O and below, this is the same as +// the Base test above, as we only use AAudio on P+. +INSTANTIATE_TEST_SUITE_P(AAudio, AudioOutputTest, testing::Values(true)); +#endif + } // namespace media
diff --git a/media/base/eme_constants.h b/media/base/eme_constants.h index cb9a850..ba9387f 100644 --- a/media/base/eme_constants.h +++ b/media/base/eme_constants.h
@@ -52,12 +52,12 @@ SupportedCodecs codecs = EME_CODEC_FLAC; #if BUILDFLAG(USE_PROPRIETARY_CODECS) codecs |= EME_CODEC_AAC; -#if BUILDFLAG(ENABLE_AC3_EAC3_AUDIO_DEMUXING) +#if BUILDFLAG(ENABLE_PLATFORM_AC3_EAC3_AUDIO) codecs |= EME_CODEC_AC3 | EME_CODEC_EAC3; -#endif // BUILDFLAG(ENABLE_AC3_EAC3_AUDIO_DEMUXING) -#if BUILDFLAG(ENABLE_MPEG_H_AUDIO_DEMUXING) +#endif // BUILDFLAG(ENABLE_PLATFORM_AC3_EAC3_AUDIO) +#if BUILDFLAG(ENABLE_PLATFORM_MPEG_H_AUDIO) codecs |= EME_CODEC_MPEG_H_AUDIO; -#endif // BUILDFLAG(ENABLE_MPEG_H_AUDIO_DEMUXING) +#endif // BUILDFLAG(ENABLE_PLATFORM_MPEG_H_AUDIO) #endif // BUILDFLAG(USE_PROPRIETARY_CODECS) return codecs; } @@ -72,12 +72,12 @@ #if BUILDFLAG(ENABLE_PLATFORM_HEVC) codecs |= EME_CODEC_HEVC; #endif // BUILDFLAG(ENABLE_PLATFORM_HEVC) -#if BUILDFLAG(ENABLE_DOLBY_VISION_DEMUXING) +#if BUILDFLAG(ENABLE_PLATFORM_DOLBY_VISION) codecs |= EME_CODEC_DOLBY_VISION_AVC; #if BUILDFLAG(ENABLE_PLATFORM_HEVC) codecs |= EME_CODEC_DOLBY_VISION_HEVC; #endif // BUILDFLAG(ENABLE_PLATFORM_HEVC) -#endif // BUILDFLAG(ENABLE_DOLBY_VISION_DEMUXING) +#endif // BUILDFLAG(ENABLE_PLATFORM_DOLBY_VISION) #endif // BUILDFLAG(USE_PROPRIETARY_CODECS) return codecs; }
diff --git a/media/base/media_switches.cc b/media/base/media_switches.cc index 5b4cf31..7ca9a46 100644 --- a/media/base/media_switches.cc +++ b/media/base/media_switches.cc
@@ -485,6 +485,11 @@ const base::Feature kUseAudioLatencyFromHAL{"UseAudioLatencyFromHAL", base::FEATURE_DISABLED_BY_DEFAULT}; +// Enable pooling of SharedImageVideo objects for use by MCVD, to save a hop to +// the GPU main thread during VideoFrame construction. +const base::Feature kUsePooledSharedImageVideoProvider{ + "UsePooledSharedImageVideoProvider", base::FEATURE_DISABLED_BY_DEFAULT}; + #endif // defined(OS_ANDROID) #if defined(OS_WIN)
diff --git a/media/base/media_switches.h b/media/base/media_switches.h index 965c584..8df20f29 100644 --- a/media/base/media_switches.h +++ b/media/base/media_switches.h
@@ -166,6 +166,7 @@ MEDIA_EXPORT extern const base::Feature kPictureInPictureAPI; MEDIA_EXPORT extern const base::Feature kHlsPlayer; MEDIA_EXPORT extern const base::Feature kUseAudioLatencyFromHAL; +MEDIA_EXPORT extern const base::Feature kUsePooledSharedImageVideoProvider; #endif // defined(OS_ANDROID) #if defined(OS_WIN)
diff --git a/media/base/mime_util_internal.cc b/media/base/mime_util_internal.cc index c2bdd43..8331cef 100644 --- a/media/base/mime_util_internal.cc +++ b/media/base/mime_util_internal.cc
@@ -320,23 +320,23 @@ CodecSet avc_and_aac(aac); avc_and_aac.emplace(H264); -#if BUILDFLAG(ENABLE_AC3_EAC3_AUDIO_DEMUXING) +#if BUILDFLAG(ENABLE_PLATFORM_AC3_EAC3_AUDIO) mp4_audio_codecs.emplace(AC3); mp4_audio_codecs.emplace(EAC3); -#endif // BUILDFLAG(ENABLE_AC3_EAC3_AUDIO_DEMUXING) +#endif // BUILDFLAG(ENABLE_PLATFORM_AC3_EAC3_AUDIO) -#if BUILDFLAG(ENABLE_MPEG_H_AUDIO_DEMUXING) +#if BUILDFLAG(ENABLE_PLATFORM_MPEG_H_AUDIO) mp4_audio_codecs.emplace(MPEG_H_AUDIO); -#endif // BUILDFLAG(ENABLE_MPEG_H_AUDIO_DEMUXING) +#endif // BUILDFLAG(ENABLE_PLATFORM_MPEG_H_AUDIO) mp4_video_codecs.emplace(H264); #if BUILDFLAG(ENABLE_PLATFORM_HEVC) mp4_video_codecs.emplace(HEVC); #endif // BUILDFLAG(ENABLE_PLATFORM_HEVC) -#if BUILDFLAG(ENABLE_DOLBY_VISION_DEMUXING) +#if BUILDFLAG(ENABLE_PLATFORM_DOLBY_VISION) mp4_video_codecs.emplace(DOLBY_VISION); -#endif // BUILDFLAG(ENABLE_DOLBY_VISION_DEMUXING) +#endif // BUILDFLAG(ENABLE_PLATFORM_DOLBY_VISION) #endif // BUILDFLAG(USE_PROPRIETARY_CODECS) #if BUILDFLAG(ENABLE_AV1_DECODER) mp4_video_codecs.emplace(AV1); @@ -661,7 +661,7 @@ case AC3: case EAC3: -#if BUILDFLAG(ENABLE_AC3_EAC3_AUDIO_DEMUXING) +#if BUILDFLAG(ENABLE_PLATFORM_AC3_EAC3_AUDIO) return true; #else return false; @@ -831,14 +831,14 @@ } #endif -#if BUILDFLAG(ENABLE_DOLBY_VISION_DEMUXING) +#if BUILDFLAG(ENABLE_PLATFORM_DOLBY_VISION) if (ParseDolbyVisionCodecId(codec_id, out_profile, out_level)) { out_result->codec = MimeUtil::DOLBY_VISION; return true; } #endif -#if BUILDFLAG(ENABLE_MPEG_H_AUDIO_DEMUXING) +#if BUILDFLAG(ENABLE_PLATFORM_MPEG_H_AUDIO) if (base::StartsWith(codec_id, "mhm1.", base::CompareCase::SENSITIVE) || base::StartsWith(codec_id, "mha1.", base::CompareCase::SENSITIVE)) { out_result->codec = MimeUtil::MPEG_H_AUDIO;
diff --git a/media/base/mime_util_unittest.cc b/media/base/mime_util_unittest.cc index f13914c..3e785a11 100644 --- a/media/base/mime_util_unittest.cc +++ b/media/base/mime_util_unittest.cc
@@ -130,7 +130,7 @@ } static bool HasEac3Support() { -#if BUILDFLAG(ENABLE_AC3_EAC3_AUDIO_DEMUXING) +#if BUILDFLAG(ENABLE_PLATFORM_AC3_EAC3_AUDIO) return true; #else return false;
diff --git a/media/base/video_codecs.cc b/media/base/video_codecs.cc index 581feed..4c04f29f 100644 --- a/media/base/video_codecs.cc +++ b/media/base/video_codecs.cc
@@ -715,7 +715,7 @@ } #endif -#if BUILDFLAG(ENABLE_DOLBY_VISION_DEMUXING) +#if BUILDFLAG(ENABLE_PLATFORM_DOLBY_VISION) bool IsDolbyVisionAVCCodecId(const std::string& codec_id) { return base::StartsWith(codec_id, "dva1.", base::CompareCase::SENSITIVE) || base::StartsWith(codec_id, "dvav.", base::CompareCase::SENSITIVE); @@ -854,7 +854,7 @@ if (ParseHEVCCodecId(codec_id, &profile, &level)) return kCodecHEVC; #endif -#if BUILDFLAG(ENABLE_DOLBY_VISION_DEMUXING) +#if BUILDFLAG(ENABLE_PLATFORM_DOLBY_VISION) if (ParseDolbyVisionCodecId(codec_id, &profile, &level)) return kCodecDolbyVision; #endif
diff --git a/media/base/video_codecs.h b/media/base/video_codecs.h index d344a923..bf7e4bc 100644 --- a/media/base/video_codecs.h +++ b/media/base/video_codecs.h
@@ -138,7 +138,7 @@ uint8_t* level_idc); #endif -#if BUILDFLAG(ENABLE_DOLBY_VISION_DEMUXING) +#if BUILDFLAG(ENABLE_PLATFORM_DOLBY_VISION) MEDIA_EXPORT bool ParseDolbyVisionCodecId(const std::string& codec_id, VideoCodecProfile* profile, uint8_t* level_id);
diff --git a/media/base/video_codecs_unittest.cc b/media/base/video_codecs_unittest.cc index 162791c9..c6d9484e 100644 --- a/media/base/video_codecs_unittest.cc +++ b/media/base/video_codecs_unittest.cc
@@ -582,7 +582,7 @@ } #endif -#if BUILDFLAG(ENABLE_DOLBY_VISION_DEMUXING) +#if BUILDFLAG(ENABLE_PLATFORM_DOLBY_VISION) TEST(ParseDolbyVisionCodecIdTest, InvalidDolbyVisionCodecIds) { VideoCodecProfile profile = VIDEO_CODEC_PROFILE_UNKNOWN; uint8_t level_id = 0;
diff --git a/media/cdm/aes_decryptor.cc b/media/cdm/aes_decryptor.cc index ff30013..176050a 100644 --- a/media/cdm/aes_decryptor.cc +++ b/media/cdm/aes_decryptor.cc
@@ -174,6 +174,7 @@ session_closed_cb_(session_closed_cb), session_keys_change_cb_(session_keys_change_cb), session_expiration_update_cb_(session_expiration_update_cb) { + DVLOG(1) << __func__; // AesDecryptor doesn't keep any persistent data, so no need to do anything // with |security_origin|. DCHECK(session_message_cb_); @@ -182,6 +183,7 @@ } AesDecryptor::~AesDecryptor() { + DVLOG(1) << __func__; key_map_.clear(); }
diff --git a/media/ffmpeg/ffmpeg_common.cc b/media/ffmpeg/ffmpeg_common.cc index f4622e1..72dc400 100644 --- a/media/ffmpeg/ffmpeg_common.cc +++ b/media/ffmpeg/ffmpeg_common.cc
@@ -80,7 +80,7 @@ switch (codec_id) { case AV_CODEC_ID_AAC: return kCodecAAC; -#if BUILDFLAG(ENABLE_AC3_EAC3_AUDIO_DEMUXING) +#if BUILDFLAG(ENABLE_PLATFORM_AC3_EAC3_AUDIO) case AV_CODEC_ID_AC3: return kCodecAC3; case AV_CODEC_ID_EAC3: @@ -341,7 +341,7 @@ // not fill |sample_fmt|. case kCodecAC3: case kCodecEAC3: -#if BUILDFLAG(ENABLE_AC3_EAC3_AUDIO_DEMUXING) +#if BUILDFLAG(ENABLE_PLATFORM_AC3_EAC3_AUDIO) // The spec for AC3/EAC3 audio is ETSI TS 102 366. According to sections // F.3.1 and F.5.1 in that spec the sample_format for AC3/EAC3 must be 16. sample_format = kSampleFormatS16; @@ -382,7 +382,7 @@ if (channel_layout == CHANNEL_LAYOUT_DISCRETE) config->SetChannelsForDiscrete(codec_context->channels); -#if BUILDFLAG(ENABLE_AC3_EAC3_AUDIO_DEMUXING) +#if BUILDFLAG(ENABLE_PLATFORM_AC3_EAC3_AUDIO) // These are bitstream formats unknown to ffmpeg, so they don't have // a known sample format size. if (codec == kCodecAC3 || codec == kCodecEAC3)
diff --git a/media/filters/ffmpeg_demuxer_unittest.cc b/media/filters/ffmpeg_demuxer_unittest.cc index 68618dd..51e98a3 100644 --- a/media/filters/ffmpeg_demuxer_unittest.cc +++ b/media/filters/ffmpeg_demuxer_unittest.cc
@@ -1384,7 +1384,7 @@ TEST_F(FFmpegDemuxerTest, Read_AC3_Audio) { CreateDemuxer("bear-ac3-only-frag.mp4"); -#if BUILDFLAG(ENABLE_AC3_EAC3_AUDIO_DEMUXING) +#if BUILDFLAG(ENABLE_PLATFORM_AC3_EAC3_AUDIO) // AC3 is not supported by default media platform. Embedders who add support // must declare it via MediaClient. MockMediaClient media_client; @@ -1414,7 +1414,7 @@ TEST_F(FFmpegDemuxerTest, Read_EAC3_Audio) { CreateDemuxer("bear-eac3-only-frag.mp4"); -#if BUILDFLAG(ENABLE_AC3_EAC3_AUDIO_DEMUXING) +#if BUILDFLAG(ENABLE_PLATFORM_AC3_EAC3_AUDIO) // EAC3 is not supported by default media platform. Embedders who add support // must declare it via MediaClient. MockMediaClient media_client;
diff --git a/media/filters/stream_parser_factory.cc b/media/filters/stream_parser_factory.cc index ff86540..0aaca79 100644 --- a/media/filters/stream_parser_factory.cc +++ b/media/filters/stream_parser_factory.cc
@@ -169,7 +169,7 @@ static const CodecInfo kHEVCHVC1CodecInfo = { "hvc1.*", CodecInfo::VIDEO, nullptr, CodecInfo::HISTOGRAM_HEVC}; #endif // BUILDFLAG(ENABLE_PLATFORM_HEVC) -#if BUILDFLAG(ENABLE_DOLBY_VISION_DEMUXING) +#if BUILDFLAG(ENABLE_PLATFORM_DOLBY_VISION) static const CodecInfo kDolbyVisionAVCCodecInfo1 = { "dva1.*", CodecInfo::VIDEO, nullptr, CodecInfo::HISTOGRAM_DOLBYVISION}; static const CodecInfo kDolbyVisionAVCCodecInfo2 = { @@ -180,14 +180,14 @@ static const CodecInfo kDolbyVisionHEVCCodecInfo2 = { "dvhe.*", CodecInfo::VIDEO, nullptr, CodecInfo::HISTOGRAM_DOLBYVISION}; #endif // BUILDFLAG(ENABLE_PLATFORM_HEVC) -#endif // BUILDFLAG(ENABLE_DOLBY_VISION_DEMUXING) +#endif // BUILDFLAG(ENABLE_PLATFORM_DOLBY_VISION) static const CodecInfo kMPEG4AACCodecInfo = {"mp4a.40.*", CodecInfo::AUDIO, &ValidateMP4ACodecID, CodecInfo::HISTOGRAM_MPEG4AAC}; static const CodecInfo kMPEG2AACLCCodecInfo = { "mp4a.67", CodecInfo::AUDIO, nullptr, CodecInfo::HISTOGRAM_MPEG2AAC}; -#if BUILDFLAG(ENABLE_AC3_EAC3_AUDIO_DEMUXING) +#if BUILDFLAG(ENABLE_PLATFORM_AC3_EAC3_AUDIO) // The 'ac-3' and 'ec-3' are mime codec ids for AC3 and EAC3 according to // http://www.mp4ra.org/codecs.html // The object types for AC3 and EAC3 in MP4 container are 0xa5 and 0xa6, so @@ -206,9 +206,9 @@ CodecInfo::HISTOGRAM_EAC3}; static const CodecInfo kEAC3CodecInfo3 = {"mp4a.A6", CodecInfo::AUDIO, nullptr, CodecInfo::HISTOGRAM_EAC3}; -#endif // BUILDFLAG(ENABLE_AC3_EAC3_AUDIO_DEMUXING) +#endif // BUILDFLAG(ENABLE_PLATFORM_AC3_EAC3_AUDIO) -#if BUILDFLAG(ENABLE_MPEG_H_AUDIO_DEMUXING) +#if BUILDFLAG(ENABLE_PLATFORM_MPEG_H_AUDIO) static const CodecInfo kMpegHAudioCodecInfo1 = { "mhm1.*", CodecInfo::AUDIO, nullptr, CodecInfo::HISTOGRAM_MPEG_H_AUDIO}; static const CodecInfo kMpegHAudioCodecInfo2 = { @@ -241,7 +241,7 @@ &kHEVCHEV1CodecInfo, &kHEVCHVC1CodecInfo, #endif -#if BUILDFLAG(ENABLE_DOLBY_VISION_DEMUXING) +#if BUILDFLAG(ENABLE_PLATFORM_DOLBY_VISION) &kDolbyVisionAVCCodecInfo1, &kDolbyVisionAVCCodecInfo2, #if BUILDFLAG(ENABLE_PLATFORM_HEVC) @@ -251,7 +251,7 @@ #endif &kMPEG4AACCodecInfo, &kMPEG2AACLCCodecInfo, -#if BUILDFLAG(ENABLE_MPEG_H_AUDIO_DEMUXING) +#if BUILDFLAG(ENABLE_PLATFORM_MPEG_H_AUDIO) &kMpegHAudioCodecInfo1, &kMpegHAudioCodecInfo2, #endif @@ -266,18 +266,18 @@ #if BUILDFLAG(USE_PROPRIETARY_CODECS) &kMPEG4AACCodecInfo, &kMPEG2AACLCCodecInfo, -#if BUILDFLAG(ENABLE_MPEG_H_AUDIO_DEMUXING) +#if BUILDFLAG(ENABLE_PLATFORM_MPEG_H_AUDIO) &kMpegHAudioCodecInfo1, &kMpegHAudioCodecInfo2, #endif -#if BUILDFLAG(ENABLE_AC3_EAC3_AUDIO_DEMUXING) +#if BUILDFLAG(ENABLE_PLATFORM_AC3_EAC3_AUDIO) &kAC3CodecInfo1, &kAC3CodecInfo2, &kAC3CodecInfo3, &kEAC3CodecInfo1, &kEAC3CodecInfo2, &kEAC3CodecInfo3, -#endif // BUILDFLAG(ENABLE_AC3_EAC3_AUDIO_DEMUXING) +#endif // BUILDFLAG(ENABLE_PLATFORM_AC3_EAC3_AUDIO) #endif // BUILDFLAG(USE_PROPRIETARY_CODECS) nullptr}; @@ -312,7 +312,7 @@ has_sbr = true; break; } -#if BUILDFLAG(ENABLE_AC3_EAC3_AUDIO_DEMUXING) +#if BUILDFLAG(ENABLE_PLATFORM_AC3_EAC3_AUDIO) } else if (base::MatchPattern(codec_id, kAC3CodecInfo1.pattern) || base::MatchPattern(codec_id, kAC3CodecInfo2.pattern) || base::MatchPattern(codec_id, kAC3CodecInfo3.pattern)) { @@ -321,7 +321,7 @@ base::MatchPattern(codec_id, kEAC3CodecInfo2.pattern) || base::MatchPattern(codec_id, kEAC3CodecInfo3.pattern)) { audio_object_types.insert(mp4::kEAC3); -#endif // BUILDFLAG(ENABLE_AC3_EAC3_AUDIO_DEMUXING) +#endif // BUILDFLAG(ENABLE_PLATFORM_AC3_EAC3_AUDIO) #endif // BUILDFLAG(USE_PROPRIETARY_CODECS) } }
diff --git a/media/formats/BUILD.gn b/media/formats/BUILD.gn index 9c54c30..7b2a260 100644 --- a/media/formats/BUILD.gn +++ b/media/formats/BUILD.gn
@@ -107,7 +107,7 @@ ] } - if (proprietary_codecs && enable_dolby_vision_demuxing) { + if (proprietary_codecs && enable_platform_dolby_vision) { sources += [ "mp4/dolby_vision.cc", "mp4/dolby_vision.h", @@ -255,7 +255,7 @@ ] } - if (enable_dolby_vision_demuxing) { + if (enable_platform_dolby_vision) { sources += [ "mp4/dolby_vision_unittest.cc" ] }
diff --git a/media/formats/mp4/box_definitions.cc b/media/formats/mp4/box_definitions.cc index ebef0a9..84e5c36 100644 --- a/media/formats/mp4/box_definitions.cc +++ b/media/formats/mp4/box_definitions.cc
@@ -29,10 +29,10 @@ #include "media/formats/mp4/avc.h" #include "media/video/h264_parser.h" // nogncheck -#if BUILDFLAG(ENABLE_DOLBY_VISION_DEMUXING) +#if BUILDFLAG(ENABLE_PLATFORM_DOLBY_VISION) #include "base/optional.h" #include "media/formats/mp4/dolby_vision.h" -#endif // BUILDFLAG(ENABLE_DOLBY_VISION_DEMUXING) +#endif // BUILDFLAG(ENABLE_PLATFORM_DOLBY_VISION) #if BUILDFLAG(ENABLE_PLATFORM_HEVC) #include "media/formats/mp4/hevc.h" @@ -47,7 +47,7 @@ const size_t kKeyIdSize = 16; const size_t kFlacMetadataBlockStreaminfoSize = 34; -#if BUILDFLAG(ENABLE_DOLBY_VISION_DEMUXING) +#if BUILDFLAG(ENABLE_PLATFORM_DOLBY_VISION) // Parse dvcC or dvvC box. base::Optional<DOVIDecoderConfigurationRecord> ParseDOVIConfig( BoxReader* reader) { @@ -69,7 +69,7 @@ return base::nullopt; } -#endif // BUILDFLAG(ENABLE_DOLBY_VISION_DEMUXING) +#endif // BUILDFLAG(ENABLE_PLATFORM_DOLBY_VISION) } // namespace @@ -863,7 +863,7 @@ frame_bitstream_converter = base::MakeRefCounted<AVCBitstreamConverter>(std::move(avcConfig)); -#if BUILDFLAG(ENABLE_DOLBY_VISION_DEMUXING) +#if BUILDFLAG(ENABLE_PLATFORM_DOLBY_VISION) // It can be Dolby Vision stream if there is DVCC box. auto dv_config = ParseDOVIConfig(reader); if (dv_config.has_value()) { @@ -871,7 +871,7 @@ video_codec = kCodecDolbyVision; video_codec_profile = dv_config->codec_profile; } -#endif // BUILDFLAG(ENABLE_DOLBY_VISION_DEMUXING) +#endif // BUILDFLAG(ENABLE_PLATFORM_DOLBY_VISION) break; } #if BUILDFLAG(ENABLE_PLATFORM_HEVC) @@ -885,7 +885,7 @@ video_codec_profile = hevcConfig->GetVideoProfile(); frame_bitstream_converter = base::MakeRefCounted<HEVCBitstreamConverter>(std::move(hevcConfig)); -#if BUILDFLAG(ENABLE_DOLBY_VISION_DEMUXING) +#if BUILDFLAG(ENABLE_PLATFORM_DOLBY_VISION) // It can be Dolby Vision stream if there is DVCC box. auto dv_config = ParseDOVIConfig(reader); if (dv_config.has_value()) { @@ -893,11 +893,11 @@ video_codec = kCodecDolbyVision; video_codec_profile = dv_config->codec_profile; } -#endif // BUILDFLAG(ENABLE_DOLBY_VISION_DEMUXING) +#endif // BUILDFLAG(ENABLE_PLATFORM_DOLBY_VISION) break; } #endif // BUILDFLAG(ENABLE_PLATFORM_HEVC) -#if BUILDFLAG(ENABLE_DOLBY_VISION_DEMUXING) +#if BUILDFLAG(ENABLE_PLATFORM_DOLBY_VISION) case FOURCC_DVA1: case FOURCC_DVAV: { DVLOG(2) << __func__ << " reading AVCDecoderConfigurationRecord (avcC)"; @@ -931,7 +931,7 @@ break; } #endif // BUILDFLAG(ENABLE_PLATFORM_HEVC) -#endif // BUILDFLAG(ENABLE_DOLBY_VISION_DEMUXING) +#endif // BUILDFLAG(ENABLE_PLATFORM_DOLBY_VISION) #endif // BUILDFLAG(USE_PROPRIETARY_CODECS) case FOURCC_VP09: { DVLOG(2) << __func__ << " parsing VPCodecConfigurationRecord (vpcC)"; @@ -980,15 +980,15 @@ #if BUILDFLAG(ENABLE_PLATFORM_HEVC) case FOURCC_HEV1: case FOURCC_HVC1: -#if BUILDFLAG(ENABLE_DOLBY_VISION_DEMUXING) +#if BUILDFLAG(ENABLE_PLATFORM_DOLBY_VISION) case FOURCC_DVH1: case FOURCC_DVHE: -#endif // BUILDFLAG(ENABLE_DOLBY_VISION_DEMUXING) +#endif // BUILDFLAG(ENABLE_PLATFORM_DOLBY_VISION) #endif // BUILDFLAG(ENABLE_PLATFORM_HEVC) -#if BUILDFLAG(ENABLE_DOLBY_VISION_DEMUXING) +#if BUILDFLAG(ENABLE_PLATFORM_DOLBY_VISION) case FOURCC_DVA1: case FOURCC_DVAV: -#endif // BUILDFLAG(ENABLE_DOLBY_VISION_DEMUXING) +#endif // BUILDFLAG(ENABLE_PLATFORM_DOLBY_VISION) #endif // BUILDFLAG(USE_PROPRIETARY_CODECS) case FOURCC_VP09: return true;
diff --git a/media/formats/mp4/fourccs.h b/media/formats/mp4/fourccs.h index fee277e..19924d3 100644 --- a/media/formats/mp4/fourccs.h +++ b/media/formats/mp4/fourccs.h
@@ -14,7 +14,7 @@ enum FourCC { FOURCC_NULL = 0, -#if BUILDFLAG(ENABLE_AC3_EAC3_AUDIO_DEMUXING) +#if BUILDFLAG(ENABLE_PLATFORM_AC3_EAC3_AUDIO) FOURCC_AC3 = 0x61632d33, // "ac-3" FOURCC_EAC3 = 0x65632d33, // "ec-3" #endif @@ -33,7 +33,7 @@ FOURCC_DFLA = 0x64664c61, // "dfLa" FOURCC_DINF = 0x64696e66, FOURCC_DOPS = 0x644f7073, // "dOps" -#if BUILDFLAG(ENABLE_DOLBY_VISION_DEMUXING) +#if BUILDFLAG(ENABLE_PLATFORM_DOLBY_VISION) FOURCC_DVA1 = 0x64766131, FOURCC_DVAV = 0x64766176, FOURCC_DVCC = 0x64766343, @@ -70,7 +70,7 @@ FOURCC_META = 0x6d657461, FOURCC_MFHD = 0x6d666864, FOURCC_MFRA = 0x6d667261, -#if BUILDFLAG(ENABLE_MPEG_H_AUDIO_DEMUXING) +#if BUILDFLAG(ENABLE_PLATFORM_MPEG_H_AUDIO) FOURCC_MHM1 = 0x6d686d31, FOURCC_MHA1 = 0x6d686131, #endif
diff --git a/media/formats/mp4/mp4_stream_parser.cc b/media/formats/mp4/mp4_stream_parser.cc index a16162f..915551d2 100644 --- a/media/formats/mp4/mp4_stream_parser.cc +++ b/media/formats/mp4/mp4_stream_parser.cc
@@ -329,10 +329,10 @@ : entry.format; if (audio_format != FOURCC_OPUS && audio_format != FOURCC_FLAC && -#if BUILDFLAG(ENABLE_AC3_EAC3_AUDIO_DEMUXING) +#if BUILDFLAG(ENABLE_PLATFORM_AC3_EAC3_AUDIO) audio_format != FOURCC_AC3 && audio_format != FOURCC_EAC3 && #endif -#if BUILDFLAG(ENABLE_MPEG_H_AUDIO_DEMUXING) +#if BUILDFLAG(ENABLE_PLATFORM_MPEG_H_AUDIO) audio_format != FOURCC_MHM1 && audio_format != FOURCC_MHA1 && #endif audio_format != FOURCC_MP4A) { @@ -370,7 +370,7 @@ sample_per_second = entry.samplerate; extra_data = entry.dfla.stream_info; #if BUILDFLAG(USE_PROPRIETARY_CODECS) -#if BUILDFLAG(ENABLE_MPEG_H_AUDIO_DEMUXING) +#if BUILDFLAG(ENABLE_PLATFORM_MPEG_H_AUDIO) } else if (audio_format == FOURCC_MHM1 || audio_format == FOURCC_MHA1) { codec = kCodecMpegHAudio; channel_layout = CHANNEL_LAYOUT_BITSTREAM; @@ -379,7 +379,7 @@ #endif } else { uint8_t audio_type = entry.esds.object_type; -#if BUILDFLAG(ENABLE_AC3_EAC3_AUDIO_DEMUXING) +#if BUILDFLAG(ENABLE_PLATFORM_AC3_EAC3_AUDIO) if (audio_type == kForbidden) { if (audio_format == FOURCC_AC3) audio_type = kAC3; @@ -406,7 +406,7 @@ #if defined(OS_ANDROID) extra_data = aac.codec_specific_data(); #endif -#if BUILDFLAG(ENABLE_AC3_EAC3_AUDIO_DEMUXING) +#if BUILDFLAG(ENABLE_PLATFORM_AC3_EAC3_AUDIO) } else if (audio_type == kAC3) { codec = kCodecAC3; channel_layout = GuessChannelLayout(entry.channelcount);
diff --git a/media/formats/mp4/mp4_stream_parser_unittest.cc b/media/formats/mp4/mp4_stream_parser_unittest.cc index 43919914..134d485 100644 --- a/media/formats/mp4/mp4_stream_parser_unittest.cc +++ b/media/formats/mp4/mp4_stream_parser_unittest.cc
@@ -594,7 +594,7 @@ audio_object_types.insert(kAC3); parser_.reset(new MP4StreamParser(audio_object_types, false, false)); -#if BUILDFLAG(ENABLE_AC3_EAC3_AUDIO_DEMUXING) +#if BUILDFLAG(ENABLE_PLATFORM_AC3_EAC3_AUDIO) bool expect_success = true; #else bool expect_success = false; @@ -618,7 +618,7 @@ audio_object_types.insert(kEAC3); parser_.reset(new MP4StreamParser(audio_object_types, false, false)); -#if BUILDFLAG(ENABLE_AC3_EAC3_AUDIO_DEMUXING) +#if BUILDFLAG(ENABLE_PLATFORM_AC3_EAC3_AUDIO) bool expect_success = true; #else bool expect_success = false;
diff --git a/media/gpu/BUILD.gn b/media/gpu/BUILD.gn index c290ec2..041f6054 100644 --- a/media/gpu/BUILD.gn +++ b/media/gpu/BUILD.gn
@@ -123,6 +123,8 @@ "android/maybe_render_early_manager.h", "android/media_codec_video_decoder.cc", "android/media_codec_video_decoder.h", + "android/pooled_shared_image_video_provider.cc", + "android/pooled_shared_image_video_provider.h", "android/promotion_hint_aggregator.h", "android/promotion_hint_aggregator_impl.cc", "android/promotion_hint_aggregator_impl.h", @@ -480,6 +482,9 @@ "android/mock_device_info.h", "android/mock_promotion_hint_aggregator.cc", "android/mock_promotion_hint_aggregator.h", + "android/mock_shared_image_video_provider.cc", + "android/mock_shared_image_video_provider.h", + "android/pooled_shared_image_video_provider_unittest.cc", "android/promotion_hint_aggregator_impl_unittest.cc", "android/surface_chooser_helper_unittest.cc", "android/video_frame_factory_impl_unittest.cc",
diff --git a/media/gpu/android/codec_image.cc b/media/gpu/android/codec_image.cc index 8c4dd49..eaf4173 100644 --- a/media/gpu/android/codec_image.cc +++ b/media/gpu/android/codec_image.cc
@@ -44,8 +44,7 @@ CodecImage::CodecImage() = default; CodecImage::~CodecImage() { - for (auto& cb : unused_cbs_) - std::move(cb).Run(this); + NotifyUnused(); } void CodecImage::Initialize( @@ -63,6 +62,19 @@ unused_cbs_.push_back(std::move(unused_cb)); } +void CodecImage::NotifyUnused() { + // If we haven't done so yet, release the codec output buffer. Also drop + // our reference to the TextureOwner (if any). In other words, undo anything + // that we did in Initialize. + ReleaseCodecBuffer(); + codec_buffer_wait_coordinator_.reset(); + promotion_hint_cb_ = PromotionHintAggregator::NotifyPromotionHintCB(); + + for (auto& cb : unused_cbs_) + std::move(cb).Run(this); + unused_cbs_.clear(); +} + gfx::Size CodecImage::GetSize() { // Return a nonzero size, to avoid GL errors, even if we dropped the codec // buffer already. Note that if we dropped it, there's no data in the @@ -329,6 +341,10 @@ return codec_buffer_wait_coordinator_->texture_owner()->GetAHardwareBuffer(); } +bool CodecImage::HasMutableState() const { + return false; +} + CodecImageHolder::CodecImageHolder( scoped_refptr<base::SequencedTaskRunner> task_runner, scoped_refptr<CodecImage> codec_image)
diff --git a/media/gpu/android/codec_image.h b/media/gpu/android/codec_image.h index fb8426c..0b13cb36 100644 --- a/media/gpu/android/codec_image.h +++ b/media/gpu/android/codec_image.h
@@ -98,6 +98,15 @@ int display_y, int display_width, int display_height) override; + // If we re-use one CodecImage with different output buffers, then we must + // not claim to have mutable state. Otherwise, CopyTexImage is only called + // once. For pooled shared images, this must return false. For single-use + // images, it works either way. + bool HasMutableState() const override; + + // Notify us that we're no longer in-use for display, and may be pointed at + // another output buffer via a call to Initialize. + void NotifyUnused(); // gpu::StreamTextureSharedImageInterface implementation. void ReleaseResources() override;
diff --git a/media/gpu/android/codec_image_unittest.cc b/media/gpu/android/codec_image_unittest.cc index bbf8bf60..e545235f 100644 --- a/media/gpu/android/codec_image_unittest.cc +++ b/media/gpu/android/codec_image_unittest.cc
@@ -82,7 +82,7 @@ enum ImageKind { kOverlay, kTextureOwner }; scoped_refptr<CodecImage> NewImage( ImageKind kind, - CodecImage::UnusedCB now_unused_cb = base::DoNothing()) { + CodecImage::UnusedCB unused_cb = base::DoNothing()) { std::unique_ptr<CodecOutputBuffer> buffer; wrapper_->DequeueOutputBuffer(nullptr, nullptr, &buffer); scoped_refptr<CodecImage> image = new CodecImage(); @@ -92,7 +92,7 @@ base::BindRepeating(&PromotionHintReceiver::OnPromotionHint, base::Unretained(&promotion_hint_receiver_))); - image->AddUnusedCB(std::move(now_unused_cb)); + image->AddUnusedCB(std::move(unused_cb)); return image; } @@ -133,6 +133,26 @@ i = nullptr; } +TEST_F(CodecImageTest, UnusedCBRunsOnNotifyUnused) { + base::MockCallback<CodecImage::UnusedCB> cb_1; + base::MockCallback<CodecImage::UnusedCB> cb_2; + auto i = NewImage(kTextureOwner); + ASSERT_TRUE(i->get_codec_output_buffer_for_testing()); + ASSERT_TRUE(i->is_texture_owner_backed()); + i->AddUnusedCB(cb_1.Get()); + i->AddUnusedCB(cb_2.Get()); + EXPECT_CALL(cb_1, Run(i.get())); + EXPECT_CALL(cb_2, Run(i.get())); + + // Also verify that the output buffer and texture owner are released. + i->NotifyUnused(); + EXPECT_FALSE(i->get_codec_output_buffer_for_testing()); + EXPECT_FALSE(i->is_texture_owner_backed()); + + // Verify that an additional call doesn't crash. It should do nothing. + i->NotifyUnused(); +} + TEST_F(CodecImageTest, ImageStartsUnrendered) { auto i = NewImage(kTextureOwner); ASSERT_FALSE(i->was_rendered_to_front_buffer());
diff --git a/media/gpu/android/media_codec_video_decoder.cc b/media/gpu/android/media_codec_video_decoder.cc index e7f795bd..8f44b19 100644 --- a/media/gpu/android/media_codec_video_decoder.cc +++ b/media/gpu/android/media_codec_video_decoder.cc
@@ -915,7 +915,7 @@ CreatePromotionHintCB(), base::BindOnce(&MediaCodecVideoDecoder::ForwardVideoFrame, weak_factory_.GetWeakPtr(), reset_generation_, - std::move(async_trace))); + std::move(async_trace), base::TimeTicks::Now())); return true; } @@ -932,10 +932,17 @@ void MediaCodecVideoDecoder::ForwardVideoFrame( int reset_generation, std::unique_ptr<ScopedAsyncTrace> async_trace, + base::TimeTicks started_at, scoped_refptr<VideoFrame> frame) { DVLOG(3) << __func__ << " : " << (frame ? frame->AsHumanReadableString() : "null"); + // Record how long this frame was pending. + const base::TimeDelta duration = base::TimeTicks::Now() - started_at; + UMA_HISTOGRAM_CUSTOM_TIMES("Media.MCVD.ForwardVideoFrameTiming", duration, + base::TimeDelta::FromMilliseconds(1), + base::TimeDelta::FromMilliseconds(100), 25); + // No |frame| indicates an error creating it. if (!frame) { DLOG(ERROR) << __func__ << " |frame| is null";
diff --git a/media/gpu/android/media_codec_video_decoder.h b/media/gpu/android/media_codec_video_decoder.h index c92548cd..721bee5 100644 --- a/media/gpu/android/media_codec_video_decoder.h +++ b/media/gpu/android/media_codec_video_decoder.h
@@ -179,9 +179,11 @@ // Forwards |frame| via |output_cb_| if |reset_generation| matches // |reset_generation_|. |async_trace| is the (optional) scoped trace that - // started when we dequeued the corresponding output buffer. + // started when we dequeued the corresponding output buffer. |started_at| is + // the wall clock time at which we dequeued the output buffer. void ForwardVideoFrame(int reset_generation, std::unique_ptr<ScopedAsyncTrace> async_trace, + base::TimeTicks started_at, scoped_refptr<VideoFrame> frame); // Starts draining the codec by queuing an EOS if required. It skips the drain
diff --git a/media/gpu/android/mock_shared_image_video_provider.cc b/media/gpu/android/mock_shared_image_video_provider.cc new file mode 100644 index 0000000..65122e3 --- /dev/null +++ b/media/gpu/android/mock_shared_image_video_provider.cc
@@ -0,0 +1,22 @@ +// 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 "media/gpu/android/mock_shared_image_video_provider.h" + +namespace media { + +MockSharedImageVideoProvider::RequestImageArgs::RequestImageArgs( + ImageReadyCB cb, + ImageSpec spec, + scoped_refptr<gpu::TextureOwner> texture_owner) + : cb_(std::move(cb)), + spec_(std::move(spec)), + texture_owner_(std::move(texture_owner)) {} + +MockSharedImageVideoProvider::RequestImageArgs::~RequestImageArgs() = default; + +MockSharedImageVideoProvider::MockSharedImageVideoProvider() = default; +MockSharedImageVideoProvider::~MockSharedImageVideoProvider() = default; + +} // namespace media
diff --git a/media/gpu/android/mock_shared_image_video_provider.h b/media/gpu/android/mock_shared_image_video_provider.h new file mode 100644 index 0000000..7d19831 --- /dev/null +++ b/media/gpu/android/mock_shared_image_video_provider.h
@@ -0,0 +1,77 @@ +// Copyright 2019 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#ifndef MEDIA_GPU_ANDROID_MOCK_SHARED_IMAGE_VIDEO_PROVIDER_H_ +#define MEDIA_GPU_ANDROID_MOCK_SHARED_IMAGE_VIDEO_PROVIDER_H_ + +#include "media/gpu/android/pooled_shared_image_video_provider.h" +#include "mojo/public/cpp/bindings/callback_helpers.h" +#include "testing/gmock/include/gmock/gmock.h" +#include "testing/gtest/include/gtest/gtest.h" + +namespace media { + +class MockSharedImageVideoProvider : public SharedImageVideoProvider { + public: + MockSharedImageVideoProvider(); + ~MockSharedImageVideoProvider(); + + void Initialize(GpuInitCB gpu_init_cb) { + Initialize_(gpu_init_cb); + gpu_init_cb_ = std::move(gpu_init_cb); + } + + MOCK_METHOD1(Initialize_, void(GpuInitCB& gpu_init_cb)); + + void RequestImage(ImageReadyCB cb, + const ImageSpec& spec, + scoped_refptr<gpu::TextureOwner> texture_owner) override { + requests_.emplace_back(std::move(cb), spec, std::move(texture_owner)); + + MockRequestImage(); + } + + MOCK_METHOD0(MockRequestImage, void()); + + // Provide an image for the least recent request. If |record| is provided, + // then we'll use it. Otherwise, we'll make one up. + void ProvideOneRequestedImage(ImageRecord* record = nullptr) { + ImageRecord tmp_record; + if (!record) { + record = &tmp_record; + record->release_cb = mojo::WrapCallbackWithDefaultInvokeIfNotRun( + base::BindOnce( + [](int* count, const gpu::SyncToken& sync_token) { (*count)++; }, + base::Unretained(&num_release_callbacks_)), + gpu::SyncToken()); + } + + auto& req = requests_.front(); + std::move(req.cb_).Run(std::move(*record)); + requests_.pop_front(); + } + + // Most recent arguments to Initialize. + GpuInitCB gpu_init_cb_; + + // Most recent arguments to RequestImage. + struct RequestImageArgs { + RequestImageArgs(ImageReadyCB cb, + ImageSpec spec, + scoped_refptr<gpu::TextureOwner> texture_owner); + ~RequestImageArgs(); + ImageReadyCB cb_; + ImageSpec spec_; + scoped_refptr<gpu::TextureOwner> texture_owner_; + }; + + std::list<RequestImageArgs> requests_; + + // Number of times a release callback has been called. + int num_release_callbacks_ = 0; +}; + +} // namespace media + +#endif // MEDIA_GPU_ANDROID_MOCK_SHARED_IMAGE_VIDEO_PROVIDER_H_
diff --git a/media/gpu/android/pooled_shared_image_video_provider.cc b/media/gpu/android/pooled_shared_image_video_provider.cc new file mode 100644 index 0000000..0415a15 --- /dev/null +++ b/media/gpu/android/pooled_shared_image_video_provider.cc
@@ -0,0 +1,222 @@ +// 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 "media/gpu/android/pooled_shared_image_video_provider.h" + +#include "gpu/command_buffer/common/sync_token.h" +#include "media/base/bind_to_current_loop.h" +#include "mojo/public/cpp/bindings/callback_helpers.h" + +namespace media { + +// static +std::unique_ptr<PooledSharedImageVideoProvider> +PooledSharedImageVideoProvider::Create( + scoped_refptr<base::SingleThreadTaskRunner> gpu_task_runner, + GetStubCB get_stub_cb, + std::unique_ptr<SharedImageVideoProvider> provider) { + return base::WrapUnique(new PooledSharedImageVideoProvider( + base::SequenceBound<GpuHelperImpl>(std::move(gpu_task_runner), + std::move(get_stub_cb)), + std::move(provider))); +} + +PooledSharedImageVideoProvider::PooledImage::PooledImage(const ImageSpec& spec, + ImageRecord record) + : spec(spec), record(std::move(record)) {} + +PooledSharedImageVideoProvider::PooledImage::~PooledImage() = default; + +PooledSharedImageVideoProvider::PendingRequest::PendingRequest( + const ImageSpec& spec, + ImageReadyCB cb) + : spec(spec), cb(std::move(cb)) {} + +PooledSharedImageVideoProvider::PendingRequest::~PendingRequest() = default; + +PooledSharedImageVideoProvider::PooledSharedImageVideoProvider( + base::SequenceBound<GpuHelper> gpu_helper, + std::unique_ptr<SharedImageVideoProvider> provider) + : provider_(std::move(provider)), + gpu_helper_(std::move(gpu_helper)), + weak_factory_(this) {} + +// Note that this will drop everything in |pool_|, which will call all the +// release callbacks for the underlying byffer. +PooledSharedImageVideoProvider::~PooledSharedImageVideoProvider() = default; + +// SharedImageVideoProvider +void PooledSharedImageVideoProvider::Initialize(GpuInitCB gpu_init_cb) { + provider_->Initialize(std::move(gpu_init_cb)); +} + +void PooledSharedImageVideoProvider::RequestImage( + ImageReadyCB cb, + const ImageSpec& spec, + scoped_refptr<gpu::TextureOwner> texture_owner) { + // See if the pool matches the requested spec. + if (pool_spec_ != spec) { + // Nope -- mark any outstanding images for destruction and start a new pool. + // Note that this calls all the release callbacks. + pool_.clear(); + + // Any images added to the pool should match |spec|. + pool_spec_ = spec; + } + + // Push this onto the pending requests. + // IMPORTANT BUT SUBTLE NOTE: |spec| doesn't mention the TextureOwner, but it + // is sent to the provider so it must also match the one that was used with + // |spec|. We assume that the generation id will be updated by our caller + // whenever the TextureOwner changes. While this is fragile, it's also just + // a temporary thing. Keeping a strong ref to |texture_owner| would probably + // work, but it's not good to keep refs to those around longer than needed. + // It might be okay to do that directly, since the request (if any) that's + // pending for it would have the strong ref, so maybe we could just add it + // here too. + pending_requests_.emplace_back(spec, std::move(cb)); + + // Are there any free images in the pool? If so, then pop one and use it to + // process the request we just pushed, assuming that it's the most recent. We + // could optimize this call out if |pending_requensts_| wasn't empty before, + // since we know it doesn't match the pool spec if the pool's not empty. As + // it is, it will just pop and re-push the pooled buffer in the (rare) case + // that the pool doesn't match. + if (!pool_.empty()) { + auto front = std::move(pool_.front()); + pool_.pop_front(); + ProcessFreePooledImage(front); + // TODO(liberato): See if skipping the return if |pool_| is now empty is + // helpful, especially during start-up. Alternatively, just request some + // constant number of images (~5) when the pool spec changes, then add them + // one at a time if needed. + return; + } + + // Request a new image, since we don't have enough. There might be some + // outstanding that will be returned, but we'd like to have enough not to wait + // on them. This has the nice property that everything in |pending_requests_| + // will have an image delivered in order for it. Note that we might not + // exactly match up returned (new) images to the requests; there might be + // intervening returns of existing images from the client that happen to match + // if we switch from spec A => spec B => spec A, but that's okay. We can be + // sure that there are at least as many that will arrive as we need. + auto ready_cb = + base::BindOnce(&PooledSharedImageVideoProvider::OnImageCreated, + weak_factory_.GetWeakPtr(), spec); + provider_->RequestImage(std::move(ready_cb), spec, std::move(texture_owner)); +} + +void PooledSharedImageVideoProvider::OnImageCreated(ImageSpec spec, + ImageRecord record) { + // Wrap |record| up for the pool, and process it. + scoped_refptr<PooledImage> pooled_image = + base::MakeRefCounted<PooledImage>(std::move(spec), std::move(record)); + ProcessFreePooledImage(pooled_image); +} + +void PooledSharedImageVideoProvider::OnImageReturned( + scoped_refptr<PooledImage> pooled_image, + const gpu::SyncToken& sync_token) { + // An image has been returned to us. Wait for |sync_token| and then send it + // to ProcessFreePooledImage to re-use / pool / delete. + gpu_helper_.Post(FROM_HERE, &GpuHelper::OnImageReturned, sync_token, + pooled_image->record.codec_image_holder, + BindToCurrentLoop(base::BindOnce( + &PooledSharedImageVideoProvider::ProcessFreePooledImage, + weak_factory_.GetWeakPtr(), pooled_image))); +} + +void PooledSharedImageVideoProvider::ProcessFreePooledImage( + scoped_refptr<PooledImage> pooled_image) { + // Are there any requests pending? + if (pending_requests_.size()) { + // See if |record| matches the top request. If so, fulfill it, else drop + // |record| since we don't need it. Note that it's possible to have pending + // requests that don't match the pool spec; the pool spec is the most recent + // request. There might be other ones that were made before that which we + // didn't fulfill yet. + auto& front = pending_requests_.front(); + if (pooled_image->spec == front.spec) { + // Construct a record that notifies us when the image is released. + // TODO(liberato): Don't copy fields this way. + ImageRecord record; + record.mailbox = pooled_image->record.mailbox; + record.is_vulkan = pooled_image->record.is_vulkan; + record.codec_image_holder = pooled_image->record.codec_image_holder; + // The release CB notifies us instead of |provider_|. + record.release_cb = mojo::WrapCallbackWithDefaultInvokeIfNotRun( + base::BindOnce(&PooledSharedImageVideoProvider::OnImageReturned, + weak_factory_.GetWeakPtr(), std::move(pooled_image)), + gpu::SyncToken()); + + // Save the callback and remove the request, in case |cb| calls us back. + auto cb = std::move(front.cb); + pending_requests_.pop_front(); + + std::move(cb).Run(std::move(record)); + return; + } + + // Can't fulfill the topmost request. Discard |pooled_image|, even if it + // matches the pool. The reason is that any pending requests will have + // images created for them, which we'll use when they arrive. It would be + // okay to store |pooled_image| in the pool if it matches, but then we'd + // have more pooled images than we expect. + return; + } + + // There are no outstanding image requests, or the top one doesn't match + // |pooled_image|. If this image is compatible with the pool, then pool it. + // Otherwise, discard it. + + // See if |record| matches |pool_spec_|. If not, then drop it. Otherwise, + // pool it for later. Note that we don't explicitly call the release cb, + // since dropping the image is sufficient to notify |provider_|. Note that + // we've already waited for any sync token at this point, so it's okay if we + // don't provide one to the underlying release cb. + if (pool_spec_ != pooled_image->spec) + return; + + // Add it to the pool. + pool_.push_front(std::move(pooled_image)); +} + +PooledSharedImageVideoProvider::GpuHelperImpl::GpuHelperImpl( + GetStubCB get_stub_cb) + : weak_factory_(this) { + gpu::CommandBufferStub* stub = get_stub_cb.Run(); + if (stub) { + stub->AddDestructionObserver(this); + command_buffer_helper_ = CommandBufferHelper::Create(stub); + } +} + +PooledSharedImageVideoProvider::GpuHelperImpl::~GpuHelperImpl() = default; + +void PooledSharedImageVideoProvider::GpuHelperImpl::OnImageReturned( + const gpu::SyncToken& sync_token, + scoped_refptr<CodecImageHolder> codec_image_holder, + base::OnceClosure cb) { + auto on_sync_token_cleared_cb = base::BindOnce( + &GpuHelperImpl::OnSyncTokenCleared, weak_factory_.GetWeakPtr(), + std::move(codec_image_holder), std::move(cb)); + command_buffer_helper_->WaitForSyncToken(sync_token, + std::move(on_sync_token_cleared_cb)); +} + +void PooledSharedImageVideoProvider::GpuHelperImpl::OnSyncTokenCleared( + scoped_refptr<CodecImageHolder> codec_image_holder, + base::OnceClosure cb) { + codec_image_holder->codec_image_raw()->NotifyUnused(); + // Do this last, since |cb| might post to some other thread. + std::move(cb).Run(); +} + +void PooledSharedImageVideoProvider::GpuHelperImpl::OnWillDestroyStub( + bool have_context) { + command_buffer_helper_ = nullptr; +} + +} // namespace media
diff --git a/media/gpu/android/pooled_shared_image_video_provider.h b/media/gpu/android/pooled_shared_image_video_provider.h new file mode 100644 index 0000000..c0ec44a --- /dev/null +++ b/media/gpu/android/pooled_shared_image_video_provider.h
@@ -0,0 +1,141 @@ +// 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 MEDIA_GPU_ANDROID_POOLED_SHARED_IMAGE_VIDEO_PROVIDER_H_ +#define MEDIA_GPU_ANDROID_POOLED_SHARED_IMAGE_VIDEO_PROVIDER_H_ + +#include "base/memory/weak_ptr.h" +#include "base/threading/sequence_bound.h" +#include "gpu/ipc/service/command_buffer_stub.h" +#include "media/gpu/android/shared_image_video_provider.h" +#include "media/gpu/command_buffer_helper.h" + +namespace media { + +class PooledSharedImageVideoProviderTest; + +// Provider class for shared images. +class MEDIA_GPU_EXPORT PooledSharedImageVideoProvider + : public SharedImageVideoProvider { + public: + // Helper class that processes image returns on the gpu thread. + class GpuHelper { + public: + GpuHelper() = default; + virtual ~GpuHelper() = default; + + // Called (on the gpu thread) to handle image return. + virtual void OnImageReturned( + const gpu::SyncToken& sync_token, + scoped_refptr<CodecImageHolder> codec_image_holder, + base::OnceClosure cb) = 0; + + private: + DISALLOW_COPY_AND_ASSIGN(GpuHelper); + }; + + // Create a default implementation. |provider| is the underlying provider to + // create shared images. + static std::unique_ptr<PooledSharedImageVideoProvider> Create( + scoped_refptr<base::SingleThreadTaskRunner> gpu_task_runner, + GetStubCB get_stub_cb, + std::unique_ptr<SharedImageVideoProvider> provider); + + ~PooledSharedImageVideoProvider() override; + + // SharedImageVideoProvider + void Initialize(GpuInitCB gpu_init_cb) override; + void RequestImage(ImageReadyCB cb, + const ImageSpec& spec, + scoped_refptr<gpu::TextureOwner> texture_owner) override; + + private: + friend class PooledSharedImageVideoProviderTest; + + PooledSharedImageVideoProvider( + base::SequenceBound<GpuHelper> gpu_helper, + std::unique_ptr<SharedImageVideoProvider> provider); + + class GpuHelperImpl : public GpuHelper, + public gpu::CommandBufferStub::DestructionObserver { + public: + GpuHelperImpl(GetStubCB get_stub_cb); + ~GpuHelperImpl() override; + + // GpuHelper + void OnImageReturned(const gpu::SyncToken& sync_token, + scoped_refptr<CodecImageHolder> codec_image_holder, + base::OnceClosure cb) override; + + // gpu::CommandBufferStub::DestructionObserver + void OnWillDestroyStub(bool have_context) override; + + private: + void OnSyncTokenCleared(scoped_refptr<CodecImageHolder> codec_image_holder, + base::OnceClosure cb); + + scoped_refptr<CommandBufferHelper> command_buffer_helper_; + base::WeakPtrFactory<GpuHelperImpl> weak_factory_; + }; + + // Record of on image from |provider|. + class PooledImage : public base::RefCounted<PooledImage> { + public: + PooledImage(const ImageSpec& spec, ImageRecord record); + + ImageSpec spec; + // The original record, including the original reuse callback. + ImageRecord record; + + private: + virtual ~PooledImage(); + + friend class base::RefCounted<PooledImage>; + }; + + // One request from the client that's pending an image. + class PendingRequest { + public: + PendingRequest(const ImageSpec& spec, ImageReadyCB cb); + ~PendingRequest(); + ImageSpec spec; + ImageReadyCB cb; + std::unique_ptr<CodecOutputBuffer> output_buffer; + scoped_refptr<gpu::TextureOwner> texture_owner; + PromotionHintAggregator::NotifyPromotionHintCB promotion_hint_cb; + }; + + // Called by |provider_| when a new image is created. + void OnImageCreated(ImageSpec spec, ImageRecord record); + + // Called by our client when it runs the release cb, to notify us that the + // image is no longer in use. + void OnImageReturned(scoped_refptr<PooledImage> pooled_image, + const gpu::SyncToken& sync_token); + + // Given a free image |pooled_image| that is not in our pool, use it to either + // fulfill a pending request, add it to the pool, or discard it. + void ProcessFreePooledImage(scoped_refptr<PooledImage> pooled_image); + + // Underlying provider that we use to construct images. + std::unique_ptr<SharedImageVideoProvider> provider_; + + // All currently unused images. + std::list<scoped_refptr<PooledImage>> pool_; + + // Spec for all images in |pool_|. + ImageSpec pool_spec_; + + std::list<PendingRequest> pending_requests_; + + base::SequenceBound<GpuHelper> gpu_helper_; + + base::WeakPtrFactory<PooledSharedImageVideoProvider> weak_factory_; + + DISALLOW_COPY_AND_ASSIGN(PooledSharedImageVideoProvider); +}; + +} // namespace media + +#endif // MEDIA_GPU_ANDROID_POOLED_SHARED_IMAGE_VIDEO_PROVIDER_H_
diff --git a/media/gpu/android/pooled_shared_image_video_provider_unittest.cc b/media/gpu/android/pooled_shared_image_video_provider_unittest.cc new file mode 100644 index 0000000..c561eed --- /dev/null +++ b/media/gpu/android/pooled_shared_image_video_provider_unittest.cc
@@ -0,0 +1,260 @@ +// 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 "media/gpu/android/pooled_shared_image_video_provider.h" + +#include <list> + +#include "base/test/mock_callback.h" +#include "base/test/task_environment.h" +#include "base/threading/sequenced_task_runner_handle.h" +#include "gpu/command_buffer/service/abstract_texture_impl_shared_context_state.h" +#include "gpu/ipc/common/command_buffer_id.h" +#include "media/gpu/android/mock_shared_image_video_provider.h" +#include "testing/gmock/include/gmock/gmock.h" +#include "testing/gtest/include/gtest/gtest.h" + +using testing::Mock; + +namespace media { + +class PooledSharedImageVideoProviderTest : public testing::Test { + public: + class MockGpuHelper : public PooledSharedImageVideoProvider::GpuHelper { + public: + MockGpuHelper(gpu::SyncToken* sync_token_out) + : sync_token_out_(sync_token_out) {} + + // PooledSharedImageVideoProvider::GpuHelper + void OnImageReturned(const gpu::SyncToken& sync_token, + scoped_refptr<CodecImageHolder> codec_image_holder, + base::OnceClosure cb) override { + *sync_token_out_ = sync_token; + + // Run the output cb. + std::move(cb).Run(); + } + + private: + gpu::SyncToken* sync_token_out_ = nullptr; + }; + + PooledSharedImageVideoProviderTest() = default; + + void SetUp() override { + task_runner_ = base::SequencedTaskRunnerHandle::Get(); + base::SequenceBound<MockGpuHelper> mock_gpu_helper(task_runner_, + &sync_token_); + + std::unique_ptr<MockSharedImageVideoProvider> mock_provider = + std::make_unique<MockSharedImageVideoProvider>(); + mock_provider_raw_ = mock_provider.get(); + + provider_ = base::WrapUnique(new PooledSharedImageVideoProvider( + std::move(mock_gpu_helper), std::move(mock_provider))); + } + + // Return an ImageReadyCB that saves the ImageRecord in |image_records_|. + SharedImageVideoProvider::ImageReadyCB SaveImageRecordCB() { + return base::BindOnce( + [](std::list<SharedImageVideoProvider::ImageRecord>* output_list, + SharedImageVideoProvider::ImageRecord record) { + output_list->push_back(std::move(record)); + }, + &image_records_); + } + + // Request an image from |provier_|, which we expect will call through to + // |mock_provider_raw_|. Have |mock_provider_raw_| return an image, too. + void RequestAndProvideImage(const SharedImageVideoProvider::ImageSpec& spec) { + EXPECT_CALL(*mock_provider_raw_, MockRequestImage()).Times(1); + provider_->RequestImage(SaveImageRecordCB(), spec, texture_owner_); + base::RunLoop().RunUntilIdle(); + Mock::VerifyAndClearExpectations(mock_provider_raw_); + mock_provider_raw_->ProvideOneRequestedImage(); + } + + base::test::TaskEnvironment task_environment_; + + scoped_refptr<base::SequencedTaskRunner> task_runner_; + + // Provider under test. + std::unique_ptr<PooledSharedImageVideoProvider> provider_; + + MockSharedImageVideoProvider* mock_provider_raw_ = nullptr; + gpu::SyncToken sync_token_; + + scoped_refptr<gpu::TextureOwner> texture_owner_; + + // Image records that we've received from |provider|, via SaveImageRecordCB(). + std::list<SharedImageVideoProvider::ImageRecord> image_records_; +}; + +TEST_F(PooledSharedImageVideoProviderTest, InitializeForwardsGpuCallback) { + bool was_called = false; + auto gpu_init_cb = base::BindOnce( + [](bool* flag, scoped_refptr<gpu::SharedContextState>) { *flag = true; }, + &was_called); + provider_->Initialize(std::move(gpu_init_cb)); + std::move(mock_provider_raw_->gpu_init_cb_).Run(nullptr); + base::RunLoop().RunUntilIdle(); + EXPECT_TRUE(was_called); +} + +TEST_F(PooledSharedImageVideoProviderTest, RequestImageRequestsMultipleImages) { + // Test the RequestImage will keep requesting images from the underlying + // provider as long as we don't return any. + SharedImageVideoProvider::ImageSpec spec(gfx::Size(1, 1), 0u); + RequestAndProvideImage(spec); + RequestAndProvideImage(spec); + RequestAndProvideImage(spec); + EXPECT_EQ(image_records_.size(), 3u); +} + +TEST_F(PooledSharedImageVideoProviderTest, ReleasingAnImageForwardsSyncToken) { + // Calling the release callback on an image should forward the sync token to + // our gpu helper. + SharedImageVideoProvider::ImageSpec spec(gfx::Size(1, 1), 0u); + RequestAndProvideImage(spec); + + gpu::SyncToken sync_token(gpu::CommandBufferNamespace::GPU_IO, + gpu::CommandBufferIdFromChannelAndRoute(2, 3), 4); + std::move(image_records_.back().release_cb).Run(sync_token); + base::RunLoop().RunUntilIdle(); + EXPECT_EQ(sync_token, sync_token_); +} + +TEST_F(PooledSharedImageVideoProviderTest, + ReleasingAnImageDoesntRunUnderlyingReleaseCallback) { + // Verify that releasing an image doesn't call the underlying release callback + // on it. Presumably, it should be sent back to the pool instead. + SharedImageVideoProvider::ImageSpec spec(gfx::Size(1, 1), 0u); + RequestAndProvideImage(spec); + + // Release the image. + image_records_.pop_back(); + base::RunLoop().RunUntilIdle(); + + EXPECT_EQ(mock_provider_raw_->num_release_callbacks_, 0); +} + +TEST_F(PooledSharedImageVideoProviderTest, RequestImageReusesReturnedImages) { + // Test the RequestImage will return images without requesting new ones, if + // some have been returned to the pool. + SharedImageVideoProvider::ImageSpec spec(gfx::Size(1, 1), 0u); + // Request two images. + RequestAndProvideImage(spec); + RequestAndProvideImage(spec); + EXPECT_EQ(image_records_.size(), 2u); + // Now return one, and request another. + image_records_.pop_back(); + // Let the release CB run. + base::RunLoop().RunUntilIdle(); + + // Shouldn't call MockRequestImage a third time. + EXPECT_CALL(*mock_provider_raw_, MockRequestImage()).Times(0); + provider_->RequestImage(SaveImageRecordCB(), spec, texture_owner_); + base::RunLoop().RunUntilIdle(); + EXPECT_EQ(image_records_.size(), 2u); +} + +TEST_F(PooledSharedImageVideoProviderTest, + DeletingProviderWithOutstandingImagesDoesntCrash) { + // Destroying |provider_| with outstanding images shouldn't break anything. + SharedImageVideoProvider::ImageSpec spec(gfx::Size(1, 1), 0u); + provider_->RequestImage(SaveImageRecordCB(), spec, texture_owner_); + base::RunLoop().RunUntilIdle(); + provider_.reset(); + base::RunLoop().RunUntilIdle(); + // Shouldn't crash. +} + +TEST_F(PooledSharedImageVideoProviderTest, + ReturnedImagesAreReleasedAfterSpecChange) { + // When we change the ImageSpec, old images should be released on the + // underlying provider as they are returned. + SharedImageVideoProvider::ImageSpec spec_1(gfx::Size(1, 1), 0u); + SharedImageVideoProvider::ImageSpec spec_2(gfx::Size(1, 2), 0u); + RequestAndProvideImage(spec_1); + RequestAndProvideImage(spec_2); + + EXPECT_EQ(mock_provider_raw_->num_release_callbacks_, 0); + + // Return image 1, and it should run the underlying release callback since it + // doesn't match the pool spec. + image_records_.pop_front(); + base::RunLoop().RunUntilIdle(); + EXPECT_EQ(mock_provider_raw_->num_release_callbacks_, 1); + + // Returning image 2 should not, since it should be put into the pool. + image_records_.pop_front(); + base::RunLoop().RunUntilIdle(); + EXPECT_EQ(mock_provider_raw_->num_release_callbacks_, 1); +} + +TEST_F(PooledSharedImageVideoProviderTest, SizeChangeEmptiesPool) { + // Verify that a size change in the ImageSpec causes the pool to be emptied. + SharedImageVideoProvider::ImageSpec spec_1(gfx::Size(1, 1), 0u); + SharedImageVideoProvider::ImageSpec spec_2(gfx::Size(1, 2), 0u); + + // Request an image with |spec_1| and release it, to send it to the pool. + RequestAndProvideImage(spec_1); + image_records_.pop_front(); + base::RunLoop().RunUntilIdle(); + EXPECT_EQ(mock_provider_raw_->num_release_callbacks_, 0); + + // Request an image with |spec_2|, which should release the first one. + RequestAndProvideImage(spec_2); + EXPECT_EQ(mock_provider_raw_->num_release_callbacks_, 1); +} + +TEST_F(PooledSharedImageVideoProviderTest, GenerationIdChangeEmptiesPool) { + // Verify that a change in the generation id causes the pool to be emptied. + SharedImageVideoProvider::ImageSpec spec_1(gfx::Size(1, 1), 0u); + SharedImageVideoProvider::ImageSpec spec_2(gfx::Size(1, 1), 1u); + RequestAndProvideImage(spec_1); + image_records_.pop_front(); + base::RunLoop().RunUntilIdle(); + RequestAndProvideImage(spec_2); + EXPECT_EQ(mock_provider_raw_->num_release_callbacks_, 1); +} + +TEST_F(PooledSharedImageVideoProviderTest, InFlightSpecChangeProvidesImage) { + // If we change the ImageSpec between requesting and receiving an image from + // the provider, it should still provide the image to the requestor. + SharedImageVideoProvider::ImageSpec spec_1(gfx::Size(1, 1), 0u); + SharedImageVideoProvider::ImageSpec spec_2(gfx::Size(1, 1), 1u); + + // Request both images before providing either. + EXPECT_CALL(*mock_provider_raw_, MockRequestImage()).Times(2); + provider_->RequestImage(SaveImageRecordCB(), spec_1, texture_owner_); + provider_->RequestImage(SaveImageRecordCB(), spec_2, texture_owner_); + base::RunLoop().RunUntilIdle(); + + // Provide the |spec_1| image. Nothing should be released since it should + // fulfill the first request. + mock_provider_raw_->ProvideOneRequestedImage(); + base::RunLoop().RunUntilIdle(); + EXPECT_EQ(mock_provider_raw_->num_release_callbacks_, 0); + EXPECT_EQ(image_records_.size(), 1u); + + // Provide the |spec_2| image, which should also be provided to us. + mock_provider_raw_->ProvideOneRequestedImage(); + base::RunLoop().RunUntilIdle(); + EXPECT_EQ(mock_provider_raw_->num_release_callbacks_, 0); + EXPECT_EQ(image_records_.size(), 2u); + + // Drop the |spec_1| image, which should be released rather than added back to + // the pool. + image_records_.pop_front(); + base::RunLoop().RunUntilIdle(); + EXPECT_EQ(mock_provider_raw_->num_release_callbacks_, 1); + + // Drop the |spec_2| image, which should be pooled rather than released. + image_records_.pop_front(); + base::RunLoop().RunUntilIdle(); + EXPECT_EQ(mock_provider_raw_->num_release_callbacks_, 1); +} + +} // namespace media
diff --git a/media/gpu/android/shared_image_video_provider.cc b/media/gpu/android/shared_image_video_provider.cc index 445acd0..c543495f 100644 --- a/media/gpu/android/shared_image_video_provider.cc +++ b/media/gpu/android/shared_image_video_provider.cc
@@ -6,11 +6,23 @@ namespace media { -SharedImageVideoProvider::ImageSpec::ImageSpec(const gfx::Size& our_size) - : size(our_size) {} +SharedImageVideoProvider::ImageSpec::ImageSpec() = default; +SharedImageVideoProvider::ImageSpec::ImageSpec(const gfx::Size& our_size, + uint64_t our_generation_id) + : size(our_size), generation_id(our_generation_id) {} SharedImageVideoProvider::ImageSpec::ImageSpec(const ImageSpec&) = default; SharedImageVideoProvider::ImageSpec::~ImageSpec() = default; +bool SharedImageVideoProvider::ImageSpec::operator==( + const ImageSpec& rhs) const { + return size == rhs.size && generation_id == rhs.generation_id; +} + +bool SharedImageVideoProvider::ImageSpec::operator!=( + const ImageSpec& rhs) const { + return !(*this == rhs); +} + SharedImageVideoProvider::ImageRecord::ImageRecord() = default; SharedImageVideoProvider::ImageRecord::ImageRecord(ImageRecord&&) = default; SharedImageVideoProvider::ImageRecord::~ImageRecord() = default;
diff --git a/media/gpu/android/shared_image_video_provider.h b/media/gpu/android/shared_image_video_provider.h index 4e1ea50db..83332f5 100644 --- a/media/gpu/android/shared_image_video_provider.h +++ b/media/gpu/android/shared_image_video_provider.h
@@ -30,16 +30,28 @@ // Description of the underlying properties of the shared image. struct ImageSpec { - ImageSpec(const gfx::Size& size); + ImageSpec(); + ImageSpec(const gfx::Size& size, uint64_t generation_id); ImageSpec(const ImageSpec&); ~ImageSpec(); // Size of the underlying texture. gfx::Size size; + // This is a hack to allow us to discard pooled images if the TextureOwner + // changes. We don't want to keep a ref to the TextureOwner here, so we + // just use a generation counter. Note that this is temporary anyway; we + // only need it for legacy mailbox support to construct a per-video-frame + // texture with the TextureOwner's service id (unowned texture hack). Once + // legacy mailboxes aren't needed, SharedImageVideo::BeginAccess can just + // ask the CodecImage for whatever TextureOwner it is using currently, which + // is set by the client via CodecImage::Initialize. + uint64_t generation_id = 0; + // TODO: Include other properties, if they matter, like texture format. - bool operator==(const ImageSpec&); + bool operator==(const ImageSpec&) const; + bool operator!=(const ImageSpec&) const; }; using ReleaseCB = base::OnceCallback<void(const gpu::SyncToken&)>; @@ -57,7 +69,8 @@ // considered to be unused. ReleaseCB release_cb; - // CodecImage that one can use for MaybeRenderEarly. + // CodecImage that one can use for MaybeRenderEarly, and to attach a codec + // output buffer. scoped_refptr<CodecImageHolder> codec_image_holder; // Is the underlying context Vulkan? If so, then one must provide YCbCrInfo
diff --git a/media/gpu/android/video_frame_factory_impl.cc b/media/gpu/android/video_frame_factory_impl.cc index cced87f..ce422d0 100644 --- a/media/gpu/android/video_frame_factory_impl.cc +++ b/media/gpu/android/video_frame_factory_impl.cc
@@ -109,6 +109,11 @@ void VideoFrameFactoryImpl::SetSurfaceBundle( scoped_refptr<CodecSurfaceBundle> surface_bundle) { scoped_refptr<CodecImageGroup> image_group; + + // Increase the generation ID used by the shared image provider, since we're + // changing the TextureOwner. This is temporary. See ImageSpec. + image_spec_.generation_id++; + if (!surface_bundle) { // Clear everything, just so we're not holding a reference. codec_buffer_wait_coordinator_ = nullptr; @@ -154,7 +159,8 @@ return; } - SharedImageVideoProvider::ImageSpec spec(coded_size); + // Update the current spec to match the size. + image_spec_.size = coded_size; auto image_ready_cb = base::BindOnce( &VideoFrameFactoryImpl::CreateVideoFrame_OnImageReady, @@ -164,7 +170,7 @@ enable_threaded_texture_mailboxes_, gpu_task_runner_); image_provider_->RequestImage( - std::move(image_ready_cb), spec, + std::move(image_ready_cb), image_spec_, codec_buffer_wait_coordinator_ ? codec_buffer_wait_coordinator_->texture_owner() : nullptr); @@ -194,6 +200,9 @@ // on the gpu main thread here, but it's okay since CodecImage is not being // used at this point. Alternatively, we could post it, or hand it off to the // MaybeRenderEarlyManager to save a post. + // + // When we remove the output buffer management from CodecImage, then that's + // what we'd have a reference to here rather than CodecImage. record.codec_image_holder->codec_image_raw()->Initialize( std::move(output_buffer), codec_buffer_wait_coordinator, std::move(promotion_hint_cb)); @@ -261,18 +270,6 @@ mailbox_holders[0] = gpu::MailboxHolder(record.mailbox, gpu::SyncToken(), GL_TEXTURE_EXTERNAL_OES); - // TODO(liberato): We should set the promotion hint cb here on the image. We - // should also set the output buffer params; we shouldn't send the output - // buffer to the gpu thread, since the codec image isn't in use anyway. We - // can access it on any thread. We'll also need to get new images when we - // switch texture owners. That's left for future work. - - // TODO(liberato): When we switch to a pool, we need to provide some way to - // call MaybeRenderEarly that doesn't depend on |release_cb|. I suppose we - // could get a RepeatingCallback that's a "reuse cb", that we'd attach to the - // VideoFrame's release cb, since we have to wait for the sync token anyway. - // That would run on the gpu thread, and could MaybeRenderEarly. - gfx::Rect visible_rect(coded_size); auto frame = VideoFrame::WrapNativeTextures( @@ -334,12 +331,24 @@ void VideoFrameFactoryImpl::RunAfterPendingVideoFrames( base::OnceClosure closure) { DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_); - // Hop through |gpu_task_runner_| to ensure it comes after pending frames. - // TODO(liberato): If we're using a pool for SharedImageVideo, then this - // doesn't really make much sense. SharedImageVideoProvider should do this - // for us instead. - gpu_task_runner_->PostTaskAndReply(FROM_HERE, base::DoNothing(), - std::move(closure)); + + // Run |closure| after we receive an image from |image_provider_|. We don't + // need the image, but it guarantees that it's ordered after all previous + // requests have been fulfilled. + + auto image_ready_cb = base::BindOnce( + [](base::OnceClosure closure, + SharedImageVideoProvider::ImageRecord record) { + // Ignore |record| since we don't actually need an image. + std::move(closure).Run(); + }, + std::move(closure)); + + image_provider_->RequestImage( + std::move(image_ready_cb), image_spec_, + codec_buffer_wait_coordinator_ + ? codec_buffer_wait_coordinator_->texture_owner() + : nullptr); } } // namespace media
diff --git a/media/gpu/android/video_frame_factory_impl.h b/media/gpu/android/video_frame_factory_impl.h index 8352166..02ccf9e 100644 --- a/media/gpu/android/video_frame_factory_impl.h +++ b/media/gpu/android/video_frame_factory_impl.h
@@ -137,6 +137,9 @@ // Optional helper to get the Vulkan YCbCrInfo. base::SequenceBound<YCbCrHelper> ycbcr_helper_; + // The current image spec that we'll use to request images. + SharedImageVideoProvider::ImageSpec image_spec_; + SEQUENCE_CHECKER(sequence_checker_); base::WeakPtrFactory<VideoFrameFactoryImpl> weak_factory_{this};
diff --git a/media/gpu/android/video_frame_factory_impl_unittest.cc b/media/gpu/android/video_frame_factory_impl_unittest.cc index f33c6ab..0e7d94d0 100644 --- a/media/gpu/android/video_frame_factory_impl_unittest.cc +++ b/media/gpu/android/video_frame_factory_impl_unittest.cc
@@ -18,6 +18,7 @@ #include "media/gpu/android/codec_buffer_wait_coordinator.h" #include "media/gpu/android/maybe_render_early_manager.h" #include "media/gpu/android/mock_codec_image.h" +#include "media/gpu/android/mock_shared_image_video_provider.h" #include "media/gpu/android/shared_image_video_provider.h" #include "testing/gmock/include/gmock/gmock.h" #include "testing/gtest/include/gtest/gtest.h" @@ -39,32 +40,6 @@ MOCK_METHOD0(MaybeRenderEarly, void()); }; -class MockSharedImageVideoProvider : public SharedImageVideoProvider { - public: - MockSharedImageVideoProvider() : spec_(gfx::Size(0, 0)) {} - - void Initialize(GpuInitCB gpu_init_cb) { Initialize_(gpu_init_cb); } - - MOCK_METHOD1(Initialize_, void(GpuInitCB& gpu_init_cb)); - - void RequestImage(ImageReadyCB cb, - const ImageSpec& spec, - scoped_refptr<gpu::TextureOwner> texture_owner) override { - cb_ = std::move(cb); - spec_ = spec; - texture_owner_ = std::move(texture_owner); - - MockRequestImage(); - } - - MOCK_METHOD0(MockRequestImage, void()); - - // Most recent arguments to RequestImage. - ImageReadyCB cb_; - ImageSpec spec_; - scoped_refptr<gpu::TextureOwner> texture_owner_; -}; - class MockYCbCrHelper : public YCbCrHelper, public DestructionObservable { public: MockYCbCrHelper(MockYCbCrHelper** thiz) { *thiz = this; } @@ -123,6 +98,9 @@ VideoFrame::IsValidConfig(PIXEL_FORMAT_ARGB, VideoFrame::STORAGE_OPAQUE, coded_size, visible_rect, natural_size)); + // Save a copy in case the test wants it. + output_buffer_raw_ = output_buffer.get(); + // We should get a call to the output callback, but no calls to the // provider. // TODO(liberato): Verify that it's sending the proper TextureOwner. @@ -241,7 +219,7 @@ auto record = MakeImageRecord(&release_cb_called_flag); scoped_refptr<CodecImage> codec_image( record.codec_image_holder->codec_image_raw()); - std::move(image_provider_raw_->cb_).Run(std::move(record)); + image_provider_raw_->ProvideOneRequestedImage(&record); base::RunLoop().RunUntilIdle(); EXPECT_NE(frame, nullptr); @@ -271,7 +249,7 @@ RequestVideoFrame(); auto image_record = MakeImageRecord(); image_record.is_vulkan = false; - std::move(image_provider_raw_->cb_).Run(std::move(image_record)); + image_provider_raw_->ProvideOneRequestedImage(&image_record); base::RunLoop().RunUntilIdle(); } @@ -283,7 +261,7 @@ MockGetYCbCrInfo(image_record.codec_image_holder)) .Times(1); image_record.is_vulkan = true; - std::move(image_provider_raw_->cb_).Run(std::move(image_record)); + image_provider_raw_->ProvideOneRequestedImage(&image_record); base::RunLoop().RunUntilIdle(); // Provide YCbCrInfo. It should provide the VideoFrame too. @@ -307,7 +285,7 @@ if (ycbcr_helper_raw_) EXPECT_CALL(*ycbcr_helper_raw_, MockGetYCbCrInfo(_)).Times(0); EXPECT_CALL(output_cb_, Run(_)).Times(1); - std::move(image_provider_raw_->cb_).Run(std::move(other_image_record)); + image_provider_raw_->ProvideOneRequestedImage(&other_image_record); base::RunLoop().RunUntilIdle(); }
diff --git a/media/media_options.gni b/media/media_options.gni index 375f50a3..dfcad0e 100644 --- a/media/media_options.gni +++ b/media/media_options.gni
@@ -63,9 +63,9 @@ # Enables AC3/EAC3 audio demuxing. This is enabled only on Chromecast, since # it only provides demuxing, and is only useful for AC3/EAC3 audio # pass-through to HDMI sink on Chromecast. - enable_ac3_eac3_audio_demuxing = proprietary_codecs && is_chromecast + enable_platform_ac3_eac3_audio = proprietary_codecs && is_chromecast - enable_mpeg_h_audio_demuxing = proprietary_codecs && is_chromecast + enable_platform_mpeg_h_audio = proprietary_codecs && is_chromecast enable_mse_mpeg2ts_stream_parser = proprietary_codecs && (is_chromecast || is_fuchsia || use_fuzzing_engine) @@ -82,7 +82,7 @@ # Enable Dolby Vision demuxing. Enable by default for Chromecast. Actual # decoding must be provided by the platform. Note some Dolby Vision profiles # which are encoded using HEVC require |enable_platform_hevc| to be enabled. - enable_dolby_vision_demuxing = proprietary_codecs && is_chromecast + enable_platform_dolby_vision = proprietary_codecs && is_chromecast # Enable HLS with SAMPLE-AES decryption. enable_hls_sample_aes = proprietary_codecs && is_chromecast
diff --git a/media/mojo/clients/mojo_renderer_unittest.cc b/media/mojo/clients/mojo_renderer_unittest.cc index b947a13..53d55bf 100644 --- a/media/mojo/clients/mojo_renderer_unittest.cc +++ b/media/mojo/clients/mojo_renderer_unittest.cc
@@ -61,8 +61,10 @@ class MojoRendererTest : public ::testing::Test { public: MojoRendererTest() - : mojo_cdm_service_(&cdm_factory_, &mojo_cdm_service_context_), - cdm_binding_(&mojo_cdm_service_) { + : mojo_cdm_service_( + std::make_unique<MojoCdmService>(&cdm_factory_, + &mojo_cdm_service_context_)), + cdm_binding_(mojo_cdm_service_.get()) { std::unique_ptr<StrictMock<MockRenderer>> mock_renderer( new StrictMock<MockRenderer>()); mock_renderer_ = mock_renderer.get(); @@ -215,7 +217,7 @@ // Service side bindings (declaration order is critical). MojoCdmServiceContext mojo_cdm_service_context_; DefaultCdmFactory cdm_factory_; - MojoCdmService mojo_cdm_service_; + std::unique_ptr<MojoCdmService> mojo_cdm_service_; mojo::Binding<mojom::ContentDecryptionModule> cdm_binding_; // Service side mocks and helpers. @@ -306,6 +308,30 @@ SetCdmAndExpect(false); } +TEST_F(MojoRendererTest, SetCdm_ReleasedCdmId) { + // The CdmContext set on |mock_renderer_|. + CdmContext* mock_renderer_cdm_context = nullptr; + + Initialize(); + CreateCdm(); + EXPECT_CALL(*mock_renderer_, SetCdm(_, _)) + .WillOnce( + DoAll(SaveArg<0>(&mock_renderer_cdm_context), RunCallback<1>(true))); + SetCdmAndExpect(true); + EXPECT_TRUE(mock_renderer_cdm_context); + + // Release the CDM. + mojo_cdm_service_.reset(); + base::RunLoop().RunUntilIdle(); + + // SetCdm() on |mock_renderer_| should not be called. + SetCdmAndExpect(false); + + // The CDM should still be around since it's set on the |mock_renderer_|. It + // should have a Decryptor since we use kClearKeyKeySystem. + EXPECT_TRUE(mock_renderer_cdm_context->GetDecryptor()); +} + TEST_F(MojoRendererTest, SetCdm_BeforeInitialize) { CreateCdm(); EXPECT_CALL(*mock_renderer_, SetCdm(_, _)).WillOnce(RunCallback<1>(true));
diff --git a/media/mojo/services/gpu_mojo_media_client.cc b/media/mojo/services/gpu_mojo_media_client.cc index 7bae02547..47e48bb 100644 --- a/media/mojo/services/gpu_mojo_media_client.cc +++ b/media/mojo/services/gpu_mojo_media_client.cc
@@ -33,6 +33,7 @@ #include "media/gpu/android/direct_shared_image_video_provider.h" #include "media/gpu/android/maybe_render_early_manager.h" #include "media/gpu/android/media_codec_video_decoder.h" +#include "media/gpu/android/pooled_shared_image_video_provider.h" #include "media/gpu/android/video_frame_factory_impl.h" #include "media/mojo/mojom/media_drm_storage.mojom.h" #include "media/mojo/mojom/provision_fetcher.mojom.h" @@ -208,8 +209,14 @@ auto get_stub_cb = base::Bind( &GetCommandBufferStub, gpu_task_runner_, media_gpu_channel_manager_, command_buffer_id->channel_token, command_buffer_id->route_id); - auto image_provider = std::make_unique<DirectSharedImageVideoProvider>( + std::unique_ptr<SharedImageVideoProvider> image_provider; + image_provider = std::make_unique<DirectSharedImageVideoProvider>( gpu_task_runner_, get_stub_cb); + if (base::FeatureList::IsEnabled(kUsePooledSharedImageVideoProvider)) { + // Wrap |image_provider| in a pool. + image_provider = PooledSharedImageVideoProvider::Create( + gpu_task_runner_, get_stub_cb, std::move(image_provider)); + } // TODO(liberato): Create this only if we're using Vulkan, else it's // ignored. If we can tell that here, then VideoFrameFactory can use it // as a signal about whether it's supposed to get YCbCrInfo rather than
diff --git a/net/BUILD.gn b/net/BUILD.gn index b4927e0..1cfbf2596 100644 --- a/net/BUILD.gn +++ b/net/BUILD.gn
@@ -2787,6 +2787,8 @@ "ssl/test_ssl_config_service.h", "ssl/test_ssl_private_key.cc", "ssl/test_ssl_private_key.h", + "test/cert_builder.cc", + "test/cert_builder.h", "test/cert_test_util.cc", "test/cert_test_util.h", "test/cert_test_util_nss.cc",
diff --git a/net/base/escape.cc b/net/base/escape.cc index 3521f9e..c9f4aec 100644 --- a/net/base/escape.cc +++ b/net/base/escape.cc
@@ -193,8 +193,6 @@ // TODO(https://crbug.com/829873): Try to make this use icu, both to // protect against regressions as the Unicode standard is updated and to // reduce the number of long lists of characters. - // TODO(https://crbug.com/824715): Add default ignorable and formatting - // code points. return !( // Per http://tools.ietf.org/html/rfc3987#section-4.1, certain BiDi // control characters are not allowed to appear unescaped in URLs. @@ -241,7 +239,62 @@ code_point == 0x2029 || // PARAGRAPH SEPARATOR (%E2%80%A9) code_point == 0x202F || // NARROW NO-BREAK SPACE (%E2%80%AF) code_point == 0x205F || // MEDIUM MATHEMATICAL SPACE (%E2%81%9F) - code_point == 0x3000); // IDEOGRAPHIC SPACE (%E3%80%80) + code_point == 0x3000 || // IDEOGRAPHIC SPACE (%E3%80%80) + + // Default Ignorable ([:Default_Ignorable_Code_Point=Yes:]) and Format + // characters ([:Cf:]) are also banned (see crbug.com/824715). + code_point == 0x00AD || // SOFT HYPHEN (%C2%AD) + code_point == 0x034F || // COMBINING GRAPHEME JOINER (%CD%8F) + // Arabic number formatting + (code_point >= 0x0600 && code_point <= 0x0605) || + // U+061C is already banned as a BiDi control character. + code_point == 0x06DD || // ARABIC END OF AYAH (%DB%9D) + code_point == 0x070F || // SYRIAC ABBREVIATION MARK (%DC%8F) + code_point == 0x08E2 || // ARABIC DISPUTED END OF AYAH (%E0%A3%A2) + code_point == 0x115F || // HANGUL CHOSEONG FILLER (%E1%85%9F) + code_point == 0x1160 || // HANGUL JUNGSEONG FILLER (%E1%85%A0) + code_point == 0x17B4 || // KHMER VOWEL INHERENT AQ (%E1%9E%B4) + code_point == 0x17B5 || // KHMER VOWEL INHERENT AA (%E1%9E%B5) + code_point == 0x180B || // MONGOLIAN FREE VARIATION SELECTOR ONE + // (%E1%A0%8B) + code_point == 0x180C || // MONGOLIAN FREE VARIATION SELECTOR TWO + // (%E1%A0%8C) + code_point == 0x180D || // MONGOLIAN FREE VARIATION SELECTOR THREE + // (%E1%A0%8D) + code_point == 0x180E || // MONGOLIAN VOWEL SEPARATOR (%E1%A0%8E) + code_point == 0x200B || // ZERO WIDTH SPACE (%E2%80%8B) + code_point == 0x200C || // ZERO WIDTH SPACE NON-JOINER (%E2%80%8C) + code_point == 0x200D || // ZERO WIDTH JOINER (%E2%80%8D) + // U+200E, U+200F, U+202A--202E, and U+2066--2069 are already banned as + // BiDi control characters. + code_point == 0x2060 || // WORD JOINER (%E2%81%A0) + code_point == 0x2061 || // FUNCTION APPLICATION (%E2%81%A1) + code_point == 0x2062 || // INVISIBLE TIMES (%E2%81%A2) + code_point == 0x2063 || // INVISIBLE SEPARATOR (%E2%81%A3) + code_point == 0x2064 || // INVISIBLE PLUS (%E2%81%A4) + code_point == 0x2065 || // null (%E2%81%A5) + // 0x2066--0x2069 are already banned as a BiDi control characters. + // General Punctuation - Deprecated (U+206A--206F) + (code_point >= 0x206A && code_point <= 0x206F) || + code_point == 0x3164 || // HANGUL FILLER (%E3%85%A4) + (code_point >= 0xFFF0 && code_point <= 0xFFF8) || // null + // Variation selectors (%EF%B8%80 -- %EF%B8%8F) + (code_point >= 0xFE00 && code_point <= 0xFE0F) || + code_point == 0xFEFF || // ZERO WIDTH NO-BREAK SPACE (%EF%BB%BF) + code_point == 0xFFA0 || // HALFWIDTH HANGUL FILLER (%EF%BE%A0) + code_point == 0xFFF9 || // INTERLINEAR ANNOTATION ANCHOR (%EF%BF%B9) + code_point == 0xFFFA || // INTERLINEAR ANNOTATION SEPARATOR (%EF%BF%BA) + code_point == 0xFFFB || // INTERLINEAR ANNOTATION TERMINATOR (%EF%BF%BB) + code_point == 0x110BD || // KAITHI NUMBER SIGN (%F0%91%82%BD) + code_point == 0x110CD || // KAITHI NUMBER SIGN ABOVE (%F0%91%83%8D) + // Egyptian hieroglyph formatting (%F0%93%90%B0 -- %F0%93%90%B8) + (code_point >= 0x13430 && code_point <= 0x13438) || + // Shorthand format controls (%F0%9B%B2%A0 -- %F0%9B%B2%A3) + (code_point >= 0x1BCA0 && code_point <= 0x1BCA3) || + // Beams and slurs (%F0%9D%85%B3 -- %F0%9D%85%BA) + (code_point >= 0x1D173 && code_point <= 0x1D17A) || + // Tags, Variation Selectors, nulls + (code_point >= 0xE0000 && code_point <= 0xE0FFF)); } // Unescapes |escaped_text| according to |rules|, returning the resulting
diff --git a/net/base/escape_unittest.cc b/net/base/escape_unittest.cc index 57be371..a6dd0d5 100644 --- a/net/base/escape_unittest.cc +++ b/net/base/escape_unittest.cc
@@ -204,6 +204,48 @@ {"(%E2%80%AF)(%E2%81%9F)(%E3%80%80)", UnescapeRule::NORMAL, "(%E2%80%AF)(%E2%81%9F)(%E3%80%80)"}, + // Default Ignorable and Formatting characters should not be unescaped. + {"(%E2%81%A5)(%EF%BF%B0)(%EF%BF%B8)", UnescapeRule::NORMAL, + "(%E2%81%A5)(%EF%BF%B0)(%EF%BF%B8)"}, + {"(%F3%A0%82%80)(%F3%A0%83%BF)(%F3%A0%87%B0)", UnescapeRule::NORMAL, + "(%F3%A0%82%80)(%F3%A0%83%BF)(%F3%A0%87%B0)"}, + {"(%F3%A0%BF%BF)(%C2%AD)(%CD%8F)", UnescapeRule::NORMAL, + "(%F3%A0%BF%BF)(%C2%AD)(%CD%8F)"}, + {"(%D8%80%20)(%D8%85)(%DB%9D)(%DC%8F)(%E0%A3%A2)", UnescapeRule::NORMAL, + "(%D8%80%20)(%D8%85)(%DB%9D)(%DC%8F)(%E0%A3%A2)"}, + {"(%E1%85%9F)(%E1%85%A0)(%E1%9E%B4)(%E1%9E%B5)", UnescapeRule::NORMAL, + "(%E1%85%9F)(%E1%85%A0)(%E1%9E%B4)(%E1%9E%B5)"}, + {"(%E1%A0%8B)(%E1%A0%8C)(%E1%A0%8D)(%E1%A0%8E)", UnescapeRule::NORMAL, + "(%E1%A0%8B)(%E1%A0%8C)(%E1%A0%8D)(%E1%A0%8E)"}, + {"(%E2%80%8B)(%E2%80%8C)(%E2%80%8D)(%E2%81%A0)", UnescapeRule::NORMAL, + "(%E2%80%8B)(%E2%80%8C)(%E2%80%8D)(%E2%81%A0)"}, + {"(%E2%81%A1)(%E2%81%A2)(%E2%81%A3)(%E2%81%A4)", UnescapeRule::NORMAL, + "(%E2%81%A1)(%E2%81%A2)(%E2%81%A3)(%E2%81%A4)"}, + {"(%E3%85%A4)(%EF%BB%BF)(%EF%BE%A0)(%EF%BF%B9)", UnescapeRule::NORMAL, + "(%E3%85%A4)(%EF%BB%BF)(%EF%BE%A0)(%EF%BF%B9)"}, + {"(%EF%BF%BB)(%F0%91%82%BD)(%F0%91%83%8D)", UnescapeRule::NORMAL, + "(%EF%BF%BB)(%F0%91%82%BD)(%F0%91%83%8D)"}, + {"(%F0%93%90%B0)(%F0%93%90%B8)", UnescapeRule::NORMAL, + "(%F0%93%90%B0)(%F0%93%90%B8)"}, + // General Punctuation - Deprecated (U+206A--206F) + {"(%E2%81%AA)(%E2%81%AD)(%E2%81%AF)", UnescapeRule::NORMAL, + "(%E2%81%AA)(%E2%81%AD)(%E2%81%AF)"}, + // Variation selectors (U+FE00--FE0F) + {"(%EF%B8%80)(%EF%B8%8C)(%EF%B8%8D)", UnescapeRule::NORMAL, + "(%EF%B8%80)(%EF%B8%8C)(%EF%B8%8D)"}, + // Shorthand format controls (U+1BCA0--1BCA3) + {"(%F0%9B%B2%A0)(%F0%9B%B2%A1)(%F0%9B%B2%A3)", UnescapeRule::NORMAL, + "(%F0%9B%B2%A0)(%F0%9B%B2%A1)(%F0%9B%B2%A3)"}, + // Musical symbols beams and slurs (U+1D173--1D17A) + {"(%F0%9D%85%B3)(%F0%9D%85%B9)(%F0%9D%85%BA)", UnescapeRule::NORMAL, + "(%F0%9D%85%B3)(%F0%9D%85%B9)(%F0%9D%85%BA)"}, + // Tags block (U+E0000--E007F), includes unassigned points + {"(%F3%A0%80%80)(%F3%A0%80%81)(%F3%A0%81%8F)", UnescapeRule::NORMAL, + "(%F3%A0%80%80)(%F3%A0%80%81)(%F3%A0%81%8F)"}, + // Ideographic-specific variation selectors (U+E0100--E01EF) + {"(%F3%A0%84%80)(%F3%A0%84%90)(%F3%A0%87%AF)", UnescapeRule::NORMAL, + "(%F3%A0%84%80)(%F3%A0%84%90)(%F3%A0%87%AF)"}, + // Two spoofing characters in a row should not be unescaped. {"%D8%9C%D8%9C", UnescapeRule::NORMAL, "%D8%9C%D8%9C"}, // Non-spoofing characters surrounded by spoofing characters should be
diff --git a/net/cert/cert_verify_proc_unittest.cc b/net/cert/cert_verify_proc_unittest.cc index b8a4eec..1a3cf326 100644 --- a/net/cert/cert_verify_proc_unittest.cc +++ b/net/cert/cert_verify_proc_unittest.cc
@@ -22,8 +22,6 @@ #include "base/test/task_environment.h" #include "base/threading/thread.h" #include "build/build_config.h" -#include "crypto/openssl_util.h" -#include "crypto/rsa_private_key.h" #include "crypto/sha2.h" #include "net/base/net_errors.h" #include "net/cert/asn1_util.h" @@ -41,11 +39,11 @@ #include "net/cert/x509_certificate.h" #include "net/cert/x509_util.h" #include "net/cert_net/cert_net_fetcher_impl.h" -#include "net/der/encode_values.h" #include "net/der/input.h" #include "net/der/parser.h" #include "net/proxy_resolution/proxy_config.h" #include "net/proxy_resolution/proxy_config_service_fixed.h" +#include "net/test/cert_builder.h" #include "net/test/cert_test_util.h" #include "net/test/embedded_test_server/embedded_test_server.h" #include "net/test/embedded_test_server/http_request.h" @@ -272,16 +270,6 @@ #endif } -// Helper to make creating an X509Certificate chain less verbose. -scoped_refptr<X509Certificate> CreateX509CertificateWithIntermediate( - bssl::UniquePtr<CRYPTO_BUFFER> cert_buffer, - bssl::UniquePtr<CRYPTO_BUFFER> intermediate_buffer) { - std::vector<bssl::UniquePtr<CRYPTO_BUFFER>> intermediates; - intermediates.push_back(std::move(intermediate_buffer)); - return X509Certificate::CreateFromBuffer(std::move(cert_buffer), - std::move(intermediates)); -} - std::string MakeRandomHexString(size_t num_bytes) { std::vector<char> rand_bytes; rand_bytes.resize(num_bytes); @@ -290,568 +278,6 @@ return base::HexEncode(&rand_bytes[0], rand_bytes.size()); } -std::string Sha256WithRSAEncryption() { - const uint8_t kSha256WithRSAEncryption[] = {0x30, 0x0D, 0x06, 0x09, 0x2a, - 0x86, 0x48, 0x86, 0xf7, 0x0d, - 0x01, 0x01, 0x0b, 0x05, 0x00}; - return std::string(std::begin(kSha256WithRSAEncryption), - std::end(kSha256WithRSAEncryption)); -} - -std::string Sha1WithRSAEncryption() { - const uint8_t kSha1WithRSAEncryption[] = {0x30, 0x0D, 0x06, 0x09, 0x2a, - 0x86, 0x48, 0x86, 0xf7, 0x0d, - 0x01, 0x01, 0x05, 0x05, 0x00}; - return std::string(std::begin(kSha1WithRSAEncryption), - std::end(kSha1WithRSAEncryption)); -} - -std::string Md5WithRSAEncryption() { - const uint8_t kMd5WithRSAEncryption[] = {0x30, 0x0d, 0x06, 0x09, 0x2a, - 0x86, 0x48, 0x86, 0xf7, 0x0d, - 0x01, 0x01, 0x04, 0x05, 0x00}; - return std::string(std::begin(kMd5WithRSAEncryption), - std::end(kMd5WithRSAEncryption)); -} - -// Adds bytes (specified as a StringPiece) to the given CBB. -// The argument ordering follows the boringssl CBB_* api style. -bool CBBAddBytes(CBB* cbb, base::StringPiece bytes) { - return CBB_add_bytes(cbb, reinterpret_cast<const uint8_t*>(bytes.data()), - bytes.size()); -} - -// Adds bytes (from fixed size array) to the given CBB. -// The argument ordering follows the boringssl CBB_* api style. -template <size_t N> -bool CBBAddBytes(CBB* cbb, const uint8_t (&data)[N]) { - return CBB_add_bytes(cbb, data, N); -} - -// Adds a RFC 5280 Time value to the given CBB. -// The argument ordering follows the boringssl CBB_* api style. -bool CBBAddTime(CBB* cbb, const base::Time& time) { - der::GeneralizedTime generalized_time; - if (!der::EncodeTimeAsGeneralizedTime(time, &generalized_time)) - return false; - CBB time_cbb; - if (generalized_time.year < 2050) { - uint8_t out[der::kUTCTimeLength]; - if (!der::EncodeUTCTime(generalized_time, out) || - !CBB_add_asn1(cbb, &time_cbb, CBS_ASN1_UTCTIME) || - !CBBAddBytes(&time_cbb, out) || !CBB_flush(cbb)) - return false; - } else { - uint8_t out[der::kGeneralizedTimeLength]; - if (!der::EncodeGeneralizedTime(generalized_time, out) || - !CBB_add_asn1(cbb, &time_cbb, CBS_ASN1_GENERALIZEDTIME) || - !CBBAddBytes(&time_cbb, out) || !CBB_flush(cbb)) - return false; - } - return true; -} - -// Finalizes the CBB to a std::string. -std::string FinishCBB(CBB* cbb) { - size_t cbb_len; - uint8_t* cbb_bytes; - - if (!CBB_finish(cbb, &cbb_bytes, &cbb_len)) { - ADD_FAILURE() << "CBB_finish() failed"; - return std::string(); - } - - bssl::UniquePtr<uint8_t> delete_bytes(cbb_bytes); - return std::string(reinterpret_cast<char*>(cbb_bytes), cbb_len); -} - -// CertBuilder is a helper class to dynamically create a test certificate. -// -// CertBuilder is initialized using an existing certificate, from which it -// copies most properties (see InitFromCert for details). -// -// The subject, serial number, and key for the final certificate are chosen -// randomly. Using a randomized subject and serial number is important to defeat -// certificate caching done by NSS, which otherwise can make test outcomes -// dependent on ordering. -class CertBuilder { - public: - // Initializes the CertBuilder using |orig_cert|. If |issuer| is null - // then the generated certificate will be self-signed. Otherwise, it - // will be signed using |issuer|. - CertBuilder(CRYPTO_BUFFER* orig_cert, CertBuilder* issuer) : issuer_(issuer) { - if (!issuer_) - issuer_ = this; - - crypto::EnsureOpenSSLInit(); - InitFromCert(der::Input(x509_util::CryptoBufferAsStringPiece(orig_cert))); - } - - // Sets a value for the indicated X.509 (v3) extension. - void SetExtension(const der::Input& oid, - std::string value, - bool critical = false) { - auto& extension_value = extensions_[oid.AsString()]; - extension_value.critical = critical; - extension_value.value = std::move(value); - - Invalidate(); - } - - // Removes an extension (if present). - void EraseExtension(const der::Input& oid) { - extensions_.erase(oid.AsString()); - - Invalidate(); - } - - // Sets an AIA extension with a single caIssuers access method. - void SetCaIssuersUrl(const GURL& url) { - std::string url_spec = url.spec(); - - // From RFC 5280: - // - // AuthorityInfoAccessSyntax ::= - // SEQUENCE SIZE (1..MAX) OF AccessDescription - // - // AccessDescription ::= SEQUENCE { - // accessMethod OBJECT IDENTIFIER, - // accessLocation GeneralName } - bssl::ScopedCBB cbb; - CBB aia, ca_issuer, access_method, access_location; - ASSERT_TRUE(CBB_init(cbb.get(), url_spec.size())); - ASSERT_TRUE(CBB_add_asn1(cbb.get(), &aia, CBS_ASN1_SEQUENCE)); - ASSERT_TRUE(CBB_add_asn1(&aia, &ca_issuer, CBS_ASN1_SEQUENCE)); - ASSERT_TRUE(CBB_add_asn1(&ca_issuer, &access_method, CBS_ASN1_OBJECT)); - ASSERT_TRUE(CBBAddBytes(&access_method, AdCaIssuersOid().AsStringPiece())); - ASSERT_TRUE(CBB_add_asn1(&ca_issuer, &access_location, - CBS_ASN1_CONTEXT_SPECIFIC | 6)); - ASSERT_TRUE(CBBAddBytes(&access_location, url_spec)); - - SetExtension(AuthorityInfoAccessOid(), FinishCBB(cbb.get())); - } - - void SetCrlDistributionPointUrl(const GURL& url) { - std::string url_spec = url.spec(); - - bssl::ScopedCBB cbb; - ASSERT_TRUE(CBB_init(cbb.get(), url_spec.size())); - CBB dps, dp, dp_name, dp_fullname, dp_url; - - // CRLDistributionPoints ::= SEQUENCE SIZE (1..MAX) OF DistributionPoint - ASSERT_TRUE(CBB_add_asn1(cbb.get(), &dps, CBS_ASN1_SEQUENCE)); - - // DistributionPoint ::= SEQUENCE { - // distributionPoint [0] DistributionPointName OPTIONAL, - // reasons [1] ReasonFlags OPTIONAL, - // cRLIssuer [2] GeneralNames OPTIONAL } - ASSERT_TRUE(CBB_add_asn1(&dps, &dp, CBS_ASN1_SEQUENCE)); - ASSERT_TRUE(CBB_add_asn1( - &dp, &dp_name, CBS_ASN1_CONTEXT_SPECIFIC | CBS_ASN1_CONSTRUCTED | 0)); - - // DistributionPointName ::= CHOICE { - // fullName [0] GeneralNames, - // nameRelativeToCRLIssuer [1] RelativeDistinguishedName } - ASSERT_TRUE( - CBB_add_asn1(&dp_name, &dp_fullname, - CBS_ASN1_CONTEXT_SPECIFIC | CBS_ASN1_CONSTRUCTED | 0)); - - // GeneralNames ::= SEQUENCE SIZE (1..MAX) OF GeneralName - // GeneralName ::= CHOICE { - // uniformResourceIdentifier [6] IA5String, - ASSERT_TRUE( - CBB_add_asn1(&dp_fullname, &dp_url, CBS_ASN1_CONTEXT_SPECIFIC | 6)); - ASSERT_TRUE(CBBAddBytes(&dp_url, url_spec)); - - SetExtension(CrlDistributionPointsOid(), FinishCBB(cbb.get())); - } - - void SetSubjectCommonName(const std::string common_name) { - // See RFC 4519. - static const uint8_t kCommonName[] = {0x55, 0x04, 0x03}; - - // See RFC 5280, section 4.1.2.4. - bssl::ScopedCBB cbb; - CBB rdns, rdn, attr, type, value; - ASSERT_TRUE(CBB_init(cbb.get(), 64)); - ASSERT_TRUE(CBB_add_asn1(cbb.get(), &rdns, CBS_ASN1_SEQUENCE)); - ASSERT_TRUE(CBB_add_asn1(&rdns, &rdn, CBS_ASN1_SET)); - ASSERT_TRUE(CBB_add_asn1(&rdn, &attr, CBS_ASN1_SEQUENCE)); - ASSERT_TRUE(CBB_add_asn1(&attr, &type, CBS_ASN1_OBJECT)); - ASSERT_TRUE(CBBAddBytes(&type, kCommonName)); - ASSERT_TRUE(CBB_add_asn1(&attr, &value, CBS_ASN1_UTF8STRING)); - ASSERT_TRUE(CBBAddBytes(&value, common_name)); - - subject_tlv_ = FinishCBB(cbb.get()); - } - - // Sets the SAN for the certificate to a single dNSName. - void SetSubjectAltName(const std::string& dns_name) { - // From RFC 5280: - // - // SubjectAltName ::= GeneralNames - // - // GeneralNames ::= SEQUENCE SIZE (1..MAX) OF GeneralName - // - // GeneralName ::= CHOICE { - // otherName [0] OtherName, - // rfc822Name [1] IA5String, - // dNSName [2] IA5String, - // ... } - bssl::ScopedCBB cbb; - CBB general_names, general_name; - ASSERT_TRUE(CBB_init(cbb.get(), dns_name.size())); - ASSERT_TRUE(CBB_add_asn1(cbb.get(), &general_names, CBS_ASN1_SEQUENCE)); - ASSERT_TRUE(CBB_add_asn1(&general_names, &general_name, - CBS_ASN1_CONTEXT_SPECIFIC | 2)); - ASSERT_TRUE(CBBAddBytes(&general_name, dns_name)); - - SetExtension(SubjectAltNameOid(), FinishCBB(cbb.get())); - } - - // Sets the signature algorithm for the certificate to either - // sha256WithRSAEncryption or sha1WithRSAEncryption. - void SetSignatureAlgorithmRsaPkca1(DigestAlgorithm digest) { - switch (digest) { - case DigestAlgorithm::Sha256: { - SetSignatureAlgorithm(Sha256WithRSAEncryption()); - break; - } - - case DigestAlgorithm::Sha1: { - SetSignatureAlgorithm(Sha1WithRSAEncryption()); - break; - } - - default: - ASSERT_TRUE(false); - } - } - - void SetSignatureAlgorithm(std::string algorithm_tlv) { - signature_algorithm_tlv_ = std::move(algorithm_tlv); - Invalidate(); - } - - void SetRandomSerialNumber() { - serial_number_ = base::RandUint64(); - Invalidate(); - } - - // Returns a CRYPTO_BUFFER to the generated certificate. - CRYPTO_BUFFER* GetCertBuffer() { - if (!cert_) - GenerateCertificate(); - return cert_.get(); - } - - bssl::UniquePtr<CRYPTO_BUFFER> DupCertBuffer() { - return bssl::UpRef(GetCertBuffer()); - } - - // Returns the subject of the generated certificate. - const std::string& GetSubject() { - if (subject_tlv_.empty()) - GenerateSubject(); - return subject_tlv_; - } - - // Returns the serial number for the generated certificate. - uint64_t GetSerialNumber() { - if (!serial_number_) - serial_number_ = base::RandUint64(); - return serial_number_; - } - - // Returns the (RSA) key for the generated certificate. - EVP_PKEY* GetKey() { - if (!key_) - GenerateKey(); - return key_.get(); - } - - // Returns an X509Certificate for the generated certificate. - scoped_refptr<X509Certificate> GetX509Certificate() { - return X509Certificate::CreateFromBuffer(DupCertBuffer(), {}); - } - - // Returns a copy of the certificate's DER. - std::string GetDER() { - return x509_util::CryptoBufferAsStringPiece(GetCertBuffer()).as_string(); - } - - private: - // Marks the generated certificate DER as invalid, so it will need to - // be re-generated next time the DER is accessed. - void Invalidate() { cert_.reset(); } - - // Sets the |key_| to a 2048-bit RSA key. - void GenerateKey() { - ASSERT_FALSE(key_); - - auto private_key = crypto::RSAPrivateKey::Create(2048); - key_ = bssl::UpRef(private_key->key()); - } - - // Generates a random subject for the certificate, comprised of just a CN. - void GenerateSubject() { - ASSERT_TRUE(subject_tlv_.empty()); - - // Use a random common name comprised of 12 bytes in hex. - std::string common_name = MakeRandomHexString(12); - - SetSubjectCommonName(common_name); - } - - // Parses |cert| and copies the following properties: - // * All extensions (dropping any duplicates) - // * Signature algorithm (from Certificate) - // * Validity (expiration) - void InitFromCert(const der::Input& cert) { - extensions_.clear(); - Invalidate(); - - // From RFC 5280, section 4.1 - // Certificate ::= SEQUENCE { - // tbsCertificate TBSCertificate, - // signatureAlgorithm AlgorithmIdentifier, - // signatureValue BIT STRING } - - // TBSCertificate ::= SEQUENCE { - // version [0] EXPLICIT Version DEFAULT v1, - // serialNumber CertificateSerialNumber, - // signature AlgorithmIdentifier, - // issuer Name, - // validity Validity, - // subject Name, - // subjectPublicKeyInfo SubjectPublicKeyInfo, - // issuerUniqueID [1] IMPLICIT UniqueIdentifier OPTIONAL, - // -- If present, version MUST be v2 or v3 - // subjectUniqueID [2] IMPLICIT UniqueIdentifier OPTIONAL, - // -- If present, version MUST be v2 or v3 - // extensions [3] EXPLICIT Extensions OPTIONAL - // -- If present, version MUST be v3 - // } - der::Parser parser(cert); - der::Parser certificate; - der::Parser tbs_certificate; - ASSERT_TRUE(parser.ReadSequence(&certificate)); - ASSERT_TRUE(certificate.ReadSequence(&tbs_certificate)); - - // version - bool unused; - ASSERT_TRUE(tbs_certificate.SkipOptionalTag( - der::kTagConstructed | der::kTagContextSpecific | 0, &unused)); - // serialNumber - ASSERT_TRUE(tbs_certificate.SkipTag(der::kInteger)); - - // signature - der::Input signature_algorithm_tlv; - ASSERT_TRUE(tbs_certificate.ReadRawTLV(&signature_algorithm_tlv)); - signature_algorithm_tlv_ = signature_algorithm_tlv.AsString(); - - // issuer - ASSERT_TRUE(tbs_certificate.SkipTag(der::kSequence)); - - // validity - der::Input validity_tlv; - ASSERT_TRUE(tbs_certificate.ReadRawTLV(&validity_tlv)); - validity_tlv_ = validity_tlv.AsString(); - - // subject - ASSERT_TRUE(tbs_certificate.SkipTag(der::kSequence)); - // subjectPublicKeyInfo - ASSERT_TRUE(tbs_certificate.SkipTag(der::kSequence)); - // issuerUniqueID - ASSERT_TRUE(tbs_certificate.SkipOptionalTag( - der::ContextSpecificPrimitive(1), &unused)); - // subjectUniqueID - ASSERT_TRUE(tbs_certificate.SkipOptionalTag( - der::ContextSpecificPrimitive(2), &unused)); - - // extensions - bool has_extensions = false; - der::Input extensions_tlv; - ASSERT_TRUE(tbs_certificate.ReadOptionalTag( - der::ContextSpecificConstructed(3), &extensions_tlv, &has_extensions)); - if (has_extensions) { - std::map<der::Input, ParsedExtension> parsed_extensions; - ASSERT_TRUE(ParseExtensions(extensions_tlv, &parsed_extensions)); - - for (const auto& parsed_extension : parsed_extensions) { - SetExtension(parsed_extension.second.oid, - parsed_extension.second.value.AsString(), - parsed_extension.second.critical); - } - } - } - - // Assembles the CertBuilder into a TBSCertificate. - void BuildTBSCertificate(std::string* out) { - bssl::ScopedCBB cbb; - CBB tbs_cert, version, extensions_context, extensions; - - ASSERT_TRUE(CBB_init(cbb.get(), 64)); - ASSERT_TRUE(CBB_add_asn1(cbb.get(), &tbs_cert, CBS_ASN1_SEQUENCE)); - ASSERT_TRUE( - CBB_add_asn1(&tbs_cert, &version, - CBS_ASN1_CONTEXT_SPECIFIC | CBS_ASN1_CONSTRUCTED | 0)); - // Always use v3 certificates. - ASSERT_TRUE(CBB_add_asn1_uint64(&version, 2)); - ASSERT_TRUE(CBB_add_asn1_uint64(&tbs_cert, GetSerialNumber())); - ASSERT_TRUE(AddSignatureAlgorithm(&tbs_cert)); - ASSERT_TRUE(CBBAddBytes(&tbs_cert, issuer_->GetSubject())); - ASSERT_TRUE(CBBAddBytes(&tbs_cert, validity_tlv_)); - ASSERT_TRUE(CBBAddBytes(&tbs_cert, GetSubject())); - ASSERT_TRUE(EVP_marshal_public_key(&tbs_cert, GetKey())); - - // Serialize all the extensions. - if (!extensions_.empty()) { - ASSERT_TRUE( - CBB_add_asn1(&tbs_cert, &extensions_context, - CBS_ASN1_CONTEXT_SPECIFIC | CBS_ASN1_CONSTRUCTED | 3)); - ASSERT_TRUE( - CBB_add_asn1(&extensions_context, &extensions, CBS_ASN1_SEQUENCE)); - - // Extension ::= SEQUENCE { - // extnID OBJECT IDENTIFIER, - // critical BOOLEAN DEFAULT FALSE, - // extnValue OCTET STRING - // -- contains the DER encoding of an ASN.1 value - // -- corresponding to the extension type identified - // -- by extnID - // } - for (const auto& extension_it : extensions_) { - CBB extension_seq, oid, extn_value; - ASSERT_TRUE( - CBB_add_asn1(&extensions, &extension_seq, CBS_ASN1_SEQUENCE)); - ASSERT_TRUE(CBB_add_asn1(&extension_seq, &oid, CBS_ASN1_OBJECT)); - ASSERT_TRUE(CBBAddBytes(&oid, extension_it.first)); - if (extension_it.second.critical) { - ASSERT_TRUE(CBB_add_asn1_bool(&extension_seq, true)); - } - - ASSERT_TRUE( - CBB_add_asn1(&extension_seq, &extn_value, CBS_ASN1_OCTETSTRING)); - ASSERT_TRUE(CBBAddBytes(&extn_value, extension_it.second.value)); - ASSERT_TRUE(CBB_flush(&extensions)); - } - } - - *out = FinishCBB(cbb.get()); - } - - bool AddSignatureAlgorithm(CBB* cbb) { - return CBBAddBytes(cbb, signature_algorithm_tlv_); - } - - void GenerateCertificate() { - ASSERT_FALSE(cert_); - - std::string tbs_cert; - BuildTBSCertificate(&tbs_cert); - const uint8_t* tbs_cert_bytes = - reinterpret_cast<const uint8_t*>(tbs_cert.data()); - - // Determine the correct digest algorithm to use (assumes RSA PKCS#1 - // signatures). - auto signature_algorithm = SignatureAlgorithm::Create( - der::Input(&signature_algorithm_tlv_), nullptr); - ASSERT_TRUE(signature_algorithm); - ASSERT_EQ(SignatureAlgorithmId::RsaPkcs1, signature_algorithm->algorithm()); - const EVP_MD* md = nullptr; - - switch (signature_algorithm->digest()) { - case DigestAlgorithm::Sha256: - md = EVP_sha256(); - break; - - case DigestAlgorithm::Sha1: - md = EVP_sha1(); - break; - - default: - ASSERT_TRUE(false) << "Only rsaEncryptionWithSha256 or " - "rsaEnryptionWithSha1 are supported"; - break; - } - - // Sign the TBSCertificate and write the entire certificate. - bssl::ScopedCBB cbb; - CBB cert, signature; - bssl::ScopedEVP_MD_CTX ctx; - uint8_t* sig_out; - size_t sig_len; - - ASSERT_TRUE(CBB_init(cbb.get(), tbs_cert.size())); - ASSERT_TRUE(CBB_add_asn1(cbb.get(), &cert, CBS_ASN1_SEQUENCE)); - ASSERT_TRUE(CBBAddBytes(&cert, tbs_cert)); - ASSERT_TRUE(AddSignatureAlgorithm(&cert)); - ASSERT_TRUE(CBB_add_asn1(&cert, &signature, CBS_ASN1_BITSTRING)); - ASSERT_TRUE(CBB_add_u8(&signature, 0 /* no unused bits */)); - ASSERT_TRUE( - EVP_DigestSignInit(ctx.get(), nullptr, md, nullptr, issuer_->GetKey())); - ASSERT_TRUE(EVP_DigestSign(ctx.get(), nullptr, &sig_len, tbs_cert_bytes, - tbs_cert.size())); - ASSERT_TRUE(CBB_reserve(&signature, &sig_out, sig_len)); - ASSERT_TRUE(EVP_DigestSign(ctx.get(), sig_out, &sig_len, tbs_cert_bytes, - tbs_cert.size())); - ASSERT_TRUE(CBB_did_write(&signature, sig_len)); - - auto cert_der = FinishCBB(cbb.get()); - cert_ = x509_util::CreateCryptoBuffer( - reinterpret_cast<const uint8_t*>(cert_der.data()), cert_der.size()); - } - - struct ExtensionValue { - bool critical = false; - std::string value; - }; - - std::string validity_tlv_; - std::string subject_tlv_; - std::string signature_algorithm_tlv_; - uint64_t serial_number_ = 0; - - std::map<std::string, ExtensionValue> extensions_; - - bssl::UniquePtr<CRYPTO_BUFFER> cert_; - bssl::UniquePtr<EVP_PKEY> key_; - - CertBuilder* issuer_ = nullptr; -}; - -// Creates a simple leaf->intermediate->root chain of CertBuilders with no AIA -// or CrlDistributionPoint extensions, and leaf having a subjectAltName of -// www.example.com. -void CreateSimpleCertBuilderChain( - std::unique_ptr<CertBuilder>* out_leaf, - std::unique_ptr<CertBuilder>* out_intermediate, - std::unique_ptr<CertBuilder>* out_root) { - const char kHostname[] = "www.example.com"; - base::FilePath certs_dir = - GetTestNetDataDirectory() - .AppendASCII("verify_certificate_chain_unittest") - .AppendASCII("target-and-intermediate"); - - CertificateList orig_certs = CreateCertificateListFromFile( - certs_dir, "chain.pem", X509Certificate::FORMAT_AUTO); - ASSERT_EQ(3U, orig_certs.size()); - - // Build slightly modified variants of |orig_certs|. - *out_root = - std::make_unique<CertBuilder>(orig_certs[2]->cert_buffer(), nullptr); - *out_intermediate = std::make_unique<CertBuilder>( - orig_certs[1]->cert_buffer(), out_root->get()); - (*out_intermediate)->EraseExtension(CrlDistributionPointsOid()); - (*out_intermediate)->EraseExtension(AuthorityInfoAccessOid()); - *out_leaf = std::make_unique<CertBuilder>(orig_certs[0]->cert_buffer(), - out_intermediate->get()); - (*out_leaf)->SetSubjectAltName(kHostname); - (*out_leaf)->EraseExtension(CrlDistributionPointsOid()); - (*out_leaf)->EraseExtension(AuthorityInfoAccessOid()); -} - } // namespace // This fixture is for tests that apply to concrete implementations of @@ -1237,7 +663,7 @@ TEST_P(CertVerifyProcInternalTest, CertWithNullInCommonNameAndNoSAN) { std::unique_ptr<CertBuilder> leaf, intermediate, root; - CreateSimpleCertBuilderChain(&leaf, &intermediate, &root); + CertBuilder::CreateSimpleChain(&leaf, &intermediate, &root); ASSERT_TRUE(leaf && intermediate && root); leaf->EraseExtension(SubjectAltNameOid()); @@ -1250,8 +676,7 @@ // Trust the root and build a chain to verify that includes the intermediate. ScopedTestRoot scoped_root(root->GetX509Certificate().get()); - scoped_refptr<X509Certificate> chain = CreateX509CertificateWithIntermediate( - leaf->DupCertBuffer(), intermediate->DupCertBuffer()); + scoped_refptr<X509Certificate> chain = leaf->GetX509CertificateChain(); ASSERT_TRUE(chain.get()); int flags = 0; @@ -1267,7 +692,7 @@ TEST_P(CertVerifyProcInternalTest, CertWithNullInCommonNameAndValidSAN) { std::unique_ptr<CertBuilder> leaf, intermediate, root; - CreateSimpleCertBuilderChain(&leaf, &intermediate, &root); + CertBuilder::CreateSimpleChain(&leaf, &intermediate, &root); ASSERT_TRUE(leaf && intermediate && root); leaf->SetSubjectAltName("www.fake.com"); @@ -1280,8 +705,7 @@ // Trust the root and build a chain to verify that includes the intermediate. ScopedTestRoot scoped_root(root->GetX509Certificate().get()); - scoped_refptr<X509Certificate> chain = CreateX509CertificateWithIntermediate( - leaf->DupCertBuffer(), intermediate->DupCertBuffer()); + scoped_refptr<X509Certificate> chain = leaf->GetX509CertificateChain(); ASSERT_TRUE(chain.get()); int flags = 0; @@ -1296,7 +720,7 @@ TEST_P(CertVerifyProcInternalTest, CertWithNullInSAN) { std::unique_ptr<CertBuilder> leaf, intermediate, root; - CreateSimpleCertBuilderChain(&leaf, &intermediate, &root); + CertBuilder::CreateSimpleChain(&leaf, &intermediate, &root); ASSERT_TRUE(leaf && intermediate && root); std::string hostname; @@ -1307,8 +731,7 @@ // Trust the root and build a chain to verify that includes the intermediate. ScopedTestRoot scoped_root(root->GetX509Certificate().get()); - scoped_refptr<X509Certificate> chain = CreateX509CertificateWithIntermediate( - leaf->DupCertBuffer(), intermediate->DupCertBuffer()); + scoped_refptr<X509Certificate> chain = leaf->GetX509CertificateChain(); ASSERT_TRUE(chain.get()); int flags = 0; @@ -3194,7 +2617,7 @@ bssl::UniquePtr<CRYPTO_BUFFER>* out_intermediate, scoped_refptr<X509Certificate>* out_root) { std::unique_ptr<CertBuilder> leaf, intermediate, root; - CreateSimpleCertBuilderChain(&leaf, &intermediate, &root); + CertBuilder::CreateSimpleChain(&leaf, &intermediate, &root); ASSERT_TRUE(leaf && intermediate && root); // Make the leaf certificate have an AIA (CA Issuers) that points to the @@ -3212,126 +2635,13 @@ } // Creates a CRL issued and signed by |crl_issuer|, marking |revoked_serials| - // as revoked. - // Returns the DER-encoded CRL. - static std::string CreateCrl(CertBuilder* crl_issuer, - const std::vector<uint64_t>& revoked_serials, - DigestAlgorithm digest) { - std::string signature_algorithm; - const EVP_MD* md = nullptr; - switch (digest) { - case DigestAlgorithm::Sha256: { - signature_algorithm = Sha256WithRSAEncryption(); - md = EVP_sha256(); - break; - } - - case DigestAlgorithm::Sha1: { - signature_algorithm = Sha1WithRSAEncryption(); - md = EVP_sha1(); - break; - } - - case DigestAlgorithm::Md5: { - signature_algorithm = Md5WithRSAEncryption(); - md = EVP_md5(); - break; - } - - default: - ADD_FAILURE(); - return std::string(); - } - // TBSCertList ::= SEQUENCE { - // version Version OPTIONAL, - // -- if present, MUST be v2 - // signature AlgorithmIdentifier, - // issuer Name, - // thisUpdate Time, - // nextUpdate Time OPTIONAL, - // revokedCertificates SEQUENCE OF SEQUENCE { - // userCertificate CertificateSerialNumber, - // revocationDate Time, - // crlEntryExtensions Extensions OPTIONAL - // -- if present, version MUST be v2 - // } OPTIONAL, - // crlExtensions [0] EXPLICIT Extensions OPTIONAL - // -- if present, version MUST be v2 - // } - bssl::ScopedCBB tbs_cbb; - CBB tbs_cert_list, revoked_serials_cbb; - if (!CBB_init(tbs_cbb.get(), 10) || - !CBB_add_asn1(tbs_cbb.get(), &tbs_cert_list, CBS_ASN1_SEQUENCE) || - !CBB_add_asn1_uint64(&tbs_cert_list, 1 /* V2 */) || - !CBBAddBytes(&tbs_cert_list, signature_algorithm) || - !CBBAddBytes(&tbs_cert_list, crl_issuer->GetSubject()) || - !CBBAddTime(&tbs_cert_list, - base::Time::Now() - base::TimeDelta::FromDays(1)) || - !CBBAddTime(&tbs_cert_list, - base::Time::Now() + base::TimeDelta::FromDays(6))) { - ADD_FAILURE(); - return std::string(); - } - if (!revoked_serials.empty()) { - if (!CBB_add_asn1(&tbs_cert_list, &revoked_serials_cbb, - CBS_ASN1_SEQUENCE)) { - ADD_FAILURE(); - return std::string(); - } - for (const int64_t revoked_serial : revoked_serials) { - CBB revoked_serial_cbb; - if (!CBB_add_asn1(&revoked_serials_cbb, &revoked_serial_cbb, - CBS_ASN1_SEQUENCE) || - !CBB_add_asn1_uint64(&revoked_serial_cbb, revoked_serial) || - !CBBAddTime(&revoked_serial_cbb, - base::Time::Now() - base::TimeDelta::FromDays(1)) || - !CBB_flush(&revoked_serials_cbb)) { - ADD_FAILURE(); - return std::string(); - } - } - } - - std::string tbs_tlv = FinishCBB(tbs_cbb.get()); - - // CertificateList ::= SEQUENCE { - // tbsCertList TBSCertList, - // signatureAlgorithm AlgorithmIdentifier, - // signatureValue BIT STRING } - bssl::ScopedCBB crl_cbb; - CBB cert_list, signature; - bssl::ScopedEVP_MD_CTX ctx; - uint8_t* sig_out; - size_t sig_len; - if (!CBB_init(crl_cbb.get(), 10) || - !CBB_add_asn1(crl_cbb.get(), &cert_list, CBS_ASN1_SEQUENCE) || - !CBBAddBytes(&cert_list, tbs_tlv) || - !CBBAddBytes(&cert_list, signature_algorithm) || - !CBB_add_asn1(&cert_list, &signature, CBS_ASN1_BITSTRING) || - !CBB_add_u8(&signature, 0 /* no unused bits */) || - !EVP_DigestSignInit(ctx.get(), nullptr, md, nullptr, - crl_issuer->GetKey()) || - !EVP_DigestSign(ctx.get(), nullptr, &sig_len, - reinterpret_cast<const uint8_t*>(tbs_tlv.data()), - tbs_tlv.size()) || - !CBB_reserve(&signature, &sig_out, sig_len) || - !EVP_DigestSign(ctx.get(), sig_out, &sig_len, - reinterpret_cast<const uint8_t*>(tbs_tlv.data()), - tbs_tlv.size()) || - !CBB_did_write(&signature, sig_len)) { - ADD_FAILURE(); - return std::string(); - } - return FinishCBB(crl_cbb.get()); - } - - // Creates a CRL issued and signed by |crl_issuer|, marking |revoked_serials| // as revoked, and registers it to be served by the test server. // Returns the full URL to retrieve the CRL from the test server. GURL CreateAndServeCrl(CertBuilder* crl_issuer, const std::vector<uint64_t>& revoked_serials, DigestAlgorithm digest = DigestAlgorithm::Sha256) { - std::string crl = CreateCrl(crl_issuer, revoked_serials, digest); + std::string crl = + CertBuilder::CreateCrl(crl_issuer, revoked_serials, digest); std::string crl_path = MakeRandomPath(".crl"); return RegisterSimpleTestServerHandler(crl_path, HTTP_OK, "application/pkix-crl", crl); @@ -3734,13 +3044,12 @@ // Create certs which have no AIA or CRL distribution points. const char kHostname[] = "www.example.com"; std::unique_ptr<CertBuilder> leaf, intermediate, root; - CreateSimpleCertBuilderChain(&leaf, &intermediate, &root); + CertBuilder::CreateSimpleChain(&leaf, &intermediate, &root); ASSERT_TRUE(leaf && intermediate && root); // Trust the root and build a chain to verify that includes the intermediate. ScopedTestRoot scoped_root(root->GetX509Certificate().get()); - scoped_refptr<X509Certificate> chain = CreateX509CertificateWithIntermediate( - leaf->DupCertBuffer(), intermediate->DupCertBuffer()); + scoped_refptr<X509Certificate> chain = leaf->GetX509CertificateChain(); ASSERT_TRUE(chain.get()); // Verify with hard-fail revocation checking for local anchors. @@ -3773,7 +3082,7 @@ const char kHostname[] = "www.example.com"; std::unique_ptr<CertBuilder> leaf, intermediate, root; - CreateSimpleCertBuilderChain(&leaf, &intermediate, &root); + CertBuilder::CreateSimpleChain(&leaf, &intermediate, &root); ASSERT_TRUE(leaf && intermediate && root); // Serve a root-issued CRL which does not revoke intermediate. @@ -3784,8 +3093,7 @@ // Trust the root and build a chain to verify that includes the intermediate. ScopedTestRoot scoped_root(root->GetX509Certificate().get()); - scoped_refptr<X509Certificate> chain = CreateX509CertificateWithIntermediate( - leaf->DupCertBuffer(), intermediate->DupCertBuffer()); + scoped_refptr<X509Certificate> chain = leaf->GetX509CertificateChain(); ASSERT_TRUE(chain.get()); // Verify with hard-fail revocation checking for local anchors. @@ -3814,7 +3122,7 @@ const char kHostname[] = "www.example.com"; std::unique_ptr<CertBuilder> leaf, intermediate, root; - CreateSimpleCertBuilderChain(&leaf, &intermediate, &root); + CertBuilder::CreateSimpleChain(&leaf, &intermediate, &root); ASSERT_TRUE(leaf && intermediate && root); // Root-issued CRL revokes leaf's serial number. This is irrelevant. @@ -3828,8 +3136,7 @@ // Trust the root and build a chain to verify that includes the intermediate. ScopedTestRoot scoped_root(root->GetX509Certificate().get()); - scoped_refptr<X509Certificate> chain = CreateX509CertificateWithIntermediate( - leaf->DupCertBuffer(), intermediate->DupCertBuffer()); + scoped_refptr<X509Certificate> chain = leaf->GetX509CertificateChain(); ASSERT_TRUE(chain.get()); // Verify with hard-fail revocation checking for local anchors. @@ -3855,7 +3162,7 @@ const char kHostname[] = "www.example.com"; std::unique_ptr<CertBuilder> leaf, intermediate, root; - CreateSimpleCertBuilderChain(&leaf, &intermediate, &root); + CertBuilder::CreateSimpleChain(&leaf, &intermediate, &root); ASSERT_TRUE(leaf && intermediate && root); // Root-issued CRL which does not revoke intermediate. @@ -3867,8 +3174,7 @@ // Trust the root and build a chain to verify that includes the intermediate. ScopedTestRoot scoped_root(root->GetX509Certificate().get()); - scoped_refptr<X509Certificate> chain = CreateX509CertificateWithIntermediate( - leaf->DupCertBuffer(), intermediate->DupCertBuffer()); + scoped_refptr<X509Certificate> chain = leaf->GetX509CertificateChain(); ASSERT_TRUE(chain.get()); // Verify with hard-fail revocation checking for local anchors. @@ -3893,7 +3199,7 @@ const char kHostname[] = "www.example.com"; std::unique_ptr<CertBuilder> leaf, intermediate, root; - CreateSimpleCertBuilderChain(&leaf, &intermediate, &root); + CertBuilder::CreateSimpleChain(&leaf, &intermediate, &root); ASSERT_TRUE(leaf && intermediate && root); // Intermediate is revoked by root issued CRL. @@ -3905,8 +3211,7 @@ // Trust the root and build a chain to verify that includes the intermediate. ScopedTestRoot scoped_root(root->GetX509Certificate().get()); - scoped_refptr<X509Certificate> chain = CreateX509CertificateWithIntermediate( - leaf->DupCertBuffer(), intermediate->DupCertBuffer()); + scoped_refptr<X509Certificate> chain = leaf->GetX509CertificateChain(); ASSERT_TRUE(chain.get()); // Verify with hard-fail revocation checking for local anchors. @@ -3934,7 +3239,7 @@ const char kHostname[] = "www.example.com"; std::unique_ptr<CertBuilder> leaf, intermediate, root; - CreateSimpleCertBuilderChain(&leaf, &intermediate, &root); + CertBuilder::CreateSimpleChain(&leaf, &intermediate, &root); ASSERT_TRUE(leaf && intermediate && root); // Serve a root-issued CRL which does not revoke intermediate. @@ -3946,8 +3251,7 @@ // Trust the root and build a chain to verify that includes the intermediate. ScopedTestRoot scoped_root(root->GetX509Certificate().get()); - scoped_refptr<X509Certificate> chain = CreateX509CertificateWithIntermediate( - leaf->DupCertBuffer(), intermediate->DupCertBuffer()); + scoped_refptr<X509Certificate> chain = leaf->GetX509CertificateChain(); ASSERT_TRUE(chain.get()); // Verify with hard-fail revocation checking for local anchors. @@ -3980,7 +3284,7 @@ const char kHostname[] = "www.example.com"; std::unique_ptr<CertBuilder> leaf, intermediate, root; - CreateSimpleCertBuilderChain(&leaf, &intermediate, &root); + CertBuilder::CreateSimpleChain(&leaf, &intermediate, &root); ASSERT_TRUE(leaf && intermediate && root); // Serve a 404 for the root-issued CRL distribution point url. @@ -3992,8 +3296,7 @@ // Trust the root and build a chain to verify that includes the intermediate. ScopedTestRoot scoped_root(root->GetX509Certificate().get()); - scoped_refptr<X509Certificate> chain = CreateX509CertificateWithIntermediate( - leaf->DupCertBuffer(), intermediate->DupCertBuffer()); + scoped_refptr<X509Certificate> chain = leaf->GetX509CertificateChain(); ASSERT_TRUE(chain.get()); // Verify with hard-fail revocation checking for local anchors. @@ -4024,13 +3327,12 @@ // Create certs which have no AIA or CRL distribution points. const char kHostname[] = "www.example.com"; std::unique_ptr<CertBuilder> leaf, intermediate, root; - CreateSimpleCertBuilderChain(&leaf, &intermediate, &root); + CertBuilder::CreateSimpleChain(&leaf, &intermediate, &root); ASSERT_TRUE(leaf && intermediate && root); // Trust the root and build a chain to verify that includes the intermediate. ScopedTestRoot scoped_root(root->GetX509Certificate().get()); - scoped_refptr<X509Certificate> chain = CreateX509CertificateWithIntermediate( - leaf->DupCertBuffer(), intermediate->DupCertBuffer()); + scoped_refptr<X509Certificate> chain = leaf->GetX509CertificateChain(); ASSERT_TRUE(chain.get()); // Verify with soft-fail revocation checking. @@ -4060,7 +3362,7 @@ const char kHostname[] = "www.example.com"; std::unique_ptr<CertBuilder> leaf, intermediate, root; - CreateSimpleCertBuilderChain(&leaf, &intermediate, &root); + CertBuilder::CreateSimpleChain(&leaf, &intermediate, &root); ASSERT_TRUE(leaf && intermediate && root); // Serve a root-issued CRL which does not revoke intermediate. @@ -4071,8 +3373,7 @@ // Trust the root and build a chain to verify that includes the intermediate. ScopedTestRoot scoped_root(root->GetX509Certificate().get()); - scoped_refptr<X509Certificate> chain = CreateX509CertificateWithIntermediate( - leaf->DupCertBuffer(), intermediate->DupCertBuffer()); + scoped_refptr<X509Certificate> chain = leaf->GetX509CertificateChain(); ASSERT_TRUE(chain.get()); // Verify with soft-fail revocation checking. @@ -4099,7 +3400,7 @@ const char kHostname[] = "www.example.com"; std::unique_ptr<CertBuilder> leaf, intermediate, root; - CreateSimpleCertBuilderChain(&leaf, &intermediate, &root); + CertBuilder::CreateSimpleChain(&leaf, &intermediate, &root); ASSERT_TRUE(leaf && intermediate && root); // Root-issued CRL revokes leaf's serial number. This is irrelevant. @@ -4113,8 +3414,7 @@ // Trust the root and build a chain to verify that includes the intermediate. ScopedTestRoot scoped_root(root->GetX509Certificate().get()); - scoped_refptr<X509Certificate> chain = CreateX509CertificateWithIntermediate( - leaf->DupCertBuffer(), intermediate->DupCertBuffer()); + scoped_refptr<X509Certificate> chain = leaf->GetX509CertificateChain(); ASSERT_TRUE(chain.get()); // Verify with soft-fail revocation checking. @@ -4138,7 +3438,7 @@ const char kHostname[] = "www.example.com"; std::unique_ptr<CertBuilder> leaf, intermediate, root; - CreateSimpleCertBuilderChain(&leaf, &intermediate, &root); + CertBuilder::CreateSimpleChain(&leaf, &intermediate, &root); ASSERT_TRUE(leaf && intermediate && root); // Root-issued CRL which does not revoke intermediate. @@ -4150,8 +3450,7 @@ // Trust the root and build a chain to verify that includes the intermediate. ScopedTestRoot scoped_root(root->GetX509Certificate().get()); - scoped_refptr<X509Certificate> chain = CreateX509CertificateWithIntermediate( - leaf->DupCertBuffer(), intermediate->DupCertBuffer()); + scoped_refptr<X509Certificate> chain = leaf->GetX509CertificateChain(); ASSERT_TRUE(chain.get()); // Verify with soft-fail revocation checking. @@ -4182,7 +3481,7 @@ const char kHostname[] = "www.example.com"; std::unique_ptr<CertBuilder> leaf, intermediate, root; - CreateSimpleCertBuilderChain(&leaf, &intermediate, &root); + CertBuilder::CreateSimpleChain(&leaf, &intermediate, &root); ASSERT_TRUE(leaf && intermediate && root); // Intermediate is revoked by root issued CRL. @@ -4194,8 +3493,7 @@ // Trust the root and build a chain to verify that includes the intermediate. ScopedTestRoot scoped_root(root->GetX509Certificate().get()); - scoped_refptr<X509Certificate> chain = CreateX509CertificateWithIntermediate( - leaf->DupCertBuffer(), intermediate->DupCertBuffer()); + scoped_refptr<X509Certificate> chain = leaf->GetX509CertificateChain(); ASSERT_TRUE(chain.get()); // Verify with soft-fail revocation checking. @@ -4226,7 +3524,7 @@ const char kHostname[] = "www.example.com"; std::unique_ptr<CertBuilder> leaf, intermediate, root; - CreateSimpleCertBuilderChain(&leaf, &intermediate, &root); + CertBuilder::CreateSimpleChain(&leaf, &intermediate, &root); ASSERT_TRUE(leaf && intermediate && root); // Root-issued CRL which does not revoke intermediate. @@ -4239,8 +3537,7 @@ // Trust the root and build a chain to verify that includes the intermediate. ScopedTestRoot scoped_root(root->GetX509Certificate().get()); - scoped_refptr<X509Certificate> chain = CreateX509CertificateWithIntermediate( - leaf->DupCertBuffer(), intermediate->DupCertBuffer()); + scoped_refptr<X509Certificate> chain = leaf->GetX509CertificateChain(); ASSERT_TRUE(chain.get()); // Verify with soft-fail revocation checking. @@ -4271,7 +3568,7 @@ const char kHostname[] = "www.example.com"; std::unique_ptr<CertBuilder> leaf, intermediate, root; - CreateSimpleCertBuilderChain(&leaf, &intermediate, &root); + CertBuilder::CreateSimpleChain(&leaf, &intermediate, &root); ASSERT_TRUE(leaf && intermediate && root); // Root-issued CRL which does not revoke intermediate. @@ -4284,8 +3581,7 @@ // Trust the root and build a chain to verify that includes the intermediate. ScopedTestRoot scoped_root(root->GetX509Certificate().get()); - scoped_refptr<X509Certificate> chain = CreateX509CertificateWithIntermediate( - leaf->DupCertBuffer(), intermediate->DupCertBuffer()); + scoped_refptr<X509Certificate> chain = leaf->GetX509CertificateChain(); ASSERT_TRUE(chain.get()); // Verify with soft-fail revocation checking. @@ -4321,7 +3617,7 @@ const char kHostname[] = "www.example.com"; std::unique_ptr<CertBuilder> leaf, intermediate, root; - CreateSimpleCertBuilderChain(&leaf, &intermediate, &root); + CertBuilder::CreateSimpleChain(&leaf, &intermediate, &root); ASSERT_TRUE(leaf && intermediate && root); // Serve a root-issued CRL which does not revoke intermediate. @@ -4333,8 +3629,7 @@ // Trust the root and build a chain to verify that includes the intermediate. ScopedTestRoot scoped_root(root->GetX509Certificate().get()); - scoped_refptr<X509Certificate> chain = CreateX509CertificateWithIntermediate( - leaf->DupCertBuffer(), intermediate->DupCertBuffer()); + scoped_refptr<X509Certificate> chain = leaf->GetX509CertificateChain(); ASSERT_TRUE(chain.get()); // Verify with soft-fail revocation checking. @@ -4362,7 +3657,7 @@ const char kHostname[] = "www.example.com"; std::unique_ptr<CertBuilder> leaf, intermediate, root; - CreateSimpleCertBuilderChain(&leaf, &intermediate, &root); + CertBuilder::CreateSimpleChain(&leaf, &intermediate, &root); ASSERT_TRUE(leaf && intermediate && root); // Serve a 404 for the root-issued CRL distribution point url. @@ -4374,8 +3669,7 @@ // Trust the root and build a chain to verify that includes the intermediate. ScopedTestRoot scoped_root(root->GetX509Certificate().get()); - scoped_refptr<X509Certificate> chain = CreateX509CertificateWithIntermediate( - leaf->DupCertBuffer(), intermediate->DupCertBuffer()); + scoped_refptr<X509Certificate> chain = leaf->GetX509CertificateChain(); ASSERT_TRUE(chain.get()); // Verify with soft-fail revocation checking.
diff --git a/net/http/http_stream_factory.cc b/net/http/http_stream_factory.cc index 55df864..c8845096 100644 --- a/net/http/http_stream_factory.cc +++ b/net/http/http_stream_factory.cc
@@ -197,89 +197,6 @@ } } -HttpStreamFactory::PreconnectingProxyServer::PreconnectingProxyServer( - ProxyServer proxy_server, - PrivacyMode privacy_mode) - : proxy_server(proxy_server), privacy_mode(privacy_mode) {} - -bool HttpStreamFactory::PreconnectingProxyServer::operator<( - const PreconnectingProxyServer& other) const { - return std::tie(proxy_server, privacy_mode) < - std::tie(other.proxy_server, other.privacy_mode); -} - -bool HttpStreamFactory::PreconnectingProxyServer::operator==( - const PreconnectingProxyServer& other) const { - return proxy_server == other.proxy_server && - privacy_mode == other.privacy_mode; -} - -bool HttpStreamFactory::OnInitConnection(const JobController& controller, - const ProxyInfo& proxy_info, - PrivacyMode privacy_mode) { - if (!controller.is_preconnect()) { - // Connection initialization can be skipped only for the preconnect jobs. - return false; - } - - if (!ProxyServerSupportsPriorities(proxy_info)) - return false; - - PreconnectingProxyServer preconnecting_proxy_server(proxy_info.proxy_server(), - privacy_mode); - - if (base::Contains(preconnecting_proxy_servers_, - preconnecting_proxy_server)) { - UMA_HISTOGRAM_EXACT_LINEAR("Net.PreconnectSkippedToProxyServers", 1, 2); - // Skip preconnect to the proxy server since we are already preconnecting - // (probably via some other job). See https://crbug.com/682041 for details. - return true; - } - - // Add the proxy server to the set of preconnecting proxy servers. - // The maximum size of |preconnecting_proxy_servers_|. - static const size_t kMaxPreconnectingServerSize = 3; - if (preconnecting_proxy_servers_.size() >= kMaxPreconnectingServerSize) { - // Erase the first entry. A better approach (at the cost of higher memory - // overhead) may be to erase the least recently used entry. - preconnecting_proxy_servers_.erase(preconnecting_proxy_servers_.begin()); - } - - preconnecting_proxy_servers_.insert(preconnecting_proxy_server); - DCHECK_GE(kMaxPreconnectingServerSize, preconnecting_proxy_servers_.size()); - // The first preconnect should be allowed. - return false; -} - -void HttpStreamFactory::OnStreamReady(const ProxyInfo& proxy_info, - PrivacyMode privacy_mode) { - if (proxy_info.is_empty()) - return; - preconnecting_proxy_servers_.erase( - PreconnectingProxyServer(proxy_info.proxy_server(), privacy_mode)); -} - -bool HttpStreamFactory::ProxyServerSupportsPriorities( - const ProxyInfo& proxy_info) const { - if (proxy_info.is_empty() || !proxy_info.proxy_server().is_valid()) - return false; - - if (!proxy_info.proxy_server().is_https()) - return false; - - HostPortPair host_port_pair = proxy_info.proxy_server().host_port_pair(); - DCHECK(!host_port_pair.IsEmpty()); - - url::SchemeHostPort scheme_host_port("https", host_port_pair.host(), - host_port_pair.port()); - - // TODO(https://crbug.com/993517): Figure out what NetworkIsolationKey() to - // use here, and what to do about this and |preconnecting_proxy_servers_|, - // which leaks data across NetworkIsolationKeys. - return session_->http_server_properties()->SupportsRequestPriority( - scheme_host_port, NetworkIsolationKey()); -} - void HttpStreamFactory::DumpMemoryStats( base::trace_event::ProcessMemoryDump* pmd, const std::string& parent_absolute_name) const {
diff --git a/net/http/http_stream_factory.h b/net/http/http_stream_factory.h index b7909cc..5a16275 100644 --- a/net/http/http_stream_factory.h +++ b/net/http/http_stream_factory.h
@@ -129,20 +129,6 @@ url::SchemeHostPort RewriteHost(const url::SchemeHostPort& server); - // |PreconnectingProxyServer| holds information of a connection to a single - // proxy server. - struct PreconnectingProxyServer { - PreconnectingProxyServer(ProxyServer proxy_server, - PrivacyMode privacy_mode); - - // Needed to be an element of std::set. - bool operator<(const PreconnectingProxyServer& other) const; - bool operator==(const PreconnectingProxyServer& other) const; - - const ProxyServer proxy_server; - const PrivacyMode privacy_mode; - }; - // Values must not be changed or reused. Keep in sync with identically named // enum in histograms.xml. enum AlternativeServiceType { @@ -179,21 +165,6 @@ // from |job_controller_set_|. void OnJobControllerComplete(JobController* controller); - // Returns true if a connection to the proxy server contained in |proxy_info| - // that has privacy mode |privacy_mode| can be skipped by a job controlled by - // |controller|. - bool OnInitConnection(const JobController& controller, - const ProxyInfo& proxy_info, - PrivacyMode privacy_mode); - - // Notifies |this| that a stream to the proxy server contained in |proxy_info| - // with privacy mode |privacy_mode| is ready. - void OnStreamReady(const ProxyInfo& proxy_info, PrivacyMode privacy_mode); - - // Returns true if |proxy_info| contains a proxy server that supports request - // priorities. - bool ProxyServerSupportsPriorities(const ProxyInfo& proxy_info) const; - HttpNetworkSession* const session_; // All Requests/Preconnects are assigned with a JobController to manage @@ -206,10 +177,6 @@ // Factory used by job controllers for creating jobs. std::unique_ptr<JobFactory> job_factory_; - // Set of proxy servers that support request priorities to which subsequent - // preconnects should be skipped. - std::set<PreconnectingProxyServer> preconnecting_proxy_servers_; - DISALLOW_COPY_AND_ASSIGN(HttpStreamFactory); };
diff --git a/net/http/http_stream_factory_job.cc b/net/http/http_stream_factory_job.cc index 8e8a1c8a..fd4c9d3 100644 --- a/net/http/http_stream_factory_job.cc +++ b/net/http/http_stream_factory_job.cc
@@ -702,11 +702,6 @@ DCHECK(proxy_info_.proxy_server().is_valid()); next_state_ = STATE_INIT_CONNECTION_COMPLETE; - if (delegate_->OnInitConnection(proxy_info_)) { - // Return since the connection initialization can be skipped. - return OK; - } - if (proxy_info_.is_https() || proxy_info_.is_quic()) { // Disable network fetches for HTTPS proxies, since the network requests // are probably going to need to go through the proxy too.
diff --git a/net/http/http_stream_factory_job.h b/net/http/http_stream_factory_job.h index 94d1a91..c7753aee 100644 --- a/net/http/http_stream_factory_job.h +++ b/net/http/http_stream_factory_job.h
@@ -106,10 +106,6 @@ const ProxyInfo& used_proxy_info, HttpAuthController* auth_controller) = 0; - // Returns true if the connection initialization to the proxy server - // contained in |proxy_info| can be skipped. - virtual bool OnInitConnection(const ProxyInfo& proxy_info) = 0; - // Invoked when the |job| finishes pre-connecting sockets. virtual void OnPreconnectsComplete(Job* job) = 0;
diff --git a/net/http/http_stream_factory_job_controller.cc b/net/http/http_stream_factory_job_controller.cc index 028e652..bd12958e 100644 --- a/net/http/http_stream_factory_job_controller.cc +++ b/net/http/http_stream_factory_job_controller.cc
@@ -211,8 +211,6 @@ const SSLConfig& used_ssl_config) { DCHECK(job); - factory_->OnStreamReady(job->proxy_info(), request_info_.privacy_mode); - if (IsJobOrphaned(job)) { // We have bound a job to the associated HttpStreamRequest, |job| has been // orphaned. @@ -419,12 +417,6 @@ auth_controller); } -bool HttpStreamFactory::JobController::OnInitConnection( - const ProxyInfo& proxy_info) { - return factory_->OnInitConnection(*this, proxy_info, - request_info_.privacy_mode); -} - void HttpStreamFactory::JobController::OnPreconnectsComplete(Job* job) { DCHECK_EQ(main_job_.get(), job); main_job_.reset();
diff --git a/net/http/http_stream_factory_job_controller.h b/net/http/http_stream_factory_job_controller.h index d91a559c..7c37e02 100644 --- a/net/http/http_stream_factory_job_controller.h +++ b/net/http/http_stream_factory_job_controller.h
@@ -121,8 +121,6 @@ const ProxyInfo& used_proxy_info, HttpAuthController* auth_controller) override; - bool OnInitConnection(const ProxyInfo& proxy_info) override; - // Invoked when the |job| finishes pre-connecting sockets. void OnPreconnectsComplete(Job* job) override;
diff --git a/net/http/http_stream_factory_unittest.cc b/net/http/http_stream_factory_unittest.cc index d1256bf..fb873fe 100644 --- a/net/http/http_stream_factory_unittest.cc +++ b/net/http/http_stream_factory_unittest.cc
@@ -1216,169 +1216,6 @@ } } -// Verify that only one preconnect job succeeds to a proxy server that supports -// request priorities. -TEST_F(HttpStreamFactoryTest, OnlyOnePreconnectToProxyServer) { - for (bool set_http_server_properties : {false, true}) { - for (int num_streams = 1; num_streams < 3; ++num_streams) { - base::HistogramTester histogram_tester; - GURL url = GURL("http://www.google.com"); - std::unique_ptr<ProxyResolutionService> proxy_resolution_service = - ProxyResolutionService::CreateFixedFromPacResult( - "HTTPS myproxy.org:443", TRAFFIC_ANNOTATION_FOR_TESTS); - - // Set up the proxy server as a server that supports request priorities. - HttpServerProperties http_server_properties; - if (set_http_server_properties) { - url::SchemeHostPort spdy_server("https", "myproxy.org", 443); - http_server_properties.SetSupportsSpdy(spdy_server, - NetworkIsolationKey(), true); - } - - SpdySessionDependencies session_deps; - HttpNetworkSession::Params session_params = - SpdySessionDependencies::CreateSessionParams(&session_deps); - session_params.enable_quic = true; - - HttpNetworkSession::Context session_context = - SpdySessionDependencies::CreateSessionContext(&session_deps); - session_context.proxy_resolution_service = proxy_resolution_service.get(); - session_context.http_server_properties = &http_server_properties; - - auto session = - std::make_unique<HttpNetworkSession>(session_params, session_context); - - HttpNetworkSessionPeer peer(session.get()); - ProxyServer proxy_server(ProxyServer::SCHEME_HTTPS, - HostPortPair("myproxy.org", 443)); - - for (int preconnect_request = 0; preconnect_request < 2; - ++preconnect_request) { - CommonConnectJobParams common_connect_job_params = - session->CreateCommonConnectJobParams(); - CapturePreconnectsTransportSocketPool* http_proxy_pool = - new CapturePreconnectsTransportSocketPool( - &common_connect_job_params); - - auto mock_pool_manager = - std::make_unique<MockClientSocketPoolManager>(); - mock_pool_manager->SetSocketPool(proxy_server, - base::WrapUnique(http_proxy_pool)); - peer.SetClientSocketPoolManager(std::move(mock_pool_manager)); - - HttpRequestInfo request; - request.method = "GET"; - request.url = url; - request.load_flags = 0; - request.traffic_annotation = - MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS); - - if (preconnect_request == 0) { - // First preconnect job should succeed. - session->http_stream_factory()->PreconnectStreams(num_streams, - request); - EXPECT_EQ(num_streams, http_proxy_pool->last_num_streams()); - } else { - // Second preconnect job should not succeed. - session->http_stream_factory()->PreconnectStreams(num_streams, - request); - if (set_http_server_properties) { - EXPECT_EQ(-1, http_proxy_pool->last_num_streams()); - } else { - EXPECT_EQ(num_streams, http_proxy_pool->last_num_streams()); - } - } - } - // Preconnects should be skipped only to proxy servers that support - // request priorities. - if (set_http_server_properties) { - histogram_tester.ExpectUniqueSample( - "Net.PreconnectSkippedToProxyServers", 1, 1); - } else { - histogram_tester.ExpectTotalCount("Net.PreconnectSkippedToProxyServers", - 0); - } - } - } -} - -// Verify that preconnect to a HTTP2 proxy server with a privacy mode different -// than that of the in-flight preconnect job succeeds. -TEST_F(HttpStreamFactoryTest, ProxyServerPreconnectDifferentPrivacyModes) { - int num_streams = 1; - base::HistogramTester histogram_tester; - GURL url = GURL("http://www.google.com"); - std::unique_ptr<ProxyResolutionService> proxy_resolution_service = - ProxyResolutionService::CreateFixedFromPacResult( - "HTTPS myproxy.org:443", TRAFFIC_ANNOTATION_FOR_TESTS); - - // Set up the proxy server as a server that supports request priorities. - HttpServerProperties http_server_properties; - - url::SchemeHostPort spdy_server("https", "myproxy.org", 443); - http_server_properties.SetSupportsSpdy(spdy_server, NetworkIsolationKey(), - true); - - SpdySessionDependencies session_deps; - HttpNetworkSession::Params session_params = - SpdySessionDependencies::CreateSessionParams(&session_deps); - session_params.enable_quic = true; - - HttpNetworkSession::Context session_context = - SpdySessionDependencies::CreateSessionContext(&session_deps); - session_context.proxy_resolution_service = proxy_resolution_service.get(); - session_context.http_server_properties = &http_server_properties; - - auto session = - std::make_unique<HttpNetworkSession>(session_params, session_context); - - HttpNetworkSessionPeer peer(session.get()); - ProxyServer proxy_server(ProxyServer::SCHEME_HTTPS, - HostPortPair("myproxy.org", 443)); - - CommonConnectJobParams common_connect_job_params = - session->CreateCommonConnectJobParams(); - CapturePreconnectsTransportSocketPool* http_proxy_pool = - new CapturePreconnectsTransportSocketPool(&common_connect_job_params); - - auto mock_pool_manager = std::make_unique<MockClientSocketPoolManager>(); - mock_pool_manager->SetSocketPool(proxy_server, - base::WrapUnique(http_proxy_pool)); - peer.SetClientSocketPoolManager(std::move(mock_pool_manager)); - - HttpRequestInfo request_privacy_mode_disabled; - request_privacy_mode_disabled.method = "GET"; - request_privacy_mode_disabled.url = url; - request_privacy_mode_disabled.load_flags = 0; - request_privacy_mode_disabled.traffic_annotation = - MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS); - - // First preconnect job should succeed. - session->http_stream_factory()->PreconnectStreams( - num_streams, request_privacy_mode_disabled); - EXPECT_EQ(num_streams, http_proxy_pool->last_num_streams()); - http_proxy_pool->reset(); - - // Second preconnect job with same privacy mode should not succeed. - session->http_stream_factory()->PreconnectStreams( - num_streams + 1, request_privacy_mode_disabled); - EXPECT_EQ(-1, http_proxy_pool->last_num_streams()); - - // Next request with a different privacy mode should succeed. - HttpRequestInfo request_privacy_mode_enabled; - request_privacy_mode_enabled.method = "GET"; - request_privacy_mode_enabled.url = url; - request_privacy_mode_enabled.load_flags = 0; - request_privacy_mode_enabled.privacy_mode = PRIVACY_MODE_ENABLED; - request_privacy_mode_enabled.traffic_annotation = - MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS); - - // Request with a different privacy mode should succeed. - session->http_stream_factory()->PreconnectStreams( - num_streams, request_privacy_mode_enabled); - EXPECT_EQ(num_streams, http_proxy_pool->last_num_streams()); -} - namespace { // Return count of distinct groups in given socket pool. @@ -1702,93 +1539,6 @@ EXPECT_FALSE(waiter.used_proxy_info().is_direct()); } -// Verifies that once a stream has been created to a proxy server (that supports -// request priorities) the next preconnect job can again open new sockets. -TEST_F(HttpStreamFactoryTest, RequestHttpStreamOverProxyWithPreconnects) { - SpdySessionDependencies session_deps(ProxyResolutionService::CreateFixed( - "https://myproxy.org:443", TRAFFIC_ANNOTATION_FOR_TESTS)); - - // Set up the proxy server as a server that supports request priorities. - auto http_server_properties = std::make_unique<HttpServerProperties>(); - url::SchemeHostPort spdy_server("https", "myproxy.org", 443); - http_server_properties->SetSupportsSpdy(spdy_server, NetworkIsolationKey(), - true); - session_deps.http_server_properties = std::move(http_server_properties); - - StaticSocketDataProvider socket_data; - socket_data.set_connect_data(MockConnect(ASYNC, OK)); - session_deps.socket_factory->AddSocketDataProvider(&socket_data); - - SSLSocketDataProvider ssl_data(ASYNC, OK); - session_deps.socket_factory->AddSSLSocketDataProvider(&ssl_data); - - std::unique_ptr<HttpNetworkSession> session( - SpdySessionDependencies::SpdyCreateSession(&session_deps)); - - // Now preconnect a request. Only the first preconnect should succeed. - HttpRequestInfo request_info; - request_info.method = "GET"; - request_info.url = GURL("http://www.google.com"); - request_info.load_flags = 0; - request_info.traffic_annotation = - MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS); - - base::HistogramTester histogram_tester; - const int num_preconnects = 5; - - // First preconnect would be successful. The next |num_preconnects-1| would be - // skipped. - for (int preconnect_request = 1; preconnect_request <= num_preconnects; - ++preconnect_request) { - session->http_stream_factory()->PreconnectStreams(1, request_info); - base::RunLoop().RunUntilIdle(); - while (GetSocketPoolGroupCount(session->GetSocketPool( - HttpNetworkSession::NORMAL_SOCKET_POOL, - ProxyServer(ProxyServer::SCHEME_HTTPS, - HostPortPair("myproxy.org", 443)))) == 0) { - base::RunLoop().RunUntilIdle(); - } - } - - histogram_tester.ExpectUniqueSample("Net.PreconnectSkippedToProxyServers", 1, - num_preconnects - 1); - - // Start a request. This should cause subsequent preconnect to proxy server to - // succeed. - SSLConfig ssl_config; - StreamRequestWaiter waiter; - std::unique_ptr<HttpStreamRequest> request( - session->http_stream_factory()->RequestStream( - request_info, DEFAULT_PRIORITY, ssl_config, ssl_config, &waiter, - /* enable_ip_based_pooling = */ true, - /* enable_alternative_services = */ true, NetLogWithSource())); - waiter.WaitForStream(); - EXPECT_TRUE(waiter.stream_done()); - ASSERT_TRUE(nullptr != waiter.stream()); - EXPECT_TRUE(nullptr == waiter.websocket_stream()); - - EXPECT_EQ(1, GetSocketPoolGroupCount(session->GetSocketPool( - HttpNetworkSession::NORMAL_SOCKET_POOL, - ProxyServer(ProxyServer::SCHEME_HTTPS, - HostPortPair("myproxy.org", 443))))); - EXPECT_FALSE(waiter.used_proxy_info().is_direct()); - - for (int preconnect_request = 1; preconnect_request <= num_preconnects; - ++preconnect_request) { - session->http_stream_factory()->PreconnectStreams(1, request_info); - base::RunLoop().RunUntilIdle(); - EXPECT_EQ(1, GetSocketPoolGroupCount(session->GetSocketPool( - HttpNetworkSession::NORMAL_SOCKET_POOL, - ProxyServer(ProxyServer::SCHEME_HTTPS, - HostPortPair("myproxy.org", 443))))); - } - - // First preconnect would be successful since the stream to the proxy server - // has suceeded. The next |num_preconnects-1| would be skipped. - histogram_tester.ExpectUniqueSample("Net.PreconnectSkippedToProxyServers", 1, - 2 * (num_preconnects - 1)); -} - TEST_F(HttpStreamFactoryTest, RequestWebSocketBasicHandshakeStream) { SpdySessionDependencies session_deps(ProxyResolutionService::CreateDirect());
diff --git a/net/quic/quic_chromium_client_session.cc b/net/quic/quic_chromium_client_session.cc index f78217df..888f3b6 100644 --- a/net/quic/quic_chromium_client_session.cc +++ b/net/quic/quic_chromium_client_session.cc
@@ -984,7 +984,7 @@ if (!VersionHasStreamType(connection()->transport_version())) { WritePriority(update.id, update.parent_stream_id, update.weight, update.exclusive); - } else { + } else if (FLAGS_quic_allow_http3_priority) { quic::PriorityFrame frame; frame.weight = update.weight; frame.exclusive = update.exclusive; @@ -3118,7 +3118,7 @@ promised_id, priority, &parent_stream_id, &weight, &exclusive); if (!VersionHasStreamType(connection()->transport_version())) { WritePriority(promised_id, parent_stream_id, weight, exclusive); - } else { + } else if (FLAGS_quic_allow_http3_priority) { quic::PriorityFrame frame; frame.weight = weight; frame.exclusive = exclusive;
diff --git a/net/quic/quic_chromium_packet_reader.cc b/net/quic/quic_chromium_packet_reader.cc index c0c2bc7..468052e 100644 --- a/net/quic/quic_chromium_packet_reader.cc +++ b/net/quic/quic_chromium_packet_reader.cc
@@ -31,7 +31,7 @@ yield_after_duration_(yield_after_duration), yield_after_(quic::QuicTime::Infinite()), read_buffer_(base::MakeRefCounted<IOBufferWithSize>( - static_cast<size_t>(quic::kMaxOutgoingPacketSize))), + static_cast<size_t>(quic::kMaxIncomingPacketSize))), net_log_(net_log) {} QuicChromiumPacketReader::~QuicChromiumPacketReader() {} @@ -74,8 +74,7 @@ } size_t QuicChromiumPacketReader::EstimateMemoryUsage() const { - // Return the size of |read_buffer_|. - return quic::kMaxOutgoingPacketSize; + return read_buffer_->size(); } bool QuicChromiumPacketReader::ProcessReadResult(int result) {
diff --git a/net/quic/quic_flags_list.h b/net/quic/quic_flags_list.h index 26b9ac2..f2a1ebd 100644 --- a/net/quic/quic_flags_list.h +++ b/net/quic/quic_flags_list.h
@@ -391,7 +391,4 @@ false) // If true, support HTTP/3 priority in v99. -// TODO(renjietang): flip back to false since draft 23 -// (https://tools.ietf.org/html/draft-ietf-quic-http-23#appendix-B.1) -// no longer support HTTP/3 priority. -QUIC_FLAG(bool, FLAGS_quic_allow_http3_priority, true) +QUIC_FLAG(bool, FLAGS_quic_allow_http3_priority, false)
diff --git a/net/quic/quic_network_transaction_unittest.cc b/net/quic/quic_network_transaction_unittest.cc index c5ac6dd..69e3099e1b 100644 --- a/net/quic/quic_network_transaction_unittest.cc +++ b/net/quic/quic_network_transaction_unittest.cc
@@ -3352,7 +3352,7 @@ client_maker_.MakeConnectionClosePacket( 13, true, quic::QUIC_TOO_MANY_RTOS, "5 consecutive retransmission timeouts")); - } else { + } else if (FLAGS_quic_allow_http3_priority) { quic_data.AddWrite( SYNCHRONOUS, client_maker_.MakeRstPacket( 3, true, GetNthClientInitiatedBidirectionalStreamId(0), @@ -3390,6 +3390,46 @@ client_maker_.MakeConnectionClosePacket( 14, true, quic::QUIC_TOO_MANY_RTOS, "5 consecutive retransmission timeouts")); + } else { + quic_data.AddWrite( + SYNCHRONOUS, client_maker_.MakeRstPacket( + 3, true, GetNthClientInitiatedBidirectionalStreamId(0), + quic::QUIC_STREAM_CANCELLED)); + client_maker_.RemoveSavedStreamFrames( + GetNthClientInitiatedBidirectionalStreamId(0)); + // When PRIORITY is disabled, packet 2 only contains request headers. And + // since the request stream is reset, packet 2 will not be retransmitted. + // TLP 1 + quic_data.AddWrite(SYNCHRONOUS, + client_maker_.MakeRetransmissionPacket(1, 4, true)); + // TLP 2 + quic_data.AddWrite(SYNCHRONOUS, + client_maker_.MakeRetransmissionPacket(3, 5, true)); + // RTO 1 + quic_data.AddWrite(SYNCHRONOUS, + client_maker_.MakeRetransmissionPacket(1, 6, true)); + quic_data.AddWrite(SYNCHRONOUS, + client_maker_.MakeRetransmissionPacket(3, 7, true)); + // RTO 2 + quic_data.AddWrite(SYNCHRONOUS, + client_maker_.MakeRetransmissionPacket(1, 8, true)); + quic_data.AddWrite(SYNCHRONOUS, + client_maker_.MakeRetransmissionPacket(3, 9, true)); + // RTO 3 + quic_data.AddWrite(SYNCHRONOUS, + client_maker_.MakeRetransmissionPacket(1, 10, true)); + quic_data.AddWrite(SYNCHRONOUS, + client_maker_.MakeRetransmissionPacket(3, 11, true)); + // RTO 4 + quic_data.AddWrite(SYNCHRONOUS, + client_maker_.MakeRetransmissionPacket(1, 12, true)); + quic_data.AddWrite(SYNCHRONOUS, + client_maker_.MakeRetransmissionPacket(3, 13, true)); + // RTO 5 + quic_data.AddWrite(SYNCHRONOUS, + client_maker_.MakeConnectionClosePacket( + 14, true, quic::QUIC_TOO_MANY_RTOS, + "5 consecutive retransmission timeouts")); } quic_data.AddRead(ASYNC, OK); @@ -6553,8 +6593,10 @@ GetNthServerInitiatedUnidirectionalStreamId(0), false, GetRequestHeaders("GET", "https", "/pushed.jpg"), &server_maker_)); if ((client_headers_include_h2_stream_dependency_ && - version_.transport_version >= quic::QUIC_VERSION_43) || - VersionHasStreamType(version_.transport_version)) { + version_.transport_version >= quic::QUIC_VERSION_43 && + !VersionHasStreamType(version_.transport_version)) || + (VersionHasStreamType(version_.transport_version) && + FLAGS_quic_allow_http3_priority)) { mock_quic_data.AddWrite( SYNCHRONOUS, ConstructClientPriorityPacket( @@ -6645,8 +6687,10 @@ GetNthServerInitiatedUnidirectionalStreamId(0), false, GetRequestHeaders("GET", "https", "/pushed.jpg"), &server_maker_)); if ((client_headers_include_h2_stream_dependency_ && - version_.transport_version >= quic::QUIC_VERSION_43) || - VersionHasStreamType(version_.transport_version)) { + version_.transport_version >= quic::QUIC_VERSION_43 && + !VersionHasStreamType(version_.transport_version)) || + (VersionHasStreamType(version_.transport_version) && + FLAGS_quic_allow_http3_priority)) { mock_quic_data.AddWrite( SYNCHRONOUS, ConstructClientPriorityPacket( @@ -6913,8 +6957,10 @@ } if ((client_headers_include_h2_stream_dependency_ && - version_.transport_version >= quic::QUIC_VERSION_43) || - VersionHasStreamType(version_.transport_version)) { + version_.transport_version >= quic::QUIC_VERSION_43 && + !VersionHasStreamType(version_.transport_version)) || + (VersionHasStreamType(version_.transport_version) && + (FLAGS_quic_allow_http3_priority))) { mock_quic_data.AddWrite( SYNCHRONOUS, ConstructClientPriorityPacket( @@ -7585,8 +7631,10 @@ GetRequestHeaders("GET", "https", "/pushed.jpg"), &server_maker_)); if ((client_headers_include_h2_stream_dependency_ && - version_.transport_version >= quic::QUIC_VERSION_43) || - VersionHasStreamType(version_.transport_version)) { + version_.transport_version >= quic::QUIC_VERSION_43 && + !VersionHasStreamType(version_.transport_version)) || + (VersionHasStreamType(version_.transport_version) && + FLAGS_quic_allow_http3_priority)) { mock_quic_data.AddWrite( SYNCHRONOUS, ConstructClientPriorityPacket(
diff --git a/net/quic/quic_stream_factory.cc b/net/quic/quic_stream_factory.cc index 4bdfe48c..208abb5 100644 --- a/net/quic/quic_stream_factory.cc +++ b/net/quic/quic_stream_factory.cc
@@ -227,6 +227,14 @@ const base::Callback<bool(const GURL&)> origin_filter_; }; +std::set<std::string> HostsFromOrigins(std::set<HostPortPair> origins) { + std::set<std::string> hosts; + for (const auto& origin : origins) { + hosts.insert(origin.host()); + } + return hosts; +} + } // namespace QuicParams::QuicParams() @@ -1098,21 +1106,6 @@ return expect_on_host_resolution_; } -void QuicStreamRequest::SetSession( - std::unique_ptr<QuicChromiumClientSession::Handle> session) { - session_ = move(session); -} - -void QuicStreamRequest::OnConnectionFailedOnDefaultNetwork() { - if (!failed_on_default_network_callback_.is_null()) - std::move(failed_on_default_network_callback_).Run(OK); -} - -void QuicStreamRequest::OnRequestComplete(int rv) { - factory_ = nullptr; - std::move(callback_).Run(rv); -} - void QuicStreamRequest::ExpectOnHostResolution() { expect_on_host_resolution_ = true; } @@ -1125,6 +1118,16 @@ } } +void QuicStreamRequest::OnRequestComplete(int rv) { + factory_ = nullptr; + std::move(callback_).Run(rv); +} + +void QuicStreamRequest::OnConnectionFailedOnDefaultNetwork() { + if (!failed_on_default_network_callback_.is_null()) + std::move(failed_on_default_network_callback_).Run(OK); +} + base::TimeDelta QuicStreamRequest::GetTimeDelayForWaitingJob() const { if (!factory_) return base::TimeDelta(); @@ -1145,17 +1148,32 @@ return std::move(session_); } -namespace { - -std::set<std::string> HostsFromOrigins(std::set<HostPortPair> origins) { - std::set<std::string> hosts; - for (const auto& origin : origins) { - hosts.insert(origin.host()); - } - return hosts; +void QuicStreamRequest::SetSession( + std::unique_ptr<QuicChromiumClientSession::Handle> session) { + session_ = move(session); } -} // namespace +QuicStreamFactory::QuicSessionAliasKey::QuicSessionAliasKey( + const HostPortPair& destination, + const QuicSessionKey& session_key) + : destination_(destination), session_key_(session_key) {} + +bool QuicStreamFactory::QuicSessionAliasKey::operator<( + const QuicSessionAliasKey& other) const { + return std::tie(destination_, session_key_) < + std::tie(other.destination_, other.session_key_); +} + +bool QuicStreamFactory::QuicSessionAliasKey::operator==( + const QuicSessionAliasKey& other) const { + return destination_.Equals(other.destination_) && + session_key_ == other.session_key_; +} + +size_t QuicStreamFactory::QuicSessionAliasKey::EstimateMemoryUsage() const { + return base::trace_event::EstimateMemoryUsage(destination_) + + base::trace_event::EstimateMemoryUsage(session_key_.server_id()); +} QuicStreamFactory::QuicStreamFactory( NetLog* net_log, @@ -1218,86 +1236,6 @@ InitializeMigrationOptions(); } -void QuicStreamFactory::InitializeMigrationOptions() { - // The following list of options cannot be set immediately until - // prerequisites are met. Cache the initial setting in local variables and - // reset them in |params_|. - bool migrate_sessions_on_network_change = - params_.migrate_sessions_on_network_change_v2; - bool migrate_sessions_early = params_.migrate_sessions_early_v2; - bool retry_on_alternate_network_before_handshake = - params_.retry_on_alternate_network_before_handshake; - bool migrate_idle_sessions = params_.migrate_idle_sessions; - bool allow_port_migration = params_.allow_port_migration; - params_.migrate_sessions_on_network_change_v2 = false; - params_.migrate_sessions_early_v2 = false; - params_.allow_port_migration = false; - params_.retry_on_alternate_network_before_handshake = false; - params_.migrate_idle_sessions = false; - - DCHECK(!(migrate_sessions_early && params_.go_away_on_path_degrading)); - DCHECK(!(allow_port_migration && params_.go_away_on_path_degrading)); - - // TODO(zhongyi): deprecate |goaway_sessions_on_ip_change| if the experiment - // is no longer needed. - // goaway_sessions_on_ip_change and close_sessions_on_ip_change should never - // be simultaneously set to true. - DCHECK(!(params_.close_sessions_on_ip_change && - params_.goaway_sessions_on_ip_change)); - - bool handle_ip_change = params_.close_sessions_on_ip_change || - params_.goaway_sessions_on_ip_change; - // If IP address changes are handled explicitly, connection migration should - // not be set. - DCHECK(!(handle_ip_change && migrate_sessions_on_network_change)); - - if (handle_ip_change) - NetworkChangeNotifier::AddIPAddressObserver(this); - - // Port migration and early migration both act on path degrading and thus can - // not be simultaneously set. - DCHECK(!allow_port_migration || !migrate_sessions_early); - - if (allow_port_migration) - params_.allow_port_migration = true; - - if (!NetworkChangeNotifier::AreNetworkHandlesSupported()) - return; - - NetworkChangeNotifier::AddNetworkObserver(this); - // Perform checks on the connection migration options. - if (!migrate_sessions_on_network_change) { - DCHECK(!migrate_sessions_early); - return; - } - - // Enable migration on platform notifications. - params_.migrate_sessions_on_network_change_v2 = true; - - if (!migrate_sessions_early) { - DCHECK(!migrate_idle_sessions && - !retry_on_alternate_network_before_handshake); - return; - } - - // Enable migration on path degrading. - params_.migrate_sessions_early_v2 = true; - // Set retransmittable on wire timeout for migration on path degrading if no - // value is specified. - if (retransmittable_on_wire_timeout_.IsZero()) { - retransmittable_on_wire_timeout_ = quic::QuicTime::Delta::FromMicroseconds( - kDefaultRetransmittableOnWireTimeout.InMicroseconds()); - } - - // Enable retry on alternate network before handshake. - if (retry_on_alternate_network_before_handshake) - params_.retry_on_alternate_network_before_handshake = true; - - // Enable migration for idle sessions. - if (migrate_idle_sessions) - params_.migrate_idle_sessions = true; -} - QuicStreamFactory::~QuicStreamFactory() { UMA_HISTOGRAM_COUNTS_1000("Net.NumQuicSessionsAtShutdown", all_sessions_.size()); @@ -1323,81 +1261,6 @@ } } -void QuicStreamFactory::set_is_quic_known_to_work_on_current_network( - bool is_quic_known_to_work_on_current_network) { - is_quic_known_to_work_on_current_network_ = - is_quic_known_to_work_on_current_network; - if (!(local_address_ == IPEndPoint())) { - if (is_quic_known_to_work_on_current_network_) { - http_server_properties_->SetLastLocalAddressWhenQuicWorked( - local_address_.address()); - } else { - http_server_properties_->ClearLastLocalAddressWhenQuicWorked(); - } - } -} - -base::TimeDelta QuicStreamFactory::GetTimeDelayForWaitingJob( - const quic::QuicServerId& server_id, - const NetworkIsolationKey& network_isolation_key) { - // If |is_quic_known_to_work_on_current_network_| is false, then one of the - // following is true: - // 1) This is startup and QuicStreamFactory::CreateSession() and - // ConfigureSocket() have yet to be called, and it is not yet known - // if the current network is the last one where QUIC worked. - // 2) Startup has been completed, and QUIC has not been used - // successfully since startup, or on this network before. - if (!is_quic_known_to_work_on_current_network_) { - // If |need_to_check_persisted_supports_quic_| is false, this is case 1) - // above. If HasLastLocalAddressWhenQuicWorked() is also true, then there's - // a chance the current network is the last one on which QUIC worked. So - // only delay the request if there's no chance that is the case. - if (!need_to_check_persisted_supports_quic_ || - !http_server_properties_->HasLastLocalAddressWhenQuicWorked()) { - return base::TimeDelta(); - } - } - - int64_t srtt = 1.5 * GetServerNetworkStatsSmoothedRttInMicroseconds( - server_id, network_isolation_key); - // Picked 300ms based on mean time from - // Net.QuicSession.HostResolution.HandshakeConfirmedTime histogram. - const int kDefaultRTT = 300 * quic::kNumMicrosPerMilli; - if (!srtt) - srtt = kDefaultRTT; - return base::TimeDelta::FromMicroseconds(srtt); -} - -void QuicStreamFactory::DumpMemoryStats( - base::trace_event::ProcessMemoryDump* pmd, - const std::string& parent_absolute_name) const { - if (all_sessions_.empty() && active_jobs_.empty()) - return; - base::trace_event::MemoryAllocatorDump* factory_dump = - pmd->CreateAllocatorDump(parent_absolute_name + "/quic_stream_factory"); - size_t memory_estimate = - base::trace_event::EstimateMemoryUsage(all_sessions_) + - base::trace_event::EstimateMemoryUsage(active_sessions_) + - base::trace_event::EstimateMemoryUsage(session_aliases_) + - base::trace_event::EstimateMemoryUsage(ip_aliases_) + - base::trace_event::EstimateMemoryUsage(session_peer_ip_) + - base::trace_event::EstimateMemoryUsage(gone_away_aliases_) + - base::trace_event::EstimateMemoryUsage(active_jobs_) + - base::trace_event::EstimateMemoryUsage(active_cert_verifier_jobs_); - factory_dump->AddScalar(base::trace_event::MemoryAllocatorDump::kNameSize, - base::trace_event::MemoryAllocatorDump::kUnitsBytes, - memory_estimate); - factory_dump->AddScalar("all_sessions", - base::trace_event::MemoryAllocatorDump::kUnitsObjects, - all_sessions_.size()); - factory_dump->AddScalar("active_jobs", - base::trace_event::MemoryAllocatorDump::kUnitsObjects, - active_jobs_.size()); - factory_dump->AddScalar("active_cert_jobs", - base::trace_event::MemoryAllocatorDump::kUnitsObjects, - active_cert_verifier_jobs_.size()); -} - bool QuicStreamFactory::CanUseExistingSession(const QuicSessionKey& session_key, const HostPortPair& destination) { // TODO(zhongyi): delete active_sessions_.empty() checks once the @@ -1421,13 +1284,6 @@ return false; } -void QuicStreamFactory::MarkAllActiveSessionsGoingAway() { - while (!active_sessions_.empty()) { - QuicChromiumClientSession* session = active_sessions_.begin()->second; - OnSessionGoingAway(session); - } -} - int QuicStreamFactory::Create(const QuicSessionKey& session_key, const HostPortPair& destination, quic::ParsedQuicVersion quic_version, @@ -1547,82 +1403,6 @@ return rv; } -QuicStreamFactory::QuicSessionAliasKey::QuicSessionAliasKey( - const HostPortPair& destination, - const QuicSessionKey& session_key) - : destination_(destination), session_key_(session_key) {} - -bool QuicStreamFactory::QuicSessionAliasKey::operator<( - const QuicSessionAliasKey& other) const { - return std::tie(destination_, session_key_) < - std::tie(other.destination_, other.session_key_); -} - -bool QuicStreamFactory::QuicSessionAliasKey::operator==( - const QuicSessionAliasKey& other) const { - return destination_.Equals(other.destination_) && - session_key_ == other.session_key_; -} - -size_t QuicStreamFactory::QuicSessionAliasKey::EstimateMemoryUsage() const { - return base::trace_event::EstimateMemoryUsage(destination_) + - base::trace_event::EstimateMemoryUsage(session_key_.server_id()); -} - -bool QuicStreamFactory::HasMatchingIpSession(const QuicSessionAliasKey& key, - const AddressList& address_list) { - const quic::QuicServerId& server_id(key.server_id()); - DCHECK(!HasActiveSession(key.session_key())); - for (const IPEndPoint& address : address_list) { - if (!base::Contains(ip_aliases_, address)) - continue; - - const SessionSet& sessions = ip_aliases_[address]; - for (QuicChromiumClientSession* session : sessions) { - if (!session->CanPool(server_id.host(), key.session_key().privacy_mode(), - key.session_key().socket_tag(), - key.session_key().network_isolation_key())) { - continue; - } - active_sessions_[key.session_key()] = session; - session_aliases_[session].insert(key); - return true; - } - } - return false; -} - -void QuicStreamFactory::OnJobComplete(Job* job, int rv) { - auto iter = active_jobs_.find(job->key().session_key()); - DCHECK(iter != active_jobs_.end()); - if (rv == OK) { - set_is_quic_known_to_work_on_current_network(true); - - auto session_it = active_sessions_.find(job->key().session_key()); - CHECK(session_it != active_sessions_.end()); - QuicChromiumClientSession* session = session_it->second; - for (auto* request : iter->second->stream_requests()) { - // Do not notify |request| yet. - request->SetSession(session->CreateHandle(job->key().destination())); - } - } - - for (auto* request : iter->second->stream_requests()) { - // Even though we're invoking callbacks here, we don't need to worry - // about |this| being deleted, because the factory is owned by the - // profile which can not be deleted via callbacks. - if (rv < 0) { - job->PopulateNetErrorDetails(request->net_error_details()); - } - request->OnRequestComplete(rv); - } - active_jobs_.erase(iter); -} - -void QuicStreamFactory::OnCertVerifyJobComplete(CertVerifierJob* job, int rv) { - active_cert_verifier_jobs_.erase(job->server_id()); -} - void QuicStreamFactory::OnSessionGoingAway(QuicChromiumClientSession* session) { const AliasSet& aliases = session_aliases_[session]; for (auto it = aliases.begin(); it != aliases.end(); ++it) { @@ -1737,140 +1517,6 @@ } } -void QuicStreamFactory::OnIPAddressChanged() { - LogPlatformNotificationInHistogram(NETWORK_IP_ADDRESS_CHANGED); - // Do nothing if connection migration is turned on. - if (params_.migrate_sessions_on_network_change_v2) - return; - - set_is_quic_known_to_work_on_current_network(false); - if (params_.close_sessions_on_ip_change) { - CloseAllSessions(ERR_NETWORK_CHANGED, quic::QUIC_IP_ADDRESS_CHANGED); - } else { - DCHECK(params_.goaway_sessions_on_ip_change); - MarkAllActiveSessionsGoingAway(); - } -} - -void QuicStreamFactory::OnNetworkConnected(NetworkHandle network) { - LogPlatformNotificationInHistogram(NETWORK_CONNECTED); - if (!params_.migrate_sessions_on_network_change_v2) - return; - - ScopedConnectionMigrationEventLog scoped_event_log(net_log_, - "OnNetworkConnected"); - auto it = all_sessions_.begin(); - // Sessions may be deleted while iterating through the map. - while (it != all_sessions_.end()) { - QuicChromiumClientSession* session = it->first; - ++it; - session->OnNetworkConnected(network, scoped_event_log.net_log()); - } -} - -void QuicStreamFactory::OnNetworkMadeDefault(NetworkHandle network) { - LogPlatformNotificationInHistogram(NETWORK_MADE_DEFAULT); - if (!params_.migrate_sessions_on_network_change_v2) - return; - - // Clear alternative services that were marked as broken until default network - // changes. - if (params_.retry_on_alternate_network_before_handshake && - default_network_ != NetworkChangeNotifier::kInvalidNetworkHandle && - network != default_network_) { - http_server_properties_->OnDefaultNetworkChanged(); - } - - DCHECK_NE(NetworkChangeNotifier::kInvalidNetworkHandle, network); - default_network_ = network; - ScopedConnectionMigrationEventLog scoped_event_log(net_log_, - "OnNetworkMadeDefault"); - - auto it = all_sessions_.begin(); - // Sessions may be deleted while iterating through the map. - while (it != all_sessions_.end()) { - QuicChromiumClientSession* session = it->first; - ++it; - session->OnNetworkMadeDefault(network, scoped_event_log.net_log()); - } - set_is_quic_known_to_work_on_current_network(false); -} - -void QuicStreamFactory::OnNetworkDisconnected(NetworkHandle network) { - LogPlatformNotificationInHistogram(NETWORK_DISCONNECTED); - if (!params_.migrate_sessions_on_network_change_v2) - return; - - ScopedConnectionMigrationEventLog scoped_event_log(net_log_, - "OnNetworkDisconnected"); - auto it = all_sessions_.begin(); - // Sessions may be deleted while iterating through the map. - while (it != all_sessions_.end()) { - QuicChromiumClientSession* session = it->first; - ++it; - session->OnNetworkDisconnectedV2(/*disconnected_network*/ network, - scoped_event_log.net_log()); - } -} - -// This method is expected to only be called when migrating from Cellular to -// WiFi on Android, and should always be preceded by OnNetworkMadeDefault(). -void QuicStreamFactory::OnNetworkSoonToDisconnect(NetworkHandle network) { - LogPlatformNotificationInHistogram(NETWORK_SOON_TO_DISCONNECT); -} - -NetworkHandle QuicStreamFactory::FindAlternateNetwork( - NetworkHandle old_network) { - // Find a new network that sessions bound to |old_network| can be migrated to. - NetworkChangeNotifier::NetworkList network_list; - NetworkChangeNotifier::GetConnectedNetworks(&network_list); - for (NetworkHandle new_network : network_list) { - if (new_network != old_network) - return new_network; - } - return NetworkChangeNotifier::kInvalidNetworkHandle; -} - -std::unique_ptr<DatagramClientSocket> QuicStreamFactory::CreateSocket( - NetLog* net_log, - const NetLogSource& source) { - auto socket = client_socket_factory_->CreateDatagramClientSocket( - DatagramSocket::DEFAULT_BIND, net_log, source); - if (params_.enable_socket_recv_optimization) - socket->EnableRecvOptimization(); - return socket; -} - -void QuicStreamFactory::OnCertDBChanged() { - // We should flush the sessions if we removed trust from a - // cert, because a previously trusted server may have become - // untrusted. - // - // We should not flush the sessions if we added trust to a cert. - // - // Since the OnCertDBChanged method doesn't tell us what - // kind of change it is, we have to flush the socket - // pools to be safe. - MarkAllActiveSessionsGoingAway(); -} - -bool QuicStreamFactory::HasActiveSession( - const QuicSessionKey& session_key) const { - // TODO(rtenneti): crbug.com/498823 - delete active_sessions_.empty() check. - if (active_sessions_.empty()) - return false; - return base::Contains(active_sessions_, session_key); -} - -bool QuicStreamFactory::HasActiveJob(const QuicSessionKey& session_key) const { - return base::Contains(active_jobs_, session_key); -} - -bool QuicStreamFactory::HasActiveCertVerifierJob( - const quic::QuicServerId& server_id) const { - return base::Contains(active_cert_verifier_jobs_, server_id); -} - int QuicStreamFactory::ConfigureSocket(DatagramClientSocket* socket, IPEndPoint addr, NetworkHandle network, @@ -1933,6 +1579,269 @@ return OK; } +NetworkHandle QuicStreamFactory::FindAlternateNetwork( + NetworkHandle old_network) { + // Find a new network that sessions bound to |old_network| can be migrated to. + NetworkChangeNotifier::NetworkList network_list; + NetworkChangeNotifier::GetConnectedNetworks(&network_list); + for (NetworkHandle new_network : network_list) { + if (new_network != old_network) + return new_network; + } + return NetworkChangeNotifier::kInvalidNetworkHandle; +} + +std::unique_ptr<DatagramClientSocket> QuicStreamFactory::CreateSocket( + NetLog* net_log, + const NetLogSource& source) { + auto socket = client_socket_factory_->CreateDatagramClientSocket( + DatagramSocket::DEFAULT_BIND, net_log, source); + if (params_.enable_socket_recv_optimization) + socket->EnableRecvOptimization(); + return socket; +} + +void QuicStreamFactory::OnIPAddressChanged() { + LogPlatformNotificationInHistogram(NETWORK_IP_ADDRESS_CHANGED); + // Do nothing if connection migration is turned on. + if (params_.migrate_sessions_on_network_change_v2) + return; + + set_is_quic_known_to_work_on_current_network(false); + if (params_.close_sessions_on_ip_change) { + CloseAllSessions(ERR_NETWORK_CHANGED, quic::QUIC_IP_ADDRESS_CHANGED); + } else { + DCHECK(params_.goaway_sessions_on_ip_change); + MarkAllActiveSessionsGoingAway(); + } +} + +void QuicStreamFactory::OnNetworkConnected(NetworkHandle network) { + LogPlatformNotificationInHistogram(NETWORK_CONNECTED); + if (!params_.migrate_sessions_on_network_change_v2) + return; + + ScopedConnectionMigrationEventLog scoped_event_log(net_log_, + "OnNetworkConnected"); + auto it = all_sessions_.begin(); + // Sessions may be deleted while iterating through the map. + while (it != all_sessions_.end()) { + QuicChromiumClientSession* session = it->first; + ++it; + session->OnNetworkConnected(network, scoped_event_log.net_log()); + } +} + +void QuicStreamFactory::OnNetworkDisconnected(NetworkHandle network) { + LogPlatformNotificationInHistogram(NETWORK_DISCONNECTED); + if (!params_.migrate_sessions_on_network_change_v2) + return; + + ScopedConnectionMigrationEventLog scoped_event_log(net_log_, + "OnNetworkDisconnected"); + auto it = all_sessions_.begin(); + // Sessions may be deleted while iterating through the map. + while (it != all_sessions_.end()) { + QuicChromiumClientSession* session = it->first; + ++it; + session->OnNetworkDisconnectedV2(/*disconnected_network*/ network, + scoped_event_log.net_log()); + } +} + +// This method is expected to only be called when migrating from Cellular to +// WiFi on Android, and should always be preceded by OnNetworkMadeDefault(). +void QuicStreamFactory::OnNetworkSoonToDisconnect(NetworkHandle network) { + LogPlatformNotificationInHistogram(NETWORK_SOON_TO_DISCONNECT); +} + +void QuicStreamFactory::OnNetworkMadeDefault(NetworkHandle network) { + LogPlatformNotificationInHistogram(NETWORK_MADE_DEFAULT); + if (!params_.migrate_sessions_on_network_change_v2) + return; + + // Clear alternative services that were marked as broken until default network + // changes. + if (params_.retry_on_alternate_network_before_handshake && + default_network_ != NetworkChangeNotifier::kInvalidNetworkHandle && + network != default_network_) { + http_server_properties_->OnDefaultNetworkChanged(); + } + + DCHECK_NE(NetworkChangeNotifier::kInvalidNetworkHandle, network); + default_network_ = network; + ScopedConnectionMigrationEventLog scoped_event_log(net_log_, + "OnNetworkMadeDefault"); + + auto it = all_sessions_.begin(); + // Sessions may be deleted while iterating through the map. + while (it != all_sessions_.end()) { + QuicChromiumClientSession* session = it->first; + ++it; + session->OnNetworkMadeDefault(network, scoped_event_log.net_log()); + } + set_is_quic_known_to_work_on_current_network(false); +} + +void QuicStreamFactory::OnCertDBChanged() { + // We should flush the sessions if we removed trust from a + // cert, because a previously trusted server may have become + // untrusted. + // + // We should not flush the sessions if we added trust to a cert. + // + // Since the OnCertDBChanged method doesn't tell us what + // kind of change it is, we have to flush the socket + // pools to be safe. + MarkAllActiveSessionsGoingAway(); +} + +void QuicStreamFactory::set_is_quic_known_to_work_on_current_network( + bool is_quic_known_to_work_on_current_network) { + is_quic_known_to_work_on_current_network_ = + is_quic_known_to_work_on_current_network; + if (!(local_address_ == IPEndPoint())) { + if (is_quic_known_to_work_on_current_network_) { + http_server_properties_->SetLastLocalAddressWhenQuicWorked( + local_address_.address()); + } else { + http_server_properties_->ClearLastLocalAddressWhenQuicWorked(); + } + } +} + +base::TimeDelta QuicStreamFactory::GetTimeDelayForWaitingJob( + const quic::QuicServerId& server_id, + const NetworkIsolationKey& network_isolation_key) { + // If |is_quic_known_to_work_on_current_network_| is false, then one of the + // following is true: + // 1) This is startup and QuicStreamFactory::CreateSession() and + // ConfigureSocket() have yet to be called, and it is not yet known + // if the current network is the last one where QUIC worked. + // 2) Startup has been completed, and QUIC has not been used + // successfully since startup, or on this network before. + if (!is_quic_known_to_work_on_current_network_) { + // If |need_to_check_persisted_supports_quic_| is false, this is case 1) + // above. If HasLastLocalAddressWhenQuicWorked() is also true, then there's + // a chance the current network is the last one on which QUIC worked. So + // only delay the request if there's no chance that is the case. + if (!need_to_check_persisted_supports_quic_ || + !http_server_properties_->HasLastLocalAddressWhenQuicWorked()) { + return base::TimeDelta(); + } + } + + int64_t srtt = 1.5 * GetServerNetworkStatsSmoothedRttInMicroseconds( + server_id, network_isolation_key); + // Picked 300ms based on mean time from + // Net.QuicSession.HostResolution.HandshakeConfirmedTime histogram. + const int kDefaultRTT = 300 * quic::kNumMicrosPerMilli; + if (!srtt) + srtt = kDefaultRTT; + return base::TimeDelta::FromMicroseconds(srtt); +} + +void QuicStreamFactory::DumpMemoryStats( + base::trace_event::ProcessMemoryDump* pmd, + const std::string& parent_absolute_name) const { + if (all_sessions_.empty() && active_jobs_.empty()) + return; + base::trace_event::MemoryAllocatorDump* factory_dump = + pmd->CreateAllocatorDump(parent_absolute_name + "/quic_stream_factory"); + size_t memory_estimate = + base::trace_event::EstimateMemoryUsage(all_sessions_) + + base::trace_event::EstimateMemoryUsage(active_sessions_) + + base::trace_event::EstimateMemoryUsage(session_aliases_) + + base::trace_event::EstimateMemoryUsage(ip_aliases_) + + base::trace_event::EstimateMemoryUsage(session_peer_ip_) + + base::trace_event::EstimateMemoryUsage(gone_away_aliases_) + + base::trace_event::EstimateMemoryUsage(active_jobs_) + + base::trace_event::EstimateMemoryUsage(active_cert_verifier_jobs_); + factory_dump->AddScalar(base::trace_event::MemoryAllocatorDump::kNameSize, + base::trace_event::MemoryAllocatorDump::kUnitsBytes, + memory_estimate); + factory_dump->AddScalar("all_sessions", + base::trace_event::MemoryAllocatorDump::kUnitsObjects, + all_sessions_.size()); + factory_dump->AddScalar("active_jobs", + base::trace_event::MemoryAllocatorDump::kUnitsObjects, + active_jobs_.size()); + factory_dump->AddScalar("active_cert_jobs", + base::trace_event::MemoryAllocatorDump::kUnitsObjects, + active_cert_verifier_jobs_.size()); +} + +bool QuicStreamFactory::HasMatchingIpSession(const QuicSessionAliasKey& key, + const AddressList& address_list) { + const quic::QuicServerId& server_id(key.server_id()); + DCHECK(!HasActiveSession(key.session_key())); + for (const IPEndPoint& address : address_list) { + if (!base::Contains(ip_aliases_, address)) + continue; + + const SessionSet& sessions = ip_aliases_[address]; + for (QuicChromiumClientSession* session : sessions) { + if (!session->CanPool(server_id.host(), key.session_key().privacy_mode(), + key.session_key().socket_tag(), + key.session_key().network_isolation_key())) { + continue; + } + active_sessions_[key.session_key()] = session; + session_aliases_[session].insert(key); + return true; + } + } + return false; +} + +void QuicStreamFactory::OnJobComplete(Job* job, int rv) { + auto iter = active_jobs_.find(job->key().session_key()); + DCHECK(iter != active_jobs_.end()); + if (rv == OK) { + set_is_quic_known_to_work_on_current_network(true); + + auto session_it = active_sessions_.find(job->key().session_key()); + CHECK(session_it != active_sessions_.end()); + QuicChromiumClientSession* session = session_it->second; + for (auto* request : iter->second->stream_requests()) { + // Do not notify |request| yet. + request->SetSession(session->CreateHandle(job->key().destination())); + } + } + + for (auto* request : iter->second->stream_requests()) { + // Even though we're invoking callbacks here, we don't need to worry + // about |this| being deleted, because the factory is owned by the + // profile which can not be deleted via callbacks. + if (rv < 0) { + job->PopulateNetErrorDetails(request->net_error_details()); + } + request->OnRequestComplete(rv); + } + active_jobs_.erase(iter); +} + +void QuicStreamFactory::OnCertVerifyJobComplete(CertVerifierJob* job, int rv) { + active_cert_verifier_jobs_.erase(job->server_id()); +} + +bool QuicStreamFactory::HasActiveSession( + const QuicSessionKey& session_key) const { + // TODO(rtenneti): crbug.com/498823 - delete active_sessions_.empty() check. + if (active_sessions_.empty()) + return false; + return base::Contains(active_sessions_, session_key); +} + +bool QuicStreamFactory::HasActiveJob(const QuicSessionKey& session_key) const { + return base::Contains(active_jobs_, session_key); +} + +bool QuicStreamFactory::HasActiveCertVerifierJob( + const quic::QuicServerId& server_id) const { + return base::Contains(active_cert_verifier_jobs_, server_id); +} + int QuicStreamFactory::CreateSession( const QuicSessionAliasKey& key, quic::ParsedQuicVersion quic_version, @@ -2087,6 +1996,13 @@ session_peer_ip_[session] = peer_address; } +void QuicStreamFactory::MarkAllActiveSessionsGoingAway() { + while (!active_sessions_.empty()) { + QuicChromiumClientSession* session = active_sessions_.begin()->second; + OnSessionGoingAway(session); + } +} + void QuicStreamFactory::ConfigureInitialRttEstimate( const quic::QuicServerId& server_id, const NetworkIsolationKey& network_isolation_key, @@ -2123,6 +2039,14 @@ SetInitialRttEstimate(base::TimeDelta(), INITIAL_RTT_DEFAULT, config); } +int64_t QuicStreamFactory::GetServerNetworkStatsSmoothedRttInMicroseconds( + const quic::QuicServerId& server_id, + const NetworkIsolationKey& network_isolation_key) const { + const base::TimeDelta* srtt = + GetServerNetworkStatsSmoothedRtt(server_id, network_isolation_key); + return srtt == nullptr ? 0 : srtt->InMicroseconds(); +} + const base::TimeDelta* QuicStreamFactory::GetServerNetworkStatsSmoothedRtt( const quic::QuicServerId& server_id, const NetworkIsolationKey& network_isolation_key) const { @@ -2135,14 +2059,6 @@ return &(stats->srtt); } -int64_t QuicStreamFactory::GetServerNetworkStatsSmoothedRttInMicroseconds( - const quic::QuicServerId& server_id, - const NetworkIsolationKey& network_isolation_key) const { - const base::TimeDelta* srtt = - GetServerNetworkStatsSmoothedRtt(server_id, network_isolation_key); - return srtt == nullptr ? 0 : srtt->InMicroseconds(); -} - bool QuicStreamFactory::WasQuicRecentlyBroken( const QuicSessionKey& session_key) const { const AlternativeService alternative_service( @@ -2152,27 +2068,6 @@ alternative_service, session_key.network_isolation_key()); } -bool QuicStreamFactory::CryptoConfigCacheIsEmpty( - const quic::QuicServerId& server_id, - const NetworkIsolationKey& network_isolation_key) { - quic::QuicCryptoClientConfig::CachedState* cached = nullptr; - NetworkIsolationKey actual_network_isolation_key = - use_network_isolation_key_for_crypto_configs_ ? network_isolation_key - : NetworkIsolationKey(); - auto map_iterator = - active_crypto_config_map_.find(actual_network_isolation_key); - if (map_iterator != active_crypto_config_map_.end()) { - cached = map_iterator->second->config()->LookupOrCreate(server_id); - } else { - auto mru_iterator = - recent_crypto_config_map_.Peek(actual_network_isolation_key); - if (mru_iterator != recent_crypto_config_map_.end()) { - cached = mru_iterator->second->config()->LookupOrCreate(server_id); - } - } - return !cached || cached->IsEmpty(); -} - quic::QuicAsyncStatus QuicStreamFactory::StartCertVerifyJob( const CryptoClientConfigHandle& crypto_config_handle, const quic::QuicServerId& server_id, @@ -2197,6 +2092,86 @@ return status; } +void QuicStreamFactory::InitializeMigrationOptions() { + // The following list of options cannot be set immediately until + // prerequisites are met. Cache the initial setting in local variables and + // reset them in |params_|. + bool migrate_sessions_on_network_change = + params_.migrate_sessions_on_network_change_v2; + bool migrate_sessions_early = params_.migrate_sessions_early_v2; + bool retry_on_alternate_network_before_handshake = + params_.retry_on_alternate_network_before_handshake; + bool migrate_idle_sessions = params_.migrate_idle_sessions; + bool allow_port_migration = params_.allow_port_migration; + params_.migrate_sessions_on_network_change_v2 = false; + params_.migrate_sessions_early_v2 = false; + params_.allow_port_migration = false; + params_.retry_on_alternate_network_before_handshake = false; + params_.migrate_idle_sessions = false; + + DCHECK(!(migrate_sessions_early && params_.go_away_on_path_degrading)); + DCHECK(!(allow_port_migration && params_.go_away_on_path_degrading)); + + // TODO(zhongyi): deprecate |goaway_sessions_on_ip_change| if the experiment + // is no longer needed. + // goaway_sessions_on_ip_change and close_sessions_on_ip_change should never + // be simultaneously set to true. + DCHECK(!(params_.close_sessions_on_ip_change && + params_.goaway_sessions_on_ip_change)); + + bool handle_ip_change = params_.close_sessions_on_ip_change || + params_.goaway_sessions_on_ip_change; + // If IP address changes are handled explicitly, connection migration should + // not be set. + DCHECK(!(handle_ip_change && migrate_sessions_on_network_change)); + + if (handle_ip_change) + NetworkChangeNotifier::AddIPAddressObserver(this); + + // Port migration and early migration both act on path degrading and thus can + // not be simultaneously set. + DCHECK(!allow_port_migration || !migrate_sessions_early); + + if (allow_port_migration) + params_.allow_port_migration = true; + + if (!NetworkChangeNotifier::AreNetworkHandlesSupported()) + return; + + NetworkChangeNotifier::AddNetworkObserver(this); + // Perform checks on the connection migration options. + if (!migrate_sessions_on_network_change) { + DCHECK(!migrate_sessions_early); + return; + } + + // Enable migration on platform notifications. + params_.migrate_sessions_on_network_change_v2 = true; + + if (!migrate_sessions_early) { + DCHECK(!migrate_idle_sessions && + !retry_on_alternate_network_before_handshake); + return; + } + + // Enable migration on path degrading. + params_.migrate_sessions_early_v2 = true; + // Set retransmittable on wire timeout for migration on path degrading if no + // value is specified. + if (retransmittable_on_wire_timeout_.IsZero()) { + retransmittable_on_wire_timeout_ = quic::QuicTime::Delta::FromMicroseconds( + kDefaultRetransmittableOnWireTimeout.InMicroseconds()); + } + + // Enable retry on alternate network before handshake. + if (retry_on_alternate_network_before_handshake) + params_.retry_on_alternate_network_before_handshake = true; + + // Enable migration for idle sessions. + if (migrate_idle_sessions) + params_.migrate_idle_sessions = true; +} + void QuicStreamFactory::InitializeCachedStateInCryptoConfig( const CryptoClientConfigHandle& crypto_config_handle, const quic::QuicServerId& server_id, @@ -2372,4 +2347,25 @@ net_log); } +bool QuicStreamFactory::CryptoConfigCacheIsEmptyForTesting( + const quic::QuicServerId& server_id, + const NetworkIsolationKey& network_isolation_key) { + quic::QuicCryptoClientConfig::CachedState* cached = nullptr; + NetworkIsolationKey actual_network_isolation_key = + use_network_isolation_key_for_crypto_configs_ ? network_isolation_key + : NetworkIsolationKey(); + auto map_iterator = + active_crypto_config_map_.find(actual_network_isolation_key); + if (map_iterator != active_crypto_config_map_.end()) { + cached = map_iterator->second->config()->LookupOrCreate(server_id); + } else { + auto mru_iterator = + recent_crypto_config_map_.Peek(actual_network_isolation_key); + if (mru_iterator != recent_crypto_config_map_.end()) { + cached = mru_iterator->second->config()->LookupOrCreate(server_id); + } + } + return !cached || cached->IsEmpty(); +} + } // namespace net
diff --git a/net/quic/quic_stream_factory.h b/net/quic/quic_stream_factory.h index 19bab90..58425c8 100644 --- a/net/quic/quic_stream_factory.h +++ b/net/quic/quic_stream_factory.h
@@ -566,10 +566,6 @@ // Helper methods. bool WasQuicRecentlyBroken(const QuicSessionKey& session_key) const; - bool CryptoConfigCacheIsEmpty( - const quic::QuicServerId& server_id, - const NetworkIsolationKey& network_isolation_key); - // Starts an asynchronous job for cert verification if // |params_.race_cert_verification| is enabled and if there are cached certs // for the given |server_id|. @@ -630,6 +626,10 @@ int cert_verify_flags, const NetLogWithSource& net_log); + bool CryptoConfigCacheIsEmptyForTesting( + const quic::QuicServerId& server_id, + const NetworkIsolationKey& network_isolation_key); + // Whether QUIC is known to work on current network. This is true when QUIC is // expected to work in general, rather than whether QUIC was broken / recently // broken when used with a particular server. That information is stored in
diff --git a/net/quic/quic_stream_factory_peer.cc b/net/quic/quic_stream_factory_peer.cc index 4c42c16..0d0eb90 100644 --- a/net/quic/quic_stream_factory_peer.cc +++ b/net/quic/quic_stream_factory_peer.cc
@@ -152,8 +152,8 @@ QuicStreamFactory* factory, const quic::QuicServerId& quic_server_id, const NetworkIsolationKey& network_isolation_key) { - return factory->CryptoConfigCacheIsEmpty(quic_server_id, - network_isolation_key); + return factory->CryptoConfigCacheIsEmptyForTesting(quic_server_id, + network_isolation_key); } void QuicStreamFactoryPeer::CacheDummyServerConfig(
diff --git a/net/quic/quic_test_packet_maker.cc b/net/quic/quic_test_packet_maker.cc index 96a9bc3..8ab3faa 100644 --- a/net/quic/quic_test_packet_maker.cc +++ b/net/quic/quic_test_packet_maker.cc
@@ -356,9 +356,11 @@ // Send SETTINGS frame(s) if they have not already been sent. MaybeAddHttp3SettingsFrames(&frames); - std::string priority_data = GenerateHttp3PriorityData(priority, stream_id); - - frames.push_back(GenerateNextStreamFrame(2, false, priority_data)); + if (FLAGS_quic_allow_http3_priority) { + std::string priority_data = + GenerateHttp3PriorityData(priority, stream_id); + frames.push_back(GenerateNextStreamFrame(2, false, priority_data)); + } // STREAM frames for HEADERS. std::vector<std::string> data = QpackEncodeHeaders( @@ -753,9 +755,11 @@ // Send SETTINGS frame(s) if they have not already been sent. MaybeAddHttp3SettingsFrames(&frames); - std::string priority_data = GenerateHttp3PriorityData(priority, stream_id); - frames.push_back(GenerateNextStreamFrame(2, false, priority_data)); - + if (FLAGS_quic_allow_http3_priority) { + std::string priority_data = + GenerateHttp3PriorityData(priority, stream_id); + frames.push_back(GenerateNextStreamFrame(2, false, priority_data)); + } // STREAM frames for HEADERS. std::vector<std::string> data = QpackEncodeHeaders( stream_id, std::move(headers), spdy_headers_frame_length); @@ -814,9 +818,11 @@ // Send SETTINGS frame(s) if they have not already been sent. MaybeAddHttp3SettingsFrames(&frames); - std::string priority_data = GenerateHttp3PriorityData(priority, stream_id); - frames.push_back(GenerateNextStreamFrame(2, false, priority_data)); - + if (FLAGS_quic_allow_http3_priority) { + std::string priority_data = + GenerateHttp3PriorityData(priority, stream_id); + frames.push_back(GenerateNextStreamFrame(2, false, priority_data)); + } std::vector<std::string> data = QpackEncodeHeaders( stream_id, std::move(headers), spdy_headers_frame_length); @@ -854,9 +860,11 @@ // Send SETTINGS frame(s) if they have not already been sent. MaybeAddHttp3SettingsFrames(&frames); - std::string priority_data = GenerateHttp3PriorityData(priority, stream_id); - frames.push_back(GenerateNextStreamFrame(2, false, priority_data)); - + if (FLAGS_quic_allow_http3_priority) { + std::string priority_data = + GenerateHttp3PriorityData(priority, stream_id); + frames.push_back(GenerateNextStreamFrame(2, false, priority_data)); + } std::vector<std::string> data = QpackEncodeHeaders( stream_id, std::move(headers), spdy_headers_frame_length);
diff --git a/net/test/cert_builder.cc b/net/test/cert_builder.cc new file mode 100644 index 0000000..1f3158cf --- /dev/null +++ b/net/test/cert_builder.cc
@@ -0,0 +1,671 @@ +// Copyright 2019 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#include "net/test/cert_builder.h" + +#include "base/files/file_path.h" +#include "base/strings/string_number_conversions.h" +#include "crypto/openssl_util.h" +#include "crypto/rsa_private_key.h" +#include "net/cert/internal/parse_certificate.h" +#include "net/cert/x509_util.h" +#include "net/der/encode_values.h" +#include "net/der/input.h" +#include "net/der/parse_values.h" +#include "net/der/parser.h" +#include "net/test/cert_test_util.h" +#include "net/test/test_data_directory.h" +#include "testing/gtest/include/gtest/gtest.h" +#include "third_party/boringssl/src/include/openssl/evp.h" +#include "third_party/boringssl/src/include/openssl/mem.h" +#include "url/gurl.h" + +namespace net { + +namespace { + +std::string MakeRandomHexString(size_t num_bytes) { + std::vector<char> rand_bytes; + rand_bytes.resize(num_bytes); + + base::RandBytes(&rand_bytes[0], rand_bytes.size()); + return base::HexEncode(&rand_bytes[0], rand_bytes.size()); +} + +std::string Sha256WithRSAEncryption() { + const uint8_t kSha256WithRSAEncryption[] = {0x30, 0x0D, 0x06, 0x09, 0x2a, + 0x86, 0x48, 0x86, 0xf7, 0x0d, + 0x01, 0x01, 0x0b, 0x05, 0x00}; + return std::string(std::begin(kSha256WithRSAEncryption), + std::end(kSha256WithRSAEncryption)); +} + +std::string Sha1WithRSAEncryption() { + const uint8_t kSha1WithRSAEncryption[] = {0x30, 0x0D, 0x06, 0x09, 0x2a, + 0x86, 0x48, 0x86, 0xf7, 0x0d, + 0x01, 0x01, 0x05, 0x05, 0x00}; + return std::string(std::begin(kSha1WithRSAEncryption), + std::end(kSha1WithRSAEncryption)); +} + +std::string Md5WithRSAEncryption() { + const uint8_t kMd5WithRSAEncryption[] = {0x30, 0x0d, 0x06, 0x09, 0x2a, + 0x86, 0x48, 0x86, 0xf7, 0x0d, + 0x01, 0x01, 0x04, 0x05, 0x00}; + return std::string(std::begin(kMd5WithRSAEncryption), + std::end(kMd5WithRSAEncryption)); +} + +// Adds bytes (specified as a StringPiece) to the given CBB. +// The argument ordering follows the boringssl CBB_* api style. +bool CBBAddBytes(CBB* cbb, base::StringPiece bytes) { + return CBB_add_bytes(cbb, reinterpret_cast<const uint8_t*>(bytes.data()), + bytes.size()); +} + +// Adds bytes (from fixed size array) to the given CBB. +// The argument ordering follows the boringssl CBB_* api style. +template <size_t N> +bool CBBAddBytes(CBB* cbb, const uint8_t (&data)[N]) { + return CBB_add_bytes(cbb, data, N); +} + +// Adds a RFC 5280 Time value to the given CBB. +// The argument ordering follows the boringssl CBB_* api style. +bool CBBAddTime(CBB* cbb, const base::Time& time) { + der::GeneralizedTime generalized_time; + if (!der::EncodeTimeAsGeneralizedTime(time, &generalized_time)) + return false; + CBB time_cbb; + if (generalized_time.year < 2050) { + uint8_t out[der::kUTCTimeLength]; + if (!der::EncodeUTCTime(generalized_time, out) || + !CBB_add_asn1(cbb, &time_cbb, CBS_ASN1_UTCTIME) || + !CBBAddBytes(&time_cbb, out) || !CBB_flush(cbb)) + return false; + } else { + uint8_t out[der::kGeneralizedTimeLength]; + if (!der::EncodeGeneralizedTime(generalized_time, out) || + !CBB_add_asn1(cbb, &time_cbb, CBS_ASN1_GENERALIZEDTIME) || + !CBBAddBytes(&time_cbb, out) || !CBB_flush(cbb)) + return false; + } + return true; +} + +// Finalizes the CBB to a std::string. +std::string FinishCBB(CBB* cbb) { + size_t cbb_len; + uint8_t* cbb_bytes; + + if (!CBB_finish(cbb, &cbb_bytes, &cbb_len)) { + ADD_FAILURE() << "CBB_finish() failed"; + return std::string(); + } + + bssl::UniquePtr<uint8_t> delete_bytes(cbb_bytes); + return std::string(reinterpret_cast<char*>(cbb_bytes), cbb_len); +} + +} // namespace + +CertBuilder::CertBuilder(CRYPTO_BUFFER* orig_cert, CertBuilder* issuer) + : issuer_(issuer) { + if (!issuer_) + issuer_ = this; + + crypto::EnsureOpenSSLInit(); + InitFromCert(der::Input(x509_util::CryptoBufferAsStringPiece(orig_cert))); +} + +CertBuilder::~CertBuilder() = default; + +// static +void CertBuilder::CreateSimpleChain( + std::unique_ptr<CertBuilder>* out_leaf, + std::unique_ptr<CertBuilder>* out_intermediate, + std::unique_ptr<CertBuilder>* out_root) { + const char kHostname[] = "www.example.com"; + base::FilePath certs_dir = + GetTestNetDataDirectory() + .AppendASCII("verify_certificate_chain_unittest") + .AppendASCII("target-and-intermediate"); + + CertificateList orig_certs = CreateCertificateListFromFile( + certs_dir, "chain.pem", X509Certificate::FORMAT_AUTO); + ASSERT_EQ(3U, orig_certs.size()); + + // Build slightly modified variants of |orig_certs|. + *out_root = + std::make_unique<CertBuilder>(orig_certs[2]->cert_buffer(), nullptr); + *out_intermediate = std::make_unique<CertBuilder>( + orig_certs[1]->cert_buffer(), out_root->get()); + (*out_intermediate)->EraseExtension(CrlDistributionPointsOid()); + (*out_intermediate)->EraseExtension(AuthorityInfoAccessOid()); + *out_leaf = std::make_unique<CertBuilder>(orig_certs[0]->cert_buffer(), + out_intermediate->get()); + (*out_leaf)->SetSubjectAltName(kHostname); + (*out_leaf)->EraseExtension(CrlDistributionPointsOid()); + (*out_leaf)->EraseExtension(AuthorityInfoAccessOid()); +} + +void CertBuilder::SetExtension(const der::Input& oid, + std::string value, + bool critical) { + auto& extension_value = extensions_[oid.AsString()]; + extension_value.critical = critical; + extension_value.value = std::move(value); + + Invalidate(); +} + +void CertBuilder::EraseExtension(const der::Input& oid) { + extensions_.erase(oid.AsString()); + + Invalidate(); +} + +void CertBuilder::SetCaIssuersUrl(const GURL& url) { + std::string url_spec = url.spec(); + + // From RFC 5280: + // + // AuthorityInfoAccessSyntax ::= + // SEQUENCE SIZE (1..MAX) OF AccessDescription + // + // AccessDescription ::= SEQUENCE { + // accessMethod OBJECT IDENTIFIER, + // accessLocation GeneralName } + bssl::ScopedCBB cbb; + CBB aia, ca_issuer, access_method, access_location; + ASSERT_TRUE(CBB_init(cbb.get(), url_spec.size())); + ASSERT_TRUE(CBB_add_asn1(cbb.get(), &aia, CBS_ASN1_SEQUENCE)); + ASSERT_TRUE(CBB_add_asn1(&aia, &ca_issuer, CBS_ASN1_SEQUENCE)); + ASSERT_TRUE(CBB_add_asn1(&ca_issuer, &access_method, CBS_ASN1_OBJECT)); + ASSERT_TRUE(CBBAddBytes(&access_method, AdCaIssuersOid().AsStringPiece())); + ASSERT_TRUE(CBB_add_asn1(&ca_issuer, &access_location, + CBS_ASN1_CONTEXT_SPECIFIC | 6)); + ASSERT_TRUE(CBBAddBytes(&access_location, url_spec)); + + SetExtension(AuthorityInfoAccessOid(), FinishCBB(cbb.get())); +} + +void CertBuilder::SetCrlDistributionPointUrl(const GURL& url) { + std::string url_spec = url.spec(); + + bssl::ScopedCBB cbb; + ASSERT_TRUE(CBB_init(cbb.get(), url_spec.size())); + CBB dps, dp, dp_name, dp_fullname, dp_url; + + // CRLDistributionPoints ::= SEQUENCE SIZE (1..MAX) OF DistributionPoint + ASSERT_TRUE(CBB_add_asn1(cbb.get(), &dps, CBS_ASN1_SEQUENCE)); + + // DistributionPoint ::= SEQUENCE { + // distributionPoint [0] DistributionPointName OPTIONAL, + // reasons [1] ReasonFlags OPTIONAL, + // cRLIssuer [2] GeneralNames OPTIONAL } + ASSERT_TRUE(CBB_add_asn1(&dps, &dp, CBS_ASN1_SEQUENCE)); + ASSERT_TRUE(CBB_add_asn1( + &dp, &dp_name, CBS_ASN1_CONTEXT_SPECIFIC | CBS_ASN1_CONSTRUCTED | 0)); + + // DistributionPointName ::= CHOICE { + // fullName [0] GeneralNames, + // nameRelativeToCRLIssuer [1] RelativeDistinguishedName } + ASSERT_TRUE( + CBB_add_asn1(&dp_name, &dp_fullname, + CBS_ASN1_CONTEXT_SPECIFIC | CBS_ASN1_CONSTRUCTED | 0)); + + // GeneralNames ::= SEQUENCE SIZE (1..MAX) OF GeneralName + // GeneralName ::= CHOICE { + // uniformResourceIdentifier [6] IA5String, + ASSERT_TRUE( + CBB_add_asn1(&dp_fullname, &dp_url, CBS_ASN1_CONTEXT_SPECIFIC | 6)); + ASSERT_TRUE(CBBAddBytes(&dp_url, url_spec)); + + SetExtension(CrlDistributionPointsOid(), FinishCBB(cbb.get())); +} + +void CertBuilder::SetSubjectCommonName(const std::string common_name) { + // See RFC 4519. + static const uint8_t kCommonName[] = {0x55, 0x04, 0x03}; + + // See RFC 5280, section 4.1.2.4. + bssl::ScopedCBB cbb; + CBB rdns, rdn, attr, type, value; + ASSERT_TRUE(CBB_init(cbb.get(), 64)); + ASSERT_TRUE(CBB_add_asn1(cbb.get(), &rdns, CBS_ASN1_SEQUENCE)); + ASSERT_TRUE(CBB_add_asn1(&rdns, &rdn, CBS_ASN1_SET)); + ASSERT_TRUE(CBB_add_asn1(&rdn, &attr, CBS_ASN1_SEQUENCE)); + ASSERT_TRUE(CBB_add_asn1(&attr, &type, CBS_ASN1_OBJECT)); + ASSERT_TRUE(CBBAddBytes(&type, kCommonName)); + ASSERT_TRUE(CBB_add_asn1(&attr, &value, CBS_ASN1_UTF8STRING)); + ASSERT_TRUE(CBBAddBytes(&value, common_name)); + + subject_tlv_ = FinishCBB(cbb.get()); +} + +void CertBuilder::SetSubjectAltName(const std::string& dns_name) { + // From RFC 5280: + // + // SubjectAltName ::= GeneralNames + // + // GeneralNames ::= SEQUENCE SIZE (1..MAX) OF GeneralName + // + // GeneralName ::= CHOICE { + // otherName [0] OtherName, + // rfc822Name [1] IA5String, + // dNSName [2] IA5String, + // ... } + bssl::ScopedCBB cbb; + CBB general_names, general_name; + ASSERT_TRUE(CBB_init(cbb.get(), dns_name.size())); + ASSERT_TRUE(CBB_add_asn1(cbb.get(), &general_names, CBS_ASN1_SEQUENCE)); + ASSERT_TRUE(CBB_add_asn1(&general_names, &general_name, + CBS_ASN1_CONTEXT_SPECIFIC | 2)); + ASSERT_TRUE(CBBAddBytes(&general_name, dns_name)); + + SetExtension(SubjectAltNameOid(), FinishCBB(cbb.get())); +} + +void CertBuilder::SetSignatureAlgorithmRsaPkca1(DigestAlgorithm digest) { + switch (digest) { + case DigestAlgorithm::Sha256: { + SetSignatureAlgorithm(Sha256WithRSAEncryption()); + break; + } + + case DigestAlgorithm::Sha1: { + SetSignatureAlgorithm(Sha1WithRSAEncryption()); + break; + } + + default: + ASSERT_TRUE(false); + } +} + +void CertBuilder::SetSignatureAlgorithm(std::string algorithm_tlv) { + signature_algorithm_tlv_ = std::move(algorithm_tlv); + Invalidate(); +} + +void CertBuilder::SetRandomSerialNumber() { + serial_number_ = base::RandUint64(); + Invalidate(); +} + +CRYPTO_BUFFER* CertBuilder::GetCertBuffer() { + if (!cert_) + GenerateCertificate(); + return cert_.get(); +} + +bssl::UniquePtr<CRYPTO_BUFFER> CertBuilder::DupCertBuffer() { + return bssl::UpRef(GetCertBuffer()); +} + +const std::string& CertBuilder::GetSubject() { + if (subject_tlv_.empty()) + GenerateSubject(); + return subject_tlv_; +} + +uint64_t CertBuilder::GetSerialNumber() { + if (!serial_number_) + serial_number_ = base::RandUint64(); + return serial_number_; +} + +EVP_PKEY* CertBuilder::GetKey() { + if (!key_) + GenerateKey(); + return key_.get(); +} + +scoped_refptr<X509Certificate> CertBuilder::GetX509Certificate() { + return X509Certificate::CreateFromBuffer(DupCertBuffer(), {}); +} + +scoped_refptr<X509Certificate> CertBuilder::GetX509CertificateChain() { + std::vector<bssl::UniquePtr<CRYPTO_BUFFER>> intermediates; + // Add intermediates, not including the self-signed root. + for (CertBuilder* cert = issuer_; cert && cert != cert->issuer_; + cert = cert->issuer_) { + intermediates.push_back(cert->DupCertBuffer()); + } + return X509Certificate::CreateFromBuffer(DupCertBuffer(), + std::move(intermediates)); +} + +std::string CertBuilder::GetDER() { + return x509_util::CryptoBufferAsStringPiece(GetCertBuffer()).as_string(); +} + +// static +std::string CertBuilder::CreateCrl(CertBuilder* crl_issuer, + const std::vector<uint64_t>& revoked_serials, + DigestAlgorithm digest) { + std::string signature_algorithm; + const EVP_MD* md = nullptr; + switch (digest) { + case DigestAlgorithm::Sha256: { + signature_algorithm = Sha256WithRSAEncryption(); + md = EVP_sha256(); + break; + } + + case DigestAlgorithm::Sha1: { + signature_algorithm = Sha1WithRSAEncryption(); + md = EVP_sha1(); + break; + } + + case DigestAlgorithm::Md5: { + signature_algorithm = Md5WithRSAEncryption(); + md = EVP_md5(); + break; + } + + default: + ADD_FAILURE(); + return std::string(); + } + // TBSCertList ::= SEQUENCE { + // version Version OPTIONAL, + // -- if present, MUST be v2 + // signature AlgorithmIdentifier, + // issuer Name, + // thisUpdate Time, + // nextUpdate Time OPTIONAL, + // revokedCertificates SEQUENCE OF SEQUENCE { + // userCertificate CertificateSerialNumber, + // revocationDate Time, + // crlEntryExtensions Extensions OPTIONAL + // -- if present, version MUST be v2 + // } OPTIONAL, + // crlExtensions [0] EXPLICIT Extensions OPTIONAL + // -- if present, version MUST be v2 + // } + bssl::ScopedCBB tbs_cbb; + CBB tbs_cert_list, revoked_serials_cbb; + if (!CBB_init(tbs_cbb.get(), 10) || + !CBB_add_asn1(tbs_cbb.get(), &tbs_cert_list, CBS_ASN1_SEQUENCE) || + !CBB_add_asn1_uint64(&tbs_cert_list, 1 /* V2 */) || + !CBBAddBytes(&tbs_cert_list, signature_algorithm) || + !CBBAddBytes(&tbs_cert_list, crl_issuer->GetSubject()) || + !CBBAddTime(&tbs_cert_list, + base::Time::Now() - base::TimeDelta::FromDays(1)) || + !CBBAddTime(&tbs_cert_list, + base::Time::Now() + base::TimeDelta::FromDays(6))) { + ADD_FAILURE(); + return std::string(); + } + if (!revoked_serials.empty()) { + if (!CBB_add_asn1(&tbs_cert_list, &revoked_serials_cbb, + CBS_ASN1_SEQUENCE)) { + ADD_FAILURE(); + return std::string(); + } + for (const int64_t revoked_serial : revoked_serials) { + CBB revoked_serial_cbb; + if (!CBB_add_asn1(&revoked_serials_cbb, &revoked_serial_cbb, + CBS_ASN1_SEQUENCE) || + !CBB_add_asn1_uint64(&revoked_serial_cbb, revoked_serial) || + !CBBAddTime(&revoked_serial_cbb, + base::Time::Now() - base::TimeDelta::FromDays(1)) || + !CBB_flush(&revoked_serials_cbb)) { + ADD_FAILURE(); + return std::string(); + } + } + } + + std::string tbs_tlv = FinishCBB(tbs_cbb.get()); + + // CertificateList ::= SEQUENCE { + // tbsCertList TBSCertList, + // signatureAlgorithm AlgorithmIdentifier, + // signatureValue BIT STRING } + bssl::ScopedCBB crl_cbb; + CBB cert_list, signature; + bssl::ScopedEVP_MD_CTX ctx; + uint8_t* sig_out; + size_t sig_len; + if (!CBB_init(crl_cbb.get(), 10) || + !CBB_add_asn1(crl_cbb.get(), &cert_list, CBS_ASN1_SEQUENCE) || + !CBBAddBytes(&cert_list, tbs_tlv) || + !CBBAddBytes(&cert_list, signature_algorithm) || + !CBB_add_asn1(&cert_list, &signature, CBS_ASN1_BITSTRING) || + !CBB_add_u8(&signature, 0 /* no unused bits */) || + !EVP_DigestSignInit(ctx.get(), nullptr, md, nullptr, + crl_issuer->GetKey()) || + !EVP_DigestSign(ctx.get(), nullptr, &sig_len, + reinterpret_cast<const uint8_t*>(tbs_tlv.data()), + tbs_tlv.size()) || + !CBB_reserve(&signature, &sig_out, sig_len) || + !EVP_DigestSign(ctx.get(), sig_out, &sig_len, + reinterpret_cast<const uint8_t*>(tbs_tlv.data()), + tbs_tlv.size()) || + !CBB_did_write(&signature, sig_len)) { + ADD_FAILURE(); + return std::string(); + } + return FinishCBB(crl_cbb.get()); +} + +void CertBuilder::Invalidate() { + cert_.reset(); +} + +void CertBuilder::GenerateKey() { + ASSERT_FALSE(key_); + + auto private_key = crypto::RSAPrivateKey::Create(2048); + key_ = bssl::UpRef(private_key->key()); +} + +void CertBuilder::GenerateSubject() { + ASSERT_TRUE(subject_tlv_.empty()); + + // Use a random common name comprised of 12 bytes in hex. + std::string common_name = MakeRandomHexString(12); + + SetSubjectCommonName(common_name); +} + +void CertBuilder::InitFromCert(const der::Input& cert) { + extensions_.clear(); + Invalidate(); + + // From RFC 5280, section 4.1 + // Certificate ::= SEQUENCE { + // tbsCertificate TBSCertificate, + // signatureAlgorithm AlgorithmIdentifier, + // signatureValue BIT STRING } + + // TBSCertificate ::= SEQUENCE { + // version [0] EXPLICIT Version DEFAULT v1, + // serialNumber CertificateSerialNumber, + // signature AlgorithmIdentifier, + // issuer Name, + // validity Validity, + // subject Name, + // subjectPublicKeyInfo SubjectPublicKeyInfo, + // issuerUniqueID [1] IMPLICIT UniqueIdentifier OPTIONAL, + // -- If present, version MUST be v2 or v3 + // subjectUniqueID [2] IMPLICIT UniqueIdentifier OPTIONAL, + // -- If present, version MUST be v2 or v3 + // extensions [3] EXPLICIT Extensions OPTIONAL + // -- If present, version MUST be v3 + // } + der::Parser parser(cert); + der::Parser certificate; + der::Parser tbs_certificate; + ASSERT_TRUE(parser.ReadSequence(&certificate)); + ASSERT_TRUE(certificate.ReadSequence(&tbs_certificate)); + + // version + bool unused; + ASSERT_TRUE(tbs_certificate.SkipOptionalTag( + der::kTagConstructed | der::kTagContextSpecific | 0, &unused)); + // serialNumber + ASSERT_TRUE(tbs_certificate.SkipTag(der::kInteger)); + + // signature + der::Input signature_algorithm_tlv; + ASSERT_TRUE(tbs_certificate.ReadRawTLV(&signature_algorithm_tlv)); + signature_algorithm_tlv_ = signature_algorithm_tlv.AsString(); + + // issuer + ASSERT_TRUE(tbs_certificate.SkipTag(der::kSequence)); + + // validity + der::Input validity_tlv; + ASSERT_TRUE(tbs_certificate.ReadRawTLV(&validity_tlv)); + validity_tlv_ = validity_tlv.AsString(); + + // subject + ASSERT_TRUE(tbs_certificate.SkipTag(der::kSequence)); + // subjectPublicKeyInfo + ASSERT_TRUE(tbs_certificate.SkipTag(der::kSequence)); + // issuerUniqueID + ASSERT_TRUE(tbs_certificate.SkipOptionalTag(der::ContextSpecificPrimitive(1), + &unused)); + // subjectUniqueID + ASSERT_TRUE(tbs_certificate.SkipOptionalTag(der::ContextSpecificPrimitive(2), + &unused)); + + // extensions + bool has_extensions = false; + der::Input extensions_tlv; + ASSERT_TRUE(tbs_certificate.ReadOptionalTag( + der::ContextSpecificConstructed(3), &extensions_tlv, &has_extensions)); + if (has_extensions) { + std::map<der::Input, ParsedExtension> parsed_extensions; + ASSERT_TRUE(ParseExtensions(extensions_tlv, &parsed_extensions)); + + for (const auto& parsed_extension : parsed_extensions) { + SetExtension(parsed_extension.second.oid, + parsed_extension.second.value.AsString(), + parsed_extension.second.critical); + } + } +} + +void CertBuilder::BuildTBSCertificate(std::string* out) { + bssl::ScopedCBB cbb; + CBB tbs_cert, version, extensions_context, extensions; + + ASSERT_TRUE(CBB_init(cbb.get(), 64)); + ASSERT_TRUE(CBB_add_asn1(cbb.get(), &tbs_cert, CBS_ASN1_SEQUENCE)); + ASSERT_TRUE( + CBB_add_asn1(&tbs_cert, &version, + CBS_ASN1_CONTEXT_SPECIFIC | CBS_ASN1_CONSTRUCTED | 0)); + // Always use v3 certificates. + ASSERT_TRUE(CBB_add_asn1_uint64(&version, 2)); + ASSERT_TRUE(CBB_add_asn1_uint64(&tbs_cert, GetSerialNumber())); + ASSERT_TRUE(AddSignatureAlgorithm(&tbs_cert)); + ASSERT_TRUE(CBBAddBytes(&tbs_cert, issuer_->GetSubject())); + ASSERT_TRUE(CBBAddBytes(&tbs_cert, validity_tlv_)); + ASSERT_TRUE(CBBAddBytes(&tbs_cert, GetSubject())); + ASSERT_TRUE(EVP_marshal_public_key(&tbs_cert, GetKey())); + + // Serialize all the extensions. + if (!extensions_.empty()) { + ASSERT_TRUE( + CBB_add_asn1(&tbs_cert, &extensions_context, + CBS_ASN1_CONTEXT_SPECIFIC | CBS_ASN1_CONSTRUCTED | 3)); + ASSERT_TRUE( + CBB_add_asn1(&extensions_context, &extensions, CBS_ASN1_SEQUENCE)); + + // Extension ::= SEQUENCE { + // extnID OBJECT IDENTIFIER, + // critical BOOLEAN DEFAULT FALSE, + // extnValue OCTET STRING + // -- contains the DER encoding of an ASN.1 value + // -- corresponding to the extension type identified + // -- by extnID + // } + for (const auto& extension_it : extensions_) { + CBB extension_seq, oid, extn_value; + ASSERT_TRUE(CBB_add_asn1(&extensions, &extension_seq, CBS_ASN1_SEQUENCE)); + ASSERT_TRUE(CBB_add_asn1(&extension_seq, &oid, CBS_ASN1_OBJECT)); + ASSERT_TRUE(CBBAddBytes(&oid, extension_it.first)); + if (extension_it.second.critical) { + ASSERT_TRUE(CBB_add_asn1_bool(&extension_seq, true)); + } + + ASSERT_TRUE( + CBB_add_asn1(&extension_seq, &extn_value, CBS_ASN1_OCTETSTRING)); + ASSERT_TRUE(CBBAddBytes(&extn_value, extension_it.second.value)); + ASSERT_TRUE(CBB_flush(&extensions)); + } + } + + *out = FinishCBB(cbb.get()); +} + +bool CertBuilder::AddSignatureAlgorithm(CBB* cbb) { + return CBBAddBytes(cbb, signature_algorithm_tlv_); +} + +void CertBuilder::GenerateCertificate() { + ASSERT_FALSE(cert_); + + std::string tbs_cert; + BuildTBSCertificate(&tbs_cert); + const uint8_t* tbs_cert_bytes = + reinterpret_cast<const uint8_t*>(tbs_cert.data()); + + // Determine the correct digest algorithm to use (assumes RSA PKCS#1 + // signatures). + auto signature_algorithm = SignatureAlgorithm::Create( + der::Input(&signature_algorithm_tlv_), nullptr); + ASSERT_TRUE(signature_algorithm); + ASSERT_EQ(SignatureAlgorithmId::RsaPkcs1, signature_algorithm->algorithm()); + const EVP_MD* md = nullptr; + + switch (signature_algorithm->digest()) { + case DigestAlgorithm::Sha256: + md = EVP_sha256(); + break; + + case DigestAlgorithm::Sha1: + md = EVP_sha1(); + break; + + default: + ASSERT_TRUE(false) << "Only rsaEncryptionWithSha256 or " + "rsaEnryptionWithSha1 are supported"; + break; + } + + // Sign the TBSCertificate and write the entire certificate. + bssl::ScopedCBB cbb; + CBB cert, signature; + bssl::ScopedEVP_MD_CTX ctx; + uint8_t* sig_out; + size_t sig_len; + + ASSERT_TRUE(CBB_init(cbb.get(), tbs_cert.size())); + ASSERT_TRUE(CBB_add_asn1(cbb.get(), &cert, CBS_ASN1_SEQUENCE)); + ASSERT_TRUE(CBBAddBytes(&cert, tbs_cert)); + ASSERT_TRUE(AddSignatureAlgorithm(&cert)); + ASSERT_TRUE(CBB_add_asn1(&cert, &signature, CBS_ASN1_BITSTRING)); + ASSERT_TRUE(CBB_add_u8(&signature, 0 /* no unused bits */)); + ASSERT_TRUE( + EVP_DigestSignInit(ctx.get(), nullptr, md, nullptr, issuer_->GetKey())); + ASSERT_TRUE(EVP_DigestSign(ctx.get(), nullptr, &sig_len, tbs_cert_bytes, + tbs_cert.size())); + ASSERT_TRUE(CBB_reserve(&signature, &sig_out, sig_len)); + ASSERT_TRUE(EVP_DigestSign(ctx.get(), sig_out, &sig_len, tbs_cert_bytes, + tbs_cert.size())); + ASSERT_TRUE(CBB_did_write(&signature, sig_len)); + + auto cert_der = FinishCBB(cbb.get()); + cert_ = x509_util::CreateCryptoBuffer( + reinterpret_cast<const uint8_t*>(cert_der.data()), cert_der.size()); +} + +} // namespace net
diff --git a/net/test/cert_builder.h b/net/test/cert_builder.h new file mode 100644 index 0000000..8660e73 --- /dev/null +++ b/net/test/cert_builder.h
@@ -0,0 +1,148 @@ +// Copyright 2019 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#ifndef NET_TEST_CERT_BUILDER_H_ +#define NET_TEST_CERT_BUILDER_H_ + +#include "base/rand_util.h" +#include "net/cert/internal/signature_algorithm.h" +#include "net/cert/x509_certificate.h" +#include "third_party/boringssl/src/include/openssl/base.h" +#include "third_party/boringssl/src/include/openssl/bytestring.h" +#include "third_party/boringssl/src/include/openssl/pool.h" + +class GURL; + +namespace net { + +namespace der { +class Input; +} + +// CertBuilder is a helper class to dynamically create a test certificate. +// +// CertBuilder is initialized using an existing certificate, from which it +// copies most properties (see InitFromCert for details). +// +// The subject, serial number, and key for the final certificate are chosen +// randomly. Using a randomized subject and serial number is important to defeat +// certificate caching done by NSS, which otherwise can make test outcomes +// dependent on ordering. +class CertBuilder { + public: + // Initializes the CertBuilder using |orig_cert|. If |issuer| is null + // then the generated certificate will be self-signed. Otherwise, it + // will be signed using |issuer|. + CertBuilder(CRYPTO_BUFFER* orig_cert, CertBuilder* issuer); + ~CertBuilder(); + + // Creates a simple leaf->intermediate->root chain of CertBuilders with no AIA + // or CrlDistributionPoint extensions, and leaf having a subjectAltName of + // www.example.com. + static void CreateSimpleChain(std::unique_ptr<CertBuilder>* out_leaf, + std::unique_ptr<CertBuilder>* out_intermediate, + std::unique_ptr<CertBuilder>* out_root); + + // Sets a value for the indicated X.509 (v3) extension. + void SetExtension(const der::Input& oid, + std::string value, + bool critical = false); + + // Removes an extension (if present). + void EraseExtension(const der::Input& oid); + + // Sets an AIA extension with a single caIssuers access method. + void SetCaIssuersUrl(const GURL& url); + + void SetCrlDistributionPointUrl(const GURL& url); + + void SetSubjectCommonName(const std::string common_name); + + // Sets the SAN for the certificate to a single dNSName. + void SetSubjectAltName(const std::string& dns_name); + + // Sets the signature algorithm for the certificate to either + // sha256WithRSAEncryption or sha1WithRSAEncryption. + void SetSignatureAlgorithmRsaPkca1(DigestAlgorithm digest); + + void SetSignatureAlgorithm(std::string algorithm_tlv); + + void SetRandomSerialNumber(); + + // Returns a CRYPTO_BUFFER to the generated certificate. + CRYPTO_BUFFER* GetCertBuffer(); + + bssl::UniquePtr<CRYPTO_BUFFER> DupCertBuffer(); + + // Returns the subject of the generated certificate. + const std::string& GetSubject(); + + // Returns the serial number for the generated certificate. + uint64_t GetSerialNumber(); + + // Returns the (RSA) key for the generated certificate. + EVP_PKEY* GetKey(); + + // Returns an X509Certificate for the generated certificate. + scoped_refptr<X509Certificate> GetX509Certificate(); + + // Returns an X509Certificate for the generated certificate, including + // intermediate certificates. + scoped_refptr<X509Certificate> GetX509CertificateChain(); + + // Returns a copy of the certificate's DER. + std::string GetDER(); + + // Creates a CRL issued and signed by |crl_issuer|, marking |revoked_serials| + // as revoked. + // Returns the DER-encoded CRL. + static std::string CreateCrl(CertBuilder* crl_issuer, + const std::vector<uint64_t>& revoked_serials, + DigestAlgorithm digest); + + private: + // Marks the generated certificate DER as invalid, so it will need to + // be re-generated next time the DER is accessed. + void Invalidate(); + + // Sets the |key_| to a 2048-bit RSA key. + void GenerateKey(); + + // Generates a random subject for the certificate, comprised of just a CN. + void GenerateSubject(); + + // Parses |cert| and copies the following properties: + // * All extensions (dropping any duplicates) + // * Signature algorithm (from Certificate) + // * Validity (expiration) + void InitFromCert(const der::Input& cert); + + // Assembles the CertBuilder into a TBSCertificate. + void BuildTBSCertificate(std::string* out); + + bool AddSignatureAlgorithm(CBB* cbb); + + void GenerateCertificate(); + + struct ExtensionValue { + bool critical = false; + std::string value; + }; + + std::string validity_tlv_; + std::string subject_tlv_; + std::string signature_algorithm_tlv_; + uint64_t serial_number_ = 0; + + std::map<std::string, ExtensionValue> extensions_; + + bssl::UniquePtr<CRYPTO_BUFFER> cert_; + bssl::UniquePtr<EVP_PKEY> key_; + + CertBuilder* issuer_ = nullptr; +}; + +} // namespace net + +#endif // NET_TEST_CERT_BUILDER_H_
diff --git a/net/tools/quic/quic_simple_server.cc b/net/tools/quic/quic_simple_server.cc index 3ea79e4..da14e4f 100644 --- a/net/tools/quic/quic_simple_server.cc +++ b/net/tools/quic/quic_simple_server.cc
@@ -34,7 +34,7 @@ // Allocate some extra space so we can send an error if the client goes over // the limit. -const int kReadBufferSize = 2 * quic::kMaxOutgoingPacketSize; +const int kReadBufferSize = 2 * quic::kMaxIncomingPacketSize; } // namespace
diff --git a/remoting/host/installer/mac/BUILD.gn b/remoting/host/installer/mac/BUILD.gn index d600928..22d32f3c 100644 --- a/remoting/host/installer/mac/BUILD.gn +++ b/remoting/host/installer/mac/BUILD.gn
@@ -2,9 +2,9 @@ # Use of this source code is governed by a BSD-style license that can be # found in the LICENSE file. -import("//remoting/build/config/remoting_build.gni") - import("//build/config/zip.gni") +import("//chrome/installer/mac/mac_signing_sources.gni") +import("//remoting/build/config/remoting_build.gni") action("remoting_me2me_host_archive") { _installer_mac_files = [ @@ -19,8 +19,14 @@ "Scripts/remoting_preflight.sh", "Keystone/GoogleSoftwareUpdate.pkg", "//chrome/installer/mac/pkg-dmg", + "//chrome/installer/mac/notarize_thing.py", ] + # Chrome's signing/notarization Python module. + _mac_signing_files = + rebase_path(mac_signing_sources, ".", "//chrome/installer/mac") + _installer_mac_files += _mac_signing_files + inputs = _installer_mac_files zip_path = "$root_build_dir/remoting-me2me-host-mac.zip"
diff --git a/remoting/host/installer/mac/do_signing.sh b/remoting/host/installer/mac/do_signing.sh index c6876d8..5079f00 100755 --- a/remoting/host/installer/mac/do_signing.sh +++ b/remoting/host/installer/mac/do_signing.sh
@@ -8,11 +8,8 @@ # installer and then packages it into a .dmg. It requires that Packages be # installed (for 'packagesbuild'). # Packages: http://s.sudre.free.fr/Software/Packages/about.html -# -# usage: do_signing.sh output_dir input_dir [codesign_keychain codesign_id -# [productsign_id]] -# -# The final disk image (dmg) is placed in |output_dir|. +# Optionally, it will submit the .dmg to Apple for notarization. +# Run with "-h" to see usage information. set -e -u @@ -204,6 +201,19 @@ fi } +notarize() { + local input_dir="${1}" + local dmg="${2}" + local user="${3}" + + echo "Notarizing and stapling .dmg..." + "${input_dir}/notarize_thing.py" \ + --user "${user}" \ + --password @env:NOTARIZATION_PASSWORD \ + --bundle-id "${HOST_BUNDLE_NAME}" \ + "${dmg}" +} + cleanup() { if [[ "${#g_cleanup_dirs[@]}" > 0 ]]; then rm -rf "${g_cleanup_dirs[@]}" @@ -212,7 +222,8 @@ usage() { echo "Usage: ${ME} -o output_dir -i input_dir "\ - "[-c codesign_id] [-p productsign_id] [-k keychain]" >&2 + "[-c codesign_id] [-p productsign_id] [-k keychain] "\ + "[-n notarization_user]" >&2 echo >&2 echo " Sign the binaries using the specified <codesign_id>, build" >&2 echo " the installer, and then sign the installer using the given" >&2 @@ -221,6 +232,9 @@ echo " installer is built without signing any binaries." >&2 echo " If <keychain> is specified, it must contain all the signing ids." >&2 echo " If not specified, then the default keychains will be used." >&2 + echo " If <notarization_user> is specified, the final DMG will be" >&2 + echo " notarized by Apple and stapled, using the given user and the" >&2 + echo " password from \$NOTARIZATION_PASSWORD variable." >&2 } main() { @@ -230,9 +244,10 @@ local codesign_id="" local productsign_id="" local keychain="" + local notarization_user="" local OPTNAME OPTIND OPTARG - while getopts ":o:i:c:p:k:h" OPTNAME; do + while getopts ":o:i:c:p:k:n:h" OPTNAME; do case ${OPTNAME} in o ) output_dir="$(shell_safe_path "${OPTARG}")" @@ -249,6 +264,9 @@ k ) keychain="$(shell_safe_path "${OPTARG}")" ;; + n ) + notarization_user="${OPTARG}" + ;; h ) usage exit 0 @@ -298,7 +316,13 @@ fi build_dmg "${input_dir}" "${output_dir}" if [[ "${do_sign_binaries}" == 1 ]]; then - sign "${output_dir}/${DMG_FILE_NAME}" "${keychain}" "${codesign_id}" + sign "${output_dir}/${DMG_FILE_NAME}" "${keychain}" "${codesign_id}" + fi + + if [[ -n "${notarization_user}" ]]; then + notarize "${input_dir}" \ + "${output_dir}/${DMG_FILE_NAME}" \ + "${notarization_user}" fi cleanup
diff --git a/sandbox/linux/bpf_dsl/bpf_dsl.h b/sandbox/linux/bpf_dsl/bpf_dsl.h index 6f0dd4e..555d820e 100644 --- a/sandbox/linux/bpf_dsl/bpf_dsl.h +++ b/sandbox/linux/bpf_dsl/bpf_dsl.h
@@ -27,34 +27,32 @@ // An idiomatic and demonstrative (albeit silly) example of this API // would be: // -// #include "sandbox/linux/bpf_dsl/bpf_dsl.h" +// #include "sandbox/linux/bpf_dsl/bpf_dsl.h" // -// using namespace sandbox::bpf_dsl; +// namespace dsl = sandbox::bpf_dsl; // -// class SillyPolicy : public Policy { -// public: -// SillyPolicy() {} -// ~SillyPolicy() override {} -// ResultExpr EvaluateSyscall(int sysno) const override { -// if (sysno == __NR_fcntl) { -// Arg<int> fd(0), cmd(1); -// Arg<unsigned long> flags(2); -// const uint64_t kGoodFlags = O_ACCMODE | O_NONBLOCK; -// return If(AllOf(fd == 0, -// cmd == F_SETFL, -// (flags & ~kGoodFlags) == 0), -// Allow()) -// .ElseIf(AnyOf(cmd == F_DUPFD, cmd == F_DUPFD_CLOEXEC), -// Error(EMFILE)) -// .Else(Trap(SetFlagHandler, NULL)); -// } else { -// return Allow(); -// } -// } +// class SillyPolicy : public dsl::Policy { +// public: +// SillyPolicy() = default; +// SillyPolicy(const SillyPolicy&) = delete; +// SillyPolicy& operator=(const SillyPolicy&) = delete; +// ~SillyPolicy() override = default; // -// private: -// DISALLOW_COPY_AND_ASSIGN(SillyPolicy); -// }; +// dsl::ResultExpr EvaluateSyscall(int sysno) const override { +// if (sysno != __NR_fcntl) +// return dsl::Allow(); +// dsl::Arg<int> fd(0), cmd(1); +// dsl::Arg<unsigned long> flags(2); +// constexpr uint64_t kGoodFlags = O_ACCMODE | O_NONBLOCK; +// return dsl::If(dsl::AllOf(fd == 0, +// cmd == F_SETFL, +// (flags & ~kGoodFlags) == 0), +// dsl::Allow()) +// .dsl::ElseIf(dsl::AnyOf(cmd == F_DUPFD, cmd == F_DUPFD_CLOEXEC), +// dsl::Error(EMFILE)) +// .dsl::Else(dsl::Trap(SetFlagHandler, nullptr)); +// } +// }; // // More generally, the DSL currently supports the following grammar: //
diff --git a/sandbox/win/fuzzer/sandbox_ipc_fuzzer.cc b/sandbox/win/fuzzer/sandbox_ipc_fuzzer.cc index 1c2ea8c..074d673 100644 --- a/sandbox/win/fuzzer/sandbox_ipc_fuzzer.cc +++ b/sandbox/win/fuzzer/sandbox_ipc_fuzzer.cc
@@ -9,20 +9,19 @@ #include "sandbox/win/src/ipc_args.h" extern "C" int LLVMFuzzerTestOneInput(const uint8_t* data, size_t size) { - using namespace sandbox; - uint32_t output_size = 0; - std::unique_ptr<CrossCallParamsEx> params(CrossCallParamsEx::CreateFromBuffer( - const_cast<uint8_t*>(data), size, &output_size)); + std::unique_ptr<sandbox::CrossCallParamsEx> params( + sandbox::CrossCallParamsEx::CreateFromBuffer(const_cast<uint8_t*>(data), + size, &output_size)); if (!params.get()) return 0; uint32_t tag = params->GetTag(); - IPCParams ipc_params = {0}; + sandbox::IPCParams ipc_params = {0}; ipc_params.ipc_tag = tag; - void* args[kMaxIpcParams]; - GetArgs(params.get(), &ipc_params, args); - ReleaseArgs(&ipc_params, args); + void* args[sandbox::kMaxIpcParams]; + sandbox::GetArgs(params.get(), &ipc_params, args); + sandbox::ReleaseArgs(&ipc_params, args); return 0; }
diff --git a/services/tracing/public/cpp/perfetto/android_system_producer.cc b/services/tracing/public/cpp/perfetto/android_system_producer.cc index 92a6812c..ba7772e 100644 --- a/services/tracing/public/cpp/perfetto/android_system_producer.cc +++ b/services/tracing/public/cpp/perfetto/android_system_producer.cc
@@ -80,6 +80,7 @@ new_registration.set_name(data_source->name()); new_registration.set_will_notify_on_start(true); new_registration.set_will_notify_on_stop(true); + new_registration.set_handles_incremental_state_clear(true); service_->RegisterDataSource(new_registration); }
diff --git a/storage/browser/quota/quota_settings.cc b/storage/browser/quota/quota_settings.cc index 59f580f9b..1467c84 100644 --- a/storage/browser/quota/quota_settings.cc +++ b/storage/browser/quota/quota_settings.cc
@@ -140,7 +140,7 @@ OptionalQuotaSettingsCallback callback) { base::PostTaskAndReplyWithResult( FROM_HERE, - {base::ThreadPool(), base::MayBlock(), base::TaskPriority::BEST_EFFORT, + {base::ThreadPool(), base::MayBlock(), base::TaskPriority::USER_VISIBLE, base::TaskShutdownBehavior::CONTINUE_ON_SHUTDOWN}, base::BindOnce(&CalculateNominalDynamicSettings, partition_path, is_incognito, base::Unretained(disk_info_helper)),
diff --git a/testing/buildbot/chromium.gpu.fyi.json b/testing/buildbot/chromium.gpu.fyi.json index 733ca71de..d9a0c64 100644 --- a/testing/buildbot/chromium.gpu.fyi.json +++ b/testing/buildbot/chromium.gpu.fyi.json
@@ -6680,11 +6680,11 @@ "containment_type": "AUTO", "dimension_sets": [ { - "device_os": "P", + "device_os": "PQ3A.190801.002", + "device_os_flavor": "google", "device_os_type": "userdebug", "device_type": "walleye", - "os": "Android", - "pool": "Chrome-GPU" + "os": "Android" } ], "idempotent": false, @@ -6713,11 +6713,11 @@ "containment_type": "AUTO", "dimension_sets": [ { - "device_os": "P", + "device_os": "PQ3A.190801.002", + "device_os_flavor": "google", "device_os_type": "userdebug", "device_type": "walleye", - "os": "Android", - "pool": "Chrome-GPU" + "os": "Android" } ], "idempotent": false @@ -6746,11 +6746,11 @@ "containment_type": "AUTO", "dimension_sets": [ { - "device_os": "P", + "device_os": "PQ3A.190801.002", + "device_os_flavor": "google", "device_os_type": "userdebug", "device_type": "walleye", - "os": "Android", - "pool": "Chrome-GPU" + "os": "Android" } ], "idempotent": false, @@ -6780,11 +6780,11 @@ "containment_type": "AUTO", "dimension_sets": [ { - "device_os": "P", + "device_os": "PQ3A.190801.002", + "device_os_flavor": "google", "device_os_type": "userdebug", "device_type": "walleye", - "os": "Android", - "pool": "Chrome-GPU" + "os": "Android" } ], "idempotent": false, @@ -7060,11 +7060,11 @@ "containment_type": "AUTO", "dimension_sets": [ { - "device_os": "P", + "device_os": "PQ3A.190801.002", + "device_os_flavor": "google", "device_os_type": "userdebug", "device_type": "walleye", - "os": "Android", - "pool": "Chrome-GPU" + "os": "Android" } ], "output_links": [ @@ -7119,11 +7119,11 @@ "containment_type": "AUTO", "dimension_sets": [ { - "device_os": "P", + "device_os": "PQ3A.190801.002", + "device_os_flavor": "google", "device_os_type": "userdebug", "device_type": "walleye", - "os": "Android", - "pool": "Chrome-GPU" + "os": "Android" } ], "idempotent": false,
diff --git a/testing/buildbot/filters/chromeos.browser_tests.filter b/testing/buildbot/filters/chromeos.browser_tests.filter index 420987c4..4a879280 100644 --- a/testing/buildbot/filters/chromeos.browser_tests.filter +++ b/testing/buildbot/filters/chromeos.browser_tests.filter
@@ -29,11 +29,6 @@ # TODO(crbug.com/990819): Enable this. -StructSequence/OobeLocalizationTest.LocalizationTest/0 -# TODO(crbug.com/977170): Enable this. --StructSequence/OobeLocalizationTest.LocalizationTest/3 --StructSequence/OobeLocalizationTest.LocalizationTest/4 --StructSequence/OobeLocalizationTest.LocalizationTest/8 - # TODO(crbug.com/978051): Enable this. -TabManagerTestWithTwoTabs.TabProactiveDiscardAndFocusBeforeFreezeCompletes
diff --git a/testing/buildbot/mixins.pyl b/testing/buildbot/mixins.pyl index 842f557..0ca4cd6 100644 --- a/testing/buildbot/mixins.pyl +++ b/testing/buildbot/mixins.pyl
@@ -545,13 +545,6 @@ }, }, }, - 'pie': { - 'swarming': { - 'dimensions': { - 'device_os': 'P', - }, - }, - }, 'pie-x86-emulator': { '$mixin_append': { 'args': [
diff --git a/testing/buildbot/waterfalls.pyl b/testing/buildbot/waterfalls.pyl index f3a6d30..b75b631 100644 --- a/testing/buildbot/waterfalls.pyl +++ b/testing/buildbot/waterfalls.pyl
@@ -2574,8 +2574,7 @@ 'os_type': 'android', 'skip_merge_script': True, 'mixins': [ - 'gpu_pool', - 'pie', + 'pie_fleet', 'walleye', ], 'test_suites': { @@ -2601,8 +2600,7 @@ 'browser_config': 'android-chromium', 'skip_merge_script': True, 'mixins': [ - 'gpu_pool', - 'pie', + 'pie_fleet', 'walleye', ], 'test_suites': {
diff --git a/third_party/blink/public/mojom/indexeddb/indexeddb.mojom b/third_party/blink/public/mojom/indexeddb/indexeddb.mojom index d173ba7..bc44681 100644 --- a/third_party/blink/public/mojom/indexeddb/indexeddb.mojom +++ b/third_party/blink/public/mojom/indexeddb/indexeddb.mojom
@@ -58,6 +58,20 @@ Min, }; +// Durability guarantees during a transaction. This maps to whether or not +// the writes to disk are explicitly flushed or not. +enum IDBTransactionDurability { + // Unspecified by caller, and so is implementation defined. + // May map to either Strict or Relaxed. + Default, + + // Always flush to disk after a write. + Strict, + + // Do not flush to disk. This is much faster. + Relaxed, +}; + union IDBKeyData { array<IDBKey> key_array; array<uint8> binary; @@ -343,7 +357,7 @@ int64 transaction_id, array<int64> object_store_ids, IDBTransactionMode mode, - bool relaxed_durability); + IDBTransactionDurability durability); Close(); VersionChangeIgnored(); AddObserver(int64 transaction_id,
diff --git a/third_party/blink/public/platform/web_runtime_features.h b/third_party/blink/public/platform/web_runtime_features.h index e968391..7fc1ca3 100644 --- a/third_party/blink/public/platform/web_runtime_features.h +++ b/third_party/blink/public/platform/web_runtime_features.h
@@ -71,6 +71,7 @@ BLINK_PLATFORM_EXPORT static void EnableCompositorTouchAction(bool); BLINK_PLATFORM_EXPORT static void EnableAccelerated2dCanvas(bool); + BLINK_PLATFORM_EXPORT static void EnableAccessibilityExposeDisplayNone(bool); BLINK_PLATFORM_EXPORT static void EnableAccessibilityObjectModel(bool); BLINK_PLATFORM_EXPORT static void EnableAdTagging(bool); BLINK_PLATFORM_EXPORT static void EnableAllowActivationDelegationAttr(bool);
diff --git a/third_party/blink/public/platform/web_theme_engine.h b/third_party/blink/public/platform/web_theme_engine.h index 73dbfd8..a9ce419 100644 --- a/third_party/blink/public/platform/web_theme_engine.h +++ b/third_party/blink/public/platform/web_theme_engine.h
@@ -31,6 +31,7 @@ #ifndef THIRD_PARTY_BLINK_PUBLIC_PLATFORM_WEB_THEME_ENGINE_H_ #define THIRD_PARTY_BLINK_PUBLIC_PLATFORM_WEB_THEME_ENGINE_H_ +#include "base/optional.h" #include "base/time/time.h" #include "third_party/blink/public/platform/web_color_scheme.h" #include "third_party/blink/public/platform/web_rect.h" @@ -81,6 +82,21 @@ kPartProgressBar }; + enum class SystemThemeColor { + kNotSupported, + kButtonFace, + kButtonText, + kGrayText, + kHighlight, + kHighlightText, + kHotlight, + kMenuHighlight, + kScrollbar, + kWindow, + kWindowText, + kMaxValue = kWindowText, + }; + // Extra parameters for drawing the PartScrollbarHorizontalTrack and // PartScrollbarVerticalTrack. struct ScrollbarTrackExtraParams { @@ -203,6 +219,11 @@ const WebRect&, const ExtraParams*, blink::WebColorScheme) {} + + virtual base::Optional<SkColor> GetSystemColor( + SystemThemeColor system_theme) const { + return base::nullopt; + } }; } // namespace blink
diff --git a/third_party/blink/renderer/core/css/css_paint_value.cc b/third_party/blink/renderer/core/css/css_paint_value.cc index e01b860..d00c3af 100644 --- a/third_party/blink/renderer/core/css/css_paint_value.cc +++ b/third_party/blink/renderer/core/css/css_paint_value.cc
@@ -4,6 +4,7 @@ #include "third_party/blink/renderer/core/css/css_paint_value.h" +#include "base/metrics/histogram_macros.h" #include "third_party/blink/renderer/core/css/css_custom_ident_value.h" #include "third_party/blink/renderer/core/css/css_paint_image_generator.h" #include "third_party/blink/renderer/core/css/css_syntax_definition.h" @@ -24,7 +25,10 @@ : CSSImageGeneratorValue(kPaintClass), name_(name), paint_image_generator_observer_(MakeGarbageCollected<Observer>(this)), - paint_off_thread_(true) {} + off_thread_paint_state_( + RuntimeEnabledFeatures::OffMainThreadCSSPaintEnabled() + ? OffThreadPaintState::kUnknown + : OffThreadPaintState::kMainThread) {} CSSPaintValue::CSSPaintValue( CSSCustomIdentValue* name, @@ -91,35 +95,39 @@ // For Off-Thread PaintWorklet, we just collect the necessary inputs together // and defer the actual JavaScript call until much later (during cc Raster). - if (RuntimeEnabledFeatures::OffMainThreadCSSPaintEnabled()) { - if (paint_off_thread_) { - // It is not necessary for a LayoutObject to always have RareData which - // contains the ElementId. If this |layout_object| doesn't have an - // ElementId, then create one for it. - layout_object.GetMutableForPainting().EnsureId(); + if (off_thread_paint_state_ != OffThreadPaintState::kMainThread) { + // It is not necessary for a LayoutObject to always have RareData which + // contains the ElementId. If this |layout_object| doesn't have an + // ElementId, then create one for it. + layout_object.GetMutableForPainting().EnsureId(); - Vector<CSSPropertyID> native_properties = - generator_->NativeInvalidationProperties(); - Vector<AtomicString> custom_properties = - generator_->CustomInvalidationProperties(); - float zoom = layout_object.StyleRef().EffectiveZoom(); - CompositorPaintWorkletInput::PropertyKeys input_property_keys; - auto style_data = PaintWorkletStylePropertyMap::BuildCrossThreadData( - document, layout_object.UniqueId(), style, native_properties, - custom_properties, input_property_keys); - paint_off_thread_ = style_data.has_value(); - if (paint_off_thread_) { - Vector<std::unique_ptr<CrossThreadStyleValue>> - cross_thread_input_arguments; - BuildInputArgumentValues(cross_thread_input_arguments); - scoped_refptr<PaintWorkletInput> input = - base::MakeRefCounted<PaintWorkletInput>( - GetName(), target_size, zoom, device_scale_factor, - generator_->WorkletId(), std::move(style_data.value()), - std::move(cross_thread_input_arguments), - std::move(input_property_keys)); - return PaintWorkletDeferredImage::Create(std::move(input), target_size); - } + Vector<CSSPropertyID> native_properties = + generator_->NativeInvalidationProperties(); + Vector<AtomicString> custom_properties = + generator_->CustomInvalidationProperties(); + float zoom = layout_object.StyleRef().EffectiveZoom(); + CompositorPaintWorkletInput::PropertyKeys input_property_keys; + auto style_data = PaintWorkletStylePropertyMap::BuildCrossThreadData( + document, layout_object.UniqueId(), style, native_properties, + custom_properties, input_property_keys); + if (off_thread_paint_state_ == OffThreadPaintState::kUnknown) { + UMA_HISTOGRAM_BOOLEAN("Blink.CSSPaintValue.PaintOffThread", + style_data.has_value()); + } + off_thread_paint_state_ = style_data.has_value() + ? OffThreadPaintState::kOffThread + : OffThreadPaintState::kMainThread; + if (off_thread_paint_state_ == OffThreadPaintState::kOffThread) { + Vector<std::unique_ptr<CrossThreadStyleValue>> + cross_thread_input_arguments; + BuildInputArgumentValues(cross_thread_input_arguments); + scoped_refptr<PaintWorkletInput> input = + base::MakeRefCounted<PaintWorkletInput>( + GetName(), target_size, zoom, device_scale_factor, + generator_->WorkletId(), std::move(style_data.value()), + std::move(cross_thread_input_arguments), + std::move(input_property_keys)); + return PaintWorkletDeferredImage::Create(std::move(input), target_size); } }
diff --git a/third_party/blink/renderer/core/css/css_paint_value.h b/third_party/blink/renderer/core/css/css_paint_value.h index 7b384a0..8c4ce29 100644 --- a/third_party/blink/renderer/core/css/css_paint_value.h +++ b/third_party/blink/renderer/core/css/css_paint_value.h
@@ -98,9 +98,12 @@ Member<Observer> paint_image_generator_observer_; Member<CSSStyleValueVector> parsed_input_arguments_; Vector<scoped_refptr<CSSVariableData>> argument_variable_data_; + enum class OffThreadPaintState { kUnknown, kOffThread, kMainThread }; + // Indicates whether this paint worklet is composited or not. kUnknown + // indicates that it has not been decided yet. // TODO(crbug.com/987974): Make this variable reset when there is a style // change. - bool paint_off_thread_; + OffThreadPaintState off_thread_paint_state_; }; template <>
diff --git a/third_party/blink/renderer/core/css/css_paint_value_test.cc b/third_party/blink/renderer/core/css/css_paint_value_test.cc index e1d9340..b5f3102 100644 --- a/third_party/blink/renderer/core/css/css_paint_value_test.cc +++ b/third_party/blink/renderer/core/css/css_paint_value_test.cc
@@ -15,8 +15,10 @@ #include "third_party/blink/renderer/core/frame/web_local_frame_impl.h" #include "third_party/blink/renderer/core/layout/layout_object.h" #include "third_party/blink/renderer/core/style/computed_style.h" +#include "third_party/blink/renderer/core/style/style_generated_image.h" #include "third_party/blink/renderer/core/testing/core_unit_test_helper.h" #include "third_party/blink/renderer/platform/graphics/paint_generated_image.h" +#include "third_party/blink/renderer/platform/testing/histogram_tester.h" #include "third_party/blink/renderer/platform/testing/unit_test_helpers.h" #include "third_party/blink/renderer/platform/testing/url_test_helpers.h" @@ -78,6 +80,10 @@ MOCK_CONST_METHOD0(IsImageGeneratorReady, bool()); MOCK_CONST_METHOD0(WorkletId, int()); + void AddNativeProperty() { + native_properties_.push_back(CSSPropertyID::kBorderImageSource); + } + private: Vector<CSSPropertyID> native_properties_; Vector<AtomicString> custom_properties_; @@ -96,6 +102,103 @@ } } // namespace +TEST_P(CSSPaintValueTest, ReportingCompositedUMA) { + HistogramTester histogram_tester; + NiceMock<MockCSSPaintImageGenerator>* mock_generator = + MakeGarbageCollected<NiceMock<MockCSSPaintImageGenerator>>(); + base::AutoReset<MockCSSPaintImageGenerator*> scoped_override_generator( + &g_override_generator, mock_generator); + base::AutoReset<CSSPaintImageGenerator::CSSPaintImageGeneratorCreateFunction> + scoped_create_function( + CSSPaintImageGenerator::GetCreateFunctionForTesting(), + ProvideOverrideGenerator); + + const FloatSize target_size(100, 100); + + SetBodyInnerHTML(R"HTML(<div id="target"></div>)HTML"); + LayoutObject* target = GetLayoutObjectByElementId("target"); + const ComputedStyle& style = *target->Style(); + + auto* ident = MakeGarbageCollected<CSSCustomIdentValue>("testpainter"); + CSSPaintValue* paint_value = MakeGarbageCollected<CSSPaintValue>(ident); + // Mark the generator as ready - GetImage should succeed when + // OffMainThreadCSSPaint is enabled. + ON_CALL(*mock_generator, IsImageGeneratorReady()).WillByDefault(Return(true)); + ON_CALL(*mock_generator, Paint(_, _, _, _)) + .WillByDefault(Return(PaintGeneratedImage::Create(nullptr, target_size))); + ASSERT_TRUE( + paint_value->GetImage(*target, GetDocument(), style, target_size)); + if (RuntimeEnabledFeatures::OffMainThreadCSSPaintEnabled()) { + histogram_tester.ExpectTotalCount("Blink.CSSPaintValue.PaintOffThread", 1u); + histogram_tester.ExpectUniqueSample("Blink.CSSPaintValue.PaintOffThread", + true, 1u); + } else { + histogram_tester.ExpectTotalCount("Blink.CSSPaintValue.PaintOffThread", 0u); + } + + ASSERT_TRUE( + paint_value->GetImage(*target, GetDocument(), style, target_size)); + if (RuntimeEnabledFeatures::OffMainThreadCSSPaintEnabled()) { + // Repaint, should not report histogram again. + histogram_tester.ExpectTotalCount("Blink.CSSPaintValue.PaintOffThread", 1u); + histogram_tester.ExpectUniqueSample("Blink.CSSPaintValue.PaintOffThread", + true, 1u); + } else { + histogram_tester.ExpectTotalCount("Blink.CSSPaintValue.PaintOffThread", 0u); + } +} + +TEST_P(CSSPaintValueTest, ReportingNonCompositedUMA) { + HistogramTester histogram_tester; + NiceMock<MockCSSPaintImageGenerator>* mock_generator = + MakeGarbageCollected<NiceMock<MockCSSPaintImageGenerator>>(); + mock_generator->AddNativeProperty(); + base::AutoReset<MockCSSPaintImageGenerator*> scoped_override_generator( + &g_override_generator, mock_generator); + base::AutoReset<CSSPaintImageGenerator::CSSPaintImageGeneratorCreateFunction> + scoped_create_function( + CSSPaintImageGenerator::GetCreateFunctionForTesting(), + ProvideOverrideGenerator); + + const FloatSize target_size(100, 100); + + SetBodyInnerHTML(R"HTML(<div id="target"></div>)HTML"); + LayoutObject* target = GetLayoutObjectByElementId("target"); + auto style = ComputedStyle::Create(); + auto* ident = MakeGarbageCollected<CSSCustomIdentValue>("testpainter"); + CSSPaintValue* paint_value = MakeGarbageCollected<CSSPaintValue>(ident); + StyleGeneratedImage* style_image = + MakeGarbageCollected<StyleGeneratedImage>(*paint_value); + style->SetBorderImageSource(style_image); + + ON_CALL(*mock_generator, IsImageGeneratorReady()).WillByDefault(Return(true)); + EXPECT_CALL(*mock_generator, Paint(_, _, _, _)) + .WillRepeatedly( + Return(PaintGeneratedImage::Create(nullptr, target_size))); + // The paint worklet is not composited, and falls back to the main thread + // paint. + ASSERT_TRUE( + paint_value->GetImage(*target, GetDocument(), *style, target_size)); + if (RuntimeEnabledFeatures::OffMainThreadCSSPaintEnabled()) { + histogram_tester.ExpectTotalCount("Blink.CSSPaintValue.PaintOffThread", 1u); + histogram_tester.ExpectUniqueSample("Blink.CSSPaintValue.PaintOffThread", + false, 1u); + } else { + histogram_tester.ExpectTotalCount("Blink.CSSPaintValue.PaintOffThread", 0u); + } + + // Repaint, should not report histogram again. + ASSERT_TRUE( + paint_value->GetImage(*target, GetDocument(), *style, target_size)); + if (RuntimeEnabledFeatures::OffMainThreadCSSPaintEnabled()) { + histogram_tester.ExpectTotalCount("Blink.CSSPaintValue.PaintOffThread", 1u); + histogram_tester.ExpectUniqueSample("Blink.CSSPaintValue.PaintOffThread", + false, 1u); + } else { + histogram_tester.ExpectTotalCount("Blink.CSSPaintValue.PaintOffThread", 0u); + } +} + TEST_P(CSSPaintValueTest, DelayPaintUntilGeneratorReady) { NiceMock<MockCSSPaintImageGenerator>* mock_generator = MakeGarbageCollected<NiceMock<MockCSSPaintImageGenerator>>();
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 f6dc21ef..0a41da6 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
@@ -1723,7 +1723,7 @@ } // Appends to the passed in CSSGridLineNamesValue if any, otherwise creates a -// new one. +// new one. Returns nullptr if an empty list is consumed. CSSGridLineNamesValue* ConsumeGridLineNames( CSSParserTokenRange& range, const CSSParserContext& context, @@ -1739,6 +1739,8 @@ if (range_copy.ConsumeIncludingWhitespace().GetType() != kRightBracketToken) return nullptr; range = range_copy; + if (line_names->length() == 0U) + return nullptr; return line_names; } @@ -1939,12 +1941,11 @@ TrackListType track_list_type) { bool allow_grid_line_names = track_list_type != TrackListType::kGridAuto; CSSValueList* values = CSSValueList::CreateSpaceSeparated(); + if (!allow_grid_line_names && range.Peek().GetType() == kLeftBracketToken) + return nullptr; CSSGridLineNamesValue* line_names = ConsumeGridLineNames(range, context); - if (line_names) { - if (!allow_grid_line_names) - return nullptr; + if (line_names) values->Append(*line_names); - } bool allow_repeat = track_list_type == TrackListType::kGridTemplate; bool seen_auto_repeat = false; @@ -1970,12 +1971,11 @@ } if (seen_auto_repeat && !all_tracks_are_fixed_sized) return nullptr; + if (!allow_grid_line_names && range.Peek().GetType() == kLeftBracketToken) + return nullptr; line_names = ConsumeGridLineNames(range, context); - if (line_names) { - if (!allow_grid_line_names) - return nullptr; + if (line_names) values->Append(*line_names); - } } while (!range.AtEnd() && range.Peek().GetType() != kDelimiterToken); return values; }
diff --git a/third_party/blink/renderer/core/exported/web_page_popup_impl.cc b/third_party/blink/renderer/core/exported/web_page_popup_impl.cc index 7e2550e4..60f9986 100644 --- a/third_party/blink/renderer/core/exported/web_page_popup_impl.cc +++ b/third_party/blink/renderer/core/exported/web_page_popup_impl.cc
@@ -122,7 +122,8 @@ #endif } - void ScheduleAnimation(const LocalFrameView*) override { + void ScheduleAnimation(const LocalFrameView*, + base::TimeDelta = base::TimeDelta()) override { if (WebTestSupport::IsRunningWebTest()) { // In single threaded web tests, the main frame's WebWidgetClient // (provided by WebViewTestProxy or WebWidgetTestProxy) runs the composite
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 a8c6b6c6..1c10fa8 100644 --- a/third_party/blink/renderer/core/frame/local_frame_view.cc +++ b/third_party/blink/renderer/core/frame/local_frame_view.cc
@@ -3356,9 +3356,9 @@ resizer_areas_->erase(it); } -void LocalFrameView::ScheduleAnimation() { +void LocalFrameView::ScheduleAnimation(base::TimeDelta delay) { if (auto* client = GetChromeClient()) - client->ScheduleAnimation(this); + client->ScheduleAnimation(this, delay); } bool LocalFrameView::FrameIsScrollableDidChange() {
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 52a76f6..319a0d6 100644 --- a/third_party/blink/renderer/core/frame/local_frame_view.h +++ b/third_party/blink/renderer/core/frame/local_frame_view.h
@@ -474,7 +474,7 @@ return resizer_areas_.get(); } - void ScheduleAnimation(); + void ScheduleAnimation(base::TimeDelta = base::TimeDelta()); // FIXME: This should probably be renamed as the 'inSubtreeLayout' parameter // passed around the LocalFrameView layout methods can be true while this
diff --git a/third_party/blink/renderer/core/frame/local_frame_view_test.cc b/third_party/blink/renderer/core/frame/local_frame_view_test.cc index ca2e05b..0c9c6049 100644 --- a/third_party/blink/renderer/core/frame/local_frame_view_test.cc +++ b/third_party/blink/renderer/core/frame/local_frame_view_test.cc
@@ -42,7 +42,8 @@ MockSetToolTip(&frame, tooltip_text, dir); } - void ScheduleAnimation(const LocalFrameView*) override { + void ScheduleAnimation(const LocalFrameView*, + base::TimeDelta = base::TimeDelta()) override { has_scheduled_animation_ = true; } bool has_scheduled_animation_;
diff --git a/third_party/blink/renderer/core/frame/web_frame_widget_base.cc b/third_party/blink/renderer/core/frame/web_frame_widget_base.cc index eee1f2f..cda9010 100644 --- a/third_party/blink/renderer/core/frame/web_frame_widget_base.cc +++ b/third_party/blink/renderer/core/frame/web_frame_widget_base.cc
@@ -60,6 +60,10 @@ void WebFrameWidgetBase::BindLocalRoot(WebLocalFrame& local_root) { local_root_ = To<WebLocalFrameImpl>(local_root); local_root_->SetFrameWidget(this); + request_animation_after_delay_timer_.reset( + new TaskRunnerTimer<WebFrameWidgetBase>( + local_root.GetTaskRunner(TaskType::kInternalDefault), this, + &WebFrameWidgetBase::RequestAnimationAfterDelayTimerFired)); } void WebFrameWidgetBase::Close() { @@ -67,6 +71,7 @@ local_root_->SetFrameWidget(nullptr); local_root_ = nullptr; client_ = nullptr; + request_animation_after_delay_timer_.reset(); } WebLocalFrame* WebFrameWidgetBase::LocalRoot() const { @@ -433,6 +438,23 @@ return WebLocalFrameImpl::FromFrame(FocusedLocalFrameInWidget()); } +void WebFrameWidgetBase::RequestAnimationAfterDelay( + const base::TimeDelta& delay) { + DCHECK(request_animation_after_delay_timer_.get()); + if (request_animation_after_delay_timer_->IsActive() && + request_animation_after_delay_timer_->NextFireInterval() > delay) { + request_animation_after_delay_timer_->Stop(); + } + if (!request_animation_after_delay_timer_->IsActive()) { + request_animation_after_delay_timer_->StartOneShot(delay, FROM_HERE); + } +} + +void WebFrameWidgetBase::RequestAnimationAfterDelayTimerFired(TimerBase*) { + if (client_) + client_->ScheduleAnimation(); +} + base::WeakPtr<AnimationWorkletMutatorDispatcherImpl> WebFrameWidgetBase::EnsureCompositorMutatorDispatcher( scoped_refptr<base::SingleThreadTaskRunner>* mutator_task_runner) {
diff --git a/third_party/blink/renderer/core/frame/web_frame_widget_base.h b/third_party/blink/renderer/core/frame/web_frame_widget_base.h index 456e789..37af84b 100644 --- a/third_party/blink/renderer/core/frame/web_frame_widget_base.h +++ b/third_party/blink/renderer/core/frame/web_frame_widget_base.h
@@ -16,6 +16,7 @@ #include "third_party/blink/renderer/core/dom/user_gesture_indicator.h" #include "third_party/blink/renderer/platform/graphics/paint/paint_image.h" #include "third_party/blink/renderer/platform/heap/member.h" +#include "third_party/blink/renderer/platform/timer.h" #include "third_party/blink/renderer/platform/wtf/casting.h" namespace cc { @@ -142,6 +143,8 @@ // focused frame has a different local root. LocalFrame* FocusedLocalFrameInWidget() const; + void RequestAnimationAfterDelay(const base::TimeDelta&); + virtual void Trace(blink::Visitor*); protected: @@ -186,6 +189,7 @@ private: void CancelDrag(); + void RequestAnimationAfterDelayTimerFired(TimerBase*); WebWidgetClient* client_; @@ -211,6 +215,9 @@ base::WeakPtr<PaintWorkletPaintDispatcher> paint_dispatcher_; scoped_refptr<base::SingleThreadTaskRunner> paint_task_runner_; + std::unique_ptr<TaskRunnerTimer<WebFrameWidgetBase>> + request_animation_after_delay_timer_; + friend class WebViewImpl; };
diff --git a/third_party/blink/renderer/core/input/mouse_event_manager.cc b/third_party/blink/renderer/core/input/mouse_event_manager.cc index 4917895..005e1f7 100644 --- a/third_party/blink/renderer/core/input/mouse_event_manager.cc +++ b/third_party/blink/renderer/core/input/mouse_event_manager.cc
@@ -790,7 +790,8 @@ if (RuntimeEnabledFeatures::TextFragmentIdentifiersEnabled( frame_->GetDocument())) { - frame_->View()->DismissFragmentAnchor(); + if (frame_->View()) + frame_->View()->DismissFragmentAnchor(); } if (frame_->GetDocument()->IsSVGDocument() &&
diff --git a/third_party/blink/renderer/core/intersection_observer/intersection_observation.cc b/third_party/blink/renderer/core/intersection_observer/intersection_observation.cc index c07392fc..5cad314 100644 --- a/third_party/blink/renderer/core/intersection_observer/intersection_observation.cc +++ b/third_party/blink/renderer/core/intersection_observer/intersection_observation.cc
@@ -16,6 +16,11 @@ namespace { +Document& TrackingDocument(const IntersectionObservation* observation) { + if (observation->Observer()->RootIsImplicit()) + return observation->Target()->GetDocument(); + return (observation->Observer()->root()->GetDocument()); +} } // namespace @@ -97,8 +102,10 @@ DOMHighResTimeStamp timestamp = observer_->GetTimeStamp(); if (timestamp == -1) return false; - if (!(flags & kIgnoreDelay) && - timestamp - last_run_time_ < observer_->GetEffectiveDelay()) { + base::TimeDelta delay = base::TimeDelta::FromMilliseconds( + observer_->GetEffectiveDelay() - (timestamp - last_run_time_)); + if (!(flags & kIgnoreDelay) && delay > base::TimeDelta()) { + TrackingDocument(this).View()->ScheduleAnimation(delay); return false; } if (target_->isConnected() && Observer()->trackVisibility()) {
diff --git a/third_party/blink/renderer/core/layout/layout_flexible_box.cc b/third_party/blink/renderer/core/layout/layout_flexible_box.cc index a475ab80..ed5939cf 100644 --- a/third_party/blink/renderer/core/layout/layout_flexible_box.cc +++ b/third_party/blink/renderer/core/layout/layout_flexible_box.cc
@@ -1227,7 +1227,8 @@ ItemPosition position, LayoutUnit ascent, LayoutUnit max_ascent, - bool is_wrap_reverse) { + bool is_wrap_reverse, + bool is_deprecated_webkit_box) { switch (position) { case ItemPosition::kLegacy: case ItemPosition::kAuto: @@ -1248,8 +1249,10 @@ break; case ItemPosition::kFlexEnd: return available_free_space; - case ItemPosition::kCenter: - return available_free_space / 2; + case ItemPosition::kCenter: { + const LayoutUnit result = (available_free_space / 2); + return is_deprecated_webkit_box ? result.ClampNegativeToZero() : result; + } case ItemPosition::kBaseline: // FIXME: If we get here in columns, we want the use the descent, except // we currently can't get the ascent/descent of orthogonal children. @@ -1299,14 +1302,18 @@ available_space, FlexLayoutAlgorithm::AlignmentForChild(StyleRef(), child.StyleRef()), LayoutUnit(), LayoutUnit(), - StyleRef().FlexWrap() == EFlexWrap::kWrapReverse); + StyleRef().FlexWrap() == EFlexWrap::kWrapReverse, + StyleRef().IsDeprecatedWebkitBox()); } LayoutUnit LayoutFlexibleBox::StaticInlinePositionForPositionedChild( const LayoutBox& child) { - return StartOffsetForContent() + - (IsColumnFlow() ? StaticCrossAxisPositionForPositionedChild(child) - : StaticMainAxisPositionForPositionedChild(child)); + const LayoutUnit start_offset = StartOffsetForContent(); + if (IsColumnFlow() && StyleRef().IsDeprecatedWebkitBox()) + return start_offset; + return start_offset + (IsColumnFlow() + ? StaticCrossAxisPositionForPositionedChild(child) + : StaticMainAxisPositionForPositionedChild(child)); } LayoutUnit LayoutFlexibleBox::StaticBlockPositionForPositionedChild( @@ -1623,7 +1630,8 @@ LayoutUnit available_space = flex_item.AvailableAlignmentSpace(); LayoutUnit offset = AlignmentOffset( available_space, position, flex_item.MarginBoxAscent(), max_ascent, - StyleRef().FlexWrap() == EFlexWrap::kWrapReverse); + StyleRef().FlexWrap() == EFlexWrap::kWrapReverse, + StyleRef().IsDeprecatedWebkitBox()); AdjustAlignmentForChild(*flex_item.box, offset); if (position == ItemPosition::kBaseline && StyleRef().FlexWrap() == EFlexWrap::kWrapReverse) {
diff --git a/third_party/blink/renderer/core/layout/layout_theme_win.cc b/third_party/blink/renderer/core/layout/layout_theme_win.cc index 43fd8ef9..e333838 100644 --- a/third_party/blink/renderer/core/layout/layout_theme_win.cc +++ b/third_party/blink/renderer/core/layout/layout_theme_win.cc
@@ -6,6 +6,7 @@ #include <windows.h> +#include "third_party/blink/public/platform/platform.h" #include "third_party/blink/renderer/platform/runtime_enabled_features.h" namespace blink { @@ -25,45 +26,42 @@ return LayoutThemeDefault::SystemColor(css_value_id, color_scheme); } - int system_index; - + blink::WebThemeEngine::SystemThemeColor theme_color; switch (css_value_id) { case CSSValueID::kButtonface: - system_index = COLOR_BTNFACE; + theme_color = blink::WebThemeEngine::SystemThemeColor::kButtonFace; break; case CSSValueID::kButtontext: - system_index = COLOR_BTNTEXT; + theme_color = blink::WebThemeEngine::SystemThemeColor::kButtonText; break; case CSSValueID::kGraytext: - system_index = COLOR_GRAYTEXT; + theme_color = blink::WebThemeEngine::SystemThemeColor::kGrayText; break; case CSSValueID::kHighlight: - system_index = COLOR_HIGHLIGHT; + theme_color = blink::WebThemeEngine::SystemThemeColor::kHighlight; break; case CSSValueID::kHighlighttext: - system_index = COLOR_HIGHLIGHTTEXT; + theme_color = blink::WebThemeEngine::SystemThemeColor::kHighlightText; break; case CSSValueID::kLinktext: case CSSValueID::kVisitedtext: - system_index = COLOR_HOTLIGHT; + theme_color = blink::WebThemeEngine::SystemThemeColor::kHotlight; break; case CSSValueID::kWindow: - system_index = COLOR_WINDOW; + theme_color = blink::WebThemeEngine::SystemThemeColor::kWindow; break; case CSSValueID::kWindowtext: - system_index = COLOR_WINDOWTEXT; + theme_color = blink::WebThemeEngine::SystemThemeColor::kWindowText; break; default: return LayoutThemeDefault::SystemColor(css_value_id, color_scheme); } - return SystemColorBySystemIndex(system_index); -} - -Color LayoutThemeWin::SystemColorBySystemIndex(int system_index) { - DWORD system_color = ::GetSysColor(system_index); - return Color(GetRValue(system_color), GetGValue(system_color), - GetBValue(system_color)); + const base::Optional<SkColor> system_color = + Platform::Current()->ThemeEngine()->GetSystemColor(theme_color); + if (system_color == base::nullopt) + return LayoutThemeDefault::SystemColor(css_value_id, color_scheme); + return Color(system_color.value()); } } // namespace blink
diff --git a/third_party/blink/renderer/core/layout/layout_theme_win.h b/third_party/blink/renderer/core/layout/layout_theme_win.h index 842870a4..860a0a74 100644 --- a/third_party/blink/renderer/core/layout/layout_theme_win.h +++ b/third_party/blink/renderer/core/layout/layout_theme_win.h
@@ -15,9 +15,6 @@ Color SystemColor(CSSValueID css_value_id, WebColorScheme color_scheme) const override; - - private: - static Color SystemColorBySystemIndex(int system_index); }; } // namespace blink
diff --git a/third_party/blink/renderer/core/layout/ng/ng_block_layout_algorithm.cc b/third_party/blink/renderer/core/layout/ng/ng_block_layout_algorithm.cc index f805de2..ce3ceb09 100644 --- a/third_party/blink/renderer/core/layout/ng/ng_block_layout_algorithm.cc +++ b/third_party/blink/renderer/core/layout/ng/ng_block_layout_algorithm.cc
@@ -948,8 +948,7 @@ LayoutUnit child_origin_line_offset = ConstraintSpace().BfcOffset().line_offset + - border_scrollbar_padding_.LineLeft(direction) + - child_data.margins.LineLeft(direction).ClampNegativeToZero(); + border_scrollbar_padding_.LineLeft(direction); // If the child has a block-start margin, and the BFC block offset is still // unresolved, and we have preceding adjoining floats, things get complicated @@ -1044,11 +1043,12 @@ bool abort_if_cleared = child_data.margins.block_start != LayoutUnit() && !child_margin_got_separated && child_determined_bfc_offset; - NGLayoutOpportunity opportunity; - scoped_refptr<const NGLayoutResult> layout_result; - std::tie(layout_result, opportunity) = LayoutNewFormattingContext( - child, child_break_token, child_data, - {child_origin_line_offset, child_bfc_offset_estimate}, abort_if_cleared); + NGBfcOffset child_bfc_offset; + scoped_refptr<const NGLayoutResult> layout_result = + LayoutNewFormattingContext( + child, child_break_token, child_data, + {child_origin_line_offset, child_bfc_offset_estimate}, + abort_if_cleared, &child_bfc_offset); if (!layout_result) { DCHECK(abort_if_cleared); @@ -1085,81 +1085,20 @@ } } - DCHECK_GT(opportunity.rect.start_offset.block_offset, - child_bfc_offset_estimate); child_bfc_offset_estimate = non_adjoining_bfc_offset_estimate; child_margin_got_separated = true; // We can re-layout the child right away. This re-layout *must* produce a - // fragment and opportunity which fits within the exclusion space. - std::tie(layout_result, opportunity) = LayoutNewFormattingContext( + // fragment which fits within the exclusion space. + layout_result = LayoutNewFormattingContext( child, child_break_token, child_data, {child_origin_line_offset, child_bfc_offset_estimate}, - /* abort_if_cleared */ false); + /* abort_if_cleared */ false, &child_bfc_offset); } NGFragment fragment(ConstraintSpace().GetWritingMode(), layout_result->PhysicalFragment()); - // Auto-margins are applied within the layout opportunity which fits. We'll - // pretend that computed margins are 0 here, as they have already been - // excluded from the layout opportunity rectangle. - NGBoxStrut auto_margins; - if (child.IsListMarker()) { - // Deal with marker's margin. It happens only when marker needs to occupy - // the whole line. - DCHECK(child.ListMarkerOccupiesWholeLine()); - // Because the marker is laid out as a normal block child, its inline size - // is extended to fill up the space. Compute the regular marker size from - // the first child. - const NGPhysicalContainerFragment& marker_fragment = - layout_result->PhysicalFragment(); - LayoutUnit marker_inline_size = LayoutUnit(); - if (!marker_fragment.Children().empty()) { - const NGPhysicalFragment& marker_child_fragment = - *marker_fragment.Children().front(); - marker_inline_size = - marker_child_fragment.Size() - .ConvertToLogical(ConstraintSpace().GetWritingMode()) - .inline_size; - } - auto_margins.inline_start = NGUnpositionedListMarker(To<NGBlockNode>(child)) - .InlineOffset(marker_inline_size); - auto_margins.inline_end = opportunity.rect.InlineSize() - - fragment.InlineSize() - auto_margins.inline_start; - } else { - LayoutUnit inline_size = fragment.InlineSize(); - // Negative margins are not used to determine opportunity, but need to take - // them into account for positioning. - LayoutUnit inline_margin = child_data.margins.InlineSum(); - if (inline_margin < 0) - inline_size += inline_margin; - ResolveInlineMargins(child_style, Style(), opportunity.rect.InlineSize(), - inline_size, &auto_margins); - } - - LayoutUnit child_bfc_line_offset = opportunity.rect.start_offset.line_offset + - auto_margins.LineLeft(direction); - - // When there are negative margins present, a new formatting context can move - // outside its layout opportunity. This occurs when the *line-left* edge - // hasn't been shifted by floats. - // - // NOTE: Firefox and EdgeHTML both match this behaviour of only considering - // the line-left edge. WebKit also considers this line-right edge, but this - // is slightly more complicated to implement, and probably not needed for web - // compatibility. - bool can_move_outside_opportunity = - opportunity.rect.start_offset.line_offset == child_origin_line_offset; - - if (can_move_outside_opportunity) { - child_bfc_line_offset += - child_data.margins.LineLeft(direction).ClampPositiveToZero(); - } - - NGBfcOffset child_bfc_offset(child_bfc_line_offset, - opportunity.rect.start_offset.block_offset); - LogicalOffset logical_offset = LogicalFromBfcOffsets( child_bfc_offset, ContainerBfcOffset(), fragment.InlineSize(), container_builder_.Size().inline_size, ConstraintSpace().Direction()); @@ -1198,36 +1137,28 @@ return true; } -std::pair<scoped_refptr<const NGLayoutResult>, NGLayoutOpportunity> +scoped_refptr<const NGLayoutResult> NGBlockLayoutAlgorithm::LayoutNewFormattingContext( NGLayoutInputNode child, const NGBreakToken* child_break_token, const NGInflowChildData& child_data, NGBfcOffset origin_offset, - bool abort_if_cleared) { + bool abort_if_cleared, + NGBfcOffset* out_child_bfc_offset) { + const ComputedStyle& child_style = child.Style(); + const TextDirection direction = ConstraintSpace().Direction(); + const WritingMode writing_mode = ConstraintSpace().GetWritingMode(); + // The origin offset is where we should start looking for layout // opportunities. It needs to be adjusted by the child's clearance. AdjustToClearance( - exclusion_space_.ClearanceOffset(child.Style().Clear(Style())), + exclusion_space_.ClearanceOffset(child_style.Clear(Style())), &origin_offset); DCHECK(container_builder_.BfcBlockOffset()); - // Before we lay out, figure out how much inline space we have available at - // the start block offset estimate (the child is not allowed to overlap with - // floats, so we need to find out how much space is used by floats at this - // block offset). This may affect the inline size of the child, e.g. when it's - // specified as auto, or if it's a table (with table-layout:auto). This will - // not affect percentage resolution, because that's going to be resolved - // against the containing block, regardless of adjacent floats. When looking - // for space, we ignore inline margins, as they will overlap with any adjacent - // floats. - LayoutUnit inline_margin = child_data.margins.InlineSum(); - LayoutUnit inline_size = - (child_available_size_.inline_size - inline_margin.ClampNegativeToZero()) - .ClampNegativeToZero(); - LayoutOpportunityVector opportunities = - exclusion_space_.AllLayoutOpportunities(origin_offset, inline_size); + exclusion_space_.AllLayoutOpportunities( + origin_offset, child_available_size_.inline_size); // We should always have at least one opportunity. DCHECK_GT(opportunities.size(), 0u); @@ -1243,32 +1174,60 @@ // Abort if we got pushed downwards. We need to adjust // origin_offset.block_offset, reposition any floats affected by that, and // try again. - return std::make_pair(nullptr, opportunity); + return nullptr; } - // When the inline dimensions of layout opportunity match the available - // space, a new formatting context can expand outside of the opportunity if - // negative margins are present. - bool can_expand_outside_opportunity = - (opportunity.rect.start_offset.line_offset == - origin_offset.line_offset && - opportunity.rect.InlineSize() == inline_size); + // Find the available inline-size which should be given to the child. + LayoutUnit line_left_offset = opportunity.rect.start_offset.line_offset; + LayoutUnit line_right_offset = opportunity.rect.end_offset.line_offset; - LayoutUnit inline_negative_margin = - can_expand_outside_opportunity ? inline_margin.ClampPositiveToZero() - : LayoutUnit(); + LayoutUnit line_left_margin = child_data.margins.LineLeft(direction); + LayoutUnit line_right_margin = child_data.margins.LineRight(direction); + + // When the inline dimensions of layout opportunity match the available + // inline-size, a new formatting context can expand outside of the + // opportunity if negative margins are present. + bool can_expand_outside_opportunity = + opportunity.rect.start_offset.line_offset == + origin_offset.line_offset && + opportunity.rect.InlineSize() == child_available_size_.inline_size; + + if (can_expand_outside_opportunity) { + // No floats have affected the available inline-size, adjust the + // available inline-size by the margins. + DCHECK_EQ(line_left_offset, origin_offset.line_offset); + DCHECK_EQ(line_right_offset, + origin_offset.line_offset + child_available_size_.inline_size); + line_left_offset += line_left_margin; + line_right_offset -= line_right_margin; + } else { + // Margins are applied from the content-box, not the layout opportunity + // area. Instead of adjusting by the size of the margins, we "shrink" the + // available inline-size if required. + line_left_offset = std::max( + line_left_offset, + origin_offset.line_offset + line_left_margin.ClampNegativeToZero()); + line_right_offset = std::min(line_right_offset, + origin_offset.line_offset + + child_available_size_.inline_size - + line_right_margin.ClampNegativeToZero()); + } + LayoutUnit opportunity_size = + (line_right_offset - line_left_offset).ClampNegativeToZero(); // The available inline size in the child constraint space needs to include // inline margins, since layout algorithms (both legacy and NG) will resolve // auto inline size by subtracting the inline margins from available inline // size. We have calculated a layout opportunity without margins in mind, // since they overlap with adjacent floats. Now we need to add them. - LogicalSize child_available_size = { - (opportunity.rect.InlineSize() - inline_negative_margin + inline_margin) - .ClampNegativeToZero(), - child_available_size_.block_size}; + LayoutUnit child_available_inline_size = + (opportunity_size + child_data.margins.InlineSum()) + .ClampNegativeToZero(); + NGConstraintSpace child_space = CreateConstraintSpaceForChild( - child, child_data, child_available_size, /* is_new_fc */ true); + child, child_data, + {child_available_inline_size, child_available_size_.block_size}, + /* is_new_fc */ true); // All formatting context roots (like this child) should start with an empty // exclusion space. @@ -1281,18 +1240,54 @@ // should be returned. DCHECK(layout_result->ExclusionSpace().IsEmpty()); - NGFragment fragment(ConstraintSpace().GetWritingMode(), - layout_result->PhysicalFragment()); + NGFragment fragment(writing_mode, layout_result->PhysicalFragment()); - // Now we can check if the fragment will fit in this layout opportunity. - if ((opportunity.rect.InlineSize() >= fragment.InlineSize() || - opportunity.rect.InlineSize() == inline_size) && - opportunity.rect.BlockSize() >= fragment.BlockSize()) - return std::make_pair(std::move(layout_result), opportunity); + // Check if the fragment will fit in this layout opportunity, if not proceed + // to the next opportunity. + if ((fragment.InlineSize() > opportunity.rect.InlineSize() && + !can_expand_outside_opportunity) || + fragment.BlockSize() > opportunity.rect.BlockSize()) + continue; + + // Now find the fragment's (final) position calculating the auto margins. + NGBoxStrut auto_margins = child_data.margins; + if (child.IsListMarker()) { + // Deal with marker's margin. It happens only when marker needs to occupy + // the whole line. + DCHECK(child.ListMarkerOccupiesWholeLine()); + // Because the marker is laid out as a normal block child, its inline + // size is extended to fill up the space. Compute the regular marker size + // from the first child. + const auto& marker_fragment = layout_result->PhysicalFragment(); + LayoutUnit marker_inline_size; + if (!marker_fragment.Children().empty()) { + marker_inline_size = + NGFragment(writing_mode, *marker_fragment.Children().front()) + .InlineSize(); + } + auto_margins.inline_start = + NGUnpositionedListMarker(To<NGBlockNode>(child)) + .InlineOffset(marker_inline_size); + auto_margins.inline_end = opportunity.rect.InlineSize() - + fragment.InlineSize() - + auto_margins.inline_start; + } else { + ResolveInlineMargins(child_style, Style(), child_available_inline_size, + fragment.InlineSize(), &auto_margins); + } + + // |auto_margins| are initialized as a copy of the child's initial margins. + // To determine the effect of the auto-margins we only apply the difference. + LayoutUnit auto_margin_line_left = + auto_margins.LineLeft(direction) - line_left_margin; + + *out_child_bfc_offset = {line_left_offset + auto_margin_line_left, + opportunity.rect.start_offset.block_offset}; + return layout_result; } NOTREACHED(); - return std::make_pair(nullptr, NGLayoutOpportunity()); + return nullptr; } bool NGBlockLayoutAlgorithm::HandleInflow(
diff --git a/third_party/blink/renderer/core/layout/ng/ng_block_layout_algorithm.h b/third_party/blink/renderer/core/layout/ng/ng_block_layout_algorithm.h index 8f98f60..edd2d5b9 100644 --- a/third_party/blink/renderer/core/layout/ng/ng_block_layout_algorithm.h +++ b/third_party/blink/renderer/core/layout/ng/ng_block_layout_algorithm.h
@@ -173,12 +173,13 @@ // Performs the actual layout of a new formatting context. This may be called // multiple times from HandleNewFormattingContext. - std::pair<scoped_refptr<const NGLayoutResult>, NGLayoutOpportunity> - LayoutNewFormattingContext(NGLayoutInputNode child, - const NGBreakToken* child_break_token, - const NGInflowChildData&, - NGBfcOffset origin_offset, - bool abort_if_cleared); + scoped_refptr<const NGLayoutResult> LayoutNewFormattingContext( + NGLayoutInputNode child, + const NGBreakToken* child_break_token, + const NGInflowChildData&, + NGBfcOffset origin_offset, + bool abort_if_cleared, + NGBfcOffset* out_child_bfc_offset); // Handle an in-flow child. // Returns false if we need to abort layout, because a previously unknown BFC
diff --git a/third_party/blink/renderer/core/loader/empty_clients.h b/third_party/blink/renderer/core/loader/empty_clients.h index 75161db..22c752ec 100644 --- a/third_party/blink/renderer/core/loader/empty_clients.h +++ b/third_party/blink/renderer/core/loader/empty_clients.h
@@ -169,7 +169,8 @@ bool TabsToLinks() override { return false; } void InvalidateRect(const IntRect&) override {} - void ScheduleAnimation(const LocalFrameView*) override {} + void ScheduleAnimation(const LocalFrameView*, + base::TimeDelta = base::TimeDelta()) override {} IntRect ViewportToScreen(const IntRect& r, const LocalFrameView*) const override {
diff --git a/third_party/blink/renderer/core/page/chrome_client.h b/third_party/blink/renderer/core/page/chrome_client.h index 4e051c2..51e7258 100644 --- a/third_party/blink/renderer/core/page/chrome_client.h +++ b/third_party/blink/renderer/core/page/chrome_client.h
@@ -126,7 +126,8 @@ virtual IntRect ViewportToScreen(const IntRect&, const LocalFrameView*) const = 0; - virtual void ScheduleAnimation(const LocalFrameView*) = 0; + virtual void ScheduleAnimation(const LocalFrameView*, + base::TimeDelta = base::TimeDelta()) = 0; // The specified rectangle is adjusted for the minimum window size and the // screen, then setWindowRect with the adjusted rectangle is called.
diff --git a/third_party/blink/renderer/core/page/chrome_client_impl.cc b/third_party/blink/renderer/core/page/chrome_client_impl.cc index 6d90e9c..8d8deb9 100644 --- a/third_party/blink/renderer/core/page/chrome_client_impl.cc +++ b/third_party/blink/renderer/core/page/chrome_client_impl.cc
@@ -429,7 +429,8 @@ web_view_->InvalidateRect(update_rect); } -void ChromeClientImpl::ScheduleAnimation(const LocalFrameView* frame_view) { +void ChromeClientImpl::ScheduleAnimation(const LocalFrameView* frame_view, + base::TimeDelta delay) { LocalFrame& frame = frame_view->GetFrame(); WebLocalFrameImpl* web_frame = WebLocalFrameImpl::FromFrame(frame); DCHECK(web_frame); @@ -440,9 +441,13 @@ // WebFrameWidget needs to be initialized before initializing the core frame? WebFrameWidgetBase* widget = web_frame->LocalRootFrameWidget(); if (widget) { - // LocalRootFrameWidget() is a WebWidget, its client is the embedder. - WebWidgetClient* web_widget_client = widget->Client(); - web_widget_client->ScheduleAnimation(); + if (delay.is_zero()) { + // LocalRootFrameWidget() is a WebWidget, its client is the embedder. + WebWidgetClient* web_widget_client = widget->Client(); + web_widget_client->ScheduleAnimation(); + } else { + widget->RequestAnimationAfterDelay(delay); + } } }
diff --git a/third_party/blink/renderer/core/page/chrome_client_impl.h b/third_party/blink/renderer/core/page/chrome_client_impl.h index faca220..1754fe8 100644 --- a/third_party/blink/renderer/core/page/chrome_client_impl.h +++ b/third_party/blink/renderer/core/page/chrome_client_impl.h
@@ -120,7 +120,8 @@ String& result) override; bool TabsToLinks() override; void InvalidateRect(const IntRect&) override; - void ScheduleAnimation(const LocalFrameView*) override; + void ScheduleAnimation(const LocalFrameView*, + base::TimeDelta = base::TimeDelta()) override; IntRect ViewportToScreen(const IntRect&, const LocalFrameView*) const override; float WindowToViewportScalar(const float) const override;
diff --git a/third_party/blink/renderer/core/page/validation_message_overlay_delegate.cc b/third_party/blink/renderer/core/page/validation_message_overlay_delegate.cc index 9aac603..80e376e4 100644 --- a/third_party/blink/renderer/core/page/validation_message_overlay_delegate.cc +++ b/third_party/blink/renderer/core/page/validation_message_overlay_delegate.cc
@@ -40,11 +40,12 @@ EmptyChromeClient::Trace(visitor); } - void ScheduleAnimation(const LocalFrameView*) override { + void ScheduleAnimation(const LocalFrameView*, + base::TimeDelta delay = base::TimeDelta()) override { // Need to pass LocalFrameView for the anchor element because the Frame for // this overlay doesn't have an associated WebFrameWidget, which schedules // animation. - main_chrome_client_->ScheduleAnimation(anchor_view_); + main_chrome_client_->ScheduleAnimation(anchor_view_, delay); } float WindowToViewportScalar(const float scalar_value) const override {
diff --git a/third_party/blink/renderer/core/style/computed_style.h b/third_party/blink/renderer/core/style/computed_style.h index a820923..c94a0d5 100644 --- a/third_party/blink/renderer/core/style/computed_style.h +++ b/third_party/blink/renderer/core/style/computed_style.h
@@ -488,7 +488,7 @@ // border-image-source StyleImage* BorderImageSource() const { return BorderImage().GetImage(); } - void SetBorderImageSource(StyleImage*); + CORE_EXPORT void SetBorderImageSource(StyleImage*); // border-image-width const BorderImageLengthBox& BorderImageWidth() const {
diff --git a/third_party/blink/renderer/core/svg/graphics/svg_image_chrome_client.cc b/third_party/blink/renderer/core/svg/graphics/svg_image_chrome_client.cc index 8389427..eba9f3f 100644 --- a/third_party/blink/renderer/core/svg/graphics/svg_image_chrome_client.cc +++ b/third_party/blink/renderer/core/svg/graphics/svg_image_chrome_client.cc
@@ -91,7 +91,8 @@ image_->RestoreAnimation(); } -void SVGImageChromeClient::ScheduleAnimation(const LocalFrameView*) { +void SVGImageChromeClient::ScheduleAnimation(const LocalFrameView*, + base::TimeDelta fire_time) { // Because a single SVGImage can be shared by multiple pages, we can't key // our svg image layout on the page's real animation frame. Therefore, we // run this fake animation timer to trigger layout in SVGImages. The name, @@ -103,11 +104,11 @@ // animations, but prefer a fixed, jittery, frame-delay if there're any // animations. Checking for pending/active animations could be more // stringent. - base::TimeDelta fire_time; if (image_->MaybeAnimated()) { if (IsSuspended()) return; - fire_time = kAnimationFrameDelay; + if (fire_time.is_zero()) + fire_time = kAnimationFrameDelay; } animation_timer_->StartOneShot(fire_time, FROM_HERE); }
diff --git a/third_party/blink/renderer/core/svg/graphics/svg_image_chrome_client.h b/third_party/blink/renderer/core/svg/graphics/svg_image_chrome_client.h index ead7000f..6460951 100644 --- a/third_party/blink/renderer/core/svg/graphics/svg_image_chrome_client.h +++ b/third_party/blink/renderer/core/svg/graphics/svg_image_chrome_client.h
@@ -56,7 +56,8 @@ private: void ChromeDestroyed() override; void InvalidateRect(const IntRect&) override; - void ScheduleAnimation(const LocalFrameView*) override; + void ScheduleAnimation(const LocalFrameView*, + base::TimeDelta = base::TimeDelta()) override; void SetTimer(std::unique_ptr<TimerBase>); TimerBase* GetTimerForTesting() const { return animation_timer_.get(); }
diff --git a/third_party/blink/renderer/devtools/front_end/console/ConsoleView.js b/third_party/blink/renderer/devtools/front_end/console/ConsoleView.js index f07fec7..d7ab2c1 100644 --- a/third_party/blink/renderer/devtools/front_end/console/ConsoleView.js +++ b/third_party/blink/renderer/devtools/front_end/console/ConsoleView.js
@@ -1238,7 +1238,7 @@ const filterKeys = Object.values(Console.ConsoleFilter.FilterType); this._suggestionBuilder = new UI.FilterSuggestionBuilder(filterKeys); this._textFilterUI = new UI.ToolbarInput( - Common.UIString('Filter'), 0.2, 1, Common.UIString('e.g. /event\\d/ -cdn url:a.com'), + Common.UIString('Filter'), '', 0.2, 1, Common.UIString('e.g. /event\\d/ -cdn url:a.com'), this._suggestionBuilder.completions.bind(this._suggestionBuilder)); this._textFilterSetting = Common.settings.createSetting('console.textFilter', ''); if (this._textFilterSetting.get())
diff --git a/third_party/blink/renderer/devtools/front_end/coverage/CoverageView.js b/third_party/blink/renderer/devtools/front_end/coverage/CoverageView.js index 3ecb51a..ba45c2eb 100644 --- a/third_party/blink/renderer/devtools/front_end/coverage/CoverageView.js +++ b/third_party/blink/renderer/devtools/front_end/coverage/CoverageView.js
@@ -42,7 +42,7 @@ /** @type {?RegExp} */ this._textFilterRegExp = null; toolbar.appendSeparator(); - this._filterInput = new UI.ToolbarInput(Common.UIString('URL filter'), 0.4, 1); + this._filterInput = new UI.ToolbarInput(Common.UIString('URL filter'), '', 0.4, 1); this._filterInput.setEnabled(false); this._filterInput.addEventListener(UI.ToolbarInput.Event.TextChanged, this._onFilterChanged, this); toolbar.appendToolbarItem(this._filterInput);
diff --git a/third_party/blink/renderer/devtools/front_end/heap_snapshot_worker/HeapSnapshot.js b/third_party/blink/renderer/devtools/front_end/heap_snapshot_worker/HeapSnapshot.js index dc0d8b3b..cfa160b 100644 --- a/third_party/blink/renderer/devtools/front_end/heap_snapshot_worker/HeapSnapshot.js +++ b/third_party/blink/renderer/devtools/front_end/heap_snapshot_worker/HeapSnapshot.js
@@ -912,34 +912,34 @@ this._firstDominatedNodeIndex = new Uint32Array(this.nodeCount + 1); this._dominatedNodes = new Uint32Array(this.nodeCount - 1); - this._progress.updateStatus('Building edge indexes\u2026'); + this._progress.updateStatus(ls`Building edge indexes\u2026`); this._buildEdgeIndexes(); - this._progress.updateStatus('Building retainers\u2026'); + this._progress.updateStatus(ls`Building retainers\u2026`); this._buildRetainers(); - this._progress.updateStatus('Calculating node flags\u2026'); + this._progress.updateStatus(ls`Calculating node flags\u2026`); this.calculateFlags(); - this._progress.updateStatus('Calculating distances\u2026'); + this._progress.updateStatus(ls`Calculating distances\u2026`); this.calculateDistances(); - this._progress.updateStatus('Building postorder index\u2026'); + this._progress.updateStatus(ls`Building postorder index\u2026`); const result = this._buildPostOrderIndex(); // Actually it is array that maps node ordinal number to dominator node ordinal number. - this._progress.updateStatus('Building dominator tree\u2026'); + this._progress.updateStatus(ls`Building dominator tree\u2026`); this._dominatorsTree = this._buildDominatorTree(result.postOrderIndex2NodeOrdinal, result.nodeOrdinal2PostOrderIndex); - this._progress.updateStatus('Calculating retained sizes\u2026'); + this._progress.updateStatus(ls`Calculating retained sizes\u2026`); this._calculateRetainedSizes(result.postOrderIndex2NodeOrdinal); - this._progress.updateStatus('Building dominated nodes\u2026'); + this._progress.updateStatus(ls`Building dominated nodes\u2026`); this._buildDominatedNodes(); - this._progress.updateStatus('Calculating statistics\u2026'); + this._progress.updateStatus(ls`Calculating statistics\u2026`); this.calculateStatistics(); - this._progress.updateStatus('Calculating samples\u2026'); + this._progress.updateStatus(ls`Calculating samples\u2026`); this._buildSamples(); - this._progress.updateStatus('Building locations\u2026'); + this._progress.updateStatus(ls`Building locations\u2026`); this._buildLocationMap(); - this._progress.updateStatus('Finished processing.'); + this._progress.updateStatus(ls`Finished processing.`); if (this._profile.snapshot.trace_function_count) { - this._progress.updateStatus('Building allocation statistics\u2026'); + this._progress.updateStatus(ls`Building allocation statistics\u2026`); const nodes = this.nodes; const nodesLength = nodes.length; const nodeFieldCount = this._nodeFieldCount; @@ -956,7 +956,7 @@ stats.ids.push(node.id()); } this._allocationProfile = new HeapSnapshotWorker.AllocationProfile(this._profile, liveObjects); - this._progress.updateStatus('Done'); + this._progress.updateStatus(ls`Done`); } }
diff --git a/third_party/blink/renderer/devtools/front_end/heap_snapshot_worker/HeapSnapshotLoader.js b/third_party/blink/renderer/devtools/front_end/heap_snapshot_worker/HeapSnapshotLoader.js index b7dd4f87..84bc429 100644 --- a/third_party/blink/renderer/devtools/front_end/heap_snapshot_worker/HeapSnapshotLoader.js +++ b/third_party/blink/renderer/devtools/front_end/heap_snapshot_worker/HeapSnapshotLoader.js
@@ -109,7 +109,7 @@ } _parseStringsArray() { - this._progress.updateStatus('Parsing strings\u2026'); + this._progress.updateStatus(ls`Parsing strings\u2026`); const closingBracketIndex = this._json.lastIndexOf(']'); if (closingBracketIndex === -1) throw new Error('Incomplete JSON');
diff --git a/third_party/blink/renderer/devtools/front_end/heap_snapshot_worker/heap_snapshot_worker_strings.grdp b/third_party/blink/renderer/devtools/front_end/heap_snapshot_worker/heap_snapshot_worker_strings.grdp index bea64f4..db239fb 100644 --- a/third_party/blink/renderer/devtools/front_end/heap_snapshot_worker/heap_snapshot_worker_strings.grdp +++ b/third_party/blink/renderer/devtools/front_end/heap_snapshot_worker/heap_snapshot_worker_strings.grdp
@@ -1,27 +1,72 @@ <?xml version="1.0" encoding="utf-8"?> <grit-part> + <message name="IDS_DEVTOOLS_0f705e2ea0d470cf4e78f85ce73abc3c" desc="Text to indicate the status of a heap snapshot in the Performance Pane"> + Calculating samples… + </message> + <message name="IDS_DEVTOOLS_15e828e7c9470740e5da2bd96f26809f" desc="Text to indicate the status of a heap snapshot in the Performance Pane"> + Building locations… + </message> + <message name="IDS_DEVTOOLS_1e6dbaafd43ee6c7ce436757c5563160" desc="Text to indicate the status of a heap snapshot in the Performance Pane"> + Building retainers… + </message> <message name="IDS_DEVTOOLS_239026e523e6f9780426e03637c5b4a4" desc="Text in Heap Snapshot Loader of the Memory panel when taking a heap snapshot"> Loading strings… </message> + <message name="IDS_DEVTOOLS_42b1c19d788d56dae8f4274ae0e06388" desc="Text to indicate the status of a heap snapshot in the Performance Pane"> + Building dominated nodes… + </message> + <message name="IDS_DEVTOOLS_508b42300b35ed4e3062adf330b76aad" desc="Text to indicate the status of a heap snapshot in the Performance Pane"> + Building dominator tree… + </message> + <message name="IDS_DEVTOOLS_58d7770bfad35df21bae2d5820e3be52" desc="Text to indicate the status of a heap snapshot in the Performance Pane"> + Building edge indexes… + </message> <message name="IDS_DEVTOOLS_58e8a5ca400f834526b09d680ddbc5d5" desc="Text in Heap Snapshot Loader of the Memory panel when taking a heap snapshot"> Loading samples… </message> + <message name="IDS_DEVTOOLS_5e3a0ca620683b8428b4dbda33bf1f5d" desc="Text to indicate the status of a heap snapshot in the Performance Pane"> + Finished processing. + </message> <message name="IDS_DEVTOOLS_6a542856aa30e3e814eaed146e67b2fd" desc="Text in Heap Snapshot Loader of the Memory panel when taking a heap snapshot"> Loading nodes… <ph name="PH1">$1d<ex>38</ex></ph>%% </message> <message name="IDS_DEVTOOLS_7da2f27d62adf93b01c2c041f37667b9" desc="Text in Heap Snapshot Loader of the Memory panel when taking a heap snapshot"> Processing snapshot… </message> + <message name="IDS_DEVTOOLS_82e20e6748434e5048a36bf2d4b33578" desc="Text to indicate the status of a heap snapshot in the Performance Pane"> + Calculating retained sizes… + </message> <message name="IDS_DEVTOOLS_84c0ec1ee2bc769daf265e63bd793201" desc="Text in Heap Snapshot Loader of the Memory panel when taking a heap snapshot"> Loading snapshot info… </message> + <message name="IDS_DEVTOOLS_93093f55895541ab4360826523fe066e" desc="Text to indicate the status of a heap snapshot in the Performance Pane"> + Building postorder index… + </message> + <message name="IDS_DEVTOOLS_991feea6b04d59d7115962d5427a64fe" desc="Text to indicate the status of a heap snapshot in the Performance Pane"> + Calculating node flags… + </message> <message name="IDS_DEVTOOLS_9bdae72f224411b7f1027a2c5c7c519b" desc="Text in Heap Snapshot Loader of the Memory panel when taking a heap snapshot"> Loading locations… </message> <message name="IDS_DEVTOOLS_b0da59cea23d810234b75c2357748ad3" desc="Text in Heap Snapshot Loader of the Memory panel when taking a heap snapshot"> Loading edges… <ph name="PH1">$1d<ex>30</ex></ph>%% </message> + <message name="IDS_DEVTOOLS_bfb105e5a3da1a90bd1eb98b4fa36f3f" desc="Text to indicate the status of a heap snapshot in the Performance Pane"> + Calculating statistics… + </message> + <message name="IDS_DEVTOOLS_d0622d0589a212a59cf8b5859e58c670" desc="Text to indicate the status of a heap snapshot in the Performance Pane"> + Calculating distances… + </message> <message name="IDS_DEVTOOLS_d67d63eca2747a30e1ffaeb04389c0bb" desc="Text in Heap Snapshot Loader of the Memory panel when taking a heap snapshot"> Loading allocation traces… <ph name="PH1">$1d<ex>30</ex></ph>%% </message> + <message name="IDS_DEVTOOLS_d86c288a983db9a91432d2d13386170f" desc="Text to indicate the status of a heap snapshot in the Performance Pane"> + Building allocation statistics… + </message> + <message name="IDS_DEVTOOLS_f92965e2c8a7afb3c1b9a5c09a263636" desc="Text to indicate the status of a heap snapshot in the Performance Pane"> + Done + </message> + <message name="IDS_DEVTOOLS_fae03f5c27a9765eec716f3e6c600945" desc="Text to indicate the status of a heap snapshot in the Performance Pane"> + Parsing strings… + </message> </grit-part> \ No newline at end of file
diff --git a/third_party/blink/renderer/devtools/front_end/network/ResourceWebSocketFrameView.js b/third_party/blink/renderer/devtools/front_end/network/ResourceWebSocketFrameView.js index 71a180b..f8160fa1 100644 --- a/third_party/blink/renderer/devtools/front_end/network/ResourceWebSocketFrameView.js +++ b/third_party/blink/renderer/devtools/front_end/network/ResourceWebSocketFrameView.js
@@ -73,7 +73,7 @@ this._filterType = null; const placeholder = 'Enter regex, for example: (web)?socket'; - this._filterTextInput = new UI.ToolbarInput(Common.UIString(placeholder), 0.4); + this._filterTextInput = new UI.ToolbarInput(Common.UIString(placeholder), '', 0.4); this._filterTextInput.addEventListener(UI.ToolbarInput.Event.TextChanged, this._updateFilterSetting, this); this._mainToolbar.appendToolbarItem(this._filterTextInput); this._filterRegex = null;
diff --git a/third_party/blink/renderer/devtools/front_end/profiler/ProfileView.js b/third_party/blink/renderer/devtools/front_end/profiler/ProfileView.js index bc6d095..38f6a6e 100644 --- a/third_party/blink/renderer/devtools/front_end/profiler/ProfileView.js +++ b/third_party/blink/renderer/devtools/front_end/profiler/ProfileView.js
@@ -34,6 +34,7 @@ this.dataGrid.addEventListener(DataGrid.DataGrid.Events.DeselectedNode, this._nodeSelected.bind(this, false)); this.viewSelectComboBox = new UI.ToolbarComboBox(this._changeView.bind(this)); + this.viewSelectComboBox.setTitle(ls`Profile view mode`); this.focusButton = new UI.ToolbarButton(Common.UIString('Focus selected function'), 'largeicon-visibility'); this.focusButton.setEnabled(false);
diff --git a/third_party/blink/renderer/devtools/front_end/profiler/profiler_strings.grdp b/third_party/blink/renderer/devtools/front_end/profiler/profiler_strings.grdp index 9aa023fa..574fbcda 100644 --- a/third_party/blink/renderer/devtools/front_end/profiler/profiler_strings.grdp +++ b/third_party/blink/renderer/devtools/front_end/profiler/profiler_strings.grdp
@@ -181,6 +181,9 @@ <message name="IDS_DEVTOOLS_6db0d0f1832acb4a56fc82f2317e61e6" desc="Text in Profile View of a profiler tool"> Parsing… </message> + <message name="IDS_DEVTOOLS_6de06ad67fbc56af1a7a5b16a41d2f2c" desc="Aria-label for profiles view combobox in memory tool"> + Profile view mode + </message> <message name="IDS_DEVTOOLS_6e9dd9cf5419fd65f433f1e4bbc5e6ad" desc="Text in Heap Profile View of a profiler tool"> SAMPLING PROFILES </message>
diff --git a/third_party/blink/renderer/devtools/front_end/protocol_monitor/ProtocolMonitor.js b/third_party/blink/renderer/devtools/front_end/protocol_monitor/ProtocolMonitor.js index 2e32fc1..fb1ad72 100644 --- a/third_party/blink/renderer/devtools/front_end/protocol_monitor/ProtocolMonitor.js +++ b/third_party/blink/renderer/devtools/front_end/protocol_monitor/ProtocolMonitor.js
@@ -60,8 +60,8 @@ this._filterParser = new TextUtils.FilterParser(keys); this._suggestionBuilder = new UI.FilterSuggestionBuilder(keys); - this._textFilterUI = - new UI.ToolbarInput(ls`Filter`, 1, .2, '', this._suggestionBuilder.completions.bind(this._suggestionBuilder)); + this._textFilterUI = new UI.ToolbarInput( + ls`Filter`, '', 1, .2, '', this._suggestionBuilder.completions.bind(this._suggestionBuilder)); this._textFilterUI.addEventListener(UI.ToolbarInput.Event.TextChanged, event => { const query = /** @type {string} */ (event.data); const filters = this._filterParser.parse(query);
diff --git a/third_party/blink/renderer/devtools/front_end/resources/DatabaseTableView.js b/third_party/blink/renderer/devtools/front_end/resources/DatabaseTableView.js index 2fd959ea..b76d74c 100644 --- a/third_party/blink/renderer/devtools/front_end/resources/DatabaseTableView.js +++ b/third_party/blink/renderer/devtools/front_end/resources/DatabaseTableView.js
@@ -39,7 +39,7 @@ this.refreshButton = new UI.ToolbarButton(Common.UIString('Refresh'), 'largeicon-refresh'); this.refreshButton.addEventListener(UI.ToolbarButton.Events.Click, this._refreshButtonClicked, this); - this._visibleColumnsInput = new UI.ToolbarInput(Common.UIString('Visible columns'), 1); + this._visibleColumnsInput = new UI.ToolbarInput(Common.UIString('Visible columns'), '', 1); this._visibleColumnsInput.addEventListener(UI.ToolbarInput.Event.TextChanged, this._onVisibleColumnsChanged, this); }
diff --git a/third_party/blink/renderer/devtools/front_end/resources/IndexedDBViews.js b/third_party/blink/renderer/devtools/front_end/resources/IndexedDBViews.js index d0713123..02f383c 100644 --- a/third_party/blink/renderer/devtools/front_end/resources/IndexedDBViews.js +++ b/third_party/blink/renderer/devtools/front_end/resources/IndexedDBViews.js
@@ -222,7 +222,7 @@ this._pageForwardButton.addEventListener(UI.ToolbarButton.Events.Click, this._pageForwardButtonClicked, this); editorToolbar.appendToolbarItem(this._pageForwardButton); - this._keyInput = new UI.ToolbarInput(ls`Start from key`, 0.5); + this._keyInput = new UI.ToolbarInput(ls`Start from key`, '', 0.5); this._keyInput.addEventListener(UI.ToolbarInput.Event.TextChanged, this._updateData.bind(this, false)); editorToolbar.appendToolbarItem(this._keyInput); editorToolbar.appendToolbarItem(new UI.ToolbarSeparator());
diff --git a/third_party/blink/renderer/devtools/front_end/resources/ServiceWorkerCacheViews.js b/third_party/blink/renderer/devtools/front_end/resources/ServiceWorkerCacheViews.js index 8b29e4a..89fb6e9 100644 --- a/third_party/blink/renderer/devtools/front_end/resources/ServiceWorkerCacheViews.js +++ b/third_party/blink/renderer/devtools/front_end/resources/ServiceWorkerCacheViews.js
@@ -55,7 +55,7 @@ this._deleteSelectedButton.addEventListener(UI.ToolbarButton.Events.Click, () => this._deleteButtonClicked(null)); editorToolbar.appendToolbarItem(this._deleteSelectedButton); - const entryPathFilterBox = new UI.ToolbarInput(ls`Filter by Path`, 1); + const entryPathFilterBox = new UI.ToolbarInput(ls`Filter by Path`, '', 1); editorToolbar.appendToolbarItem(entryPathFilterBox); const entryPathFilterThrottler = new Common.Throttler(300); this._entryPathFilter = '';
diff --git a/third_party/blink/renderer/devtools/front_end/resources/ServiceWorkersView.js b/third_party/blink/renderer/devtools/front_end/resources/ServiceWorkersView.js index 9dc6f28..3a96d898 100644 --- a/third_party/blink/renderer/devtools/front_end/resources/ServiceWorkersView.js +++ b/third_party/blink/renderer/devtools/front_end/resources/ServiceWorkersView.js
@@ -43,7 +43,7 @@ }); const toolbar = new UI.Toolbar('service-worker-filter-toolbar', this._otherSWFilter); - this._filter = new UI.ToolbarInput(ls`Filter service worker`, 1); + this._filter = new UI.ToolbarInput(ls`Filter service worker`, '', 1); this._filter.addEventListener(UI.ToolbarInput.Event.TextChanged, () => this._filterChanged()); toolbar.appendToolbarItem(this._filter);
diff --git a/third_party/blink/renderer/devtools/front_end/resources/StorageItemsView.js b/third_party/blink/renderer/devtools/front_end/resources/StorageItemsView.js index 9137521..635cd24b 100644 --- a/third_party/blink/renderer/devtools/front_end/resources/StorageItemsView.js +++ b/third_party/blink/renderer/devtools/front_end/resources/StorageItemsView.js
@@ -16,7 +16,7 @@ this._mainToolbar = new UI.Toolbar('top-resources-toolbar', this.element); - this._filterItem = new UI.ToolbarInput(Common.UIString('Filter'), 0.4); + this._filterItem = new UI.ToolbarInput(Common.UIString('Filter'), '', 0.4); this._filterItem.addEventListener(UI.ToolbarInput.Event.TextChanged, this._filterChanged, this); const toolbarSeparator = new UI.ToolbarSeparator();
diff --git a/third_party/blink/renderer/devtools/front_end/timeline/EventsTimelineTreeView.js b/third_party/blink/renderer/devtools/front_end/timeline/EventsTimelineTreeView.js index 48d94ae9..9a3e6ff 100644 --- a/third_party/blink/renderer/devtools/front_end/timeline/EventsTimelineTreeView.js +++ b/third_party/blink/renderer/devtools/front_end/timeline/EventsTimelineTreeView.js
@@ -45,6 +45,14 @@ /** * @override + * @return {string} + */ + getToolbarInputAccessiblePlaceHolder() { + return ls`Filter event log`; + } + + /** + * @override * @return {!TimelineModel.TimelineProfileTree.Node} */ _buildTree() {
diff --git a/third_party/blink/renderer/devtools/front_end/timeline/TimelineTreeView.js b/third_party/blink/renderer/devtools/front_end/timeline/TimelineTreeView.js index 7f93e22..2815c593 100644 --- a/third_party/blink/renderer/devtools/front_end/timeline/TimelineTreeView.js +++ b/third_party/blink/renderer/devtools/front_end/timeline/TimelineTreeView.js
@@ -48,6 +48,13 @@ } /** + * @return {string} + */ + getToolbarInputAccessiblePlaceHolder() { + return ''; + } + + /** * @protected * @return {?Timeline.PerformanceModel} model */ @@ -156,7 +163,7 @@ * @param {!UI.Toolbar} toolbar */ populateToolbar(toolbar) { - this._textFilterUI = new UI.ToolbarInput(Common.UIString('Filter')); + this._textFilterUI = new UI.ToolbarInput(Common.UIString('Filter'), this.getToolbarInputAccessiblePlaceHolder()); this._textFilterUI.addEventListener(UI.ToolbarInput.Event.TextChanged, textFilterChanged, this); toolbar.appendToolbarItem(this._textFilterUI); @@ -253,6 +260,9 @@ this._updateDetailsForSelection(); if (this._searchableView) this._searchableView.refreshSearch(); + const rootNode = this._dataGrid.rootNode(); + if (rootNode.children.length > 0) + rootNode.children[0].select(); } /** @@ -396,10 +406,11 @@ * @param {!DataGrid.DataGridNode} gridNode */ _onContextMenu(contextMenu, gridNode) { + if (gridNode._linkElement && !contextMenu.containsTarget(gridNode._linkElement)) + contextMenu.appendApplicableItems(gridNode._linkElement); const profileNode = gridNode._profileNode; - if (!profileNode) - return; - this._appendContextMenuItems(contextMenu, profileNode); + if (profileNode) + this._appendContextMenuItems(contextMenu, profileNode); } /** @@ -494,6 +505,7 @@ this._grandTotalTime = grandTotalTime; this._maxSelfTime = maxSelfTime; this._maxTotalTime = maxTotalTime; + this._linkElement = null; } /** @@ -532,10 +544,13 @@ container.createChild('div', 'activity-warning').title = Common.UIString('Not optimized: %s', deoptReason); name.textContent = Timeline.TimelineUIUtils.eventTitle(event); - const link = this._treeView._linkifyLocation(event); - if (link) - container.createChild('div', 'activity-link').appendChild(link); - icon.style.backgroundColor = Timeline.TimelineUIUtils.eventColor(event); + this._linkElement = this._treeView._linkifyLocation(event); + if (this._linkElement) + container.createChild('div', 'activity-link').appendChild(this._linkElement); + const eventStyle = Timeline.TimelineUIUtils.eventStyle(event); + const eventCategory = eventStyle.category; + UI.ARIAUtils.setAccessibleName(icon, eventCategory.title); + icon.style.backgroundColor = eventCategory.color; } return cell; } @@ -665,7 +680,7 @@ super.updateContents(selection); const rootNode = this._dataGrid.rootNode(); if (rootNode.children.length) - rootNode.children[0].revealAndSelect(); + rootNode.children[0].select(); } _updateExtensionResolver() { @@ -772,7 +787,8 @@ {label: Common.UIString('Group by Subdomain'), value: groupBy.Subdomain}, {label: Common.UIString('Group by URL'), value: groupBy.URL}, ]; - toolbar.appendToolbarItem(new UI.ToolbarSettingComboBox(options, this._groupBySetting)); + toolbar.appendToolbarItem( + new UI.ToolbarSettingComboBox(options, this._groupBySetting, undefined /* optGroup */, ls`Group by`)); toolbar.appendSpacer(); toolbar.appendToolbarItem(this._splitWidget.createShowHideSidebarButton(Common.UIString('heaviest stack'))); } @@ -972,6 +988,14 @@ /** * @override + * @return {string} + */ + getToolbarInputAccessiblePlaceHolder() { + return ls`Filter call tree`; + } + + /** + * @override * @return {!TimelineModel.TimelineProfileTree.Node} */ _buildTree() { @@ -991,6 +1015,14 @@ /** * @override + * @return {string} + */ + getToolbarInputAccessiblePlaceHolder() { + return ls`Filter bottom-up`; + } + + /** + * @override * @return {!TimelineModel.TimelineProfileTree.Node} */ _buildTree() {
diff --git a/third_party/blink/renderer/devtools/front_end/timeline/timeline_strings.grdp b/third_party/blink/renderer/devtools/front_end/timeline/timeline_strings.grdp index a508ae8..389883b 100644 --- a/third_party/blink/renderer/devtools/front_end/timeline/timeline_strings.grdp +++ b/third_party/blink/renderer/devtools/front_end/timeline/timeline_strings.grdp
@@ -69,6 +69,9 @@ <message name="IDS_DEVTOOLS_08db5f30f625a406882862b8a29b1bc6" desc="Text in Timeline UIUtils of the Performance panel"> Major GC </message> + <message name="IDS_DEVTOOLS_099ca81d7a70c42447d89e172198ba5d" desc="Aria-label for filter bar in Event Log view"> + Filter event log + </message> <message name="IDS_DEVTOOLS_09d66464ad53e6080988ad30824ea023" desc="Text in Timeline Flame Chart Data Provider of the Performance panel"> Frame — <ph name="TRACK_URL">$1s<ex>https://example.com</ex></ph> </message> @@ -424,6 +427,9 @@ <message name="IDS_DEVTOOLS_66f1aed235ade25269a561e81cbbb43a" desc="Text in Timeline UIUtils of the Performance panel"> Scripting </message> + <message name="IDS_DEVTOOLS_6734ebb8322bff404034f6ebbcc0d2fb" desc="Aria-label for filter bar in Call Tree view"> + Filter call tree + </message> <message name="IDS_DEVTOOLS_67eed98f4bc75c4ab261b79a0e2c52cd" desc="Text in Timeline UIUtils of the Performance panel"> Cache Rejected </message> @@ -717,6 +723,9 @@ <message name="IDS_DEVTOOLS_be85f6b3661854c85ddbde4c1429b2a2" desc="Text in Timeline UIUtils of the Performance panel"> (<ph name="CLIP___">$1s<ex>2</ex></ph>, <ph name="CLIP___">$2s<ex>2</ex></ph>) </message> + <message name="IDS_DEVTOOLS_be87d8c3de2675bbc53f9442af9d8feb" desc="Aria-label for grouping combo box in Timeline Details View"> + Group by + </message> <message name="IDS_DEVTOOLS_be97c5beb33f5316b2c221bfbb95852b" desc="Text in Timeline UIUtils of the Performance panel"> MIME Type </message> @@ -810,6 +819,9 @@ <message name="IDS_DEVTOOLS_d5f967961bccf06a9eb7989d69d94a15" desc="Text in Timeline UIUtils of the Performance panel"> network transfer </message> + <message name="IDS_DEVTOOLS_d6ef31f5b235ec815c3b62fc6f236804" desc="Aria-label for the filter bar in Bottom-Up view"> + Filter bottom-up + </message> <message name="IDS_DEVTOOLS_d84fe3f1d290e4855cc0487b5ea18a4a" desc="Text in Timeline UIUtils of the Performance panel"> Pinch Begin </message>
diff --git a/third_party/blink/renderer/devtools/front_end/ui/ContextMenu.js b/third_party/blink/renderer/devtools/front_end/ui/ContextMenu.js index 3aded96..69b9b89 100644 --- a/third_party/blink/renderer/devtools/front_end/ui/ContextMenu.js +++ b/third_party/blink/renderer/devtools/front_end/ui/ContextMenu.js
@@ -499,6 +499,14 @@ /** * @param {!Object} target + * @return {boolean} + */ + containsTarget(target) { + return this._pendingTargets.indexOf(target) >= 0; + } + + /** + * @param {!Object} target */ appendApplicableItems(target) { this._pendingPromises.push(self.runtime.allInstances(UI.ContextMenu.Provider, target));
diff --git a/third_party/blink/renderer/devtools/front_end/ui/TabbedPane.js b/third_party/blink/renderer/devtools/front_end/ui/TabbedPane.js index 6c4aae4..84c71d1 100644 --- a/third_party/blink/renderer/devtools/front_end/ui/TabbedPane.js +++ b/third_party/blink/renderer/devtools/front_end/ui/TabbedPane.js
@@ -308,9 +308,10 @@ /** * @param {string} id * @param {boolean=} userGesture + * @param {boolean=} forceFocus * @return {boolean} */ - selectTab(id, userGesture) { + selectTab(id, userGesture, forceFocus) { if (this._currentTabLocked) return false; const focused = this._viewHasFocus(); @@ -330,7 +331,7 @@ this._tabsHistory.splice(0, 0, tab); this._updateTabElements(); - if (focused) + if (focused || forceFocus) this.focus(); const eventData = {tabId: id, view: tab.view, isUserGesture: userGesture}; @@ -603,7 +604,7 @@ */ _dropDownMenuItemSelected(tab) { this._lastSelectedOverflowTab = tab; - this.selectTab(tab.id, true); + this.selectTab(tab.id, true, true); } _totalWidth() {
diff --git a/third_party/blink/renderer/devtools/front_end/ui/Toolbar.js b/third_party/blink/renderer/devtools/front_end/ui/Toolbar.js index 8434b8b..5882bdf 100644 --- a/third_party/blink/renderer/devtools/front_end/ui/Toolbar.js +++ b/third_party/blink/renderer/devtools/front_end/ui/Toolbar.js
@@ -558,12 +558,13 @@ UI.ToolbarInput = class extends UI.ToolbarItem { /** * @param {string} placeholder + * @param {string=} accessiblePlaceholder * @param {number=} growFactor * @param {number=} shrinkFactor * @param {string=} tooltip * @param {(function(string, string, boolean=):!Promise<!UI.SuggestBox.Suggestions>)=} completions */ - constructor(placeholder, growFactor, shrinkFactor, tooltip, completions) { + constructor(placeholder, accessiblePlaceholder, growFactor, shrinkFactor, tooltip, completions) { super(createElementWithClass('div', 'toolbar-input')); const internalPromptElement = this.element.createChild('div', 'toolbar-input-prompt'); @@ -577,7 +578,7 @@ this._prompt.initialize(completions || (() => Promise.resolve([])), ' '); if (tooltip) this._prompt.setTitle(tooltip); - this._prompt.setPlaceholder(placeholder); + this._prompt.setPlaceholder(placeholder, accessiblePlaceholder); this._prompt.addEventListener(UI.TextPrompt.Events.TextChanged, this._onChangeCallback.bind(this)); if (growFactor) @@ -971,12 +972,15 @@ * @param {!Array<!{value: string, label: string}>} options * @param {!Common.Setting} setting * @param {string=} optGroup + * @param {string=} accessibleName */ - constructor(options, setting, optGroup) { + constructor(options, setting, optGroup, accessibleName) { super(null); this._setting = setting; this._options = options; this._selectElement.addEventListener('change', this._valueChanged.bind(this), false); + if (accessibleName) + UI.ARIAUtils.setAccessibleName(this._selectElement, accessibleName); if (optGroup) { const optGroupElement = this._selectElement.createChild('optgroup'); optGroupElement.label = optGroup;
diff --git a/third_party/blink/renderer/devtools/scripts/check_localizable_resources.js b/third_party/blink/renderer/devtools/scripts/check_localizable_resources.js index 50e1019..21e37366 100644 --- a/third_party/blink/renderer/devtools/scripts/check_localizable_resources.js +++ b/third_party/blink/renderer/devtools/scripts/check_localizable_resources.js
@@ -33,7 +33,7 @@ if (shouldAutoFix) await autofix(error); else - await getErrors(error); + getErrors(); } catch (e) { console.log(e.stack); console.log(`Error: ${e.message}`); @@ -43,11 +43,12 @@ main(); -async function getErrors(existingError) { - const toAddError = await checkLocalizedStrings.getAndReportResourcesToAdd(); +function getErrors(existingError) { + const toAddError = checkLocalizedStrings.getAndReportResourcesToAdd(); const toModifyError = checkLocalizedStrings.getAndReportIDSKeysToModify(); const toRemoveError = checkLocalizedStrings.getAndReportResourcesToRemove(); - let error = `${existingError}\n${toAddError || ''}${toModifyError || ''}${toRemoveError || ''}`; + let error = + `${existingError ? `${existingError}\n` : ''}${toAddError || ''}${toModifyError || ''}${toRemoveError || ''}`; if (error === '') { console.log('DevTools localizable resources checker passed.');
diff --git a/third_party/blink/renderer/devtools/scripts/localization_utils/check_localized_strings.js b/third_party/blink/renderer/devtools/scripts/localization_utils/check_localized_strings.js index ab4d65a..90dd6b6 100644 --- a/third_party/blink/renderer/devtools/scripts/localization_utils/check_localized_strings.js +++ b/third_party/blink/renderer/devtools/scripts/localization_utils/check_localized_strings.js
@@ -188,6 +188,12 @@ * Parse localizable resources. */ async function parseLocalizableResourceMaps() { + if (frontendStrings.size === 0 && IDSkeys.size === 0) + await parseLocalizableResourceMapsHelper(); + return [frontendStrings, IDSkeys]; +} + +async function parseLocalizableResourceMapsHelper() { const grdpToFiles = new Map(); const dirs = devtoolsFrontendDirs || await localizationUtils.getChildDirectoriesFromDirectory(devtoolsFrontendPath); const grdpToFilesPromises = dirs.map(dir => { @@ -485,7 +491,7 @@ * with grdp <message>s and report error of resources to add, * remove or modify. */ -async function getAndReportResourcesToAdd() { +function getAndReportResourcesToAdd() { const keysToAddToGRD = getMessagesToAdd(); if (keysToAddToGRD.size === 0) return; @@ -625,8 +631,6 @@ } module.exports = { - frontendStrings, - IDSkeys, parseLocalizableResourceMaps, getAndReportIDSKeysToModify, getAndReportResourcesToAdd,
diff --git a/third_party/blink/renderer/modules/accessibility/ax_object.cc b/third_party/blink/renderer/modules/accessibility/ax_object.cc index f39a8c7..f9e7f73 100644 --- a/third_party/blink/renderer/modules/accessibility/ax_object.cc +++ b/third_party/blink/renderer/modules/accessibility/ax_object.cc
@@ -56,6 +56,7 @@ #include "third_party/blink/renderer/modules/accessibility/ax_range.h" #include "third_party/blink/renderer/modules/accessibility/ax_sparse_attribute_setter.h" #include "third_party/blink/renderer/platform/language.h" +#include "third_party/blink/renderer/platform/runtime_enabled_features.h" #include "third_party/blink/renderer/platform/text/platform_locale.h" #include "third_party/blink/renderer/platform/wtf/hash_set.h" #include "third_party/blink/renderer/platform/wtf/std_lib_extras.h" @@ -1213,16 +1214,29 @@ if (IsLineBreakingObject()) return true; - // Allow the browser side ax tree to access aria-hidden="true", "visibility: - // hidden", and "visibility: collapse" nodes. This is useful for APIs that - // return the node referenced by aria-labeledby and aria-describedby - if (GetLayoutObject()) { + // Allow the browser side ax tree to access "visibility: [hidden|collapse]" + // and "display: none" nodes. This is useful for APIs that return the node + // referenced by aria-labeledby and aria-describedby. + // An element must have an id attribute or it cannot be referenced by + // aria-labelledby or aria-describedby. + if (RuntimeEnabledFeatures::AccessibilityExposeDisplayNoneEnabled()) { + if (Element* element = GetElement()) { + if (element->FastHasAttribute(kIdAttr) && + IsHiddenForTextAlternativeCalculation()) { + return true; + } + } + } else if (GetLayoutObject()) { if (GetLayoutObject()->Style()->Visibility() != EVisibility::kVisible) return true; - if (AriaHiddenRoot()) - return true; } + // Allow the browser side ax tree to access "aria-hidden" nodes. + // This is useful for APIs that return the node referenced by + // aria-labeledby and aria-describedby. + if (GetLayoutObject() && AriaHiddenRoot()) + return true; + return false; }
diff --git a/third_party/blink/renderer/modules/accessibility/ax_object_cache_impl.cc b/third_party/blink/renderer/modules/accessibility/ax_object_cache_impl.cc index 932e25f..bdcae67 100644 --- a/third_party/blink/renderer/modules/accessibility/ax_object_cache_impl.cc +++ b/third_party/blink/renderer/modules/accessibility/ax_object_cache_impl.cc
@@ -88,6 +88,7 @@ #include "third_party/blink/renderer/modules/accessibility/ax_virtual_object.h" #include "third_party/blink/renderer/modules/media_controls/elements/media_control_elements_helper.h" #include "third_party/blink/renderer/modules/permissions/permission_utils.h" +#include "third_party/blink/renderer/platform/runtime_enabled_features.h" namespace blink { @@ -168,6 +169,45 @@ documents_.erase(document); } +Node* AXObjectCacheImpl::FocusedElement() { + Node* focused_node = document_->FocusedElement(); + if (!focused_node) + focused_node = document_; + + // If it's an image map, get the focused link within the image map. + if (IsA<HTMLAreaElement>(focused_node)) + return focused_node; + + // See if there's a page popup, for example a calendar picker. + Element* adjusted_focused_element = document_->AdjustedFocusedElement(); + if (auto* input = ToHTMLInputElementOrNull(adjusted_focused_element)) { + if (AXObject* ax_popup = input->PopupRootAXObject()) { + if (Element* focused_element_in_popup = + ax_popup->GetDocument()->FocusedElement()) + focused_node = focused_element_in_popup; + } + } + + return focused_node; +} + +AXObject* AXObjectCacheImpl::GetOrCreateFocusedObjectFromNode(Node* node) { + // If it's an image map, get the focused link within the image map. + if (auto* area = DynamicTo<HTMLAreaElement>(node)) + return FocusedImageMapUIElement(area); + + AXObject* obj = GetOrCreate(node); + if (!obj) + return nullptr; + + // the HTML element, for example, is focusable but has an AX object that is + // ignored + if (!obj->AccessibilityIsIncludedInTree()) + obj = obj->ParentObjectIncludedInTree(); + + return obj; +} + AXObject* AXObjectCacheImpl::FocusedImageMapUIElement( HTMLAreaElement* area_element) { // Find the corresponding accessibility object for the HTMLAreaElement. This @@ -198,34 +238,7 @@ } AXObject* AXObjectCacheImpl::FocusedObject() { - Node* focused_node = document_->FocusedElement(); - if (!focused_node) - focused_node = document_; - - // If it's an image map, get the focused link within the image map. - if (auto* area = DynamicTo<HTMLAreaElement>(focused_node)) - return FocusedImageMapUIElement(area); - - // See if there's a page popup, for example a calendar picker. - Element* adjusted_focused_element = document_->AdjustedFocusedElement(); - if (auto* input = ToHTMLInputElementOrNull(adjusted_focused_element)) { - if (AXObject* ax_popup = input->PopupRootAXObject()) { - if (Element* focused_element_in_popup = - ax_popup->GetDocument()->FocusedElement()) - focused_node = focused_element_in_popup; - } - } - - AXObject* obj = GetOrCreate(focused_node); - if (!obj) - return nullptr; - - // the HTML element, for example, is focusable but has an AX object that is - // ignored - if (!obj->AccessibilityIsIncludedInTree()) - obj = obj->ParentObjectUnignored(); - - return obj; + return GetOrCreateFocusedObjectFromNode(this->FocusedElement()); } AXObject* AXObjectCacheImpl::Get(LayoutObject* layout_object) { @@ -1175,6 +1188,30 @@ PostNotification(listbox, ax::mojom::Event::kSelectedChildrenChanged); } +void AXObjectCacheImpl::HandleNodeLostFocusWithCleanLayout(Node* node) { + DCHECK(node); + DCHECK(!node->GetDocument().NeedsLayoutTreeUpdateForNode(*node)); + AXObject* obj = Get(node); + if (!obj) + return; + + PostNotification(obj, ax::mojom::Event::kBlur); +} + +void AXObjectCacheImpl::HandleNodeGainedFocusWithCleanLayout(Node* node) { + DCHECK(node); + DCHECK(!node->GetDocument().NeedsLayoutTreeUpdateForNode(*node)); + // Something about the call chain for this method seems to leave distribution + // in a dirty state - update it before we call GetOrCreate so that we don't + // crash. + node->UpdateDistributionForFlatTreeTraversal(); + AXObject* obj = GetOrCreateFocusedObjectFromNode(node); + if (!obj) + return; + + PostNotification(obj, ax::mojom::Event::kFocus); +} + // This might be the new target of a relation. Handle all possible cases. void AXObjectCacheImpl::MaybeNewRelationTarget(Node* node, AXObject* obj) { // Track reverse relations @@ -1219,12 +1256,8 @@ DCHECK(!node->GetDocument().NeedsLayoutTreeUpdateForNode(*node)); - AXObject* obj = Get(node); - if (!obj && IsHTMLSelectElement(node)) - obj = GetOrCreate(node); - // Invalidate the current object and make the parent reconsider its children. - if (obj) { + if (AXObject* obj = GetOrCreate(node)) { // Save parent for later use. AXObject* parent = obj->ParentObject(); @@ -1590,13 +1623,23 @@ if (!page) return; - AXObject* focused_object = this->FocusedObject(); - if (!focused_object) - return; + if (RuntimeEnabledFeatures::AccessibilityExposeDisplayNoneEnabled()) { + if (old_focused_element) { + DeferTreeUpdate(&AXObjectCacheImpl::HandleNodeLostFocusWithCleanLayout, + old_focused_element); + } - AXObject* old_focused_object = Get(old_focused_element); - PostNotification(old_focused_object, ax::mojom::Event::kBlur); - PostNotification(focused_object, ax::mojom::Event::kFocus); + DeferTreeUpdate(&AXObjectCacheImpl::HandleNodeGainedFocusWithCleanLayout, + this->FocusedElement()); + } else { + AXObject* focused_object = this->FocusedObject(); + if (!focused_object) + return; + + AXObject* old_focused_object = Get(old_focused_element); + PostNotification(old_focused_object, ax::mojom::Event::kBlur); + PostNotification(focused_object, ax::mojom::Event::kFocus); + } } void AXObjectCacheImpl::HandleInitialFocus() {
diff --git a/third_party/blink/renderer/modules/accessibility/ax_object_cache_impl.h b/third_party/blink/renderer/modules/accessibility/ax_object_cache_impl.h index 100038e6..2ca263cb 100644 --- a/third_party/blink/renderer/modules/accessibility/ax_object_cache_impl.h +++ b/third_party/blink/renderer/modules/accessibility/ax_object_cache_impl.h
@@ -194,6 +194,8 @@ void HandleRoleChangeIfNotEditableWithCleanLayout(Node*); void HandleAriaExpandedChangeWithCleanLayout(Node*); void HandleAriaSelectedChangedWithCleanLayout(Node*); + void HandleNodeLostFocusWithCleanLayout(Node*); + void HandleNodeGainedFocusWithCleanLayout(Node*); bool InlineTextBoxAccessibilityEnabled(); @@ -322,6 +324,12 @@ // ContextLifecycleObserver overrides. void ContextDestroyed(ExecutionContext*) override; + // Get the currently focused Node element. + Node* FocusedElement(); + + // GetOrCreate the focusable AXObject for a specific Node. + AXObject* GetOrCreateFocusedObjectFromNode(Node*); + AXObject* FocusedImageMapUIElement(HTMLAreaElement*); AXID GetOrCreateAXID(AXObject*);
diff --git a/third_party/blink/renderer/modules/background_fetch/background_fetch_registration.cc b/third_party/blink/renderer/modules/background_fetch/background_fetch_registration.cc index 63e740a0..08cb59a 100644 --- a/third_party/blink/renderer/modules/background_fetch/background_fetch_registration.cc +++ b/third_party/blink/renderer/modules/background_fetch/background_fetch_registration.cc
@@ -71,8 +71,11 @@ registration_ = registration; registration_service_.Bind(std::move(registration_service)); - auto task_runner = - GetExecutionContext()->GetTaskRunner(TaskType::kBackgroundFetch); + ExecutionContext* context = GetExecutionContext(); + if (!context || context->IsContextDestroyed()) + return; + + auto task_runner = context->GetTaskRunner(TaskType::kBackgroundFetch); registration_service_->AddRegistrationObserver( observer_receiver_.BindNewPipeAndPassRemote(task_runner)); }
diff --git a/third_party/blink/renderer/modules/indexeddb/idb_database.cc b/third_party/blink/renderer/modules/indexeddb/idb_database.cc index 7f0794e..bcb343ac 100644 --- a/third_party/blink/renderer/modules/indexeddb/idb_database.cc +++ b/third_party/blink/renderer/modules/indexeddb/idb_database.cc
@@ -421,13 +421,19 @@ ->GetTaskRunner(TaskType::kDatabaseAccess), transaction_id); - bool relaxed_durability = false; - if (RuntimeEnabledFeatures::IDBRelaxedDurabilityEnabled() && options) - relaxed_durability = options->relaxedDurability(); + mojom::IDBTransactionDurability durability = + mojom::IDBTransactionDurability::Default; + if (RuntimeEnabledFeatures::IDBRelaxedDurabilityEnabled() && options) { + if (options->durability() == "relaxed") { + durability = mojom::IDBTransactionDurability::Relaxed; + } else if (options->durability() == "strict") { + durability = mojom::IDBTransactionDurability::Strict; + } + } backend_->CreateTransaction(transaction_backend->CreateReceiver(), transaction_id, object_store_ids, mode, - relaxed_durability); + durability); return IDBTransaction::CreateNonVersionChange( script_state, std::move(transaction_backend), transaction_id, scope, mode,
diff --git a/third_party/blink/renderer/modules/indexeddb/idb_request_test.cc b/third_party/blink/renderer/modules/indexeddb/idb_request_test.cc index 84de726..4ec6a3ad 100644 --- a/third_party/blink/renderer/modules/indexeddb/idb_request_test.cc +++ b/third_party/blink/renderer/modules/indexeddb/idb_request_test.cc
@@ -90,7 +90,7 @@ int64_t transaction_id, const WTF::Vector<int64_t>& object_store_ids, mojom::blink::IDBTransactionMode mode, - bool relaxed_durability) override {} + mojom::blink::IDBTransactionDurability) override {} MOCK_METHOD0(Close, void()); void VersionChangeIgnored() override {} void AddObserver(int64_t transaction_id,
diff --git a/third_party/blink/renderer/modules/indexeddb/idb_transaction_options.idl b/third_party/blink/renderer/modules/indexeddb/idb_transaction_options.idl index 6da6153..64109b9 100644 --- a/third_party/blink/renderer/modules/indexeddb/idb_transaction_options.idl +++ b/third_party/blink/renderer/modules/indexeddb/idb_transaction_options.idl
@@ -2,8 +2,12 @@ // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. +enum IDBTransactionDurability { "default", "strict", "relaxed" }; + dictionary IDBTransactionOptions { - // If relaxedDurability is true, then the transaction will not be flushed - // to disk. This is more performant at the cost of durability. - boolean relaxedDurability = false; + // If durability is "relaxed", then the transaction will not be flushed + // to disk. This is more performant at the cost of durability. If it is + // "strict", then it will always be flushed to disk. "default" leaves the + // decision up to the implementation. + IDBTransactionDurability durability = "default"; };
diff --git a/third_party/blink/renderer/modules/indexeddb/inspector_indexed_db_agent.cc b/third_party/blink/renderer/modules/indexeddb/inspector_indexed_db_agent.cc index 337cbc7..56ff8283 100644 --- a/third_party/blink/renderer/modules/indexeddb/inspector_indexed_db_agent.cc +++ b/third_party/blink/renderer/modules/indexeddb/inspector_indexed_db_agent.cc
@@ -326,7 +326,7 @@ StringOrStringSequence scope; scope.SetString(object_store_name); IDBTransactionOptions options; - options.setRelaxedDurability(true); + options.setDurability("relaxed"); IDBTransaction* idb_transaction = idb_database->transaction( script_state, scope, mode, &options, exception_state); if (exception_state.HadException())
diff --git a/third_party/blink/renderer/modules/indexeddb/mock_web_idb_database.h b/third_party/blink/renderer/modules/indexeddb/mock_web_idb_database.h index 6f91bde..9dce5f2 100644 --- a/third_party/blink/renderer/modules/indexeddb/mock_web_idb_database.h +++ b/third_party/blink/renderer/modules/indexeddb/mock_web_idb_database.h
@@ -29,7 +29,7 @@ int64_t id, const Vector<int64_t>& scope, mojom::IDBTransactionMode, - bool relaxed_durability)); + mojom::IDBTransactionDurability)); MOCK_METHOD0(Close, void()); MOCK_METHOD0(VersionChangeIgnored, void()); MOCK_METHOD1(Abort, void(int64_t transaction_id));
diff --git a/third_party/blink/renderer/modules/indexeddb/web_idb_database.h b/third_party/blink/renderer/modules/indexeddb/web_idb_database.h index 04ec3a37..34ed7bc4 100644 --- a/third_party/blink/renderer/modules/indexeddb/web_idb_database.h +++ b/third_party/blink/renderer/modules/indexeddb/web_idb_database.h
@@ -53,7 +53,7 @@ int64_t id, const Vector<int64_t>& scope, mojom::IDBTransactionMode, - bool relaxed_durability) = 0; + mojom::IDBTransactionDurability) = 0; virtual void Close() = 0; virtual void VersionChangeIgnored() = 0;
diff --git a/third_party/blink/renderer/modules/indexeddb/web_idb_database_impl.cc b/third_party/blink/renderer/modules/indexeddb/web_idb_database_impl.cc index 482b56de..ce509c8 100644 --- a/third_party/blink/renderer/modules/indexeddb/web_idb_database_impl.cc +++ b/third_party/blink/renderer/modules/indexeddb/web_idb_database_impl.cc
@@ -37,9 +37,9 @@ int64_t transaction_id, const Vector<int64_t>& object_store_ids, mojom::IDBTransactionMode mode, - bool relaxed_durability) { + mojom::IDBTransactionDurability durability) { database_->CreateTransaction(std::move(transaction_receiver), transaction_id, - object_store_ids, mode, relaxed_durability); + object_store_ids, mode, durability); } void WebIDBDatabaseImpl::Close() {
diff --git a/third_party/blink/renderer/modules/indexeddb/web_idb_database_impl.h b/third_party/blink/renderer/modules/indexeddb/web_idb_database_impl.h index 63309de..84f75aa5 100644 --- a/third_party/blink/renderer/modules/indexeddb/web_idb_database_impl.h +++ b/third_party/blink/renderer/modules/indexeddb/web_idb_database_impl.h
@@ -36,7 +36,7 @@ int64_t transaction_id, const Vector<int64_t>& scope, mojom::IDBTransactionMode mode, - bool relaxed_durability) override; + mojom::IDBTransactionDurability durability) override; void Close() override; void VersionChangeIgnored() override;
diff --git a/third_party/blink/renderer/modules/webgpu/gpu_render_bundle_encoder.idl b/third_party/blink/renderer/modules/webgpu/gpu_render_bundle_encoder.idl index 6d3a898..9689b025 100644 --- a/third_party/blink/renderer/modules/webgpu/gpu_render_bundle_encoder.idl +++ b/third_party/blink/renderer/modules/webgpu/gpu_render_bundle_encoder.idl
@@ -17,7 +17,7 @@ // GPURenderEncoderBase methods void setPipeline(GPURenderPipeline pipeline); - void setIndexBuffer(GPUBuffer buffer, unsigned long long offset); + void setIndexBuffer(GPUBuffer buffer, optional unsigned long long offset = 0); [RaisesException] void setVertexBuffers(unsigned long startSlot, sequence<GPUBuffer> buffers, sequence<unsigned long long> offsets);
diff --git a/third_party/blink/renderer/modules/webgpu/gpu_render_pass_encoder.idl b/third_party/blink/renderer/modules/webgpu/gpu_render_pass_encoder.idl index b3db800..40d0203 100644 --- a/third_party/blink/renderer/modules/webgpu/gpu_render_pass_encoder.idl +++ b/third_party/blink/renderer/modules/webgpu/gpu_render_pass_encoder.idl
@@ -24,7 +24,7 @@ float minDepth, float maxDepth); void setScissorRect(unsigned long x, unsigned long y, unsigned long width, unsigned long height); - void setIndexBuffer(GPUBuffer buffer, unsigned long long offset); + void setIndexBuffer(GPUBuffer buffer, optional unsigned long long offset = 0); [RaisesException] void setVertexBuffers(unsigned long startSlot, sequence<GPUBuffer> buffers, sequence<unsigned long long> offsets);
diff --git a/third_party/blink/renderer/modules/xr/xr_anchor.cc b/third_party/blink/renderer/modules/xr/xr_anchor.cc index fee23ea2..d3b6f7ab 100644 --- a/third_party/blink/renderer/modules/xr/xr_anchor.cc +++ b/third_party/blink/renderer/modules/xr/xr_anchor.cc
@@ -10,10 +10,10 @@ namespace blink { -XRAnchor::XRAnchor(int32_t id, XRSession* session) +XRAnchor::XRAnchor(uint32_t id, XRSession* session) : id_(id), session_(session), anchor_data_(base::nullopt) {} -XRAnchor::XRAnchor(int32_t id, +XRAnchor::XRAnchor(uint32_t id, XRSession* session, const device::mojom::blink::XRAnchorDataPtr& anchor_data, double timestamp)
diff --git a/third_party/blink/renderer/modules/xr/xr_anchor.h b/third_party/blink/renderer/modules/xr/xr_anchor.h index fdec8bb..1fcb6373 100644 --- a/third_party/blink/renderer/modules/xr/xr_anchor.h +++ b/third_party/blink/renderer/modules/xr/xr_anchor.h
@@ -21,9 +21,9 @@ DEFINE_WRAPPERTYPEINFO(); public: - XRAnchor(int32_t id, XRSession* session); + XRAnchor(uint32_t id, XRSession* session); - XRAnchor(int32_t id, + XRAnchor(uint32_t id, XRSession* session, const device::mojom::blink::XRAnchorDataPtr& anchor_data, double timestamp); @@ -54,7 +54,7 @@ double timestamp); }; - const int32_t id_; + const uint32_t id_; Member<XRSession> session_;
diff --git a/third_party/blink/renderer/modules/xr/xr_plane.cc b/third_party/blink/renderer/modules/xr/xr_plane.cc index 14496fb..e7cb010 100644 --- a/third_party/blink/renderer/modules/xr/xr_plane.cc +++ b/third_party/blink/renderer/modules/xr/xr_plane.cc
@@ -13,7 +13,7 @@ namespace blink { -XRPlane::XRPlane(int32_t id, +XRPlane::XRPlane(uint32_t id, XRSession* session, const device::mojom::blink::XRPlaneDataPtr& plane_data, double timestamp) @@ -26,7 +26,7 @@ plane_data->polygon), timestamp) {} -XRPlane::XRPlane(int32_t id, +XRPlane::XRPlane(uint32_t id, XRSession* session, const base::Optional<Orientation>& orientation, const TransformationMatrix& pose_matrix, @@ -41,7 +41,7 @@ DVLOG(3) << __func__; } -int32_t XRPlane::id() const { +uint32_t XRPlane::id() const { return id_; }
diff --git a/third_party/blink/renderer/modules/xr/xr_plane.h b/third_party/blink/renderer/modules/xr/xr_plane.h index e7cf645c..516b004 100644 --- a/third_party/blink/renderer/modules/xr/xr_plane.h +++ b/third_party/blink/renderer/modules/xr/xr_plane.h
@@ -27,18 +27,18 @@ public: enum Orientation { kHorizontal, kVertical }; - XRPlane(int32_t id, + XRPlane(uint32_t id, XRSession* session, const device::mojom::blink::XRPlaneDataPtr& plane_data, double timestamp); - XRPlane(int32_t id, + XRPlane(uint32_t id, XRSession* session, const base::Optional<Orientation>& orientation, const TransformationMatrix& pose_matrix, const HeapVector<Member<DOMPointReadOnly>>& polygon, double timestamp); - int32_t id() const; + uint32_t id() const; XRSpace* planeSpace() const; @@ -62,7 +62,7 @@ void Trace(blink::Visitor* visitor) override; private: - const int32_t id_; + const uint32_t id_; HeapVector<Member<DOMPointReadOnly>> polygon_; base::Optional<Orientation> orientation_;
diff --git a/third_party/blink/renderer/modules/xr/xr_session.cc b/third_party/blink/renderer/modules/xr/xr_session.cc index f3e17ab..59b4df8 100644 --- a/third_party/blink/renderer/modules/xr/xr_session.cc +++ b/third_party/blink/renderer/modules/xr/xr_session.cc
@@ -253,36 +253,20 @@ return; } - if (init->hasBaseLayer() && init->baseLayer()) { - // Validate that any baseLayer provided was created with this session. - if (init->baseLayer()->session() != this) { - exception_state.ThrowDOMException(DOMExceptionCode::kInvalidStateError, - kIncompatibleLayer); - return; - } - - // If the baseLayer was previously null and there are outstanding rAF - // callbacks, kick off a new frame request to flush them out. - if (!render_state_->baseLayer() && !pending_frame_ && - !callback_collection_->IsEmpty()) { - // Kick off a request for a new XR frame. - xr_->frameProvider()->RequestFrame(this); - pending_frame_ = true; - } - - if (!immersive() && init->baseLayer()->output_canvas()) { - // If the output canvas was previously null and there are outstanding rAF - // callbacks, kick off a new frame request to flush them out. - if (!render_state_->output_canvas() && !pending_frame_ && - !callback_collection_->IsEmpty()) { - // Kick off a request for a new XR frame. - xr_->frameProvider()->RequestFrame(this); - pending_frame_ = true; - } - } + // Validate that any baseLayer provided was created with this session. + if (init->hasBaseLayer() && init->baseLayer() && + init->baseLayer()->session() != this) { + exception_state.ThrowDOMException(DOMExceptionCode::kInvalidStateError, + kIncompatibleLayer); + return; } pending_render_state_.push_back(init); + + // Updating our render state may have caused us to be in a state where we + // should be requesting frames again. Kick off a new frame request in case + // there are any pending callbacks to flush them out. + MaybeRequestFrame(); } void XRSession::updateWorldTrackingState( @@ -518,11 +502,7 @@ return 0; int id = callback_collection_->RegisterCallback(callback); - if (!pending_frame_) { - // Kick off a request for a new XR frame. - xr_->frameProvider()->RequestFrame(this); - pending_frame_ = true; - } + MaybeRequestFrame(); return id; } @@ -615,7 +595,7 @@ void XRSession::OnCreateAnchorResult(ScriptPromiseResolver* resolver, device::mojom::CreateAnchorResult result, - int32_t id) { + uint32_t id) { DCHECK(create_anchor_promises_.Contains(resolver)); create_anchor_promises_.erase(resolver); @@ -680,7 +660,7 @@ is_tracked_anchors_null_ = false; - HeapHashMap<int32_t, Member<XRAnchor>> updated_anchors; + HeapHashMap<uint32_t, Member<XRAnchor>> updated_anchors; // First, process all planes that had their information updated (new planes // are also processed here). @@ -846,20 +826,35 @@ if (visibility_state_ != state) { visibility_state_ = state; - // If the visibility state was changed to something other than hidden and - // there are rAF callbacks still waiting to resolve kickstart the rAF loop - // again. - if (visibility_state_ != XRVisibilityState::HIDDEN && !pending_frame_ && - !callback_collection_->IsEmpty()) { - xr_->frameProvider()->RequestFrame(this); - pending_frame_ = true; - } + // If the visibility state was changed to something other than hidden, we + // may be able to restart the frame loop. + MaybeRequestFrame(); DispatchEvent( *XRSessionEvent::Create(event_type_names::kVisibilitychange, this)); } } +void XRSession::MaybeRequestFrame() { + bool will_have_base_layer = !!render_state_->baseLayer(); + for (const auto& init : pending_render_state_) { + if (init->hasBaseLayer()) { + will_have_base_layer = !!init->baseLayer(); + } + } + + // We can request a frame if we're not hidden, we don't already have a pending + // frame, we have pending callbacks, and we will have a base layer when it + // resolves. + bool can_request_frame = + visibility_state_ != XRVisibilityState::HIDDEN && !pending_frame_ && + !callback_collection_->IsEmpty() && will_have_base_layer; + if (can_request_frame) { + xr_->frameProvider()->RequestFrame(this); + pending_frame_ = true; + } +} + void XRSession::DetachOutputCanvas(HTMLCanvasElement* canvas) { if (!canvas) return; @@ -876,8 +871,9 @@ } void XRSession::ApplyPendingRenderState() { + DCHECK(!prev_base_layer_); if (pending_render_state_.size() > 0) { - XRWebGLLayer* prev_base_layer = render_state_->baseLayer(); + prev_base_layer_ = render_state_->baseLayer(); HTMLCanvasElement* prev_ouput_canvas = render_state_->output_canvas(); update_views_next_frame_ = true; @@ -890,7 +886,7 @@ // If this is an inline session and the base layer has changed, give it an // opportunity to update it's drawing buffer size. if (!immersive() && render_state_->baseLayer() && - render_state_->baseLayer() != prev_base_layer) { + render_state_->baseLayer() != prev_base_layer_) { render_state_->baseLayer()->OnResize(); } @@ -961,6 +957,7 @@ return; // If there are pending render state changes, apply them now. + prev_base_layer_ = nullptr; ApplyPendingRenderState(); if (pending_frame_) { @@ -969,8 +966,17 @@ // Don't allow frames to be processed if there's no layers attached to the // session. That would allow tracking with no associated visuals. XRWebGLLayer* frame_base_layer = render_state_->baseLayer(); - if (!frame_base_layer) + if (!frame_base_layer) { + // If we previously had a frame base layer, we need to still attempt to + // submit a frame back to the runtime, as all "GetFrameData" calls need a + // matching submit. + if (prev_base_layer_) { + prev_base_layer_->OnFrameStart(output_mailbox_holder); + prev_base_layer_->OnFrameEnd(); + prev_base_layer_ = nullptr; + } return; + } // Don't allow frames to be processed if an inline session doesn't have an // output canvas. @@ -1312,6 +1318,7 @@ visitor->Trace(create_anchor_promises_); visitor->Trace(reference_spaces_); visitor->Trace(anchor_ids_to_anchors_); + visitor->Trace(prev_base_layer_); EventTargetWithInlineData::Trace(visitor); }
diff --git a/third_party/blink/renderer/modules/xr/xr_session.h b/third_party/blink/renderer/modules/xr/xr_session.h index 9a344bfe..5eb4147 100644 --- a/third_party/blink/renderer/modules/xr/xr_session.h +++ b/third_party/blink/renderer/modules/xr/xr_session.h
@@ -45,6 +45,7 @@ class XRRigidTransform; class XRSpace; class XRViewData; +class XRWebGLLayer; class XRWorldInformation; class XRWorldTrackingState; class XRWorldTrackingStateInit; @@ -243,6 +244,8 @@ void UpdateCanvasDimensions(Element*); void ApplyPendingRenderState(); + void MaybeRequestFrame(); + void OnInputStateChangeInternal( int16_t frame_id, base::span<const device::mojom::blink::XRInputSourceStatePtr> @@ -264,7 +267,7 @@ void OnCreateAnchorResult(ScriptPromiseResolver* resolver, device::mojom::CreateAnchorResult result, - int32_t id); + uint32_t id); void EnsureEnvironmentErrorHandler(); void OnEnvironmentProviderError(); @@ -288,11 +291,12 @@ XRSessionFeatureSet enabled_features_; bool is_tracked_anchors_null_ = true; - HeapHashMap<int32_t, Member<XRAnchor>> anchor_ids_to_anchors_; + HeapHashMap<uint32_t, Member<XRAnchor>> anchor_ids_to_anchors_; WTF::Vector<XRViewData> views_; Member<XRInputSourceArray> input_sources_; + Member<XRWebGLLayer> prev_base_layer_; Member<ResizeObserver> resize_observer_; Member<XRCanvasInputProvider> canvas_input_provider_; bool environment_error_handler_subscribed_ = false;
diff --git a/third_party/blink/renderer/modules/xr/xr_world_information.cc b/third_party/blink/renderer/modules/xr/xr_world_information.cc index 0feed185..b74d9fd 100644 --- a/third_party/blink/renderer/modules/xr/xr_world_information.cc +++ b/third_party/blink/renderer/modules/xr/xr_world_information.cc
@@ -58,7 +58,7 @@ is_detected_planes_null_ = false; - HeapHashMap<int32_t, Member<XRPlane>> updated_planes; + HeapHashMap<uint32_t, Member<XRPlane>> updated_planes; // First, process all planes that had their information updated (new planes // are also processed here).
diff --git a/third_party/blink/renderer/modules/xr/xr_world_information.h b/third_party/blink/renderer/modules/xr/xr_world_information.h index 6f6e816..cbe0246 100644 --- a/third_party/blink/renderer/modules/xr/xr_world_information.h +++ b/third_party/blink/renderer/modules/xr/xr_world_information.h
@@ -37,7 +37,7 @@ // This is the case if we have a freshly constructed instance, or if our // last `ProcessPlaneInformation()` was called with base::nullopt. bool is_detected_planes_null_ = true; - HeapHashMap<int32_t, Member<XRPlane>> plane_ids_to_planes_; + HeapHashMap<uint32_t, Member<XRPlane>> plane_ids_to_planes_; Member<XRSession> session_; };
diff --git a/third_party/blink/renderer/platform/exported/web_runtime_features.cc b/third_party/blink/renderer/platform/exported/web_runtime_features.cc index dff5f2e..bd433b1 100644 --- a/third_party/blink/renderer/platform/exported/web_runtime_features.cc +++ b/third_party/blink/renderer/platform/exported/web_runtime_features.cc
@@ -88,6 +88,10 @@ RuntimeEnabledFeatures::SetAccelerated2dCanvasEnabled(enable); } +void WebRuntimeFeatures::EnableAccessibilityExposeDisplayNone(bool enable) { + RuntimeEnabledFeatures::SetAccessibilityExposeDisplayNoneEnabled(enable); +} + void WebRuntimeFeatures::EnableAccessibilityObjectModel(bool enable) { RuntimeEnabledFeatures::SetAccessibilityObjectModelEnabled(enable); }
diff --git a/third_party/blink/renderer/platform/runtime_enabled_features.json5 b/third_party/blink/renderer/platform/runtime_enabled_features.json5 index ce12da2c..88c9d2b 100644 --- a/third_party/blink/renderer/platform/runtime_enabled_features.json5 +++ b/third_party/blink/renderer/platform/runtime_enabled_features.json5
@@ -99,6 +99,9 @@ status: "stable", }, { + name: "AccessibilityExposeDisplayNone", + }, + { name: "AccessibilityObjectModel", status: "experimental", },
diff --git a/third_party/blink/tools/blinkpy/web_tests/controllers/single_test_runner.py b/third_party/blink/tools/blinkpy/web_tests/controllers/single_test_runner.py index 76e5ff60..875d91bb 100644 --- a/third_party/blink/tools/blinkpy/web_tests/controllers/single_test_runner.py +++ b/third_party/blink/tools/blinkpy/web_tests/controllers/single_test_runner.py
@@ -512,11 +512,11 @@ test_result = None putAllMismatchBeforeMatch = sorted reference_test_names = [] + if self._port.lookup_virtual_test_base(self._test_name): + args = self._port.lookup_virtual_reference_args(self._test_name) + else: + args = self._port.lookup_physical_reference_args(self._test_name) for expectation, reference_filename in putAllMismatchBeforeMatch(self._reference_files): - if self._port.lookup_virtual_test_base(self._test_name): - args = self._port.lookup_virtual_reference_args(self._test_name) - else: - args = self._port.lookup_physical_reference_args(self._test_name) reference_test_name = self._port.relative_test_filename(reference_filename) reference_test_names.append(reference_test_name) driver_input = DriverInput(reference_test_name, self._timeout_ms,
diff --git a/third_party/blink/web_tests/FlagExpectations/disable-blink-features=LayoutNG b/third_party/blink/web_tests/FlagExpectations/disable-blink-features=LayoutNG index c8b8d291e..04c5a4a5 100644 --- a/third_party/blink/web_tests/FlagExpectations/disable-blink-features=LayoutNG +++ b/third_party/blink/web_tests/FlagExpectations/disable-blink-features=LayoutNG
@@ -10,6 +10,7 @@ crbug.com/591099 external/wpt/css/CSS2/floats/float-nowrap-3.html [ Failure ] crbug.com/591099 external/wpt/css/CSS2/floats/floats-line-wrap-shifted-001.html [ Failure ] crbug.com/591099 external/wpt/css/CSS2/floats/overhanging-float-paint-order.html [ Failure ] +crbug.com/591099 external/wpt/css/CSS2/floats/zero-width-floats-positioning.tentative.html [ Failure ] ### external/wpt/css/CSS2/floats-clear/ crbug.com/591099 external/wpt/css/CSS2/floats-clear/no-clearance-adjoining-opposite-float.html [ Failure ]
diff --git a/third_party/blink/web_tests/NeverFixTests b/third_party/blink/web_tests/NeverFixTests index 715d091..00a6bff 100644 --- a/third_party/blink/web_tests/NeverFixTests +++ b/third_party/blink/web_tests/NeverFixTests
@@ -1518,6 +1518,67 @@ virtual/threaded/external/wpt/css/css-animations/animation-timing-function-011-manual.html [ WontFix ] virtual/threaded/external/wpt/css/css-animations/animation-timing-function-012-manual.html [ WontFix ] virtual/threaded/external/wpt/css/css-animations/animationstart-and-animationend-events-manual.html [ WontFix ] +external/wpt/css/css-transitions/transition-delay-000-manual.html [ WontFix ] +external/wpt/css/css-transitions/transition-delay-002-manual.html [ WontFix ] +external/wpt/css/css-transitions/transition-delay-003-manual.html [ WontFix ] +external/wpt/css/css-transitions/transition-duration-002-manual.html [ WontFix ] +external/wpt/css/css-transitions/transition-duration-003-manual.html [ WontFix ] +external/wpt/css/css-transitions/transition-duration-004-manual.html [ WontFix ] +external/wpt/css/css-transitions/transition-property-003-manual.html [ WontFix ] +external/wpt/css/css-transitions/transition-property-004-manual.html [ WontFix ] +external/wpt/css/css-transitions/transition-property-005-manual.html [ WontFix ] +external/wpt/css/css-transitions/transition-property-006-manual.html [ WontFix ] +external/wpt/css/css-transitions/transition-property-007-manual.html [ WontFix ] +external/wpt/css/css-transitions/transition-property-008-manual.html [ WontFix ] +external/wpt/css/css-transitions/transition-property-009-manual.html [ WontFix ] +external/wpt/css/css-transitions/transition-property-010-manual.html [ WontFix ] +external/wpt/css/css-transitions/transition-property-011-manual.html [ WontFix ] +external/wpt/css/css-transitions/transition-property-012-manual.html [ WontFix ] +external/wpt/css/css-transitions/transition-property-013-manual.html [ WontFix ] +external/wpt/css/css-transitions/transition-property-014-manual.html [ WontFix ] +external/wpt/css/css-transitions/transition-property-015-manual.html [ WontFix ] +external/wpt/css/css-transitions/transition-property-016-manual.html [ WontFix ] +external/wpt/css/css-transitions/transition-property-017-manual.html [ WontFix ] +external/wpt/css/css-transitions/transition-property-018-manual.html [ WontFix ] +external/wpt/css/css-transitions/transition-property-019-manual.html [ WontFix ] +external/wpt/css/css-transitions/transition-property-020-manual.html [ WontFix ] +external/wpt/css/css-transitions/transition-property-021-manual.html [ WontFix ] +external/wpt/css/css-transitions/transition-property-022-manual.html [ WontFix ] +external/wpt/css/css-transitions/transition-property-023-manual.html [ WontFix ] +external/wpt/css/css-transitions/transition-property-024-manual.html [ WontFix ] +external/wpt/css/css-transitions/transition-property-025-manual.html [ WontFix ] +external/wpt/css/css-transitions/transition-property-026-manual.html [ WontFix ] +external/wpt/css/css-transitions/transition-property-027-manual.html [ WontFix ] +external/wpt/css/css-transitions/transition-property-028-manual.html [ WontFix ] +external/wpt/css/css-transitions/transition-property-029-manual.html [ WontFix ] +external/wpt/css/css-transitions/transition-property-030-manual.html [ WontFix ] +external/wpt/css/css-transitions/transition-property-031-manual.html [ WontFix ] +external/wpt/css/css-transitions/transition-property-032-manual.html [ WontFix ] +external/wpt/css/css-transitions/transition-property-033-manual.html [ WontFix ] +external/wpt/css/css-transitions/transition-property-034-manual.html [ WontFix ] +external/wpt/css/css-transitions/transition-property-035-manual.html [ WontFix ] +external/wpt/css/css-transitions/transition-property-036-manual.html [ WontFix ] +external/wpt/css/css-transitions/transition-property-037-manual.html [ WontFix ] +external/wpt/css/css-transitions/transition-property-038-manual.html [ WontFix ] +external/wpt/css/css-transitions/transition-property-039-manual.html [ WontFix ] +external/wpt/css/css-transitions/transition-property-040-manual.html [ WontFix ] +external/wpt/css/css-transitions/transition-property-041-manual.html [ WontFix ] +external/wpt/css/css-transitions/transition-property-042-manual.html [ WontFix ] +external/wpt/css/css-transitions/transition-property-043-manual.html [ WontFix ] +external/wpt/css/css-transitions/transition-property-044-manual.html [ WontFix ] +external/wpt/css/css-transitions/transition-property-045-manual.html [ WontFix ] +external/wpt/css/css-transitions/transition-timing-function-002-manual.html [ WontFix ] +external/wpt/css/css-transitions/transition-timing-function-003-manual.html [ WontFix ] +external/wpt/css/css-transitions/transition-timing-function-004-manual.html [ WontFix ] +external/wpt/css/css-transitions/transition-timing-function-005-manual.html [ WontFix ] +external/wpt/css/css-transitions/transition-timing-function-006-manual.html [ WontFix ] +external/wpt/css/css-transitions/transition-timing-function-007-manual.html [ WontFix ] +external/wpt/css/css-transitions/transition-timing-function-008-manual.html [ WontFix ] +external/wpt/css/css-transitions/transition-timing-function-009-manual.html [ WontFix ] +external/wpt/css/css-transitions/transition-timing-function-010-manual.html [ WontFix ] +external/wpt/css/css-transitions/transition-timing-function-011-manual.html [ WontFix ] +external/wpt/css/css-transitions/transition-timing-function-012-manual.html [ WontFix ] +external/wpt/css/css-transitions/transition-timing-function-013-manual.html [ WontFix ] external/wpt/css/css-ui/cursor-pointer-links-001-manual.html [ WontFix ] external/wpt/css/css-ui/cursor-pointer-links-002-manual.html [ WontFix ] external/wpt/css/css-ui/cursor-pointer-links-003-manual.html [ WontFix ]
diff --git a/third_party/blink/web_tests/TestExpectations b/third_party/blink/web_tests/TestExpectations index 8efeecb6..81f4bf4 100644 --- a/third_party/blink/web_tests/TestExpectations +++ b/third_party/blink/web_tests/TestExpectations
@@ -3898,67 +3898,6 @@ crbug.com/626703 external/wpt/css/vendor-imports/mozilla/mozilla-central-reftests/flexbox/flexbox-flex-basis-content-002b.html [ Failure ] crbug.com/626703 external/wpt/css/vendor-imports/mozilla/mozilla-central-reftests/flexbox/flexbox-flex-basis-content-001b.html [ Failure ] crbug.com/626703 [ Win7 ] external/wpt/css/css-fonts/variations/font-opentype-collections.html [ Timeout ] -crbug.com/626703 external/wpt/css/css-transitions/transition-property-017.html [ Skip ] -crbug.com/626703 external/wpt/css/css-transitions/transition-property-030.html [ Skip ] -crbug.com/626703 external/wpt/css/css-transitions/transition-property-015.html [ Skip ] -crbug.com/626703 external/wpt/css/css-transitions/transition-property-021.html [ Skip ] -crbug.com/626703 external/wpt/css/css-transitions/transition-property-039.html [ Skip ] -crbug.com/626703 external/wpt/css/css-transitions/transition-timing-function-008.html [ Skip ] -crbug.com/626703 external/wpt/css/css-transitions/transition-timing-function-002.html [ Skip ] -crbug.com/626703 external/wpt/css/css-transitions/transition-property-012.html [ Skip ] -crbug.com/626703 external/wpt/css/css-transitions/transition-property-014.html [ Skip ] -crbug.com/626703 external/wpt/css/css-transitions/transition-property-016.html [ Skip ] -crbug.com/626703 external/wpt/css/css-transitions/transition-timing-function-007.html [ Skip ] -crbug.com/626703 external/wpt/css/css-transitions/transition-property-009.html [ Skip ] -crbug.com/626703 external/wpt/css/css-transitions/transition-property-029.html [ Skip ] -crbug.com/626703 external/wpt/css/css-transitions/transition-property-023.html [ Skip ] -crbug.com/626703 external/wpt/css/css-transitions/transition-property-027.html [ Skip ] -crbug.com/626703 external/wpt/css/css-transitions/transition-timing-function-010.html [ Skip ] -crbug.com/626703 external/wpt/css/css-transitions/transition-property-003.html [ Skip ] -crbug.com/626703 external/wpt/css/css-transitions/transition-property-011.html [ Skip ] -crbug.com/626703 external/wpt/css/css-transitions/transition-property-008.html [ Skip ] -crbug.com/626703 external/wpt/css/css-transitions/transition-timing-function-011.html [ Skip ] -crbug.com/626703 external/wpt/css/css-transitions/transition-property-020.html [ Skip ] -crbug.com/626703 external/wpt/css/css-transitions/transition-timing-function-013.html [ Skip ] -crbug.com/626703 external/wpt/css/css-transitions/transition-timing-function-012.html [ Skip ] -crbug.com/626703 external/wpt/css/css-transitions/transition-property-031.html [ Skip ] -crbug.com/626703 external/wpt/css/css-transitions/transition-delay-000.html [ Skip ] -crbug.com/626703 external/wpt/css/css-transitions/transition-property-041.html [ Skip ] -crbug.com/626703 external/wpt/css/css-transitions/transition-property-026.html [ Skip ] -crbug.com/626703 external/wpt/css/css-transitions/transition-duration-003.html [ Skip ] -crbug.com/626703 external/wpt/css/css-transitions/transition-delay-002.html [ Skip ] -crbug.com/626703 external/wpt/css/css-transitions/transition-timing-function-005.html [ Skip ] -crbug.com/626703 external/wpt/css/css-transitions/transition-property-004.html [ Skip ] -crbug.com/626703 external/wpt/css/css-transitions/transition-property-006.html [ Skip ] -crbug.com/626703 external/wpt/css/css-transitions/transition-property-018.html [ Skip ] -crbug.com/626703 external/wpt/css/css-transitions/transition-property-022.html [ Skip ] -crbug.com/626703 external/wpt/css/css-transitions/transition-duration-002.html [ Skip ] -crbug.com/626703 external/wpt/css/css-transitions/transition-property-024.html [ Skip ] -crbug.com/626703 external/wpt/css/css-transitions/transition-timing-function-009.html [ Skip ] -crbug.com/626703 external/wpt/css/css-transitions/transition-property-037.html [ Skip ] -crbug.com/626703 external/wpt/css/css-transitions/transition-property-007.html [ Skip ] -crbug.com/626703 external/wpt/css/css-transitions/transition-property-005.html [ Skip ] -crbug.com/626703 external/wpt/css/css-transitions/transition-property-042.html [ Skip ] -crbug.com/626703 external/wpt/css/css-transitions/transition-property-036.html [ Skip ] -crbug.com/626703 external/wpt/css/css-transitions/transition-property-038.html [ Skip ] -crbug.com/626703 external/wpt/css/css-transitions/transition-delay-003.html [ Skip ] -crbug.com/626703 external/wpt/css/css-transitions/transition-property-010.html [ Skip ] -crbug.com/626703 external/wpt/css/css-transitions/transition-property-028.html [ Skip ] -crbug.com/626703 external/wpt/css/css-transitions/transition-timing-function-004.html [ Skip ] -crbug.com/626703 external/wpt/css/css-transitions/transition-property-043.html [ Skip ] -crbug.com/626703 external/wpt/css/css-transitions/transition-property-040.html [ Skip ] -crbug.com/626703 external/wpt/css/css-transitions/transition-property-019.html [ Skip ] -crbug.com/626703 external/wpt/css/css-transitions/transition-property-034.html [ Skip ] -crbug.com/626703 external/wpt/css/css-transitions/transition-property-045.html [ Skip ] -crbug.com/626703 external/wpt/css/css-transitions/transition-property-035.html [ Skip ] -crbug.com/626703 external/wpt/css/css-transitions/transition-property-033.html [ Skip ] -crbug.com/626703 external/wpt/css/css-transitions/transition-timing-function-003.html [ Skip ] -crbug.com/626703 external/wpt/css/css-transitions/transition-property-044.html [ Skip ] -crbug.com/626703 external/wpt/css/css-transitions/transition-timing-function-006.html [ Skip ] -crbug.com/626703 external/wpt/css/css-transitions/transition-duration-004.html [ Skip ] -crbug.com/626703 external/wpt/css/css-transitions/transition-property-032.html [ Skip ] -crbug.com/626703 external/wpt/css/css-transitions/transition-property-025.html [ Skip ] -crbug.com/626703 external/wpt/css/css-transitions/transition-property-013.html [ Skip ] crbug.com/626703 external/wpt/css/css-animations/animation-delay-010.html [ Failure ] crbug.com/626703 virtual/threaded/external/wpt/css/css-animations/animation-delay-010.html [ Failure ] crbug.com/626703 external/wpt/css/vendor-imports/mozilla/mozilla-central-reftests/counter-styles-3/system-numeric.html [ Failure ] @@ -5912,9 +5851,6 @@ crbug.com/963141 [ Linux ] media/video-object-fit.html [ Pass Failure ] crbug.com/963141 [ Linux ] virtual/audio-service/media/video-object-fit.html [ Pass Failure ] -# Sheriff 2019-05-17 -crbug.com/964239 virtual/threaded/external/wpt/css/css-scroll-snap/scroll-margin.html [ Pass Failure ] - # Workaround for bug; should be removed soon. crbug.com/959693 external/wpt/trusted-types/WorkerGlobalScope-importScripts.https.html [ Timeout ] @@ -5923,7 +5859,6 @@ crbug.com/972476 std-switch/switch-appearance-customization.html [ Failure ] # Sheriff 2019-05-20 -crbug.com/964239 external/wpt/css/css-scroll-snap/scroll-margin.html [ Pass Failure ] crbug.com/965389 [ Mac ] media/track/track-cue-rendering-position-auto.html [ Pass Failure ] crbug.com/965389 [ Mac ] virtual/audio-service/media/track/track-cue-rendering-position-auto.html [ Pass Failure ]
diff --git a/third_party/blink/web_tests/external/wpt/IndexedDB/transaction-relaxed-durability.tentative.any.js b/third_party/blink/web_tests/external/wpt/IndexedDB/transaction-relaxed-durability.tentative.any.js index c6a6f37..2ba96ec 100644 --- a/third_party/blink/web_tests/external/wpt/IndexedDB/transaction-relaxed-durability.tentative.any.js +++ b/third_party/blink/web_tests/external/wpt/IndexedDB/transaction-relaxed-durability.tentative.any.js
@@ -12,8 +12,9 @@ let cases = [ undefined, {}, - {relaxedDurability: false}, - {relaxedDurability: true}, + {durability: "default"}, + {durability: "relaxed"}, + {durability: "strict"}, ]; for (let i = 0; i < cases.length; ++i) {
diff --git a/third_party/blink/web_tests/external/wpt/css/CSS2/floats/new-fc-beside-float-with-margin-rtl.html b/third_party/blink/web_tests/external/wpt/css/CSS2/floats/new-fc-beside-float-with-margin-rtl.html new file mode 100644 index 0000000..5a564f78 --- /dev/null +++ b/third_party/blink/web_tests/external/wpt/css/CSS2/floats/new-fc-beside-float-with-margin-rtl.html
@@ -0,0 +1,9 @@ +<!DOCTYPE html> +<link rel="help" href="https://www.w3.org/TR/CSS22/visuren.html#bfc-next-to-float" title="9.5 Floats"> +<meta name="assert" content="The new formatting context's margin-right does not push it down to the next area."> +<link rel="match" href="../../reference/ref-filled-green-100px-square.xht"> +<p>Test passes if there is a filled green square and <strong>no red</strong>.</p> +<div style="width: 100px; height: 100px; background: red; direction: rtl;"> + <div style="float: left; width: 50px; height: 100px; background: green;"></div> + <div style="overflow: hidden; height: 100px; margin-left: -20px; background: green;"></div> +</div>
diff --git a/third_party/blink/web_tests/external/wpt/css/CSS2/floats/new-fc-beside-float-with-margin.html b/third_party/blink/web_tests/external/wpt/css/CSS2/floats/new-fc-beside-float-with-margin.html new file mode 100644 index 0000000..ead8e54 --- /dev/null +++ b/third_party/blink/web_tests/external/wpt/css/CSS2/floats/new-fc-beside-float-with-margin.html
@@ -0,0 +1,9 @@ +<!DOCTYPE html> +<link rel="help" href="https://www.w3.org/TR/CSS22/visuren.html#bfc-next-to-float" title="9.5 Floats"> +<meta name="assert" content="The new formatting context's margin-right does not push it down to the next area."> +<link rel="match" href="../../reference/ref-filled-green-100px-square.xht"> +<p>Test passes if there is a filled green square and <strong>no red</strong>.</p> +<div style="width: 100px; height: 100px; background: red;"> + <div style="float:left; width:50px; height:100px; background:green;"></div> + <div style="overflow: hidden; margin-right: 1px; width:50px; height:100px; background:green;"></div> +</div>
diff --git a/third_party/blink/web_tests/external/wpt/css/CSS2/floats/zero-width-floats-positioning.html b/third_party/blink/web_tests/external/wpt/css/CSS2/floats/zero-width-floats-positioning.tentative.html similarity index 92% rename from third_party/blink/web_tests/external/wpt/css/CSS2/floats/zero-width-floats-positioning.html rename to third_party/blink/web_tests/external/wpt/css/CSS2/floats/zero-width-floats-positioning.tentative.html index 7f8e34d..18f8f6e 100644 --- a/third_party/blink/web_tests/external/wpt/css/CSS2/floats/zero-width-floats-positioning.html +++ b/third_party/blink/web_tests/external/wpt/css/CSS2/floats/zero-width-floats-positioning.tentative.html
@@ -4,7 +4,7 @@ <link rel="help" href="https://www.w3.org/TR/CSS22/visudet.html#float-width" title="10.3.5 Floating, non-replaced elements"> <link rel="match" href="../../reference/ref-filled-green-100px-square-only.html"> <p>Test passes if there is a filled green square.</p> -<div style="margin-left: 50px; width: 125px;"> +<div style="width: 125px;"> <div style="float: left; width: 0px; height: 50px;"></div> <div style="float: right; clear: left; width: 25px; height: 50px;"></div> <div style="overflow: hidden; margin-left: -50px; height: 100px; background: green;"></div>
diff --git a/third_party/blink/web_tests/external/wpt/css/css-content/inheritance-expected.txt b/third_party/blink/web_tests/external/wpt/css/css-content/inheritance-expected.txt new file mode 100644 index 0000000..a75fca40 --- /dev/null +++ b/third_party/blink/web_tests/external/wpt/css/css-content/inheritance-expected.txt
@@ -0,0 +1,9 @@ +This is a testharness.js-based test. +FAIL Property quotes has initial value auto assert_equals: expected "auto" but got "" +PASS Property quotes inherits +FAIL Property bookmark-level has initial value none assert_true: bookmark-level doesn't seem to be supported in the computed style expected true got false +FAIL Property bookmark-level does not inherit assert_true: expected true got false +FAIL Property bookmark-state has initial value open assert_true: bookmark-state doesn't seem to be supported in the computed style expected true got false +FAIL Property bookmark-state does not inherit assert_true: expected true got false +Harness: the test ran to completion. +
diff --git a/third_party/blink/web_tests/external/wpt/css/css-content/inheritance.html b/third_party/blink/web_tests/external/wpt/css/css-content/inheritance.html new file mode 100644 index 0000000..a324255 --- /dev/null +++ b/third_party/blink/web_tests/external/wpt/css/css-content/inheritance.html
@@ -0,0 +1,24 @@ +<!DOCTYPE html> +<html> +<head> +<meta charset="utf-8"> +<title>Inheritance of CSS Contents properties</title> +<link rel="help" href="https://drafts.csswg.org/css-content/#propdef-quotes"> +<link rel="help" href="https://drafts.csswg.org/css-content/#property-index"> +<meta name="assert" content="Properties inherit or not according to the spec."> +<meta name="assert" content="Properties have initial values according to the spec."> +<script src="/resources/testharness.js"></script> +<script src="/resources/testharnessreport.js"></script> +<script src="/css/support/inheritance-testcommon.js"></script> +</head> +<body> +<div id="container"> + <div id="target"></div> +</div> +<script> +assert_inherited('quotes', 'auto', 'none'); +assert_not_inherited('bookmark-level', 'none', '1'); +assert_not_inherited('bookmark-state', 'open', 'closed'); +</script> +</body> +</html>
diff --git a/third_party/blink/web_tests/external/wpt/css/css-grid/parsing/grid-area-shorthand.html b/third_party/blink/web_tests/external/wpt/css/css-grid/parsing/grid-area-shorthand.html new file mode 100644 index 0000000..9a26550 --- /dev/null +++ b/third_party/blink/web_tests/external/wpt/css/css-grid/parsing/grid-area-shorthand.html
@@ -0,0 +1,99 @@ +<!DOCTYPE html> +<html> +<head> +<meta charset="utf-8"> +<title>CSS Grid Layout Test: grid-area sets longhands</title> +<link rel="help" href="https://drafts.csswg.org/css-grid-1/#propdef-grid-area"> +<meta name="assert" content="grid-area supports the full grammar '<grid-line> [ / <grid-line> ]{0,3}'."> +<script src="/resources/testharness.js"></script> +<script src="/resources/testharnessreport.js"></script> +<script src="/css/support/shorthand-testcommon.js"></script> +</head> +<body> +<script> +test_shorthand_value('grid-area', 'auto', { + 'grid-row-start': 'auto', + 'grid-column-start': 'auto', + 'grid-row-end': 'auto', + 'grid-column-end': 'auto' +}); + +// <custom-ident> +test_shorthand_value('grid-area', '--a', { + 'grid-row-start': '--a', + 'grid-column-start': '--a', + 'grid-row-end': '--a', + 'grid-column-end': '--a' +}); + +test_shorthand_value('grid-area', 'a / b', { + 'grid-row-start': 'a', + 'grid-column-start': 'b', + 'grid-row-end': 'a', + 'grid-column-end': 'b' +}); + +test_shorthand_value('grid-area', 'a / b / c', { + 'grid-row-start': 'a', + 'grid-column-start': 'b', + 'grid-row-end': 'c', + 'grid-column-end': 'b' +}); + +test_shorthand_value('grid-area', 'a / b / c / d', { + 'grid-row-start': 'a', + 'grid-column-start': 'b', + 'grid-row-end': 'c', + 'grid-column-end': 'd' +}); + +// <integer> && <custom-ident>? +// span && [ <integer> || <custom-ident> ] +test_shorthand_value('grid-area', '+90 -a- / 2 i span', { + 'grid-row-start': '90 -a-', + 'grid-column-start': 'span 2 i', + 'grid-row-end': 'auto', + 'grid-column-end': 'auto' +}); + +test_shorthand_value('grid-area', '1 / 2 / 3 / 4', { + 'grid-row-start': '1', + 'grid-column-start': '2', + 'grid-row-end': '3', + 'grid-column-end': '4' +}); + + +test_shorthand_value('grid-row', 'auto', { + 'grid-row-start': 'auto', + 'grid-row-end': 'auto' +}); + +test_shorthand_value('grid-row', 'one / 2', { + 'grid-row-start': 'one', + 'grid-row-end': '2' +}); + +test_shorthand_value('grid-row', '1 two / four 3', { + 'grid-row-start': '1 two', + 'grid-row-end': '3 four' +}); + + +test_shorthand_value('grid-column', '5 span', { + 'grid-column-start': 'span 5', + 'grid-column-end': 'auto' +}); + +test_shorthand_value('grid-column', '1 / two', { + 'grid-column-start': '1', + 'grid-column-end': 'two' +}); + +test_shorthand_value('grid-column', 'span 1 two / four 3 span', { + 'grid-column-start': 'span 1 two', + 'grid-column-end': 'span 3 four' +}); +</script> +</body> +</html>
diff --git a/third_party/blink/web_tests/external/wpt/css/css-grid/parsing/grid-auto-columns-invalid.html b/third_party/blink/web_tests/external/wpt/css/css-grid/parsing/grid-auto-columns-invalid.html index 40b6059..04e0fadf 100644 --- a/third_party/blink/web_tests/external/wpt/css/css-grid/parsing/grid-auto-columns-invalid.html +++ b/third_party/blink/web_tests/external/wpt/css/css-grid/parsing/grid-auto-columns-invalid.html
@@ -32,7 +32,8 @@ // <track-size>+ test_invalid_value("grid-auto-columns", "2em / 3em"); test_invalid_value("grid-auto-columns", "auto, 10%"); -test_invalid_value("grid-auto-rows", "1px [a] 1px"); +test_invalid_value("grid-auto-columns", "1px [a] 1px"); +test_invalid_value("grid-auto-columns", "[] 1px []"); </script> </body> </html>
diff --git a/third_party/blink/web_tests/external/wpt/css/css-grid/parsing/grid-auto-rows-invalid.html b/third_party/blink/web_tests/external/wpt/css/css-grid/parsing/grid-auto-rows-invalid.html index 4111e25..1b61479 100644 --- a/third_party/blink/web_tests/external/wpt/css/css-grid/parsing/grid-auto-rows-invalid.html +++ b/third_party/blink/web_tests/external/wpt/css/css-grid/parsing/grid-auto-rows-invalid.html
@@ -32,6 +32,7 @@ test_invalid_value("grid-auto-rows", "2em / 3em"); test_invalid_value("grid-auto-rows", "auto, 10%"); test_invalid_value("grid-auto-rows", "1px [a] 1px"); +test_invalid_value("grid-auto-rows", "[] 1px []"); </script> </body> </html>
diff --git a/third_party/blink/web_tests/external/wpt/css/css-grid/parsing/grid-template-columns-valid.html b/third_party/blink/web_tests/external/wpt/css/css-grid/parsing/grid-template-columns-valid.html index 85ac76a..6bf2e7bc 100644 --- a/third_party/blink/web_tests/external/wpt/css/css-grid/parsing/grid-template-columns-valid.html +++ b/third_party/blink/web_tests/external/wpt/css/css-grid/parsing/grid-template-columns-valid.html
@@ -47,7 +47,7 @@ // 'repeat(1, 10px)' in Firefox // '[] 10px' in Safari // '10px' in Edge 18 -test_valid_value("grid-template-columns", 'repeat(1, [] 10px)', ['repeat(1, 10px)', 'repeat(1, [] 10px)']); +test_valid_value("grid-template-columns", 'repeat(1, [] 10px [])', 'repeat(1, 10px)'); // 'repeat(1, [one two] 20%)' in Blink, Firefox // '[one two] 20%' in Safari, Edge 18 @@ -61,6 +61,7 @@ // <track-list> = [ <line-names>? [ <track-size> | <track-repeat> ] ]+ <line-names>? test_valid_value("grid-template-columns", 'min-content repeat(5, minmax(10px, auto))'); +test_valid_value("grid-template-columns", '[] 150px [] 1fr []', '150px 1fr'); // <auto-repeat> = repeat( [ auto-fill | auto-fit ] , [ <line-names>? <fixed-size> ]+ <line-names>? ) test_valid_value("grid-template-columns", 'repeat(auto-fill, 10px)');
diff --git a/third_party/blink/web_tests/external/wpt/css/css-grid/parsing/grid-template-rows-valid.html b/third_party/blink/web_tests/external/wpt/css/css-grid/parsing/grid-template-rows-valid.html index ec8d64f..2d3a1ed 100644 --- a/third_party/blink/web_tests/external/wpt/css/css-grid/parsing/grid-template-rows-valid.html +++ b/third_party/blink/web_tests/external/wpt/css/css-grid/parsing/grid-template-rows-valid.html
@@ -43,11 +43,7 @@ // <track-repeat> = repeat( [ <positive-integer> ] , [ <line-names>? <track-size> ]+ <line-names>? ) -// 'repeat(1, [] 10px)' in Blink -// 'repeat(1, 10px)' in Firefox -// '[] 10px' in Safari -// '10px' in Edge 18 -test_valid_value("grid-template-rows", 'repeat(1, [] 10px)', ['repeat(1, 10px)', 'repeat(1, [] 10px)']); +test_valid_value("grid-template-rows", 'repeat(1, [] 10px [])', 'repeat(1, 10px)'); // 'repeat(1, [one two] 20%)' in Blink, Firefox // '[one two] 20%' in Safari, Edge 18 @@ -61,6 +57,7 @@ // <track-list> = [ <line-names>? [ <track-size> | <track-repeat> ] ]+ <line-names>? test_valid_value("grid-template-rows", 'min-content repeat(5, minmax(10px, auto))'); +test_valid_value("grid-template-rows", '[] 150px [] 1fr []', '150px 1fr'); // <auto-repeat> = repeat( [ auto-fill | auto-fit ] , [ <line-names>? <fixed-size> ]+ <line-names>? ) test_valid_value("grid-template-rows", 'repeat(auto-fill, 10px)');
diff --git a/third_party/blink/web_tests/external/wpt/css/css-grid/parsing/grid-template-shorthand.html b/third_party/blink/web_tests/external/wpt/css/css-grid/parsing/grid-template-shorthand.html new file mode 100644 index 0000000..b916535 --- /dev/null +++ b/third_party/blink/web_tests/external/wpt/css/css-grid/parsing/grid-template-shorthand.html
@@ -0,0 +1,62 @@ +<!DOCTYPE html> +<html> +<head> +<meta charset="utf-8"> +<title>CSS Grid Layout Test: grid-template sets longhands</title> +<link rel="help" href="https://drafts.csswg.org/css-grid-1/#propdef-grid-template"> +<meta name="assert" content="grid-template supports the full grammar 'none | [ <grid-template-rows> / <grid-template-columns> ] | [ <line-names>? <string> <track-size>? <line-names>? ]+ [ / <explicit-track-list> ]?'."> +<script src="/resources/testharness.js"></script> +<script src="/resources/testharnessreport.js"></script> +<script src="/css/support/shorthand-testcommon.js"></script> +</head> +<body> +<script> +test_shorthand_value('grid-template', 'none', { + 'grid-template-rows': 'none', + 'grid-template-columns': 'none', + 'grid-template-areas': 'none' +}); + +// <grid-template-rows> / <grid-template-columns> +test_shorthand_value('grid-template', '10px / 20%', { + 'grid-template-rows': '10px', + 'grid-template-columns': '20%', + 'grid-template-areas': 'none' +}); + +test_shorthand_value('grid-template', 'fit-content(calc(-0.5em + 10px)) / fit-content(calc(0.5em + 10px))', { + 'grid-template-rows': 'fit-content(calc(-0.5em + 10px))', + 'grid-template-columns': 'fit-content(calc(0.5em + 10px))', + 'grid-template-areas': 'none' +}); + +// [ <line-names>? <string> <track-size>? <line-names>? ]+ [ / <explicit-track-list> ]? +test_shorthand_value('grid-template', + '[header-top] "a a a" [header-bottom]' + + ' [main-top] "b b b" 1fr [main-bottom]' + + ' / auto 1fr auto', { + 'grid-template-rows': '[header-top] auto [header-bottom main-top] 1fr [main-bottom]', + 'grid-template-columns': 'auto 1fr auto', + 'grid-template-areas': '"a a a" "b b b"' +}); + +test_shorthand_value('grid-template', + ' "a a a"' + + ' "b b b" 1fr' + + '/ auto 1fr auto', { + 'grid-template-rows': 'auto 1fr', + 'grid-template-columns': 'auto 1fr auto', + 'grid-template-areas': '"a a a" "b b b"' +}); + +test_shorthand_value('grid-template', + ' [] "a a a" []' + + ' [] "b b b" 1fr []' + + ' / [] auto 1fr [] auto []', { + 'grid-template-rows': 'auto 1fr', + 'grid-template-columns': 'auto 1fr auto', + 'grid-template-areas': '"a a a" "b b b"' +}); +</script> +</body> +</html>
diff --git a/third_party/blink/web_tests/external/wpt/css/css-scroll-snap/scroll-margin.html b/third_party/blink/web_tests/external/wpt/css/css-scroll-snap/scroll-margin.html index c85232e..e6ce4ac4 100644 --- a/third_party/blink/web_tests/external/wpt/css/css-scroll-snap/scroll-margin.html +++ b/third_party/blink/web_tests/external/wpt/css/css-scroll-snap/scroll-margin.html
@@ -58,14 +58,31 @@ test(() => { target.style.left = "0px"; target.style.top = "0px"; - target.style.scrollSnapAlign = "start"; - target.style.scrollMargin = "100px"; - // Scroll to the position between #target and #another-target elements but - // if the scroll-margin 100px contributed to the snap start-aligned snap - // position it will be farther than #another-target. - scroller.scrollTo(200, 200); + // Since the target is at (0px, 0px) in the scroll port, the added margin + // should not be considered, and the snap points for this snap area should be + // the closest points in the scroll port (i.e x=0 or y=0). + target.style.scrollMargin = "200px"; + + // Distance from target without margin: + // `scroll position (150px, 150px)` - `target position (0px, 0px)` + // = (150px, 150px) + // + // Distance from target with margin: + // `scroll position (150px, 150px)` - [`target position (0px, 0px)` - + // `target margin (200px, 200px)`] + // = (350px, 350px) + // + // Distance from other target: + // `other target position (400px, 400px)` - `scroll position (150px, 150px)` + // = (250px, 250px) + // + // Therefore if the "out-of-scrollport" scroll-margin contributes to the + // calculation, then the other target would be snapped to. However if the + // scroll-margin is not considered, then the (0px, 0px) target should be + // snapped to. + scroller.scrollTo(150, 150); assert_equals(scroller.scrollLeft, 0); assert_equals(scroller.scrollTop, 0); }, "scroll-margin doesn't contribute to the snap position of the element " +
diff --git a/third_party/blink/web_tests/external/wpt/css/css-transitions/parsing/transition-timing-function-computed.html b/third_party/blink/web_tests/external/wpt/css/css-transitions/parsing/transition-timing-function-computed.html index 9834dfd..e57856b 100644 --- a/third_party/blink/web_tests/external/wpt/css/css-transitions/parsing/transition-timing-function-computed.html +++ b/third_party/blink/web_tests/external/wpt/css/css-transitions/parsing/transition-timing-function-computed.html
@@ -13,6 +13,8 @@ <div id="target"></div> <script> test_computed_value("transition-timing-function", "linear"); +test_computed_value("transition-timing-function", "", "ease"); +test_computed_value("transition-timing-function", "initial", "ease"); test_computed_value("transition-timing-function", "ease"); test_computed_value("transition-timing-function", "ease-in"); @@ -22,7 +24,9 @@ test_computed_value("transition-timing-function", "cubic-bezier(0, -2, 1, 3)"); test_computed_value("transition-timing-function", "cubic-bezier(0, 0.7, 1, 1.3)"); - +test_computed_value("transition-timing-function", "step-start", "steps(1, start)"); +test_computed_value("transition-timing-function", "step-end", "steps(1)"); +test_computed_value("transition-timing-function", "steps(4)"); test_computed_value("transition-timing-function", "steps(4, start)"); test_computed_value("transition-timing-function", "steps(2, end)", "steps(2)"); test_computed_value("transition-timing-function", "steps(2, jump-start)");
diff --git a/third_party/blink/web_tests/external/wpt/css/css-transitions/parsing/transition-timing-function-invalid.html b/third_party/blink/web_tests/external/wpt/css/css-transitions/parsing/transition-timing-function-invalid.html index 00bd213..d736ef0 100644 --- a/third_party/blink/web_tests/external/wpt/css/css-transitions/parsing/transition-timing-function-invalid.html +++ b/third_party/blink/web_tests/external/wpt/css/css-transitions/parsing/transition-timing-function-invalid.html
@@ -14,11 +14,23 @@ <script> test_invalid_value("transition-timing-function", "auto"); test_invalid_value("transition-timing-function", "ease-in ease-out"); + +test_invalid_value("transition-timing-function", "cubic-bezier(foobar)"); test_invalid_value("transition-timing-function", "cubic-bezier(1, 2, 3)"); test_invalid_value("transition-timing-function", "cubic-bezier(1, 2, 3, infinite)"); test_invalid_value("transition-timing-function", "cubic-bezier(1, 2, 3, 4, 5)"); test_invalid_value("transition-timing-function", "cubic-bezier(-0.1, 0.1, 0.5, 0.9)"); test_invalid_value("transition-timing-function", "cubic-bezier(0.5, 0.1, 1.1, 0.9)"); + +test_invalid_value("transition-timing-function", "steps(foobar)"); +test_invalid_value("transition-timing-function", "steps(3.3, end)"); +test_invalid_value("transition-timing-function", "steps(3, top)"); +test_invalid_value("transition-timing-function", "steps(-3, top)"); +test_invalid_value("transition-timing-function", "steps(0, jump-start)"); +test_invalid_value("transition-timing-function", "steps(0, jump-end)"); +test_invalid_value("transition-timing-function", "steps(0, jump-both)"); +test_invalid_value("transition-timing-function", "steps(1, jump-none)"); + </script> </body> </html>
diff --git a/third_party/blink/web_tests/external/wpt/css/css-transitions/parsing/transition-timing-function-valid-expected.txt b/third_party/blink/web_tests/external/wpt/css/css-transitions/parsing/transition-timing-function-valid-expected.txt new file mode 100644 index 0000000..0d8cfd0 --- /dev/null +++ b/third_party/blink/web_tests/external/wpt/css/css-transitions/parsing/transition-timing-function-valid-expected.txt
@@ -0,0 +1,21 @@ +This is a testharness.js-based test. +PASS e.style['transition-timing-function'] = "linear" should set the property value +PASS e.style['transition-timing-function'] = "ease" should set the property value +PASS e.style['transition-timing-function'] = "ease-in" should set the property value +PASS e.style['transition-timing-function'] = "ease-out" should set the property value +PASS e.style['transition-timing-function'] = "ease-in-out" should set the property value +PASS e.style['transition-timing-function'] = "cubic-bezier(0.1, 0.2, 0.8, 0.9)" should set the property value +PASS e.style['transition-timing-function'] = "cubic-bezier(0, -2, 1, 3)" should set the property value +PASS e.style['transition-timing-function'] = "cubic-bezier(0, 0.7, 1, 1.3)" should set the property value +FAIL e.style['transition-timing-function'] = "step-start" should set the property value assert_equals: serialization should be canonical expected "steps(1, start)" but got "step-start" +FAIL e.style['transition-timing-function'] = "step-end" should set the property value assert_equals: serialization should be canonical expected "steps(1)" but got "step-end" +PASS e.style['transition-timing-function'] = "steps(4)" should set the property value +PASS e.style['transition-timing-function'] = "steps(4, start)" should set the property value +PASS e.style['transition-timing-function'] = "steps(2, end)" should set the property value +PASS e.style['transition-timing-function'] = "steps(2, jump-start)" should set the property value +PASS e.style['transition-timing-function'] = "steps(2, jump-end)" should set the property value +PASS e.style['transition-timing-function'] = "steps(2, jump-both)" should set the property value +PASS e.style['transition-timing-function'] = "steps(2, jump-none)" should set the property value +PASS e.style['transition-timing-function'] = "linear, ease, linear" should set the property value +Harness: the test ran to completion. +
diff --git a/third_party/blink/web_tests/external/wpt/css/css-transitions/parsing/transition-timing-function-valid.html b/third_party/blink/web_tests/external/wpt/css/css-transitions/parsing/transition-timing-function-valid.html index 2e2c182..5402fda 100644 --- a/third_party/blink/web_tests/external/wpt/css/css-transitions/parsing/transition-timing-function-valid.html +++ b/third_party/blink/web_tests/external/wpt/css/css-transitions/parsing/transition-timing-function-valid.html
@@ -22,6 +22,9 @@ test_valid_value("transition-timing-function", "cubic-bezier(0, -2, 1, 3)"); test_valid_value("transition-timing-function", "cubic-bezier(0, 0.7, 1, 1.3)"); +test_valid_value("transition-timing-function", "step-start", "steps(1, start)"); +test_valid_value("transition-timing-function", "step-end", "steps(1)"); +test_valid_value("transition-timing-function", "steps(4)"); test_valid_value("transition-timing-function", "steps(4, start)"); test_valid_value("transition-timing-function", "steps(2, end)", "steps(2)"); test_valid_value("transition-timing-function", "steps(2, jump-start)");
diff --git a/third_party/blink/web_tests/external/wpt/css/css-transitions/transition-delay-000.html b/third_party/blink/web_tests/external/wpt/css/css-transitions/transition-delay-000-manual.html similarity index 96% rename from third_party/blink/web_tests/external/wpt/css/css-transitions/transition-delay-000.html rename to third_party/blink/web_tests/external/wpt/css/css-transitions/transition-delay-000-manual.html index 2b4cedb..b2050859 100644 --- a/third_party/blink/web_tests/external/wpt/css/css-transitions/transition-delay-000.html +++ b/third_party/blink/web_tests/external/wpt/css/css-transitions/transition-delay-000-manual.html
@@ -4,7 +4,6 @@ <link rel="author" title="Intel" href="http://www.intel.com"> <link rel="author" title="Shiyou Tan" href="mailto:shiyoux.tan@intel.com"> <link rel="help" title="2.4. The 'transition-delay' Property" href="http://www.w3.org/TR/css3-transitions/#transition-delay-property"> -<meta name="flags" content="interact"> <meta name="assert" content="The 'transition-delay' property set positive number to delay the execution of transition"> <style> #test {
diff --git a/third_party/blink/web_tests/external/wpt/css/css-transitions/transition-delay-002.html b/third_party/blink/web_tests/external/wpt/css/css-transitions/transition-delay-002-manual.html similarity index 93% rename from third_party/blink/web_tests/external/wpt/css/css-transitions/transition-delay-002.html rename to third_party/blink/web_tests/external/wpt/css/css-transitions/transition-delay-002-manual.html index 70e952b..168f94b 100644 --- a/third_party/blink/web_tests/external/wpt/css/css-transitions/transition-delay-002.html +++ b/third_party/blink/web_tests/external/wpt/css/css-transitions/transition-delay-002-manual.html
@@ -4,7 +4,6 @@ <link rel="author" title="Intel" href="http://www.intel.com"> <link rel="author" title="Shiyou Tan" href="mailto:shiyoux.tan@intel.com"> <link rel="help" title="2.4. The 'transition-delay' Property" href="http://www.w3.org/TR/css3-transitions/#transition-delay-property"> -<meta name="flags" content="interact"> <meta name="assert" content="Test checks that the 'transition-delay' property set 0 will not delay the execution of transition"> <style> div { @@ -33,7 +32,7 @@ test.addEventListener("click", function(evt) { if (clicked == 0) { ref.setAttribute("style", "background-color: green;"); - setInterval(function() {console.log(clicked); + setInterval(function() { if (clicked == 2) { test.setAttribute("style", "background-color: green;"); }
diff --git a/third_party/blink/web_tests/external/wpt/css/css-transitions/transition-delay-003.html b/third_party/blink/web_tests/external/wpt/css/css-transitions/transition-delay-003-manual.html similarity index 93% rename from third_party/blink/web_tests/external/wpt/css/css-transitions/transition-delay-003.html rename to third_party/blink/web_tests/external/wpt/css/css-transitions/transition-delay-003-manual.html index 3062e9a..e3680ca 100644 --- a/third_party/blink/web_tests/external/wpt/css/css-transitions/transition-delay-003.html +++ b/third_party/blink/web_tests/external/wpt/css/css-transitions/transition-delay-003-manual.html
@@ -4,7 +4,6 @@ <link rel="author" title="Intel" href="http://www.intel.com"> <link rel="author" title="Shiyou Tan" href="mailto:shiyoux.tan@intel.com"> <link rel="help" title="2.4. The 'transition-delay' Property" href="http://www.w3.org/TR/css3-transitions/#transition-delay-property"> -<meta name="flags" content="interact"> <meta name="assert" content="Test checks that the 'transition-delay' property set negative number will not delay the execution of transition"> <style> div { @@ -33,7 +32,7 @@ test.addEventListener("click", function(evt) { if (clicked == 0) { ref.setAttribute("style", "background-color: green;"); - setInterval(function() {console.log(clicked); + setInterval(function() { if (clicked == 2) { test.setAttribute("style", "background-color: green;"); }
diff --git a/third_party/blink/web_tests/external/wpt/css/css-transitions/transition-duration-002.html b/third_party/blink/web_tests/external/wpt/css/css-transitions/transition-duration-002-manual.html similarity index 96% rename from third_party/blink/web_tests/external/wpt/css/css-transitions/transition-duration-002.html rename to third_party/blink/web_tests/external/wpt/css/css-transitions/transition-duration-002-manual.html index e9ba5760..03f514d3 100644 --- a/third_party/blink/web_tests/external/wpt/css/css-transitions/transition-duration-002.html +++ b/third_party/blink/web_tests/external/wpt/css/css-transitions/transition-duration-002-manual.html
@@ -4,7 +4,6 @@ <link rel="author" title="Intel" href="http://www.intel.com"> <link rel="author" title="Shiyou Tan" href="mailto:shiyoux.tan@intel.com"> <link rel="help" title="2.2. The 'transition-duration' Property" href="http://www.w3.org/TR/css3-transitions/#transition-duration-property"> -<meta name="flags" content="interact"> <meta name="assert" content="The 'transition-duration' property set positive number specifies the time that transition from the old value to the new value should take."> <style> div {
diff --git a/third_party/blink/web_tests/external/wpt/css/css-transitions/transition-duration-003.html b/third_party/blink/web_tests/external/wpt/css/css-transitions/transition-duration-003-manual.html similarity index 97% rename from third_party/blink/web_tests/external/wpt/css/css-transitions/transition-duration-003.html rename to third_party/blink/web_tests/external/wpt/css/css-transitions/transition-duration-003-manual.html index bb68b5f..cb56100 100644 --- a/third_party/blink/web_tests/external/wpt/css/css-transitions/transition-duration-003.html +++ b/third_party/blink/web_tests/external/wpt/css/css-transitions/transition-duration-003-manual.html
@@ -4,7 +4,6 @@ <link rel="author" title="Intel" href="http://www.intel.com"> <link rel="author" title="Shiyou Tan" href="mailto:shiyoux.tan@intel.com"> <link rel="help" title="2.2. The 'transition-duration' Property" href="http://www.w3.org/TR/css3-transitions/#transition-duration-property"> -<meta name="flags" content="interact"> <meta name="assert" content="Test checks that the initial value of 'transition-duration' property is '0s' which means the transition is immediate."> <style> div {
diff --git a/third_party/blink/web_tests/external/wpt/css/css-transitions/transition-duration-004.html b/third_party/blink/web_tests/external/wpt/css/css-transitions/transition-duration-004-manual.html similarity index 96% rename from third_party/blink/web_tests/external/wpt/css/css-transitions/transition-duration-004.html rename to third_party/blink/web_tests/external/wpt/css/css-transitions/transition-duration-004-manual.html index 01c424733..b93904bb 100644 --- a/third_party/blink/web_tests/external/wpt/css/css-transitions/transition-duration-004.html +++ b/third_party/blink/web_tests/external/wpt/css/css-transitions/transition-duration-004-manual.html
@@ -4,7 +4,6 @@ <link rel="author" title="Intel" href="http://www.intel.com"> <link rel="author" title="Shiyou Tan" href="mailto:shiyoux.tan@intel.com"> <link rel="help" title="2.2. The 'transition-duration' Property" href="http://www.w3.org/TR/css3-transitions/#transition-duration-property"> -<meta name="flags" content="interact"> <meta name="assert" content="A negative value for 'transition-duration renders the declaration invalid which means the transition is immediate."> <style> div {
diff --git a/third_party/blink/web_tests/external/wpt/css/css-transitions/transition-property-003.html b/third_party/blink/web_tests/external/wpt/css/css-transitions/transition-property-003-manual.html similarity index 96% rename from third_party/blink/web_tests/external/wpt/css/css-transitions/transition-property-003.html rename to third_party/blink/web_tests/external/wpt/css/css-transitions/transition-property-003-manual.html index 17668b05..291204d 100644 --- a/third_party/blink/web_tests/external/wpt/css/css-transitions/transition-property-003.html +++ b/third_party/blink/web_tests/external/wpt/css/css-transitions/transition-property-003-manual.html
@@ -4,7 +4,6 @@ <link rel="author" title="Intel" href="http://www.intel.com"> <link rel="author" title="Shiyou Tan" href="mailto:shiyoux.tan@intel.com"> <link rel="help" title="2.1. The 'transition-property' Property" href="http://www.w3.org/TR/css3-transitions/#transition-property-property"> -<meta name="flags" content="interact"> <meta name="assert" content="The 'transition-duration' property set 'none' means that no property will be transitioned."> <style> div {
diff --git a/third_party/blink/web_tests/external/wpt/css/css-transitions/transition-property-004.html b/third_party/blink/web_tests/external/wpt/css/css-transitions/transition-property-004-manual.html similarity index 96% rename from third_party/blink/web_tests/external/wpt/css/css-transitions/transition-property-004.html rename to third_party/blink/web_tests/external/wpt/css/css-transitions/transition-property-004-manual.html index 6393c6e..d2e84c9 100644 --- a/third_party/blink/web_tests/external/wpt/css/css-transitions/transition-property-004.html +++ b/third_party/blink/web_tests/external/wpt/css/css-transitions/transition-property-004-manual.html
@@ -4,7 +4,6 @@ <link rel="author" title="Intel" href="http://www.intel.com"> <link rel="author" title="Shiyou Tan" href="mailto:shiyoux.tan@intel.com"> <link rel="help" title="2.1. The 'transition-property' Property" href="http://www.w3.org/TR/css3-transitions/#transition-property-property"> -<meta name="flags" content="interact"> <meta name="assert" content="The 'transition-duration' property set 'all' means that all properties are transitioned."> <style> #test {
diff --git a/third_party/blink/web_tests/external/wpt/css/css-transitions/transition-property-005.html b/third_party/blink/web_tests/external/wpt/css/css-transitions/transition-property-005-manual.html similarity index 96% rename from third_party/blink/web_tests/external/wpt/css/css-transitions/transition-property-005.html rename to third_party/blink/web_tests/external/wpt/css/css-transitions/transition-property-005-manual.html index a10ff4a..e699410 100644 --- a/third_party/blink/web_tests/external/wpt/css/css-transitions/transition-property-005.html +++ b/third_party/blink/web_tests/external/wpt/css/css-transitions/transition-property-005-manual.html
@@ -4,7 +4,6 @@ <link rel="author" title="Intel" href="http://www.intel.com"> <link rel="author" title="Shiyou Tan" href="mailto:shiyoux.tan@intel.com"> <link rel="help" title="2.1. The 'transition-property' Property" href="http://www.w3.org/TR/css3-transitions/#transition-property-property"> -<meta name="flags" content="interact"> <meta name="assert" content="The 'transition-duration' property set more than one properties like 'height, width' means only the specified properties will be transitioned."> <style>
diff --git a/third_party/blink/web_tests/external/wpt/css/css-transitions/transition-property-006.html b/third_party/blink/web_tests/external/wpt/css/css-transitions/transition-property-006-manual.html similarity index 96% rename from third_party/blink/web_tests/external/wpt/css/css-transitions/transition-property-006.html rename to third_party/blink/web_tests/external/wpt/css/css-transitions/transition-property-006-manual.html index e7d8c5e3..6032a401 100644 --- a/third_party/blink/web_tests/external/wpt/css/css-transitions/transition-property-006.html +++ b/third_party/blink/web_tests/external/wpt/css/css-transitions/transition-property-006-manual.html
@@ -4,7 +4,6 @@ <link rel="author" title="Intel" href="http://www.intel.com"> <link rel="author" title="Shiyou Tan" href="mailto:shiyoux.tan@intel.com"> <link rel="help" title="7.1. Properties from CSS" href="http://www.w3.org/TR/css3-transitions/#animatable-css"> -<meta name="flags" content="interact"> <meta name="assert" content="Test checks that the 'background-position' property is animatable."> <style> #test {
diff --git a/third_party/blink/web_tests/external/wpt/css/css-transitions/transition-property-007.html b/third_party/blink/web_tests/external/wpt/css/css-transitions/transition-property-007-manual.html similarity index 96% rename from third_party/blink/web_tests/external/wpt/css/css-transitions/transition-property-007.html rename to third_party/blink/web_tests/external/wpt/css/css-transitions/transition-property-007-manual.html index 0d006fe..898aea5b 100644 --- a/third_party/blink/web_tests/external/wpt/css/css-transitions/transition-property-007.html +++ b/third_party/blink/web_tests/external/wpt/css/css-transitions/transition-property-007-manual.html
@@ -4,7 +4,6 @@ <link rel="author" title="Intel" href="http://www.intel.com"> <link rel="author" title="Shiyou Tan" href="mailto:shiyoux.tan@intel.com"> <link rel="help" title="7.1. Properties from CSS" href="http://www.w3.org/TR/css3-transitions/#animatable-css"> -<meta name="flags" content="interact"> <meta name="assert" content="Test checks that the 'border-bottom-color' property animatable."> <style> #test {
diff --git a/third_party/blink/web_tests/external/wpt/css/css-transitions/transition-property-008.html b/third_party/blink/web_tests/external/wpt/css/css-transitions/transition-property-008-manual.html similarity index 96% rename from third_party/blink/web_tests/external/wpt/css/css-transitions/transition-property-008.html rename to third_party/blink/web_tests/external/wpt/css/css-transitions/transition-property-008-manual.html index 47ca1eee..53caa10 100644 --- a/third_party/blink/web_tests/external/wpt/css/css-transitions/transition-property-008.html +++ b/third_party/blink/web_tests/external/wpt/css/css-transitions/transition-property-008-manual.html
@@ -4,7 +4,6 @@ <link rel="author" title="Intel" href="http://www.intel.com"> <link rel="author" title="Shiyou Tan" href="mailto:shiyoux.tan@intel.com"> <link rel="help" title="7.1. Properties from CSS" href="http://www.w3.org/TR/css3-transitions/#animatable-css"> -<meta name="flags" content="interact"> <meta name="assert" content="Test checks that the 'border-bottom-width' property animatable."> <style> #test {
diff --git a/third_party/blink/web_tests/external/wpt/css/css-transitions/transition-property-009.html b/third_party/blink/web_tests/external/wpt/css/css-transitions/transition-property-009-manual.html similarity index 96% rename from third_party/blink/web_tests/external/wpt/css/css-transitions/transition-property-009.html rename to third_party/blink/web_tests/external/wpt/css/css-transitions/transition-property-009-manual.html index b45948b..5f27285 100644 --- a/third_party/blink/web_tests/external/wpt/css/css-transitions/transition-property-009.html +++ b/third_party/blink/web_tests/external/wpt/css/css-transitions/transition-property-009-manual.html
@@ -4,7 +4,6 @@ <link rel="author" title="Intel" href="http://www.intel.com"> <link rel="author" title="Shiyou Tan" href="mailto:shiyoux.tan@intel.com"> <link rel="help" title="7.1. Properties from CSS" href="http://www.w3.org/TR/css3-transitions/#animatable-css"> -<meta name="flags" content="interact"> <meta name="assert" content="Test checks that the 'border-left-color' property is animatable."> <style> #test {
diff --git a/third_party/blink/web_tests/external/wpt/css/css-transitions/transition-property-010.html b/third_party/blink/web_tests/external/wpt/css/css-transitions/transition-property-010-manual.html similarity index 96% rename from third_party/blink/web_tests/external/wpt/css/css-transitions/transition-property-010.html rename to third_party/blink/web_tests/external/wpt/css/css-transitions/transition-property-010-manual.html index f05f6aa..a7e06ef7 100644 --- a/third_party/blink/web_tests/external/wpt/css/css-transitions/transition-property-010.html +++ b/third_party/blink/web_tests/external/wpt/css/css-transitions/transition-property-010-manual.html
@@ -4,7 +4,6 @@ <link rel="author" title="Intel" href="http://www.intel.com"> <link rel="author" title="Shiyou Tan" href="mailto:shiyoux.tan@intel.com"> <link rel="help" title="7.1. Properties from CSS" href="http://www.w3.org/TR/css3-transitions/#animatable-css"> -<meta name="flags" content="interact"> <meta name="assert" content="Test checks that the 'border-left-width' property is animatable."> <style> #test {
diff --git a/third_party/blink/web_tests/external/wpt/css/css-transitions/transition-property-011.html b/third_party/blink/web_tests/external/wpt/css/css-transitions/transition-property-011-manual.html similarity index 96% rename from third_party/blink/web_tests/external/wpt/css/css-transitions/transition-property-011.html rename to third_party/blink/web_tests/external/wpt/css/css-transitions/transition-property-011-manual.html index 7b3716d..3799ad2 100644 --- a/third_party/blink/web_tests/external/wpt/css/css-transitions/transition-property-011.html +++ b/third_party/blink/web_tests/external/wpt/css/css-transitions/transition-property-011-manual.html
@@ -4,7 +4,6 @@ <link rel="author" title="Intel" href="http://www.intel.com"> <link rel="author" title="Shiyou Tan" href="mailto:shiyoux.tan@intel.com"> <link rel="help" title="7.1. Properties from CSS" href="http://www.w3.org/TR/css3-transitions/#animatable-css"> -<meta name="flags" content="interact"> <meta name="assert" content="Test checks that the 'border-right-color' property is animatable."> <style> #test {
diff --git a/third_party/blink/web_tests/external/wpt/css/css-transitions/transition-property-012.html b/third_party/blink/web_tests/external/wpt/css/css-transitions/transition-property-012-manual.html similarity index 96% rename from third_party/blink/web_tests/external/wpt/css/css-transitions/transition-property-012.html rename to third_party/blink/web_tests/external/wpt/css/css-transitions/transition-property-012-manual.html index 0e19e52..8587e26 100644 --- a/third_party/blink/web_tests/external/wpt/css/css-transitions/transition-property-012.html +++ b/third_party/blink/web_tests/external/wpt/css/css-transitions/transition-property-012-manual.html
@@ -4,7 +4,6 @@ <link rel="author" title="Intel" href="http://www.intel.com"> <link rel="author" title="Shiyou Tan" href="mailto:shiyoux.tan@intel.com"> <link rel="help" title="7.1. Properties from CSS" href="http://www.w3.org/TR/css3-transitions/#animatable-css"> -<meta name="flags" content="interact"> <meta name="assert" content="Test checks that the 'border-right-width' property is animatable."> <style> #test {
diff --git a/third_party/blink/web_tests/external/wpt/css/css-transitions/transition-property-013.html b/third_party/blink/web_tests/external/wpt/css/css-transitions/transition-property-013-manual.html similarity index 96% rename from third_party/blink/web_tests/external/wpt/css/css-transitions/transition-property-013.html rename to third_party/blink/web_tests/external/wpt/css/css-transitions/transition-property-013-manual.html index 9fb075b..3b13c038 100644 --- a/third_party/blink/web_tests/external/wpt/css/css-transitions/transition-property-013.html +++ b/third_party/blink/web_tests/external/wpt/css/css-transitions/transition-property-013-manual.html
@@ -4,7 +4,6 @@ <link rel="author" title="Intel" href="http://www.intel.com"> <link rel="author" title="Shiyou Tan" href="mailto:shiyoux.tan@intel.com"> <link rel="help" title="7.1. Properties from CSS" href="http://www.w3.org/TR/css3-transitions/#animatable-css"> -<meta name="flags" content="interact"> <meta name="assert" content="Test checks that the 'border-top-color' property is animatable."> <style> #test {
diff --git a/third_party/blink/web_tests/external/wpt/css/css-transitions/transition-property-014.html b/third_party/blink/web_tests/external/wpt/css/css-transitions/transition-property-014-manual.html similarity index 96% rename from third_party/blink/web_tests/external/wpt/css/css-transitions/transition-property-014.html rename to third_party/blink/web_tests/external/wpt/css/css-transitions/transition-property-014-manual.html index 91075ff..d4aca380 100644 --- a/third_party/blink/web_tests/external/wpt/css/css-transitions/transition-property-014.html +++ b/third_party/blink/web_tests/external/wpt/css/css-transitions/transition-property-014-manual.html
@@ -4,7 +4,6 @@ <link rel="author" title="Intel" href="http://www.intel.com"> <link rel="author" title="Shiyou Tan" href="mailto:shiyoux.tan@intel.com"> <link rel="help" title="7.1. Properties from CSS" href="http://www.w3.org/TR/css3-transitions/#animatable-css"> -<meta name="flags" content="interact"> <meta name="assert" content="Test checks that the 'border-top-width' property is animatable."> <style> #test {
diff --git a/third_party/blink/web_tests/external/wpt/css/css-transitions/transition-property-015.html b/third_party/blink/web_tests/external/wpt/css/css-transitions/transition-property-015-manual.html similarity index 96% rename from third_party/blink/web_tests/external/wpt/css/css-transitions/transition-property-015.html rename to third_party/blink/web_tests/external/wpt/css/css-transitions/transition-property-015-manual.html index b37d4fc..e5805bc 100644 --- a/third_party/blink/web_tests/external/wpt/css/css-transitions/transition-property-015.html +++ b/third_party/blink/web_tests/external/wpt/css/css-transitions/transition-property-015-manual.html
@@ -4,7 +4,6 @@ <link rel="author" title="Intel" href="http://www.intel.com"> <link rel="author" title="Shiyou Tan" href="mailto:shiyoux.tan@intel.com"> <link rel="help" title="7.1. Properties from CSS" href="http://www.w3.org/TR/css3-transitions/#animatable-css"> -<meta name="flags" content="interact"> <meta name="assert" content="Test checks that the 'border-spacing' property is animatable."> <style> #test {
diff --git a/third_party/blink/web_tests/external/wpt/css/css-transitions/transition-property-016.html b/third_party/blink/web_tests/external/wpt/css/css-transitions/transition-property-016-manual.html similarity index 96% rename from third_party/blink/web_tests/external/wpt/css/css-transitions/transition-property-016.html rename to third_party/blink/web_tests/external/wpt/css/css-transitions/transition-property-016-manual.html index 2670cd7..d2cc57c 100644 --- a/third_party/blink/web_tests/external/wpt/css/css-transitions/transition-property-016.html +++ b/third_party/blink/web_tests/external/wpt/css/css-transitions/transition-property-016-manual.html
@@ -4,7 +4,6 @@ <link rel="author" title="Intel" href="http://www.intel.com"> <link rel="author" title="Shiyou Tan" href="mailto:shiyoux.tan@intel.com"> <link rel="help" title="7.1. Properties from CSS" href="http://www.w3.org/TR/css3-transitions/#animatable-css"> -<meta name="flags" content="interact"> <meta name="assert" content="Test checks that the 'bottom' property is animatable."> <style> #test {
diff --git a/third_party/blink/web_tests/external/wpt/css/css-transitions/transition-property-017.html b/third_party/blink/web_tests/external/wpt/css/css-transitions/transition-property-017-manual.html similarity index 96% rename from third_party/blink/web_tests/external/wpt/css/css-transitions/transition-property-017.html rename to third_party/blink/web_tests/external/wpt/css/css-transitions/transition-property-017-manual.html index 3b94ecd..f24c51a7 100644 --- a/third_party/blink/web_tests/external/wpt/css/css-transitions/transition-property-017.html +++ b/third_party/blink/web_tests/external/wpt/css/css-transitions/transition-property-017-manual.html
@@ -4,7 +4,6 @@ <link rel="author" title="Intel" href="http://www.intel.com"> <link rel="author" title="Shiyou Tan" href="mailto:shiyoux.tan@intel.com"> <link rel="help" title="7.1. Properties from CSS" href="http://www.w3.org/TR/css3-transitions/#animatable-css"> -<meta name="flags" content="interact"> <meta name="assert" content="Test checks that the 'clip' property is animatable."> <style> #test {
diff --git a/third_party/blink/web_tests/external/wpt/css/css-transitions/transition-property-018.html b/third_party/blink/web_tests/external/wpt/css/css-transitions/transition-property-018-manual.html similarity index 95% rename from third_party/blink/web_tests/external/wpt/css/css-transitions/transition-property-018.html rename to third_party/blink/web_tests/external/wpt/css/css-transitions/transition-property-018-manual.html index 593e3ff..e0b6bd9 100644 --- a/third_party/blink/web_tests/external/wpt/css/css-transitions/transition-property-018.html +++ b/third_party/blink/web_tests/external/wpt/css/css-transitions/transition-property-018-manual.html
@@ -4,7 +4,6 @@ <link rel="author" title="Intel" href="http://www.intel.com"> <link rel="author" title="Shiyou Tan" href="mailto:shiyoux.tan@intel.com"> <link rel="help" title="7.1. Properties from CSS" href="http://www.w3.org/TR/css3-transitions/#animatable-css"> -<meta name="flags" content="interact"> <meta name="assert" content="Test checks that the 'color' property is animatable."> <style> #test {
diff --git a/third_party/blink/web_tests/external/wpt/css/css-transitions/transition-property-019.html b/third_party/blink/web_tests/external/wpt/css/css-transitions/transition-property-019-manual.html similarity index 96% rename from third_party/blink/web_tests/external/wpt/css/css-transitions/transition-property-019.html rename to third_party/blink/web_tests/external/wpt/css/css-transitions/transition-property-019-manual.html index 83f9000..24751292 100644 --- a/third_party/blink/web_tests/external/wpt/css/css-transitions/transition-property-019.html +++ b/third_party/blink/web_tests/external/wpt/css/css-transitions/transition-property-019-manual.html
@@ -4,7 +4,6 @@ <link rel="author" title="Intel" href="http://www.intel.com"> <link rel="author" title="Shiyou Tan" href="mailto:shiyoux.tan@intel.com"> <link rel="help" title="7.1. Properties from CSS" href="http://www.w3.org/TR/css3-transitions/#animatable-css"> -<meta name="flags" content="interact"> <meta name="assert" content="Test checks that the 'font-size' property is animatable."> <style> #test {
diff --git a/third_party/blink/web_tests/external/wpt/css/css-transitions/transition-property-020.html b/third_party/blink/web_tests/external/wpt/css/css-transitions/transition-property-020-manual.html similarity index 96% rename from third_party/blink/web_tests/external/wpt/css/css-transitions/transition-property-020.html rename to third_party/blink/web_tests/external/wpt/css/css-transitions/transition-property-020-manual.html index af0aea41..e4f7b57 100644 --- a/third_party/blink/web_tests/external/wpt/css/css-transitions/transition-property-020.html +++ b/third_party/blink/web_tests/external/wpt/css/css-transitions/transition-property-020-manual.html
@@ -4,7 +4,6 @@ <link rel="author" title="Intel" href="http://www.intel.com"> <link rel="author" title="Shiyou Tan" href="mailto:shiyoux.tan@intel.com"> <link rel="help" title="7.1. Properties from CSS" href="http://www.w3.org/TR/css3-transitions/#animatable-css"> -<meta name="flags" content="interact"> <meta name="assert" content="Test checks that the 'font-weight' property is animatable."> <style> #test {
diff --git a/third_party/blink/web_tests/external/wpt/css/css-transitions/transition-property-021.html b/third_party/blink/web_tests/external/wpt/css/css-transitions/transition-property-021-manual.html similarity index 96% rename from third_party/blink/web_tests/external/wpt/css/css-transitions/transition-property-021.html rename to third_party/blink/web_tests/external/wpt/css/css-transitions/transition-property-021-manual.html index f499c9a..c049222 100644 --- a/third_party/blink/web_tests/external/wpt/css/css-transitions/transition-property-021.html +++ b/third_party/blink/web_tests/external/wpt/css/css-transitions/transition-property-021-manual.html
@@ -4,7 +4,6 @@ <link rel="author" title="Intel" href="http://www.intel.com"> <link rel="author" title="Shiyou Tan" href="mailto:shiyoux.tan@intel.com"> <link rel="help" title="7.1. Properties from CSS" href="http://www.w3.org/TR/css3-transitions/#animatable-css"> -<meta name="flags" content="interact"> <meta name="assert" content="Test checks that the 'left' property is animatable."> <style> #test {
diff --git a/third_party/blink/web_tests/external/wpt/css/css-transitions/transition-property-022.html b/third_party/blink/web_tests/external/wpt/css/css-transitions/transition-property-022-manual.html similarity index 96% rename from third_party/blink/web_tests/external/wpt/css/css-transitions/transition-property-022.html rename to third_party/blink/web_tests/external/wpt/css/css-transitions/transition-property-022-manual.html index f369549..ece1a32 100644 --- a/third_party/blink/web_tests/external/wpt/css/css-transitions/transition-property-022.html +++ b/third_party/blink/web_tests/external/wpt/css/css-transitions/transition-property-022-manual.html
@@ -4,7 +4,7 @@ <link rel="author" title="Intel" href="http://www.intel.com"> <link rel="author" title="Shiyou Tan" href="mailto:shiyoux.tan@intel.com"> <link rel="help" title="7.1. Properties from CSS" href="http://www.w3.org/TR/css3-transitions/#animatable-css"> -<meta name="flags" content="ahem interact"> +<meta name="flags" content="ahem"> <meta name="assert" content="Test checks that the 'letter-spacing' property is animatable."> <link rel="stylesheet" type="text/css" href="/fonts/ahem.css" /> <style>
diff --git a/third_party/blink/web_tests/external/wpt/css/css-transitions/transition-property-023.html b/third_party/blink/web_tests/external/wpt/css/css-transitions/transition-property-023-manual.html similarity index 95% rename from third_party/blink/web_tests/external/wpt/css/css-transitions/transition-property-023.html rename to third_party/blink/web_tests/external/wpt/css/css-transitions/transition-property-023-manual.html index 81c8cadac..267be61 100644 --- a/third_party/blink/web_tests/external/wpt/css/css-transitions/transition-property-023.html +++ b/third_party/blink/web_tests/external/wpt/css/css-transitions/transition-property-023-manual.html
@@ -4,7 +4,6 @@ <link rel="author" title="Intel" href="http://www.intel.com"> <link rel="author" title="Shiyou Tan" href="mailto:shiyoux.tan@intel.com"> <link rel="help" title="7.1. Properties from CSS" href="http://www.w3.org/TR/css3-transitions/#animatable-css"> -<meta name="flags" content="interact"> <meta name="assert" content="Test checks that the 'line-height' property is animatable."> <style> #test {
diff --git a/third_party/blink/web_tests/external/wpt/css/css-transitions/transition-property-024.html b/third_party/blink/web_tests/external/wpt/css/css-transitions/transition-property-024-manual.html similarity index 96% rename from third_party/blink/web_tests/external/wpt/css/css-transitions/transition-property-024.html rename to third_party/blink/web_tests/external/wpt/css/css-transitions/transition-property-024-manual.html index b0e9d41d..fad3d7a 100644 --- a/third_party/blink/web_tests/external/wpt/css/css-transitions/transition-property-024.html +++ b/third_party/blink/web_tests/external/wpt/css/css-transitions/transition-property-024-manual.html
@@ -4,7 +4,6 @@ <link rel="author" title="Intel" href="http://www.intel.com"> <link rel="author" title="Shiyou Tan" href="mailto:shiyoux.tan@intel.com"> <link rel="help" title="7.1. Properties from CSS" href="http://www.w3.org/TR/css3-transitions/#animatable-css"> -<meta name="flags" content="interact"> <meta name="assert" content="Test checks that the 'margin-bottom' property is animatable."> <style> #ref {
diff --git a/third_party/blink/web_tests/external/wpt/css/css-transitions/transition-property-025.html b/third_party/blink/web_tests/external/wpt/css/css-transitions/transition-property-025-manual.html similarity index 96% rename from third_party/blink/web_tests/external/wpt/css/css-transitions/transition-property-025.html rename to third_party/blink/web_tests/external/wpt/css/css-transitions/transition-property-025-manual.html index bfa6f698..c0f27618 100644 --- a/third_party/blink/web_tests/external/wpt/css/css-transitions/transition-property-025.html +++ b/third_party/blink/web_tests/external/wpt/css/css-transitions/transition-property-025-manual.html
@@ -4,7 +4,6 @@ <link rel="author" title="Intel" href="http://www.intel.com"> <link rel="author" title="Shiyou Tan" href="mailto:shiyoux.tan@intel.com"> <link rel="help" title="7.1. Properties from CSS" href="http://www.w3.org/TR/css3-transitions/#animatable-css"> -<meta name="flags" content="interact"> <meta name="assert" content="Test checks that the 'margin-left' property is animatable."> <style> #test {
diff --git a/third_party/blink/web_tests/external/wpt/css/css-transitions/transition-property-026.html b/third_party/blink/web_tests/external/wpt/css/css-transitions/transition-property-026-manual.html similarity index 96% rename from third_party/blink/web_tests/external/wpt/css/css-transitions/transition-property-026.html rename to third_party/blink/web_tests/external/wpt/css/css-transitions/transition-property-026-manual.html index d6f0481..35846e3f 100644 --- a/third_party/blink/web_tests/external/wpt/css/css-transitions/transition-property-026.html +++ b/third_party/blink/web_tests/external/wpt/css/css-transitions/transition-property-026-manual.html
@@ -4,7 +4,6 @@ <link rel="author" title="Intel" href="http://www.intel.com"> <link rel="author" title="Shiyou Tan" href="mailto:shiyoux.tan@intel.com"> <link rel="help" title="7.1. Properties from CSS" href="http://www.w3.org/TR/css3-transitions/#animatable-css"> -<meta name="flags" content="interact"> <meta name="assert" content="Test checks that the 'margin-right' property is animatable."> <style> div {
diff --git a/third_party/blink/web_tests/external/wpt/css/css-transitions/transition-property-027.html b/third_party/blink/web_tests/external/wpt/css/css-transitions/transition-property-027-manual.html similarity index 96% rename from third_party/blink/web_tests/external/wpt/css/css-transitions/transition-property-027.html rename to third_party/blink/web_tests/external/wpt/css/css-transitions/transition-property-027-manual.html index 01f50dc..5ad5f5d 100644 --- a/third_party/blink/web_tests/external/wpt/css/css-transitions/transition-property-027.html +++ b/third_party/blink/web_tests/external/wpt/css/css-transitions/transition-property-027-manual.html
@@ -4,7 +4,6 @@ <link rel="author" title="Intel" href="http://www.intel.com"> <link rel="author" title="Shiyou Tan" href="mailto:shiyoux.tan@intel.com"> <link rel="help" title="7.1. Properties from CSS" href="http://www.w3.org/TR/css3-transitions/#animatable-css"> -<meta name="flags" content="interact"> <meta name="assert" content="Test checks that the 'max-height' property is animatable."> <style> #test {
diff --git a/third_party/blink/web_tests/external/wpt/css/css-transitions/transition-property-028.html b/third_party/blink/web_tests/external/wpt/css/css-transitions/transition-property-028-manual.html similarity index 96% rename from third_party/blink/web_tests/external/wpt/css/css-transitions/transition-property-028.html rename to third_party/blink/web_tests/external/wpt/css/css-transitions/transition-property-028-manual.html index 83d87511..be319d2c 100644 --- a/third_party/blink/web_tests/external/wpt/css/css-transitions/transition-property-028.html +++ b/third_party/blink/web_tests/external/wpt/css/css-transitions/transition-property-028-manual.html
@@ -4,7 +4,6 @@ <link rel="author" title="Intel" href="http://www.intel.com"> <link rel="author" title="Shiyou Tan" href="mailto:shiyoux.tan@intel.com"> <link rel="help" title="7.1. Properties from CSS" href="http://www.w3.org/TR/css3-transitions/#animatable-css"> -<meta name="flags" content="interact"> <meta name="assert" content="Test checks that the 'max-width' property is animatable."> <style> #test {
diff --git a/third_party/blink/web_tests/external/wpt/css/css-transitions/transition-property-029.html b/third_party/blink/web_tests/external/wpt/css/css-transitions/transition-property-029-manual.html similarity index 96% rename from third_party/blink/web_tests/external/wpt/css/css-transitions/transition-property-029.html rename to third_party/blink/web_tests/external/wpt/css/css-transitions/transition-property-029-manual.html index fb435c91..84c5532 100644 --- a/third_party/blink/web_tests/external/wpt/css/css-transitions/transition-property-029.html +++ b/third_party/blink/web_tests/external/wpt/css/css-transitions/transition-property-029-manual.html
@@ -4,7 +4,6 @@ <link rel="author" title="Intel" href="http://www.intel.com"> <link rel="author" title="Shiyou Tan" href="mailto:shiyoux.tan@intel.com"> <link rel="help" title="7.1. Properties from CSS" href="http://www.w3.org/TR/css3-transitions/#animatable-css"> -<meta name="flags" content="interact"> <meta name="assert" content="Test checks that the 'min-height' property is animatable."> <style> #test {
diff --git a/third_party/blink/web_tests/external/wpt/css/css-transitions/transition-property-030.html b/third_party/blink/web_tests/external/wpt/css/css-transitions/transition-property-030-manual.html similarity index 96% rename from third_party/blink/web_tests/external/wpt/css/css-transitions/transition-property-030.html rename to third_party/blink/web_tests/external/wpt/css/css-transitions/transition-property-030-manual.html index 286af42..ba75f7c 100644 --- a/third_party/blink/web_tests/external/wpt/css/css-transitions/transition-property-030.html +++ b/third_party/blink/web_tests/external/wpt/css/css-transitions/transition-property-030-manual.html
@@ -4,7 +4,6 @@ <link rel="author" title="Intel" href="http://www.intel.com"> <link rel="author" title="Shiyou Tan" href="mailto:shiyoux.tan@intel.com"> <link rel="help" title="7.1. Properties from CSS" href="http://www.w3.org/TR/css3-transitions/#animatable-css"> -<meta name="flags" content="interact"> <meta name="assert" content="Test checks that the 'min-width' property is animatable."> <style> #test {
diff --git a/third_party/blink/web_tests/external/wpt/css/css-transitions/transition-property-031.html b/third_party/blink/web_tests/external/wpt/css/css-transitions/transition-property-031-manual.html similarity index 95% rename from third_party/blink/web_tests/external/wpt/css/css-transitions/transition-property-031.html rename to third_party/blink/web_tests/external/wpt/css/css-transitions/transition-property-031-manual.html index d5bf232..14cf23c 100644 --- a/third_party/blink/web_tests/external/wpt/css/css-transitions/transition-property-031.html +++ b/third_party/blink/web_tests/external/wpt/css/css-transitions/transition-property-031-manual.html
@@ -4,7 +4,6 @@ <link rel="author" title="Intel" href="http://www.intel.com"> <link rel="author" title="Shiyou Tan" href="mailto:shiyoux.tan@intel.com"> <link rel="help" title="7.1. Properties from CSS" href="http://www.w3.org/TR/css3-transitions/#animatable-css"> -<meta name="flags" content="interact"> <meta name="assert" content="Test checks that the 'opacity' property is animatable."> <style> #test {
diff --git a/third_party/blink/web_tests/external/wpt/css/css-transitions/transition-property-032.html b/third_party/blink/web_tests/external/wpt/css/css-transitions/transition-property-032-manual.html similarity index 96% rename from third_party/blink/web_tests/external/wpt/css/css-transitions/transition-property-032.html rename to third_party/blink/web_tests/external/wpt/css/css-transitions/transition-property-032-manual.html index 020a857..c659660 100644 --- a/third_party/blink/web_tests/external/wpt/css/css-transitions/transition-property-032.html +++ b/third_party/blink/web_tests/external/wpt/css/css-transitions/transition-property-032-manual.html
@@ -4,7 +4,6 @@ <link rel="author" title="Intel" href="http://www.intel.com"> <link rel="author" title="Shiyou Tan" href="mailto:shiyoux.tan@intel.com"> <link rel="help" title="7.1. Properties from CSS" href="http://www.w3.org/TR/css3-transitions/#animatable-css"> -<meta name="flags" content="interact"> <meta name="assert" content="Test checks that the 'outline-color' property is animatable."> <style> #test {
diff --git a/third_party/blink/web_tests/external/wpt/css/css-transitions/transition-property-033.html b/third_party/blink/web_tests/external/wpt/css/css-transitions/transition-property-033-manual.html similarity index 96% rename from third_party/blink/web_tests/external/wpt/css/css-transitions/transition-property-033.html rename to third_party/blink/web_tests/external/wpt/css/css-transitions/transition-property-033-manual.html index fcb999fa..fd7646c 100644 --- a/third_party/blink/web_tests/external/wpt/css/css-transitions/transition-property-033.html +++ b/third_party/blink/web_tests/external/wpt/css/css-transitions/transition-property-033-manual.html
@@ -4,7 +4,6 @@ <link rel="author" title="Intel" href="http://www.intel.com"> <link rel="author" title="Shiyou Tan" href="mailto:shiyoux.tan@intel.com"> <link rel="help" title="7.1. Properties from CSS" href="http://www.w3.org/TR/css3-transitions/#animatable-css"> -<meta name="flags" content="interact"> <meta name="assert" content="Test checks that the 'outline-width' property is animatable."> <style> #test {
diff --git a/third_party/blink/web_tests/external/wpt/css/css-transitions/transition-property-034.html b/third_party/blink/web_tests/external/wpt/css/css-transitions/transition-property-034-manual.html similarity index 96% rename from third_party/blink/web_tests/external/wpt/css/css-transitions/transition-property-034.html rename to third_party/blink/web_tests/external/wpt/css/css-transitions/transition-property-034-manual.html index b4da3a9b..0780412 100644 --- a/third_party/blink/web_tests/external/wpt/css/css-transitions/transition-property-034.html +++ b/third_party/blink/web_tests/external/wpt/css/css-transitions/transition-property-034-manual.html
@@ -4,7 +4,6 @@ <link rel="author" title="Intel" href="http://www.intel.com"> <link rel="author" title="Shiyou Tan" href="mailto:shiyoux.tan@intel.com"> <link rel="help" title="7.1. Properties from CSS" href="http://www.w3.org/TR/css3-transitions/#animatable-css"> -<meta name="flags" content="interact"> <meta name="assert" content="Test checks that the 'padding-bottom' property is animatable."> <style> #test {
diff --git a/third_party/blink/web_tests/external/wpt/css/css-transitions/transition-property-035.html b/third_party/blink/web_tests/external/wpt/css/css-transitions/transition-property-035-manual.html similarity index 96% rename from third_party/blink/web_tests/external/wpt/css/css-transitions/transition-property-035.html rename to third_party/blink/web_tests/external/wpt/css/css-transitions/transition-property-035-manual.html index 27c9ea9..4a9e9b12 100644 --- a/third_party/blink/web_tests/external/wpt/css/css-transitions/transition-property-035.html +++ b/third_party/blink/web_tests/external/wpt/css/css-transitions/transition-property-035-manual.html
@@ -4,7 +4,6 @@ <link rel="author" title="Intel" href="http://www.intel.com"> <link rel="author" title="Shiyou Tan" href="mailto:shiyoux.tan@intel.com"> <link rel="help" title="7.1. Properties from CSS" href="http://www.w3.org/TR/css3-transitions/#animatable-css"> -<meta name="flags" content="interact"> <meta name="assert" content="Test checks that the 'padding-left' property is animatable."> <style> #test {
diff --git a/third_party/blink/web_tests/external/wpt/css/css-transitions/transition-property-036.html b/third_party/blink/web_tests/external/wpt/css/css-transitions/transition-property-036-manual.html similarity index 96% rename from third_party/blink/web_tests/external/wpt/css/css-transitions/transition-property-036.html rename to third_party/blink/web_tests/external/wpt/css/css-transitions/transition-property-036-manual.html index 326e615..746bc40 100644 --- a/third_party/blink/web_tests/external/wpt/css/css-transitions/transition-property-036.html +++ b/third_party/blink/web_tests/external/wpt/css/css-transitions/transition-property-036-manual.html
@@ -4,7 +4,6 @@ <link rel="author" title="Intel" href="http://www.intel.com"> <link rel="author" title="Shiyou Tan" href="mailto:shiyoux.tan@intel.com"> <link rel="help" title="7.1. Properties from CSS" href="http://www.w3.org/TR/css3-transitions/#animatable-css"> -<meta name="flags" content="interact"> <meta name="assert" content="Test checks that the 'padding-right' property is animatable."> <style> #test {
diff --git a/third_party/blink/web_tests/external/wpt/css/css-transitions/transition-property-037.html b/third_party/blink/web_tests/external/wpt/css/css-transitions/transition-property-037-manual.html similarity index 96% rename from third_party/blink/web_tests/external/wpt/css/css-transitions/transition-property-037.html rename to third_party/blink/web_tests/external/wpt/css/css-transitions/transition-property-037-manual.html index 79ce16f..d031caa 100644 --- a/third_party/blink/web_tests/external/wpt/css/css-transitions/transition-property-037.html +++ b/third_party/blink/web_tests/external/wpt/css/css-transitions/transition-property-037-manual.html
@@ -4,7 +4,6 @@ <link rel="author" title="Intel" href="http://www.intel.com"> <link rel="author" title="Shiyou Tan" href="mailto:shiyoux.tan@intel.com"> <link rel="help" title="7.1. Properties from CSS" href="http://www.w3.org/TR/css3-transitions/#animatable-css"> -<meta name="flags" content="interact"> <meta name="assert" content="Test checks that the 'padding-top' property is animatable."> <style> #test {
diff --git a/third_party/blink/web_tests/external/wpt/css/css-transitions/transition-property-038.html b/third_party/blink/web_tests/external/wpt/css/css-transitions/transition-property-038-manual.html similarity index 96% rename from third_party/blink/web_tests/external/wpt/css/css-transitions/transition-property-038.html rename to third_party/blink/web_tests/external/wpt/css/css-transitions/transition-property-038-manual.html index 5b16e41..2f9302b 100644 --- a/third_party/blink/web_tests/external/wpt/css/css-transitions/transition-property-038.html +++ b/third_party/blink/web_tests/external/wpt/css/css-transitions/transition-property-038-manual.html
@@ -4,7 +4,6 @@ <link rel="author" title="Intel" href="http://www.intel.com"> <link rel="author" title="Shiyou Tan" href="mailto:shiyoux.tan@intel.com"> <link rel="help" title="7.1. Properties from CSS" href="http://www.w3.org/TR/css3-transitions/#animatable-css"> -<meta name="flags" content="interact"> <meta name="assert" content="Test checks that the 'right' property is animatable."> <style> #test {
diff --git a/third_party/blink/web_tests/external/wpt/css/css-transitions/transition-property-039.html b/third_party/blink/web_tests/external/wpt/css/css-transitions/transition-property-039-manual.html similarity index 95% rename from third_party/blink/web_tests/external/wpt/css/css-transitions/transition-property-039.html rename to third_party/blink/web_tests/external/wpt/css/css-transitions/transition-property-039-manual.html index 0ef6da5..bf0b209b 100644 --- a/third_party/blink/web_tests/external/wpt/css/css-transitions/transition-property-039.html +++ b/third_party/blink/web_tests/external/wpt/css/css-transitions/transition-property-039-manual.html
@@ -4,7 +4,6 @@ <link rel="author" title="Intel" href="http://www.intel.com"> <link rel="author" title="Shiyou Tan" href="mailto:shiyoux.tan@intel.com"> <link rel="help" title="7.1. Properties from CSS" href="http://www.w3.org/TR/css3-transitions/#animatable-css"> -<meta name="flags" content="interact"> <meta name="assert" content="Test checks that the 'text-indent' property is animatable."> <style> #test {
diff --git a/third_party/blink/web_tests/external/wpt/css/css-transitions/transition-property-040.html b/third_party/blink/web_tests/external/wpt/css/css-transitions/transition-property-040-manual.html similarity index 95% rename from third_party/blink/web_tests/external/wpt/css/css-transitions/transition-property-040.html rename to third_party/blink/web_tests/external/wpt/css/css-transitions/transition-property-040-manual.html index b333f371..83a3cf80 100644 --- a/third_party/blink/web_tests/external/wpt/css/css-transitions/transition-property-040.html +++ b/third_party/blink/web_tests/external/wpt/css/css-transitions/transition-property-040-manual.html
@@ -4,7 +4,6 @@ <link rel="author" title="Intel" href="http://www.intel.com"> <link rel="author" title="Shiyou Tan" href="mailto:shiyoux.tan@intel.com"> <link rel="help" title="7.1. Properties from CSS" href="http://www.w3.org/TR/css3-transitions/#animatable-css"> -<meta name="flags" content="interact"> <meta name="assert" content="Test checks that the 'text-shadow' property is animatable."> <style> #test {
diff --git a/third_party/blink/web_tests/external/wpt/css/css-transitions/transition-property-041.html b/third_party/blink/web_tests/external/wpt/css/css-transitions/transition-property-041-manual.html similarity index 95% rename from third_party/blink/web_tests/external/wpt/css/css-transitions/transition-property-041.html rename to third_party/blink/web_tests/external/wpt/css/css-transitions/transition-property-041-manual.html index b3386a0..04f8351 100644 --- a/third_party/blink/web_tests/external/wpt/css/css-transitions/transition-property-041.html +++ b/third_party/blink/web_tests/external/wpt/css/css-transitions/transition-property-041-manual.html
@@ -4,7 +4,6 @@ <link rel="author" title="Intel" href="http://www.intel.com"> <link rel="author" title="Shiyou Tan" href="mailto:shiyoux.tan@intel.com"> <link rel="help" title="7.1. Properties from CSS" href="http://www.w3.org/TR/css3-transitions/#animatable-css"> -<meta name="flags" content="interact"> <meta name="assert" content="Test checks that the 'top' property is animatable."> <style> #test {
diff --git a/third_party/blink/web_tests/external/wpt/css/css-transitions/transition-property-042.html b/third_party/blink/web_tests/external/wpt/css/css-transitions/transition-property-042-manual.html similarity index 96% rename from third_party/blink/web_tests/external/wpt/css/css-transitions/transition-property-042.html rename to third_party/blink/web_tests/external/wpt/css/css-transitions/transition-property-042-manual.html index fbb3e2d..15977497 100644 --- a/third_party/blink/web_tests/external/wpt/css/css-transitions/transition-property-042.html +++ b/third_party/blink/web_tests/external/wpt/css/css-transitions/transition-property-042-manual.html
@@ -4,7 +4,6 @@ <link rel="author" title="Intel" href="http://www.intel.com"> <link rel="author" title="Shiyou Tan" href="mailto:shiyoux.tan@intel.com"> <link rel="help" title="7.1. Properties from CSS" href="http://www.w3.org/TR/css3-transitions/#animatable-css"> -<meta name="flags" content="interact"> <meta name="assert" content="Test checks that the 'vertical-align' property is animatable."> <style> #test {
diff --git a/third_party/blink/web_tests/external/wpt/css/css-transitions/transition-property-043.html b/third_party/blink/web_tests/external/wpt/css/css-transitions/transition-property-043-manual.html similarity index 96% rename from third_party/blink/web_tests/external/wpt/css/css-transitions/transition-property-043.html rename to third_party/blink/web_tests/external/wpt/css/css-transitions/transition-property-043-manual.html index b87dc84..3b939bcf 100644 --- a/third_party/blink/web_tests/external/wpt/css/css-transitions/transition-property-043.html +++ b/third_party/blink/web_tests/external/wpt/css/css-transitions/transition-property-043-manual.html
@@ -4,7 +4,6 @@ <link rel="author" title="Intel" href="http://www.intel.com"> <link rel="author" title="Shiyou Tan" href="mailto:shiyoux.tan@intel.com"> <link rel="help" title="7.1. Properties from CSS" href="http://www.w3.org/TR/css3-transitions/#animatable-css"> -<meta name="flags" content="interact"> <meta name="assert" content="Test checks that the 'visibility' property is animatable."> <style> #test {
diff --git a/third_party/blink/web_tests/external/wpt/css/css-transitions/transition-property-044.html b/third_party/blink/web_tests/external/wpt/css/css-transitions/transition-property-044-manual.html similarity index 95% rename from third_party/blink/web_tests/external/wpt/css/css-transitions/transition-property-044.html rename to third_party/blink/web_tests/external/wpt/css/css-transitions/transition-property-044-manual.html index f1d584f..d7c2f46 100644 --- a/third_party/blink/web_tests/external/wpt/css/css-transitions/transition-property-044.html +++ b/third_party/blink/web_tests/external/wpt/css/css-transitions/transition-property-044-manual.html
@@ -4,7 +4,7 @@ <link rel="author" title="Intel" href="http://www.intel.com"> <link rel="author" title="Shiyou Tan" href="mailto:shiyoux.tan@intel.com"> <link rel="help" title="7.1. Properties from CSS" href="http://www.w3.org/TR/css3-transitions/#animatable-css"> -<meta name="flags" content="ahem interact"> +<meta name="flags" content="ahem"> <meta name="assert" content="Test checks that the 'word-spacing' property is animatable."> <link rel="stylesheet" type="text/css" href="/fonts/ahem.css" /> <style>
diff --git a/third_party/blink/web_tests/external/wpt/css/css-transitions/transition-property-045.html b/third_party/blink/web_tests/external/wpt/css/css-transitions/transition-property-045-manual.html similarity index 95% rename from third_party/blink/web_tests/external/wpt/css/css-transitions/transition-property-045.html rename to third_party/blink/web_tests/external/wpt/css/css-transitions/transition-property-045-manual.html index 3fa82c1..912ed4d 100644 --- a/third_party/blink/web_tests/external/wpt/css/css-transitions/transition-property-045.html +++ b/third_party/blink/web_tests/external/wpt/css/css-transitions/transition-property-045-manual.html
@@ -4,7 +4,7 @@ <link rel="author" title="Intel" href="http://www.intel.com"> <link rel="author" title="Shiyou Tan" href="mailto:shiyoux.tan@intel.com"> <link rel="help" title="7.1. Properties from CSS" href="http://www.w3.org/TR/css3-transitions/#animatable-css"> -<meta name="flags" content="ahem interact"> +<meta name="flags" content="ahem"> <meta name="assert" content="Test checks that the 'z-index' property is animatable."> <style> div {
diff --git a/third_party/blink/web_tests/external/wpt/css/css-transitions/transition-timing-function-001.html b/third_party/blink/web_tests/external/wpt/css/css-transitions/transition-timing-function-001.html deleted file mode 100644 index 4c9598f..0000000 --- a/third_party/blink/web_tests/external/wpt/css/css-transitions/transition-timing-function-001.html +++ /dev/null
@@ -1,94 +0,0 @@ -<!DOCTYPE html> -<html> - <head> - <meta charset="utf-8"> - <title>CSS Transitions Test: Parsing transition-timing-function</title> - <meta name="assert" content="Test checks that transition-timing-function values are parsed properly"> - <link rel="help" title="2.3. The 'transition-timing-function' Property" href="http://www.w3.org/TR/css3-transitions/#transition-timing-function-property"> - <link rel="author" title="Rodney Rehm" href="http://rodneyrehm.de/en/"> - <meta name="flags" content="dom"> - - <script src="/resources/testharness.js" type="text/javascript"></script> - <script src="/resources/testharnessreport.js" type="text/javascript"></script> - - <script src="./support/vendorPrefix.js" type="text/javascript"></script> - <script src="./support/helper.js" type="text/javascript"></script> - </head> - <body> - <!-- required by testharnessreport.js --> - <div id="log"></div> - <!-- elements used for testing --> - <div id="container"> - <div id="transition"></div> - </div> - - <script> - var transition = document.getElementById('transition'); - var defaultValue = 'ease'; - var values = { - // keywords - 'ease': 'ease', - 'linear': 'linear', - 'ease-in': 'ease-in', - 'ease-out': 'ease-out', - 'ease-in-out': 'ease-in-out', - 'step-start': 'steps(1, start)', - 'step-end': 'steps(1)', - // cubic bezier - 'cubic-bezier(0.1, 0.2, 0.3, 0.4)': 'cubic-bezier(0.1, 0.2, 0.3, 0.4)', - 'cubic-bezier(0.1, -0.2, 0.3, -0.4)': 'cubic-bezier(0.1, -0.2, 0.3, -0.4)', - 'cubic-bezier(0.1, 1.2, 0.3, 1.4)': 'cubic-bezier(0.1, 1.2, 0.3, 1.4)', - // steps - 'steps(3, start)': 'steps(3, start)', - 'steps(3, end)': 'steps(3)', - 'steps(3)': 'steps(3)', - 'steps(3, jump-start)': 'steps(3, jump-start)', - 'steps(3, jump-end)': 'steps(3)', - 'steps(3, jump-both)': 'steps(3, jump-both)', - 'steps(3, jump-none)': 'steps(3, jump-none)', - // invalid - 'cubic-bezier(foobar)': defaultValue, - 'steps(foobar)': defaultValue, - 'steps(3.3, end)': defaultValue, - 'steps(3, top)': defaultValue, - 'steps(-3, top)': defaultValue, - 'steps(0, jump-start)': defaultValue, - 'steps(0, jump-end)': defaultValue, - 'steps(0, jump-both)': defaultValue, - 'steps(1, jump-none)': defaultValue, - // Both x values must be in the range [0, 1] - 'cubic-bezier(-0.1, -0.2, -0.3, -0.4)': defaultValue, - 'cubic-bezier(1.1, 1.2, 1.3, 1.4)': defaultValue - }; - - // these tests are supposed to fail and - // possibly make the engine issue a parser warning - var invalidTests = { - 'cubic-bezier(foobar)': true, - 'steps(foobar)': true, - 'steps(3.3, end)': true, - 'steps(3, top)': true, - 'steps(-3, top)': true, - // Both x values must be in the range [0, 1] - 'cubic-bezier(-0.1, -0.2, -0.3, -0.4)': true, - 'cubic-bezier(1.1, 1.2, 1.3, 1.4)': true - }; - - for (var key in values) { - if (Object.prototype.hasOwnProperty.call(values, key)) { - test(function() { - setStyle('#transition', { - 'transition-timing-function': key - }); - var result = computedStyle(transition, 'transition-timing-function'); - assert_equals(result, values[key], "Expected computed value"); - }, "parse '" + key + "'", - { - // mark tests that fail as such - flags: invalidTests[key] ? "invalid" : "" - }); - } - } - </script> - </body> -</html>
diff --git a/third_party/blink/web_tests/external/wpt/css/css-transitions/transition-timing-function-002.html b/third_party/blink/web_tests/external/wpt/css/css-transitions/transition-timing-function-002-manual.html similarity index 97% rename from third_party/blink/web_tests/external/wpt/css/css-transitions/transition-timing-function-002.html rename to third_party/blink/web_tests/external/wpt/css/css-transitions/transition-timing-function-002-manual.html index 527eb9e..abd729b 100644 --- a/third_party/blink/web_tests/external/wpt/css/css-transitions/transition-timing-function-002.html +++ b/third_party/blink/web_tests/external/wpt/css/css-transitions/transition-timing-function-002-manual.html
@@ -4,7 +4,6 @@ <link rel="author" title="Intel" href="http://www.intel.com"> <link rel="author" title="Shiyou Tan" href="mailto:shiyoux.tan@intel.com"> <link rel="help" title="2.3. The 'transition-timing-function' Property" href="http://www.w3.org/TR/css3-transitions/#transition-timing-function"> -<meta name="flags" content="interact"> <meta name="assert" content="The 'transition-timing-function' property set 'ease' is equivalent to cubic-bezier(0.25, 0.1, 0.25, 1.0)"> <style> div {
diff --git a/third_party/blink/web_tests/external/wpt/css/css-transitions/transition-timing-function-003.html b/third_party/blink/web_tests/external/wpt/css/css-transitions/transition-timing-function-003-manual.html similarity index 97% rename from third_party/blink/web_tests/external/wpt/css/css-transitions/transition-timing-function-003.html rename to third_party/blink/web_tests/external/wpt/css/css-transitions/transition-timing-function-003-manual.html index 353b94e..9fee35a 100644 --- a/third_party/blink/web_tests/external/wpt/css/css-transitions/transition-timing-function-003.html +++ b/third_party/blink/web_tests/external/wpt/css/css-transitions/transition-timing-function-003-manual.html
@@ -4,7 +4,6 @@ <link rel="author" title="Intel" href="http://www.intel.com"> <link rel="author" title="Shiyou Tan" href="mailto:shiyoux.tan@intel.com"> <link rel="help" title="2.3. The 'transition-timing-function' Property" href="http://www.w3.org/TR/css3-transitions/#transition-timing-function"> -<meta name="flags" content="interact"> <meta name="assert" content="The 'transition-timing-function' property set 'ease-in' is equivalent to cubic-bezier(0.42, 0, 1.0, 1.0)"> <style> div {
diff --git a/third_party/blink/web_tests/external/wpt/css/css-transitions/transition-timing-function-004.html b/third_party/blink/web_tests/external/wpt/css/css-transitions/transition-timing-function-004-manual.html similarity index 97% rename from third_party/blink/web_tests/external/wpt/css/css-transitions/transition-timing-function-004.html rename to third_party/blink/web_tests/external/wpt/css/css-transitions/transition-timing-function-004-manual.html index 0601b4b..f57d49ae 100644 --- a/third_party/blink/web_tests/external/wpt/css/css-transitions/transition-timing-function-004.html +++ b/third_party/blink/web_tests/external/wpt/css/css-transitions/transition-timing-function-004-manual.html
@@ -4,7 +4,6 @@ <link rel="author" title="Intel" href="http://www.intel.com"> <link rel="author" title="Shiyou Tan" href="mailto:shiyoux.tan@intel.com"> <link rel="help" title="2.3. The 'transition-timing-function' Property" href="http://www.w3.org/TR/css3-transitions/#transition-timing-function"> -<meta name="flags" content="interact"> <meta name="assert" content="The 'transition-timing-function' property set 'ease-in-out' is equivalent to cubic-bezier(0.42, 0, 0.58, 1.0)"> <style> div {
diff --git a/third_party/blink/web_tests/external/wpt/css/css-transitions/transition-timing-function-005.html b/third_party/blink/web_tests/external/wpt/css/css-transitions/transition-timing-function-005-manual.html similarity index 97% rename from third_party/blink/web_tests/external/wpt/css/css-transitions/transition-timing-function-005.html rename to third_party/blink/web_tests/external/wpt/css/css-transitions/transition-timing-function-005-manual.html index eb46ece..27726cd 100644 --- a/third_party/blink/web_tests/external/wpt/css/css-transitions/transition-timing-function-005.html +++ b/third_party/blink/web_tests/external/wpt/css/css-transitions/transition-timing-function-005-manual.html
@@ -4,7 +4,6 @@ <link rel="author" title="Intel" href="http://www.intel.com"> <link rel="author" title="Shiyou Tan" href="mailto:shiyoux.tan@intel.com"> <link rel="help" title="2.3. The 'transition-timing-function' Property" href="http://www.w3.org/TR/css3-transitions/#transition-timing-function"> -<meta name="flags" content="interact"> <meta name="assert" content="The 'transition-timing-function' property set 'ease-out' is equivalent to cubic-bezier(0, 0, 0.58, 1.0)"> <style> div {
diff --git a/third_party/blink/web_tests/external/wpt/css/css-transitions/transition-timing-function-006.html b/third_party/blink/web_tests/external/wpt/css/css-transitions/transition-timing-function-006-manual.html similarity index 97% rename from third_party/blink/web_tests/external/wpt/css/css-transitions/transition-timing-function-006.html rename to third_party/blink/web_tests/external/wpt/css/css-transitions/transition-timing-function-006-manual.html index d8640d93..d97e6bb 100644 --- a/third_party/blink/web_tests/external/wpt/css/css-transitions/transition-timing-function-006.html +++ b/third_party/blink/web_tests/external/wpt/css/css-transitions/transition-timing-function-006-manual.html
@@ -4,7 +4,6 @@ <link rel="author" title="Intel" href="http://www.intel.com"> <link rel="author" title="Shiyou Tan" href="mailto:shiyoux.tan@intel.com"> <link rel="help" title="2.3. The 'transition-timing-function' Property" href="http://www.w3.org/TR/css3-transitions/#transition-timing-function"> -<meta name="flags" content="interact"> <meta name="assert" content="The 'transition-timing-function' property set 'linear' is equivalent to cubic-bezier(0.0, 0.0, 1.0, 1.0)"> <style> div {
diff --git a/third_party/blink/web_tests/external/wpt/css/css-transitions/transition-timing-function-007.html b/third_party/blink/web_tests/external/wpt/css/css-transitions/transition-timing-function-007.html deleted file mode 100644 index 72ffbf6..0000000 --- a/third_party/blink/web_tests/external/wpt/css/css-transitions/transition-timing-function-007.html +++ /dev/null
@@ -1,40 +0,0 @@ -<!DOCTYPE html> -<meta charset="utf-8"> -<title>CSS Transitions Test: transition-timing-function - 'step-end' equivalent to 'steps(1, end)'</title> -<link rel="author" title="Intel" href="http://www.intel.com"> -<link rel="author" title="Shiyou Tan" href="mailto:shiyoux.tan@intel.com"> -<link rel="help" title="2.3. The 'transition-timing-function' Property" href="http://www.w3.org/TR/css3-transitions/#transition-timing-function"> -<meta name="flags" content="interact"> -<meta name="assert" content="The 'transition-timing-function' property set 'step-end' is equivalent to 'steps(1, end)'"> -<style> - div { - height: 100px; - transition: width 2s; - width: 100px; - } - #test1 { - background-color: blue; - transition-timing-function: step-end; - } - #test2 { - background-color: yellow; - transition-timing-function: steps(1, end); - } -</style> -<body> - <p>Click the 'Start' button. Test passes if the width growth of blue square is <strong>equivalent</strong> to the yellow square.</p> - <div id="test1"></div> - <div id="test2"></div> - <button>Start</button> - <script> - (function() { - var button = document.querySelector("button"); - button.addEventListener("click", function(evt) { - var test1 = document.querySelector("#test1"), - test2 = document.querySelector("#test2"); - test1.setAttribute("style", "width: 300px"); - test2.setAttribute("style", "width: 300px"); - }, false); - })(); - </script> -</body>
diff --git a/third_party/blink/web_tests/external/wpt/css/css-transitions/transition-timing-function-008.html b/third_party/blink/web_tests/external/wpt/css/css-transitions/transition-timing-function-008.html deleted file mode 100644 index 2e20f7e..0000000 --- a/third_party/blink/web_tests/external/wpt/css/css-transitions/transition-timing-function-008.html +++ /dev/null
@@ -1,40 +0,0 @@ -<!DOCTYPE html> -<meta charset="utf-8"> -<title>CSS Transitions Test: transition-timing-function - 'step-start' equivalent to 'steps(1, start)'</title> -<link rel="author" title="Intel" href="http://www.intel.com"> -<link rel="author" title="Shiyou Tan" href="mailto:shiyoux.tan@intel.com"> -<link rel="help" title="2.3. The 'transition-timing-function' Property" href="http://www.w3.org/TR/css3-transitions/#transition-timing-function"> -<meta name="flags" content="interact"> -<meta name="assert" content="The 'transition-timing-function' property set 'step-start' is equivalent to 'steps(1, start)'"> -<style> - div { - height: 100px; - transition: width 2s; - width: 100px; - } - #test1 { - background-color: blue; - transition-timing-function: step-start; - } - #test2 { - background-color: yellow; - transition-timing-function: steps(1, start); - } -</style> -<body> - <p>Click the 'Start' button. Test passes if the width growth of blue square is <strong>equivalent</strong> to the yellow square.</p> - <div id="test1"></div> - <div id="test2"></div> - <button>Start</button> - <script> - (function() { - var button = document.querySelector("button"); - button.addEventListener("click", function(evt) { - var test1 = document.querySelector("#test1"), - test2 = document.querySelector("#test2"); - test1.setAttribute("style", "width: 300px"); - test2.setAttribute("style", "width: 300px"); - }, false); - })(); - </script> -</body>
diff --git a/third_party/blink/web_tests/external/wpt/css/css-transitions/transition-timing-function-009.html b/third_party/blink/web_tests/external/wpt/css/css-transitions/transition-timing-function-009.html deleted file mode 100644 index a3e2f1a..0000000 --- a/third_party/blink/web_tests/external/wpt/css/css-transitions/transition-timing-function-009.html +++ /dev/null
@@ -1,40 +0,0 @@ -<!DOCTYPE html> -<meta charset="utf-8"> -<title>CSS Transitions Test: transition-timing-function - ease(initial value)</title> -<link rel="author" title="Intel" href="http://www.intel.com"> -<link rel="author" title="Shiyou Tan" href="mailto:shiyoux.tan@intel.com"> -<link rel="help" title="2.3. The 'transition-timing-function' Property" href="http://www.w3.org/TR/css3-transitions/#transition-timing-function"> -<meta name="flags" content="interact"> -<meta name="assert" content="Test checks that the initial value of 'transition-timing-function' property is 'ease'."> -<style> - div { - height: 100px; - transition-duration: 2s; - transition-property: width; - width: 100px; - } - #test1 { - background-color: blue; - transition-timing-function: ease; - } - #test2 { - background-color: yellow; - } -</style> -<body> - <p>Click the 'Start' button. Test passes if the width growth of blue square is <strong>equivalent</strong> to the yellow square.</p> - <div id="test1"></div> - <div id="test2"></div> - <button>Start</button> - <script> - (function() { - var button = document.querySelector("button"); - button.addEventListener("click", function(evt) { - var test1 = document.querySelector("#test1"), - test2 = document.querySelector("#test2"); - test1.setAttribute("style", "width: 300px"); - test2.setAttribute("style", "width: 300px"); - }, false); - })(); - </script> -</body>
diff --git a/third_party/blink/web_tests/external/wpt/css/css-transitions/transition-timing-function-010.html b/third_party/blink/web_tests/external/wpt/css/css-transitions/transition-timing-function-010-manual.html similarity index 96% rename from third_party/blink/web_tests/external/wpt/css/css-transitions/transition-timing-function-010.html rename to third_party/blink/web_tests/external/wpt/css/css-transitions/transition-timing-function-010-manual.html index 16af806..953d721 100644 --- a/third_party/blink/web_tests/external/wpt/css/css-transitions/transition-timing-function-010.html +++ b/third_party/blink/web_tests/external/wpt/css/css-transitions/transition-timing-function-010-manual.html
@@ -4,7 +4,6 @@ <link rel="author" title="Intel" href="http://www.intel.com"> <link rel="author" title="Shiyou Tan" href="mailto:shiyoux.tan@intel.com"> <link rel="help" title="2.3. The 'transition-timing-function' Property" href="http://www.w3.org/TR/css3-transitions/#transition-timing-function"> -<meta name="flags" content="interact"> <meta name="assert" content="Test checks that the first parameter of 'steps()' function specifies the number of intervals."> <style> div {
diff --git a/third_party/blink/web_tests/external/wpt/css/css-transitions/transition-timing-function-011.html b/third_party/blink/web_tests/external/wpt/css/css-transitions/transition-timing-function-011.html deleted file mode 100644 index 5d0f5a2..0000000 --- a/third_party/blink/web_tests/external/wpt/css/css-transitions/transition-timing-function-011.html +++ /dev/null
@@ -1,41 +0,0 @@ -<!DOCTYPE html> -<meta charset="utf-8"> -<title>CSS Transitions Test: transition-timing-function - steps(the second parameter default 'end')</title> -<link rel="author" title="Intel" href="http://www.intel.com"> -<link rel="author" title="Shiyou Tan" href="mailto:shiyoux.tan@intel.com"> -<link rel="help" title="2.3. The 'transition-timing-function' Property" href="http://www.w3.org/TR/css3-transitions/#transition-timing-function"> -<meta name="flags" content="interact"> -<meta name="assert" content="Test checks that the second parameter of 'steps()' function is default 'end'."> -<style> - div { - height: 100px; - transition-duration: 2s; - transition-property: width; - width: 100px; - } - #test1 { - background-color: blue; - transition-timing-function: steps(2); - } - #test2 { - background-color: yellow; - transition-timing-function: steps(2, end); - } -</style> -<body> - <p>Click the 'Start' button. Test passes if the width growth of blue square is <strong>equivalent</strong> to the yellow square.</p> - <div id="test1"></div> - <div id="test2"></div> - <button>Start</button> - <script> - (function() { - var button = document.querySelector("button"); - button.addEventListener("click", function(evt) { - var test1 = document.querySelector("#test1"), - test2 = document.querySelector("#test2"); - test1.setAttribute("style", "width: 300px"); - test2.setAttribute("style", "width: 300px"); - }, false); - })(); - </script> -</body>
diff --git a/third_party/blink/web_tests/external/wpt/css/css-transitions/transition-timing-function-012.html b/third_party/blink/web_tests/external/wpt/css/css-transitions/transition-timing-function-012.html deleted file mode 100644 index f3bc812..0000000 --- a/third_party/blink/web_tests/external/wpt/css/css-transitions/transition-timing-function-012.html +++ /dev/null
@@ -1,41 +0,0 @@ -<!DOCTYPE html> -<meta charset="utf-8"> -<title>CSS Transitions Test: transition-timing-function - steps(-2)</title> -<link rel="author" title="Intel" href="http://www.intel.com"> -<link rel="author" title="Shiyou Tan" href="mailto:shiyoux.tan@intel.com"> -<link rel="help" title="2.3. The 'transition-timing-function' Property" href="http://www.w3.org/TR/css3-transitions/#transition-timing-function"> -<meta name="flags" content="interact"> -<meta name="assert" content="Test checks that the 'steps()' function with negative number is invalid, the transition-timing-function will use 'ease' as default."> -<style> - div { - height: 100px; - transition-duration: 2s; - transition-property: width; - width: 100px; - } - #test1 { - background-color: blue; - transition-timing-function: steps(-2); - } - #test2 { - background-color: yellow; - transition-timing-function: ease; - } -</style> -<body> - <p>Click the 'Start' button. Test passes if the width growth of blue square is <strong>equivalent</strong> to the yellow square.</p> - <div id="test1"></div> - <div id="test2"></div> - <button>Start</button> - <script> - (function() { - var button = document.querySelector("button"); - button.addEventListener("click", function(evt) { - var test1 = document.querySelector("#test1"), - test2 = document.querySelector("#test2"); - test1.setAttribute("style", "width: 300px"); - test2.setAttribute("style", "width: 300px"); - }, false); - })(); - </script> -</body>
diff --git a/third_party/blink/web_tests/external/wpt/css/css-transitions/transition-timing-function-013.html b/third_party/blink/web_tests/external/wpt/css/css-transitions/transition-timing-function-013.html deleted file mode 100644 index 5d89c45e..0000000 --- a/third_party/blink/web_tests/external/wpt/css/css-transitions/transition-timing-function-013.html +++ /dev/null
@@ -1,41 +0,0 @@ -<!DOCTYPE html> -<meta charset="utf-8"> -<title>CSS Transitions Test: transition-timing-function - steps(0)</title> -<link rel="author" title="Intel" href="http://www.intel.com"> -<link rel="author" title="Shiyou Tan" href="mailto:shiyoux.tan@intel.com"> -<link rel="help" title="2.3. The 'transition-timing-function' Property" href="http://www.w3.org/TR/css3-transitions/#transition-timing-function"> -<meta name="flags" content="interact"> -<meta name="assert" content="Test checks that the 'steps()' function with '0' is invalid, the transition-timing-function will use 'ease' as default."> -<style> - div { - height: 100px; - transition-duration: 2s; - transition-property: width; - width: 100px; - } - #test1 { - background-color: blue; - transition-timing-function: steps(0); - } - #test2 { - background-color: yellow; - transition-timing-function: ease; - } -</style> -<body> - <p>Click the 'Start' button. Test passes if the width growth of blue square is <strong>equivalent</strong> to the yellow square.</p> - <div id="test1"></div> - <div id="test2"></div> - <button>Start</button> - <script> - (function() { - var button = document.querySelector("button"); - button.addEventListener("click", function(evt) { - var test1 = document.querySelector("#test1"), - test2 = document.querySelector("#test2"); - test1.setAttribute("style", "width: 300px"); - test2.setAttribute("style", "width: 300px"); - }, false); - })(); - </script> -</body>
diff --git a/third_party/blink/web_tests/external/wpt/intersection-observer/v2/delay-test.html b/third_party/blink/web_tests/external/wpt/intersection-observer/v2/delay-test.html index 231df32c..e3906ea 100644 --- a/third_party/blink/web_tests/external/wpt/intersection-observer/v2/delay-test.html +++ b/third_party/blink/web_tests/external/wpt/intersection-observer/v2/delay-test.html
@@ -46,7 +46,7 @@ // The first notification should be sent without delay. waitForNotification(t, t.step_func(step0)); - function waitForDelay(timerExpiredBeforeLastFrame) { + function waitForDelay(timerExpiredBeforeLastFrame, nextStep) { requestAnimationFrame(t.step_func(() => { if (timerExpiredBeforeLastFrame) { // New notifications should have been generated during the previous @@ -54,11 +54,11 @@ assert_equals(entries.length, 2); assert_greater_than(entries[1].time - entries[0].time, delay); assert_false(entries[1].isVisible); - t.done(); + nextStep(); } else { // Observer may not have updated yet. Wait for next frame. let timerExpired = performance.now() - entries[0].time >= delay; - waitForDelay(timerExpired); + waitForDelay(timerExpired, nextStep); } })); } @@ -69,7 +69,20 @@ // This should trigger a notification on the next run. occluder.style.marginTop = "-10px"; // Enter a rAF loop until the delay timer expires. - waitForDelay(false); + waitForDelay(false, step1); + } + + function step1() { + occluder.style.marginTop = "10px"; + // This style invalidation should cause a frame to run before the observer + // can generate a notification (due to delay parameter). Make sure the + // notification will still be generated even if we don't force more frames + // with a rAF loop. + t.step_timeout(() => { + assert_equals(entries.length, 3); + assert_true(entries[0].isVisible); + t.done(); + }, 2 * delay); } }, "'delay' parameter throttles frequency of notifications.");
diff --git a/third_party/blink/web_tests/external/wpt/webxr/xrSession_input_events_end.https.html b/third_party/blink/web_tests/external/wpt/webxr/xrSession_input_events_end.https.html index 37e0206..a932aad 100644 --- a/third_party/blink/web_tests/external/wpt/webxr/xrSession_input_events_end.https.html +++ b/third_party/blink/web_tests/external/wpt/webxr/xrSession_input_events_end.https.html
@@ -10,10 +10,16 @@ let fakeDeviceInitParams = TRACKED_IMMERSIVE_DEVICE; +let gl = null; + function requestImmersiveSession() { return new Promise((resolve, reject) => { navigator.xr.test.simulateUserActivation(() => { navigator.xr.requestSession('immersive-vr').then((session) => { + session.updateRenderState({ + baseLayer: new XRWebGLLayer(session, gl) + }); + resolve(session); }, (err) => { reject(err); @@ -22,8 +28,8 @@ }); } -let testFunction = function(session, fakeDeviceController, t) { - +let testFunction = function(session, fakeDeviceController, t, sessionObjects) { + gl = sessionObjects.gl; // helper method to send a click and then request a dummy animation frame to // ensure that the click propagates. We're doing everything in these tests // from event watchers, we just need to trigger the add/click to make the
diff --git a/third_party/blink/web_tests/platform/mac/virtual/threaded/external/wpt/css/css-scroll-snap/scroll-margin-expected.txt b/third_party/blink/web_tests/platform/mac/virtual/threaded/external/wpt/css/css-scroll-snap/scroll-margin-expected.txt deleted file mode 100644 index d3bfa9a..0000000 --- a/third_party/blink/web_tests/platform/mac/virtual/threaded/external/wpt/css/css-scroll-snap/scroll-margin-expected.txt +++ /dev/null
@@ -1,5 +0,0 @@ -This is a testharness.js-based test. -PASS Snaps to the positions adjusted by scroll-margin -FAIL scroll-margin doesn't contribute to the snap position of the element if it's outside of the scroll port assert_equals: expected 0 but got 400 -Harness: the test ran to completion. -
diff --git a/third_party/closure_compiler/externs/autofill_private.js b/third_party/closure_compiler/externs/autofill_private.js index d905d06..1263cf2 100644 --- a/third_party/closure_compiler/externs/autofill_private.js +++ b/third_party/closure_compiler/externs/autofill_private.js
@@ -1,4 +1,4 @@ -// Copyright 2018 The Chromium Authors. All rights reserved. +// 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. @@ -197,6 +197,12 @@ chrome.autofillPrivate.logServerCardLinkClicked = function() {}; /** + * Enables or disables FIDO Authentication for credit card unmasking. + * @param {boolean} enabled + */ +chrome.autofillPrivate.setCreditCardFIDOAuthEnabledState = function(enabled) {}; + +/** * Fired when the address list has changed, meaning that an entry has been * added, removed, or changed. |entries| The updated list of entries. * @type {!ChromeEvent}
diff --git a/third_party/feed/BUILD.gn b/third_party/feed/BUILD.gn index 3757358..a827f47 100644 --- a/third_party/feed/BUILD.gn +++ b/third_party/feed/BUILD.gn
@@ -34,6 +34,9 @@ resource_dirs = [ "src/src/main/java/com/google/android/libraries/feed/sharedstream/ui/res", ] + deps = [ + "//chrome/android:chrome_app_java_resources", + ] custom_package = "com.google.android.libraries.feed.sharedstream.ui" } @@ -47,6 +50,9 @@ resource_dirs = [ "src/src/main/java/com/google/android/libraries/feed/sharedstream/ui/res", ] + deps = [ + "//chrome/android:chrome_app_java_resources", + ] custom_package = "com.google.android.libraries.feed.basicstream.internal.drivers" } @@ -65,6 +71,9 @@ "src/src/main/java/com/google/android/libraries/feed/basicstream/res/", "src/src/main/java/com/google/android/libraries/feed/sharedstream/ui/res", ] + deps = [ + "//chrome/android:chrome_app_java_resources", + ] custom_package = "com.google.android.libraries.feed.basicstream" } @@ -78,6 +87,9 @@ resource_dirs = [ "src/src/main/java/com/google/android/libraries/feed/sharedstream/ui/res", ] + deps = [ + "//chrome/android:chrome_app_java_resources", + ] custom_package = "com.google.android.libraries.feed.sharedstream.contextmenumanager" }
diff --git a/third_party/feed/README.chromium b/third_party/feed/README.chromium index 0426612..b14e6b2 100644 --- a/third_party/feed/README.chromium +++ b/third_party/feed/README.chromium
@@ -2,7 +2,7 @@ Short name: feed URL: https://chromium.googlesource.com/feed Version: 0 -Revision: 4e6265827406b37da706e1e404cac5f99ae2854e +Revision: c25c8f41145ed610d1a73004e8bcd62d8e8111c1 License: Apache 2.0 License File: LICENSE Security Critical: yes
diff --git a/third_party/libvpx/README.chromium b/third_party/libvpx/README.chromium index 7deb8be..1c5c6d5 100644 --- a/third_party/libvpx/README.chromium +++ b/third_party/libvpx/README.chromium
@@ -5,9 +5,9 @@ License File: source/libvpx/LICENSE Security Critical: yes -Date: Tuesday September 10 2019 +Date: Friday September 20 2019 Branch: master -Commit: c094391e954aa274b9dcce3d6afcb5ba6bae7eff +Commit: b8d86733e9d9c58e17028720751f96dad2df7a09 Description: Contains the sources used to compile libvpx binaries used by Google Chrome and
diff --git a/third_party/libvpx/source/config/vpx_version.h b/third_party/libvpx/source/config/vpx_version.h index d7b78c35..6c549fc 100644 --- a/third_party/libvpx/source/config/vpx_version.h +++ b/third_party/libvpx/source/config/vpx_version.h
@@ -2,7 +2,7 @@ #define VERSION_MAJOR 1 #define VERSION_MINOR 8 #define VERSION_PATCH 1 -#define VERSION_EXTRA "131-gc094391e95" +#define VERSION_EXTRA "139-gb8d86733e9" #define VERSION_PACKED ((VERSION_MAJOR<<16)|(VERSION_MINOR<<8)|(VERSION_PATCH)) -#define VERSION_STRING_NOSP "v1.8.1-131-gc094391e95" -#define VERSION_STRING " v1.8.1-131-gc094391e95" +#define VERSION_STRING_NOSP "v1.8.1-139-gb8d86733e9" +#define VERSION_STRING " v1.8.1-139-gb8d86733e9"
diff --git a/third_party/metrics_proto/README.chromium b/third_party/metrics_proto/README.chromium index 264f9c7..5c88f3b8 100644 --- a/third_party/metrics_proto/README.chromium +++ b/third_party/metrics_proto/README.chromium
@@ -1,8 +1,8 @@ Name: Metrics Protos Short Name: metrics_proto URL: This is the canonical public repository -Version: 267295422 -Date: 2019/09/05 UTC +Version: 270770521 +Date: 2019/09/23 UTC License: BSD Security Critical: Yes
diff --git a/third_party/metrics_proto/omnibox_event.proto b/third_party/metrics_proto/omnibox_event.proto index e0522f1..a5d58d1 100644 --- a/third_party/metrics_proto/omnibox_event.proto +++ b/third_party/metrics_proto/omnibox_event.proto
@@ -206,6 +206,8 @@ // Non personalized query suggestions generated from a lightweight on device // head model. ON_DEVICE_HEAD = 17; + // Zero-prefix query suggestions based on device local history. + ZERO_SUGGEST_LOCAL_HISTORY = 18; } // The result set displayed on the completion popup
diff --git a/tools/binary_size/libsupersize/archive.py b/tools/binary_size/libsupersize/archive.py index fc799c2..ca8f930 100644 --- a/tools/binary_size/libsupersize/archive.py +++ b/tools/binary_size/libsupersize/archive.py
@@ -15,6 +15,7 @@ import os import posixpath import re +import string import subprocess import sys import tempfile @@ -34,6 +35,7 @@ import nm import obj_analyzer import path_util +import string_extract sys.path.insert(1, os.path.join(path_util.SRC_ROOT, 'tools', 'grit')) from grit.format import data_pack @@ -159,6 +161,10 @@ elif symbol.IsDex(): symbol.full_name, symbol.template_name, symbol.name = ( function_signature.ParseJava(full_name)) + elif symbol.IsStringLiteral(): + symbol.full_name = full_name + symbol.template_name = full_name + symbol.name = full_name elif symbol.IsNative(): # Remove [clone] suffix, and set flag accordingly. # Search from left-to-right, as multiple [clone]s can exist. @@ -844,6 +850,24 @@ num_deduced, num_arbitrations, num_unassigned) +def _NameStringLiterals(raw_symbols, elf_path, tool_prefix): + # Assign ASCII-readable string literals names like "string contents". + STRING_LENGTH_CUTOFF = 30 + + for sym, name in string_extract.ReadStringLiterals(raw_symbols, elf_path, + tool_prefix): + # Newlines and tabs are used as delimiters in file_format.py + # At this point, names still have a terminating null byte. + name = name.translate(None, '\t\n').strip('\00') + is_printable = all(c in string.printable for c in name) + if not is_printable: + sym.full_name = models.STRING_LITERAL_NAME + elif len(name) > STRING_LENGTH_CUTOFF: + sym.full_name = '"{}[...]"'.format(name[:STRING_LENGTH_CUTOFF]) + else: + sym.full_name = '"{}"'.format(name) + + def _ParseElfInfo(map_path, elf_path, tool_prefix, track_string_literals, outdir_context=None, linker_name=None): """Adds ELF section sizes and symbols.""" @@ -956,6 +980,9 @@ linker_map_parser.DeduceObjectPathsFromThinMap(raw_symbols, linker_map_extras) + if elf_path: + _NameStringLiterals(raw_symbols, elf_path, tool_prefix) + # If we have an ELF file, use its sizes as the source of truth, since some # sections can differ from the .map. return (elf_section_sizes if elf_path else map_section_sizes, raw_symbols, @@ -1521,7 +1548,7 @@ # Do not call _NormalizeNames() during archive since that method tends to need # tweaks over time. Calling it only when loading .size files allows for more - # flexability. + # flexibility. if normalize_names: _NormalizeNames(raw_symbols)
diff --git a/tools/binary_size/libsupersize/console.py b/tools/binary_size/libsupersize/console.py index ae1d3ce..b13164e 100644 --- a/tools/binary_size/libsupersize/console.py +++ b/tools/binary_size/libsupersize/console.py
@@ -126,26 +126,8 @@ elf_path = self._ElfPathForSymbol( size_info, tool_prefix, elf_path) - address, offset, _ = string_extract.LookupElfRodataInfo( - elf_path, tool_prefix) - adjust = offset - address - ret = [] - with open(elf_path, 'rb') as f: - for symbol in thing: - if symbol.section != 'r' or ( - not all_rodata and not symbol.IsStringLiteral()): - continue - f.seek(symbol.address + adjust) - data = f.read(symbol.size_without_padding) - # As of Oct 2017, there are ~90 symbols name .L.str(.##). These appear - # in the linker map file explicitly, and there doesn't seem to be a - # pattern as to which variables lose their kConstant name (the more - # common case), or which string literals don't get moved to - # ** merge strings (less common). - if symbol.IsStringLiteral() or ( - all_rodata and data and data[-1] == '\0'): - ret.append((symbol, data)) - return ret + return string_extract.ReadStringLiterals( + thing, elf_path, tool_prefix, all_rodata=all_rodata) def _DiffFunc(self, before=None, after=None, sort=True): """Diffs two SizeInfo objects. Returns a DeltaSizeInfo.
diff --git a/tools/binary_size/libsupersize/models.py b/tools/binary_size/libsupersize/models.py index 84c35d2f..6ad2d5a 100644 --- a/tools/binary_size/libsupersize/models.py +++ b/tools/binary_size/libsupersize/models.py
@@ -168,7 +168,6 @@ STRING_LITERAL_NAME = 'string literal' - class BaseSizeInfo(object): """Base class for SizeInfo and DeltaSizeInfo. @@ -359,7 +358,10 @@ self.name.endswith(']') and not self.name.endswith('[]')) def IsStringLiteral(self): - return self.full_name == STRING_LITERAL_NAME + # String literals have names like "string" or "very_long_str[...]", while + # non-ASCII strings are named STRING_LITERAL_NAME. + return self.full_name.startswith( + '"') or self.full_name == STRING_LITERAL_NAME # Used for diffs to know whether or not it is accurate to consider two symbols # with the same name as being the same.
diff --git a/tools/binary_size/libsupersize/string_extract.py b/tools/binary_size/libsupersize/string_extract.py index 52e5cb98..79fd1be 100644 --- a/tools/binary_size/libsupersize/string_extract.py +++ b/tools/binary_size/libsupersize/string_extract.py
@@ -10,6 +10,9 @@ ReadFileChunks(): Reads raw data from a file, given a list of ranges in the file. +ReadStringLiterals(): + Reads the ELF file to find the string contents of a list of string literals. + ResolveStringPiecesIndirect(): BulkForkAndCall() target: Given {path: [string addresses]} and [raw_string_data for each string_section]: @@ -290,3 +293,29 @@ ret = _AnnotateStringData(string_data, GeneratePathAndValues()) return [concurrent.EncodeDictOfLists(x) for x in ret] + + +def ReadStringLiterals(symbols, elf_path, tool_prefix, all_rodata=False): + """Returns an iterable of (symbol, string) for all string literal symbols. + + Args: + symbols: An iterable of Symbols + elf_path: Path to the executable containing the symbols. + all_rodata: Assume every symbol within .rodata that ends with a \0 is a + string literal. + """ + address, offset, _ = LookupElfRodataInfo(elf_path, tool_prefix) + adjust = offset - address + with open(elf_path, 'rb') as f: + for symbol in symbols: + if symbol.section != 'r': + continue + f.seek(symbol.address + adjust) + data = f.read(symbol.size_without_padding) + # As of Oct 2017, there are ~90 symbols name .L.str(.##). These appear + # in the linker map file explicitly, and there doesn't seem to be a + # pattern as to which variables lose their kConstant name (the more + # common case), or which string literals don't get moved to + # ** merge strings (less common). + if symbol.IsStringLiteral() or (all_rodata and data and data[-1] == '\0'): + yield ((symbol, data))
diff --git a/tools/binary_size/libsupersize/testdata/Archive_Apk.golden b/tools/binary_size/libsupersize/testdata/Archive_Apk.golden index e173eb9e..4335852 100644 --- a/tools/binary_size/libsupersize/testdata/Archive_Apk.golden +++ b/tools/binary_size/libsupersize/testdata/Archive_Apk.golden
@@ -288,9 +288,9 @@ .other@0(size_without_padding=1024,padding=0,full_name=res/drawable-v13/test.xml,object_path=,source_path=chrome/android/res/drawable/test.xml,flags={},num_aliases=1,component=) .other@0(size_without_padding=0,padding=764,full_name=Overhead: APK file,object_path=,source_path=,flags={},num_aliases=1,component=) .other@0(size_without_padding=0,padding=33984171,full_name=Overhead: ELF file,object_path=,source_path=,flags={},num_aliases=1,component=) -.rodata@266e600(size_without_padding=5,padding=0,full_name=string literal,object_path=base/base/page_allocator.o,source_path=base/page_allocator.cc,flags={},num_aliases=2,component=Blink>Internal) -.rodata@266e600(size_without_padding=5,padding=0,full_name=string literal,object_path=third_party/icu/icuuc/ucnv_ext.o,source_path=third_party/icu/ucnv_ext.c,flags={gen},num_aliases=2,component=Internal>Android) -.rodata@266e605(size_without_padding=16,padding=0,full_name=string literal,object_path=third_party/icu/icuuc/ucnv_ext.o,source_path=third_party/icu/ucnv_ext.c,flags={gen},num_aliases=1,component=Internal>Android) +.rodata@266e600(size_without_padding=5,padding=0,full_name="Str1",object_path=base/base/page_allocator.o,source_path=base/page_allocator.cc,flags={},num_aliases=2,component=Blink>Internal) +.rodata@266e600(size_without_padding=5,padding=0,full_name="Str1",object_path=third_party/icu/icuuc/ucnv_ext.o,source_path=third_party/icu/ucnv_ext.c,flags={gen},num_aliases=2,component=Internal>Android) +.rodata@266e605(size_without_padding=16,padding=0,full_name="String literal2",object_path=third_party/icu/icuuc/ucnv_ext.o,source_path=third_party/icu/ucnv_ext.c,flags={gen},num_aliases=1,component=Internal>Android) .rodata@266e630(size_without_padding=16,padding=27,full_name=** merge strings,object_path=,source_path=,flags={},num_aliases=1,component=) .rodata@284d600(size_without_padding=3425,padding=1961920,full_name=** merge constants,object_path=,source_path=,flags={},num_aliases=1,component=) .rodata@284e364(size_without_padding=0,padding=3,full_name=** symbol gap 0,object_path=,source_path=,flags={},num_aliases=1,component=)
diff --git a/tools/binary_size/libsupersize/testdata/Archive_Elf.golden b/tools/binary_size/libsupersize/testdata/Archive_Elf.golden index e87d5712..71c8468 100644 --- a/tools/binary_size/libsupersize/testdata/Archive_Elf.golden +++ b/tools/binary_size/libsupersize/testdata/Archive_Elf.golden
@@ -85,9 +85,9 @@ .data.rel.ro.local@2cd84e0(size_without_padding=16,padding=16,full_name=.Lswitch.table.45,object_path=third_party/gvr-android-sdk/libgvr_shim_static_arm.a/libcontroller_api_impl.a_controller_api_impl.o,source_path=,flags={},num_aliases=1,component=) .data.rel.ro.local@2cd84f0(size_without_padding=8,padding=0,full_name=kSystemClassPrefixes,object_path=third_party/gvr-android-sdk/libgvr_shim_static_arm.a/libport_android_jni.a_jni_utils.o,source_path=,flags={anon},num_aliases=1,component=) .other@0(size_without_padding=0,padding=33984171,full_name=Overhead: ELF file,object_path=,source_path=,flags={},num_aliases=1,component=) -.rodata@266e600(size_without_padding=5,padding=0,full_name=string literal,object_path=base/base/page_allocator.o,source_path=base/page_allocator.cc,flags={},num_aliases=2,component=Blink>Internal) -.rodata@266e600(size_without_padding=5,padding=0,full_name=string literal,object_path=third_party/icu/icuuc/ucnv_ext.o,source_path=third_party/icu/ucnv_ext.c,flags={gen},num_aliases=2,component=Internal>Android) -.rodata@266e605(size_without_padding=16,padding=0,full_name=string literal,object_path=third_party/icu/icuuc/ucnv_ext.o,source_path=third_party/icu/ucnv_ext.c,flags={gen},num_aliases=1,component=Internal>Android) +.rodata@266e600(size_without_padding=5,padding=0,full_name="Str1",object_path=base/base/page_allocator.o,source_path=base/page_allocator.cc,flags={},num_aliases=2,component=Blink>Internal) +.rodata@266e600(size_without_padding=5,padding=0,full_name="Str1",object_path=third_party/icu/icuuc/ucnv_ext.o,source_path=third_party/icu/ucnv_ext.c,flags={gen},num_aliases=2,component=Internal>Android) +.rodata@266e605(size_without_padding=16,padding=0,full_name="String literal2",object_path=third_party/icu/icuuc/ucnv_ext.o,source_path=third_party/icu/ucnv_ext.c,flags={gen},num_aliases=1,component=Internal>Android) .rodata@266e630(size_without_padding=16,padding=27,full_name=** merge strings,object_path=,source_path=,flags={},num_aliases=1,component=) .rodata@284d600(size_without_padding=3425,padding=1961920,full_name=** merge constants,object_path=,source_path=,flags={},num_aliases=1,component=) .rodata@284e364(size_without_padding=0,padding=3,full_name=** symbol gap 0,object_path=,source_path=,flags={},num_aliases=1,component=)
diff --git a/tools/binary_size/libsupersize/testdata/Archive_MinimalApks.golden b/tools/binary_size/libsupersize/testdata/Archive_MinimalApks.golden index 01c78def..ffc0afab 100644 --- a/tools/binary_size/libsupersize/testdata/Archive_MinimalApks.golden +++ b/tools/binary_size/libsupersize/testdata/Archive_MinimalApks.golden
@@ -289,9 +289,9 @@ .other@0(size_without_padding=1024,padding=0,full_name=res/drawable-v13/test.xml,object_path=,source_path=chrome/android/res/drawable/test.xml,flags={},num_aliases=1,component=) .other@0(size_without_padding=0,padding=764,full_name=Overhead: APK file,object_path=,source_path=,flags={},num_aliases=1,component=) .other@0(size_without_padding=0,padding=33984171,full_name=Overhead: ELF file,object_path=,source_path=,flags={},num_aliases=1,component=) -.rodata@266e600(size_without_padding=5,padding=0,full_name=string literal,object_path=base/base/page_allocator.o,source_path=base/page_allocator.cc,flags={},num_aliases=2,component=Blink>Internal) -.rodata@266e600(size_without_padding=5,padding=0,full_name=string literal,object_path=third_party/icu/icuuc/ucnv_ext.o,source_path=third_party/icu/ucnv_ext.c,flags={gen},num_aliases=2,component=Internal>Android) -.rodata@266e605(size_without_padding=16,padding=0,full_name=string literal,object_path=third_party/icu/icuuc/ucnv_ext.o,source_path=third_party/icu/ucnv_ext.c,flags={gen},num_aliases=1,component=Internal>Android) +.rodata@266e600(size_without_padding=5,padding=0,full_name="Str1",object_path=base/base/page_allocator.o,source_path=base/page_allocator.cc,flags={},num_aliases=2,component=Blink>Internal) +.rodata@266e600(size_without_padding=5,padding=0,full_name="Str1",object_path=third_party/icu/icuuc/ucnv_ext.o,source_path=third_party/icu/ucnv_ext.c,flags={gen},num_aliases=2,component=Internal>Android) +.rodata@266e605(size_without_padding=16,padding=0,full_name="String literal2",object_path=third_party/icu/icuuc/ucnv_ext.o,source_path=third_party/icu/ucnv_ext.c,flags={gen},num_aliases=1,component=Internal>Android) .rodata@266e630(size_without_padding=16,padding=27,full_name=** merge strings,object_path=,source_path=,flags={},num_aliases=1,component=) .rodata@284d600(size_without_padding=3425,padding=1961920,full_name=** merge constants,object_path=,source_path=,flags={},num_aliases=1,component=) .rodata@284e364(size_without_padding=0,padding=3,full_name=** symbol gap 0,object_path=,source_path=,flags={},num_aliases=1,component=)
diff --git a/tools/binary_size/libsupersize/testdata/Archive_Pak_Files.golden b/tools/binary_size/libsupersize/testdata/Archive_Pak_Files.golden index 13c0f0ec..ce5b255 100644 --- a/tools/binary_size/libsupersize/testdata/Archive_Pak_Files.golden +++ b/tools/binary_size/libsupersize/testdata/Archive_Pak_Files.golden
@@ -87,9 +87,9 @@ .data.rel.ro.local@2cd84e0(size_without_padding=16,padding=16,full_name=.Lswitch.table.45,object_path=third_party/gvr-android-sdk/libgvr_shim_static_arm.a/libcontroller_api_impl.a_controller_api_impl.o,source_path=,flags={},num_aliases=1,component=) .data.rel.ro.local@2cd84f0(size_without_padding=8,padding=0,full_name=kSystemClassPrefixes,object_path=third_party/gvr-android-sdk/libgvr_shim_static_arm.a/libport_android_jni.a_jni_utils.o,source_path=,flags={anon},num_aliases=1,component=) .other@0(size_without_padding=0,padding=33984171,full_name=Overhead: ELF file,object_path=,source_path=,flags={},num_aliases=1,component=) -.rodata@266e600(size_without_padding=5,padding=0,full_name=string literal,object_path=base/base/page_allocator.o,source_path=base/page_allocator.cc,flags={},num_aliases=2,component=Blink>Internal) -.rodata@266e600(size_without_padding=5,padding=0,full_name=string literal,object_path=third_party/icu/icuuc/ucnv_ext.o,source_path=third_party/icu/ucnv_ext.c,flags={gen},num_aliases=2,component=Internal>Android) -.rodata@266e605(size_without_padding=16,padding=0,full_name=string literal,object_path=third_party/icu/icuuc/ucnv_ext.o,source_path=third_party/icu/ucnv_ext.c,flags={gen},num_aliases=1,component=Internal>Android) +.rodata@266e600(size_without_padding=5,padding=0,full_name="Str1",object_path=base/base/page_allocator.o,source_path=base/page_allocator.cc,flags={},num_aliases=2,component=Blink>Internal) +.rodata@266e600(size_without_padding=5,padding=0,full_name="Str1",object_path=third_party/icu/icuuc/ucnv_ext.o,source_path=third_party/icu/ucnv_ext.c,flags={gen},num_aliases=2,component=Internal>Android) +.rodata@266e605(size_without_padding=16,padding=0,full_name="String literal2",object_path=third_party/icu/icuuc/ucnv_ext.o,source_path=third_party/icu/ucnv_ext.c,flags={gen},num_aliases=1,component=Internal>Android) .rodata@266e630(size_without_padding=16,padding=27,full_name=** merge strings,object_path=,source_path=,flags={},num_aliases=1,component=) .rodata@284d600(size_without_padding=3425,padding=1961920,full_name=** merge constants,object_path=,source_path=,flags={},num_aliases=1,component=) .rodata@284e364(size_without_padding=0,padding=3,full_name=** symbol gap 0,object_path=,source_path=,flags={},num_aliases=1,component=)
diff --git a/tools/binary_size/libsupersize/testdata/Console.golden b/tools/binary_size/libsupersize/testdata/Console.golden index 24494bf..5d58f265 100644 --- a/tools/binary_size/libsupersize/testdata/Console.golden +++ b/tools/binary_size/libsupersize/testdata/Console.golden
@@ -60,8 +60,8 @@ # For even more inspiration, look at canned_queries.py # (and feel free to add your own!). -0: (.rodata@266e600(size_without_padding=5,padding=0,full_name=string literal,object_path=base/base/page_allocator.o,source_path=base/page_allocator.cc,flags={},num_aliases=2,component=Blink>Internal), 'Str1\x00') -1: (.rodata@266e605(size_without_padding=16,padding=0,full_name=string literal,object_path=third_party/icu/icuuc/ucnv_ext.o,source_path=third_party/icu/ucnv_ext.c,flags={gen},num_aliases=1,component=Internal>Android), 'String literal2\x00') +0: (.rodata@266e600(size_without_padding=5,padding=0,full_name="Str1",object_path=base/base/page_allocator.o,source_path=base/page_allocator.cc,flags={},num_aliases=2,component=Blink>Internal), 'Str1\x00') +1: (.rodata@266e605(size_without_padding=16,padding=0,full_name="String literal2",object_path=third_party/icu/icuuc/ucnv_ext.o,source_path=third_party/icu/ucnv_ext.c,flags={gen},num_aliases=1,component=Internal>Android), 'String literal2\x00') Metadata: elf_arch=arm elf_build_id=WhatAnAmazingBuildId @@ -126,11 +126,11 @@ 13) 34774455 (92.7%) o@0x0 33984171 {no path} Overhead: ELF file 14) 34774457 (92.7%) r@0x266e600 2.5 (size=5) base/page_allocator.cc - string literal (num_aliases=2) + "Str1" (num_aliases=2) 15) 34774460 (92.7%) r@0x266e600 2.5 (size=5) $root_gen_dir/third_party/icu/ucnv_ext.c - string literal (num_aliases=2) + "Str1" (num_aliases=2) 16) 34774476 (92.7%) r@0x266e605 16 $root_gen_dir/third_party/icu/ucnv_ext.c - string literal + "String literal2" 17) 34774519 (92.7%) r@0x266e630 43 {no path} ** merge strings 18) 36739864 (98.0%) r@0x284d600 1965345 {no path}
diff --git a/tools/binary_size/libsupersize/testdata/Csv.golden b/tools/binary_size/libsupersize/testdata/Csv.golden index ecd143c..07f40e9 100644 --- a/tools/binary_size/libsupersize/testdata/Csv.golden +++ b/tools/binary_size/libsupersize/testdata/Csv.golden
@@ -25,9 +25,9 @@ ,0x2cd84e0,16,16,1,32.0,R,.Lswitch.table.45 ,0x2cd84f0,8,0,1,8.0,R,kSystemClassPrefixes ,0x0,0,33984171,1,33984171.0,o,Overhead: ELF file -,0x266e600,5,0,2,2.5,r,string literal -,0x266e600,5,0,2,2.5,r,string literal -,0x266e605,16,0,1,16.0,r,string literal +,0x266e600,5,0,2,2.5,r,"""Str1""" +,0x266e600,5,0,2,2.5,r,"""Str1""" +,0x266e605,16,0,1,16.0,r,"""String literal2""" ,0x266e630,16,27,1,43.0,r,** merge strings ,0x284d600,3425,1961920,1,1965345.0,r,** merge constants ,0x284e364,0,3,1,3.0,r,** symbol gap 0
diff --git a/tools/binary_size/libsupersize/testdata/FullDescription.golden b/tools/binary_size/libsupersize/testdata/FullDescription.golden index 3cc6349..14b93d1b 100644 --- a/tools/binary_size/libsupersize/testdata/FullDescription.golden +++ b/tools/binary_size/libsupersize/testdata/FullDescription.golden
@@ -163,13 +163,13 @@ flags={} name=Overhead: ELF file 14) 34774457 (92.7%) r@0x266e600 pss=2.5 (size=5) padding=0 num_aliases=2 source_path=base/page_allocator.cc object_path=base/base/page_allocator.o - flags={} name=string literal + flags={} name="Str1" 15) 34774460 (92.7%) r@0x266e600 pss=2.5 (size=5) padding=0 num_aliases=2 source_path=third_party/icu/ucnv_ext.c object_path=third_party/icu/icuuc/ucnv_ext.o - flags={gen} name=string literal + flags={gen} name="Str1" 16) 34774476 (92.7%) r@0x266e605 pss=16 padding=0 num_aliases=1 source_path=third_party/icu/ucnv_ext.c object_path=third_party/icu/icuuc/ucnv_ext.o - flags={gen} name=string literal + flags={gen} name="String literal2" 17) 34774519 (92.7%) r@0x266e630 pss=43 padding=27 num_aliases=1 source_path= object_path= flags={} name=** merge strings @@ -344,13 +344,13 @@ flags={} name=Overhead: ELF file 14) 34774457 (92.7%) r@0x266e600 pss=2.5 (size=5) padding=0 num_aliases=2 source_path=base/page_allocator.cc object_path=base/base/page_allocator.o - flags={} name=string literal + flags={} name="Str1" 15) 34774460 (92.7%) r@0x266e600 pss=2.5 (size=5) padding=0 num_aliases=2 source_path=third_party/icu/ucnv_ext.c object_path=third_party/icu/icuuc/ucnv_ext.o - flags={gen} name=string literal + flags={gen} name="Str1" 16) 34774476 (92.7%) r@0x266e605 pss=16 padding=0 num_aliases=1 source_path=third_party/icu/ucnv_ext.c object_path=third_party/icu/icuuc/ucnv_ext.o - flags={gen} name=string literal + flags={gen} name="String literal2" 17) 34774519 (92.7%) r@0x266e630 pss=43 padding=27 num_aliases=1 source_path= object_path= flags={} name=** merge strings
diff --git a/tools/binary_size/libsupersize/testdata/SymbolGroupMethods.golden b/tools/binary_size/libsupersize/testdata/SymbolGroupMethods.golden index d3042b2..ae370478 100644 --- a/tools/binary_size/libsupersize/testdata/SymbolGroupMethods.golden +++ b/tools/binary_size/libsupersize/testdata/SymbolGroupMethods.golden
@@ -1,9 +1,9 @@ GroupedByName() -Showing 46 symbols (46 unique) with total pss: 37499787 bytes +Showing 47 symbols (47 unique) with total pss: 37499787 bytes Histogram of symbols based on PSS: {0}: 6 [8,16): 3 [64,128): 2 [2048,4096): 1 [524288,1048576): 2 [2,4): 3 [16,32): 11 [128,256): 1 [8192,16384): 1 [1048576,2097152): 1 - [4,8): 5 [32,64): 7 [256,512): 1 [65536,131072): 1 [33554432,67108864): 1 + [4,8): 6 [32,64): 7 [256,512): 1 [65536,131072): 1 [33554432,67108864): 1 Sizes: .text=81.8kb .rodata=2.52mb .data.rel.ro=92 bytes .data=168 bytes .bss=512kb .other=32.4mb total=35.8mb Counts: .text=21 .rodata=11 .data.rel.ro=3 .data=5 .bss=6 .other=1 Number of unique paths: 9 @@ -25,44 +25,45 @@ 11) 790276 (2.1%) *@Group 32 .Lswitch.table.45 (count=1) 12) 790284 (2.1%) *@Group 8 kSystemClassPrefixes (count=1) 13) 34774455 (92.7%) *@Group 33984171 Overhead: ELF file (count=1) -14) 34774476 (92.7%) *@Group 21 string literal (count=3) -15) 34774519 (92.7%) *@Group 43 ** merge strings (count=1) -16) 36739864 (98.0%) *@Group 1965345 ** merge constants (count=1) -17) 36739867 (98.0%) *@Group 3 ** symbol gap 0 (count=1) -18) 36739875 (98.0%) *@Group 8 (count=1) -19) 36739919 (98.0%) *@Group 44 Name (count=1) -20) 36739951 (98.0%) *@Group 32 chrome::mojom::FilePatcher::Name_ (count=1) -21) 37415991 (99.8%) *@Group 676040 kAnimationFrameTimeHistogramClassPath (count=1) -22) 37415995 (99.8%) *@Group 4 blink::CSSValueKeywordsHash::findValueImpl::value_word_list (count=1) -23) 37416011 (99.8%) *@Group 16 _GLOBAL__sub_I_page_allocator.cc (count=1) -24) 37416067 (99.8%) *@Group 56 _GLOBAL__sub_I_bbr_sender.cc (count=1) -25) 37416095 (99.8%) *@Group 28 _GLOBAL__sub_I_pacing_sender.cc (count=1) -26) 37416165 (99.8%) *@Group 70 extFromUUseMapping (count=2) -27) 37425923 (99.8%) *@Group 9758 ** symbol gaps (count=1) -28) 37426371 (99.8%) *@Group 448 ucnv_extMatchFromU (count=1) -29) 37426399 (99.8%) *@Group 28 _GLOBAL__sub_I_SkDeviceProfile.cpp (count=1) -30) 37495523 (100.0%) *@Group 69124 foo_bar (count=1) -31) 37495547 (100.0%) *@Group 24 BazAlias (count=1) -32) 37495577 (100.0%) *@Group 30 blink::ContiguousContainerBase::shrinkToFit (count=3) -33) 37495580 (100.0%) *@Group 3 BarAlias (count=1) -34) 37495583 (100.0%) *@Group 3 FooAlias (count=1) -35) 37495611 (100.0%) *@Group 28 blink::ContiguousContainerBase::ContiguousContainerBase (count=1) -36) 37495705 (100.0%) *@Group 94 blink::PaintChunker::releasePaintChunks (count=1) -37) 37499739 (100.0%) *@Group 4034 ** outlined function (count=1) -38) 37499763 (100.0%) *@Group 24 ** outlined function * 2 (count=1) -39) 37499787 (100.0%) *@Group 24 aliasedWithOutlinedFunction (count=1) -40) 37499787 (100.0%) *@Group 0 ff_cos_131072 (count=1) -41) 37499787 (100.0%) *@Group 0 ff_cos_131072_fixed (count=1) -42) 37499787 (100.0%) *@Group 0 ff_cos_65536 (count=1) -43) 37499787 (100.0%) *@Group 0 g_chrome_content_browser_client (count=1) -44) 37499787 (100.0%) *@Group 0 SaveHistogram::atomic_histogram_pointer (count=1) -45) 37499787 (100.0%) *@Group 0 g_AnimationFrameTimeHistogram_clazz (count=1) +14) 34774460 (92.7%) *@Group 5 "Str1" (count=2) +15) 34774476 (92.7%) *@Group 16 "String literal2" (count=1) +16) 34774519 (92.7%) *@Group 43 ** merge strings (count=1) +17) 36739864 (98.0%) *@Group 1965345 ** merge constants (count=1) +18) 36739867 (98.0%) *@Group 3 ** symbol gap 0 (count=1) +19) 36739875 (98.0%) *@Group 8 (count=1) +20) 36739919 (98.0%) *@Group 44 Name (count=1) +21) 36739951 (98.0%) *@Group 32 chrome::mojom::FilePatcher::Name_ (count=1) +22) 37415991 (99.8%) *@Group 676040 kAnimationFrameTimeHistogramClassPath (count=1) +23) 37415995 (99.8%) *@Group 4 blink::CSSValueKeywordsHash::findValueImpl::value_word_list (count=1) +24) 37416011 (99.8%) *@Group 16 _GLOBAL__sub_I_page_allocator.cc (count=1) +25) 37416067 (99.8%) *@Group 56 _GLOBAL__sub_I_bbr_sender.cc (count=1) +26) 37416095 (99.8%) *@Group 28 _GLOBAL__sub_I_pacing_sender.cc (count=1) +27) 37416165 (99.8%) *@Group 70 extFromUUseMapping (count=2) +28) 37425923 (99.8%) *@Group 9758 ** symbol gaps (count=1) +29) 37426371 (99.8%) *@Group 448 ucnv_extMatchFromU (count=1) +30) 37426399 (99.8%) *@Group 28 _GLOBAL__sub_I_SkDeviceProfile.cpp (count=1) +31) 37495523 (100.0%) *@Group 69124 foo_bar (count=1) +32) 37495547 (100.0%) *@Group 24 BazAlias (count=1) +33) 37495577 (100.0%) *@Group 30 blink::ContiguousContainerBase::shrinkToFit (count=3) +34) 37495580 (100.0%) *@Group 3 BarAlias (count=1) +35) 37495583 (100.0%) *@Group 3 FooAlias (count=1) +36) 37495611 (100.0%) *@Group 28 blink::ContiguousContainerBase::ContiguousContainerBase (count=1) +37) 37495705 (100.0%) *@Group 94 blink::PaintChunker::releasePaintChunks (count=1) +38) 37499739 (100.0%) *@Group 4034 ** outlined function (count=1) +39) 37499763 (100.0%) *@Group 24 ** outlined function * 2 (count=1) +40) 37499787 (100.0%) *@Group 24 aliasedWithOutlinedFunction (count=1) +41) 37499787 (100.0%) *@Group 0 ff_cos_131072 (count=1) +42) 37499787 (100.0%) *@Group 0 ff_cos_131072_fixed (count=1) +43) 37499787 (100.0%) *@Group 0 ff_cos_65536 (count=1) +44) 37499787 (100.0%) *@Group 0 g_chrome_content_browser_client (count=1) +45) 37499787 (100.0%) *@Group 0 SaveHistogram::atomic_histogram_pointer (count=1) +46) 37499787 (100.0%) *@Group 0 g_AnimationFrameTimeHistogram_clazz (count=1) GroupedByName(depth=1) -Showing 38 symbols (38 unique) with total pss: 37499787 bytes +Showing 39 symbols (39 unique) with total pss: 37499787 bytes Histogram of symbols based on PSS: - {0}: 6 [16,32): 8 [128,256): 2 [8192,16384): 1 [1048576,2097152): 1 - [2,4): 3 [32,64): 6 [256,512): 1 [65536,131072): 1 [33554432,67108864): 1 - [8,16): 4 [64,128): 1 [2048,4096): 1 [524288,1048576): 2 + {0}: 6 [8,16): 4 [64,128): 1 [2048,4096): 1 [524288,1048576): 2 + [2,4): 3 [16,32): 8 [128,256): 2 [8192,16384): 1 [1048576,2097152): 1 + [4,8): 1 [32,64): 6 [256,512): 1 [65536,131072): 1 [33554432,67108864): 1 Sizes: .text=81.8kb .rodata=2.52mb .data.rel.ro=92 bytes .data=168 bytes .bss=512kb .other=32.4mb total=35.8mb Counts: .text=21 .rodata=11 .data.rel.ro=3 .data=5 .bss=6 .other=1 Number of unique paths: 9 @@ -80,40 +81,41 @@ 7) 790308 (2.1%) *@Group 32 .Lswitch.table.45 (count=1) 8) 790316 (2.1%) *@Group 8 kSystemClassPrefixes (count=1) 9) 34774487 (92.7%) *@Group 33984171 Overhead: ELF file (count=1) -10) 34774508 (92.7%) *@Group 21 string literal (count=3) -11) 34774551 (92.7%) *@Group 43 ** merge strings (count=1) -12) 36739896 (98.0%) *@Group 1965345 ** merge constants (count=1) -13) 36739899 (98.0%) *@Group 3 ** symbol gap 0 (count=1) -14) 36739907 (98.0%) *@Group 8 (count=1) -15) 36739951 (98.0%) *@Group 44 Name (count=1) -16) 37415991 (99.8%) *@Group 676040 kAnimationFrameTimeHistogramClassPath (count=1) -17) 37416147 (99.8%) *@Group 156 blink (count=6) -18) 37416163 (99.8%) *@Group 16 _GLOBAL__sub_I_page_allocator.cc (count=1) -19) 37416219 (99.8%) *@Group 56 _GLOBAL__sub_I_bbr_sender.cc (count=1) -20) 37416247 (99.8%) *@Group 28 _GLOBAL__sub_I_pacing_sender.cc (count=1) -21) 37416317 (99.8%) *@Group 70 extFromUUseMapping (count=2) -22) 37426075 (99.8%) *@Group 9758 ** symbol gaps (count=1) -23) 37426523 (99.8%) *@Group 448 ucnv_extMatchFromU (count=1) -24) 37426551 (99.8%) *@Group 28 _GLOBAL__sub_I_SkDeviceProfile.cpp (count=1) -25) 37495675 (100.0%) *@Group 69124 foo_bar (count=1) -26) 37495699 (100.0%) *@Group 24 BazAlias (count=1) -27) 37495702 (100.0%) *@Group 3 BarAlias (count=1) -28) 37495705 (100.0%) *@Group 3 FooAlias (count=1) -29) 37499739 (100.0%) *@Group 4034 ** outlined function (count=1) -30) 37499763 (100.0%) *@Group 24 ** outlined function * 2 (count=1) -31) 37499787 (100.0%) *@Group 24 aliasedWithOutlinedFunction (count=1) -32) 37499787 (100.0%) *@Group 0 ff_cos_131072 (count=1) -33) 37499787 (100.0%) *@Group 0 ff_cos_131072_fixed (count=1) -34) 37499787 (100.0%) *@Group 0 ff_cos_65536 (count=1) -35) 37499787 (100.0%) *@Group 0 g_chrome_content_browser_client (count=1) -36) 37499787 (100.0%) *@Group 0 SaveHistogram (count=1) -37) 37499787 (100.0%) *@Group 0 g_AnimationFrameTimeHistogram_clazz (count=1) +10) 34774492 (92.7%) *@Group 5 "Str1" (count=2) +11) 34774508 (92.7%) *@Group 16 "String literal2" (count=1) +12) 34774551 (92.7%) *@Group 43 ** merge strings (count=1) +13) 36739896 (98.0%) *@Group 1965345 ** merge constants (count=1) +14) 36739899 (98.0%) *@Group 3 ** symbol gap 0 (count=1) +15) 36739907 (98.0%) *@Group 8 (count=1) +16) 36739951 (98.0%) *@Group 44 Name (count=1) +17) 37415991 (99.8%) *@Group 676040 kAnimationFrameTimeHistogramClassPath (count=1) +18) 37416147 (99.8%) *@Group 156 blink (count=6) +19) 37416163 (99.8%) *@Group 16 _GLOBAL__sub_I_page_allocator.cc (count=1) +20) 37416219 (99.8%) *@Group 56 _GLOBAL__sub_I_bbr_sender.cc (count=1) +21) 37416247 (99.8%) *@Group 28 _GLOBAL__sub_I_pacing_sender.cc (count=1) +22) 37416317 (99.8%) *@Group 70 extFromUUseMapping (count=2) +23) 37426075 (99.8%) *@Group 9758 ** symbol gaps (count=1) +24) 37426523 (99.8%) *@Group 448 ucnv_extMatchFromU (count=1) +25) 37426551 (99.8%) *@Group 28 _GLOBAL__sub_I_SkDeviceProfile.cpp (count=1) +26) 37495675 (100.0%) *@Group 69124 foo_bar (count=1) +27) 37495699 (100.0%) *@Group 24 BazAlias (count=1) +28) 37495702 (100.0%) *@Group 3 BarAlias (count=1) +29) 37495705 (100.0%) *@Group 3 FooAlias (count=1) +30) 37499739 (100.0%) *@Group 4034 ** outlined function (count=1) +31) 37499763 (100.0%) *@Group 24 ** outlined function * 2 (count=1) +32) 37499787 (100.0%) *@Group 24 aliasedWithOutlinedFunction (count=1) +33) 37499787 (100.0%) *@Group 0 ff_cos_131072 (count=1) +34) 37499787 (100.0%) *@Group 0 ff_cos_131072_fixed (count=1) +35) 37499787 (100.0%) *@Group 0 ff_cos_65536 (count=1) +36) 37499787 (100.0%) *@Group 0 g_chrome_content_browser_client (count=1) +37) 37499787 (100.0%) *@Group 0 SaveHistogram (count=1) +38) 37499787 (100.0%) *@Group 0 g_AnimationFrameTimeHistogram_clazz (count=1) GroupedByName(depth=-1) -Showing 41 symbols (41 unique) with total pss: 37499787 bytes +Showing 42 symbols (42 unique) with total pss: 37499787 bytes Histogram of symbols based on PSS: {0}: 6 [8,16): 4 [64,128): 2 [2048,4096): 1 [524288,1048576): 2 [2,4): 3 [16,32): 8 [128,256): 1 [8192,16384): 1 [1048576,2097152): 1 - [4,8): 1 [32,64): 8 [256,512): 1 [65536,131072): 1 [33554432,67108864): 1 + [4,8): 2 [32,64): 8 [256,512): 1 [65536,131072): 1 [33554432,67108864): 1 Sizes: .text=81.8kb .rodata=2.52mb .data.rel.ro=92 bytes .data=168 bytes .bss=512kb .other=32.4mb total=35.8mb Counts: .text=21 .rodata=11 .data.rel.ro=3 .data=5 .bss=6 .other=1 Number of unique paths: 9 @@ -131,42 +133,43 @@ 7) 790276 (2.1%) *@Group 32 .Lswitch.table.45 (count=1) 8) 790284 (2.1%) *@Group 8 kSystemClassPrefixes (count=1) 9) 34774455 (92.7%) *@Group 33984171 Overhead: ELF file (count=1) -10) 34774476 (92.7%) *@Group 21 string literal (count=3) -11) 34774519 (92.7%) *@Group 43 ** merge strings (count=1) -12) 36739864 (98.0%) *@Group 1965345 ** merge constants (count=1) -13) 36739867 (98.0%) *@Group 3 ** symbol gap 0 (count=1) -14) 36739875 (98.0%) *@Group 8 (count=1) -15) 36739919 (98.0%) *@Group 44 Name (count=1) -16) 36739951 (98.0%) *@Group 32 chrome::mojom::FilePatcher (count=1) -17) 37415991 (99.8%) *@Group 676040 kAnimationFrameTimeHistogramClassPath (count=1) -18) 37415995 (99.8%) *@Group 4 blink::CSSValueKeywordsHash::findValueImpl (count=1) -19) 37416011 (99.8%) *@Group 16 _GLOBAL__sub_I_page_allocator.cc (count=1) -20) 37416067 (99.8%) *@Group 56 _GLOBAL__sub_I_bbr_sender.cc (count=1) -21) 37416095 (99.8%) *@Group 28 _GLOBAL__sub_I_pacing_sender.cc (count=1) -22) 37416165 (99.8%) *@Group 70 extFromUUseMapping (count=2) -23) 37425923 (99.8%) *@Group 9758 ** symbol gaps (count=1) -24) 37426371 (99.8%) *@Group 448 ucnv_extMatchFromU (count=1) -25) 37426399 (99.8%) *@Group 28 _GLOBAL__sub_I_SkDeviceProfile.cpp (count=1) -26) 37495523 (100.0%) *@Group 69124 foo_bar (count=1) -27) 37495547 (100.0%) *@Group 24 BazAlias (count=1) -28) 37495605 (100.0%) *@Group 58 blink::ContiguousContainerBase (count=4) -29) 37495608 (100.0%) *@Group 3 BarAlias (count=1) -30) 37495611 (100.0%) *@Group 3 FooAlias (count=1) -31) 37495705 (100.0%) *@Group 94 blink::PaintChunker (count=1) -32) 37499739 (100.0%) *@Group 4034 ** outlined function (count=1) -33) 37499763 (100.0%) *@Group 24 ** outlined function * 2 (count=1) -34) 37499787 (100.0%) *@Group 24 aliasedWithOutlinedFunction (count=1) -35) 37499787 (100.0%) *@Group 0 ff_cos_131072 (count=1) -36) 37499787 (100.0%) *@Group 0 ff_cos_131072_fixed (count=1) -37) 37499787 (100.0%) *@Group 0 ff_cos_65536 (count=1) -38) 37499787 (100.0%) *@Group 0 g_chrome_content_browser_client (count=1) -39) 37499787 (100.0%) *@Group 0 SaveHistogram (count=1) -40) 37499787 (100.0%) *@Group 0 g_AnimationFrameTimeHistogram_clazz (count=1) +10) 34774460 (92.7%) *@Group 5 "Str1" (count=2) +11) 34774476 (92.7%) *@Group 16 "String literal2" (count=1) +12) 34774519 (92.7%) *@Group 43 ** merge strings (count=1) +13) 36739864 (98.0%) *@Group 1965345 ** merge constants (count=1) +14) 36739867 (98.0%) *@Group 3 ** symbol gap 0 (count=1) +15) 36739875 (98.0%) *@Group 8 (count=1) +16) 36739919 (98.0%) *@Group 44 Name (count=1) +17) 36739951 (98.0%) *@Group 32 chrome::mojom::FilePatcher (count=1) +18) 37415991 (99.8%) *@Group 676040 kAnimationFrameTimeHistogramClassPath (count=1) +19) 37415995 (99.8%) *@Group 4 blink::CSSValueKeywordsHash::findValueImpl (count=1) +20) 37416011 (99.8%) *@Group 16 _GLOBAL__sub_I_page_allocator.cc (count=1) +21) 37416067 (99.8%) *@Group 56 _GLOBAL__sub_I_bbr_sender.cc (count=1) +22) 37416095 (99.8%) *@Group 28 _GLOBAL__sub_I_pacing_sender.cc (count=1) +23) 37416165 (99.8%) *@Group 70 extFromUUseMapping (count=2) +24) 37425923 (99.8%) *@Group 9758 ** symbol gaps (count=1) +25) 37426371 (99.8%) *@Group 448 ucnv_extMatchFromU (count=1) +26) 37426399 (99.8%) *@Group 28 _GLOBAL__sub_I_SkDeviceProfile.cpp (count=1) +27) 37495523 (100.0%) *@Group 69124 foo_bar (count=1) +28) 37495547 (100.0%) *@Group 24 BazAlias (count=1) +29) 37495605 (100.0%) *@Group 58 blink::ContiguousContainerBase (count=4) +30) 37495608 (100.0%) *@Group 3 BarAlias (count=1) +31) 37495611 (100.0%) *@Group 3 FooAlias (count=1) +32) 37495705 (100.0%) *@Group 94 blink::PaintChunker (count=1) +33) 37499739 (100.0%) *@Group 4034 ** outlined function (count=1) +34) 37499763 (100.0%) *@Group 24 ** outlined function * 2 (count=1) +35) 37499787 (100.0%) *@Group 24 aliasedWithOutlinedFunction (count=1) +36) 37499787 (100.0%) *@Group 0 ff_cos_131072 (count=1) +37) 37499787 (100.0%) *@Group 0 ff_cos_131072_fixed (count=1) +38) 37499787 (100.0%) *@Group 0 ff_cos_65536 (count=1) +39) 37499787 (100.0%) *@Group 0 g_chrome_content_browser_client (count=1) +40) 37499787 (100.0%) *@Group 0 SaveHistogram (count=1) +41) 37499787 (100.0%) *@Group 0 g_AnimationFrameTimeHistogram_clazz (count=1) GroupedByName(depth=1, min_count=2) -Showing 38 symbols (36 unique) with total pss: 37499787 bytes +Showing 39 symbols (37 unique) with total pss: 37499787 bytes Histogram of symbols based on PSS: [2,4): 3 [16,32): 9 [128,256): 3 [8192,16384): 1 [262144,524288): 1 [33554432,67108864): 1 - [4,8): 1 [32,64): 6 [256,512): 1 [65536,131072): 1 [524288,1048576): 2 + [4,8): 2 [32,64): 6 [256,512): 1 [65536,131072): 1 [524288,1048576): 2 [8,16): 4 [64,128): 1 [2048,4096): 1 [131072,262144): 2 [1048576,2097152): 1 Sizes: .text=81.8kb .rodata=2.52mb .data.rel.ro=92 bytes .data=168 bytes .bss=512kb .other=32.4mb total=35.8mb Counts: .text=21 .rodata=11 .data.rel.ro=3 .data=5 .bss=6 .other=1 @@ -195,58 +198,60 @@ kSystemClassPrefixes 9) 34774487 (92.7%) o@0x0 33984171 {no path} Overhead: ELF file -10) 34774508 (92.7%) *@Group 21 {no path} - string literal (count=3) -11) 34774551 (92.7%) r@0x266e630 43 {no path} +10) 34774492 (92.7%) *@Group 5 {no path} + "Str1" (count=2) +11) 34774508 (92.7%) r@0x266e605 16 $root_gen_dir/third_party/icu/ucnv_ext.c + "String literal2" +12) 34774551 (92.7%) r@0x266e630 43 {no path} ** merge strings -12) 36739896 (98.0%) r@0x284d600 1965345 {no path} +13) 36739896 (98.0%) r@0x284d600 1965345 {no path} ** merge constants -13) 36739899 (98.0%) r@0x284e364 3 {no path} +14) 36739899 (98.0%) r@0x284e364 3 {no path} ** symbol gap 0 -14) 36739907 (98.0%) r@0x284e364 8 base/page_allocator.cc -15) 36739951 (98.0%) r@0x284e370 44 base/page_allocator.cc +15) 36739907 (98.0%) r@0x284e364 8 base/page_allocator.cc +16) 36739951 (98.0%) r@0x284e370 44 base/page_allocator.cc Name -16) 37415991 (99.8%) r@0x28f3450 676040 third_party/paint.cc +17) 37415991 (99.8%) r@0x28f3450 676040 third_party/paint.cc kAnimationFrameTimeHistogramClassPath -17) 37416147 (99.8%) *@Group 156 {no path} +18) 37416147 (99.8%) *@Group 156 {no path} blink (count=6) -18) 37416163 (99.8%) t@0x28d900 16 base/page_allocator.cc +19) 37416163 (99.8%) t@0x28d900 16 base/page_allocator.cc _GLOBAL__sub_I_page_allocator.cc -19) 37416219 (99.8%) t@0x28d910 56 base/page_allocator.cc +20) 37416219 (99.8%) t@0x28d910 56 base/page_allocator.cc _GLOBAL__sub_I_bbr_sender.cc -20) 37416247 (99.8%) t@0x28d948 28 base/page_allocator.cc +21) 37416247 (99.8%) t@0x28d948 28 base/page_allocator.cc _GLOBAL__sub_I_pacing_sender.cc -21) 37416317 (99.8%) *@Group 70 base/page_allocator.cc +22) 37416317 (99.8%) *@Group 70 base/page_allocator.cc extFromUUseMapping (count=2) -22) 37426075 (99.8%) t@Group 9758 {no path} +23) 37426075 (99.8%) t@Group 9758 {no path} ** symbol gaps (count=2) -23) 37426523 (99.8%) t@0x28f000 448 $root_gen_dir/third_party/icu/ucnv_ext.c +24) 37426523 (99.8%) t@0x28f000 448 $root_gen_dir/third_party/icu/ucnv_ext.c ucnv_extMatchFromU -24) 37426551 (99.8%) t@0x28f1c8 28 $root_gen_dir/third_party/icu/ucnv_ext.c +25) 37426551 (99.8%) t@0x28f1c8 28 $root_gen_dir/third_party/icu/ucnv_ext.c _GLOBAL__sub_I_SkDeviceProfile.cpp -25) 37495675 (100.0%) t@0x28f1e0 69124 $root_gen_dir/third_party/icu/ucnv_ext.c +26) 37495675 (100.0%) t@0x28f1e0 69124 $root_gen_dir/third_party/icu/ucnv_ext.c foo_bar -26) 37495699 (100.0%) t@0x2a0000 24 (size=48) $root_gen_dir/third_party/icu/ucnv_ext.c +27) 37495699 (100.0%) t@0x2a0000 24 (size=48) $root_gen_dir/third_party/icu/ucnv_ext.c BazAlias (num_aliases=2) -27) 37495702 (100.0%) t@0x2a0010 3 (size=12) third_party/fft_float.cc +28) 37495702 (100.0%) t@0x2a0010 3 (size=12) third_party/fft_float.cc BarAlias (num_aliases=4) -28) 37495705 (100.0%) t@0x2a0010 3 (size=12) third_party/fft_float.cc +29) 37495705 (100.0%) t@0x2a0010 3 (size=12) third_party/fft_float.cc FooAlias (num_aliases=4) -29) 37499739 (100.0%) t@0x2a2000 4034 third_party/container/container.c +30) 37499739 (100.0%) t@0x2a2000 4034 third_party/container/container.c ** outlined function -30) 37499763 (100.0%) t@0x2a2020 24 (size=48) {no path} +31) 37499763 (100.0%) t@0x2a2020 24 (size=48) {no path} ** outlined function * 2 (num_aliases=2) -31) 37499787 (100.0%) t@0x2a2020 24 (size=48) {no path} +32) 37499787 (100.0%) t@0x2a2020 24 (size=48) {no path} aliasedWithOutlinedFunction (num_aliases=2) -32) 37499787 (100.0%) b@0x0 262144 third_party/fft_float.cc +33) 37499787 (100.0%) b@0x0 262144 third_party/fft_float.cc ff_cos_131072 -33) 37499787 (100.0%) b@0x0 131072 third_party/fft_fixed.cc +34) 37499787 (100.0%) b@0x0 131072 third_party/fft_fixed.cc ff_cos_131072_fixed -34) 37499787 (100.0%) b@0x0 131072 third_party/fft_float.cc +35) 37499787 (100.0%) b@0x0 131072 third_party/fft_float.cc ff_cos_65536 -35) 37499787 (100.0%) b@0x2dffda0 28 $root_gen_dir/third_party/icu/ucnv_ext.c +36) 37499787 (100.0%) b@0x2dffda0 28 $root_gen_dir/third_party/icu/ucnv_ext.c g_chrome_content_browser_client -36) 37499787 (100.0%) b@0x2dffe80 200 $root_gen_dir/third_party/icu/ucnv_ext.c +37) 37499787 (100.0%) b@0x2dffe80 200 $root_gen_dir/third_party/icu/ucnv_ext.c SaveHistogram::atomic_histogram_pointer -37) 37499787 (100.0%) b@0x2dffe84 4 $root_gen_dir/third_party/icu/ucnv_ext.c +38) 37499787 (100.0%) b@0x2dffe84 4 $root_gen_dir/third_party/icu/ucnv_ext.c g_AnimationFrameTimeHistogram_clazz
diff --git a/tools/binary_size/trybot_commit_size_checker.py b/tools/binary_size/trybot_commit_size_checker.py index a89dea8..0310b5f 100755 --- a/tools/binary_size/trybot_commit_size_checker.py +++ b/tools/binary_size/trybot_commit_size_checker.py
@@ -275,7 +275,7 @@ 'url': '{{' + _TEXT_FILENAME + '}}', }, { - 'name': '>>> Supersize HTML Diff <<<', + 'name': '>>> SuperSize HTML Diff <<<', 'url': _HTML_REPORT_BASE_URL + '{{' + _NDJSON_FILENAME + '}}', }, ] @@ -295,7 +295,7 @@ binary_size_extras = [ { - 'text': 'Supersize HTML Diff', + 'text': 'SuperSize HTML Diff', 'url': _HTML_REPORT_BASE_URL + '{{' + _NDJSON_FILENAME + '}}', }, {
diff --git a/tools/bisect_repackage/bisect_repackage.py b/tools/bisect_repackage/bisect_repackage.py index 76cd60a..9a8500a 100644 --- a/tools/bisect_repackage/bisect_repackage.py +++ b/tools/bisect_repackage/bisect_repackage.py
@@ -45,6 +45,7 @@ 'chrome_100_percent.pak', 'chrome_200_percent.pak', 'chromedriver', + 'crashpad_handler', 'default_apps/', 'icudtl.dat', 'ClearKeyCdm/', @@ -98,6 +99,7 @@ CHROME_STRIP_LIST = { 'linux': [ 'chrome', + 'crashpad_handler', 'nacl_helper' ] }
diff --git a/tools/git/OWNERS b/tools/git/OWNERS index e0511af8..734ea1a 100644 --- a/tools/git/OWNERS +++ b/tools/git/OWNERS
@@ -1 +1,2 @@ per-file move_source_file.py=satorux@chromium.org +per-file suggest_owners.py=mheikal@chromium.org
diff --git a/tools/git/suggest_owners.py b/tools/git/suggest_owners.py index 9fa3ed88..2ff0886 100755 --- a/tools/git/suggest_owners.py +++ b/tools/git/suggest_owners.py
@@ -5,6 +5,7 @@ import argparse import subprocess +import pickle import os from os import path from datetime import date, timedelta @@ -12,166 +13,340 @@ Commit = namedtuple('Commit', ['hash', 'author', 'commit_date', 'dirs']) -# Takes a git command arguments and runs it returning the output (throwing an -# exception on error). +# dict mapping each subdirectory and author to the number of their commits and +# modifications in that directory +DIRECTORY_AUTHORS = defaultdict(dict) + +# cache for directory owners for memoisation purposes +OWNERS_CACHE = {} + +# filename for pickle cache +CACHE_FILENAME = 'suggest_owners.cache' + def _RunGitCommand(options, cmd_args): - repo_path = os.path.join(options.repo_path, '.git') + repo_path = path.join(options.repo_path, '.git') cmd = ['git', '--git-dir', repo_path] + cmd_args + print '>', ' '.join(cmd) return subprocess.check_output(cmd) -# return true if this author is a chromium dev and is not a bot. Pretty naive, -# looks for roller in the username. -def _IsValidAuthor(author): +def _ValidAuthor(author): return author.find('@chromium.org') > -1 and author.find('roller') == -1 -# Get a list of commits from the repo and return a nested dictionary -# directory -> author -> num_commits -def processAllCommits(options): +# Returns additions/deletions by a commit to a directory (and its descendants). +def getEditsForDirectory(commit, directory): + additions = deletions = 0 + for commit_directory, (directory_additions, directory_deletions) \ + in commit.dirs.items(): + # check if commit_directory is same as or a descendant of directory + if isSubDirectory(directory, commit_directory): + additions += directory_additions + deletions += directory_deletions + return additions, deletions + + +# This propagates a commit touching a directory to also be touching all +# ancesstor directories. +def _PropagateCommit(options, commit): + touched_dirs = set() + # first get all the touched dirs and their ancestors + for directory in commit.dirs.iterkeys(): + while directory != '': + touched_dirs.add(directory) + # get the parent directory + directory = path.dirname(directory) + # loop over them and calculate the edits per directory + for directory in touched_dirs: + author_commits, author_additions, author_deletions = \ + DIRECTORY_AUTHORS[directory].get(commit.author, (0,0,0)) + directory_additions, directory_deletions = \ + getEditsForDirectory(commit, directory) + DIRECTORY_AUTHORS[directory][commit.author] = \ + (author_commits + 1, author_additions + directory_additions, + author_deletions + directory_deletions) + + +# Checks if child_directory is same as or below parent_directory. For some +# reason the os.path module does not have this functionality. +def isSubDirectory(parent_directory, child_directory): + parent_directory = parent_directory + '/' + child_directory = child_directory + '/' + return child_directory.startswith(parent_directory) + + +def _GetGitLogCmd(options): + # TODO(mheikal): git-log with --numstat vs --name-only takes 10x the time to + # complete. It takes >15 mins for git log --numstat to return the 1 year git + # history of the full repo. Should probably add a script flag to switch off + # keeping track of number of modifications per commit. date_limit = date.today() - timedelta(days=options.days_ago) format_string = "%h,%ae,%cI" cmd_args = [ 'log', '--since', date_limit.isoformat(), - '--name-only', + '--numstat', '--pretty=format:%s'%format_string, ] - # has to be last arg if options.subdirectory: cmd_args += ['--', options.subdirectory] + return cmd_args - output = _RunGitCommand(options, cmd_args) + +def _ParseCommitLine(line): + commit_hash, author, commit_date = line.split(",") + return Commit(hash=commit_hash, author=author, commit_date=commit_date, + dirs={}) + + +def _ParseFileStatsLine(current_commit, line): + try: + additions, deletions, filepath = line.split('\t') + except ValueError: + return False + if additions == '-': + additions = 0 + else: + additions = int(additions) + if deletions == '-': + deletions = 0 + else: + deletions = int(deletions) + dir_path = path.dirname(filepath) + commit_additions, commit_deletions = \ + current_commit.dirs.get(dir_path, (0,0)) + current_commit.dirs[dir_path] = ( + additions + commit_additions, deletions + commit_deletions) + return True + + +def processAllCommits(options): + if not options.subdirectory and options.days_ago > 100: + print ('git log for your query might take > 5 minutes, limit by a ' + 'subdirectory or reduce the number of days of history to low double ' + 'digits to make this faster. There is no progress indicator, it is ' + 'all waiting for single git log to finish.') + output = _RunGitCommand(options, _GetGitLogCmd(options)) current_commit = None - author = None - directory_authors = defaultdict(Counter) for line in output.splitlines(): if current_commit is None: - commit_hash, author, commit_date = line.split(",") - current_commit = Commit(hash=commit_hash, author=author, - commit_date=commit_date, dirs=set()) + current_commit = _ParseCommitLine(line) else: if line == '': # all commit details read - if _IsValidAuthor(current_commit.author): - for directory in current_commit.dirs: - if directory == '': - continue - directory_authors[directory][author] += 1 + if _ValidAuthor(current_commit.author): + _PropagateCommit(options, current_commit) current_commit = None else: - current_commit.dirs.add(os.path.dirname(line)) - return directory_authors + # Merge commits weird out git-log. If we fail to parse the line, then + # the last commit was a merge and this line is actually another commit + # description line. + if not _ParseFileStatsLine(current_commit, line): + current_commit = _ParseCommitLine(line) + # process the final commit + if _ValidAuthor(current_commit.author): + _PropagateCommit(options, current_commit) -# Return a list of owners for a given directory by reading OWNERS files in its -# ancestors. The parsing of OWNERS files is pretty naive, it does not handle -# file imports. -def _GetOwners(options, repo_subdir): - directory_path = os.path.join(options.repo_path, repo_subdir) - owners_path = os.path.join(directory_path, 'OWNERS') - owners = [] - while directory_path != '': - if os.path.isfile(owners_path): - with open(owners_path) as f: - owners.extend([line.strip() for line in f.readlines() if - line.find('@chromium.org') > -1]) - directory_path = path.dirname(directory_path) - owners_path = os.path.join(directory_path, 'OWNERS') +def _CountCommits(directory): + return sum( + [count for (count, _a, _d) in DIRECTORY_AUTHORS[directory].itervalues()]) + + +def _GetOwnerLevel(options, author, directory): + sorted_owners = sorted(_GetOwners(options, directory), key=lambda (o,l): l) + for owner, level in sorted_owners: + if author == owner: + return level + else: + return -1 + + +# Returns the owners for a repo subdirectory. This does not understand per-file +# directives. +# TODO(mheikal): use depot_tools owners.py for parsing owners files. +def _GetOwners(options, directory_path): + if directory_path in OWNERS_CACHE: + return OWNERS_CACHE[directory_path] + owners_path = path.join(options.repo_path, directory_path, 'OWNERS') + owners = set() + parent_dir = directory_path + owner_level = 0 + while parent_dir != '': + if path.isfile(owners_path): + parsed_owners, noparent = _ParseOwnersFile(options, owners_path) + owners.update([(owner, owner_level) for owner in parsed_owners]) + owner_level += 1 + if noparent: + break + parent_dir = path.dirname(parent_dir) + owners_path = path.join(parent_dir, 'OWNERS') + OWNERS_CACHE[directory_path] = set(owners) return owners -# Return the number of commits for a given directory -def _CountDirectoryCommits(directory_authors, directory): - return sum(directory_authors[directory].values()) +# Parse an OWNERS file, returns set of owners and if the file sets noparent +def _ParseOwnersFile(options, filepath): + owners = set() + noparent = False + with open(filepath) as f: + for line in f.readlines(): + line = line.strip() + # The script deals with directories so per-files are ignored. + if line == '' or line[0] == '#' or line.startswith('per-file'): + continue + if line.startswith('file://'): + relpath = line[7:] + abspath = path.join(options.repo_path, relpath) + parsed_owners, _ = _ParseOwnersFile(options, abspath) + owners.update(parsed_owners) + if line == 'set noparent': + noparent = True + index = line.find('@chromium.org') + if index > -1: + owners.add(line[:index + len('@chromium.org')]) + return owners, noparent -# Given a directory merge all its children's commits into its own, then delete -# each child subdirectory's entry if it has too few commits. -def _GroupToParentDirectory(options, directory_authors, parent): - global DIRECTORY_AUTHORS - parent_path = path.join(options.repo_path, parent) - - for entry in os.listdir(parent_path): - if path.isdir(os.path.join(parent_path, entry)): - entry_dir = path.join(parent, entry) - directory_authors[parent].update(directory_authors[entry_dir]) - commit_count = _CountDirectoryCommits(directory_authors, entry_dir) - if commit_count < options.dir_commit_limit: - directory_authors.pop(entry_dir) +# Trivial directories are ones that just contain a single child subdir and +# nothing else. +def _IsTrivialDirectory(options, repo_subdir): + try: + return len(os.listdir(path.join(options.repo_path, repo_subdir))) == 1 + except OSError: + # directory no longer exists + return False -# Merge directories with too few commits into their parent directory. This -# method changes the directory_authors dict in-place. -def mergeDirectories(options, directory_authors): - changed = False - for directory in directory_authors.keys(): - if not path.exists(path.join(options.repo_path, directory)): - del directory_authors[directory] +def computeSuggestions(options): + directory_suggestions = [] + for directory, authors in sorted( + DIRECTORY_AUTHORS.iteritems(), key=lambda (d, a): d): + if _IsTrivialDirectory(options, directory): continue - num_commits = _CountDirectoryCommits(directory_authors, directory) - if num_commits == 0: + if _CountCommits(directory) < options.dir_commit_limit: continue - elif num_commits < options.dir_commit_limit: - parent = os.path.dirname(directory) - _GroupToParentDirectory(options, directory_authors, parent) - changed = True - return changed - - -# Retrieves a set of authors that should not be suggested for a directory -def _GetIgnoredAuthors(options, repo_subdir): - if options.ignore_authors: - ignored_authors = set(map(str.strip, options.ignore_authors.split(','))) - else: - ignored_authors = set() - ignored_authors.update(_GetOwners(options, repo_subdir)) - return ignored_authors - - -# Prints out a list of suggested new owners for each directory with a high -# enough commit count. -def outputSuggestions(options, directory_authors): - for directory, authors in sorted(directory_authors.iteritems()): - commit_count = _CountDirectoryCommits(directory_authors, directory) - if commit_count < options.dir_commit_limit: + # skip suggestions for directories outside the passed in directory + if (options.subdirectory + and not isSubDirectory(options.subdirectory, directory)): continue - ignored_authors = _GetIgnoredAuthors(options, directory) - suggestions = [(a,c) for a,c in authors.most_common() - if a not in ignored_authors and c >= options.author_cl_limit] - print "%s: %d commits in the last %d days" % \ - (directory, commit_count, options.days_ago) - for author, commit_count in suggestions[:options.max_suggestions]: - print author, commit_count + # sort authors by descending number of commits + sorted_authors = sorted(authors.items(), + key=lambda (author, details): -details[0]) + # keep only authors above the limit + suggestions = [(a,c) for a,c in sorted_authors if \ + a not in options.ignore_authors \ + and c[0] >= options.author_cl_limit] + directory_suggestions.append((directory, suggestions)) + return directory_suggestions + + +def _PrintSettings(options): + print ('Showing directories with at least ({}) commits in the last ({}) ' + 'days.'.format(options.dir_commit_limit, options.days_ago)) + print ('Showing top ({}) committers who have commited at least ({}) commits ' + 'to the directory in the last ({}) days.'.format( + options.max_suggestions, options.author_cl_limit, + options.days_ago)) + print '(owners+N) represents distance through OWNERS files for said owner\n' + + +def printSuggestions(options, directory_suggestions): + print '\nCommit stats:' + _PrintSettings(options) + for directory, suggestions in directory_suggestions: + print '{}: {} commits in the last {} days'.format( + directory, _CountCommits(directory), options.days_ago) + non_owner_suggestions = 0 + for author, (commit_count, additions, deletions) in suggestions: + owner_level = _GetOwnerLevel(options, author, directory) + if owner_level > -1: + owner_string = ' (owner+{})'.format(owner_level) + else: + non_owner_suggestions +=1 + owner_string = '' + print '{}{}, commits: {}, additions:{}, deletions: {}'.format( + author, owner_string, commit_count, additions, deletions) + if non_owner_suggestions >= options.max_suggestions: + break print -# main 2.0 +def _GetHeadCommitHash(options): + return _RunGitCommand(options, ['rev-parse', 'HEAD']).strip() + + +def _GetCacheMetadata(options): + return _GetHeadCommitHash(options), options.days_ago, options.subdirectory + + +def _IsCacheValid(options, metadata): + head_hash, days_ago, cached_subdirectory = metadata + if head_hash != _GetHeadCommitHash(options): + return False + if days_ago != options.days_ago: + return False + if (cached_subdirectory is not None + and not isSubDirectory(cached_subdirectory, options.subdirectory)): + return False + return True + + +def cacheProcessedCommits(options): + metadata = _GetCacheMetadata(options) + with open(CACHE_FILENAME, 'w') as f: + pickle.dump((metadata, DIRECTORY_AUTHORS), f) + + +def maybeRestoreProcessedCommits(options): + global DIRECTORY_AUTHORS + if not path.exists(CACHE_FILENAME): + return False + with open(CACHE_FILENAME) as f: + stored_metadata, cached_directory_authors = pickle.load(f) + if _IsCacheValid(options, stored_metadata): + print 'Loading from cache' + DIRECTORY_AUTHORS = cached_directory_authors + return True + else: + print 'Cache is stale or invalid, must rerun `git log`' + return False + def do(options): - directory_authors = processAllCommits(options) - while mergeDirectories(options, directory_authors): - pass - outputSuggestions(options, directory_authors) + if options.skip_cache or not maybeRestoreProcessedCommits(options): + processAllCommits(options) + cacheProcessedCommits(options) + directory_suggestions = computeSuggestions(options) + printSuggestions(options, directory_suggestions) def main(): parser = argparse.ArgumentParser( formatter_class=argparse.ArgumentDefaultsHelpFormatter) parser.add_argument('repo_path') - parser.add_argument('--days-ago', help='Number of days of history to search' - ' through.', default=365) - parser.add_argument('--subdirectory', help='Limit to this subdirectory') - parser.add_argument('--ignore-authors', help='Ignore this comma separated' - ' list of authors') - parser.add_argument('--max-suggestions', help='Maximum number of suggested' - ' authors per directory.', default=5) - parser.add_argument('--author-cl-limit', help='Do not suggest authors who' - ' have commited less than this to the directory.', - default=10) - parser.add_argument('--dir-commit-limit', help='Merge directories with less' - ' than this number of commits into their parent' - ' directory.', default=100) + parser.add_argument('--days-ago', type=int, + help='Number of days of history to search through.', + default=365, metavar='DAYS_AGO') + parser.add_argument('--subdirectory', + help='Limit suggestions to this subdirectory', default='') + parser.add_argument('--ignore-authors', + help='Ignore this comma separated list of authors') + parser.add_argument('--max-suggestions', type=int, help='Maximum number of ' + 'suggested authors per directory.', default=5) + parser.add_argument('--author-cl-limit', type=int, help='Do not suggest ' + 'authors who have commited less than this to the ' + 'directory in the last DAYS_AGO days.', default=10) + parser.add_argument('--dir-commit-limit', type=int, help='Skip directories ' + 'with less than this number of commits in the last ' + 'DAYS_AGO days.', default=100) + parser.add_argument('--skip-cache', action='store_true', + help='Do not read from cache.', default=False) options = parser.parse_args() + if options.ignore_authors: + options.ignore_authors = set( + map(str.strip, options.ignore_authors.split(','))) + else: + options.ignore_authors = set() do(options)
diff --git a/tools/metrics/histograms/enums.xml b/tools/metrics/histograms/enums.xml index 05d1f9c..aa0a8ad 100644 --- a/tools/metrics/histograms/enums.xml +++ b/tools/metrics/histograms/enums.xml
@@ -5904,6 +5904,11 @@ <int value="1" label="Completed"/> </enum> +<enum name="BooleanCompositorCSSPaint"> + <int value="0" label="A CSS Paint is fall back on the main thread"/> + <int value="1" label="A CSS Paint is painted on the compositor thread"/> +</enum> + <enum name="BooleanConfirmed"> <int value="0" label="Not Confirmed"/> <int value="1" label="Confirmed"/> @@ -20653,6 +20658,7 @@ <int value="1381" label="AUTOTESTPRIVATE_GETARCSTARTTIME"/> <int value="1382" label="AUTOTESTPRIVATE_SETOVERVIEWMODESTATE"/> <int value="1383" label="AUTOTESTPRIVATE_TAKESCREENSHOTFORDISPLAY"/> + <int value="1384" label="AUTOFILLPRIVATE_SETCREDITCARDFIDOAUTHENABLEDSTATE"/> </enum> <enum name="ExtensionIconState"> @@ -34829,6 +34835,7 @@ <int value="-2020721975" label="smart-virtual-keyboard"/> <int value="-2020024440" label="scroll-end-effect"/> <int value="-2017953534" label="enable-hosted-app-shim-creation"/> + <int value="-2015293660" label="AccessibilityExposeDisplayNone:disabled"/> <int value="-2013551096" label="ViewsSimplifiedFullscreenUI:disabled"/> <int value="-2013124655" label="EnableEphemeralFlashPermission:disabled"/> <int value="-2012990889" label="SpannableInlineAutocomplete:enabled"/> @@ -34951,6 +34958,7 @@ label="enable-zero-suggest-most-visited-without-serp"/> <int value="-1886713568" label="AutofillGetPaymentsIdentityFromSync:disabled"/> + <int value="-1885074774" label="ShelfScrollable:enabled"/> <int value="-1883170077" label="EnableHtmlBaseUsernameDetector:disabled"/> <int value="-1882330924" label="NTPArticleSuggestions:enabled"/> <int value="-1881250251" label="InterestFeedContentSuggestions:disabled"/> @@ -35100,7 +35108,6 @@ <int value="-1684773837" label="TabEngagementReportingAndroid:disabled"/> <int value="-1684123448" label="disable-best-effort-tasks"/> <int value="-1682843294" label="DataReductionProxyDecidesTransform:enabled"/> - <int value="-1681832882" label="shelf-scrollable"/> <int value="-1679624666" label="NtpRealbox:enabled"/> <int value="-1677715989" label="UnifiedConsent:disabled"/> <int value="-1676256979" @@ -35560,6 +35567,7 @@ <int value="-1118921985" label="ForceEnableSystemAec:enabled"/> <int value="-1114080030" label="ResourceLoadingHints:enabled"/> <int value="-1112782121" label="AndroidSigninPromos:disabled"/> + <int value="-1109826787" label="AccessibilityExposeDisplayNone:enabled"/> <int value="-1107762575" label="enable-data-reduction-proxy-config-client"/> <int value="-1107103335" label="FsNosymfollow:enabled"/> <int value="-1105637876" label="FilteringScrollPrediction:enabled"/> @@ -35596,6 +35604,7 @@ <int value="-1074257709" label="ScalableAppList:enabled"/> <int value="-1074107607" label="data-reduction-proxy-experiment"/> <int value="-1073479583" label="ShowArcFilesApp:disabled"/> + <int value="-1069628248" label="OmniboxZeroSuggestionsOnSERP:enabled"/> <int value="-1069453905" label="CCTModuleUseIntentExtras:disabled"/> <int value="-1067635248" label="SpeculativeResourcePrefetching:disabled"/> <int value="-1064733740" label="ui-show-composited-layer-borders"/> @@ -35814,6 +35823,7 @@ <int value="-787969387" label="HTTPSServerPreviewsUsingURLLoader:enabled"/> <int value="-787876637" label="HomeLauncherGestures:enabled"/> <int value="-787426248" label="ChromeHomeSurvey:disabled"/> + <int value="-787238455" label="OmniboxZeroSuggestionsOnSERP:disabled"/> <int value="-780798969" label="disable-single-click-autofill"/> <int value="-778126349" label="DownloadsLocationChange:enabled"/> <int value="-777126951" label="FontSrcLocalMatching:enabled"/> @@ -36554,6 +36564,7 @@ <int value="223591010" label="CastMediaRouteProvider:enabled"/> <int value="223662457" label="BackgroundLoadingForDownloads:enabled"/> <int value="229476202" label="CryptAuthV2Enrollment:enabled"/> + <int value="229877058" label="ShelfScrollable:disabled"/> <int value="233721248" label="DownloadRename:disabled"/> <int value="237570976" label="CommandLineOnNonRooted:disabled"/> <int value="237964589"
diff --git a/tools/metrics/histograms/histograms.xml b/tools/metrics/histograms/histograms.xml index 0ad0b7e..355f8ac 100644 --- a/tools/metrics/histograms/histograms.xml +++ b/tools/metrics/histograms/histograms.xml
@@ -14523,6 +14523,16 @@ </summary> </histogram> +<histogram name="Blink.CSSPaintValue.PaintOffThread" + enum="BooleanCompositorCSSPaint" expires_after="2021-09-08"> + <owner>xidachen@chromium.org</owner> + <owner>smcgruer@chromium.org</owner> + <summary> + Records if a CSS Paint is painted on the compositor thread or has fallen + back to the main thread. + </summary> +</histogram> + <histogram name="Blink.DecodedImage.CanvasExpanded" enum="BooleanCanvasExpanded" expires_after="2016-11-30"> <obsolete> @@ -62251,6 +62261,17 @@ </summary> </histogram> +<histogram name="Media.MCVD.ForwardVideoFrameTiming" units="ms" + expires_after="2019-12-31"> + <owner>liberato@chromium.org</owner> + <owner>sandersd@chromium.org</owner> + <owner>tguilbert@chromium.org</owner> + <summary> + The time between MediaCodec::dequeueOutputBuffer() and the dispatch of the + corresponding VideoFrame from MediaCodecVideoDecoder. + </summary> +</histogram> + <histogram name="Media.MeanTimeBetweenRebuffers" units="ms" expires_after="2020-02-02"> <owner>dalecurtis@chromium.org</owner> @@ -71415,6 +71436,17 @@ </summary> </histogram> +<histogram name="Navigation.IsLockedProcess.HTTPOrHTTPS" + enum="NavigationIsLockedProcess" expires_after="2020-12-31"> + <owner>alexmos@chromium.org</owner> + <owner>lukasza@chromium.org</owner> + <summary> + Whether the navigation commits in a process that is locked to an origin. + Logged at ready-to-commit time for every navigation that commits with a HTTP + or HTTPS URL scheme, excluding same-document navigations and errors. + </summary> +</histogram> + <histogram name="Navigation.IsMobileOptimized" enum="BooleanIsMobileOptimized" expires_after="2018-03-05"> <obsolete> @@ -71687,6 +71719,18 @@ </summary> </histogram> +<histogram name="Navigation.RequiresDedicatedProcess.HTTPOrHTTPS" + enum="NavigationRequiresDedicatedProcess" expires_after="2020-12-31"> + <owner>alexmos@chromium.org</owner> + <owner>lukasza@chromium.org</owner> + <summary> + Whether the navigation commits in a SiteInstance that requires a dedicated + process. Logged at ready-to-commit time for every navigation that commits + with a HTTP or HTTPS URL scheme, excluding same-document navigations and + errors. + </summary> +</histogram> + <histogram name="Navigation.ResourceHandler.ProceedWithResponseUntilFirstReadCompleted" units="ms"> @@ -71719,6 +71763,9 @@ <histogram name="Navigation.SandboxFrameBackForwardStaysWithinSubtree" enum="BooleanWithinSubtree" expires_after="M78"> + <obsolete> + Removed as of 09/2019. + </obsolete> <owner>creis@chromium.org</owner> <owner>dtapuska@chromium.org</owner> <summary> @@ -77920,6 +77967,9 @@ </histogram> <histogram name="Net.PreconnectSkippedToProxyServers" units="count"> + <obsolete> + Deprecated September 2019 + </obsolete> <owner>tbansal@chromium.org</owner> <summary> Indicates number of times a preconnect to proxy server was skipped due to an @@ -89578,6 +89628,16 @@ </summary> </histogram> +<histogram name="Notifications.Triggers.DisplayDelay" units="ms" + expires_after="M82"> + <owner>knollr@chromium.org</owner> + <owner>peter@chromium.org</owner> + <summary> + Delay between the expected and actual display time of a notification. + Recorded just before displaying a notification with a show trigger. + </summary> +</histogram> + <histogram name="Notifications.Triggers.HasShowTrigger" enum="Boolean" expires_after="M80"> <owner>knollr@chromium.org</owner> @@ -162629,6 +162689,7 @@ <suffix name="ar" label="Augmented Reality Module"/> <suffix name="autofill_assistant" label="Assistant-in-Chrome Module"/> <suffix name="dev_ui" label="Developer UI Module"/> + <suffix name="extra_icu" label="Extra ICU Module"/> <suffix name="tab_ui" label="Tab Management Module"/> <suffix name="test_dummy" label="Test Dummy Module"/> <suffix name="vr" label="Virtual Reality Module"/>
diff --git a/tools/metrics/ukm/ukm.xml b/tools/metrics/ukm/ukm.xml index 3743330c..98fdcd8 100644 --- a/tools/metrics/ukm/ukm.xml +++ b/tools/metrics/ukm/ukm.xml
@@ -4910,7 +4910,7 @@ </event> <event name="NavigationPredictorAnchorElementMetrics"> - <owner>ryansturm@chromium.com</owner> + <owner>ryansturm@chromium.org</owner> <summary> Metrics that describe an anchor element's data. This event is emitted at most 10 times per page load, once for each of the top n URLs on a page, and @@ -4961,6 +4961,7 @@ </event> <event name="NavigationPredictorPageLinkClick"> + <owner>ryansturm@chromium.org</owner> <summary> Sent on an in-page link click. An integer from 0-10 (1-indexed), corresponding to the index of that anchor element in the list of top ten @@ -4971,7 +4972,7 @@ </event> <event name="NavigationPredictorPageLinkMetrics" singular="True"> - <owner>ryansturm@chromium.com</owner> + <owner>ryansturm@chromium.org</owner> <summary> Metrics that describe aggregate information about the links within a page. Some anchor elements present on a page may not be represented in these
diff --git a/tools/perf/benchmarks/system_health_smoke_test.py b/tools/perf/benchmarks/system_health_smoke_test.py index bb87abc..21d8839 100644 --- a/tools/perf/benchmarks/system_health_smoke_test.py +++ b/tools/perf/benchmarks/system_health_smoke_test.py
@@ -44,6 +44,7 @@ 'system_health.memory_mobile/browse:social:tumblr_infinite_scroll', 'system_health.memory_mobile/browse:tools:maps', 'system_health.memory_mobile/browse:news:cnn', + 'system_health.memory_mobile/load:media:facebook_photos', 'system_health.memory_mobile/load:news:cnn', 'system_health.memory_mobile/load:tools:stackoverflow', 'system_health.memory_desktop/load_accessibility:shopping:amazon',
diff --git a/tools/perf/chrome_telemetry_build/BUILD.gn b/tools/perf/chrome_telemetry_build/BUILD.gn index a95b547..bb36f70 100644 --- a/tools/perf/chrome_telemetry_build/BUILD.gn +++ b/tools/perf/chrome_telemetry_build/BUILD.gn
@@ -82,6 +82,12 @@ data_deps = [ "//third_party/catapult:telemetry_chrome_test_support", ] + if (is_chromeos) { + data_deps += [ + "//third_party/breakpad:minidump_stackwalk", + "//third_party/breakpad:dump_syms", + ] + } if (is_android) { data += [ "//build/android/stacktrace/",
diff --git a/tools/perf/core/minidump_unittest.py b/tools/perf/core/minidump_unittest.py index 6b236224..04d5f03 100644 --- a/tools/perf/core/minidump_unittest.py +++ b/tools/perf/core/minidump_unittest.py
@@ -16,7 +16,7 @@ @decorators.Isolated # ChromeOS and Android are currently hard coded to return None for minidump # paths, so disable on those platforms. - @decorators.Disabled('chromeos', 'android') + @decorators.Disabled('android') def testSymbolizeMinidump(self): # Wait for the browser to restart fully before crashing self._LoadPageThenWait('var sam = "car";', 'sam') @@ -88,7 +88,7 @@ self.assertTrue(crash_function in sections[4]) @decorators.Isolated - @decorators.Disabled('chromeos', 'android') + @decorators.Disabled('android') def testMultipleCrashMinidumps(self): # Wait for the browser to restart fully before crashing self._LoadPageThenWait('var cat = "dog";', 'cat')
diff --git a/tools/perf/page_sets/data/system_health_mobile.json b/tools/perf/page_sets/data/system_health_mobile.json index 4c8fb26..6c471ac6 100644 --- a/tools/perf/page_sets/data/system_health_mobile.json +++ b/tools/perf/page_sets/data/system_health_mobile.json
@@ -144,6 +144,9 @@ "load:media:facebook_photos": { "DEFAULT": "system_health_mobile_040.wprgo" }, + "load:media:facebook_photos:2019": { + "DEFAULT": "system_health_mobile_6fb624f9e6.wprgo" + }, "load:media:flickr": { "DEFAULT": "system_health_mobile_003.wprgo" }, @@ -255,6 +258,9 @@ "load:social:instagram": { "DEFAULT": "system_health_mobile_001.wprgo" }, + "load:social:instagram:2019": { + "DEFAULT": "system_health_mobile_71bac3270a.wprgo" + }, "load:social:pinterest": { "DEFAULT": "system_health_mobile_001.wprgo" },
diff --git a/tools/perf/page_sets/data/system_health_mobile_6fb624f9e6.wprgo.sha1 b/tools/perf/page_sets/data/system_health_mobile_6fb624f9e6.wprgo.sha1 new file mode 100644 index 0000000..17df97c --- /dev/null +++ b/tools/perf/page_sets/data/system_health_mobile_6fb624f9e6.wprgo.sha1
@@ -0,0 +1 @@ +6fb624f9e6ceef74d330750d57a078c9058d37b6 \ No newline at end of file
diff --git a/tools/perf/page_sets/data/system_health_mobile_71bac3270a.wprgo.sha1 b/tools/perf/page_sets/data/system_health_mobile_71bac3270a.wprgo.sha1 new file mode 100644 index 0000000..a31b424c --- /dev/null +++ b/tools/perf/page_sets/data/system_health_mobile_71bac3270a.wprgo.sha1
@@ -0,0 +1 @@ +71bac3270a61abec13028982d17b228db59b9d4b \ No newline at end of file
diff --git a/tools/perf/page_sets/system_health/loading_stories.py b/tools/perf/page_sets/system_health/loading_stories.py index ec5e6f1..a4a2e2b 100644 --- a/tools/perf/page_sets/system_health/loading_stories.py +++ b/tools/perf/page_sets/system_health/loading_stories.py
@@ -134,6 +134,11 @@ TAGS = [story_tags.YEAR_2018] SUPPORTED_PLATFORMS = platforms.DESKTOP_ONLY +class LoadInstagramMobileStory2019(_LoadingStory): + NAME = 'load:social:instagram:2019' + URL = 'https://www.instagram.com/selenagomez/' + TAGS = [story_tags.YEAR_2019] + SUPPORTED_PLATFORMS = platforms.MOBILE_ONLY class LoadPinterestStory(_LoadingStory): NAME = 'load:social:pinterest' @@ -313,6 +318,14 @@ SUPPORTED_PLATFORMS = platforms.MOBILE_ONLY TAGS = [story_tags.EMERGING_MARKET, story_tags.YEAR_2016] +class LoadFacebookPhotosMobileStory2019(_LoadingStory): + """Load a page of rihanna's facebook with a photo.""" + NAME = 'load:media:facebook_photos:2019' + URL = ( + 'https://m.facebook.com/rihanna/photos/a.207477806675/10156574885461676/?type=3&source=54&ref=page_internal') + SUPPORTED_PLATFORMS = platforms.MOBILE_ONLY + TAGS = [story_tags.EMERGING_MARKET, story_tags.YEAR_2019] + class LoadFacebookPhotosDesktopStory2018(_LoadingStory): """Load a page of rihanna's facebook with a photo."""
diff --git a/tools/polymer/polymer.py b/tools/polymer/polymer.py index d6b8ea1..ef9a2b73 100644 --- a/tools/polymer/polymer.py +++ b/tools/polymer/polymer.py
@@ -304,7 +304,7 @@ IIFE_CLOSING = '})();' # Remove this line. - CR_DEFINE_START_REGEX = 'cr.define\(' + CR_DEFINE_START_REGEX = r'cr.define\(' # Ignore all lines after this comment, including the line it appears on. CR_DEFINE_END_REGEX = r'\s*// #cr_define_end'
diff --git a/tools/traffic_annotation/bin/README.md b/tools/traffic_annotation/bin/README.md index a1cdde4..414b178 100644 --- a/tools/traffic_annotation/bin/README.md +++ b/tools/traffic_annotation/bin/README.md
@@ -10,7 +10,7 @@ ```bash git new-branch roll_traffic_annotation_tools python tools/clang/scripts/build.py --bootstrap \ - --without-android --extra-tools traffic_annotation_extractor + --without-android --without-fuchsia --extra-tools traffic_annotation_extractor cp third_party/llvm-build/Release+Asserts/bin/traffic_annotation_extractor \ tools/traffic_annotation/bin/linux64/
diff --git a/ui/accessibility/BUILD.gn b/ui/accessibility/BUILD.gn index 239d3d48f..1fd66cdb 100644 --- a/ui/accessibility/BUILD.gn +++ b/ui/accessibility/BUILD.gn
@@ -33,6 +33,8 @@ jumbo_component("accessibility") { sources = [ + "accessibility_features.cc", + "accessibility_features.h", "accessibility_switches.cc", "accessibility_switches.h", "ax_action_data.cc",
diff --git a/ui/accessibility/accessibility_features.cc b/ui/accessibility/accessibility_features.cc new file mode 100644 index 0000000..97eee4d --- /dev/null +++ b/ui/accessibility/accessibility_features.cc
@@ -0,0 +1,21 @@ +// Copyright (c) 2019 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#include "ui/accessibility/accessibility_features.h" + +#include "base/feature_list.h" +#include "build/build_config.h" + +namespace features { + +// Enable exposing "display: none" nodes to the browser process AXTree +const base::Feature kEnableAccessibilityExposeDisplayNone{ + "AccessibilityExposeDisplayNone", base::FEATURE_DISABLED_BY_DEFAULT}; + +bool IsAccessibilityExposeDisplayNoneEnabled() { + return base::FeatureList::IsEnabled( + ::features::kEnableAccessibilityExposeDisplayNone); +} + +} // namespace features
diff --git a/ui/accessibility/accessibility_features.h b/ui/accessibility/accessibility_features.h new file mode 100644 index 0000000..c2f5d55f --- /dev/null +++ b/ui/accessibility/accessibility_features.h
@@ -0,0 +1,23 @@ +// Copyright (c) 2019 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +// Define all the base::Features used by ui/accessibility. +#ifndef UI_ACCESSIBILITY_ACCESSIBILITY_FEATURES_H_ +#define UI_ACCESSIBILITY_ACCESSIBILITY_FEATURES_H_ + +#include "base/feature_list.h" +#include "build/build_config.h" +#include "ui/accessibility/ax_export.h" + +namespace features { + +AX_EXPORT extern const base::Feature kEnableAccessibilityExposeDisplayNone; + +// Returns true if "display: none" nodes should be exposed to the +// browser process AXTree. +AX_EXPORT bool IsAccessibilityExposeDisplayNoneEnabled(); + +} // namespace features + +#endif // UI_ACCESSIBILITY_ACCESSIBILITY_FEATURES_H_
diff --git a/ui/accessibility/ax_node_position.cc b/ui/accessibility/ax_node_position.cc index f448bf46..fd49d91 100644 --- a/ui/accessibility/ax_node_position.cc +++ b/ui/accessibility/ax_node_position.cc
@@ -5,6 +5,7 @@ #include "ui/accessibility/ax_node_position.h" #include "base/strings/string_util.h" +#include "ui/accessibility/accessibility_features.h" #include "ui/accessibility/ax_enums.mojom.h" #include "ui/accessibility/ax_tree_manager_map.h" @@ -92,32 +93,24 @@ if (!IsLeafTextPosition()) return AsLeafTextPosition()->AsUnignoredTextPosition(adjustment_behavior); - if (!GetAnchor()->IsIgnored()) - return Clone(); + AXPositionInstance unignored_position = + CreateUnignoredPositionFromLeafTextPosition(adjustment_behavior); - // Find the next/previous node that is not ignored. - AXNode* unignored_node = GetAnchor(); - while (unignored_node) { - switch (adjustment_behavior) { - case AdjustmentBehavior::kMoveRight: - unignored_node = unignored_node->GetNextUnignoredInTreeOrder(); - break; - case AdjustmentBehavior::kMoveLeft: - unignored_node = unignored_node->GetPreviousUnignoredInTreeOrder(); - } - if (unignored_node && unignored_node->IsText()) { - switch (adjustment_behavior) { - case AdjustmentBehavior::kMoveRight: - return CreateTextPosition(tree_id(), unignored_node->id(), 0, - ax::mojom::TextAffinity::kDownstream); - case AdjustmentBehavior::kMoveLeft: - return CreateTextPosition(tree_id(), unignored_node->id(), 0, - ax::mojom::TextAffinity::kDownstream) - ->CreatePositionAtEndOfAnchor(); - } + // If creating an unignored position using |adjustment_behavior| returns a + // null position, the position may be at the start or end of a document. + // For this case attempt to adjust using the opposite AdjustmentBehavior. + if (features::IsAccessibilityExposeDisplayNoneEnabled()) { + if (unignored_position->IsNullPosition()) { + const AdjustmentBehavior opposite_adjustment = + (adjustment_behavior == AdjustmentBehavior::kMoveRight) + ? AdjustmentBehavior::kMoveLeft + : AdjustmentBehavior::kMoveRight; + unignored_position = + CreateUnignoredPositionFromLeafTextPosition(opposite_adjustment); } } - return CreateNullPosition(); + + return unignored_position; } int AXNodePosition::MaxTextOffset() const { @@ -372,4 +365,37 @@ return parent; } +AXNodePosition::AXPositionInstance +AXNodePosition::CreateUnignoredPositionFromLeafTextPosition( + AdjustmentBehavior adjustment_behavior) const { + DCHECK(IsLeafTextPosition()); + + AXNode* unignored_node = GetAnchor(); + if (!unignored_node->IsIgnored()) + return Clone(); + + // Find the next/previous node that is not ignored. + while (unignored_node) { + switch (adjustment_behavior) { + case AdjustmentBehavior::kMoveRight: + unignored_node = unignored_node->GetNextUnignoredInTreeOrder(); + break; + case AdjustmentBehavior::kMoveLeft: + unignored_node = unignored_node->GetPreviousUnignoredInTreeOrder(); + } + if (unignored_node && unignored_node->IsText()) { + switch (adjustment_behavior) { + case AdjustmentBehavior::kMoveRight: + return CreateTextPosition(tree_id(), unignored_node->id(), 0, + ax::mojom::TextAffinity::kDownstream); + case AdjustmentBehavior::kMoveLeft: + return CreateTextPosition(tree_id(), unignored_node->id(), 0, + ax::mojom::TextAffinity::kDownstream) + ->CreatePositionAtEndOfAnchor(); + } + } + } + return CreateNullPosition(); +} + } // namespace ui
diff --git a/ui/accessibility/ax_node_position.h b/ui/accessibility/ax_node_position.h index 4da2880..16b9cf4 100644 --- a/ui/accessibility/ax_node_position.h +++ b/ui/accessibility/ax_node_position.h
@@ -73,6 +73,9 @@ AXTreeID child_tree_id, AXTreeID* parent_tree_id, int32_t* parent_id); + + AXPositionInstance CreateUnignoredPositionFromLeafTextPosition( + AdjustmentBehavior adjustment_behavior) const; }; } // namespace ui
diff --git a/ui/accessibility/platform/ax_platform_node_textrangeprovider_win.cc b/ui/accessibility/platform/ax_platform_node_textrangeprovider_win.cc index 89bfc03..84ce65f 100644 --- a/ui/accessibility/platform/ax_platform_node_textrangeprovider_win.cc +++ b/ui/accessibility/platform/ax_platform_node_textrangeprovider_win.cc
@@ -177,8 +177,8 @@ case TextUnit_Page: { // If the document doesn't support pagination, default to document units // per UIA spec - AXPositionInstance common_ancestor = start_->LowestCommonAncestor(*end_); - if (common_ancestor->GetAnchor()->tree()->HasPaginationSupport()) { + const AXNode* common_anchor = start_->LowestCommonAnchor(*end_); + if (common_anchor->tree()->HasPaginationSupport()) { start_ = start_->CreatePreviousPageStartPosition( ui::AXBoundaryBehavior::StopIfAlreadyAtBoundary); end_ = start_->CreateNextPageEndPosition( @@ -765,13 +765,10 @@ std::vector<gfx::NativeViewAccessible> descendants; - AXPositionInstance common_ancestor = - start_->LowestCommonAncestor(*end_.get()); - - AXPlatformNodeDelegate* delegate = - GetDelegate(common_ancestor.get()) - ->GetFromNodeID(common_ancestor->anchor_id()) - ->GetDelegate(); + const AXNode* common_anchor = start_->LowestCommonAnchor(*end_); + const AXTreeID tree_id = common_anchor->tree()->GetAXTreeID(); + const AXNode::AXID node_id = common_anchor->id(); + AXPlatformNodeDelegate* delegate = GetDelegate(tree_id, node_id); DCHECK(delegate); while (ui::IsIgnored(delegate->GetData())) { auto* node = static_cast<AXPlatformNodeWin*>(
diff --git a/ui/base/models/button_menu_item_model.cc b/ui/base/models/button_menu_item_model.cc index 3e629cd..cfa584fa 100644 --- a/ui/base/models/button_menu_item_model.cc +++ b/ui/base/models/button_menu_item_model.cc
@@ -37,7 +37,6 @@ int command_id; ButtonType type; base::string16 label; - int icon_idr; bool part_of_group; }; @@ -53,25 +52,24 @@ void ButtonMenuItemModel::AddGroupItemWithStringId( int command_id, int string_id) { - Item item = { command_id, TYPE_BUTTON, l10n_util::GetStringUTF16(string_id), - -1, true }; + Item item = {command_id, TYPE_BUTTON, l10n_util::GetStringUTF16(string_id), + true}; items_.push_back(item); } -void ButtonMenuItemModel::AddItemWithImage(int command_id, - int icon_idr) { - Item item = { command_id, TYPE_BUTTON, base::string16(), icon_idr, false }; +void ButtonMenuItemModel::AddImageItem(int command_id) { + Item item = {command_id, TYPE_BUTTON, base::string16(), false}; items_.push_back(item); } void ButtonMenuItemModel::AddButtonLabel(int command_id, int string_id) { - Item item = { command_id, TYPE_BUTTON_LABEL, - l10n_util::GetStringUTF16(string_id), -1, false }; + Item item = {command_id, TYPE_BUTTON_LABEL, + l10n_util::GetStringUTF16(string_id), false}; items_.push_back(item); } void ButtonMenuItemModel::AddSpace() { - Item item = { 0, TYPE_SPACE, base::string16(), -1, false }; + Item item = {0, TYPE_SPACE, base::string16(), false}; items_.push_back(item); } @@ -109,14 +107,6 @@ return items_[index].label; } -bool ButtonMenuItemModel::GetIconAt(int index, int* icon_idr) const { - if (items_[index].icon_idr == -1) - return false; - - *icon_idr = items_[index].icon_idr; - return true; -} - bool ButtonMenuItemModel::PartOfGroup(int index) const { return items_[index].part_of_group; }
diff --git a/ui/base/models/button_menu_item_model.h b/ui/base/models/button_menu_item_model.h index 22595e6..eabf456 100644 --- a/ui/base/models/button_menu_item_model.h +++ b/ui/base/models/button_menu_item_model.h
@@ -54,8 +54,11 @@ // this method will have the same size, based on the largest button. void AddGroupItemWithStringId(int command_id, int string_id); - // Adds a button that has an icon instead of a label. - void AddItemWithImage(int command_id, int icon_idr); + // Adds a button that has an icon instead of a label. Note that the image + // itself must be separately configured by platform-specific code; this method + // simply serves to add a blank item in the menu with a specified + // |command_id|. + void AddImageItem(int command_id); // Adds a non-clickable button with a desensitized label that doesn't do // anything. Usually combined with IsItemForCommandIdDynamic() to add @@ -84,10 +87,6 @@ // Returns the current label value for the button at |index|. base::string16 GetLabelAt(int index) const; - // If the button at |index| should have an icon instead, returns true and - // sets the IDR |icon|. - bool GetIconAt(int index, int* icon) const; - // If the button at |index| should have its size equalized along with all // other items that have their PartOfGroup bit set. bool PartOfGroup(int index) const;
diff --git a/ui/base/ui_base_features.cc b/ui/base/ui_base_features.cc index a2e985a..ae43e08 100644 --- a/ui/base/ui_base_features.cc +++ b/ui/base/ui_base_features.cc
@@ -13,7 +13,7 @@ #if defined(OS_WIN) // If enabled, calculate native window occlusion - Windows-only. const base::Feature kCalculateNativeWinOcclusion{ - "CalculateNativeWinOcclusion", base::FEATURE_DISABLED_BY_DEFAULT}; + "CalculateNativeWinOcclusion", base::FEATURE_ENABLED_BY_DEFAULT}; #endif // OW_WIN #if defined(OS_CHROMEOS) @@ -127,6 +127,10 @@ const base::Feature kFormControlsRefresh = {"FormControlsRefresh", base::FEATURE_DISABLED_BY_DEFAULT}; +// Enable WebUI accessibility enhancements for review and testing. +const base::Feature kWebUIA11yEnhancements{"WebUIA11yEnhancements", + base::FEATURE_DISABLED_BY_DEFAULT}; + bool IsFormControlsRefreshEnabled() { return base::FeatureList::IsEnabled(features::kFormControlsRefresh); }
diff --git a/ui/base/ui_base_features.h b/ui/base/ui_base_features.h index 8fa392e..e571ffc 100644 --- a/ui/base/ui_base_features.h +++ b/ui/base/ui_base_features.h
@@ -87,6 +87,9 @@ COMPONENT_EXPORT(UI_BASE_FEATURES) extern const base::Feature kHandwritingGesture; #endif + +COMPONENT_EXPORT(UI_BASE_FEATURES) +extern const base::Feature kWebUIA11yEnhancements; } // namespace features #endif // UI_BASE_UI_BASE_FEATURES_H_
diff --git a/ui/base/webui/web_ui_util.cc b/ui/base/webui/web_ui_util.cc index 29ad19d..09a164647 100644 --- a/ui/base/webui/web_ui_util.cc +++ b/ui/base/webui/web_ui_util.cc
@@ -7,6 +7,7 @@ #include <vector> #include "base/base64.h" +#include "base/feature_list.h" #include "base/i18n/rtl.h" #include "base/logging.h" #include "base/memory/ref_counted_memory.h" @@ -19,6 +20,7 @@ #include "ui/base/l10n/l10n_util.h" #include "ui/base/resource/resource_bundle.h" #include "ui/base/template_expressions.h" +#include "ui/base/ui_base_features.h" #include "ui/base/window_open_disposition.h" #include "ui/gfx/codec/png_codec.h" #include "ui/gfx/font.h" @@ -168,6 +170,8 @@ void SetLoadTimeDataDefaults(const std::string& app_locale, base::DictionaryValue* localized_strings) { + // Needs to be all lowercase due to + localized_strings->SetString("a11yenhanced", GetA11yEnhanced()); localized_strings->SetString("fontfamily", GetFontFamily()); localized_strings->SetString("fontsize", GetFontSize()); localized_strings->SetString("language", l10n_util::GetLanguage(app_locale)); @@ -176,6 +180,7 @@ void SetLoadTimeDataDefaults(const std::string& app_locale, ui::TemplateReplacements* replacements) { + (*replacements)["a11yenhanced"] = GetA11yEnhanced(); (*replacements)["fontfamily"] = GetFontFamily(); (*replacements)["fontsize"] = GetFontSize(); (*replacements)["language"] = l10n_util::GetLanguage(app_locale); @@ -210,6 +215,12 @@ html->append("</style>"); } +std::string GetA11yEnhanced() { + return base::FeatureList::IsEnabled(features::kWebUIA11yEnhancements) + ? "a11y-enhanced" + : ""; +} + std::string GetFontFamily() { std::string font_family = l10n_util::GetStringUTF8(IDS_WEB_FONT_FAMILY);
diff --git a/ui/base/webui/web_ui_util.h b/ui/base/webui/web_ui_util.h index e0e49eab..bb1f6604 100644 --- a/ui/base/webui/web_ui_util.h +++ b/ui/base/webui/web_ui_util.h
@@ -87,6 +87,7 @@ // inline stylesheet. UI_BASE_EXPORT void AppendWebUiCssTextDefaults(std::string* html); +UI_BASE_EXPORT std::string GetA11yEnhanced(); // Get some common font styles for all of WebUI. UI_BASE_EXPORT std::string GetFontFamily(); UI_BASE_EXPORT std::string GetFontSize();
diff --git a/ui/native_theme/native_theme.cc b/ui/native_theme/native_theme.cc index 929e339..5fd3bb3 100644 --- a/ui/native_theme/native_theme.cc +++ b/ui/native_theme/native_theme.cc
@@ -84,6 +84,15 @@ return system_colors_; } +base::Optional<SkColor> NativeTheme::GetSystemColorFromMap( + SystemThemeColor theme_color) const { + auto color = system_colors_.find(theme_color); + if (color != system_colors_.end()) + return color->second; + + return base::nullopt; +} + bool NativeTheme::HasDifferentSystemColors( const std::map<NativeTheme::SystemThemeColor, SkColor>& colors) const { return system_colors_ != colors;
diff --git a/ui/native_theme/native_theme.h b/ui/native_theme/native_theme.h index 3604105..c1d4ad9a2 100644 --- a/ui/native_theme/native_theme.h +++ b/ui/native_theme/native_theme.h
@@ -466,6 +466,9 @@ virtual const std::map<SystemThemeColor, SkColor>& GetSystemColors() const; + base::Optional<SkColor> GetSystemColorFromMap( + SystemThemeColor theme_color) const; + bool HasDifferentSystemColors( const std::map<SystemThemeColor, SkColor>& colors) const;
diff --git a/ui/views/widget/widget_hwnd_utils.cc b/ui/views/widget/widget_hwnd_utils.cc index abd3b4e..0cccf60 100644 --- a/ui/views/widget/widget_hwnd_utils.cc +++ b/ui/views/widget/widget_hwnd_utils.cc
@@ -42,7 +42,7 @@ if (params.show_state == ui::SHOW_STATE_MINIMIZED) *style |= WS_MINIMIZE; if (!params.accept_events) - *ex_style |= WS_EX_TRANSPARENT | WS_EX_LAYERED; + *ex_style |= WS_EX_TRANSPARENT; DCHECK_NE(Widget::InitParams::ACTIVATABLE_DEFAULT, params.activatable); if (params.activatable == Widget::InitParams::ACTIVATABLE_NO) *ex_style |= WS_EX_NOACTIVATE;
diff --git a/ui/webui/resources/cr_components/chromeos/network/network_ip_config.js b/ui/webui/resources/cr_components/chromeos/network/network_ip_config.js index cc5403eb..03d15f0 100644 --- a/ui/webui/resources/cr_components/chromeos/network/network_ip_config.js +++ b/ui/webui/resources/cr_components/chromeos/network/network_ip_config.js
@@ -166,8 +166,10 @@ OncMojo.getIPConfigForType(properties, 'IPv4')); let ipv6 = this.getIPConfigUIProperties_( OncMojo.getIPConfigForType(properties, 'IPv6')); + // If connected and the IP address is automatic and set, show 'Loading' if + // the ipv6 address is not set. if (OncMojo.connectionStateIsConnected(properties.connectionState) && - ipv4 && ipv4.ipAddress) { + this.automatic_ && ipv4 && ipv4.ipAddress) { ipv6 = ipv6 || {}; ipv6.ipAddress = ipv6.ipAddress || this.i18n('loading'); }
diff --git a/ui/webui/resources/cr_elements/cr_drawer/cr_drawer.html b/ui/webui/resources/cr_elements/cr_drawer/cr_drawer.html index 40f2cb02..cb1dc2e 100644 --- a/ui/webui/resources/cr_elements/cr_drawer/cr_drawer.html +++ b/ui/webui/resources/cr_elements/cr_drawer/cr_drawer.html
@@ -99,14 +99,14 @@ overflow: auto; } </style> - <dialog id="dialog" on-cancel="onDialogCancel_" on-tap="onDialogTap_" + <dialog id="dialog" on-cancel="onDialogCancel_" on-click="onDialogTap_" on-close="onDialogClose_"> - <div id="container" on-tap="onContainerTap_"> + <div id="container" on-click="onContainerTap_"> <div class="drawer-header"> <!-- Hidden from a11y because this icon is decorative. Clicking closes the dialog, but screen reader users can do this by pressing ESC, so aria-hidden is OK here. --> - <iron-icon id="iconButton" icon="[[iconName]]" on-tap="onIconTap_" + <iron-icon id="iconButton" icon="[[iconName]]" on-click="onIconTap_" title="[[iconTitle]]" hidden="[[!iconName]]" aria-hidden="true"> </iron-icon> <div id="heading" tabindex="-1">[[heading]]</div>
diff --git a/ui/webui/resources/cr_elements/cr_icon_button/cr_icon_button.html b/ui/webui/resources/cr_elements/cr_icon_button/cr_icon_button.html index 12dfc7f..f889e4bb 100644 --- a/ui/webui/resources/cr_elements/cr_icon_button/cr_icon_button.html +++ b/ui/webui/resources/cr_elements/cr_icon_button/cr_icon_button.html
@@ -13,12 +13,10 @@ --cr-icon-button-icon-size: 20px; --cr-icon-button-size: 36px; --cr-icon-button-height: var(--cr-icon-button-size); + --cr-icon-button-transition: 150ms ease-in-out; --cr-icon-button-width: var(--cr-icon-button-size); /* Copied from paper-fab.html. Prevents square touch highlight. */ -webkit-tap-highlight-color: transparent; - background-position: center; - background-repeat: no-repeat; - background-size: var(--cr-icon-button-icon-size); border-radius: 4px; color: var(--cr-icon-button-color); cursor: pointer; @@ -40,25 +38,29 @@ pointer-events: none; } + :host(.no-overlap) { + --cr-icon-button-margin-end: 0; + --cr-icon-button-margin-start: 0; + } + :host-context([dir=rtl]) { transform: scaleX(-1); /* Invert X: flip on the Y axis (aka mirror). */ } - @media (prefers-color-scheme: dark) { - :host { - --cr-icon-button-color: var(--google-grey-refresh-500); - } + :host(:not([iron-icon])) #maskedImage { + -webkit-mask-image: var(--cr-icon-image); + -webkit-mask-position: center; + -webkit-mask-repeat: no-repeat; + -webkit-mask-size: var(--cr-icon-button-icon-size); + background-color: var(--cr-icon-button-color); + height: 100%; + transition: background-color var(--cr-icon-button-transition); + width: 100%; + z-index: 1; } - :host paper-ripple { - /* GG900 .15 is about GG700 .21 */ - --paper-ripple-opacity: var(--cr-icon-button-ripple-opacity, .21); - } - - @media (prefers-color-scheme: dark) { - :host paper-ripple { - --paper-ripple-opacity: var(--cr-icon-button-ripple-opacity, .4); - } + :host-context([a11y-enhanced]):host([ripple-showing_]) #maskedImage { + background-color: var(--cr-icon-button-focus-color, white); } #icon { @@ -74,11 +76,61 @@ } iron-icon { + --iron-icon-fill-color: var(--cr-icon-button-color); --iron-icon-height: var(--cr-icon-button-icon-size); --iron-icon-width: var(--cr-icon-button-icon-size); + transition: fill var(--cr-icon-button-transition); + z-index: 1; + } + + :host-context([a11y-enhanced]):host([ripple-showing_]) iron-icon { + --iron-icon-fill-color: var(--cr-icon-button-focus-color, white); + } + + paper-ripple { + /* GG900 .15 is about GG700 .21 */ + --paper-ripple-opacity: var(--cr-icon-button-ripple-opacity, .21); + } + + + :host-context([a11y-enhanced]) paper-ripple { + --paper-ripple-opacity: 1; + opacity: 0; + transition: opacity var(--cr-icon-button-transition); + } + + @media (prefers-color-scheme: dark) { + :host { + --cr-icon-button-color: var(--google-grey-refresh-500); + } + + :host-context([a11y-enhanced]):host([ripple-showing_]) iron-icon { + --iron-icon-fill-color: var(--cr-icon-button-focus-color, + var(--google-grey-900)); + } + + :host(:not([iron-icon])) #maskedImage { + background-color: var(--cr-icon-button-color, + var(--google-grey-refresh-500)); + } + + :host-context([a11y-enhanced]):host([ripple-showing_]) #maskedImage { + background-color: var(--cr-icon-button-focus-color, + var(--google-grey-900)); + } + + paper-ripple { + --paper-ripple-opacity: var(--cr-icon-button-ripple-opacity, .4); + } + } + + :host-context([a11y-enhanced]):host([ripple-showing_]) paper-ripple { + opacity: 1; } </style> - <div id="icon"></div> + <div id="icon"> + <div id="maskedImage"></div> + </div> </template> <script src="cr_icon_button.js"></script> </dom-module>
diff --git a/ui/webui/resources/cr_elements/cr_icon_button/cr_icon_button.js b/ui/webui/resources/cr_elements/cr_icon_button/cr_icon_button.js index 5f103f62..d86cd00 100644 --- a/ui/webui/resources/cr_elements/cr_icon_button/cr_icon_button.js +++ b/ui/webui/resources/cr_elements/cr_icon_button/cr_icon_button.js
@@ -44,6 +44,14 @@ ironIcon: { type: String, observer: 'onIronIconChanged_', + reflectToAttribute: true, + }, + + /** @private */ + rippleShowing_: { + type: Boolean, + value: false, + reflectToAttribute: true, }, }, @@ -56,6 +64,7 @@ listeners: { blur: 'hideRipple_', click: 'onClick_', + down: 'showRipple_', focus: 'showRipple_', keydown: 'onKeyDown_', keyup: 'onKeyUp_', @@ -67,6 +76,7 @@ hideRipple_: function() { if (this.hasRipple()) { this.getRipple().clear(); + this.rippleShowing_ = false; } }, @@ -74,6 +84,7 @@ showRipple_: function() { if (!this.noink && !this.disabled) { this.getRipple().showAndHoldDown(); + this.rippleShowing_ = true; } },
diff --git a/ui/webui/resources/cr_elements/cr_icons_css.html b/ui/webui/resources/cr_elements/cr_icons_css.html index f3fdcfb..aeddcc3c 100644 --- a/ui/webui/resources/cr_elements/cr_icons_css.html +++ b/ui/webui/resources/cr_elements/cr_icons_css.html
@@ -4,166 +4,95 @@ <dom-module id="cr-icons"> <template> <style> - :host-context([dir=rtl]) .cr-icon { - transform: scaleX(-1); /* Invert X: flip on the Y axis (aka mirror). */ + .icon-arrow-back { + --cr-icon-image: url(../images/icon_arrow_back.svg); + } + + .icon-arrow-dropdown { + --cr-icon-image: url(../images/icon_arrow_dropdown.svg); + } + + .icon-cancel { + --cr-icon-image: url(../images/icon_cancel.svg); + } + + .icon-clear { + --cr-icon-image: url(../images/icon_clear.svg); + } + + .icon-delete-gray { + --cr-icon-image: url(../images/icon_delete_gray.svg); + } + + .icon-picture-delete { + --cr-icon-image: url(../images/icon_picture_delete.svg); + } + + .icon-expand-less { + --cr-icon-image: url(../images/icon_expand_less.svg); + } + + .icon-expand-more { + --cr-icon-image: url(../images/icon_expand_more.svg); + } + + .icon-external { + --cr-icon-image: url(../images/open_in_new.svg); + } + + .icon-more-vert { + --cr-icon-image: url(../images/icon_more_vert.svg); + } + + .icon-refresh { + --cr-icon-image: url(../images/icon_refresh.svg); + } + + .icon-search { + --cr-icon-image: url(../images/icon_search.svg); + } + + .icon-settings { + --cr-icon-image: url(../images/icon_settings.svg); + } + + .icon-visibility { + --cr-icon-image: url(../images/icon_visibility.svg); + } + + .icon-visibility-off { + --cr-icon-image: url(../images/icon_visibility_off.svg); + } + + .subpage-arrow { + --cr-icon-image: url(../images/arrow_right.svg); } .cr-icon { @apply --cr-paper-icon-button-margin; - background-position: center; - background-repeat: no-repeat; - background-size: var(--cr-icon-size); + -webkit-mask-image: var(--cr-icon-image); + -webkit-mask-position: center; + -webkit-mask-repeat: no-repeat; + -webkit-mask-size: var(--cr-icon-size); + background-color: var(--google-grey-refresh-700); flex-shrink: 0; height: var(--cr-icon-ripple-size); user-select: none; width: var(--cr-icon-ripple-size); } - :-webkit-any(cr-icon-button, .cr-icon).no-overlap { + :host-context([dir=rtl]) .cr-icon { + transform: scaleX(-1); /* Invert X: flip on the Y axis (aka mirror). */ + } + + .cr-icon.no-overlap { margin-inline-end: 0; margin-inline-start: 0; } - :-webkit-any(cr-icon-button, .cr-icon).icon-arrow-back { - background-image: url(../images/icon_arrow_back.svg); - } @media (prefers-color-scheme: dark) { - :-webkit-any(cr-icon-button, .cr-icon).icon-arrow-back { - background-image: url(../images/dark/icon_arrow_back.svg); - } - } - - :-webkit-any(cr-icon-button, .cr-icon).icon-cancel { - background-image: url(../images/icon_cancel.svg); - } - @media (prefers-color-scheme: dark) { - :-webkit-any(cr-icon-button, .cr-icon).icon-cancel { - background-image: url(../images/dark/icon_cancel.svg); - } - } - - :-webkit-any(cr-icon-button, .cr-icon).icon-clear { - background-image: url(../images/icon_clear.svg); - } - @media (prefers-color-scheme: dark) { - :-webkit-any(cr-icon-button, .cr-icon).icon-clear { - background-image: url(../images/dark/icon_clear.svg); - } - } - - :-webkit-any(cr-icon-button, .cr-icon).icon-delete-gray { - background-image: url(../images/icon_delete_gray.svg); - } - @media (prefers-color-scheme: dark) { - :-webkit-any(cr-icon-button, .cr-icon).icon-delete-gray { - background-image: url(../images/dark/icon_delete_gray.svg); - } - } - - :-webkit-any(cr-icon-button, .cr-icon).icon-picture-delete { - background-image: url(../images/icon_picture_delete.svg); - } - @media (prefers-color-scheme: dark) { - :-webkit-any(cr-icon-button, .cr-icon).icon-picture-delete { - background-image: url(../images/dark/icon_picture_delete.svg); - } - } - - :-webkit-any(cr-icon-button, .cr-icon).icon-expand-less { - background-image: url(../images/icon_expand_less.svg); - } - @media (prefers-color-scheme: dark) { - :-webkit-any(cr-icon-button, .cr-icon).icon-expand-less { - background-image: url(../images/dark/icon_expand_less.svg); - } - } - - :-webkit-any(cr-icon-button, .cr-icon).icon-expand-more { - background-image: url(../images/icon_expand_more.svg); - } - @media (prefers-color-scheme: dark) { - :-webkit-any(cr-icon-button, .cr-icon).icon-expand-more { - background-image: url(../images/dark/icon_expand_more.svg); - } - } - - :-webkit-any(cr-icon-button, .cr-icon).icon-external { - background-image: url(../images/open_in_new.svg); - } - /* Open in new is the same for light and dark mode. */ - - :-webkit-any(cr-icon-button, .cr-icon).icon-more-vert { - background-image: url(../images/icon_more_vert.svg); - } - @media (prefers-color-scheme: dark) { - :-webkit-any(cr-icon-button, .cr-icon).icon-more-vert { - background-image: url(../images/dark/icon_more_vert.svg); - } - } - :-webkit-any(cr-icon-button, .cr-icon).icon-more-vert-light-mode { - background-image: url(../images/icon_more_vert.svg); - } - - :-webkit-any(cr-icon-button, .cr-icon).icon-refresh { - background-image: url(../images/icon_refresh.svg); - } - @media (prefers-color-scheme: dark) { - :-webkit-any(cr-icon-button, .cr-icon).icon-refresh { - background-image: url(../images/dark/icon_refresh.svg); - } - } - - :-webkit-any(cr-icon-button, .cr-icon).icon-settings { - background-image: url(../images/icon_settings.svg); - } - @media (prefers-color-scheme: dark) { - :-webkit-any(cr-icon-button, .cr-icon).icon-settings { - background-image: url(../images/dark/icon_settings.svg); - } - } - - :-webkit-any(cr-icon-button, .cr-icon).icon-search { - background-image: url(../images/icon_search.svg); - } - @media (prefers-color-scheme: dark) { - :-webkit-any(cr-icon-button, .cr-icon).icon-search { - background-image: url(../images/dark/icon_search.svg); - } - } - - :-webkit-any(cr-icon-button, .cr-icon).icon-arrow-dropdown { - background-image: url(../images/icon_arrow_dropdown.svg); - } - @media (prefers-color-scheme: dark) { - :-webkit-any(cr-icon-button, .cr-icon).icon-arrow-dropdown { - background-image: url(../images/dark/icon_arrow_dropdown.svg); - } - } - - :-webkit-any(cr-icon-button, .cr-icon).subpage-arrow { - background-image: url(../images/arrow_right.svg); - } - @media (prefers-color-scheme: dark) { - :-webkit-any(cr-icon-button, .cr-icon).subpage-arrow { - background-image: url(../images/dark/arrow_right.svg); - } - } - - :-webkit-any(cr-icon-button, .cr-icon).icon-visibility { - background-image: url(../images/icon_visibility.svg); - } - @media (prefers-color-scheme: dark) { - :-webkit-any(cr-icon-button, .cr-icon).icon-visibility { - background-image: url(../images/dark/icon_visibility.svg); - } - } - - :-webkit-any(cr-icon-button, .cr-icon).icon-visibility-off { - background-image: url(../images/icon_visibility_off.svg); - } - @media (prefers-color-scheme: dark) { - :-webkit-any(cr-icon-button, .cr-icon).icon-visibility-off { - background-image: url(../images/dark/icon_visibility_off.svg); + .cr-icon { + background-color: var(--google-grey-refresh-500); } } </style>
diff --git a/ui/webui/resources/cr_elements/cr_toolbar/cr_toolbar.html b/ui/webui/resources/cr_elements/cr_toolbar/cr_toolbar.html index ace3c147..a899d48 100644 --- a/ui/webui/resources/cr_elements/cr_toolbar/cr_toolbar.html +++ b/ui/webui/resources/cr_elements/cr_toolbar/cr_toolbar.html
@@ -12,6 +12,7 @@ <template> <style include="cr-icons cr-hidden-style"> :host { + --cr-icon-button-focus-color: var(--google-blue-700); align-items: center; background-color: var(--google-blue-700); color: #fff; @@ -21,6 +22,9 @@ @media (prefers-color-scheme: dark) { :host { + /* Toolbar background color rgba(255, 255, 255, .04) added to body + background color --google-grey-900. */ + --cr-icon-button-focus-color: #28292c; background-color: rgba(255, 255, 255, .04); border-bottom: var(--cr-separator-line); box-sizing: border-box; @@ -167,7 +171,7 @@ <template is="dom-if" if="[[showMenuPromo]]"> <div id="menuPromo" role="tooltip"> [[menuPromo]] - <button id="closePromo" on-tap="onClosePromoTap_" + <button id="closePromo" on-click="onClosePromoTap_" aria-label$="[[closeMenuPromo]]">✕</button> </paper-tooltip> </template>
diff --git a/ui/webui/resources/cr_elements/cr_toolbar/cr_toolbar_search_field.html b/ui/webui/resources/cr_elements/cr_toolbar/cr_toolbar_search_field.html index 7d4d186..3eb5dbd 100644 --- a/ui/webui/resources/cr_elements/cr_toolbar/cr_toolbar_search_field.html +++ b/ui/webui/resources/cr_elements/cr_toolbar/cr_toolbar_search_field.html
@@ -31,15 +31,14 @@ @media (prefers-color-scheme: light) { cr-icon-button { - --cr-icon-button-color: currentColor; - --iron-icon-fill-color: - var(--cr-toolbar-search-field-input-color, white); + --cr-icon-button-color: var(--cr-toolbar-search-field-input-color, + white); } } @media (prefers-color-scheme: dark) { cr-icon-button { - --iron-icon-fill-color: var(--cr-toolbar-search-field-input-color, + --cr-icon-button-color: var(--cr-toolbar-search-field-input-color, var(--google-grey-refresh-500)); } }
diff --git a/ui/webui/resources/cr_elements/shared_style_css.html b/ui/webui/resources/cr_elements/shared_style_css.html index 292378f..8b18b8e 100644 --- a/ui/webui/resources/cr_elements/shared_style_css.html +++ b/ui/webui/resources/cr_elements/shared_style_css.html
@@ -25,16 +25,6 @@ cursor: pointer; } - .subpage-arrow, - .icon-external { - display: none; - } - - [actionable] :-webkit-any(.subpage-arrow, .icon-external), - [actionable]:-webkit-any(.subpage-arrow, .icon-external) { - display: block; - } - /* Horizontal rule line. */ .hr { border-top: var(--cr-separator-line);
diff --git a/ui/webui/resources/cr_elements_images.grdp b/ui/webui/resources/cr_elements_images.grdp index 7c12c157..1f0b8227 100644 --- a/ui/webui/resources/cr_elements_images.grdp +++ b/ui/webui/resources/cr_elements_images.grdp
@@ -9,46 +9,8 @@ file="images/arrow_right.svg" type="BINDATA" compress="gzip" /> <include name="IDR_WEBUI_IMAGES_DARK_ARROW_DOWN" file="images/dark/arrow_down.svg" type="BINDATA" compress="gzip" /> - <include name="IDR_WEBUI_IMAGES_DARK_ARROW_RIGHT" - file="images/dark/arrow_right.svg" type="BINDATA" compress="gzip" /> - <include name="IDR_WEBUI_IMAGES_DARK_ICON_ARROW_BACK" - file="images/dark/icon_arrow_back.svg" type="BINDATA" - compress="gzip" /> - <include name="IDR_WEBUI_IMAGES_DARK_ICON_ARROW_DROPDOWN" - file="images/dark/icon_arrow_dropdown.svg" type="BINDATA" - compress="gzip" /> - <include name="IDR_WEBUI_IMAGES_DARK_ICON_CANCEL" - file="images/dark/icon_cancel.svg" type="BINDATA" compress="gzip" /> - <include name="IDR_WEBUI_IMAGES_DARK_ICON_CLEAR" - file="images/dark/icon_clear.svg" type="BINDATA" compress="gzip" /> - <include name="IDR_WEBUI_IMAGES_DARK_ICON_DELETE_GRAY" - file="images/dark/icon_delete_gray.svg" type="BINDATA" - compress="gzip" /> - <include name="IDR_WEBUI_IMAGES_DARK_ICON_EXPAND_LESS" - file="images/dark/icon_expand_less.svg" type="BINDATA" - compress="gzip" /> - <include name="IDR_WEBUI_IMAGES_DARK_ICON_EXPAND_MORE" - file="images/dark/icon_expand_more.svg" type="BINDATA" - compress="gzip" /> - <include name="IDR_WEBUI_IMAGES_DARK_ICON_MORE_VERT" - file="images/dark/icon_more_vert.svg" type="BINDATA" - compress="gzip" /> - <include name="IDR_WEBUI_IMAGES_DARK_ICON_PICTURE_DELETE" - file="images/dark/icon_picture_delete.svg" type="BINDATA" - compress="gzip" /> - <include name="IDR_WEBUI_IMAGES_DARK_ICON_REFRESH" - file="images/dark/icon_refresh.svg" type="BINDATA" compress="gzip" /> - <include name="IDR_WEBUI_IMAGES_DARK_ICON_SETTINGS" - file="images/dark/icon_settings.svg" type="BINDATA" - compress="gzip" /> <include name="IDR_WEBUI_IMAGES_DARK_ICON_SEARCH" file="images/dark/icon_search.svg" type="BINDATA" compress="gzip" /> - <include name="IDR_WEBUI_IMAGES_DARK_ICON_VISIBILITY" - file="images/dark/icon_visibility.svg" type="BINDATA" - compress="gzip" /> - <include name="IDR_WEBUI_IMAGES_DARK_ICON_VISIBILITY_OFF" - file="images/dark/icon_visibility_off.svg" type="BINDATA" - compress="gzip" /> <include name="IDR_WEBUI_IMAGES_ICON_ARROW_BACK" file="images/icon_arrow_back.svg" type="BINDATA" compress="gzip" /> <include name="IDR_WEBUI_IMAGES_ICON_ARROW_DROPDOWN"
diff --git a/ui/webui/resources/images/dark/arrow_right.svg b/ui/webui/resources/images/dark/arrow_right.svg deleted file mode 100644 index a1e71de..0000000 --- a/ui/webui/resources/images/dark/arrow_right.svg +++ /dev/null
@@ -1 +0,0 @@ -<svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" fill="#9aa0a6"><path d="M10 7l5 5-5 5z"/></svg> \ No newline at end of file
diff --git a/ui/webui/resources/images/dark/icon_arrow_back.svg b/ui/webui/resources/images/dark/icon_arrow_back.svg deleted file mode 100644 index 5747b495..0000000 --- a/ui/webui/resources/images/dark/icon_arrow_back.svg +++ /dev/null
@@ -1 +0,0 @@ -<svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" fill="#9aa0a6"><path d="M20 11H7.83l5.59-5.59L12 4l-8 8 8 8 1.41-1.41L7.83 13H20v-2z"/></svg> \ No newline at end of file
diff --git a/ui/webui/resources/images/dark/icon_arrow_dropdown.svg b/ui/webui/resources/images/dark/icon_arrow_dropdown.svg deleted file mode 100644 index e68ecf14..0000000 --- a/ui/webui/resources/images/dark/icon_arrow_dropdown.svg +++ /dev/null
@@ -1 +0,0 @@ -<svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" fill="#9aa0a6"><path d="M7 10l5 5 5-5z"/></svg> \ No newline at end of file
diff --git a/ui/webui/resources/images/dark/icon_cancel.svg b/ui/webui/resources/images/dark/icon_cancel.svg deleted file mode 100644 index 8cc110e8..0000000 --- a/ui/webui/resources/images/dark/icon_cancel.svg +++ /dev/null
@@ -1 +0,0 @@ -<svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 2 4" fill="#9aa0a6"><path d="M12 2C6.47 2 2 6.47 2 12s4.47 10 10 10 10-4.47 10-10S17.53 2 12 2zm5 13.59L15.59 17 12 13.41 8.41 17 7 15.59 10.59 12 7 8.41 8.41 7 12 10.59 15.59 7 17 8.41 13.41 12 17 15.59z"/></svg> \ No newline at end of file
diff --git a/ui/webui/resources/images/dark/icon_clear.svg b/ui/webui/resources/images/dark/icon_clear.svg deleted file mode 100644 index e54b804..0000000 --- a/ui/webui/resources/images/dark/icon_clear.svg +++ /dev/null
@@ -1 +0,0 @@ -<svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" fill="#9aa0a6"><path d="M19 6.41L17.59 5 12 10.59 6.41 5 5 6.41 10.59 12 5 17.59 6.41 19 12 13.41 17.59 19 19 17.59 13.41 12z"/></svg> \ No newline at end of file
diff --git a/ui/webui/resources/images/dark/icon_delete_gray.svg b/ui/webui/resources/images/dark/icon_delete_gray.svg deleted file mode 100644 index fe178de..0000000 --- a/ui/webui/resources/images/dark/icon_delete_gray.svg +++ /dev/null
@@ -1 +0,0 @@ -<svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" fill="#9aa0a6"><path d="M6 19c0 1.1.9 2 2 2h8c1.1 0 2-.9 2-2V7H6v12zM19 4h-3.5l-1-1h-5l-1 1H5v2h14V4z"/></svg> \ No newline at end of file
diff --git a/ui/webui/resources/images/dark/icon_expand_less.svg b/ui/webui/resources/images/dark/icon_expand_less.svg deleted file mode 100644 index 2ff69ede..0000000 --- a/ui/webui/resources/images/dark/icon_expand_less.svg +++ /dev/null
@@ -1 +0,0 @@ -<svg xmlns="http://www.w3.org/2000/svg" fill="#9aa0a6" width="24" height="24"><path d="M12 8l-6 6 1.41 1.41L12 10.83l4.59 4.58L18 14z"/></svg> \ No newline at end of file
diff --git a/ui/webui/resources/images/dark/icon_expand_more.svg b/ui/webui/resources/images/dark/icon_expand_more.svg deleted file mode 100644 index 9ae4310..0000000 --- a/ui/webui/resources/images/dark/icon_expand_more.svg +++ /dev/null
@@ -1 +0,0 @@ -<svg xmlns="http://www.w3.org/2000/svg" fill="#9aa0a6" width="24" height="24"><path d="M16.59 8.59L12 13.17 7.41 8.59 6 10l6 6 6-6z"/></svg> \ No newline at end of file
diff --git a/ui/webui/resources/images/dark/icon_more_vert.svg b/ui/webui/resources/images/dark/icon_more_vert.svg deleted file mode 100644 index 1e86d68ec..0000000 --- a/ui/webui/resources/images/dark/icon_more_vert.svg +++ /dev/null
@@ -1 +0,0 @@ -<svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" fill="#9aa0a6"><path d="M12 8c1.1 0 2-.9 2-2s-.9-2-2-2-2 .9-2 2 .9 2 2 2zm0 2c-1.1 0-2 .9-2 2s.9 2 2 2 2-.9 2-2-.9-2-2-2zm0 6c-1.1 0-2 .9-2 2s.9 2 2 2 2-.9 2-2-.9-2-2-2z"/></svg> \ No newline at end of file
diff --git a/ui/webui/resources/images/dark/icon_picture_delete.svg b/ui/webui/resources/images/dark/icon_picture_delete.svg deleted file mode 100644 index f582d05..0000000 --- a/ui/webui/resources/images/dark/icon_picture_delete.svg +++ /dev/null
@@ -1 +0,0 @@ -<svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" fill="#e8eaed"><path d="M6 19c0 1.1.9 2 2 2h8c1.1 0 2-.9 2-2V7H6v12zM19 4h-3.5l-1-1h-5l-1 1H5v2h14V4z"/></svg> \ No newline at end of file
diff --git a/ui/webui/resources/images/dark/icon_refresh.svg b/ui/webui/resources/images/dark/icon_refresh.svg deleted file mode 100644 index 6542cec..0000000 --- a/ui/webui/resources/images/dark/icon_refresh.svg +++ /dev/null
@@ -1 +0,0 @@ -<svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" fill="#9aa0a6"><path d="M17.65 6.35A7.958 7.958 0 0 0 12 4c-4.42 0-7.99 3.58-7.99 8s3.57 8 7.99 8c3.73 0 6.84-2.55 7.73-6h-2.08A5.99 5.99 0 0 1 12 18c-3.31 0-6-2.69-6-6s2.69-6 6-6c1.66 0 3.14.69 4.22 1.78L13 11h7V4l-2.35 2.35z"/></svg> \ No newline at end of file
diff --git a/ui/webui/resources/images/dark/icon_settings.svg b/ui/webui/resources/images/dark/icon_settings.svg deleted file mode 100644 index 33a55b9e6..0000000 --- a/ui/webui/resources/images/dark/icon_settings.svg +++ /dev/null
@@ -1 +0,0 @@ -<svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" fill="#9aa0a6"><path d="M19.43 12.98c.04-.32.07-.64.07-.98s-.03-.66-.07-.98l2.11-1.65c.19-.15.24-.42.12-.64l-2-3.46c-.12-.22-.39-.3-.61-.22l-2.49 1c-.52-.4-1.08-.73-1.69-.98l-.38-2.65A.488.488 0 0 0 14 2h-4c-.25 0-.46.18-.49.42l-.38 2.65c-.61.25-1.17.59-1.69.98l-2.49-1c-.23-.09-.49 0-.61.22l-2 3.46c-.13.22-.07.49.12.64l2.11 1.65c-.04.32-.07.65-.07.98s.03.66.07.98l-2.11 1.65c-.19.15-.24.42-.12.64l2 3.46c.12.22.39.3.61.22l2.49-1c.52.4 1.08.73 1.69.98l.38 2.65c.03.24.24.42.49.42h4c.25 0 .46-.18.49-.42l.38-2.65c.61-.25 1.17-.59 1.69-.98l2.49 1c.23.09.49 0 .61-.22l2-3.46c.12-.22.07-.49-.12-.64l-2.11-1.65zM12 15.5c-1.93 0-3.5-1.57-3.5-3.5s1.57-3.5 3.5-3.5 3.5 1.57 3.5 3.5-1.57 3.5-3.5 3.5z"/></svg> \ No newline at end of file
diff --git a/ui/webui/resources/images/dark/icon_visibility.svg b/ui/webui/resources/images/dark/icon_visibility.svg deleted file mode 100644 index 2352cc47..0000000 --- a/ui/webui/resources/images/dark/icon_visibility.svg +++ /dev/null
@@ -1 +0,0 @@ -<svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" fill="#9aa0a6"><path d="M12 4.5C7 4.5 2.73 7.61 1 12c1.73 4.39 6 7.5 11 7.5s9.27-3.11 11-7.5c-1.73-4.39-6-7.5-11-7.5zM12 17c-2.76 0-5-2.24-5-5s2.24-5 5-5 5 2.24 5 5-2.24 5-5 5zm0-8c-1.66 0-3 1.34-3 3s1.34 3 3 3 3-1.34 3-3-1.34-3-3-3z"/></svg> \ No newline at end of file
diff --git a/ui/webui/resources/images/dark/icon_visibility_off.svg b/ui/webui/resources/images/dark/icon_visibility_off.svg deleted file mode 100644 index 9cd712c..0000000 --- a/ui/webui/resources/images/dark/icon_visibility_off.svg +++ /dev/null
@@ -1 +0,0 @@ -<svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" fill="#9aa0a6"><path d="M12 7c2.76 0 5 2.24 5 5 0 .65-.13 1.26-.36 1.83l2.92 2.92c1.51-1.26 2.7-2.89 3.43-4.75-1.73-4.39-6-7.5-11-7.5-1.4 0-2.74.25-3.98.7l2.16 2.16C10.74 7.13 11.35 7 12 7zM2 4.27l2.28 2.28.46.46A11.804 11.804 0 0 0 1 12c1.73 4.39 6 7.5 11 7.5 1.55 0 3.03-.3 4.38-.84l.42.42L19.73 22 21 20.73 3.27 3 2 4.27zM7.53 9.8l1.55 1.55c-.05.21-.08.43-.08.65 0 1.66 1.34 3 3 3 .22 0 .44-.03.65-.08l1.55 1.55c-.67.33-1.41.53-2.2.53-2.76 0-5-2.24-5-5 0-.79.2-1.53.53-2.2zm4.31-.78l3.15 3.15.02-.16c0-1.66-1.34-3-3-3l-.17.01z"/></svg> \ No newline at end of file
diff --git a/ui/webui/resources/js/chromeos/onc_mojo.js b/ui/webui/resources/js/chromeos/onc_mojo.js index e979779..1bf6ecc 100644 --- a/ui/webui/resources/js/chromeos/onc_mojo.js +++ b/ui/webui/resources/js/chromeos/onc_mojo.js
@@ -758,6 +758,11 @@ } } + // Only populate static ip config properties for IPv4. + if (desiredType != 'IPv4') { + return undefined; + } + if (!ipConfig) { ipConfig = /** @type {!mojom.IPConfigProperties} */ ({routingPrefix: 0}); }
diff --git a/weblayer/browser/java/org/chromium/weblayer_private/BrowserControllerImpl.java b/weblayer/browser/java/org/chromium/weblayer_private/BrowserControllerImpl.java index 356f54e..908a9c7 100644 --- a/weblayer/browser/java/org/chromium/weblayer_private/BrowserControllerImpl.java +++ b/weblayer/browser/java/org/chromium/weblayer_private/BrowserControllerImpl.java
@@ -5,8 +5,6 @@ package org.chromium.weblayer_private; import android.content.Context; -import android.content.ContextWrapper; -import android.content.res.Resources; import android.view.Gravity; import android.view.KeyEvent; import android.view.MotionEvent; @@ -63,16 +61,9 @@ public void onScrollChanged(int lPix, int tPix, int oldlPix, int oldtPix) {} } - public BrowserControllerImpl(Context clientContext, Context implContext, ProfileImpl profile) { + public BrowserControllerImpl(Context context, ProfileImpl profile) { mProfile = profile; - Context context = new ContextWrapper(clientContext) { - @Override - public Resources getResources() { - // Always use resources from the implementation APK. - return implContext.getResources(); - } - }; // Use false to disable listening to activity state. // TODO: this should *not* use ActivityWindowAndroid as that relies on Activity, and this // code should not assume it is supplied an Activity.
diff --git a/weblayer/browser/java/org/chromium/weblayer_private/ProfileImpl.java b/weblayer/browser/java/org/chromium/weblayer_private/ProfileImpl.java index c6b6624..3e76f82 100644 --- a/weblayer/browser/java/org/chromium/weblayer_private/ProfileImpl.java +++ b/weblayer/browser/java/org/chromium/weblayer_private/ProfileImpl.java
@@ -33,10 +33,8 @@ } @Override - public IBrowserController createBrowserController( - IObjectWrapper clientContext, IObjectWrapper implContext) { - return new BrowserControllerImpl(ObjectWrapper.unwrap(clientContext, Context.class), - ObjectWrapper.unwrap(implContext, Context.class), this); + public IBrowserController createBrowserController(IObjectWrapper context) { + return new BrowserControllerImpl(ObjectWrapper.unwrap(context, Context.class), this); } long getNativeProfile() {
diff --git a/weblayer/browser/java/org/chromium/weblayer_private/WebLayerImpl.java b/weblayer/browser/java/org/chromium/weblayer_private/WebLayerImpl.java index 645b24b5..e38fe12 100644 --- a/weblayer/browser/java/org/chromium/weblayer_private/WebLayerImpl.java +++ b/weblayer/browser/java/org/chromium/weblayer_private/WebLayerImpl.java
@@ -4,10 +4,7 @@ package org.chromium.weblayer_private; -import android.app.Application; import android.content.Context; -import android.content.ContextWrapper; -import android.content.res.Resources; import android.os.IBinder; import android.util.AndroidRuntimeException; @@ -35,8 +32,8 @@ private static final String COMMAND_LINE_FILE = "/data/local/tmp/weblayer-command-line"; @UsedByReflection("WebLayer") - public static IBinder create(Application application, Context implContext) { - return new WebLayerImpl(application, implContext); + public static IBinder create(Context context) { + return new WebLayerImpl(context); } @Override @@ -44,18 +41,12 @@ return new ProfileImpl(path); } - private WebLayerImpl(Application application, Context implContext) { - ContextUtils.initApplicationContext(new ContextWrapper(application) { - @Override - public Resources getResources() { - // Always use resources from the implementation APK. - return implContext.getResources(); - } - }); + private WebLayerImpl(Context context) { + ContextUtils.initApplicationContext(context); ResourceBundle.setNoAvailableLocalePaks(); PathUtils.setPrivateDataDirectorySuffix(PRIVATE_DATA_DIRECTORY_SUFFIX); - ChildProcessCreationParams.set(application.getPackageName(), false /* isExternalService */, + ChildProcessCreationParams.set(context.getPackageName(), false /* isExternalService */, LibraryProcessType.PROCESS_WEBLAYER_CHILD, true /* bindToCaller */, false /* ignoreVisibilityForImportance */, "org.chromium.weblayer.ChildProcessService$Privileged",
diff --git a/weblayer/browser/java/org/chromium/weblayer_private/aidl/IProfile.aidl b/weblayer/browser/java/org/chromium/weblayer_private/aidl/IProfile.aidl index 3099c12..3e8e2af 100644 --- a/weblayer/browser/java/org/chromium/weblayer_private/aidl/IProfile.aidl +++ b/weblayer/browser/java/org/chromium/weblayer_private/aidl/IProfile.aidl
@@ -14,9 +14,7 @@ /** * Creates a new IBrowserController. - * @param clientContext Context from the client - * @param implContext Context that refers to the weblayer implementation + * @param context Context that refers the the weblayer implementation */ - IBrowserController createBrowserController(in IObjectWrapper clientContext, - in IObjectWrapper implContext) = 2; + IBrowserController createBrowserController(in IObjectWrapper context) = 2; }
diff --git a/weblayer/public/java/org/chromium/weblayer/ChildProcessService.java b/weblayer/public/java/org/chromium/weblayer/ChildProcessService.java index 9514db7..932d7434 100644 --- a/weblayer/public/java/org/chromium/weblayer/ChildProcessService.java +++ b/weblayer/public/java/org/chromium/weblayer/ChildProcessService.java
@@ -5,9 +5,7 @@ package org.chromium.weblayer; import android.app.Service; -import android.content.ComponentCallbacks; import android.content.Context; -import android.content.ContextWrapper; import android.content.Intent; import android.os.IBinder; import android.os.RemoteException; @@ -33,24 +31,7 @@ (IBinder) remoteContext.getClassLoader() .loadClass("org.chromium.weblayer_private.ChildProcessServiceImpl") .getMethod("create", Service.class, Context.class) - .invoke(null, this, new ContextWrapper(remoteContext) { - @Override - public Context getApplicationContext() { - return remoteContext; - } - - @Override - public void registerComponentCallbacks( - ComponentCallbacks callback) { - getApplication().registerComponentCallbacks(callback); - } - - @Override - public void unregisterComponentCallbacks( - ComponentCallbacks callback) { - getApplication().unregisterComponentCallbacks(callback); - } - })); + .invoke(null, this, remoteContext)); mImpl.onCreate(); } catch (Exception e) { throw new APICallException(e);
diff --git a/weblayer/public/java/org/chromium/weblayer/Profile.java b/weblayer/public/java/org/chromium/weblayer/Profile.java index a64d52e..10d5a2d 100644 --- a/weblayer/public/java/org/chromium/weblayer/Profile.java +++ b/weblayer/public/java/org/chromium/weblayer/Profile.java
@@ -45,9 +45,8 @@ public BrowserFragmentImpl createBrowserFragment(Context context) { try { - return new BrowserFragmentImpl( - mImpl.createBrowserController(ObjectWrapper.wrap(context), - ObjectWrapper.wrap(WebLayer.createRemoteContext(context)))); + return new BrowserFragmentImpl(mImpl.createBrowserController( + ObjectWrapper.wrap(WebLayer.createRemoteContext(context)))); } catch (RemoteException e) { throw new APICallException(e); }
diff --git a/weblayer/public/java/org/chromium/weblayer/WebLayer.java b/weblayer/public/java/org/chromium/weblayer/WebLayer.java index 9b96d146..78152de4 100644 --- a/weblayer/public/java/org/chromium/weblayer/WebLayer.java +++ b/weblayer/public/java/org/chromium/weblayer/WebLayer.java
@@ -5,10 +5,13 @@ package org.chromium.weblayer; import android.app.Application; +import android.content.ComponentCallbacks; import android.content.Context; +import android.content.ContextWrapper; import android.content.pm.PackageInfo; import android.content.pm.PackageManager; import android.content.pm.PackageManager.NameNotFoundException; +import android.content.res.Resources; import android.os.Bundle; import android.os.IBinder; import android.os.RemoteException; @@ -65,8 +68,8 @@ mImpl = IWebLayer.Stub.asInterface( (IBinder) remoteContext.getClassLoader() .loadClass("org.chromium.weblayer_private.WebLayerImpl") - .getMethod("create", Application.class, Context.class) - .invoke(null, application, remoteContext)); + .getMethod("create", Context.class) + .invoke(null, remoteContext)); } catch (Exception e) { throw new APICallException(e); } @@ -97,14 +100,49 @@ * Creates a Context for the remote (weblayer implementation) side. */ static Context createRemoteContext(Context localContext) { + Context remoteContext; try { // TODO(cduvall): Might want to cache the remote context so we don't need to call into // package manager more than we need to. - return localContext.createPackageContext(getImplPackageName(localContext), + remoteContext = localContext.createPackageContext(getImplPackageName(localContext), Context.CONTEXT_IGNORE_SECURITY | Context.CONTEXT_INCLUDE_CODE); } catch (NameNotFoundException e) { throw new AndroidRuntimeException(e); } + return wrapContext(localContext, remoteContext); + } + + private static Context wrapContext(Context localContext, Context remoteContext) { + return new ContextWrapper(localContext) { + @Override + public Context getApplicationContext() { + if (getBaseContext().getApplicationContext() == getBaseContext()) return this; + return wrapContext(getBaseContext().getApplicationContext(), remoteContext); + } + + @Override + public Resources getResources() { + return remoteContext.getResources(); + } + + @Override + public ClassLoader getClassLoader() { + return remoteContext.getClassLoader(); + } + + @Override + public void registerComponentCallbacks(ComponentCallbacks callback) { + // We have to override registerComponentCallbacks and unregisterComponentCallbacks + // since they call getApplicationContext().[un]registerComponentCallbacks() + // which causes us to go into a loop. + getBaseContext().registerComponentCallbacks(callback); + } + + @Override + public void unregisterComponentCallbacks(ComponentCallbacks callback) { + getBaseContext().unregisterComponentCallbacks(callback); + } + }; } private static String getImplPackageName(Context localContext)