diff --git a/DEPS b/DEPS index 40e14f4..f626df2 100644 --- a/DEPS +++ b/DEPS
@@ -117,7 +117,7 @@ # Three lines of non-changing comments so that # the commit queue can handle CLs rolling ANGLE # and whatever else without interference from each other. - 'angle_revision': '6e5bf36ff50f7976463c3c32151ece044e802284', + 'angle_revision': '3394a73db973081e6ab86ba51c6eccc7ee9826d0', # Three lines of non-changing comments so that # the commit queue can handle CLs rolling build tools # and whatever else without interference from each other. @@ -129,7 +129,7 @@ # Three lines of non-changing comments so that # the commit queue can handle CLs rolling PDFium # and whatever else without interference from each other. - 'pdfium_revision': '5f4cd74d2693e23b27237b935f28a87611e25e6b', + 'pdfium_revision': 'd5e282648a08a0b68c30edce51fafeeb5d76db7b', # Three lines of non-changing comments so that # the commit queue can handle CLs rolling openmax_dl # and whatever else without interference from each other. @@ -165,7 +165,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': 'ed63b1319414a36b099cad8443d497bda8f085a2', + 'catapult_revision': '3d85a23b6c188d2e3803be81c288bdf56e992ed7', # Three lines of non-changing comments so that # the commit queue can handle CLs rolling libFuzzer # and whatever else without interference from each other. @@ -552,7 +552,7 @@ # Build tools for Chrome OS. Note: This depends on third_party/pyelftools. 'src/third_party/chromite': { - 'url': Var('chromium_git') + '/chromiumos/chromite.git' + '@' + 'a82d0a22067f72fda9d72c3679f108a9c1550407', + 'url': Var('chromium_git') + '/chromiumos/chromite.git' + '@' + 'e5f282cb55b2366f57f0904546374843c98e3dc9', 'condition': 'checkout_linux', }, @@ -577,7 +577,7 @@ }, 'src/third_party/depot_tools': - Var('chromium_git') + '/chromium/tools/depot_tools.git' + '@' + 'efb38bb3d729f9d5b27f5202c766d43186c0103a', + Var('chromium_git') + '/chromium/tools/depot_tools.git' + '@' + '95fb6dc810348da9dd261a4f7ac2d66c5743da86', 'src/third_party/devtools-node-modules': Var('chromium_git') + '/external/github.com/ChromeDevTools/devtools-node-modules' + '@' + Var('devtools_node_modules_revision'), @@ -623,7 +623,7 @@ Var('chromium_git') + '/chromium/deps/flac.git' + '@' + 'af862024c8c8fa0ae07ced05e89013d881b00596', 'src/third_party/flatbuffers/src': - Var('chromium_git') + '/external/github.com/google/flatbuffers.git' + '@' + '01c50d57a67a52ee3cddd81b54d4647e9123a290', + Var('chromium_git') + '/external/github.com/google/flatbuffers.git' + '@' + 'c721009491dc8275052cf33f7334e015ed737927', # Used for embedded builds. CrOS & Linux use the system version. 'src/third_party/fontconfig/src': { @@ -826,7 +826,7 @@ }, 'src/third_party/libvpx/source/libvpx': - Var('chromium_git') + '/webm/libvpx.git' + '@' + 'b8642738c9851232c9bb1e1a22474953d3d367cf', + Var('chromium_git') + '/webm/libvpx.git' + '@' + '6c62530c666fc0bcf4385a35a7c49e44c9f38cf5', 'src/third_party/libwebm/source': Var('chromium_git') + '/webm/libwebm.git' + '@' + '01c1d1d76f139345c442bfc8e61b4e1cba809059', @@ -1049,7 +1049,7 @@ Var('chromium_git') + '/external/khronosgroup/webgl.git' + '@' + '7ca87fb1d3da3b3d2060886e8c58e726d74c8219', 'src/third_party/webrtc': - Var('webrtc_git') + '/src.git' + '@' + '74ed734d717a3d3f47f393ab0f8593c7f6a696d6', + Var('webrtc_git') + '/src.git' + '@' + 'b005087a8cac6afda03b0b100f7a9f5b26ebeac4', 'src/third_party/xdg-utils': { 'url': Var('chromium_git') + '/chromium/deps/xdg-utils.git' + '@' + 'd80274d5869b17b8c9067a1022e4416ee7ed5e0d',
diff --git a/android_webview/DEPS b/android_webview/DEPS index 0b24be7..8ea0912d 100644 --- a/android_webview/DEPS +++ b/android_webview/DEPS
@@ -31,6 +31,7 @@ "+services/viz/public/interfaces", "+skia", "+third_party/skia/include", + "+third_party/boringssl/src/include", "+ui/android", "+ui/base", "+ui/gfx",
diff --git a/android_webview/apk/java/AndroidManifest.xml b/android_webview/apk/java/AndroidManifest.xml index d948a86..94264a9 100644 --- a/android_webview/apk/java/AndroidManifest.xml +++ b/android_webview/apk/java/AndroidManifest.xml
@@ -7,13 +7,16 @@ <manifest xmlns:android="http://schemas.android.com/apk/res/android" xmlns:tools="http://schemas.android.com/tools" - package="{{package|default('com.android.webview')}}"> + package="{{package|default('com.android.webview')}}" + tools:ignore="MissingLeanbackLauncher"> <uses-sdk android:minSdkVersion="{{minsdk|default(21)}}" android:targetSdkVersion="{{targetsdk|default(28)}}"> </uses-sdk> <uses-feature android:name="android.hardware.touchscreen" android:required="false" /> + <uses-feature android:name="android.software.leanback" + android:required="false" /> <uses-permission android:name="android.permission.INTERNET" /> <uses-permission android:name="android.permission.ACCESS_NETWORK_STATE" />
diff --git a/android_webview/browser/aw_autofill_client.cc b/android_webview/browser/aw_autofill_client.cc index 929bc18..796de2bb 100644 --- a/android_webview/browser/aw_autofill_client.cc +++ b/android_webview/browser/aw_autofill_client.cc
@@ -262,7 +262,14 @@ NOTIMPLEMENTED(); } -void AwAutofillClient::ShowLocalCardMigrationPrompt(base::OnceClosure closure) { +void AwAutofillClient::ShowLocalCardMigrationDialog( + base::OnceClosure show_migration_dialog_closure) { + NOTIMPLEMENTED(); +} + +void AwAutofillClient::ConfirmMigrateLocalCardToCloud( + std::vector<autofill::MigratableCreditCard>& migratable_credit_cards, + base::OnceClosure start_migrating_cards_closure) { NOTIMPLEMENTED(); }
diff --git a/android_webview/browser/aw_autofill_client.h b/android_webview/browser/aw_autofill_client.h index 1416cdc..32aeb0b 100644 --- a/android_webview/browser/aw_autofill_client.h +++ b/android_webview/browser/aw_autofill_client.h
@@ -23,6 +23,7 @@ class CardUnmaskDelegate; class CreditCard; class FormStructure; +class MigratableCreditCard; class PersonalDataManager; } @@ -74,7 +75,11 @@ UnmaskCardReason reason, base::WeakPtr<autofill::CardUnmaskDelegate> delegate) override; void OnUnmaskVerificationResult(PaymentsRpcResult result) override; - void ShowLocalCardMigrationPrompt(base::OnceClosure closure) override; + void ShowLocalCardMigrationDialog( + base::OnceClosure show_migration_dialog_closure) override; + void ConfirmMigrateLocalCardToCloud( + std::vector<autofill::MigratableCreditCard>& migratable_credit_cards, + base::OnceClosure start_migrating_cards_closure) override; void ConfirmSaveAutofillProfile(const autofill::AutofillProfile& profile, base::OnceClosure callback) override; void ConfirmSaveCreditCardLocally(const autofill::CreditCard& card,
diff --git a/android_webview/browser/net/aw_url_request_context_getter.cc b/android_webview/browser/net/aw_url_request_context_getter.cc index 9d28b87..6222725 100644 --- a/android_webview/browser/net/aw_url_request_context_getter.cc +++ b/android_webview/browser/net/aw_url_request_context_getter.cc
@@ -38,6 +38,7 @@ #include "content/public/common/content_switches.h" #include "content/public/common/url_constants.h" #include "net/base/cache_type.h" +#include "net/cert/cert_verifier.h" #include "net/cookies/cookie_store.h" #include "net/dns/mapped_host_resolver.h" #include "net/extras/sqlite/sqlite_channel_id_store.h" @@ -176,31 +177,6 @@ return job_factory; } -// For Android WebView, do not enforce policies that are not consistent with -// the underlying OS validator. -// This means not enforcing the Legacy Symantec PKI policies outlined in -// https://security.googleblog.com/2017/09/chromes-plan-to-distrust-symantec.html -// or disabling SHA-1 for locally-installed trust anchors. -class AwSSLConfigService : public net::SSLConfigService { - public: - AwSSLConfigService() { - default_config_.symantec_enforcement_disabled = true; - default_config_.sha1_local_anchors_enabled = true; - } - - void GetSSLConfig(net::SSLConfig* config) override { - *config = default_config_; - } - - bool CanShareConnectionWithClientCerts( - const std::string& hostname) const override { - return false; - } - - private: - net::SSLConfig default_config_; -}; - } // namespace AwURLRequestContextGetter::AwURLRequestContextGetter( @@ -344,9 +320,18 @@ CreateAuthHandlerFactory(host_resolver.get())); builder.set_host_resolver(std::move(host_resolver)); - builder.set_ssl_config_service(std::make_unique<AwSSLConfigService>()); - url_request_context_ = builder.Build(); + + // For Android WebView, do not enforce policies that are not consistent with + // the underlying OS validator. + // This means not enforcing the Legacy Symantec PKI policies outlined in + // https://security.googleblog.com/2017/09/chromes-plan-to-distrust-symantec.html + // or disabling SHA-1 for locally-installed trust anchors. + net::CertVerifier::Config config; + config.enable_sha1_local_anchors = true; + config.disable_symantec_enforcement = true; + url_request_context_->cert_verifier()->SetConfig(config); + #if DCHECK_IS_ON() g_created_url_request_context_builder = true; #endif
diff --git a/android_webview/browser/net/aw_url_request_context_getter_unittest.cc b/android_webview/browser/net/aw_url_request_context_getter_unittest.cc index eb990c8..1812b99 100644 --- a/android_webview/browser/net/aw_url_request_context_getter_unittest.cc +++ b/android_webview/browser/net/aw_url_request_context_getter_unittest.cc
@@ -14,16 +14,22 @@ #include "content/public/common/url_constants.h" #include "content/public/test/test_browser_thread_bundle.h" #include "net/base/net_errors.h" +#include "net/base/test_completion_callback.h" +#include "net/cert/cert_verifier.h" +#include "net/cert/test_root_certs.h" #include "net/log/net_log.h" +#include "net/log/net_log_with_source.h" #include "net/proxy_resolution/proxy_config_service.h" #include "net/proxy_resolution/proxy_config_service_android.h" #include "net/proxy_resolution/proxy_resolution_service.h" -#include "net/ssl/ssl_config.h" -#include "net/ssl/ssl_config_service.h" +#include "net/test/cert_test_util.h" +#include "net/test/gtest_util.h" +#include "net/test/test_data_directory.h" #include "net/test/url_request/url_request_failed_job.h" #include "net/url_request/url_request_context.h" #include "net/url_request/url_request_job_factory.h" #include "testing/gtest/include/gtest/gtest.h" +#include "third_party/boringssl/src/include/openssl/pool.h" namespace android_webview { @@ -95,13 +101,33 @@ TEST_F(AwURLRequestContextGetterTest, SymantecPoliciesExempted) { net::URLRequestContext* context = getter_->GetURLRequestContext(); ASSERT_TRUE(context); - net::SSLConfigService* config_service = context->ssl_config_service(); - ASSERT_TRUE(config_service); - net::SSLConfig config; - EXPECT_FALSE(config.symantec_enforcement_disabled); - config_service->GetSSLConfig(&config); - EXPECT_TRUE(config.symantec_enforcement_disabled); + scoped_refptr<net::X509Certificate> cert = + net::CreateCertificateChainFromFile(net::GetTestCertsDirectory(), + "www.ahrn.com.pem", + net::X509Certificate::FORMAT_AUTO); + ASSERT_TRUE(cert); + ASSERT_EQ(2u, cert->intermediate_buffers().size()); + + scoped_refptr<net::X509Certificate> root = + net::X509Certificate::CreateFromBuffer( + bssl::UpRef(cert->intermediate_buffers().back()), {}); + ASSERT_TRUE(root); + net::ScopedTestRoot test_root(root.get()); + + net::CertVerifyResult result; + int flags = 0; + net::TestCompletionCallback callback; + std::unique_ptr<net::CertVerifier::Request> request; + int error = context->cert_verifier()->Verify( + net::CertVerifier::RequestParams(cert, "www.ahrn.com", flags, + std::string(), net::CertificateList()), + nullptr, &result, callback.callback(), &request, net::NetLogWithSource()); + EXPECT_THAT(error, net::test::IsError(net::ERR_IO_PENDING)); + EXPECT_TRUE(request); + + error = callback.WaitForResult(); + EXPECT_THAT(error, net::test::IsError(net::OK)); } // Tests that SHA-1 is still allowed for locally-installed trust anchors, @@ -110,13 +136,36 @@ TEST_F(AwURLRequestContextGetterTest, SHA1LocalAnchorsAllowed) { net::URLRequestContext* context = getter_->GetURLRequestContext(); ASSERT_TRUE(context); - net::SSLConfigService* config_service = context->ssl_config_service(); - ASSERT_TRUE(config_service); - net::SSLConfig config; - EXPECT_FALSE(config.sha1_local_anchors_enabled); - config_service->GetSSLConfig(&config); - EXPECT_TRUE(config.sha1_local_anchors_enabled); + net::CertificateList certs; + ASSERT_TRUE(net::LoadCertificateFiles( + {"weak_digest_sha1_ee.pem", "weak_digest_sha1_intermediate.pem", + "weak_digest_sha1_root.pem"}, + &certs)); + ASSERT_EQ(3u, certs.size()); + + std::vector<bssl::UniquePtr<CRYPTO_BUFFER>> intermediates; + intermediates.push_back(bssl::UpRef(certs[1]->cert_buffer())); + scoped_refptr<net::X509Certificate> cert = + net::X509Certificate::CreateFromBuffer( + bssl::UpRef(certs[0]->cert_buffer()), std::move(intermediates)); + ASSERT_TRUE(cert); + + net::ScopedTestRoot test_root(certs[2].get()); + + net::CertVerifyResult result; + int flags = 0; + net::TestCompletionCallback callback; + std::unique_ptr<net::CertVerifier::Request> request; + int error = context->cert_verifier()->Verify( + net::CertVerifier::RequestParams(cert, "127.0.0.1", flags, std::string(), + net::CertificateList()), + nullptr, &result, callback.callback(), &request, net::NetLogWithSource()); + EXPECT_THAT(error, net::test::IsError(net::ERR_IO_PENDING)); + EXPECT_TRUE(request); + + error = callback.WaitForResult(); + EXPECT_THAT(error, net::test::IsError(net::OK)); } } // namespace android_webview
diff --git a/android_webview/javatests/AndroidManifest.xml b/android_webview/javatests/AndroidManifest.xml index b4f2aa0..5838eae 100644 --- a/android_webview/javatests/AndroidManifest.xml +++ b/android_webview/javatests/AndroidManifest.xml
@@ -7,8 +7,7 @@ <uses-sdk android:minSdkVersion="21" android:targetSdkVersion="23" /> <instrumentation android:name="org.chromium.base.test.BaseChromiumAndroidJUnitRunner" android:targetPackage="org.chromium.android_webview.shell" - android:label="Tests for org.chromium.android_webview" - chromium-junit4="true"/> + android:label="Tests for org.chromium.android_webview"/> <uses-permission android:name="android.permission.RUN_INSTRUMENTATION" /> <uses-permission android:name="android.permission.ACCESS_MOCK_LOCATION" /> <uses-permission android:name="android.permission.READ_LOGS"/>
diff --git a/android_webview/lib/aw_main_delegate.cc b/android_webview/lib/aw_main_delegate.cc index a028297..a7281fd 100644 --- a/android_webview/lib/aw_main_delegate.cc +++ b/android_webview/lib/aw_main_delegate.cc
@@ -36,6 +36,7 @@ #include "components/safe_browsing/android/safe_browsing_api_handler_bridge.h" #include "components/services/heap_profiling/public/cpp/allocator_shim.h" #include "components/spellcheck/spellcheck_buildflags.h" +#include "components/viz/common/features.h" #include "content/public/browser/android/browser_media_player_manager_register.h" #include "content/public/browser/browser_main_runner.h" #include "content/public/browser/browser_thread.h" @@ -161,6 +162,10 @@ CommandLineHelper::AddDisabledFeature(*cl, features::kWebPayments.name); + // WebView isn't compatible with OOP-D. + CommandLineHelper::AddDisabledFeature(*cl, + features::kVizDisplayCompositor.name); + // WebView does not support AndroidOverlay yet for video overlays. CommandLineHelper::AddDisabledFeature(*cl, media::kUseAndroidOverlay.name);
diff --git a/android_webview/tools/automated_ui_tests/javatests/AndroidManifest.xml b/android_webview/tools/automated_ui_tests/javatests/AndroidManifest.xml index 1e022dfd..9a683b9 100644 --- a/android_webview/tools/automated_ui_tests/javatests/AndroidManifest.xml +++ b/android_webview/tools/automated_ui_tests/javatests/AndroidManifest.xml
@@ -21,6 +21,5 @@ <instrumentation android:name="android.support.test.runner.AndroidJUnitRunner" android:targetPackage="org.chromium.webview_ui_test" - android:label="Tests for org.chromium.webview_ui_test" - chromium-junit4="true"/> + android:label="Tests for org.chromium.webview_ui_test"/> </manifest>
diff --git a/android_webview/tools/system_webview_shell/layout_tests/AndroidManifest.xml b/android_webview/tools/system_webview_shell/layout_tests/AndroidManifest.xml index 9757c8f9..f0198a6 100644 --- a/android_webview/tools/system_webview_shell/layout_tests/AndroidManifest.xml +++ b/android_webview/tools/system_webview_shell/layout_tests/AndroidManifest.xml
@@ -32,6 +32,5 @@ <instrumentation android:name="android.support.test.runner.AndroidJUnitRunner" android:targetPackage="org.chromium.webview_shell" - android:label="Layout tests for org.chromium.webview_shell" - chromium-junit4="true"/> + android:label="Layout tests for org.chromium.webview_shell"/> </manifest>
diff --git a/android_webview/tools/system_webview_shell/page_cycler/AndroidManifest.xml b/android_webview/tools/system_webview_shell/page_cycler/AndroidManifest.xml index f5e1752..7a79f2e 100644 --- a/android_webview/tools/system_webview_shell/page_cycler/AndroidManifest.xml +++ b/android_webview/tools/system_webview_shell/page_cycler/AndroidManifest.xml
@@ -21,6 +21,5 @@ <instrumentation android:name="org.chromium.base.test.BaseChromiumAndroidJUnitRunner" android:targetPackage="org.chromium.webview_shell" - android:label="Page cycler for org.chromium.webview_shell" - chromium-junit4="true"/> + android:label="Page cycler for org.chromium.webview_shell"/> </manifest>
diff --git a/ash/app_list/views/search_box_view.cc b/ash/app_list/views/search_box_view.cc index 71f3662..7fbedc6 100644 --- a/ash/app_list/views/search_box_view.cc +++ b/ash/app_list/views/search_box_view.cc
@@ -95,6 +95,8 @@ view_delegate_(view_delegate), app_list_view_(app_list_view), is_new_style_launcher_enabled_(features::IsNewStyleLauncherEnabled()), + is_app_list_search_autocomplete_enabled_( + features::IsAppListSearchAutocompleteEnabled()), weak_ptr_factory_(this) { set_is_tablet_mode(app_list_view->is_tablet_mode()); if (features::IsZeroStateSuggestionsEnabled()) @@ -359,6 +361,9 @@ } void SearchBoxView::ProcessAutocomplete() { + if (!is_app_list_search_autocomplete_enabled_) + return; + // Current non-autocompleted text. const base::string16& user_typed_text = search_box()->text().substr(0, highlight_range_.start()); @@ -418,11 +423,17 @@ } void SearchBoxView::AcceptAutocompleteText() { + if (!is_app_list_search_autocomplete_enabled_) + return; + if (highlight_range_.start() != search_box()->text().length()) ContentsChanged(search_box(), search_box()->text()); } void SearchBoxView::AcceptOneCharInAutocompleteText() { + if (!is_app_list_search_autocomplete_enabled_) + return; + highlight_range_.set_start(highlight_range_.start() + 1); highlight_range_.set_end(search_box()->text().length()); const base::string16 original_text = search_box()->text(); @@ -434,6 +445,9 @@ } void SearchBoxView::ClearAutocompleteText() { + if (!is_app_list_search_autocomplete_enabled_) + return; + search_box()->SetText( search_box()->text().substr(0, highlight_range_.start())); } @@ -441,7 +455,8 @@ void SearchBoxView::ContentsChanged(views::Textfield* sender, const base::string16& new_contents) { // Update autocomplete text highlight range to track user typed text. - highlight_range_.set_start(search_box()->text().length()); + if (is_app_list_search_autocomplete_enabled_) + highlight_range_.set_start(search_box()->text().length()); search_box::SearchBoxViewBase::ContentsChanged(sender, new_contents); app_list_view_->SetStateFromSearchBoxView( IsSearchBoxTrimmedQueryEmpty(), true /*triggered_by_contents_change*/); @@ -449,6 +464,9 @@ void SearchBoxView::SetAutocompleteText( const base::string16& autocomplete_text) { + if (!is_app_list_search_autocomplete_enabled_) + return; + const base::string16& current_text = search_box()->text(); // Currrent text is a prefix of autocomplete text. DCHECK(base::StartsWith(autocomplete_text, current_text, @@ -469,7 +487,8 @@ bool SearchBoxView::HandleKeyEvent(views::Textfield* sender, const ui::KeyEvent& key_event) { if (search_box()->HasFocus() && is_search_box_active() && - !search_box()->text().empty()) { + !search_box()->text().empty() && + is_app_list_search_autocomplete_enabled_) { // If the search box has no text in it currently, autocomplete should not // work. last_key_pressed_ = key_event.key_code();
diff --git a/ash/app_list/views/search_box_view.h b/ash/app_list/views/search_box_view.h index 3728e49..2bce637 100644 --- a/ash/app_list/views/search_box_view.h +++ b/ash/app_list/views/search_box_view.h
@@ -146,6 +146,9 @@ // True if new style launcher feature is enabled. const bool is_new_style_launcher_enabled_; + // True if app list search autocomplete is enabled. + const bool is_app_list_search_autocomplete_enabled_; + base::WeakPtrFactory<SearchBoxView> weak_ptr_factory_; DISALLOW_COPY_AND_ASSIGN(SearchBoxView);
diff --git a/ash/app_list/views/search_box_view_unittest.cc b/ash/app_list/views/search_box_view_unittest.cc index 53bdc17..3ea9897e 100644 --- a/ash/app_list/views/search_box_view_unittest.cc +++ b/ash/app_list/views/search_box_view_unittest.cc
@@ -17,6 +17,7 @@ #include "ash/public/cpp/app_list/vector_icons/vector_icons.h" #include "base/macros.h" #include "base/strings/utf_string_conversions.h" +#include "base/test/scoped_feature_list.h" #include "ui/chromeos/search_box/search_box_constants.h" #include "ui/chromeos/search_box/search_box_view_delegate.h" #include "ui/gfx/image/image_skia.h" @@ -286,9 +287,40 @@ *actual_icon.bitmap())); } +class SearchBoxViewAutocompleteTest + : public SearchBoxViewTest, + public ::testing::WithParamInterface<ui::KeyboardCode> { + public: + SearchBoxViewAutocompleteTest() = default; + ~SearchBoxViewAutocompleteTest() override = default; + + // Overridden from testing::Test + void SetUp() override { + scoped_feature_list_.InitWithFeatures( + {features::kEnableAppListSearchAutocomplete}, {}); + SearchBoxViewTest::SetUp(); + } + + ui::KeyboardCode key_code() const { return GetParam(); } + + private: + base::test::ScopedFeatureList scoped_feature_list_; + + DISALLOW_COPY_AND_ASSIGN(SearchBoxViewAutocompleteTest); +}; + +INSTANTIATE_TEST_CASE_P(, + SearchBoxViewAutocompleteTest, + ::testing::Values(ui::VKEY_TAB, + ui::VKEY_LEFT, + ui::VKEY_RIGHT, + ui::VKEY_UP, + ui::VKEY_DOWN)); + // Tests that autocomplete suggestions are consistent with top SearchResult list // titles. -TEST_F(SearchBoxViewTest, SearchBoxAutocompletesTopListResultTitle) { +TEST_F(SearchBoxViewAutocompleteTest, + SearchBoxAutocompletesTopListResultTitle) { // Add two SearchResults, one with higher ranking. Initialize their title // field to a non-empty string. CreateSearchResult(ash::SearchResultDisplayType::kList, 1.0, @@ -307,7 +339,8 @@ // Tests that autocomplete suggestions are consistent with top SearchResult tile // titles. -TEST_F(SearchBoxViewTest, SearchBoxAutocompletesTopTileResultTitle) { +TEST_F(SearchBoxViewAutocompleteTest, + SearchBoxAutocompletesTopTileResultTitle) { // Add two SearchResults, one with higher ranking. Initialize their title // field to a non-empty string. CreateSearchResult(ash::SearchResultDisplayType::kTile, 1.0, @@ -326,7 +359,8 @@ // Tests that autocomplete suggestions are consistent with top SearchResult list // details. -TEST_F(SearchBoxViewTest, SearchBoxAutocompletesTopListResultDetails) { +TEST_F(SearchBoxViewAutocompleteTest, + SearchBoxAutocompletesTopListResultDetails) { // Add two SearchResults, one with higher ranking. Initialize their details // field to a non-empty string. CreateSearchResult(ash::SearchResultDisplayType::kList, 1.0, base::string16(), @@ -345,7 +379,8 @@ // Tests that autocomplete suggestions are consistent with top SearchResult tile // details. -TEST_F(SearchBoxViewTest, SearchBoxAutocompletesTopTileResultDetails) { +TEST_F(SearchBoxViewAutocompleteTest, + SearchBoxAutocompletesTopTileResultDetails) { // Add two SearchResults, one with higher ranking. Initialize their details // field to a non-empty string. CreateSearchResult(ash::SearchResultDisplayType::kTile, 1.0, base::string16(), @@ -364,7 +399,8 @@ // Tests that SearchBoxView's textfield text does not autocomplete if the top // result title or details do not have a matching prefix. -TEST_F(SearchBoxViewTest, SearchBoxDoesNotAutocompleteWrongCharacter) { +TEST_F(SearchBoxViewAutocompleteTest, + SearchBoxDoesNotAutocompleteWrongCharacter) { // Add a search result with non-empty details and title fields. CreateSearchResult(ash::SearchResultDisplayType::kList, 1.0, base::ASCIIToUTF16("title"), @@ -379,7 +415,7 @@ // Tests that autocomplete suggestion will remain if next key in the suggestion // is typed. -TEST_F(SearchBoxViewTest, SearchBoxAutocompletesAcceptsNextChar) { +TEST_F(SearchBoxViewAutocompleteTest, SearchBoxAutocompletesAcceptsNextChar) { // Add a search result with a non-empty title field. CreateSearchResult(ash::SearchResultDisplayType::kList, 1.0, base::ASCIIToUTF16("hello world!"), base::string16()); @@ -403,7 +439,8 @@ // Tests that only the autocomplete suggestion text is deleted after hitting // backspace. -TEST_F(SearchBoxViewTest, SearchBoxDeletesAutocompleteTextOnlyAfterBackspace) { +TEST_F(SearchBoxViewAutocompleteTest, + SearchBoxDeletesAutocompleteTextOnlyAfterBackspace) { // Add a search result with a non-empty title field. CreateSearchResult(ash::SearchResultDisplayType::kList, 1.0, base::ASCIIToUTF16("hello world!"), base::string16()); @@ -422,26 +459,6 @@ EXPECT_EQ(view()->search_box()->text(), base::ASCIIToUTF16("he")); } -class SearchBoxViewAutocompleteTest - : public SearchBoxViewTest, - public ::testing::WithParamInterface<ui::KeyboardCode> { - public: - SearchBoxViewAutocompleteTest() = default; - ~SearchBoxViewAutocompleteTest() = default; - ui::KeyboardCode key_code() const { return GetParam(); } - - private: - DISALLOW_COPY_AND_ASSIGN(SearchBoxViewAutocompleteTest); -}; - -INSTANTIATE_TEST_CASE_P(, - SearchBoxViewAutocompleteTest, - ::testing::Values(ui::VKEY_TAB, - ui::VKEY_LEFT, - ui::VKEY_RIGHT, - ui::VKEY_UP, - ui::VKEY_DOWN)); - // Tests that autocomplete suggestion is accepted and displayed in SearchModel // after hitting certain control keys. TEST_P(SearchBoxViewAutocompleteTest,
diff --git a/ash/ash_strings.grd b/ash/ash_strings.grd index be8f0c7..f084d87 100644 --- a/ash/ash_strings.grd +++ b/ash/ash_strings.grd
@@ -1733,9 +1733,30 @@ <message name="IDS_ASH_ASSISTANT_MULTI_DEVICE_HOTWORD_LOSS" desc="Message shown in Assistant UI when we have detected hotword but are answering on another device."> Answering on another device </message> - <message name="IDS_ASH_ASSISTANT_WHATS_ON_MY_SCREEN" desc="Message shown on suggestion chip in Assistant UI to initiate a contextual search for results matching screen content."> + <message name="IDS_ASH_ASSISTANT_CHIP_IM_BORED" desc="Message shown on suggestion chip in Assistant UI to initiate a query for something amusing, a joke for example."> + I'm bored + </message> + <message name="IDS_ASH_ASSISTANT_CHIP_OPEN_FILES" desc="Message shown on suggestion chip in Assistant UI to initiate a query to open files."> + Open files + </message> + <message name="IDS_ASH_ASSISTANT_CHIP_PLAY_MUSIC" desc="Message shown on suggestion chip in Assistant UI to initiate a query to play music."> + Play music + </message> + <message name="IDS_ASH_ASSISTANT_CHIP_SEND_AN_EMAIL" desc="Message shown on suggestion chip in Assistant UI to initiate a query to send an email."> + Send an email + </message> + <message name="IDS_ASH_ASSISTANT_CHIP_WHAT_CAN_YOU_DO" desc="Message shown on suggestion chip in Assistant UI to initiate a query for Assistant capabilities."> + What can you do? + </message> + <message name="IDS_ASH_ASSISTANT_CHIP_WHATS_ON_MY_CALENDAR" desc="Message shown on suggestion chip in Assistant UI to initiate a query for upcoming calendar events."> + What's on my calendar? + </message> + <message name="IDS_ASH_ASSISTANT_CHIP_WHATS_ON_MY_SCREEN" desc="Message shown on suggestion chip in Assistant UI to initiate a contextual search for results matching screen content."> What's on my screen? </message> + <message name="IDS_ASH_ASSISTANT_CHIP_WHATS_THE_WEATHER" desc="Message shown on suggestion chip in Assistant UI to initiate a query for the current weather."> + What's the weather? + </message> <message name="IDS_ASH_MESSAGE_CENTER_UNLOCK_TO_PERFORM_ACTION" desc="The short message to encourage user to unlock the device so that Chrome OS can perform the notification action selected by user after unlocking."> Unlock device to perform the notification action </message>
diff --git a/ash/assistant/ui/assistant_container_view.cc b/ash/assistant/ui/assistant_container_view.cc index e49d589..3e3680e 100644 --- a/ash/assistant/ui/assistant_container_view.cc +++ b/ash/assistant/ui/assistant_container_view.cc
@@ -17,6 +17,8 @@ #include "ash/shell.h" #include "ash/wm/tablet_mode/tablet_mode_controller.h" #include "base/strings/utf_string_conversions.h" +#include "ui/aura/window.h" +#include "ui/aura/window_targeter.h" #include "ui/display/display.h" #include "ui/display/screen.h" #include "ui/gfx/animation/slide_animation.h" @@ -40,6 +42,32 @@ // Animation. constexpr int kResizeAnimationDurationMs = 250; +// Window properties. +DEFINE_UI_CLASS_PROPERTY_KEY(bool, kOnlyAllowMouseClickEvents, false); + +// AssistantContainerEventTargeter --------------------------------------------- + +class AssistantContainerEventTargeter : public aura::WindowTargeter { + public: + AssistantContainerEventTargeter() = default; + ~AssistantContainerEventTargeter() override = default; + + // aura::WindowTargeter: + bool SubtreeShouldBeExploredForEvent(aura::Window* window, + const ui::LocatedEvent& event) override { + if (window->GetProperty(kOnlyAllowMouseClickEvents)) { + if (event.type() != ui::ET_MOUSE_PRESSED && + event.type() != ui::ET_MOUSE_RELEASED) { + return false; + } + } + return aura::WindowTargeter::SubtreeShouldBeExploredForEvent(window, event); + } + + private: + DISALLOW_COPY_AND_ASSIGN(AssistantContainerEventTargeter); +}; + // AssistantContainerLayout ---------------------------------------------------- // The AssistantContainerLayout calculates preferred size to fit the largest @@ -142,6 +170,16 @@ assistant_controller_->ui_controller()->RemoveModelObserver(this); } +// static +void AssistantContainerView::OnlyAllowMouseClickEvents(aura::Window* window) { + window->SetProperty(kOnlyAllowMouseClickEvents, true); +} + +void AssistantContainerView::AddedToWidget() { + GetWidget()->GetNativeWindow()->SetEventTargeter( + std::make_unique<AssistantContainerEventTargeter>()); +} + void AssistantContainerView::ChildPreferredSizeChanged(views::View* child) { PreferredSizeChanged(); }
diff --git a/ash/assistant/ui/assistant_container_view.h b/ash/assistant/ui/assistant_container_view.h index 4b372da..a5145ae 100644 --- a/ash/assistant/ui/assistant_container_view.h +++ b/ash/assistant/ui/assistant_container_view.h
@@ -11,14 +11,14 @@ #include "ui/gfx/animation/animation_delegate.h" #include "ui/views/bubble/bubble_dialog_delegate_view.h" -namespace gfx { -class SlideAnimation; -} // namespace gfx - namespace aura { class Window; } // namespace aura +namespace gfx { +class SlideAnimation; +} // namespace gfx + namespace ash { class AssistantController; @@ -34,7 +34,13 @@ explicit AssistantContainerView(AssistantController* assistant_controller); ~AssistantContainerView() override; + // Instructs the event targeter for the Assistant window to only allow mouse + // click events to reach the specified |window|. All other events will not + // be explored by |window|'s subtree for handling. + static void OnlyAllowMouseClickEvents(aura::Window* window); + // views::BubbleDialogDelegateView: + void AddedToWidget() override; int GetDialogButtons() const override; void ChildPreferredSizeChanged(views::View* child) override; void PreferredSizeChanged() override;
diff --git a/ash/assistant/ui/main_stage/ui_element_container_view.cc b/ash/assistant/ui/main_stage/ui_element_container_view.cc index 035a3c0..daa08f5 100644 --- a/ash/assistant/ui/main_stage/ui_element_container_view.cc +++ b/ash/assistant/ui/main_stage/ui_element_container_view.cc
@@ -8,18 +8,24 @@ #include "ash/assistant/assistant_interaction_controller.h" #include "ash/assistant/model/assistant_response.h" #include "ash/assistant/model/assistant_ui_element.h" +#include "ash/assistant/ui/assistant_container_view.h" #include "ash/assistant/ui/assistant_ui_constants.h" #include "ash/assistant/ui/main_stage/assistant_text_element_view.h" #include "ash/assistant/util/animation_util.h" #include "ash/public/cpp/app_list/answer_card_contents_registry.h" +#include "ash/shell.h" #include "base/base64.h" #include "base/callback.h" #include "base/time/time.h" #include "base/unguessable_token.h" #include "ui/aura/window.h" +#include "ui/aura/window_tree_host.h" #include "ui/compositor/callback_layer_animation_observer.h" #include "ui/compositor/layer_animation_element.h" #include "ui/compositor/layer_animator.h" +#include "ui/events/event.h" +#include "ui/events/event_sink.h" +#include "ui/events/event_utils.h" #include "ui/views/controls/native/native_view_host.h" #include "ui/views/layout/box_layout.h" #include "ui/views/layout/fill_layout.h" @@ -50,6 +56,31 @@ // WebContents. constexpr char kDataUriPrefix[] = "data:text/html;base64,"; +// Helpers --------------------------------------------------------------------- + +void CreateAndSendMouseClick(aura::WindowTreeHost* host, + const gfx::Point& location_in_pixels) { + ui::MouseEvent press_event(ui::ET_MOUSE_PRESSED, location_in_pixels, + location_in_pixels, ui::EventTimeForNow(), + ui::EF_LEFT_MOUSE_BUTTON, + ui::EF_LEFT_MOUSE_BUTTON); + + // Send an ET_MOUSE_PRESSED event. + ui::EventDispatchDetails details = + host->event_sink()->OnEventFromSource(&press_event); + + if (details.dispatcher_destroyed) + return; + + ui::MouseEvent release_event(ui::ET_MOUSE_RELEASED, location_in_pixels, + location_in_pixels, ui::EventTimeForNow(), + ui::EF_LEFT_MOUSE_BUTTON, + ui::EF_LEFT_MOUSE_BUTTON); + + // Send an ET_MOUSE_RELEASED event. + ignore_result(host->event_sink()->OnEventFromSource(&release_event)); +} + // CardElementViewHolder ------------------------------------------------------- // This class uses a child widget to host a view for a card element that has an @@ -84,6 +115,49 @@ // views::NativeViewHost: const char* GetClassName() const override { return "CardElementViewHolder"; } + void OnGestureEvent(ui::GestureEvent* event) override { + // We need to route GESTURE_TAP events to our Assistant card because links + // should be tappable. The Assistant card window will not receive gesture + // events so we convert the gesture into analogous mouse events. + if (event->type() != ui::ET_GESTURE_TAP) { + views::View::OnGestureEvent(event); + return; + } + + // Consume the original event. + event->StopPropagation(); + event->SetHandled(); + + aura::Window* root_window = GetWidget()->GetNativeWindow()->GetRootWindow(); + + // Get the appropriate event location in pixels. + gfx::Point location_in_pixels = event->location(); + ConvertPointToScreen(this, &location_in_pixels); + aura::WindowTreeHost* host = root_window->GetHost(); + host->ConvertDIPToPixels(&location_in_pixels); + + wm::CursorManager* cursor_manager = Shell::Get()->cursor_manager(); + + // We want to prevent the cursor from changing its visibility during our + // mouse events because we are actually handling a gesture. To accomplish + // this, we cache the cursor's visibility and lock it in its current state. + const bool visible = cursor_manager->IsCursorVisible(); + cursor_manager->LockCursor(); + + CreateAndSendMouseClick(host, location_in_pixels); + + // Restore the original cursor visibility that may have changed during our + // sequence of mouse events. This change would not have been perceivable to + // the user since it occurred within our lock. + if (visible) + cursor_manager->ShowCursor(); + else + cursor_manager->HideCursor(); + + // Release our cursor lock. + cursor_manager->UnlockCursor(); + } + // views::ViewObserver: void OnViewPreferredSizeChanged(views::View* view) override { contents_view_->SetPreferredSize(view->GetPreferredSize()); @@ -92,6 +166,20 @@ void Attach() { views::NativeViewHost::Attach(child_widget_->GetNativeView()); + + aura::Window* const top_level_window = native_view()->GetToplevelWindow(); + + // Find the window for the Assistant card. + aura::Window* window = native_view(); + while (window->parent() != top_level_window) + window = window->parent(); + + // The Assistant card window will consume all events that enter it. This + // prevents us from being able to scroll the native view hierarchy + // vertically. As such, we need to prevent the Assistant card window from + // receiving events it doesn't need. It needs mouse click events for + // handling links. + AssistantContainerView::OnlyAllowMouseClickEvents(window); } private:
diff --git a/ash/display/display_configuration_controller.cc b/ash/display/display_configuration_controller.cc index 4b73eb8..223e6b0 100644 --- a/ash/display/display_configuration_controller.cc +++ b/ash/display/display_configuration_controller.cc
@@ -37,6 +37,8 @@ kScreenRotationAnimatorKey, nullptr); +bool g_disable_animator_for_test = false; + } // namespace namespace ash { @@ -58,6 +60,11 @@ DISALLOW_COPY_AND_ASSIGN(DisplayChangeLimiter); }; +// static +void DisplayConfigurationController::DisableAnimatorForTest() { + g_disable_animator_for_test = true; +} + DisplayConfigurationController::DisplayConfigurationController( display::DisplayManager* display_manager, WindowTreeHostManager* window_tree_host_manager) @@ -67,7 +74,8 @@ window_tree_host_manager_->AddObserver(this); if (chromeos::IsRunningAsSystemCompositor()) limiter_.reset(new DisplayChangeLimiter); - display_animator_.reset(new DisplayAnimator()); + if (!g_disable_animator_for_test) + display_animator_.reset(new DisplayAnimator()); } DisplayConfigurationController::~DisplayConfigurationController() { @@ -129,12 +137,16 @@ if (display_manager_->IsDisplayIdValid(display_id)) { if (GetTargetRotation(display_id) == rotation) return; - ScreenRotationAnimator* screen_rotation_animator = - GetScreenRotationAnimatorForDisplay(display_id); - screen_rotation_animator->Rotate(rotation, source, mode); - } else { - display_manager_->SetDisplayRotation(display_id, rotation, source); + if (display_animator_) { + ScreenRotationAnimator* screen_rotation_animator = + GetScreenRotationAnimatorForDisplay(display_id); + screen_rotation_animator->Rotate(rotation, source, mode); + return; + } } + // Invalid |display_id| or animator is disabled; call + // DisplayManager::SetDisplayRotation directly. + display_manager_->SetDisplayRotation(display_id, rotation, source); } display::Display::Rotation DisplayConfigurationController::GetTargetRotation( @@ -172,10 +184,11 @@ // Protected -void DisplayConfigurationController::ResetAnimatorForTest() { - if (!display_animator_) - return; - display_animator_.reset(); +void DisplayConfigurationController::SetAnimatorForTest(bool enable) { + if (display_animator_ && !enable) + display_animator_.reset(); + else if (!display_animator_ && enable) + display_animator_.reset(new DisplayAnimator()); } void DisplayConfigurationController::SetScreenRotationAnimatorForTest(
diff --git a/ash/display/display_configuration_controller.h b/ash/display/display_configuration_controller.h index f4f39970..0a1e999 100644 --- a/ash/display/display_configuration_controller.h +++ b/ash/display/display_configuration_controller.h
@@ -78,11 +78,13 @@ // WindowTreeHostManager::Observer void OnDisplayConfigurationChanged() override; + static void DisableAnimatorForTest(); + protected: friend class DisplayConfigurationControllerTestApi; - // Allow tests to skip animations. - void ResetAnimatorForTest(); + // Allow tests to enable or disable animations. + void SetAnimatorForTest(bool enable); void SetScreenRotationAnimatorForTest( int64_t display_id,
diff --git a/ash/display/display_configuration_controller_test_api.cc b/ash/display/display_configuration_controller_test_api.cc index 07ff30c..a15c127 100644 --- a/ash/display/display_configuration_controller_test_api.cc +++ b/ash/display/display_configuration_controller_test_api.cc
@@ -13,8 +13,8 @@ DisplayConfigurationController* controller) : controller_(controller) {} -void DisplayConfigurationControllerTestApi::DisableDisplayAnimator() { - controller_->ResetAnimatorForTest(); +void DisplayConfigurationControllerTestApi::SetDisplayAnimator(bool enable) { + controller_->SetAnimatorForTest(enable); } ScreenRotationAnimator*
diff --git a/ash/display/display_configuration_controller_test_api.h b/ash/display/display_configuration_controller_test_api.h index 1fc2d5b2..0a4e6f4 100644 --- a/ash/display/display_configuration_controller_test_api.h +++ b/ash/display/display_configuration_controller_test_api.h
@@ -22,7 +22,7 @@ DisplayConfigurationController* controller); // Wrapper functions for DisplayConfigurationController. - void DisableDisplayAnimator(); + void SetDisplayAnimator(bool enable); ScreenRotationAnimator* GetScreenRotationAnimatorForDisplay( int64_t display_id);
diff --git a/ash/display/display_configuration_controller_unittest.cc b/ash/display/display_configuration_controller_unittest.cc index 4de0111..84751b6d 100644 --- a/ash/display/display_configuration_controller_unittest.cc +++ b/ash/display/display_configuration_controller_unittest.cc
@@ -68,7 +68,8 @@ display::Display display = display::Screen::GetScreen()->GetPrimaryDisplay(); DisplayConfigurationController* controller = Shell::Get()->display_configuration_controller(); - DisplayConfigurationControllerTestApi testapi(controller); + // AshTestHelper disables display animations; re-enable them. + DisplayConfigurationControllerTestApi(controller).SetDisplayAnimator(true); controller->SetDisplayRotation( display.id(), display::Display::ROTATE_180, display::Display::RotationSource::USER, @@ -83,7 +84,8 @@ display::Display display = display::Screen::GetScreen()->GetPrimaryDisplay(); DisplayConfigurationController* controller = Shell::Get()->display_configuration_controller(); - DisplayConfigurationControllerTestApi testapi(controller); + // AshTestHelper disables display animations; re-enable them. + DisplayConfigurationControllerTestApi(controller).SetDisplayAnimator(true); controller->SetDisplayRotation( display.id(), display::Display::ROTATE_180, display::Display::RotationSource::USER,
diff --git a/ash/display/window_tree_host_manager_unittest.cc b/ash/display/window_tree_host_manager_unittest.cc index 71ccd4c..f22a895 100644 --- a/ash/display/window_tree_host_manager_unittest.cc +++ b/ash/display/window_tree_host_manager_unittest.cc
@@ -245,52 +245,12 @@ DISALLOW_COPY_AND_ASSIGN(WindowTreeHostManagerShutdownTest); }; -class StartupHelper : public TestShellDelegate, - public WindowTreeHostManager::Observer { - public: - StartupHelper() : displays_initialized_(false) {} - ~StartupHelper() override = default; - - // ShellDelegate: - void PreInit() override { - Shell::Get()->window_tree_host_manager()->AddObserver(this); - } - - // WindowTreeHostManager::Observer: - void OnDisplaysInitialized() override { - DCHECK(!displays_initialized_); - displays_initialized_ = true; - } - - bool displays_initialized() const { return displays_initialized_; } - - private: - bool displays_initialized_; - - DISALLOW_COPY_AND_ASSIGN(StartupHelper); -}; - class WindowTreeHostManagerStartupTest : public AshTestBase, public TestHelper { public: - WindowTreeHostManagerStartupTest() - : TestHelper(this), startup_helper_(new StartupHelper) {} + WindowTreeHostManagerStartupTest() : TestHelper(this) {} ~WindowTreeHostManagerStartupTest() override = default; - // AshTestBase: - void SetUp() override { - ash_test_helper()->set_test_shell_delegate(startup_helper_); - AshTestBase::SetUp(); - } - void TearDown() override { - Shell::Get()->window_tree_host_manager()->RemoveObserver(startup_helper_); - AshTestBase::TearDown(); - } - - const StartupHelper* startup_helper() const { return startup_helper_; } - private: - StartupHelper* startup_helper_; // Owned by ash::Shell. - DISALLOW_COPY_AND_ASSIGN(WindowTreeHostManagerStartupTest); }; @@ -401,7 +361,10 @@ } TEST_F(WindowTreeHostManagerStartupTest, Startup) { - EXPECT_TRUE(startup_helper()->displays_initialized()); + // Ensure that WindowTreeHostManager was initialized and created at least one + // root window. + aura::Window::Windows root_windows = Shell::GetAllRootWindows(); + EXPECT_FALSE(root_windows.empty()); } TEST_F(WindowTreeHostManagerTest, SecondaryDisplayLayout) {
diff --git a/ash/login/ui/lock_contents_view.cc b/ash/login/ui/lock_contents_view.cc index 1a19f07..949c168 100644 --- a/ash/login/ui/lock_contents_view.cc +++ b/ash/login/ui/lock_contents_view.cc
@@ -1250,12 +1250,72 @@ LoginBigUserView* opt_to_hide, bool animate) { DCHECK(to_update); - UpdateAuthForAuthUser(to_update->auth_user(), - opt_to_hide ? opt_to_hide->auth_user() : nullptr, - animate); - UpdateAuthForPublicAccount( - to_update->public_account(), - opt_to_hide ? opt_to_hide->public_account() : nullptr, animate); + + auto capture_animation_state_pre_layout = [&](LoginBigUserView* view) { + if (!animate || !view) + return; + if (view->auth_user()) + view->auth_user()->CaptureStateForAnimationPreLayout(); + }; + + auto enable_auth = [&](LoginBigUserView* view) { + DCHECK(view); + if (view->auth_user()) { + UserState* state = FindStateForUser( + view->auth_user()->current_user()->basic_user_info->account_id); + uint32_t to_update_auth; + if (state->force_online_sign_in) { + to_update_auth = LoginAuthUserView::AUTH_ONLINE_SIGN_IN; + } else if (state->disable_auth) { + to_update_auth = LoginAuthUserView::AUTH_DISABLED; + } else { + to_update_auth = LoginAuthUserView::AUTH_PASSWORD; + keyboard::KeyboardController* keyboard_controller = + GetKeyboardController(); + const bool is_keyboard_visible = + keyboard_controller ? keyboard_controller->IsKeyboardVisible() + : false; + if (state->show_pin && !is_keyboard_visible) + to_update_auth |= LoginAuthUserView::AUTH_PIN; + if (state->enable_tap_auth) + to_update_auth |= LoginAuthUserView::AUTH_TAP; + if (state->fingerprint_state != + mojom::FingerprintUnlockState::UNAVAILABLE) { + to_update_auth |= LoginAuthUserView::AUTH_FINGERPRINT; + } + } + view->auth_user()->SetAuthMethods(to_update_auth, state->show_pin); + } else if (view->public_account()) { + view->public_account()->SetAuthEnabled(true /*enabled*/, animate); + } + }; + + auto disable_auth = [&](LoginBigUserView* view) { + if (!view) + return; + if (view->auth_user()) { + view->auth_user()->SetAuthMethods(LoginAuthUserView::AUTH_NONE, + false /*can_use_pin*/); + } else if (view->public_account()) { + view->public_account()->SetAuthEnabled(false /*enabled*/, animate); + } + }; + + auto apply_animation_post_layout = [&](LoginBigUserView* view) { + if (!animate || !view) + return; + if (view->auth_user()) + view->auth_user()->ApplyAnimationPostLayout(); + }; + + // The high-level layout flow: + capture_animation_state_pre_layout(to_update); + capture_animation_state_pre_layout(opt_to_hide); + enable_auth(to_update); + disable_auth(opt_to_hide); + Layout(); + apply_animation_post_layout(to_update); + apply_animation_post_layout(opt_to_hide); } void LockContentsView::SwapToBigUser(int user_index) { @@ -1558,74 +1618,6 @@ return view; } -void LockContentsView::UpdateAuthForPublicAccount( - LoginPublicAccountUserView* opt_to_update, - LoginPublicAccountUserView* opt_to_hide, - bool animate) { - if (opt_to_update) - opt_to_update->SetAuthEnabled(true /*enabled*/, animate); - if (opt_to_hide) - opt_to_hide->SetAuthEnabled(false /*enabled*/, animate); - - Layout(); -} - -void LockContentsView::UpdateAuthForAuthUser(LoginAuthUserView* opt_to_update, - LoginAuthUserView* opt_to_hide, - bool animate) { - // Capture animation metadata before we changing state. - if (animate) { - if (opt_to_update) - opt_to_update->CaptureStateForAnimationPreLayout(); - if (opt_to_hide) - opt_to_hide->CaptureStateForAnimationPreLayout(); - } - - // Update auth methods for |opt_to_update|. - if (opt_to_update) { - UserState* state = FindStateForUser( - opt_to_update->current_user()->basic_user_info->account_id); - uint32_t to_update_auth; - if (state->force_online_sign_in) { - to_update_auth = LoginAuthUserView::AUTH_ONLINE_SIGN_IN; - } else if (state->disable_auth) { - to_update_auth = LoginAuthUserView::AUTH_DISABLED; - } else { - to_update_auth = LoginAuthUserView::AUTH_PASSWORD; - keyboard::KeyboardController* keyboard_controller = - GetKeyboardController(); - const bool is_keyboard_visible = - keyboard_controller ? keyboard_controller->IsKeyboardVisible() - : false; - if (state->show_pin && !is_keyboard_visible) - to_update_auth |= LoginAuthUserView::AUTH_PIN; - if (state->enable_tap_auth) - to_update_auth |= LoginAuthUserView::AUTH_TAP; - if (state->fingerprint_state != - mojom::FingerprintUnlockState::UNAVAILABLE) { - to_update_auth |= LoginAuthUserView::AUTH_FINGERPRINT; - } - } - opt_to_update->SetAuthMethods(to_update_auth, state->show_pin); - } - - // Disable auth on |opt_to_hide|. - if (opt_to_hide) { - opt_to_hide->SetAuthMethods(LoginAuthUserView::AUTH_NONE, - false /*can_use_pin*/); - } - - Layout(); - - // Apply animations. - if (animate) { - if (opt_to_update) - opt_to_update->ApplyAnimationPostLayout(); - if (opt_to_hide) - opt_to_hide->ApplyAnimationPostLayout(); - } -} - void LockContentsView::SetDisplayStyle(DisplayStyle style) { const bool show_expanded_view = style == DisplayStyle::kExclusivePublicAccountExpandedView;
diff --git a/ash/login/ui/lock_contents_view.h b/ash/login/ui/lock_contents_view.h index ebaf06e..8e39cc7 100644 --- a/ash/login/ui/lock_contents_view.h +++ b/ash/login/ui/lock_contents_view.h
@@ -47,7 +47,6 @@ class LoginBubble; class LoginDetachableBaseModel; class LoginExpandedPublicAccountView; -class LoginPublicAccountUserView; class LoginUserView; class NoteActionLaunchButton; class ScrollableUsersListView; @@ -324,18 +323,6 @@ const std::vector<mojom::LoginUserInfoPtr>& users, LoginDisplayStyle display_style); - // Update the auth enable/disabled for public account user. - // Both |opt_to_update| and |opt_to_hide| could be null. - void UpdateAuthForPublicAccount(LoginPublicAccountUserView* opt_to_update, - LoginPublicAccountUserView* opt_to_hide, - bool animate); - - // Update the auth method for regular user. - // Both |opt_to_update| and |opt_to_hide| could be null. - void UpdateAuthForAuthUser(LoginAuthUserView* opt_to_update, - LoginAuthUserView* opt_to_hide, - bool animate); - // Change the visibility of child views based on the |style|. void SetDisplayStyle(DisplayStyle style);
diff --git a/ash/login/ui/scrollable_users_list_view.h b/ash/login/ui/scrollable_users_list_view.h index 587f4576..a4e1a05e 100644 --- a/ash/login/ui/scrollable_users_list_view.h +++ b/ash/login/ui/scrollable_users_list_view.h
@@ -81,11 +81,11 @@ static GradientParams BuildForStyle(LoginDisplayStyle style); // Start color for drawing linear gradient. - SkColor color_from; + SkColor color_from = SK_ColorTRANSPARENT; // End color for drawing linear gradient. - SkColor color_to; + SkColor color_to = SK_ColorTRANSPARENT; // Height of linear gradient. - SkScalar height; + SkScalar height = 0; }; // Updates visibility of scroll bar thumb. Called when hover state changes.
diff --git a/ash/public/cpp/app_list/app_list_features.cc b/ash/public/cpp/app_list/app_list_features.cc index 718605b..7f92783 100644 --- a/ash/public/cpp/app_list/app_list_features.cc +++ b/ash/public/cpp/app_list/app_list_features.cc
@@ -31,6 +31,8 @@ base::FEATURE_DISABLED_BY_DEFAULT}; const base::Feature kEnableZeroStateSuggestions{ "EnableZeroStateSuggestions", base::FEATURE_DISABLED_BY_DEFAULT}; +const base::Feature kEnableAppListSearchAutocomplete{ + "EnableAppListSearchAutocomplete", base::FEATURE_DISABLED_BY_DEFAULT}; bool IsAnswerCardEnabled() { // Not using local static variable to allow tests to change this value. @@ -74,6 +76,10 @@ return base::FeatureList::IsEnabled(kEnableZeroStateSuggestions); } +bool IsAppListSearchAutocompleteEnabled() { + return base::FeatureList::IsEnabled(kEnableAppListSearchAutocomplete); +} + std::string AnswerServerUrl() { const std::string experiment_url = base::GetFieldTrialParamValueByFeature(kEnableAnswerCard, "ServerUrl");
diff --git a/ash/public/cpp/app_list/app_list_features.h b/ash/public/cpp/app_list/app_list_features.h index 7510838..3654e8b 100644 --- a/ash/public/cpp/app_list/app_list_features.h +++ b/ash/public/cpp/app_list/app_list_features.h
@@ -53,6 +53,9 @@ // Enables the feature to display zero state suggestions. ASH_PUBLIC_EXPORT extern const base::Feature kEnableZeroStateSuggestions; +// Enables the feature to autocomplete text typed in the AppList search box. +ASH_PUBLIC_EXPORT extern const base::Feature kEnableAppListSearchAutocomplete; + bool ASH_PUBLIC_EXPORT IsAnswerCardEnabled(); bool ASH_PUBLIC_EXPORT IsAppShortcutSearchEnabled(); bool ASH_PUBLIC_EXPORT IsBackgroundBlurEnabled(); @@ -63,6 +66,7 @@ bool ASH_PUBLIC_EXPORT IsNewStyleLauncherEnabled(); bool ASH_PUBLIC_EXPORT IsContinueReadingEnabled(); bool ASH_PUBLIC_EXPORT IsZeroStateSuggestionsEnabled(); +bool ASH_PUBLIC_EXPORT IsAppListSearchAutocompleteEnabled(); std::string ASH_PUBLIC_EXPORT AnswerServerUrl(); std::string ASH_PUBLIC_EXPORT AnswerServerQuerySuffix();
diff --git a/ash/rotator/screen_rotation_animator_unittest.cc b/ash/rotator/screen_rotation_animator_unittest.cc index da4b58bf..dbfc3adb 100644 --- a/ash/rotator/screen_rotation_animator_unittest.cc +++ b/ash/rotator/screen_rotation_animator_unittest.cc
@@ -635,11 +635,13 @@ &ScreenRotationAnimatorSmoothAnimationTest::QuitWaitForCopyCallback, base::Unretained(this)), run_loop_->QuitWhenIdleClosure()); + TestScreenRotationAnimator* animator = animator_.get(); - DisplayConfigurationControllerTestApi( - Shell::Get()->display_configuration_controller()) - .SetScreenRotationAnimatorForDisplay(internal_display_id, - std::move(animator_)); + DisplayConfigurationControllerTestApi testapi( + Shell::Get()->display_configuration_controller()); + testapi.SetDisplayAnimator(true); + testapi.SetScreenRotationAnimatorForDisplay(internal_display_id, + std::move(animator_)); ScreenOrientationControllerTestApi( Shell::Get()->screen_orientation_controller()) .SetDisplayRotation(display::Display::ROTATE_90,
diff --git a/ash/shell.cc b/ash/shell.cc index 6fd9c12b..74036b357 100644 --- a/ash/shell.cc +++ b/ash/shell.cc
@@ -1051,8 +1051,6 @@ cursor_manager_ = std::make_unique<CursorManager>(base::WrapUnique(native_cursor_manager_)); - shell_delegate_->PreInit(); - // In CLASSIC mode, |initial_display_prefs| contains the synchronously // loaded display pref values. Otherwise |initial_display_prefs| is null and // the pref values will be loaded once |local_state_| is available. (Any store
diff --git a/ash/shell/shell_delegate_impl.cc b/ash/shell/shell_delegate_impl.cc index 427f3c5..e0f7c454 100644 --- a/ash/shell/shell_delegate_impl.cc +++ b/ash/shell/shell_delegate_impl.cc
@@ -21,8 +21,6 @@ return true; } -void ShellDelegateImpl::PreInit() {} - std::unique_ptr<keyboard::KeyboardUI> ShellDelegateImpl::CreateKeyboardUI() { return std::make_unique<TestKeyboardUI>(); }
diff --git a/ash/shell/shell_delegate_impl.h b/ash/shell/shell_delegate_impl.h index 00b94a479..a076f3bae 100644 --- a/ash/shell/shell_delegate_impl.h +++ b/ash/shell/shell_delegate_impl.h
@@ -25,7 +25,6 @@ // ShellDelegate: bool CanShowWindowForUser(aura::Window* window) const override; - void PreInit() override; std::unique_ptr<keyboard::KeyboardUI> CreateKeyboardUI() override; std::unique_ptr<ScreenshotDelegate> CreateScreenshotDelegate() override; AccessibilityDelegate* CreateAccessibilityDelegate() override;
diff --git a/ash/shell_delegate.h b/ash/shell_delegate.h index 8e0dfc23..5375565 100644 --- a/ash/shell_delegate.h +++ b/ash/shell_delegate.h
@@ -39,10 +39,6 @@ // user. virtual bool CanShowWindowForUser(aura::Window* window) const = 0; - // Called before processing |Shell::Init()| so that the delegate - // can perform tasks necessary before the shell is initialized. - virtual void PreInit() = 0; - // Create a shell-specific keyboard::KeyboardUI. virtual std::unique_ptr<keyboard::KeyboardUI> CreateKeyboardUI() = 0;
diff --git a/ash/shell_delegate_mash.cc b/ash/shell_delegate_mash.cc index a686ac9..708a464 100644 --- a/ash/shell_delegate_mash.cc +++ b/ash/shell_delegate_mash.cc
@@ -52,10 +52,6 @@ return true; } -void ShellDelegateMash::PreInit() { - NOTIMPLEMENTED_LOG_ONCE(); -} - std::unique_ptr<keyboard::KeyboardUI> ShellDelegateMash::CreateKeyboardUI() { NOTIMPLEMENTED_LOG_ONCE(); return nullptr;
diff --git a/ash/shell_delegate_mash.h b/ash/shell_delegate_mash.h index 2b06e77..ed20500 100644 --- a/ash/shell_delegate_mash.h +++ b/ash/shell_delegate_mash.h
@@ -19,7 +19,6 @@ // ShellDelegate: bool CanShowWindowForUser(aura::Window* window) const override; - void PreInit() override; std::unique_ptr<keyboard::KeyboardUI> CreateKeyboardUI() override; std::unique_ptr<ScreenshotDelegate> CreateScreenshotDelegate() override; AccessibilityDelegate* CreateAccessibilityDelegate() override;
diff --git a/ash/test/ash_test_helper.cc b/ash/test/ash_test_helper.cc index 00d5818..658cf80 100644 --- a/ash/test/ash_test_helper.cc +++ b/ash/test/ash_test_helper.cc
@@ -279,7 +279,7 @@ .DisableChangeDisplayUponHostResize(); DisplayConfigurationControllerTestApi( shell->display_configuration_controller()) - .DisableDisplayAnimator(); + .SetDisplayAnimator(false); app_list_test_helper_ = std::make_unique<AppListTestHelper>();
diff --git a/ash/test_shell_delegate.cc b/ash/test_shell_delegate.cc index 595a0c1..4efc0cd4 100644 --- a/ash/test_shell_delegate.cc +++ b/ash/test_shell_delegate.cc
@@ -21,8 +21,6 @@ return true; } -void TestShellDelegate::PreInit() {} - std::unique_ptr<keyboard::KeyboardUI> TestShellDelegate::CreateKeyboardUI() { return std::make_unique<TestKeyboardUI>(); }
diff --git a/ash/test_shell_delegate.h b/ash/test_shell_delegate.h index f40ee11..033232be 100644 --- a/ash/test_shell_delegate.h +++ b/ash/test_shell_delegate.h
@@ -19,7 +19,6 @@ // Overridden from ShellDelegate: bool CanShowWindowForUser(aura::Window* window) const override; - void PreInit() override; std::unique_ptr<keyboard::KeyboardUI> CreateKeyboardUI() override; std::unique_ptr<ScreenshotDelegate> CreateScreenshotDelegate() override; AccessibilityDelegate* CreateAccessibilityDelegate() override;
diff --git a/base/BUILD.gn b/base/BUILD.gn index 5ea64942..afd66c3 100644 --- a/base/BUILD.gn +++ b/base/BUILD.gn
@@ -1305,6 +1305,14 @@ } } + if (use_clang_coverage) { + # Call-sites use this conditional on the CLANG_COVERAGE macro, for clarity. + sources += [ + "test/clang_coverage.cc", + "test/clang_coverage.h", + ] + } + # Allow more direct string conversions on platforms with native utf8 # strings if (is_mac || is_ios || is_chromeos || is_chromecast || is_fuchsia) {
diff --git a/base/android/android_image_reader_abi.h b/base/android/android_image_reader_abi.h index c81087f..2c24d86 100644 --- a/base/android/android_image_reader_abi.h +++ b/base/android/android_image_reader_abi.h
@@ -41,7 +41,7 @@ enum AIMAGE_FORMATS { AIMAGE_FORMAT_YUV_420_888 = 0x23, - IMAGE_FORMAT_PRIVATE = 0x22 + AIMAGE_FORMAT_PRIVATE = 0x22 }; using pAImage_delete = void (*)(AImage* image); @@ -68,11 +68,12 @@ AImageReader_ImageCallback onImageAvailable; } AImageReader_ImageListener; -using pAImageReader_new = media_status_t (*)(int32_t width, - int32_t height, - int32_t format, - int32_t maxImages, - AImageReader** reader); +using pAImageReader_newWithUsage = media_status_t (*)(int32_t width, + int32_t height, + int32_t format, + uint64_t usage, + int32_t maxImages, + AImageReader** reader); using pAImageReader_setImageListener = media_status_t (*)(AImageReader* reader,
diff --git a/base/android/android_image_reader_compat.cc b/base/android/android_image_reader_compat.cc index 0b08c17..30b0fde4 100644 --- a/base/android/android_image_reader_compat.cc +++ b/base/android/android_image_reader_compat.cc
@@ -61,7 +61,7 @@ LOAD_FUNCTION(libmediandk, AImage_getHardwareBuffer); LOAD_FUNCTION(libmediandk, AImage_getWidth); LOAD_FUNCTION(libmediandk, AImage_getHeight); - LOAD_FUNCTION(libmediandk, AImageReader_new); + LOAD_FUNCTION(libmediandk, AImageReader_newWithUsage); LOAD_FUNCTION(libmediandk, AImageReader_setImageListener); LOAD_FUNCTION(libmediandk, AImageReader_delete); LOAD_FUNCTION(libmediandk, AImageReader_getWindow); @@ -102,12 +102,15 @@ return AImage_getHeight_(image, height); } -media_status_t AndroidImageReader::AImageReader_new(int32_t width, - int32_t height, - int32_t format, - int32_t maxImages, - AImageReader** reader) { - return AImageReader_new_(width, height, format, maxImages, reader); +media_status_t AndroidImageReader::AImageReader_newWithUsage( + int32_t width, + int32_t height, + int32_t format, + uint64_t usage, + int32_t maxImages, + AImageReader** reader) { + return AImageReader_newWithUsage_(width, height, format, usage, maxImages, + reader); } media_status_t AndroidImageReader::AImageReader_setImageListener(
diff --git a/base/android/android_image_reader_compat.h b/base/android/android_image_reader_compat.h index 5d5d881..093b6fd7 100644 --- a/base/android/android_image_reader_compat.h +++ b/base/android/android_image_reader_compat.h
@@ -35,11 +35,12 @@ AHardwareBuffer** buffer); media_status_t AImage_getWidth(const AImage* image, int32_t* width); media_status_t AImage_getHeight(const AImage* image, int32_t* height); - media_status_t AImageReader_new(int32_t width, - int32_t height, - int32_t format, - int32_t maxImages, - AImageReader** reader); + media_status_t AImageReader_newWithUsage(int32_t width, + int32_t height, + int32_t format, + uint64_t usage, + int32_t maxImages, + AImageReader** reader); media_status_t AImageReader_setImageListener( AImageReader* reader, AImageReader_ImageListener* listener); @@ -63,7 +64,7 @@ pAImage_getHardwareBuffer AImage_getHardwareBuffer_; pAImage_getWidth AImage_getWidth_; pAImage_getHeight AImage_getHeight_; - pAImageReader_new AImageReader_new_; + pAImageReader_newWithUsage AImageReader_newWithUsage_; pAImageReader_setImageListener AImageReader_setImageListener_; pAImageReader_delete AImageReader_delete_; pAImageReader_getWindow AImageReader_getWindow_;
diff --git a/base/debug/debugger_posix.cc b/base/debug/debugger_posix.cc index b62bf01..150a7d8 100644 --- a/base/debug/debugger_posix.cc +++ b/base/debug/debugger_posix.cc
@@ -18,6 +18,7 @@ #include <vector> #include "base/macros.h" +#include "base/test/clang_coverage.h" #include "base/threading/platform_thread.h" #include "base/time/time.h" #include "build/build_config.h" @@ -246,6 +247,10 @@ #endif void BreakDebugger() { +#if defined(CLANG_COVERAGE) + WriteClangCoverageProfile(); +#endif + // NOTE: This code MUST be async-signal safe (it's used by in-process // stack dumping signal handler). NO malloc or stdio is allowed here.
diff --git a/base/debug/debugger_win.cc b/base/debug/debugger_win.cc index a1d86e4..b1f1ecc3 100644 --- a/base/debug/debugger_win.cc +++ b/base/debug/debugger_win.cc
@@ -7,6 +7,8 @@ #include <stdlib.h> #include <windows.h> +#include "base/test/clang_coverage.h" + namespace base { namespace debug { @@ -15,6 +17,10 @@ } void BreakDebugger() { +#if defined(CLANG_COVERAGE) + WriteClangCoverageProfile(); +#endif + if (IsDebugUISuppressed()) _exit(1);
diff --git a/base/files/file_util_win.cc b/base/files/file_util_win.cc index e81757f..6ae2331 100644 --- a/base/files/file_util_win.cc +++ b/base/files/file_util_win.cc
@@ -598,8 +598,8 @@ AssertBlockingAllowed(); // If the path exists, we've succeeded if it's a directory, failed otherwise. - const wchar_t* full_path_str = full_path.value().c_str(); - DWORD fileattr = ::GetFileAttributes(full_path_str); + const wchar_t* const full_path_str = full_path.value().c_str(); + const DWORD fileattr = ::GetFileAttributes(full_path_str); if (fileattr != INVALID_FILE_ATTRIBUTES) { if ((fileattr & FILE_ATTRIBUTE_DIRECTORY) != 0) { DVLOG(1) << "CreateDirectory(" << full_path_str << "), " @@ -608,9 +608,9 @@ } DLOG(WARNING) << "CreateDirectory(" << full_path_str << "), " << "conflicts with existing file."; - if (error) { + if (error) *error = File::FILE_ERROR_NOT_A_DIRECTORY; - } + ::SetLastError(ERROR_FILE_EXISTS); return false; } @@ -621,37 +621,33 @@ // directories starting with the highest-level missing parent. FilePath parent_path(full_path.DirName()); if (parent_path.value() == full_path.value()) { - if (error) { + if (error) *error = File::FILE_ERROR_NOT_FOUND; - } + ::SetLastError(ERROR_FILE_NOT_FOUND); return false; } if (!CreateDirectoryAndGetError(parent_path, error)) { DLOG(WARNING) << "Failed to create one of the parent directories."; - if (error) { - DCHECK(*error != File::FILE_OK); - } + DCHECK(!error || *error != File::FILE_OK); return false; } - if (!::CreateDirectory(full_path_str, NULL)) { - DWORD error_code = ::GetLastError(); - if (error_code == ERROR_ALREADY_EXISTS && DirectoryExists(full_path)) { - // This error code ERROR_ALREADY_EXISTS doesn't indicate whether we - // were racing with someone creating the same directory, or a file - // with the same path. If DirectoryExists() returns true, we lost the - // race to create the same directory. - return true; - } else { - if (error) - *error = File::OSErrorToFileError(error_code); - DLOG(WARNING) << "Failed to create directory " << full_path_str - << ", last error is " << error_code << "."; - return false; - } - } else { + if (::CreateDirectory(full_path_str, NULL)) + return true; + + const DWORD error_code = ::GetLastError(); + if (error_code == ERROR_ALREADY_EXISTS && DirectoryExists(full_path)) { + // This error code ERROR_ALREADY_EXISTS doesn't indicate whether we were + // racing with someone creating the same directory, or a file with the same + // path. If DirectoryExists() returns true, we lost the race to create the + // same directory. return true; } + if (error) + *error = File::OSErrorToFileError(error_code); + ::SetLastError(error_code); + DPLOG(WARNING) << "Failed to create directory " << full_path_str; + return false; } bool NormalizeFilePath(const FilePath& path, FilePath* real_path) {
diff --git a/base/process/process_fuchsia.cc b/base/process/process_fuchsia.cc index ea6fea94..0c669b57 100644 --- a/base/process/process_fuchsia.cc +++ b/base/process/process_fuchsia.cc
@@ -12,6 +12,7 @@ #include "base/fuchsia/default_job.h" #include "base/fuchsia/fuchsia_logging.h" #include "base/strings/stringprintf.h" +#include "base/test/clang_coverage.h" namespace base { @@ -88,6 +89,9 @@ // static void Process::TerminateCurrentProcessImmediately(int exit_code) { +#if defined(CLANG_COVERAGE) + WriteClangCoverageProfile(); +#endif _exit(exit_code); }
diff --git a/base/process/process_posix.cc b/base/process/process_posix.cc index 08a918c..f52a627 100644 --- a/base/process/process_posix.cc +++ b/base/process/process_posix.cc
@@ -15,6 +15,7 @@ #include "base/logging.h" #include "base/posix/eintr_wrapper.h" #include "base/process/kill.h" +#include "base/test/clang_coverage.h" #include "base/threading/thread_restrictions.h" #include "build/build_config.h" @@ -271,6 +272,9 @@ // static void Process::TerminateCurrentProcessImmediately(int exit_code) { +#if defined(CLANG_COVERAGE) + WriteClangCoverageProfile(); +#endif _exit(exit_code); }
diff --git a/base/process/process_win.cc b/base/process/process_win.cc index a2e614c5..0c1a68a 100644 --- a/base/process/process_win.cc +++ b/base/process/process_win.cc
@@ -8,6 +8,7 @@ #include "base/logging.h" #include "base/numerics/safe_conversions.h" #include "base/process/kill.h" +#include "base/test/clang_coverage.h" #include "base/threading/thread_restrictions.h" #include <windows.h> @@ -85,6 +86,9 @@ // static void Process::TerminateCurrentProcessImmediately(int exit_code) { +#if defined(CLANG_COVERAGE) + WriteClangCoverageProfile(); +#endif ::TerminateProcess(GetCurrentProcess(), exit_code); // There is some ambiguity over whether the call above can return. Rather than // hitting confusing crashes later on we should crash right here.
diff --git a/base/sampling_heap_profiler/module_cache_win.cc b/base/sampling_heap_profiler/module_cache_win.cc index ca5b280..5ac407bc 100644 --- a/base/sampling_heap_profiler/module_cache_win.cc +++ b/base/sampling_heap_profiler/module_cache_win.cc
@@ -35,7 +35,11 @@ std::string GetBuildIDForModule(HMODULE module_handle) { GUID guid; DWORD age; - win::PEImage(module_handle).GetDebugId(&guid, &age, /* pdb_file= */ nullptr); + if (!win::PEImage(module_handle) + .GetDebugId(&guid, &age, /* pdb_filename= */ nullptr, + /* pdb_filename_length= */ nullptr)) { + return std::string(); + } const int kGUIDSize = 39; string16 build_id; int result =
diff --git a/base/test/clang_coverage.cc b/base/test/clang_coverage.cc new file mode 100644 index 0000000..33f823e --- /dev/null +++ b/base/test/clang_coverage.cc
@@ -0,0 +1,25 @@ +// 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 "base/test/clang_coverage.h" + +#include "base/no_destructor.h" +#include "base/synchronization/lock.h" + +extern "C" int __llvm_profile_dump(void); + +namespace base { + +void WriteClangCoverageProfile() { + // __llvm_profile_dump() guarantees that it will not dump coverage information + // if it is being called twice or more. However, it is not thread safe, as it + // is supposed to be called from atexit() handler rather than being called + // directly from random places. Since we have to call it ourselves, we must + // ensure thread safety in order to prevent duplication of coverage counters. + static base::NoDestructor<base::Lock> lock; + base::AutoLock auto_lock(*lock); + __llvm_profile_dump(); +} + +} // namespace base
diff --git a/base/test/clang_coverage.h b/base/test/clang_coverage.h new file mode 100644 index 0000000..44337f1f --- /dev/null +++ b/base/test/clang_coverage.h
@@ -0,0 +1,21 @@ +// 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 BASE_TEST_CLANG_COVERAGE_H_ +#define BASE_TEST_CLANG_COVERAGE_H_ + +namespace base { + +// Write out the accumulated code coverage profile to the configured file. +// This is used internally by e.g. base::Process and FATAL logging, to cause +// coverage information to be stored even when performing an "immediate" exit +// (or triggering a debug crash), where the automatic at-exit writer will not +// be invoked. +// This call is thread-safe, and will write profiling data at-most-once. +// Call-sites invoke this API only if the CLANG_COVERAGE macro is defined. +void WriteClangCoverageProfile(); + +} // namespace base + +#endif // BASE_TEST_CLANG_COVERAGE_H_
diff --git a/base/win/pe_image.cc b/base/win/pe_image.cc index 4705348..ec1c4734f 100644 --- a/base/win/pe_image.cc +++ b/base/win/pe_image.cc
@@ -102,16 +102,13 @@ } DWORD PEImage::GetImageDirectoryEntrySize(UINT directory) const { - PIMAGE_NT_HEADERS nt_headers = GetNTHeaders(); - - return nt_headers->OptionalHeader.DataDirectory[directory].Size; + const IMAGE_DATA_DIRECTORY* const entry = GetDataDirectory(directory); + return entry ? entry->Size : 0; } PVOID PEImage::GetImageDirectoryEntryAddr(UINT directory) const { - PIMAGE_NT_HEADERS nt_headers = GetNTHeaders(); - - return RVAToAddr( - nt_headers->OptionalHeader.DataDirectory[directory].VirtualAddress); + const IMAGE_DATA_DIRECTORY* const entry = GetDataDirectory(directory); + return entry ? RVAToAddr(entry->VirtualAddress) : nullptr; } PIMAGE_SECTION_HEADER PEImage::GetImageSectionFromAddr(PVOID address) const { @@ -152,33 +149,47 @@ return ret; } -bool PEImage::GetDebugId(LPGUID guid, LPDWORD age, LPCSTR* pdb_filename) const { +bool PEImage::GetDebugId(LPGUID guid, + LPDWORD age, + LPCSTR* pdb_filename, + size_t* pdb_filename_length) const { DWORD debug_directory_size = GetImageDirectoryEntrySize(IMAGE_DIRECTORY_ENTRY_DEBUG); PIMAGE_DEBUG_DIRECTORY debug_directory = reinterpret_cast<PIMAGE_DEBUG_DIRECTORY>( GetImageDirectoryEntryAddr(IMAGE_DIRECTORY_ENTRY_DEBUG)); + if (!debug_directory) + return false; - size_t directory_count = - debug_directory_size / sizeof(IMAGE_DEBUG_DIRECTORY); - + size_t directory_count = debug_directory_size / sizeof(IMAGE_DEBUG_DIRECTORY); for (size_t index = 0; index < directory_count; ++index) { - if (debug_directory[index].Type == IMAGE_DEBUG_TYPE_CODEVIEW) { - PdbInfo* pdb_info = reinterpret_cast<PdbInfo*>( - RVAToAddr(debug_directory[index].AddressOfRawData)); - if (pdb_info->Signature != kPdbInfoSignature) { - // Unsupported PdbInfo signature - return false; - } + const IMAGE_DEBUG_DIRECTORY& entry = debug_directory[index]; + if (entry.Type != IMAGE_DEBUG_TYPE_CODEVIEW) + continue; // Unsupported debugging info format. + if (entry.SizeOfData < sizeof(PdbInfo)) + continue; // The data is too small to hold PDB info. + const PdbInfo* pdb_info = + reinterpret_cast<const PdbInfo*>(RVAToAddr(entry.AddressOfRawData)); + if (!pdb_info) + continue; // The data is not present in a mapped section. + if (pdb_info->Signature != kPdbInfoSignature) + continue; // Unsupported PdbInfo signature - if (guid) - *guid = pdb_info->Guid; - if (age) - *age = pdb_info->Age; - if (pdb_filename) - *pdb_filename = pdb_info->PdbFileName; - return true; + if (guid) + *guid = pdb_info->Guid; + if (age) + *age = pdb_info->Age; + if (pdb_filename) { + const size_t length_max = + entry.SizeOfData - offsetof(PdbInfo, PdbFileName); + const char* eos = pdb_info->PdbFileName; + for (const char* const end = pdb_info->PdbFileName + length_max; + eos < end && *eos; ++eos) + ; + *pdb_filename_length = eos - pdb_info->PdbFileName; + *pdb_filename = pdb_info->PdbFileName; } + return true; } return false; } @@ -209,6 +220,8 @@ PBYTE exports = reinterpret_cast<PBYTE>( GetImageDirectoryEntryAddr(IMAGE_DIRECTORY_ENTRY_EXPORT)); DWORD size = GetImageDirectoryEntrySize(IMAGE_DIRECTORY_ENTRY_EXPORT); + if (!exports || !size) + return NULL; // Check for forwarded exports as a special case. if (exports <= function && exports + size > function) @@ -288,7 +301,7 @@ DWORD size = GetImageDirectoryEntrySize(IMAGE_DIRECTORY_ENTRY_EXPORT); // Check if there are any exports at all. - if (NULL == directory || 0 == size) + if (!directory || !size) return true; PIMAGE_EXPORT_DIRECTORY exports = reinterpret_cast<PIMAGE_EXPORT_DIRECTORY>( @@ -340,12 +353,12 @@ bool PEImage::EnumRelocs(EnumRelocsFunction callback, PVOID cookie) const { PVOID directory = GetImageDirectoryEntryAddr(IMAGE_DIRECTORY_ENTRY_BASERELOC); DWORD size = GetImageDirectoryEntrySize(IMAGE_DIRECTORY_ENTRY_BASERELOC); - PIMAGE_BASE_RELOCATION base = reinterpret_cast<PIMAGE_BASE_RELOCATION>( - directory); - if (!directory) + if (!directory || !size) return true; + PIMAGE_BASE_RELOCATION base = + reinterpret_cast<PIMAGE_BASE_RELOCATION>(directory); while (size >= sizeof(IMAGE_BASE_RELOCATION) && base->SizeOfBlock && size >= base->SizeOfBlock) { PWORD reloc = reinterpret_cast<PWORD>(base + 1); @@ -429,11 +442,11 @@ PVOID directory = GetImageDirectoryEntryAddr( IMAGE_DIRECTORY_ENTRY_DELAY_IMPORT); DWORD size = GetImageDirectoryEntrySize(IMAGE_DIRECTORY_ENTRY_DELAY_IMPORT); - PImgDelayDescr delay_descriptor = reinterpret_cast<PImgDelayDescr>(directory); - if (directory == NULL || size == 0) + if (!directory || !size) return true; + PImgDelayDescr delay_descriptor = reinterpret_cast<PImgDelayDescr>(directory); for (; delay_descriptor->rvaHmod; delay_descriptor++) { PIMAGE_THUNK_DATA name_table; PIMAGE_THUNK_DATA iat; @@ -564,6 +577,23 @@ return reinterpret_cast<char*>(module_) + rva; } +const IMAGE_DATA_DIRECTORY* PEImage::GetDataDirectory(UINT directory) const { + PIMAGE_NT_HEADERS nt_headers = GetNTHeaders(); + + // Does the image report that it includes this directory entry? + if (directory >= nt_headers->OptionalHeader.NumberOfRvaAndSizes) + return nullptr; + + // Is there space for this directory entry in the optional header? + if (nt_headers->FileHeader.SizeOfOptionalHeader < + (offsetof(IMAGE_OPTIONAL_HEADER, DataDirectory) + + (directory + 1) * sizeof(IMAGE_DATA_DIRECTORY))) { + return nullptr; + } + + return &nt_headers->OptionalHeader.DataDirectory[directory]; +} + PVOID PEImageAsData::RVAToAddr(DWORD rva) const { if (rva == 0) return NULL;
diff --git a/base/win/pe_image.h b/base/win/pe_image.h index 3f8f868..cb13c0d 100644 --- a/base/win/pe_image.h +++ b/base/win/pe_image.h
@@ -109,10 +109,12 @@ // returns NULL if there is no such section. PIMAGE_SECTION_HEADER GetSectionHeader(UINT section) const; - // Returns the size of a given directory entry. + // Returns the size of a given directory entry or 0 if |directory| is out of + // bounds. DWORD GetImageDirectoryEntrySize(UINT directory) const; - // Returns the address of a given directory entry. + // Returns the address of a given directory entry or NULL if |directory| is + // out of bounds. PVOID GetImageDirectoryEntryAddr(UINT directory) const; // Returns the section header for a given address. @@ -130,10 +132,23 @@ // Returns the exports directory. PIMAGE_EXPORT_DIRECTORY GetExportDirectory() const; - // Returns the debug id (guid+age) and |pdb_filename|. Parameters are optional - // and can be null. |pdb_filename| is a direct reference to PEImage and - // doesn't not need to be freed. - bool GetDebugId(LPGUID guid, LPDWORD age, LPCSTR* pdb_filename) const; + // Retrieves the contents of the image's CodeView debug entry, returning true + // if such an entry is found and is within a section mapped into the current + // process's memory. |guid|, |age|, and |pdb_filename| are each optional and + // may be NULL. |pdb_filename_length| is mandatory if |pdb_filename| is not + // NULL, as the latter is populated with a direct reference to a string in the + // image that is is not guaranteed to be terminated (note: informal + // documentation indicates that it should be terminated, but the data is + // untrusted). Furthermore, owing to its nature of being a string in the + // image, it is only valid while the image is mapped into the process, and the + // caller is not responsible for freeing it. |pdb_filename_length| is + // populated with the string length of |pdb_filename| (not including a + // terminator) and must be used rather than relying on |pdb_filename| being + // properly terminated. + bool GetDebugId(LPGUID guid, + LPDWORD age, + LPCSTR* pdb_filename, + size_t* pdb_filename_length) const; // Returns a given export entry. // Use: e = image.GetExportEntry(f); @@ -227,6 +242,10 @@ bool ImageAddrToOnDiskOffset(LPVOID address, DWORD *on_disk_offset) const; private: + // Returns a pointer to a data directory, or NULL if |directory| is out of + // range. + const IMAGE_DATA_DIRECTORY* GetDataDirectory(UINT directory) const; + HMODULE module_; };
diff --git a/base/win/pe_image_unittest.cc b/base/win/pe_image_unittest.cc index 7890ce6..8091ea0 100644 --- a/base/win/pe_image_unittest.cc +++ b/base/win/pe_image_unittest.cc
@@ -4,6 +4,7 @@ // This file contains unit tests for PEImage. #include <algorithm> +#include <iterator> #include <vector> #include "base/files/file_path.h" @@ -203,6 +204,7 @@ // Test that we can get debug id out of a module. TEST(PEImageTest, GetDebugId) { + static constexpr char kPdbFileName[] = "advapi32.pdb"; ScopedNativeLibrary module(FilePath(L"advapi32.dll")); ASSERT_TRUE(module.is_valid()); @@ -210,11 +212,13 @@ GUID guid = {0}; DWORD age = 0; LPCSTR pdb_file = nullptr; - EXPECT_TRUE(pe.GetDebugId(&guid, &age, &pdb_file)); - EXPECT_STREQ("advapi32.pdb", pdb_file); + size_t pdb_file_length = 0; + EXPECT_TRUE(pe.GetDebugId(&guid, &age, &pdb_file, &pdb_file_length)); + EXPECT_EQ(pdb_file_length, std::size(kPdbFileName) - 1); + EXPECT_STREQ(pdb_file, kPdbFileName); // Should be valid to call without parameters. - EXPECT_TRUE(pe.GetDebugId(nullptr, nullptr, nullptr)); + EXPECT_TRUE(pe.GetDebugId(nullptr, nullptr, nullptr, nullptr)); GUID empty_guid = {0}; EXPECT_TRUE(!IsEqualGUID(empty_guid, guid));
diff --git a/build/android/pylib/instrumentation/instrumentation_test_instance.py b/build/android/pylib/instrumentation/instrumentation_test_instance.py index 452b259..809fce60 100644 --- a/build/android/pylib/instrumentation/instrumentation_test_instance.py +++ b/build/android/pylib/instrumentation/instrumentation_test_instance.py
@@ -568,15 +568,15 @@ self._test_package = self._test_apk.GetPackageName() all_instrumentations = self._test_apk.GetAllInstrumentations() all_junit3_runner_classes = [ - x for x in all_instrumentations if ('0xffffffff' not in x.get( - 'chromium-junit4', ''))] - all_junit4_test_runner_classes = [ x for x in all_instrumentations if ('0xffffffff' in x.get( - 'chromium-junit4', ''))] + 'chromium-junit3', ''))] + all_junit4_runner_classes = [ + x for x in all_instrumentations if ('0xffffffff' not in x.get( + 'chromium-junit3', ''))] if len(all_junit3_runner_classes) > 1: logging.warning('This test apk has more than one JUnit3 instrumentation') - if len(all_junit4_test_runner_classes) > 1: + if len(all_junit4_runner_classes) > 1: logging.warning('This test apk has more than one JUnit4 instrumentation') self._junit3_runner_class = ( @@ -584,8 +584,8 @@ if all_junit3_runner_classes else self.test_apk.GetInstrumentationName()) self._junit4_runner_class = ( - all_junit4_test_runner_classes[0]['android:name'] - if all_junit4_test_runner_classes else None) + all_junit4_runner_classes[0]['android:name'] + if all_junit4_runner_classes else None) if self._junit4_runner_class: if self._test_apk_incremental_install_json:
diff --git a/build/fuchsia/sdk.sha1 b/build/fuchsia/sdk.sha1 index 413cca9..4681c14 100644 --- a/build/fuchsia/sdk.sha1 +++ b/build/fuchsia/sdk.sha1
@@ -1 +1 @@ -1aedaa9ac17c5429b5cab2dde8407299ead0ac0d \ No newline at end of file +4f01773b4b548b1c26ad1825dd8fa9b791d9318c \ No newline at end of file
diff --git a/build/util/lastchange.py b/build/util/lastchange.py index 18521bc2..82c5f394 100755 --- a/build/util/lastchange.py +++ b/build/util/lastchange.py
@@ -214,8 +214,10 @@ sys.stdout.write(contents) else: if out_file: - if WriteIfChanged(out_file, contents): - with open(out_file + '.committime', 'w') as timefile: + committime_file = out_file + '.committime' + out_changed = WriteIfChanged(out_file, contents) + if out_changed or not os.path.exists(committime_file): + with open(committime_file, 'w') as timefile: timefile.write(str(version_info.timestamp)) if header: WriteIfChanged(header,
diff --git a/cc/animation/DEPS b/cc/animation/DEPS index 6afc308..80d05f0 100644 --- a/cc/animation/DEPS +++ b/cc/animation/DEPS
@@ -13,5 +13,6 @@ "+cc/trees/property_animation_state.h", "+cc/trees/property_tree.h", "+cc/trees/scroll_node.h", + "+cc/trees/transform_node.h", "+cc/trees/target_property.h", ]
diff --git a/cc/animation/animation_host_unittest.cc b/cc/animation/animation_host_unittest.cc index 680f7c8a..1b90600c 100644 --- a/cc/animation/animation_host_unittest.cc +++ b/cc/animation/animation_host_unittest.cc
@@ -13,6 +13,7 @@ #include "cc/test/animation_timelines_test_common.h" #include "cc/test/mock_layer_tree_mutator.h" #include "cc/trees/scroll_node.h" +#include "cc/trees/transform_node.h" #include "testing/gmock/include/gmock/gmock.h" #include "testing/gtest/include/gtest/gtest.h" @@ -258,14 +259,39 @@ void CreateScrollingNodeForElement(ElementId element_id, PropertyTrees* property_trees) { - ScrollNode node; - node.scrollable = true; - // Setup scroll dimention to be 100x100. - node.bounds = gfx::Size(200, 200); - node.container_bounds = gfx::Size(100, 100); + // A scrolling node in cc has a corresponding transform node (See + // |ScrollNode::transform_id|). This setup here creates both nodes and links + // them as they would normally be. This more complete setup is necessary here + // because ScrollTimelin depends on both nodes for its calculations. + TransformNode transform_node; + transform_node.scrolls = true; + transform_node.source_node_id = TransformTree::kRootNodeId; + int transform_node_id = + property_trees->transform_tree.Insert(transform_node, 0); + property_trees->element_id_to_transform_node_index[element_id] = + transform_node_id; - int node_id = property_trees->scroll_tree.Insert(node, 0); - property_trees->element_id_to_scroll_node_index[element_id] = node_id; + ScrollNode scroll_node; + scroll_node.scrollable = true; + // Setup scroll dimention to be 100x100. + scroll_node.bounds = gfx::Size(200, 200); + scroll_node.container_bounds = gfx::Size(100, 100); + scroll_node.element_id = element_id; + scroll_node.transform_id = transform_node_id; + + int scroll_node_id = property_trees->scroll_tree.Insert(scroll_node, 0); + property_trees->element_id_to_scroll_node_index[element_id] = scroll_node_id; +} + +void SetScrollOffset(PropertyTrees* property_trees, + ElementId element_id, + gfx::ScrollOffset offset) { + // Update both scroll and transform trees + property_trees->scroll_tree.SetScrollOffset(element_id, offset); + TransformNode* transform_node = + property_trees->transform_tree.FindNodeFromElementId(element_id); + transform_node->scroll_offset = offset; + transform_node->needs_local_transform_update = true; } TEST_F(AnimationHostTest, LayerTreeMutatorUpdateReflectsScrollAnimations) { @@ -281,20 +307,18 @@ PropertyTrees property_trees; property_trees.is_main_thread = false; + property_trees.is_active = true; CreateScrollingNodeForElement(element_id, &property_trees); - ScrollTree& scroll_tree = property_trees.scroll_tree; // Set an initial scroll value. - scroll_tree.SetScrollOffsetDeltaForTesting(element_id, - gfx::Vector2dF(10, 10)); + SetScrollOffset(&property_trees, element_id, gfx::ScrollOffset(10, 10)); scoped_refptr<MockAnimation> mock_scroll_animation( new MockAnimation(animation_id1)); EXPECT_CALL(*mock_scroll_animation, Tick(_)) .WillOnce(InvokeWithoutArgs([&]() { // Scroll to 20% of the max value. - scroll_tree.SetScrollOffsetDeltaForTesting(element_id, - gfx::Vector2dF(20, 20)); + SetScrollOffset(&property_trees, element_id, gfx::ScrollOffset(20, 20)); })); // Ensure scroll animation is ticking. @@ -326,7 +350,8 @@ // Ticking host should cause scroll animation to scroll which should also be // reflected in the input of the layer tree mutator in the same animation // frame. - host_impl_->TickAnimations(base::TimeTicks(), scroll_tree, false); + host_impl_->TickAnimations(base::TimeTicks(), property_trees.scroll_tree, + false); } } // namespace
diff --git a/cc/animation/scroll_timeline.cc b/cc/animation/scroll_timeline.cc index ee02fb5..63a56ec 100644 --- a/cc/animation/scroll_timeline.cc +++ b/cc/animation/scroll_timeline.cc
@@ -40,15 +40,18 @@ // The scroller may not be in the ScrollTree if it is not currently scrollable // (e.g. has overflow: visible). By the spec, return an unresolved time value. - if (!scroll_tree.FindNodeFromElementId(scroller_id)) + const ScrollNode* scroll_node = + scroll_tree.FindNodeFromElementId(scroller_id); + if (!scroll_node) return std::numeric_limits<double>::quiet_NaN(); - gfx::ScrollOffset offset = scroll_tree.current_scroll_offset(scroller_id); + gfx::ScrollOffset offset = + scroll_tree.GetPixelSnappedScrollOffset(scroll_node->id); DCHECK_GE(offset.x(), 0); DCHECK_GE(offset.y(), 0); - gfx::ScrollOffset scroll_dimensions = scroll_tree.MaxScrollOffset( - scroll_tree.FindNodeFromElementId(scroller_id)->id); + gfx::ScrollOffset scroll_dimensions = + scroll_tree.MaxScrollOffset(scroll_node->id); double current_offset = (orientation_ == Vertical) ? offset.y() : offset.x(); double max_offset = (orientation_ == Vertical) ? scroll_dimensions.y()
diff --git a/cc/animation/scroll_timeline_unittest.cc b/cc/animation/scroll_timeline_unittest.cc index 3fc5cbe..686ee56 100644 --- a/cc/animation/scroll_timeline_unittest.cc +++ b/cc/animation/scroll_timeline_unittest.cc
@@ -5,11 +5,49 @@ #include "cc/animation/scroll_timeline.h" #include "cc/trees/property_tree.h" #include "cc/trees/scroll_node.h" +#include "cc/trees/transform_node.h" #include "testing/gtest/include/gtest/gtest.h" #include "ui/gfx/geometry/scroll_offset.h" namespace cc { +void SetScrollOffset(PropertyTrees* property_trees, + ElementId scroller_id, + gfx::ScrollOffset offset) { + // Update both scroll and transform trees + property_trees->scroll_tree.SetScrollOffset(scroller_id, offset); + TransformNode* transform_node = + property_trees->transform_tree.FindNodeFromElementId(scroller_id); + transform_node->scroll_offset = offset; + transform_node->needs_local_transform_update = true; +} + +void CreateScrollingElement(PropertyTrees* property_trees, + ElementId scroller_id, + gfx::Size content_size, + gfx::Size container_size) { + // Create a corresponding TransformNode for the scrolling element. + TransformNode transform_node; + transform_node.scrolls = true; + transform_node.source_node_id = TransformTree::kRootNodeId; + int transform_node_id = + property_trees->transform_tree.Insert(transform_node, 0); + property_trees->element_id_to_transform_node_index[scroller_id] = + transform_node_id; + + // Add the scrolling node for the scrolling and link it to the above transform + // node. + ScrollNode scroll_node; + scroll_node.scrollable = true; + scroll_node.bounds = content_size; + scroll_node.container_bounds = container_size; + scroll_node.element_id = scroller_id; + scroll_node.transform_id = transform_node_id; + int scroll_node_id = property_trees->scroll_tree.Insert(scroll_node, 0); + + property_trees->element_id_to_scroll_node_index[scroller_id] = scroll_node_id; +} + class ScrollTimelineTest : public ::testing::Test { public: ScrollTimelineTest() @@ -19,17 +57,14 @@ property_trees_.is_main_thread = true; property_trees_.is_active = false; - // We add a single node that is scrolling a 550x1100 contents inside a - // 50x100 container. - ScrollNode node; - node.scrollable = true; - node.bounds = content_size_; - node.container_bounds = container_size_; - - int node_id = property_trees_.scroll_tree.Insert(node, 0); - property_trees_.element_id_to_scroll_node_index[scroller_id_] = node_id; + // Create a single scroller that is scrolling a 500x500 contents inside a + // 100x100 container. + CreateScrollingElement(&property_trees_, scroller_id_, content_size_, + container_size_); } + PropertyTrees& property_trees() { return property_trees_; } + ScrollTree& scroll_tree() { return property_trees_.scroll_tree; } ElementId scroller_id() const { return scroller_id_; } gfx::Size container_size() const { return container_size_; } @@ -54,12 +89,12 @@ time_range); // Unscrolled, both timelines should read a current time of 0. - scroll_tree().SetScrollOffset(scroller_id(), gfx::ScrollOffset()); + SetScrollOffset(&property_trees(), scroller_id(), gfx::ScrollOffset()); EXPECT_FLOAT_EQ(0, vertical_timeline.CurrentTime(scroll_tree(), false)); EXPECT_FLOAT_EQ(0, horizontal_timeline.CurrentTime(scroll_tree(), false)); // Now do some scrolling and make sure that the ScrollTimelines update. - scroll_tree().SetScrollOffset(scroller_id(), gfx::ScrollOffset(75, 50)); + SetScrollOffset(&property_trees(), scroller_id(), gfx::ScrollOffset(75, 50)); // As noted above, we have mapped the time range such that current time should // just be the scroll offset. @@ -73,7 +108,8 @@ ScrollTimeline timeline(scroller_id(), ScrollTimeline::Vertical, 100); double halfwayY = (content_size().height() - container_size().height()) / 2.; - scroll_tree().SetScrollOffset(scroller_id(), gfx::ScrollOffset(0, halfwayY)); + SetScrollOffset(&property_trees(), scroller_id(), + gfx::ScrollOffset(0, halfwayY)); EXPECT_FLOAT_EQ(50, timeline.CurrentTime(scroll_tree(), false)); } @@ -95,17 +131,11 @@ // Initially only the pending tree has the scroll node. ElementId scroller_id(1); - ScrollNode node; - node.scrollable = true; - node.bounds = content_size(); - node.container_bounds = container_size(); - - int node_id = pending_tree.scroll_tree.Insert(node, 0); - pending_tree.element_id_to_scroll_node_index[scroller_id] = node_id; + CreateScrollingElement(&pending_tree, scroller_id, content_size(), + container_size()); double halfwayY = (content_size().height() - container_size().height()) / 2.; - pending_tree.scroll_tree.SetScrollOffset(scroller_id, - gfx::ScrollOffset(0, halfwayY)); + SetScrollOffset(&pending_tree, scroller_id, gfx::ScrollOffset(0, halfwayY)); ScrollTimeline main_timeline(scroller_id, ScrollTimeline::Vertical, 100); @@ -131,4 +161,19 @@ impl_timeline->CurrentTime(pending_tree.scroll_tree, false)); } +TEST_F(ScrollTimelineTest, CurrentTimeIsAdjustedForPixelSnapping) { + double time_range = content_size().height() - container_size().height(); + ScrollTimeline timeline(scroller_id(), ScrollTimeline::Vertical, time_range); + + SetScrollOffset(&property_trees(), scroller_id(), gfx::ScrollOffset(0, 50)); + + // For simplicity emulate snapping by directly setting snap_amount of + // transform node. + TransformNode* transform_node = + property_trees().transform_tree.FindNodeFromElementId(scroller_id()); + transform_node->snap_amount = gfx::Vector2dF(0, 0.5); + + EXPECT_FLOAT_EQ(49.5, timeline.CurrentTime(scroll_tree(), false)); +} + } // namespace cc
diff --git a/cc/tiles/decoded_image_tracker.cc b/cc/tiles/decoded_image_tracker.cc index 9f717c9..0ebda327 100644 --- a/cc/tiles/decoded_image_tracker.cc +++ b/cc/tiles/decoded_image_tracker.cc
@@ -7,33 +7,17 @@ namespace cc { namespace { -// Timeout images after 250ms, whether or not they've been used. This prevents -// unbounded cache usage. -const int64_t kTimeoutDurationMs = 250; +const int kNumFramesToLock = 2; } // namespace -DecodedImageTracker::ImageLock::ImageLock( - DecodedImageTracker* tracker, - ImageController::ImageDecodeRequestId request_id, - base::TimeTicks lock_time) - : tracker_(tracker), request_id_(request_id), lock_time_(lock_time) {} - -DecodedImageTracker::ImageLock::~ImageLock() { - tracker_->image_controller_->UnlockImageDecode(request_id_); -} - -DecodedImageTracker::DecodedImageTracker( - ImageController* controller, - scoped_refptr<base::SequencedTaskRunner> task_runner) - : image_controller_(controller), - task_runner_(std::move(task_runner)), - now_fn_(base::Bind(&base::TimeTicks::Now)), - weak_ptr_factory_(this) { +DecodedImageTracker::DecodedImageTracker(ImageController* controller) + : image_controller_(controller) { DCHECK(image_controller_); } DecodedImageTracker::~DecodedImageTracker() { - UnlockAllImages(); + for (auto& pair : locked_images_) + image_controller_->UnlockImageDecode(pair.first); } void DecodedImageTracker::QueueImageDecode( @@ -51,74 +35,38 @@ DrawImage draw_image(image, image_bounds, kNone_SkFilterQuality, SkMatrix::I(), frame_index, target_color_space); image_controller_->QueueImageDecode( - draw_image, - base::Bind(&DecodedImageTracker::ImageDecodeFinished, - base::Unretained(this), callback, image.stable_id())); + draw_image, base::Bind(&DecodedImageTracker::ImageDecodeFinished, + base::Unretained(this), callback)); } -void DecodedImageTracker::UnlockAllImages() { - locked_images_.clear(); -} - -void DecodedImageTracker::OnImagesUsedInDraw( - const std::vector<DrawImage>& draw_images) { - for (const DrawImage& draw_image : draw_images) - locked_images_.erase(draw_image.paint_image().stable_id()); +void DecodedImageTracker::NotifyFrameFinished() { + // Go through the images and if the frame ref count goes to 0, unlock the + // image in the controller. + for (auto it = locked_images_.begin(); it != locked_images_.end();) { + auto id = it->first; + int& ref_count = it->second; + if (--ref_count != 0) { + ++it; + continue; + } + image_controller_->UnlockImageDecode(id); + it = locked_images_.erase(it); + } } void DecodedImageTracker::ImageDecodeFinished( const base::Callback<void(bool)>& callback, - PaintImage::Id image_id, - ImageController::ImageDecodeRequestId request_id, + ImageController::ImageDecodeRequestId id, ImageController::ImageDecodeResult result) { TRACE_EVENT0(TRACE_DISABLED_BY_DEFAULT("cc.debug"), "DecodedImageTracker::ImageDecodeFinished"); - if (result == ImageController::ImageDecodeResult::SUCCESS) { - // If this image already exists, just replace it with the new (latest) - // decode. - locked_images_.erase(image_id); - locked_images_.emplace( - image_id, std::make_unique<ImageLock>(this, request_id, now_fn_.Run())); - EnqueueTimeout(); - } + if (result == ImageController::ImageDecodeResult::SUCCESS) + locked_images_.push_back(std::make_pair(id, kNumFramesToLock)); bool decode_succeeded = result == ImageController::ImageDecodeResult::SUCCESS || result == ImageController::ImageDecodeResult::DECODE_NOT_REQUIRED; callback.Run(decode_succeeded); } -void DecodedImageTracker::OnTimeoutImages() { - timeout_pending_ = false; - if (locked_images_.size() == 0) - return; - - auto now = now_fn_.Run(); - auto timeout = base::TimeDelta::FromMilliseconds(kTimeoutDurationMs); - for (auto it = locked_images_.begin(); it != locked_images_.end();) { - auto& image = it->second; - if (now - image->lock_time() < timeout) { - ++it; - continue; - } - it = locked_images_.erase(it); - } - - EnqueueTimeout(); -} - -void DecodedImageTracker::EnqueueTimeout() { - if (timeout_pending_) - return; - if (locked_images_.size() == 0) - return; - - timeout_pending_ = true; - task_runner_->PostDelayedTask( - FROM_HERE, - base::Bind(&DecodedImageTracker::OnTimeoutImages, - weak_ptr_factory_.GetWeakPtr()), - base::TimeDelta::FromMilliseconds(kTimeoutDurationMs)); -} - } // namespace cc
diff --git a/cc/tiles/decoded_image_tracker.h b/cc/tiles/decoded_image_tracker.h index 36f6dc3..4321a02 100644 --- a/cc/tiles/decoded_image_tracker.h +++ b/cc/tiles/decoded_image_tracker.h
@@ -9,7 +9,6 @@ #include <vector> #include "base/bind.h" -#include "base/time/time.h" #include "cc/cc_export.h" #include "cc/tiles/image_controller.h" @@ -25,9 +24,7 @@ // are silently ignored. class CC_EXPORT DecodedImageTracker { public: - explicit DecodedImageTracker( - ImageController* controller, - scoped_refptr<base::SequencedTaskRunner> task_runner); + explicit DecodedImageTracker(ImageController* controller); ~DecodedImageTracker(); // Request that the given image be decoded. This issues a callback upon @@ -36,57 +33,18 @@ void QueueImageDecode(const PaintImage& image, const gfx::ColorSpace& target_color_space, const base::Callback<void(bool)>& callback); - - // Unlock all locked images - used to respond to memory pressure or - // application background. - void UnlockAllImages(); - - // Notifies the tracker that images have been used, allowing it to - // unlock them. - void OnImagesUsedInDraw(const std::vector<DrawImage>& draw_images); - - using NowFn = base::Callback<base::TimeTicks()>; - void SetNowFunctionForTesting(NowFn now_fn) { now_fn_ = now_fn; } - - // Test only functions: - size_t NumLockedImagesForTesting() const { return locked_images_.size(); } + void NotifyFrameFinished(); private: friend class DecodedImageTrackerTest; void ImageDecodeFinished(const base::Callback<void(bool)>& callback, - PaintImage::Id image_id, - ImageController::ImageDecodeRequestId request_id, + ImageController::ImageDecodeRequestId id, ImageController::ImageDecodeResult result); - void OnTimeoutImages(); - void EnqueueTimeout(); ImageController* image_controller_; - - // Helper class tracking a locked image decode. Automatically releases the - // lock using the provided DecodedImageTracker* on destruction. - class ImageLock { - public: - ImageLock(DecodedImageTracker* tracker, - ImageController::ImageDecodeRequestId request_id, - base::TimeTicks lock_time); - ~ImageLock(); - base::TimeTicks lock_time() const { return lock_time_; } - - private: - DecodedImageTracker* tracker_; - ImageController::ImageDecodeRequestId request_id_; - base::TimeTicks lock_time_; - DISALLOW_COPY_AND_ASSIGN(ImageLock); - }; - base::flat_map<PaintImage::Id, std::unique_ptr<ImageLock>> locked_images_; - bool timeout_pending_ = false; - scoped_refptr<base::SequencedTaskRunner> task_runner_; - - // Defaults to base::TimeTicks::Now(), but overrideable for testing. - NowFn now_fn_; - - base::WeakPtrFactory<DecodedImageTracker> weak_ptr_factory_; + std::vector<std::pair<ImageController::ImageDecodeRequestId, int>> + locked_images_; DISALLOW_COPY_AND_ASSIGN(DecodedImageTracker); };
diff --git a/cc/tiles/decoded_image_tracker_unittest.cc b/cc/tiles/decoded_image_tracker_unittest.cc index a31f5a2..f729d62 100644 --- a/cc/tiles/decoded_image_tracker_unittest.cc +++ b/cc/tiles/decoded_image_tracker_unittest.cc
@@ -5,7 +5,6 @@ #include <vector> #include "base/bind.h" -#include "base/test/test_mock_time_task_runner.h" #include "cc/paint/paint_image_builder.h" #include "cc/test/skia_common.h" #include "cc/tiles/decoded_image_tracker.h" @@ -64,22 +63,15 @@ class DecodedImageTrackerTest : public testing::Test { public: - DecodedImageTrackerTest() - : task_runner_(new base::TestMockTimeTaskRunner()), - decoded_image_tracker_(&image_controller_, task_runner_) { - decoded_image_tracker_.SetNowFunctionForTesting( - base::Bind(&base::TestMockTimeTaskRunner::NowTicks, task_runner_)); - } + DecodedImageTrackerTest() : decoded_image_tracker_(&image_controller_) {} TestImageController* image_controller() { return &image_controller_; } DecodedImageTracker* decoded_image_tracker() { return &decoded_image_tracker_; } - base::TestMockTimeTaskRunner* task_runner() { return task_runner_.get(); } private: TestImageController image_controller_; - scoped_refptr<base::TestMockTimeTaskRunner> task_runner_; DecodedImageTracker decoded_image_tracker_; }; @@ -93,7 +85,7 @@ EXPECT_EQ(1u, image_controller()->num_locked_images()); } -TEST_F(DecodedImageTrackerTest, Colorspace) { +TEST_F(DecodedImageTrackerTest, NotifyFrameFinishedUnlocksImages) { bool locked = false; gfx::ColorSpace decoded_color_space( gfx::ColorSpace::PrimaryID::XYZ_D50, @@ -104,6 +96,11 @@ paint_image, decoded_color_space, base::Bind([](bool* locked, bool success) { *locked = true; }, base::Unretained(&locked))); + EXPECT_TRUE(locked); + EXPECT_EQ(1u, image_controller()->num_locked_images()); + + decoded_image_tracker()->NotifyFrameFinished(); + EXPECT_EQ(1u, image_controller()->num_locked_images()); // Check that the decoded color space images are locked, but if the color // space differs then that image is not locked. Note that we use the high @@ -117,97 +114,19 @@ kHigh_SkFilterQuality, SkMatrix::I(), PaintImage::kDefaultFrameIndex, srgb_color_space); EXPECT_FALSE(image_controller()->IsDrawImageLocked(srgb_draw_image)); -} -TEST_F(DecodedImageTrackerTest, ImagesTimeOut) { - // Add an image, this will start a 250ms timeout to release it. - bool locked = false; + locked = false; decoded_image_tracker()->QueueImageDecode( - CreateDiscardablePaintImage(gfx::Size(1, 1)), gfx::ColorSpace(), - base::Bind([](bool* locked, bool success) { *locked = true; }, - base::Unretained(&locked))); - EXPECT_TRUE(locked); - EXPECT_EQ(1u, image_controller()->num_locked_images()); - - // Advance by 150ms, the image should still be locked. - task_runner()->FastForwardBy(base::TimeDelta::FromMilliseconds(150)); - EXPECT_EQ(1u, image_controller()->num_locked_images()); - - // Add an image, this will not start a new timeout, as one is pending. - decoded_image_tracker()->QueueImageDecode( - CreateDiscardablePaintImage(gfx::Size(1, 1)), gfx::ColorSpace(), + CreateDiscardablePaintImage(gfx::Size(1, 1)), decoded_color_space, base::Bind([](bool* locked, bool success) { *locked = true; }, base::Unretained(&locked))); EXPECT_TRUE(locked); EXPECT_EQ(2u, image_controller()->num_locked_images()); - // Advance by 100ms, we our first image should be released. - // Trigger a single commit, the first image should be unlocked. - task_runner()->FastForwardBy(base::TimeDelta::FromMilliseconds(100)); + decoded_image_tracker()->NotifyFrameFinished(); EXPECT_EQ(1u, image_controller()->num_locked_images()); - // Advance by another 250ms, our second image should release. - task_runner()->FastForwardBy(base::TimeDelta::FromMilliseconds(250)); - EXPECT_EQ(0u, image_controller()->num_locked_images()); -} - -TEST_F(DecodedImageTrackerTest, ImageUsedInDraw) { - // Insert two images: - bool locked = false; - auto paint_image_1 = CreateDiscardablePaintImage(gfx::Size(1, 1)); - decoded_image_tracker()->QueueImageDecode( - paint_image_1, gfx::ColorSpace(), - base::Bind([](bool* locked, bool success) { *locked = true; }, - base::Unretained(&locked))); - EXPECT_TRUE(locked); - EXPECT_EQ(1u, image_controller()->num_locked_images()); - - auto paint_image_2 = CreateDiscardablePaintImage(gfx::Size(1, 1)); - decoded_image_tracker()->QueueImageDecode( - paint_image_2, gfx::ColorSpace(), - base::Bind([](bool* locked, bool success) { *locked = true; }, - base::Unretained(&locked))); - EXPECT_TRUE(locked); - EXPECT_EQ(2u, image_controller()->num_locked_images()); - - // Create dummy draw images for each: - DrawImage draw_image_1(paint_image_1, SkIRect::MakeWH(1, 1), - kHigh_SkFilterQuality, SkMatrix::I(), 0, - gfx::ColorSpace()); - DrawImage draw_image_2(paint_image_2, SkIRect::MakeWH(1, 1), - kHigh_SkFilterQuality, SkMatrix::I(), 0, - gfx::ColorSpace()); - - // Both should be in the cache: - EXPECT_TRUE(image_controller()->IsDrawImageLocked(draw_image_1)); - EXPECT_TRUE(image_controller()->IsDrawImageLocked(draw_image_2)); - - // Pretend we've drawn with image 2. - decoded_image_tracker()->OnImagesUsedInDraw({draw_image_2}); - - // Only image 1 should now be in the cache. - EXPECT_TRUE(image_controller()->IsDrawImageLocked(draw_image_1)); - EXPECT_FALSE(image_controller()->IsDrawImageLocked(draw_image_2)); -} - -TEST_F(DecodedImageTrackerTest, UnlockAllImages) { - // Insert two images: - bool locked = false; - decoded_image_tracker()->QueueImageDecode( - CreateDiscardablePaintImage(gfx::Size(1, 1)), gfx::ColorSpace(), - base::Bind([](bool* locked, bool success) { *locked = true; }, - base::Unretained(&locked))); - EXPECT_TRUE(locked); - EXPECT_EQ(1u, image_controller()->num_locked_images()); - decoded_image_tracker()->QueueImageDecode( - CreateDiscardablePaintImage(gfx::Size(1, 1)), gfx::ColorSpace(), - base::Bind([](bool* locked, bool success) { *locked = true; }, - base::Unretained(&locked))); - EXPECT_TRUE(locked); - EXPECT_EQ(2u, image_controller()->num_locked_images()); - - // Unlock all images. - decoded_image_tracker()->UnlockAllImages(); + decoded_image_tracker()->NotifyFrameFinished(); EXPECT_EQ(0u, image_controller()->num_locked_images()); }
diff --git a/cc/tiles/tile_manager.cc b/cc/tiles/tile_manager.cc index c5bfde7..2059191 100644 --- a/cc/tiles/tile_manager.cc +++ b/cc/tiles/tile_manager.cc
@@ -362,7 +362,7 @@ did_oom_on_last_assign_(false), image_controller_(origin_task_runner, std::move(image_worker_task_runner)), - decoded_image_tracker_(&image_controller_, origin_task_runner), + decoded_image_tracker_(&image_controller_), checker_image_tracker_(&image_controller_, this, tile_manager_settings_.enable_checker_imaging, @@ -1032,10 +1032,8 @@ prepare_tiles_count_, TilePriority::SOON, ImageDecodeCache::TaskType::kInRaster); std::vector<scoped_refptr<TileTask>> new_locked_image_tasks = - image_controller_.SetPredecodeImages(new_locked_images, tracing_info); - // Notify |decoded_image_tracker_| after |image_controller_| to ensure we've - // taken new refs on the images before releasing the predecode API refs. - decoded_image_tracker_.OnImagesUsedInDraw(new_locked_images); + image_controller_.SetPredecodeImages(std::move(new_locked_images), + tracing_info); work_to_schedule.extra_prepaint_images.clear(); for (auto& task : new_locked_image_tasks) { @@ -1157,9 +1155,6 @@ bool has_at_raster_images = false; image_controller_.GetTasksForImagesAndRef( &sync_decoded_images, &decode_tasks, &has_at_raster_images, tracing_info); - // Notify |decoded_image_tracker_| after |image_controller_| to ensure we've - // taken new refs on the images before releasing the predecode API refs. - decoded_image_tracker_.OnImagesUsedInDraw(sync_decoded_images); const bool has_checker_images = !checkered_images.empty(); tile->set_raster_task_scheduled_with_checker_images(has_checker_images);
diff --git a/cc/tiles/tile_manager_unittest.cc b/cc/tiles/tile_manager_unittest.cc index 2df3ed771..b9cbd76f 100644 --- a/cc/tiles/tile_manager_unittest.cc +++ b/cc/tiles/tile_manager_unittest.cc
@@ -3220,124 +3220,5 @@ TakeHostImpl(); } -class DecodedImageTrackerTileManagerTest : public TestLayerTreeHostBase { - public: - void TearDown() override { - // Allow all tasks on the image worker to run now. Any scheduled decodes - // will be aborted. - task_runner_->set_run_tasks_synchronously(true); - } - - LayerTreeSettings CreateSettings() override { - LayerTreeSettings settings = TestLayerTreeHostBase::CreateSettings(); - settings.max_preraster_distance_in_screen_pixels = 100; - return settings; - } - - std::unique_ptr<FakeLayerTreeHostImpl> CreateHostImpl( - const LayerTreeSettings& settings, - TaskRunnerProvider* task_runner_provider, - TaskGraphRunner* task_graph_runner) override { - task_runner_ = base::MakeRefCounted<SynchronousSimpleTaskRunner>(); - return std::make_unique<FakeLayerTreeHostImpl>( - settings, task_runner_provider, task_graph_runner, task_runner_); - } - - std::unique_ptr<TaskGraphRunner> CreateTaskGraphRunner() override { - return std::make_unique<SynchronousTaskGraphRunner>(); - } - - void FlushDecodeTasks() { - while (task_runner_->HasPendingTask()) { - task_runner_->RunUntilIdle(); - base::RunLoop().RunUntilIdle(); - } - } - - private: - scoped_refptr<SynchronousSimpleTaskRunner> task_runner_; -}; - -TEST_F(DecodedImageTrackerTileManagerTest, DecodedImageTrackerDropsLocksOnUse) { - // Pick arbitrary IDs - they don't really matter as long as they're constant. - const int kLayerId = 7; - - host_impl()->tile_manager()->SetTileTaskManagerForTesting( - std::make_unique<FakeTileTaskManagerImpl>()); - - // Create two test images, one will be positioned to be needed NOW, the other - // will be positioned to be prepaint. - int dimension = 250; - PaintImage image1 = - CreateDiscardablePaintImage(gfx::Size(dimension, dimension)); - PaintImage image2 = - CreateDiscardablePaintImage(gfx::Size(dimension, dimension)); - - // Add the images to our decoded_image_tracker. - host_impl()->tile_manager()->decoded_image_tracker().QueueImageDecode( - image1, gfx::ColorSpace(), base::DoNothing()); - host_impl()->tile_manager()->decoded_image_tracker().QueueImageDecode( - image2, gfx::ColorSpace(), base::DoNothing()); - EXPECT_EQ(0u, host_impl() - ->tile_manager() - ->decoded_image_tracker() - .NumLockedImagesForTesting()); - FlushDecodeTasks(); - EXPECT_EQ(2u, host_impl() - ->tile_manager() - ->decoded_image_tracker() - .NumLockedImagesForTesting()); - - // Add images to a fake recording source. - const gfx::Size layer_bounds(1000, 500); - std::unique_ptr<FakeRecordingSource> recording_source = - FakeRecordingSource::CreateFilledRecordingSource(layer_bounds); - recording_source->set_fill_with_nonsolid_color(true); - recording_source->add_draw_image(image1, gfx::Point(0, 0)); - recording_source->add_draw_image(image2, gfx::Point(700, 0)); - recording_source->Rerecord(); - - scoped_refptr<FakeRasterSource> pending_raster_source = - FakeRasterSource::CreateFromRecordingSource(recording_source.get()); - - host_impl()->CreatePendingTree(); - LayerTreeImpl* pending_tree = host_impl()->pending_tree(); - pending_tree->SetDeviceViewportSize( - host_impl()->active_tree()->GetDeviceViewport().size()); - - // Steal from the recycled tree. - std::unique_ptr<FakePictureLayerImpl> pending_layer = - FakePictureLayerImpl::CreateWithRasterSource(pending_tree, kLayerId, - pending_raster_source); - pending_layer->SetDrawsContent(true); - - // The bounds() are half the recording source size, allowing for prepaint - // images. - pending_layer->SetBounds(gfx::Size(500, 500)); - pending_tree->SetRootLayerForTesting(std::move(pending_layer)); - - // Add tilings/tiles for the layer. - host_impl()->pending_tree()->BuildLayerListAndPropertyTreesForTesting(); - host_impl()->pending_tree()->UpdateDrawProperties(); - - // Build the raster queue and invalidate the top tile if partial raster is - // enabled. - std::unique_ptr<RasterTilePriorityQueue> queue(host_impl()->BuildRasterQueue( - SAME_PRIORITY_FOR_BOTH_TREES, RasterTilePriorityQueue::Type::ALL)); - ASSERT_FALSE(queue->IsEmpty()); - - // PrepareTiles to schedule tasks. This should cause the decoded image tracker - // to release its lock. - EXPECT_EQ(2u, host_impl() - ->tile_manager() - ->decoded_image_tracker() - .NumLockedImagesForTesting()); - host_impl()->tile_manager()->PrepareTiles(host_impl()->global_tile_state()); - EXPECT_EQ(0u, host_impl() - ->tile_manager() - ->decoded_image_tracker() - .NumLockedImagesForTesting()); -} - } // namespace } // namespace cc
diff --git a/cc/trees/layer_tree_host_impl.cc b/cc/trees/layer_tree_host_impl.cc index 1fa5e4f..611ca479a 100644 --- a/cc/trees/layer_tree_host_impl.cc +++ b/cc/trees/layer_tree_host_impl.cc
@@ -2442,6 +2442,7 @@ skipped_frame_tracker_.FinishFrame(); impl_thread_phase_ = ImplThreadPhase::IDLE; current_begin_frame_tracker_.Finish(); + tile_manager_.decoded_image_tracker().NotifyFrameFinished(); } void LayerTreeHostImpl::DidNotProduceFrame(const viz::BeginFrameAck& ack) { @@ -2872,7 +2873,6 @@ } if (resource_pool_) resource_pool_->OnPurgeMemory(); - tile_manager_.decoded_image_tracker().UnlockAllImages(); } void LayerTreeHostImpl::OnMemoryPressure( @@ -2920,7 +2920,6 @@ EvictAllUIResources(); // Call PrepareTiles to evict tiles when we become invisible. PrepareTiles(); - tile_manager_.decoded_image_tracker().UnlockAllImages(); } }
diff --git a/cc/trees/property_tree.cc b/cc/trees/property_tree.cc index 7ad70ee..cee7353d 100644 --- a/cc/trees/property_tree.cc +++ b/cc/trees/property_tree.cc
@@ -1434,6 +1434,33 @@ : gfx::ScrollOffset(); } +const gfx::ScrollOffset ScrollTree::GetPixelSnappedScrollOffset( + int scroll_node_id) const { + const ScrollNode* scroll_node = Node(scroll_node_id); + DCHECK(scroll_node); + gfx::ScrollOffset offset = current_scroll_offset(scroll_node->element_id); + + const TransformNode* transform_node = + property_trees()->transform_tree.Node(scroll_node->transform_id); + DCHECK(offset == transform_node->scroll_offset) + << "Transform node scroll offset does not match the actual offset, this " + "means the snapped_amount calculation will be incorrect"; + + if (transform_node->scrolls) { + // If necessary perform a update for this node to ensure snap amount is + // accurate. This method is used by scroll timeline, so it is possible for + // it to get called before transform tree has gone through a full update + // cycle so this node snap amount may be stale. + if (transform_node->needs_local_transform_update) + property_trees()->transform_tree.UpdateTransforms(transform_node->id); + + offset.set_x(offset.x() - transform_node->snap_amount.x()); + offset.set_y(offset.y() - transform_node->snap_amount.y()); + } + + return offset; +} + gfx::ScrollOffset ScrollTree::PullDeltaForMainThread( SyncedScrollOffset* scroll_offset) { DCHECK(property_trees()->is_active);
diff --git a/cc/trees/property_tree.h b/cc/trees/property_tree.h index 7fb0479..9a9d9fd 100644 --- a/cc/trees/property_tree.h +++ b/cc/trees/property_tree.h
@@ -419,6 +419,18 @@ // on the active tree. const gfx::ScrollOffset current_scroll_offset(ElementId id) const; + // Returns the scroll offset taking into account any adjustments that may be + // included due to pixel snapping. + // + // Note: Using this method may causes the associated transform node for this + // scroll node to update its transforms. + // + // TODO(crbug.com/585458): Updating single transform node only works for + // simple cases but we really should update the whole transform tree otherwise + // we are ignoring any parent transform node that needs updating and thus our + // snap amount can be incorrect. + const gfx::ScrollOffset GetPixelSnappedScrollOffset(int scroll_node_id) const; + // Collects deltas for scroll changes on the impl thread that need to be // reported to the main thread during the main frame. As such, should only be // called on the impl thread side PropertyTrees.
diff --git a/chrome/android/feed/core/java/src/org/chromium/chrome/browser/feed/FeedContentBridge.java b/chrome/android/feed/core/java/src/org/chromium/chrome/browser/feed/FeedContentBridge.java new file mode 100644 index 0000000..df95f7f --- /dev/null +++ b/chrome/android/feed/core/java/src/org/chromium/chrome/browser/feed/FeedContentBridge.java
@@ -0,0 +1,130 @@ +// Copyright 2018 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +package org.chromium.chrome.browser.feed; + +import com.google.android.libraries.feed.host.storage.ContentMutation; +import com.google.android.libraries.feed.host.storage.ContentOperation; +import com.google.android.libraries.feed.host.storage.ContentOperation.Delete; +import com.google.android.libraries.feed.host.storage.ContentOperation.DeleteByPrefix; +import com.google.android.libraries.feed.host.storage.ContentOperation.Type; +import com.google.android.libraries.feed.host.storage.ContentOperation.Upsert; + +import org.chromium.base.Callback; +import org.chromium.base.annotations.CalledByNative; +import org.chromium.base.annotations.JNINamespace; +import org.chromium.chrome.browser.profiles.Profile; + +import java.util.HashMap; +import java.util.List; +import java.util.Map; + +/** + * Provides access to native implementations of content storage. + */ +@JNINamespace("feed") +public class FeedContentBridge { + private long mNativeFeedContentBridge; + + /** + * Creates a {@link FeedContentBridge} for accessing native content storage + * implementation for the current user, and initial native side bridge. + */ + public FeedContentBridge() {} + + /** + * Inits native side bridge. + * + * @param profile {@link Profile} of the user we are rendering the Feed for. + */ + public void init(Profile profile) { + mNativeFeedContentBridge = nativeInit(profile); + } + + /** Cleans up native half of this bridge. */ + public void destroy() { + assert mNativeFeedContentBridge != 0; + nativeDestroy(mNativeFeedContentBridge); + mNativeFeedContentBridge = 0; + } + + public void loadContent(List<String> keys, Callback<Map<String, byte[]>> callback) { + assert mNativeFeedContentBridge != 0; + String[] keysArray = keys.toArray(new String[keys.size()]); + nativeLoadContent(mNativeFeedContentBridge, keysArray, callback); + } + + public void loadContentByPrefix(String prefix, Callback<Map<String, byte[]>> callback) { + assert mNativeFeedContentBridge != 0; + nativeLoadContentByPrefix(mNativeFeedContentBridge, prefix, callback); + } + + public void loadAllContentKeys(Callback<String[]> callback) { + assert mNativeFeedContentBridge != 0; + nativeLoadAllContentKeys(mNativeFeedContentBridge, callback); + } + + public void commitContentMutation(ContentMutation contentMutation, Callback<Boolean> callback) { + assert mNativeFeedContentBridge != 0; + + nativeCreateContentMutation(mNativeFeedContentBridge); + for (ContentOperation operation : contentMutation.getOperations()) { + switch (operation.getType()) { + case Type.UPSERT: + Upsert upsert = (Upsert) operation; + nativeAppendUpsertOperation( + mNativeFeedContentBridge, upsert.getKey(), upsert.getValue()); + break; + case Type.DELETE: + Delete delete = (Delete) operation; + nativeAppendDeleteOperation(mNativeFeedContentBridge, delete.getKey()); + break; + case Type.DELETE_BY_PREFIX: + DeleteByPrefix deleteByPrefix = (DeleteByPrefix) operation; + nativeAppendDeleteByPrefixOperation( + mNativeFeedContentBridge, deleteByPrefix.getPrefix()); + break; + case Type.DELETE_ALL: + nativeAppendDeleteAllOperation(mNativeFeedContentBridge); + break; + default: + // Operation type is not supported, therefore failing immediately. + assert false : "Unsupported type of operation."; + nativeDeleteContentMutation(mNativeFeedContentBridge); + callback.onResult(false); + return; + } + } + nativeCommitContentMutation(mNativeFeedContentBridge, callback); + } + + @CalledByNative + private static Object createKeyAndDataMap(String[] keys, byte[][] data) { + assert keys.length == data.length; + Map<String, byte[]> valueMap = new HashMap<>(keys.length); + for (int i = 0; i < keys.length && i < data.length; ++i) { + valueMap.put(keys[i], data[i]); + } + return valueMap; + } + + private native long nativeInit(Profile profile); + private native void nativeDestroy(long nativeFeedContentBridge); + private native void nativeLoadContent( + long nativeFeedContentBridge, String[] keys, Callback<Map<String, byte[]>> callback); + private native void nativeLoadContentByPrefix( + long nativeFeedContentBridge, String prefix, Callback<Map<String, byte[]>> callback); + private native void nativeLoadAllContentKeys( + long nativeFeedContentBridge, Callback<String[]> callback); + private native void nativeCommitContentMutation( + long nativeFeedContentBridge, Callback<Boolean> callback); + private native void nativeCreateContentMutation(long nativeFeedContentBridge); + private native void nativeDeleteContentMutation(long nativeFeedContentBridge); + private native void nativeAppendDeleteOperation(long nativeFeedContentBridge, String key); + private native void nativeAppendDeleteByPrefixOperation( + long nativeFeedContentBridge, String prefix); + private native void nativeAppendUpsertOperation( + long nativeFeedContentBridge, String key, byte[] data); + private native void nativeAppendDeleteAllOperation(long nativeFeedContentBridge); +}
diff --git a/chrome/android/feed/core/java/src/org/chromium/chrome/browser/feed/FeedContentStorage.java b/chrome/android/feed/core/java/src/org/chromium/chrome/browser/feed/FeedContentStorage.java index 9926d3a..ed2a54e 100644 --- a/chrome/android/feed/core/java/src/org/chromium/chrome/browser/feed/FeedContentStorage.java +++ b/chrome/android/feed/core/java/src/org/chromium/chrome/browser/feed/FeedContentStorage.java
@@ -8,16 +8,11 @@ import com.google.android.libraries.feed.common.functional.Consumer; import com.google.android.libraries.feed.host.storage.CommitResult; import com.google.android.libraries.feed.host.storage.ContentMutation; -import com.google.android.libraries.feed.host.storage.ContentOperation; -import com.google.android.libraries.feed.host.storage.ContentOperation.Delete; -import com.google.android.libraries.feed.host.storage.ContentOperation.DeleteByPrefix; -import com.google.android.libraries.feed.host.storage.ContentOperation.Type; -import com.google.android.libraries.feed.host.storage.ContentOperation.Upsert; import com.google.android.libraries.feed.host.storage.ContentStorage; import org.chromium.base.Callback; -import java.util.Collections; +import java.util.Arrays; import java.util.List; import java.util.Map; @@ -25,7 +20,7 @@ * Implementation of {@link ContentStorage} that persisits data on native side. */ public class FeedContentStorage implements ContentStorage { - private FeedStorageBridge mFeedStorageBridge; + private FeedContentBridge mFeedContentBridge; private static class StorageCallback<T> implements Callback<T> { private final Consumer<Result<T>> mConsumer; @@ -41,30 +36,33 @@ } } + private static class GetAllKeysCallback implements Callback<String[]> { + private final Consumer < Result < List<String>>> mConsumer; + + public GetAllKeysCallback(Consumer < Result < List<String>>> consumer) { + mConsumer = consumer; + } + + @Override + public void onResult(String[] keys) { + // TODO(gangwu): Need to handle failure case. + mConsumer.accept(Result.success(Arrays.asList(keys))); + } + } + private static class CommitCallback implements Callback<Boolean> { private final Consumer<CommitResult> mConsumer; - private int mOperationsLeft; - private boolean mSuccess; - CommitCallback(Consumer<CommitResult> consumer, int operationsCount) { + CommitCallback(Consumer<CommitResult> consumer) { mConsumer = consumer; - mOperationsLeft = operationsCount; - mSuccess = true; } @Override public void onResult(Boolean result) { - --mOperationsLeft; - assert mOperationsLeft >= 0; - - mSuccess &= result.booleanValue(); - // TODO(gangwu): if |result| is failure, all other operation should halt immediately. - if (mOperationsLeft == 0) { - if (mSuccess) { - mConsumer.accept(CommitResult.SUCCESS); - } else { - mConsumer.accept(CommitResult.FAILURE); - } + if (result) { + mConsumer.accept(CommitResult.SUCCESS); + } else { + mConsumer.accept(CommitResult.FAILURE); } } } @@ -72,73 +70,42 @@ /** * Creates a {@link FeedContentStorage} for storing content for the current user. * - * @param bridge {@link FeedStorageBridge} implementation can handle content storage request. + * @param bridge {@link FeedContentBridge} implementation can handle content storage request. */ - public FeedContentStorage(FeedStorageBridge bridge) { - mFeedStorageBridge = bridge; + public FeedContentStorage(FeedContentBridge bridge) { + mFeedContentBridge = bridge; } /** Cleans up {@link FeedContentStorage}. */ public void destroy() { - assert mFeedStorageBridge != null; - mFeedStorageBridge.destroy(); - mFeedStorageBridge = null; + assert mFeedContentBridge != null; + mFeedContentBridge.destroy(); + mFeedContentBridge = null; } @Override public void get(List<String> keys, Consumer < Result < Map<String, byte[]>>> consumer) { - assert mFeedStorageBridge != null; - mFeedStorageBridge.loadContent(keys, new StorageCallback<Map<String, byte[]>>(consumer)); + assert mFeedContentBridge != null; + mFeedContentBridge.loadContent(keys, new StorageCallback<Map<String, byte[]>>(consumer)); } @Override public void getAll(String prefix, Consumer < Result < Map<String, byte[]>>> consumer) { - assert mFeedStorageBridge != null; - mFeedStorageBridge.loadContentByPrefix( + assert mFeedContentBridge != null; + mFeedContentBridge.loadContentByPrefix( prefix, new StorageCallback<Map<String, byte[]>>(consumer)); } @Override public void commit(ContentMutation mutation, Consumer<CommitResult> consumer) { - assert mFeedStorageBridge != null; - - CommitCallback callback = new CommitCallback(consumer, mutation.getOperations().size()); - for (ContentOperation operation : mutation.getOperations()) { - switch (operation.getType()) { - case Type.UPSERT: - // TODO(gangwu): If upserts are continuous, we should conbine them into one - // array, and then send to native side. - Upsert upsert = (Upsert) operation; - String[] upsertKeys = {upsert.getKey()}; - byte[][] upsertData = {upsert.getValue()}; - mFeedStorageBridge.saveContent(upsertKeys, upsertData, callback); - break; - case Type.DELETE: - // TODO(gangwu): If deletes are continuous, we should conbine them into one - // array, and then send to native side. - Delete delete = (Delete) operation; - List<String> deleteKeys = Collections.singletonList(delete.getKey()); - mFeedStorageBridge.deleteContent(deleteKeys, callback); - break; - case Type.DELETE_BY_PREFIX: - DeleteByPrefix deleteByPrefix = (DeleteByPrefix) operation; - String prefix = deleteByPrefix.getPrefix(); - mFeedStorageBridge.deleteContentByPrefix(prefix, callback); - break; - case Type.DELETE_ALL: - mFeedStorageBridge.deleteAllContent(callback); - break; - default: - // Unsupport type of operations, so cannot performance the operation. - callback.onResult(false); - break; - } - } + assert mFeedContentBridge != null; + CommitCallback callback = new CommitCallback(consumer); + mFeedContentBridge.commitContentMutation(mutation, callback); } @Override public void getAllKeys(Consumer < Result < List<String>>> consumer) { - assert mFeedStorageBridge != null; - mFeedStorageBridge.loadAllContentKeys(new StorageCallback<List<String>>(consumer)); + assert mFeedContentBridge != null; + mFeedContentBridge.loadAllContentKeys(new GetAllKeysCallback(consumer)); } }
diff --git a/chrome/android/feed/feed_java_sources.gni b/chrome/android/feed/feed_java_sources.gni index e4cecd3..1e10ef2 100644 --- a/chrome/android/feed/feed_java_sources.gni +++ b/chrome/android/feed/feed_java_sources.gni
@@ -10,6 +10,7 @@ feed_java_sources = [ "//chrome/android/feed/core/java/src/org/chromium/chrome/browser/feed/FeedBasicLogging.java", + "//chrome/android/feed/core/java/src/org/chromium/chrome/browser/feed/FeedContentBridge.java", "//chrome/android/feed/core/java/src/org/chromium/chrome/browser/feed/FeedContentStorage.java", "//chrome/android/feed/core/java/src/org/chromium/chrome/browser/feed/FeedEventReporter.java", "//chrome/android/feed/core/java/src/org/chromium/chrome/browser/feed/FeedImageLoader.java",
diff --git a/chrome/android/java/res/layout/data_reduction_stats_layout.xml b/chrome/android/java/res/layout/data_reduction_stats_layout.xml index 690f3f20..a42efe8 100644 --- a/chrome/android/java/res/layout/data_reduction_stats_layout.xml +++ b/chrome/android/java/res/layout/data_reduction_stats_layout.xml
@@ -18,7 +18,6 @@ android:layout_marginTop="8dp" android:gravity="center_horizontal" android:drawablePadding="3dp" - android:drawableTop="@drawable/data_reduction_big" android:text="@string/data_reduction_initial_title" android:textAppearance="@style/BlackDisabledText1" />
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/omnibox/UrlBarViewBinder.java b/chrome/android/java/src/org/chromium/chrome/browser/omnibox/UrlBarViewBinder.java index 8a6fff8..f0df4dd 100644 --- a/chrome/android/java/src/org/chromium/chrome/browser/omnibox/UrlBarViewBinder.java +++ b/chrome/android/java/src/org/chromium/chrome/browser/omnibox/UrlBarViewBinder.java
@@ -43,7 +43,10 @@ } else if (UrlBarProperties.FOCUS_CHANGE_CALLBACK.equals(propertyKey)) { final Callback<Boolean> focusChangeCallback = model.getValue(UrlBarProperties.FOCUS_CHANGE_CALLBACK); - view.setOnFocusChangeListener((v, focused) -> focusChangeCallback.onResult(focused)); + view.setOnFocusChangeListener((v, focused) -> { + if (focused) view.setIgnoreTextChangesForAutocomplete(false); + focusChangeCallback.onResult(focused); + }); } else if (UrlBarProperties.SHOW_CURSOR.equals(propertyKey)) { view.setCursorVisible(model.getValue(UrlBarProperties.SHOW_CURSOR)); } else if (UrlBarProperties.TEXT_CONTEXT_MENU_DELEGATE.equals(propertyKey)) {
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/preferences/datareduction/DataReductionStatsPreference.java b/chrome/android/java/src/org/chromium/chrome/browser/preferences/datareduction/DataReductionStatsPreference.java index bffefe1..b72f787 100644 --- a/chrome/android/java/src/org/chromium/chrome/browser/preferences/datareduction/DataReductionStatsPreference.java +++ b/chrome/android/java/src/org/chromium/chrome/browser/preferences/datareduction/DataReductionStatsPreference.java
@@ -15,6 +15,7 @@ import android.content.Context; import android.content.DialogInterface; import android.preference.Preference; +import android.support.graphics.drawable.VectorDrawableCompat; import android.support.v7.app.AlertDialog; import android.text.format.DateUtils; import android.util.AttributeSet; @@ -274,6 +275,10 @@ protected void onBindView(View view) { super.onBindView(view); mInitialDataSavingsTextView = (TextView) view.findViewById(R.id.initial_data_savings); + mInitialDataSavingsTextView.setCompoundDrawablesWithIntrinsicBounds(null, + VectorDrawableCompat.create(getContext().getResources(), + R.drawable.data_reduction_big, getContext().getTheme()), + null, null); mDataSavingsSummaryContainer = (LinearLayout) view.findViewById(R.id.data_savings_summary_container); mDataUsageTextView = (TextView) view.findViewById(R.id.data_reduction_usage);
diff --git a/chrome/android/javatests/AndroidManifest.xml b/chrome/android/javatests/AndroidManifest.xml index ca993846..828cf7a 100644 --- a/chrome/android/javatests/AndroidManifest.xml +++ b/chrome/android/javatests/AndroidManifest.xml
@@ -59,6 +59,5 @@ <instrumentation android:name="org.chromium.base.test.BaseChromiumAndroidJUnitRunner" android:targetPackage="{{manifest_package}}" - android:label="Tests for {{manifest_package}}" - chromium-junit4="true"/> + android:label="Tests for {{manifest_package}}"/> </manifest>
diff --git a/chrome/android/javatests/src/org/chromium/chrome/browser/toolbar/BrandColorTest.java b/chrome/android/javatests/src/org/chromium/chrome/browser/toolbar/BrandColorTest.java index b120806..58e24d7b 100644 --- a/chrome/android/javatests/src/org/chromium/chrome/browser/toolbar/BrandColorTest.java +++ b/chrome/android/javatests/src/org/chromium/chrome/browser/toolbar/BrandColorTest.java
@@ -31,6 +31,7 @@ import org.chromium.chrome.browser.tab.TabObserver; import org.chromium.chrome.browser.tab.TabTestUtils; import org.chromium.chrome.browser.util.ColorUtils; +import org.chromium.chrome.browser.util.FeatureUtilities; import org.chromium.chrome.test.ChromeActivityTestRule; import org.chromium.chrome.test.ChromeJUnit4ClassRunner; import org.chromium.chrome.test.util.DisableInTabbedMode; @@ -104,8 +105,9 @@ mActivityTestRule.startMainActivityWithURL(url); mToolbar = (ToolbarPhone) mActivityTestRule.getActivity().findViewById(R.id.toolbar); mToolbarDataProvider = mToolbar.getToolbarDataProvider(); - mDefaultColor = ApiCompatibilityUtils.getColor( - mActivityTestRule.getActivity().getResources(), R.color.default_primary_color); + mDefaultColor = + ColorUtils.getDefaultThemeColor(mActivityTestRule.getActivity().getResources(), + FeatureUtilities.isChromeModernDesignEnabled(), /* isIncognito =*/false); } /**
diff --git a/chrome/android/javatests/src/org/chromium/chrome/browser/widget/OverviewListLayoutTest.java b/chrome/android/javatests/src/org/chromium/chrome/browser/widget/OverviewListLayoutTest.java index ca16c51..bea17a21 100644 --- a/chrome/android/javatests/src/org/chromium/chrome/browser/widget/OverviewListLayoutTest.java +++ b/chrome/android/javatests/src/org/chromium/chrome/browser/widget/OverviewListLayoutTest.java
@@ -218,8 +218,13 @@ } }); - TestTouchUtils.performClickOnMainSync( - InstrumentationRegistry.getInstrumentation(), item.findViewById(R.id.close_btn)); + if (FeatureUtilities.isChromeModernDesignEnabled()) { + TestTouchUtils.performClickOnMainSync(InstrumentationRegistry.getInstrumentation(), + item.findViewById(R.id.close_btn_modern)); + } else { + TestTouchUtils.performClickOnMainSync(InstrumentationRegistry.getInstrumentation(), + item.findViewById(R.id.close_btn)); + } didReceiveClosureCommittedHelper.waitForCallback(0);
diff --git a/chrome/android/junit/src/org/chromium/chrome/browser/feed/FeedContentStorageTest.java b/chrome/android/junit/src/org/chromium/chrome/browser/feed/FeedContentStorageTest.java index 36ae6f4..b4e5ea1 100644 --- a/chrome/android/junit/src/org/chromium/chrome/browser/feed/FeedContentStorageTest.java +++ b/chrome/android/junit/src/org/chromium/chrome/browser/feed/FeedContentStorageTest.java
@@ -54,7 +54,7 @@ public static final byte[] CONTENT_DATA3 = "CONTENT_DATA_3".getBytes(Charset.forName("UTF-8")); @Mock - private FeedStorageBridge mBridge; + private FeedContentBridge mBridge; @Mock private Consumer<CommitResult> mBooleanConsumer; @Mock @@ -74,13 +74,13 @@ @Captor private ArgumentCaptor<List<String>> mStringListArgument; @Captor - private ArgumentCaptor<String[]> mStringArrayArgument; + private ArgumentCaptor<ContentMutation> mContentMutationArgument; @Captor private ArgumentCaptor<byte[][]> mByteArrayOfArrayArgument; @Captor private ArgumentCaptor<Callback<Boolean>> mBooleanCallbackArgument; @Captor - private ArgumentCaptor < Callback < List<String>>> mStringListCallbackArgument; + private ArgumentCaptor<Callback<String[]>> mArrayOfStringCallbackArgument; @Captor private ArgumentCaptor < Callback < Map<String, byte[]>>> mMapCallbackArgument; @@ -96,11 +96,11 @@ }; } - private Answer<Void> createStringListAnswer(List<String> stringList) { + private Answer<Void> createArrayOfStringAnswer(String[] arrayOfString) { return new Answer<Void>() { @Override public Void answer(InvocationOnMock invocation) { - mStringListCallbackArgument.getValue().onResult(stringList); + mArrayOfStringCallbackArgument.getValue().onResult(arrayOfString); return null; } }; @@ -129,11 +129,12 @@ } } - private void verifyStringListResult( - List<String> expectedList, boolean expectedBoolean, Result<List<String>> actualResult) { + private void verifyArrayOfStringResult( + String[] expectedArray, boolean expectedBoolean, Result<List<String>> actualResult) { assertEquals(expectedBoolean, actualResult.isSuccessful()); if (!expectedBoolean) return; + List<String> expectedList = Arrays.asList(expectedArray); List<String> actualList = actualResult.getValue(); assertEquals(expectedList.size(), actualList.size()); for (String expectedString : expectedList) { @@ -186,40 +187,24 @@ @Test @SmallTest public void getAllKeysTest() { - List<String> answerStrings = Arrays.asList(CONTENT_KEY1, CONTENT_KEY2, CONTENT_KEY3); - Answer<Void> answer = createStringListAnswer(answerStrings); - doAnswer(answer).when(mBridge).loadAllContentKeys(mStringListCallbackArgument.capture()); + String[] answerStrings = {CONTENT_KEY1, CONTENT_KEY2, CONTENT_KEY3}; + Answer<Void> answer = createArrayOfStringAnswer(answerStrings); + doAnswer(answer).when(mBridge).loadAllContentKeys(mArrayOfStringCallbackArgument.capture()); mContentStorage.getAllKeys(mListConsumer); - verify(mBridge, times(1)).loadAllContentKeys(mStringListCallbackArgument.capture()); + verify(mBridge, times(1)).loadAllContentKeys(mArrayOfStringCallbackArgument.capture()); verify(mListConsumer, times(1)).accept(mStringListCaptor.capture()); - verifyStringListResult(answerStrings, true, mStringListCaptor.getValue()); + verifyArrayOfStringResult(answerStrings, true, mStringListCaptor.getValue()); } @Test @SmallTest public void commitTest() { - Answer<Void> answerSaveContent = createBooleanAnswer(true); - doAnswer(answerSaveContent) + Answer<Void> answerCommitContent = createBooleanAnswer(true); + doAnswer(answerCommitContent) .when(mBridge) - .saveContent(mStringArrayArgument.capture(), mByteArrayOfArrayArgument.capture(), - mBooleanCallbackArgument.capture()); - - Answer<Void> answerDeleteContent = createBooleanAnswer(true); - doAnswer(answerDeleteContent) - .when(mBridge) - .deleteContent(mStringListArgument.capture(), mBooleanCallbackArgument.capture()); - - Answer<Void> answerDeleteContentByPrefix = createBooleanAnswer(true); - doAnswer(answerDeleteContentByPrefix) - .when(mBridge) - .deleteContentByPrefix( - mStringArgument.capture(), mBooleanCallbackArgument.capture()); - - Answer<Void> answerDeleteAllContent = createBooleanAnswer(true); - doAnswer(answerDeleteAllContent) - .when(mBridge) - .deleteAllContent(mBooleanCallbackArgument.capture()); + .commitContentMutation( + mContentMutationArgument.capture(), mBooleanCallbackArgument.capture()); mContentStorage.commit(new ContentMutation.Builder() .upsert(CONTENT_KEY1, CONTENT_DATA1) @@ -229,14 +214,8 @@ .build(), mBooleanConsumer); verify(mBridge, times(1)) - .saveContent(mStringArrayArgument.capture(), mByteArrayOfArrayArgument.capture(), - mBooleanCallbackArgument.capture()); - verify(mBridge, times(1)) - .deleteContent(mStringListArgument.capture(), mBooleanCallbackArgument.capture()); - verify(mBridge, times(1)) - .deleteContentByPrefix( - mStringArgument.capture(), mBooleanCallbackArgument.capture()); - verify(mBridge, times(1)).deleteAllContent(mBooleanCallbackArgument.capture()); + .commitContentMutation( + mContentMutationArgument.capture(), mBooleanCallbackArgument.capture()); verify(mBooleanConsumer, times(1)).accept(mCommitResultCaptor.capture()); CommitResult commitResult = mCommitResultCaptor.getValue();
diff --git a/chrome/android/sync_shell/javatests/AndroidManifest.xml b/chrome/android/sync_shell/javatests/AndroidManifest.xml index a0e7c86..f7e8762 100644 --- a/chrome/android/sync_shell/javatests/AndroidManifest.xml +++ b/chrome/android/sync_shell/javatests/AndroidManifest.xml
@@ -19,6 +19,5 @@ </application> <instrumentation android:name="org.chromium.base.test.BaseChromiumAndroidJUnitRunner" android:targetPackage="{{manifest_package}}" - android:label="Tests for {{manifest_package}}" - chromium-junit4="true"/> + android:label="Tests for {{manifest_package}}"/> </manifest>
diff --git a/chrome/app/chrome_command_ids.h b/chrome/app/chrome_command_ids.h index a42b8205..1f25eca 100644 --- a/chrome/app/chrome_command_ids.h +++ b/chrome/app/chrome_command_ids.h
@@ -179,7 +179,6 @@ #define IDC_CUSTOMIZE_TOUCH_BAR 40251 #define IDC_SHOW_BETA_FORUM 40252 #define IDC_TOGGLE_JAVASCRIPT_APPLE_EVENTS 40253 -#define IDC_TOGGLE_CONFIRM_TO_QUIT_OPTION 40254 // Spell-check // Insert any additional suggestions before _LAST; these have to be consecutive.
diff --git a/chrome/app/chrome_main_delegate.cc b/chrome/app/chrome_main_delegate.cc index e2f656d8..8e4c81c 100644 --- a/chrome/app/chrome_main_delegate.cc +++ b/chrome/app/chrome_main_delegate.cc
@@ -789,8 +789,14 @@ // Register component_updater PathProvider after DIR_USER_DATA overidden by // command line flags. Maybe move the chrome PathProvider down here also? + int alt_preinstalled_components_dir = +#if defined(OS_CHROMEOS) + chromeos::DIR_PREINSTALLED_COMPONENTS; +#else + chrome::DIR_INTERNAL_PLUGINS; +#endif component_updater::RegisterPathProvider(chrome::DIR_COMPONENTS, - chrome::DIR_INTERNAL_PLUGINS, + alt_preinstalled_components_dir, chrome::DIR_USER_DATA); #if !defined(OS_ANDROID) && !defined(OS_WIN)
diff --git a/chrome/app/chromeos_strings.grdp b/chrome/app/chromeos_strings.grdp index 60c7e3c..1d3830c 100644 --- a/chrome/app/chromeos_strings.grdp +++ b/chrome/app/chromeos_strings.grdp
@@ -4852,24 +4852,6 @@ <message name="IDS_ASSISTANT_THIRD_PARTY_SCREEN_TITLE" desc="Title for assitant third party screen."> Google Partners work with your Assistant to help you </message> - <message name="IDS_ASSISTANT_CONFIRM_SCREEN_TITLE" desc="Title for assistant confirm screen."> - Get the full Assistant experience with these settings - </message> - <message name="IDS_ASSISTANT_CONFIRM_SCREEN_ACCEPT_TITLE" desc="Title for accept assistant confirm screen."> - Yes I'm In - </message> - <message name="IDS_ASSISTANT_CONFIRM_SCREEN_ACCEPT_MESSAGE" desc="Message for accept assistant confirm screen."> - To help you with your calendar, reminders, flights and more, your Assistant needs the Web & App Activity, Device Information, Voice & Audio Activity settings. - </message> - <message name="IDS_ASSISTANT_CONFIRM_SCREEN_ACCEPT_MESSAGE_EXPANDED" desc="Extra message for accept assistant confirm screen."> - Note: The data these settings control may be saved and used in any Google service where you are signed in to give you personalized experiences and useful ads. You can see your data, delete it and change your settings at account.google.com. - </message> - <message name="IDS_ASSISTANT_CONFIRM_SCREEN_REJECT_TITLE" desc="Title for reject assistant confirm screen."> - No Thanks - </message> - <message name="IDS_ASSISTANT_CONFIRM_SCREEN_REJECT_MESSAGE" desc="Message for reject assistant confirm screen."> - Depending on your account settings, your Assistant experience may be limited to things like web results, jokes, and local info. - </message> <message name="IDS_ASSISTANT_CONTINUE_BUTTON" desc="Continue button for asssitant optin flow."> Continue </message>
diff --git a/chrome/app/generated_resources.grd b/chrome/app/generated_resources.grd index f0f1e5c8..c572ac4 100644 --- a/chrome/app/generated_resources.grd +++ b/chrome/app/generated_resources.grd
@@ -5212,12 +5212,8 @@ </if> <if expr="is_win or (is_linux and not chromeos)"> - <!-- Confirm to quit panel --> - <message name="IDS_CONFIRM_TO_QUIT_DESCRIPTION" desc="Instructions for how the user should confirm quitting."> - Hold |<ph name="ACCELERATOR1">$1<ex>Ctrl</ex></ph>|+|<ph name="ACCELERATOR2">$2<ex>Shift</ex></ph>|+|<ph name="ACCELERATOR3">$3<ex>Q</ex></ph>| to exit - </message> - <message name="IDS_CONFIRM_TO_QUIT_OPTION" desc="The label of the checkbox preference that enables the confirm-to-quit feature."> - Warn before exiting (<ph name="KEY_EQUIVALENT">$1<ex>Ctrl+Shift+Q</ex></ph>) + <message name="IDS_QUIT_ACCELERATOR_TUTORIAL" desc="Instructions for how the user should quit using keyboard shortcuts."> + Press |<ph name="ACCELERATOR1">$1<ex>Ctrl</ex></ph>|+|<ph name="ACCELERATOR2">$2<ex>Shift</ex></ph>| followed by |<ph name="ACCELERATOR3">$3<ex>Q</ex></ph>| to exit </message> </if> @@ -5278,6 +5274,12 @@ <message name="IDS_FEEDBACK_INCLUDE_PERFORMANCE_TRACE_CHECKBOX" desc="Checkbox for including system performance data on the bug report dialog box"> Send performance trace data </message> + <message name="IDS_FEEDBACK_BLUETOOTH_LOGS_CHECKBOX" desc="Checkbox for including bluetooth logs"> + Attach <ph name="BEGIN_LINK"><a href="#" id="bluetooth-logs-info-link"></ph>Bluetooth Logs<ph name="END_LINK"></a></ph> (Google internal) + </message> + <message name="IDS_FEEDBACK_BLUETOOTH_LOGS_MESSAGE" desc="Message shown after user clicks on the bluetooth logs hyperlink"> + To better diagnose Bluetooth issues, Googlers can include additional Bluetooth logs with their feedback reports. When this option is checked, your report will include btsnoop and HCI logs from your current session, sanitized to remove as much PII as possible. Access to these logs will be restricted to managers of the Chrome OS product group in Listnr. Logs will be purged after 90 days. + </message> <message name="IDS_FEEDBACK_OFFLINE_DIALOG_TITLE" desc="The title of the message box displayed when the user attempts to send a report while offline"> Feedback Report </message> @@ -9037,99 +9039,144 @@ <!-- Web-modal dialog shown during Web Authenticaton API requests. --> <if expr="is_win or is_macosx or desktop_linux or chromeos"> - <message name="IDS_WEBAUTHN_INITIAL_SHEET_TITLE" desc="Title of the dialog shown when a web site wants to register/verify a user's security key through the Web Authentication API."> - <ph name="APP_NAME">$1<ex>google.com</ex></ph> wants to verify your identity + <message name="IDS_WEBAUTHN_GENERIC_TITLE" desc="Title of most dialogs shown while the user is authenticating on a web site using a Security Key."> + Use your Security Key with <ph name="APP_NAME">$1<ex>google.com</ex></ph> </message> - <message name="IDS_WEBAUTHN_INITIAL_SHEET_DESCRIPTION" desc="Contents of the dialog shown when a web site wants to register/verify a user's security key through the Web Authentication API."> - Verifying your identity helps protect your private data + <message name="IDS_WEBAUTHN_WELCOME_SCREEN_TITLE" desc="Title of the dialog shown the very first time the user wants to authenticate on a web site using a Security Key."> + <ph name="APP_NAME">$1<ex>google.com</ex></ph> wants to verify your identity </message> - <message name="IDS_WEBAUTHN_INITIAL_SHEET_NEXT" desc="Contents of the button shown to let the user continue to register/verify his/her identity via using a security key."> + <message name="IDS_WEBAUTHN_WELCOME_SCREEN_DESCRIPTION" desc="Description in the dialog shown the very first time the user wants to authenticate on a web site using a Security Key."> + Verifying your identity helps protect your personal information + </message> + <message name="IDS_WEBAUTHN_WELCOME_SCREEN_NEXT" desc="Button text to continue using a Security Key for authentication on the web for the very first time."> Continue </message> - <message name="IDS_WEBAUTHN_TRANSPORT_SELECTION_TITLE" desc="Title of the dialog shown when instructing the user to choose transport type to use to register/verfify using a security key."> - Verify your identity with <ph name="APP_NAME">$1<ex>google.com</ex></ph> + <message name="IDS_WEBAUTHN_TRANSPORT_SELECTION_TITLE" desc="Title of the dialog instructing the user to choose how they want to connect their Security Key with their computer, e.g. USB or Bluetooth."> + Verify your identity with <ph name="APP_NAME">$1<ex>google.com</ex></ph> </message> - <message name="IDS_WEBAUTHN_TRANSPORT_SELECTION_DESCRIPTION" desc="Contents of the dialog shown when instructing the user to choose transport type for the security key to be used by the Web Authentication API."> + <message name="IDS_WEBAUTHN_TRANSPORT_SELECTION_DESCRIPTION" desc="Description in the dialog instructing the user to choose how they want to connect their Security Key with their computer, e.g. USB or Bluetooth."> Pick an option </message> - <message name="IDS_WEBAUTHN_TRANSPORT_BLE" desc="Use a Security Key with the Web Authentication API over Bluetooth Low Energy."> - Use your Security Key with Bluetooth + <message name="IDS_WEBAUTHN_TRANSPORT_BLE" desc="Menu item text. The user selects this to use a Security Key (an external physcial device for user authentication) connected to the computer over Bluetooth Low Energy."> + Bluetooth Security Key </message> - <message name="IDS_WEBAUTHN_TRANSPORT_USB" desc="Use a Security Key with the Web Authentication API over Universal Serial Bus (USB)."> - Use your Security Key with USB + <message name="IDS_WEBAUTHN_TRANSPORT_USB" desc="Menu item text. The user selects this to use a Security Key (an external physical device for user authentication) plugged in to the USB port of the computer."> + USB Security Key </message> - <message name="IDS_WEBAUTHN_TRANSPORT_NFC" desc="Use a Security Key with the Web Authentication API over Near-Field Communication (NFC)."> - Use your Security Key with NFC + <message name="IDS_WEBAUTHN_TRANSPORT_NFC" desc="Menu item text. The user selects this to use a Security Key (an external physical device for user authentication) connected to the computer over Near-Field Communication."> + NFC Security Key </message> - <message name="IDS_WEBAUTHN_TRANSPORT_INTERNAL" desc="Use a Security Key with the Web Authentication API that is built in to the platform, such as Touch ID or Face ID."> - Use a built-in Security Key + <message name="IDS_WEBAUTHN_TRANSPORT_INTERNAL" desc="Menu item text. The user selects this to use a hardware-based authentication mechanism that is built in to the computer, such as a fingerprint reader."> + Built-in sensor </message> - <message name="IDS_WEBAUTHN_TRANSPORT_CABLE" desc="Use a phone as a Security Key over cloud-assisted BLE with the Web Authentication API."> - Use your phone as a Security Key + <message name="IDS_WEBAUTHN_TRANSPORT_CABLE" desc="Menu item text. The user selects this to use their phone, once connected to their computer over Bluetooth Low Energy, to sign in to web site on their computer."> + Your phone </message> - <message name="IDS_WEBAUTHN_USB_TITLE_ON_REGISTER" desc="Title of the dialog shown when the user has choosen to access their security key through USB during registration."> - Use USB Security Key - </message> - <message name="IDS_WEBAUTHN_USB_TITLE_ON_SIGNIN" desc="Title of the dialog shown when the user has choosen to access their security key through USB during sign-in."> - Use USB Security Key with <ph name="APP_NAME">$1<ex>google.com</ex></ph> - </message> - <message name="IDS_WEBAUTHN_USB_INSERT_DESCRIPTION" desc="Contents of the dialog shown instructing the user to plug in their USB security key."> + <message name="IDS_WEBAUTHN_USB_ACTIVATE_DESCRIPTION" desc="Description in the dialog instructing the user to plug in and activate (e.g. press a button on) their USB Security Key (an external physcial device for user authentication)."> Plug in your Security Key and activate it </message> - <message name="IDS_WEBAUTHN_TIMEOUT_TITLE" desc="Title of the dialog shown when the Web Authentication request times out."> - Time out + <message name="IDS_WEBAUTHN_USB_SUCCESS_TITLE" desc="Title of the dialog informing the user that Chrome detected that they activated (e.g. pressed a button on) an external physical device used for authentication."> + Touch registered... </message> - <message name="IDS_WEBAUTHN_TIMEOUT_DESCRIPTION" desc="Contents of the dialog shown when Web Authentication request times out due to inactivity or error."> + <message name="IDS_WEBAUTHN_ERROR_GENERIC_TITLE" desc="Title of most dialogs shown when an error occurs while the user trying to sign in to a web site using a hardware-based authentication mechanism."> + Something went wrong... + </message> + <message name="IDS_WEBAUTHN_ERROR_WRONG_KEY_DESCRIPTION" desc="Description in the dialog informing the user that they are trying to use the wrong Security Key (an external physical device for user authentication) to sign in to a given web site, that is, not the one they have previously registered on that site." meaning="Here, `key` refers to a Security Key, an external physical device for user authentication."> + You have registered with a different key before + </message> + <message name="IDS_WEBAUTHN_ERROR_TIMEOUT_DESCRIPTION" desc="Description in the dialog shown when the user takes too long to sign in to a web site using a hardware-based authentication mechanism."> The request timed out </message> - <message name="IDS_WEBAUTHN_BLE_POWER_ON_MANUAL_TITLE" desc="Title of the dialog shown when instructing the user to manually turn on Bluetooth so that security keys can be used over Bluetooth."> - Turn on Bluetooth + <message name="IDS_WEBAUTHN_ERROR_NO_TRANSPORTS_DESCRIPTION" desc="Description in the dialog shown when the user's could not sign in to a web site, because their computer did not support any of the hardware-based authentication mechanisms desired by the web site."> + We could not verify your identity on this device </message> - <message name="IDS_WEBAUTHN_BLE_POWER_ON_MANUAL_DESCRIPTION" desc="Contents of the dialog shown instructing the user to turn on bluetooth so that security keys can be used over Bluetooth."> + <message name="IDS_WEBAUTHN_BLUETOOTH_POWER_ON_AUTO_TITLE" desc="Title of the dialog informing the user that Chrome needs to turn on Bluetooth by itself so that Security Keys can be used over Bluetooth."> + Turn on Bluetooth? + </message> + <message name="IDS_WEBAUTHN_BLUETOOTH_POWER_ON_AUTO_DESCRIPTION" desc="Description in the dialog informing the user that Chrome needs to turn on Bluetooth by itself so that Security Keys (external physical devices for user authentication) can be used over Bluetooth."> + Bluetooth will be temporarily turned on to communicate with your Security Key + </message> + <message name="IDS_WEBAUTHN_BLUETOOTH_POWER_ON_AUTO_NEXT" desc="Button text to allow Chrome to turn on Bluetooth so that Security Keys can be used over Bluetooth."> + Turn on + </message> + <message name="IDS_WEBAUTHN_BLUETOOTH_POWER_ON_MANUAL_TITLE" desc="Title of the dialog requesting the user to manually turn on Bluetooth so that Security Keys can be used over Bluetooth."> + Turn on Bluetooth? + </message> + <message name="IDS_WEBAUTHN_BLUETOOTH_POWER_ON_MANUAL_DESCRIPTION" desc="Description in the dialog requesting the user to manually turn on Bluetooth so that Security Keys (external physical devices for user authentication)can be used over Bluetooth."> Your Security Key only works when your device's Bluetooth is on </message> - <message name="IDS_WEBAUTHN_BLE_POWER_ON_MANUAL_TRY_AGAIN" desc="Contents of the button shown to let the user restart the Bluetooth pairing process with Bluetooth powered on."> + <message name="IDS_WEBAUTHN_BLUETOOTH_POWER_ON_MANUAL_NEXT" desc="Button text. The user clicks this once they manually turned on Bluetooth, so that Chrome would retry connecting to Security Keys over Bluetooth."> Try again </message> - <message name="IDS_WEBAUTHN_BLE_PAIRING_BEGIN_TITLE" desc="Title of the dialog shown when preparing the user to pair Bluetooth security key."> + <message name="IDS_WEBAUTHN_BLE_PAIRING_BEGIN_TITLE" desc="Title of the dialog explaining to the user that they first need to pair a Bluetooth Security Key (an external physical device for user authentication) with their computer, and only after they can use it to sign in to web sites on their computer."> Ready to pair your Security Key? </message> - <message name="IDS_WEBAUTHN_BLE_PAIRING_BEGIN_DESCRIPTION" desc="Contents of the dialog shown when initiating the user to pair Bluetooth security key."> + <message name="IDS_WEBAUTHN_BLE_PAIRING_BEGIN_DESCRIPTION" desc="Description in the dialog explaining to the user that they first need to pair a Bluetooth Security Key (an external physical device for user authentication) with their computer, and only after they can use it to sign in to web sites on their computer." meaning="Here, `key` refers to a Security Key, an external physical device for user authentication."> Pair your key to this device so you can use it to sign into your account </message> - <message name="IDS_WEBAUTHN_BLE_PAIRING_BEGIN_START" desc="Contents of the button that lets the user initiate Bluetooth pairing process."> - Begin + <message name="IDS_WEBAUTHN_BLE_PAIRING_BEGIN_NEXT" desc="Button text to initiate pairing of a Bluetooth Security Key with their computer."> + Begin </message> - <message name="IDS_WEBAUTHN_BLE_ENTER_PAIRING_MODE_TITLE" desc="Title of the dialog shown when instructing the user to put security key into pairing mode."> - Allow the use of your Security Key - </message> - <message name="IDS_WEBAUTHN_BLE_ENTER_PAIRING_MODE_DESCRIPTION" desc="Contents of the dialog shown when instructing the user to put security key into pairing mode."> + <message name="IDS_WEBAUTHN_BLE_ENTER_PAIRING_MODE_DESCRIPTION" desc="Description in the dialog instructing the user to put their Bluetooth Security Key (an external physical device for user authentication) into pairing mode. This is achieved by holding down the button on the device for 5 seconds, or longer."> Press and hold the button on your Security Key for at least 5 seconds </message> - <message name="IDS_WEBAUTHN_BLE_DEVICE_SELECTION_TITLE" desc="Title of the dialog shown when instructing the user to select security key to connect."> + <message name="IDS_WEBAUTHN_BLE_DEVICE_SELECTION_TITLE" desc="Title of the dialog instructing the user to select their Bluetooth Security Key (an external physical device for user authentication) from a list of nearby Bluetooth devices. The user can identify their Security Key in the list by the name printed on the back of the Security Key."> Select your Security Key </message> - <message name="IDS_WEBAUTHN_BLE_DEVICE_SELECTION_DESCRIPTION" desc="Contents of the dialog shown when instructing the user to select his/her security key from list of near by BLE devices."> + <message name="IDS_WEBAUTHN_BLE_DEVICE_SELECTION_DESCRIPTION" desc="Description in the dialog instructing the user to select their Bluetooth Security Key (an external physical device for user authentication) from a list of nearby Bluetooth devices. The user can identify their Security Key in the list by the name printed on the back of the Security Key." meaning="Here, `key` refers to a Security Key, an external physical device for user authentication."> Find the name printed on the back of your key </message> - <message name="IDS_WEBAUTHN_BLE_PIN_ENTRY_TITLE" desc="Title of the dialog shown when instructing the user to enter the PIN code to pair a Bluetooth security key."> + <message name="IDS_WEBAUTHN_BLE_DEVICE_SELECTION_SEARCHING_LABEL" desc="Label text. Displayed while Chrome is scanning for nearby Bluetooth devices."> + Searching... + </message> + <message name="IDS_WEBAUTHN_BLE_DEVICE_SELECTION_REMINDER_LABEL" desc="Label text. Reminds the user that their Bluetooth Security Key (an external physical device for user authentication) will only show up in the list of nearby Bluetooth devices if they put it into pairing mode. This is achieved by holding down the button on the device for 5 seconds, or longer." meaning="Here, `key` refers to a Security Key, an external physical device for user authentication."> + To see your Security Key, it needs to be in pairing mode. Press the button on your key for at least 5 seconds. + </message> + <message name="IDS_WEBAUTHN_BLE_PIN_ENTRY_TITLE" desc="Title of the dialog shown when instructing the user to enter the PIN code (a 6-digit number) to pair a Bluetooth Security Key (an external physical device for user authentication) with their computer."> Pair with <ph name="DEVICE_NAME">$1<ex>VHGSHSSN</ex></ph> </message> - <message name="IDS_WEBAUTHN_BLE_PIN_ENTRY_DESCRIPTION" desc="Contents of the dialog shown when instructing the user to enter the PIN code to pair a Bluetooth security key."> - Find the 6-digit PIN on the back of your key + <message name="IDS_WEBAUTHN_BLE_PIN_ENTRY_DESCRIPTION" desc="Description in the dialog shown when instructing the user to enter the PIN code to pair a Bluetooth Security Key (an external physical device for user authentication) with their computer. The PIN code is a 6-digit secret number written on the back of the device." meaning="Here, `key` refers to a Security Key, an external physical device for user authentication."> + Find the 6-digit PIN on the back of your key </message> - <message name="IDS_WEBAUTHN_BLE_PIN_ENTRY_NEXT" desc="Contents of the button that lets the user continue the pairing process with the entered Bluetooth PIN code."> - Next + <message name="IDS_WEBAUTHN_BLE_PIN_ENTRY_PIN_LABEL" desc="Label text. Displayed next to a text box where the user enters the PIN code (a 6-digit number) to pair a Bluetooth device."> + Pin </message> - <message name="IDS_WEBAUTHN_BLE_VERIFYING_TITLE" desc="Title of the dialog shown when the user has established BLE connection with the security key."> - Verifying your Security Key + <message name="IDS_WEBAUTHN_BLE_PIN_ENTRY_NEXT" desc="Button text. The user clicks this button once they have entered the PIN code (a 6-digit number) into a text vbox, so that the pairing of the Bluetooth device can continue."> + Next </message> - <message name="IDS_WEBAUTHN_BLE_ACTIVATE_TITLE" desc="Title of the dialog shown when the user tries to sign-in using a security key."> - Use your Security Key with <ph name="APP_NAME">$1<ex>airbnb.com</ex></ph> + <message name="IDS_WEBAUTHN_BLE_OS_PIN_ENTRY_TITLE" desc="Description in the dialog instructing the user to enter the PIN code to pair a Bluetooth Security Key (an external physical device for user authentication) with their computer. The PIN code is a 6-digit secret number written on the back of the device." meaning="Here, `key` refers to a Security Key, an external physical device for user authentication."> + Find the 6-digit PIN on the back of your key </message> - <message name="IDS_WEBAUTHN_BLE_ACTIVATE_DESCRIPTION" desc="Contents of the dialog shown when the user tries to sign-in using a security key."> + <message name="IDS_WEBAUTHN_BLE_OS_PIN_ENTRY_DESCRIPTION" desc="Description in the drepresenting using the user's phone as a physical device that is connected to the user's computer over Bluetooth Low Energy to authenticate the user on the web.ialog shown when instructing the user to enter the PIN code to pair a Bluetooth Security Key (an external physical device for user authentication)."> + Continue when you're ready to enter the PIN + </message> + <message name="IDS_WEBAUTHN_BLE_VERIFYING_TITLE" desc="Title of the dialog informing the user that verifying a Bluetooth Security Key (an external physical device for user authentication) is in progress."> + Verifying your Security Key... + </message> + <message name="IDS_WEBAUTHN_BLE_ACTIVATE_DESCRIPTION" desc="Description in the dialog instructing the user to activate (e.g. press a button on) their Bluetooth Security Key (an external physical device for user authentication)." meaning="Here, `key` refers to a Security Key, an external physical device for user authentication."> To use most keys, simply press the button - </message> + </message> + <message name="IDS_WEBAUTHN_TRANSPORT_POPUP_LABEL" desc="Menu item text. The user selects this to verify their identity on a web site (i.e. sign in) using a different hardware-based authentication mechanism from what they have selected previously."> + Choose another option + </message> + <message name="IDS_WEBAUTHN_TRANSPORT_POPUP_USB" desc="Menu item text. The user selects this to verify their identity on a web site (i.e. sign in) using a Security Key (an external physcial device for user authentication) plugged in to the USB port of the computer."> + Verify via USB + </message> + <message name="IDS_WEBAUTHN_TRANSPORT_POPUP_BLE" desc="Menu item text. The user selects this to verify their identity on a web site (i.e. sign in) using a Security Key (an external physcial device for user authentication) connected to the user's computer over Bluetooth Low Energy."> + Verify via Bluetooth + </message> + <message name="IDS_WEBAUTHN_TRANSPORT_POPUP_ANOTHER_BLE" desc="Menu item text. The user selects this to verify their identity on a web site (i.e. sign in) using a Bluetooth Security Key (an external physcial device for user authentication connected over Bluetooth Low Energy) that they haven't used on this computer before."> + Add another Bluetooth Security Key + </message> + <message name="IDS_WEBAUTHN_TRANSPORT_POPUP_NFC" desc="Menu item text. The user selects this to verify their identity on a web site (i.e. sign in) using a Security Key (an external physcial device for user authentication) connected to the computer over Near-Field Communication."> + Verify via NFC + </message> + <message name="IDS_WEBAUTHN_TRANSPORT_POPUP_INTERNAL" desc="Menu item text. The user selects this to verify their identity on a web site (i.e. sign in) using a hardware-based authentication mechanism that is built in to the computer, such as a fingerprint reader."> + Verify via built-in sensor + </message> + <message name="IDS_WEBAUTHN_TRANSPORT_POPUP_CABLE" desc="Menu item text. The user selects this to verify their identity on a web site (i.e. sign in) using their phone. They wirelessly connect their phone to their computer over Bluetooth Low Energy, and then use the phone to sign in to web sites on their computer."> + Verify via your phone + </message> </if> <if expr="is_macosx"> <message name="IDS_WEBAUTHN_TOUCH_ID_TITLE" desc="Title of the dialog shown when the user tries to sign in with Touch ID." meaning="'Touch ID' is the fingerprint recognition feature in macOS. Try to refer Apple support documentation in the target language for the appropriate product name translation.">
diff --git a/chrome/browser/BUILD.gn b/chrome/browser/BUILD.gn index 0f4b800e..22fce03 100644 --- a/chrome/browser/BUILD.gn +++ b/chrome/browser/BUILD.gn
@@ -4384,6 +4384,8 @@ if (enable_feed_in_chrome) { sources += [ + "android/feed/feed_content_bridge.cc", + "android/feed/feed_content_bridge.h", "android/feed/feed_host_service_factory.cc", "android/feed/feed_host_service_factory.h", "android/feed/feed_image_loader_bridge.cc", @@ -4658,6 +4660,7 @@ if (enable_feed_in_chrome) { sources += [ + "../android/feed/core/java/src/org/chromium/chrome/browser/feed/FeedContentBridge.java", "../android/feed/core/java/src/org/chromium/chrome/browser/feed/FeedImageLoaderBridge.java", "../android/feed/core/java/src/org/chromium/chrome/browser/feed/FeedNetworkBridge.java", "../android/feed/core/java/src/org/chromium/chrome/browser/feed/FeedSchedulerBridge.java",
diff --git a/chrome/browser/about_flags.cc b/chrome/browser/about_flags.cc index bc08939a..ac3c338d 100644 --- a/chrome/browser/about_flags.cc +++ b/chrome/browser/about_flags.cc
@@ -795,7 +795,7 @@ const FeatureEntry::FeatureParam kAutofillPreviewStyleBlackOnBlue050[] = { {blink::features::kAutofillPreviewStyleExperimentBgColorParameterName, - "#E8F0F3"}, + "#E8F0FE"}, {blink::features::kAutofillPreviewStyleExperimentColorParameterName, "#000000"}, }; @@ -807,7 +807,7 @@ }; const FeatureEntry::FeatureParam kAutofillPreviewStyleBlue900OnBlue050[] = { {blink::features::kAutofillPreviewStyleExperimentBgColorParameterName, - "#E8F0F3"}, + "#E8F0FE"}, {blink::features::kAutofillPreviewStyleExperimentColorParameterName, "#174EA6"}, }; @@ -1668,6 +1668,10 @@ flag_descriptions::kNotificationIndicatorName, flag_descriptions::kNotificationIndicatorDescription, kOsCrOS, FEATURE_VALUE_TYPE(features::kNotificationIndicator)}, + {"enable-app-list-search-autocomplete", + flag_descriptions::kEnableAppListSearchAutocompleteName, + flag_descriptions::kEnableAppListSearchAutocompleteDescription, kOsCrOS, + FEATURE_VALUE_TYPE(app_list::features::kEnableAppListSearchAutocomplete)}, { "enable-pinch", flag_descriptions::kPinchScaleName, flag_descriptions::kPinchScaleDescription, kOsLinux | kOsWin | kOsCrOS, @@ -2551,11 +2555,6 @@ flag_descriptions::kEnableInputImeApiDescription, kOsWin | kOsLinux, ENABLE_DISABLE_VALUE_TYPE(switches::kEnableInputImeAPI, switches::kDisableInputImeAPI)}, -#if !defined(OS_CHROMEOS) - {"warn-before-quitting", flag_descriptions::kWarnBeforeQuittingFlagName, - flag_descriptions::kWarnBeforeQuittingFlagDescription, kOsWin | kOsLinux, - FEATURE_VALUE_TYPE(features::kWarnBeforeQuitting)}, -#endif // OS_CHROMEOS #endif // OS_WIN || OS_LINUX {"enable-origin-trials", flag_descriptions::kOriginTrialsName, flag_descriptions::kOriginTrialsDescription, kOsAll,
diff --git a/chrome/browser/android/feed/feed_content_bridge.cc b/chrome/browser/android/feed/feed_content_bridge.cc new file mode 100644 index 0000000..c641f6b --- /dev/null +++ b/chrome/browser/android/feed/feed_content_bridge.cc
@@ -0,0 +1,205 @@ +// 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/android/feed/feed_content_bridge.h" + +#include <jni.h> + +#include <list> +#include <memory> +#include <utility> + +#include "base/android/callback_android.h" +#include "base/android/jni_array.h" +#include "base/android/jni_string.h" +#include "base/bind.h" +#include "base/threading/thread_task_runner_handle.h" +#include "chrome/browser/android/feed/feed_host_service_factory.h" +#include "chrome/browser/profiles/profile.h" +#include "chrome/browser/profiles/profile_android.h" +#include "components/feed/core/feed_content_database.h" +#include "components/feed/core/feed_content_mutation.h" +#include "components/feed/core/feed_host_service.h" +#include "jni/FeedContentBridge_jni.h" +#include "ui/gfx/android/java_bitmap.h" +#include "ui/gfx/image/image.h" + +namespace feed { + +using base::android::AppendJavaStringArrayToStringVector; +using base::android::AttachCurrentThread; +using base::android::ConvertJavaStringToUTF8; +using base::android::JavaArrayOfByteArrayToStringVector; +using base::android::JavaIntArrayToIntVector; +using base::android::JavaRef; +using base::android::JavaParamRef; +using base::android::ScopedJavaGlobalRef; +using base::android::ScopedJavaLocalRef; +using base::android::ToJavaArrayOfByteArray; +using base::android::ToJavaArrayOfStrings; +using base::android::JavaByteArrayToByteVector; + +static jlong JNI_FeedContentBridge_Init( + JNIEnv* env, + const JavaParamRef<jobject>& j_this, + const JavaParamRef<jobject>& j_profile) { + Profile* profile = ProfileAndroid::FromProfileAndroid(j_profile); + FeedHostService* host_service = + FeedHostServiceFactory::GetForBrowserContext(profile); + DCHECK(host_service); + FeedContentDatabase* feed_content_database = + host_service->GetContentDatabase(); + DCHECK(feed_content_database); + FeedContentBridge* native_content_bridge = + new FeedContentBridge(feed_content_database); + return reinterpret_cast<intptr_t>(native_content_bridge); +} + +FeedContentBridge::FeedContentBridge(FeedContentDatabase* feed_content_database) + : feed_content_database_(feed_content_database), weak_ptr_factory_(this) {} + +FeedContentBridge::~FeedContentBridge() = default; + +void FeedContentBridge::Destroy(JNIEnv* env, const JavaRef<jobject>& j_this) { + delete this; +} + +void FeedContentBridge::LoadContent(JNIEnv* j_env, + const JavaRef<jobject>& j_this, + const JavaRef<jobjectArray>& j_keys, + const JavaRef<jobject>& j_callback) { + std::vector<std::string> keys; + AppendJavaStringArrayToStringVector(j_env, j_keys.obj(), &keys); + ScopedJavaGlobalRef<jobject> callback(j_callback); + + feed_content_database_->LoadContent( + keys, base::BindOnce(&FeedContentBridge::OnLoadContentDone, + weak_ptr_factory_.GetWeakPtr(), callback)); +} + +void FeedContentBridge::LoadContentByPrefix( + JNIEnv* j_env, + const JavaRef<jobject>& j_this, + const JavaRef<jstring>& j_prefix, + const JavaRef<jobject>& j_callback) { + std::string prefix = ConvertJavaStringToUTF8(j_env, j_prefix); + ScopedJavaGlobalRef<jobject> callback(j_callback); + + feed_content_database_->LoadContentByPrefix( + prefix, base::BindOnce(&FeedContentBridge::OnLoadContentDone, + weak_ptr_factory_.GetWeakPtr(), callback)); +} + +void FeedContentBridge::LoadAllContentKeys(JNIEnv* j_env, + const JavaRef<jobject>& j_this, + const JavaRef<jobject>& j_callback) { + ScopedJavaGlobalRef<jobject> callback(j_callback); + + feed_content_database_->LoadAllContentKeys( + base::BindOnce(&FeedContentBridge::OnLoadAllContentKeysDone, + weak_ptr_factory_.GetWeakPtr(), callback)); +} + +void FeedContentBridge::CommitContentMutation( + JNIEnv* j_env, + const JavaRef<jobject>& j_this, + const JavaRef<jobject>& j_callback) { + DCHECK(content_mutation_); + ScopedJavaGlobalRef<jobject> callback(j_callback); + + feed_content_database_->CommitContentMutation( + std::move(content_mutation_), + base::BindOnce(&FeedContentBridge::OnStorageCommitDone, + weak_ptr_factory_.GetWeakPtr(), callback)); +} + +void FeedContentBridge::CreateContentMutation(JNIEnv* j_env, + const JavaRef<jobject>& j_this) { + DCHECK(!content_mutation_); + content_mutation_ = std::make_unique<ContentMutation>(); +} + +void FeedContentBridge::DeleteContentMutation(JNIEnv* j_env, + const JavaRef<jobject>& j_this) { + DCHECK(content_mutation_); + content_mutation_.reset(); +} + +void FeedContentBridge::AppendDeleteOperation(JNIEnv* j_env, + const JavaRef<jobject>& j_this, + const JavaRef<jstring>& j_key) { + DCHECK(content_mutation_); + std::string key(ConvertJavaStringToUTF8(j_env, j_key)); + + content_mutation_->AppendDeleteOperation(key); +} + +void FeedContentBridge::AppendDeleteByPrefixOperation( + JNIEnv* j_env, + const JavaRef<jobject>& j_this, + const JavaRef<jstring>& j_prefix) { + DCHECK(content_mutation_); + std::string prefix(ConvertJavaStringToUTF8(j_env, j_prefix)); + + content_mutation_->AppendDeleteByPrefixOperation(prefix); +} + +void FeedContentBridge::AppendUpsertOperation( + JNIEnv* j_env, + const JavaRef<jobject>& j_this, + const JavaRef<jstring>& j_key, + const JavaRef<jbyteArray>& j_data) { + DCHECK(content_mutation_); + std::string key(ConvertJavaStringToUTF8(j_env, j_key)); + std::vector<uint8_t> byte_vector; + JavaByteArrayToByteVector(j_env, j_data.obj(), &byte_vector); + + content_mutation_->AppendUpsertOperation( + key, std::string(byte_vector.begin(), byte_vector.end())); +} + +void FeedContentBridge::AppendDeleteAllOperation( + JNIEnv* j_env, + const JavaRef<jobject>& j_this) { + DCHECK(content_mutation_); + + content_mutation_->AppendDeleteAllOperation(); +} + +void FeedContentBridge::OnLoadContentDone( + ScopedJavaGlobalRef<jobject> callback, + std::vector<FeedContentDatabase::KeyAndData> pairs) { + std::vector<std::string> keys; + std::vector<std::string> data; + for (auto pair : pairs) { + keys.push_back(std::move(pair.first)); + data.push_back(std::move(pair.second)); + } + + JNIEnv* env = AttachCurrentThread(); + ScopedJavaLocalRef<jobjectArray> j_keys = ToJavaArrayOfStrings(env, keys); + ScopedJavaLocalRef<jobjectArray> j_data = ToJavaArrayOfByteArray(env, data); + + // Create Java Map by JNI call. + ScopedJavaLocalRef<jobject> j_pairs = + Java_FeedContentBridge_createKeyAndDataMap(env, j_keys, j_data); + RunObjectCallbackAndroid(callback, j_pairs); +} + +void FeedContentBridge::OnLoadAllContentKeysDone( + ScopedJavaGlobalRef<jobject> callback, + std::vector<std::string> keys) { + JNIEnv* env = AttachCurrentThread(); + ScopedJavaLocalRef<jobjectArray> j_keys = ToJavaArrayOfStrings(env, keys); + + RunObjectCallbackAndroid(callback, j_keys); +} + +void FeedContentBridge::OnStorageCommitDone( + ScopedJavaGlobalRef<jobject> callback, + bool success) { + RunBooleanCallbackAndroid(callback, success); +} + +} // namespace feed
diff --git a/chrome/browser/android/feed/feed_content_bridge.h b/chrome/browser/android/feed/feed_content_bridge.h new file mode 100644 index 0000000..ecc1d7a --- /dev/null +++ b/chrome/browser/android/feed/feed_content_bridge.h
@@ -0,0 +1,88 @@ +// 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_ANDROID_FEED_FEED_CONTENT_BRIDGE_H_ +#define CHROME_BROWSER_ANDROID_FEED_FEED_CONTENT_BRIDGE_H_ + +#include <memory> +#include <string> +#include <vector> + +#include "base/android/scoped_java_ref.h" +#include "base/memory/weak_ptr.h" +#include "components/feed/core/feed_content_database.h" + +namespace feed { + +class FeedContentDatabase; + +// Native counterpart of FeedContentBridge.java. Holds non-owning pointers +// to native implementation to which operations are delegated. Results are +// passed back by a single argument callback so +// base::android::RunBooleanCallbackAndroid() and +// base::android::RunObjectCallbackAndroid() can be used. This bridge is +// instantiated, owned, and destroyed from Java. +class FeedContentBridge { + public: + explicit FeedContentBridge(FeedContentDatabase* feed_Storage_database); + ~FeedContentBridge(); + + void Destroy(JNIEnv* j_env, const base::android::JavaRef<jobject>& j_this); + + void LoadContent(JNIEnv* j_env, + const base::android::JavaRef<jobject>& j_this, + const base::android::JavaRef<jobjectArray>& j_keys, + const base::android::JavaRef<jobject>& j_callback); + void LoadContentByPrefix(JNIEnv* j_env, + const base::android::JavaRef<jobject>& j_this, + const base::android::JavaRef<jstring>& j_prefix, + const base::android::JavaRef<jobject>& j_callback); + void LoadAllContentKeys(JNIEnv* j_env, + const base::android::JavaRef<jobject>& j_this, + const base::android::JavaRef<jobject>& j_callback); + void CommitContentMutation(JNIEnv* j_env, + const base::android::JavaRef<jobject>& j_this, + const base::android::JavaRef<jobject>& j_callback); + + void CreateContentMutation(JNIEnv* j_env, + const base::android::JavaRef<jobject>& j_this); + void DeleteContentMutation(JNIEnv* j_env, + const base::android::JavaRef<jobject>& j_this); + void AppendDeleteOperation(JNIEnv* j_env, + const base::android::JavaRef<jobject>& j_this, + const base::android::JavaRef<jstring>& j_key); + void AppendDeleteByPrefixOperation( + JNIEnv* j_env, + const base::android::JavaRef<jobject>& j_this, + const base::android::JavaRef<jstring>& j_prefix); + void AppendUpsertOperation(JNIEnv* j_env, + const base::android::JavaRef<jobject>& j_this, + const base::android::JavaRef<jstring>& j_key, + const base::android::JavaRef<jbyteArray>& j_data); + void AppendDeleteAllOperation(JNIEnv* j_env, + const base::android::JavaRef<jobject>& j_this); + + private: + void OnLoadContentDone(base::android::ScopedJavaGlobalRef<jobject> callback, + std::vector<FeedContentDatabase::KeyAndData> pairs); + void OnLoadAllContentKeysDone( + base::android::ScopedJavaGlobalRef<jobject> callback, + std::vector<std::string> keys); + void OnStorageCommitDone(base::android::ScopedJavaGlobalRef<jobject> callback, + bool success); + + // This unique_ptr will hold a list of ContentOperations which are not + // committed yet. After commit to database, this unique_ptr will be reset. + std::unique_ptr<ContentMutation> content_mutation_; + + FeedContentDatabase* feed_content_database_; + + base::WeakPtrFactory<FeedContentBridge> weak_ptr_factory_; + + DISALLOW_COPY_AND_ASSIGN(FeedContentBridge); +}; + +} // namespace feed + +#endif // CHROME_BROWSER_ANDROID_FEED_FEED_CONTENT_BRIDGE_H_
diff --git a/chrome/browser/android/feed/feed_host_service_factory.cc b/chrome/browser/android/feed/feed_host_service_factory.cc index 40d9749..1da9140c 100644 --- a/chrome/browser/android/feed/feed_host_service_factory.cc +++ b/chrome/browser/android/feed/feed_host_service_factory.cc
@@ -15,6 +15,7 @@ #include "chrome/browser/search/suggestions/image_decoder_impl.h" #include "chrome/browser/signin/identity_manager_factory.h" #include "chrome/common/channel_info.h" +#include "components/feed/core/feed_content_database.h" #include "components/feed/core/feed_host_service.h" #include "components/feed/core/feed_image_manager.h" #include "components/feed/core/feed_networking_host.h" @@ -90,9 +91,12 @@ auto storage_database = std::make_unique<FeedStorageDatabase>(feed_dir); + auto content_database = std::make_unique<FeedContentDatabase>(feed_dir); + return new FeedHostService( std::move(image_manager), std::move(networking_host), - std::move(scheduler_host), std::move(storage_database)); + std::move(scheduler_host), std::move(storage_database), + std::move(content_database)); } content::BrowserContext* FeedHostServiceFactory::GetBrowserContextToUse(
diff --git a/chrome/browser/android/vr/gvr_controller_delegate.cc b/chrome/browser/android/vr/gvr_controller_delegate.cc index 6dc08616..1985b58 100644 --- a/chrome/browser/android/vr/gvr_controller_delegate.cc +++ b/chrome/browser/android/vr/gvr_controller_delegate.cc
@@ -55,22 +55,22 @@ ControllerModel controller_model; controller_->GetTransform(&controller_model.transform); - controller_model.touchpad_button_state = PlatformController::ButtonState::kUp; + controller_model.touchpad_button_state = ControllerModel::ButtonState::kUp; DCHECK(!(controller_->ButtonUpHappened(PlatformController::kButtonSelect) && controller_->ButtonDownHappened(PlatformController::kButtonSelect))) << "Cannot handle a button down and up event within one frame."; if (controller_->ButtonState(gvr::kControllerButtonClick)) { controller_model.touchpad_button_state = - PlatformController::ButtonState::kDown; + ControllerModel::ButtonState::kDown; } controller_model.app_button_state = controller_->ButtonState(gvr::kControllerButtonApp) - ? PlatformController::ButtonState::kDown - : PlatformController::ButtonState::kUp; + ? ControllerModel::ButtonState::kDown + : ControllerModel::ButtonState::kUp; controller_model.home_button_state = controller_->ButtonState(gvr::kControllerButtonHome) - ? PlatformController::ButtonState::kDown - : PlatformController::ButtonState::kUp; + ? ControllerModel::ButtonState::kDown + : ControllerModel::ButtonState::kUp; controller_model.opacity = controller_->GetOpacity(); controller_model.laser_direction = controller_direction; controller_model.laser_origin = controller_->GetPointerStart(); @@ -121,7 +121,8 @@ // Set handedness. state->description->handedness = - controller_->GetHandedness() == PlatformController::kRightHanded + controller_->GetHandedness() == + ControllerModel::Handedness::kRightHanded ? device::mojom::XRHandedness::RIGHT : device::mojom::XRHandedness::LEFT;
diff --git a/chrome/browser/android/vr/vr_controller.cc b/chrome/browser/android/vr/vr_controller.cc index c0c6bc9..5900c57 100644 --- a/chrome/browser/android/vr/vr_controller.cc +++ b/chrome/browser/android/vr/vr_controller.cc
@@ -153,10 +153,10 @@ return last_button_timestamp_; } -PlatformController::Handedness VrController::GetHandedness() const { +ControllerModel::Handedness VrController::GetHandedness() const { return handedness_ == GVR_CONTROLLER_RIGHT_HANDED - ? PlatformController::kRightHanded - : PlatformController::kLeftHanded; + ? ControllerModel::kRightHanded + : ControllerModel::kLeftHanded; } bool VrController::GetRecentered() const {
diff --git a/chrome/browser/android/vr/vr_controller.h b/chrome/browser/android/vr/vr_controller.h index 061a66c..e58b023 100644 --- a/chrome/browser/android/vr/vr_controller.h +++ b/chrome/browser/android/vr/vr_controller.h
@@ -80,7 +80,7 @@ base::TimeTicks GetLastOrientationTimestamp() const override; base::TimeTicks GetLastTouchTimestamp() const override; base::TimeTicks GetLastButtonTimestamp() const override; - PlatformController::Handedness GetHandedness() const override; + ControllerModel::Handedness GetHandedness() const override; bool GetRecentered() const override; int GetBatteryLevel() const override;
diff --git a/chrome/browser/chrome_browser_field_trials_desktop.cc b/chrome/browser/chrome_browser_field_trials_desktop.cc index e72df79..e40383e 100644 --- a/chrome/browser/chrome_browser_field_trials_desktop.cc +++ b/chrome/browser/chrome_browser_field_trials_desktop.cc
@@ -89,11 +89,15 @@ GUID guid; DWORD age; - pe.GetDebugId(&guid, &age, /* pdb_file= */ nullptr); - module.age = age; - static_assert(sizeof(module.identifier) >= sizeof(guid), - "Identifier field must be able to contain a GUID."); - memcpy(module.identifier, &guid, sizeof(guid)); + if (pe.GetDebugId(&guid, &age, /* pdb_filename= */ nullptr, + /* pdb_filename_length= */ nullptr)) { + module.age = age; + static_assert(sizeof(module.identifier) >= sizeof(guid), + "Identifier field must be able to contain a GUID."); + memcpy(module.identifier, &guid, sizeof(guid)); + } else { + memset(module.identifier, 0, sizeof(module.identifier)); + } module.file = "chrome.dll"; module.debug_file = "chrome.dll.pdb";
diff --git a/chrome/browser/chromeos/accessibility/select_to_speak_event_handler.cc b/chrome/browser/chromeos/accessibility/select_to_speak_event_handler.cc index 91777ec2..454527859 100644 --- a/chrome/browser/chromeos/accessibility/select_to_speak_event_handler.cc +++ b/chrome/browser/chromeos/accessibility/select_to_speak_event_handler.cc
@@ -92,9 +92,7 @@ } void SelectToSpeakEventHandler::OnKeyEvent(ui::KeyEvent* event) { - if (!IsSelectToSpeakEnabled()) - return; - + DCHECK(IsSelectToSpeakEnabled()); DCHECK(event); // We can only call TtsController on the UI thread, make sure we @@ -163,9 +161,7 @@ } void SelectToSpeakEventHandler::OnMouseEvent(ui::MouseEvent* event) { - if (!IsSelectToSpeakEnabled()) - return; - + DCHECK(IsSelectToSpeakEnabled()); DCHECK(event); if (state_ == INACTIVE) { if (event->type() == ui::ET_MOUSE_PRESSED) { @@ -209,9 +205,7 @@ } void SelectToSpeakEventHandler::OnTouchEvent(ui::TouchEvent* event) { - if (!IsSelectToSpeakEnabled()) - return; - + DCHECK(IsSelectToSpeakEnabled()); DCHECK(event); if (state_ == INACTIVE && event->type() == ui::ET_TOUCH_PRESSED) {
diff --git a/chrome/browser/chromeos/policy/DEPS b/chrome/browser/chromeos/policy/DEPS index 19a7f86..a4f1c9827 100644 --- a/chrome/browser/chromeos/policy/DEPS +++ b/chrome/browser/chromeos/policy/DEPS
@@ -3,12 +3,3 @@ "+components/invalidation", "+components/user_manager", ] - -specific_include_rules = { - # TODO(mash): http://crbug.com/705713. - "display_rotation_default_handler\.*": [ - "+ash/display/window_tree_host_manager.h", - "+ash/shell.h", - "+ash/shell_observer.h", - ], -}
diff --git a/chrome/browser/chromeos/policy/display_rotation_default_handler.cc b/chrome/browser/chromeos/policy/display_rotation_default_handler.cc index 5906801..34277ba 100644 --- a/chrome/browser/chromeos/policy/display_rotation_default_handler.cc +++ b/chrome/browser/chromeos/policy/display_rotation_default_handler.cc
@@ -6,79 +6,97 @@ #include <stddef.h> -#include "ash/shell.h" +#include "ash/public/interfaces/constants.mojom.h" #include "base/bind.h" #include "base/bind_helpers.h" #include "base/location.h" #include "base/logging.h" #include "base/memory/ref_counted.h" #include "base/single_thread_task_runner.h" +#include "base/strings/string_number_conversions.h" #include "base/threading/thread_task_runner_handle.h" #include "chromeos/settings/cros_settings_names.h" -#include "ui/display/manager/display_manager.h" +#include "content/public/common/service_manager_connection.h" +#include "services/service_manager/public/cpp/connector.h" namespace policy { DisplayRotationDefaultHandler::DisplayRotationDefaultHandler() { - ash::Shell::Get()->window_tree_host_manager()->AddObserver(this); - ash::Shell::Get()->AddShellObserver(this); settings_observer_ = chromeos::CrosSettings::Get()->AddSettingsObserver( chromeos::kDisplayRotationDefault, base::Bind(&DisplayRotationDefaultHandler::OnCrosSettingsChanged, base::Unretained(this))); + + content::ServiceManagerConnection::GetForProcess() + ->GetConnector() + ->BindInterface(ash::mojom::kServiceName, &cros_display_config_); + + // Make the initial display unit info request. This will be queued until the + // Ash service is ready. + cros_display_config_->GetDisplayUnitInfoList( + false /* single_unified */, + base::BindOnce(&DisplayRotationDefaultHandler::OnGetInitialDisplayInfo, + weak_ptr_factory_.GetWeakPtr())); } -DisplayRotationDefaultHandler::~DisplayRotationDefaultHandler() { +DisplayRotationDefaultHandler::~DisplayRotationDefaultHandler() = default; + +void DisplayRotationDefaultHandler::OnDisplayConfigChanged() { + RequestAndRotateDisplays(); } -void DisplayRotationDefaultHandler::OnShellInitialized() { +void DisplayRotationDefaultHandler::OnGetInitialDisplayInfo( + std::vector<ash::mojom::DisplayUnitInfoPtr> info_list) { + // Add this as an observer to the mojo service now that it is ready. + // (We only care about changes that occur after we set any policy + // rotation below). + ash::mojom::CrosDisplayConfigObserverAssociatedPtrInfo ptr_info; + cros_display_config_observer_binding_.Bind(mojo::MakeRequest(&ptr_info)); + cros_display_config_->AddObserver(std::move(ptr_info)); + + // Get the initial policy values from CrosSettings and apply any rotation. UpdateFromCrosSettings(); - RotateDisplays(); + RotateDisplays(std::move(info_list)); } -void DisplayRotationDefaultHandler::OnDisplayConfigurationChanged() { - RotateDisplays(); -} - -void DisplayRotationDefaultHandler::OnWindowTreeHostManagerShutdown() { - ash::Shell::Get()->window_tree_host_manager()->RemoveObserver(this); - ash::Shell::Get()->RemoveShellObserver(this); - settings_observer_.reset(); - base::ThreadTaskRunnerHandle::Get()->DeleteSoon(FROM_HERE, this); +void DisplayRotationDefaultHandler::RequestAndRotateDisplays() { + cros_display_config_->GetDisplayUnitInfoList( + false /* single_unified */, + base::BindOnce(&DisplayRotationDefaultHandler::RotateDisplays, + weak_ptr_factory_.GetWeakPtr())); } void DisplayRotationDefaultHandler::OnCrosSettingsChanged() { if (!UpdateFromCrosSettings()) return; // Policy changed, so reset all displays. - rotated_displays_.clear(); - RotateDisplays(); + rotated_display_ids_.clear(); + RequestAndRotateDisplays(); } -void DisplayRotationDefaultHandler::RotateDisplays() { - if (!policy_enabled_ || rotation_in_progress_) +void DisplayRotationDefaultHandler::RotateDisplays( + std::vector<ash::mojom::DisplayUnitInfoPtr> info_list) { + if (!policy_enabled_) return; - // Avoid nested calls of this function due to OnDisplayConfigurationChanged - // being called by rotations here. - rotation_in_progress_ = true; + for (const ash::mojom::DisplayUnitInfoPtr& display_unit_info : info_list) { + std::string display_id = display_unit_info->id; + if (rotated_display_ids_.find(display_id) != rotated_display_ids_.end()) + continue; - display::DisplayManager* const display_manager = - ash::Shell::Get()->display_manager(); - const size_t num_displays = display_manager->GetNumDisplays(); - for (size_t i = 0; i < num_displays; ++i) { - const display::Display& display = display_manager->GetDisplayAt(i); - const int64_t id = display.id(); - if (rotated_displays_.find(id) == rotated_displays_.end()) { - rotated_displays_.insert(id); - if (display.rotation() != display_rotation_default_) { - display_manager->SetDisplayRotation( - id, display_rotation_default_, - display::Display::RotationSource::ACTIVE); - } - } + rotated_display_ids_.insert(display_id); + display::Display::Rotation rotation(display_unit_info->rotation); + if (rotation == display_rotation_default_) + continue; + + // The following sets only the |rotation| property of the display + // configuration; no other properties will be affected. + auto config_properties = ash::mojom::DisplayConfigProperties::New(); + config_properties->rotation = + ash::mojom::DisplayRotation::New(display_rotation_default_); + cros_display_config_->SetDisplayProperties( + display_unit_info->id, std::move(config_properties), base::DoNothing()); } - rotation_in_progress_ = false; } bool DisplayRotationDefaultHandler::UpdateFromCrosSettings() {
diff --git a/chrome/browser/chromeos/policy/display_rotation_default_handler.h b/chrome/browser/chromeos/policy/display_rotation_default_handler.h index 78d99f0..a02fb2d 100644 --- a/chrome/browser/chromeos/policy/display_rotation_default_handler.h +++ b/chrome/browser/chromeos/policy/display_rotation_default_handler.h
@@ -9,45 +9,51 @@ #include <memory> #include <set> +#include <string> +#include <vector> -#include "ash/display/window_tree_host_manager.h" -#include "ash/shell_observer.h" +#include "ash/public/interfaces/cros_display_config.mojom.h" #include "base/macros.h" +#include "base/memory/weak_ptr.h" #include "chrome/browser/chromeos/settings/cros_settings.h" +#include "mojo/public/cpp/bindings/associated_binding.h" #include "ui/display/display.h" namespace policy { // Enforces the device policy DisplayRotationDefault. -// This class is created in ChromeShellDelegate::PreInit() and registers -// itself with WindowTreeHostManager as Observer for display changes, and -// with CrosSettings as Observer for setting changes. Whenever there is a change -// in the display configuration, any new display with an id that is not already -// in rotated_displays_ will be rotated according to the policy. When there is a -// change to the CrosSettings, the new policy is applied to all connected -// displays. -// This class owns itself and destroys itself when OnShutdown is called by -// WindowTreeHostManager. +// This class must be constructed after CrosSettings is initialized. +// On construction this class registers itself with +// ash::mojom::CrosDisplayConfigObserver for display changes and with +// CrosSettings for settings changes. Whenever there is a change in the display +// configuration, any new display with an id that is not already in +// |rotated_display_ids_| will be rotated according to the policy. When there is +// a change to CrosSettings, the new policy is applied to all displays. +// NOTE: This only rotates displays on startup and when the policy changes. +// i.e. this will not override subsequent rotations (e.g. via Settings or an +// extension with display configuration permissions). class DisplayRotationDefaultHandler - : public ash::WindowTreeHostManager::Observer, - public ash::ShellObserver { + : public ash::mojom::CrosDisplayConfigObserver { public: DisplayRotationDefaultHandler(); ~DisplayRotationDefaultHandler() override; - // ash::ShellObserver: - void OnShellInitialized() override; - - // ash::WindowTreeHostManager::Observer: - void OnDisplayConfigurationChanged() override; - void OnWindowTreeHostManagerShutdown() override; + // ash::mojom::CrosDisplayConfigObserver + void OnDisplayConfigChanged() override; private: + // Receives the initial display info list and initializes the class. + void OnGetInitialDisplayInfo( + std::vector<ash::mojom::DisplayUnitInfoPtr> info_list); + + // Requests the list of displays and calls RotateDisplays. + void RequestAndRotateDisplays(); + // Callback function for settings_observer_. void OnCrosSettingsChanged(); // Applies the policy to all connected displays as necessary. - void RotateDisplays(); + void RotateDisplays(std::vector<ash::mojom::DisplayUnitInfoPtr> info_list); // Reads |chromeos::kDisplayRotationDefault| from CrosSettings and stores // its value, and whether it has a value, in member variables @@ -58,11 +64,13 @@ bool policy_enabled_ = false; display::Display::Rotation display_rotation_default_ = display::Display::ROTATE_0; - std::set<int64_t> rotated_displays_; - bool rotation_in_progress_ = false; - + std::set<std::string> rotated_display_ids_; + ash::mojom::CrosDisplayConfigControllerPtr cros_display_config_; + mojo::AssociatedBinding<ash::mojom::CrosDisplayConfigObserver> + cros_display_config_observer_binding_{this}; std::unique_ptr<chromeos::CrosSettings::ObserverSubscription> settings_observer_; + base::WeakPtrFactory<DisplayRotationDefaultHandler> weak_ptr_factory_{this}; DISALLOW_COPY_AND_ASSIGN(DisplayRotationDefaultHandler); };
diff --git a/chrome/browser/chromeos/policy/display_rotation_default_handler_browsertest.cc b/chrome/browser/chromeos/policy/display_rotation_default_handler_browsertest.cc index eba4277..a0a7445 100644 --- a/chrome/browser/chromeos/policy/display_rotation_default_handler_browsertest.cc +++ b/chrome/browser/chromeos/policy/display_rotation_default_handler_browsertest.cc
@@ -8,6 +8,7 @@ #include <memory> +#include "ash/display/display_configuration_controller.h" #include "ash/shell.h" #include "base/bind.h" #include "base/command_line.h" @@ -84,6 +85,7 @@ void SetUpInProcessBrowserTestFixture() override { InstallOwnerKey(); MarkAsEnterpriseOwned(); + ash::DisplayConfigurationController::DisableAnimatorForTest(); DevicePolicyCrosBrowserTest::SetUpInProcessBrowserTestFixture(); } @@ -122,8 +124,7 @@ // Creates second display if there is none yet, or removes it if there is one. void ToggleSecondDisplay() { GetDisplayManager()->AddRemoveDisplay(); - base::RunLoop run_loop; - run_loop.RunUntilIdle(); + base::RunLoop().RunUntilIdle(); } void RefreshPolicyAndWaitUntilDeviceSettingsUpdated() { @@ -138,6 +139,8 @@ chromeos::kSystemUse24HourClock, run_loop.QuitClosure()); RefreshDevicePolicy(); run_loop.Run(); + // Allow tasks posted by CrosSettings observers to complete: + base::RunLoop().RunUntilIdle(); } private: @@ -276,6 +279,7 @@ test_helper_.InstallOwnerKey(); test_helper_.MarkAsEnterpriseOwned(); + ash::DisplayConfigurationController::DisableAnimatorForTest(); } chromeos::FakeSessionManagerClient* fake_session_manager_client_; @@ -301,6 +305,8 @@ fake_session_manager_client_->set_device_policy(device_policy->GetBlob()); fake_session_manager_client_->OnPropertyChangeComplete(true); run_loop.Run(); + // Allow tasks posted by CrosSettings observers to complete: + base::RunLoop().RunUntilIdle(); // Check the display's rotation. display::DisplayManager* const display_manager = GetDisplayManager(); @@ -313,6 +319,7 @@ // the policy value is restored after reboot. display_manager->SetDisplayRotation(first_display_id, user_rotation, display::Display::RotationSource::USER); + base::RunLoop().RunUntilIdle(); EXPECT_EQ(user_rotation, first_display.rotation()); }
diff --git a/chrome/browser/chromeos/policy/policy_cert_verifier.cc b/chrome/browser/chromeos/policy/policy_cert_verifier.cc index 53c8ccab..1e160a9 100644 --- a/chrome/browser/chromeos/policy/policy_cert_verifier.cc +++ b/chrome/browser/chromeos/policy/policy_cert_verifier.cc
@@ -93,4 +93,8 @@ return error; } +void PolicyCertVerifier::SetConfig(const Config& config) { + delegate_->SetConfig(config); +} + } // namespace policy
diff --git a/chrome/browser/chromeos/policy/policy_cert_verifier.h b/chrome/browser/chromeos/policy/policy_cert_verifier.h index cb65173..4ade577 100644 --- a/chrome/browser/chromeos/policy/policy_cert_verifier.h +++ b/chrome/browser/chromeos/policy/policy_cert_verifier.h
@@ -50,6 +50,7 @@ net::CompletionOnceCallback callback, std::unique_ptr<Request>* out_req, const net::NetLogWithSource& net_log) override; + void SetConfig(const Config& config) override; private: net::CertificateList trust_anchors_;
diff --git a/chrome/browser/download/download_service_factory.cc b/chrome/browser/download/download_service_factory.cc index 619e5f7..33279dd 100644 --- a/chrome/browser/download/download_service_factory.cc +++ b/chrome/browser/download/download_service_factory.cc
@@ -28,6 +28,7 @@ #include "components/offline_pages/buildflags/buildflags.h" #include "content/public/browser/browser_context.h" #include "content/public/browser/browser_thread.h" +#include "content/public/browser/network_service_instance.h" #include "content/public/browser/storage_partition.h" #if defined(OS_ANDROID) @@ -85,8 +86,8 @@ content::BrowserThread::IO); return download::BuildInMemoryDownloadService( - context, std::move(clients), base::FilePath(), blob_context_getter, - io_task_runner); + context, std::move(clients), content::GetNetworkConnectionTracker(), + base::FilePath(), blob_context_getter, io_task_runner); } else { // Build download service for normal profile. base::FilePath storage_dir; @@ -106,9 +107,9 @@ task_scheduler = std::make_unique<DownloadTaskSchedulerImpl>(context); #endif - return download::BuildDownloadService(context, std::move(clients), - storage_dir, background_task_runner, - std::move(task_scheduler)); + return download::BuildDownloadService( + context, std::move(clients), content::GetNetworkConnectionTracker(), + storage_dir, background_task_runner, std::move(task_scheduler)); } }
diff --git a/chrome/browser/extensions/api/feedback_private/chrome_feedback_private_delegate.cc b/chrome/browser/extensions/api/feedback_private/chrome_feedback_private_delegate.cc index 5d3dbdf2..746440e 100644 --- a/chrome/browser/extensions/api/feedback_private/chrome_feedback_private_delegate.cc +++ b/chrome/browser/extensions/api/feedback_private/chrome_feedback_private_delegate.cc
@@ -77,6 +77,8 @@ SET_STRING("privacy-note", IDS_FEEDBACK_PRIVACY_NOTE); SET_STRING("performance-trace", IDS_FEEDBACK_INCLUDE_PERFORMANCE_TRACE_CHECKBOX); + SET_STRING("bluetooth-logs-info", IDS_FEEDBACK_BLUETOOTH_LOGS_CHECKBOX); + SET_STRING("bluetooth-logs-message", IDS_FEEDBACK_BLUETOOTH_LOGS_MESSAGE); // Add the localized strings needed for the "system information" page. SET_STRING("sysinfoPageTitle", IDS_FEEDBACK_SYSINFO_PAGE_TITLE); SET_STRING("sysinfoPageDescription", IDS_ABOUT_SYS_DESC);
diff --git a/chrome/browser/extensions/api/notifications/notifications_api.cc b/chrome/browser/extensions/api/notifications/notifications_api.cc index e528a26..66cfea4 100644 --- a/chrome/browser/extensions/api/notifications/notifications_api.cc +++ b/chrome/browser/extensions/api/notifications/notifications_api.cc
@@ -287,6 +287,9 @@ if (options->event_time.get()) optional_fields.timestamp = base::Time::FromJsTime(*options->event_time); + if (options->silent) + optional_fields.silent = *options->silent; + if (options->buttons.get()) { // Currently we allow up to 2 buttons. size_t number_of_buttons = options->buttons->size(); @@ -446,6 +449,9 @@ if (options->event_time) notification->set_timestamp(base::Time::FromJsTime(*options->event_time)); + if (options->silent) + notification->set_silent(*options->silent); + if (options->buttons) { // Currently we allow up to 2 buttons. size_t number_of_buttons = options->buttons->size();
diff --git a/chrome/browser/extensions/api/notifications/notifications_apitest.cc b/chrome/browser/extensions/api/notifications/notifications_apitest.cc index 5a4c1317..d597412 100644 --- a/chrome/browser/extensions/api/notifications/notifications_apitest.cc +++ b/chrome/browser/extensions/api/notifications/notifications_apitest.cc
@@ -292,6 +292,7 @@ EXPECT_EQ(base::ASCIIToUTF16(kNewTitle), notification->title()); EXPECT_EQ(base::ASCIIToUTF16(kNewMessage), notification->message()); EXPECT_EQ(kNewPriority, notification->priority()); + EXPECT_TRUE(notification->silent()); EXPECT_EQ(1u, notification->buttons().size()); EXPECT_EQ(base::ASCIIToUTF16(kButtonTitle), notification->buttons()[0].title); }
diff --git a/chrome/browser/extensions/convert_web_app.cc b/chrome/browser/extensions/convert_web_app.cc index cc4bb36c..95080f7 100644 --- a/chrome/browser/extensions/convert_web_app.cc +++ b/chrome/browser/extensions/convert_web_app.cc
@@ -25,6 +25,7 @@ #include "base/strings/utf_string_conversions.h" #include "base/time/time.h" #include "base/values.h" +#include "chrome/browser/web_applications/components/web_app_helpers.h" #include "chrome/common/chrome_paths.h" #include "chrome/common/extensions/api/url_handlers/url_handlers_parser.h" #include "chrome/common/extensions/manifest_handlers/app_theme_color_info.h" @@ -45,28 +46,9 @@ namespace keys = manifest_keys; - namespace { - const char kIconsDirName[] = "icons"; const char kScopeUrlHandlerId[] = "scope"; - -// Create the public key for the converted web app. -// -// Web apps are not signed, but the public key for an extension doubles as -// its unique identity, and we need one of those. A web app's unique identity -// is its manifest URL, so we hash that to create a public key. There will be -// no corresponding private key, which means that these extensions cannot be -// auto-updated using ExtensionUpdater. -std::string GenerateKey(const GURL& app_url) { - char raw[crypto::kSHA256Length] = {0}; - std::string key; - crypto::SHA256HashString(app_url.spec().c_str(), raw, - crypto::kSHA256Length); - base::Base64Encode(base::StringPiece(raw, crypto::kSHA256Length), &key); - return key; -} - } // namespace std::unique_ptr<base::DictionaryValue> CreateURLHandlersForBookmarkApp( @@ -159,7 +141,8 @@ // Create the manifest std::unique_ptr<base::DictionaryValue> root(new base::DictionaryValue); - root->SetString(keys::kPublicKey, GenerateKey(web_app.app_url)); + root->SetString(keys::kPublicKey, + web_app::GenerateExtensionKeyFromURL(web_app.app_url)); root->SetString(keys::kName, base::UTF16ToUTF8(web_app.title)); root->SetString(keys::kVersion, ConvertTimeToExtensionVersion(create_time)); root->SetString(keys::kDescription, base::UTF16ToUTF8(web_app.description));
diff --git a/chrome/browser/feedback/show_feedback_page.cc b/chrome/browser/feedback/show_feedback_page.cc index 4c24fdf..e355894 100644 --- a/chrome/browser/feedback/show_feedback_page.cc +++ b/chrome/browser/feedback/show_feedback_page.cc
@@ -5,6 +5,7 @@ #include <string> #include "base/metrics/histogram_macros.h" +#include "base/strings/string_util.h" #include "chrome/browser/feedback/feedback_dialog_utils.h" #include "chrome/browser/profiles/profile.h" #include "chrome/browser/ui/browser.h" @@ -13,10 +14,37 @@ #include "chrome/common/chrome_switches.h" #include "extensions/browser/api/feedback_private/feedback_private_api.h" +#if defined(OS_CHROMEOS) +#include "chrome/browser/signin/signin_manager_factory.h" +#include "components/signin/core/browser/signin_manager.h" +#endif + namespace feedback_private = extensions::api::feedback_private; namespace chrome { +namespace { + +#if defined(OS_CHROMEOS) +constexpr char kGoogleDotCom[] = "@google.com"; + +// Returns if the feedback page is considered to be triggered from user +// interaction. +bool IsFromUserInteraction(FeedbackSource source) { + switch (source) { + case kFeedbackSourceArcApp: + case kFeedbackSourceAsh: + case kFeedbackSourceBrowserCommand: + case kFeedbackSourceMdSettingsAboutPage: + case kFeedbackSourceOldSettingsAboutPage: + return true; + default: + return false; + } +} +#endif +} + void ShowFeedbackPage(Browser* browser, FeedbackSource source, const std::string& description_template, @@ -42,12 +70,25 @@ extensions::FeedbackPrivateAPI* api = extensions::FeedbackPrivateAPI::GetFactoryInstance()->Get(profile); - api->RequestFeedbackForFlow( - description_template, description_placeholder_text, category_tag, - extra_diagnostics, page_url, + feedback_private::FeedbackFlow flow = source == kFeedbackSourceSadTabPage ? feedback_private::FeedbackFlow::FEEDBACK_FLOW_SADTABCRASH - : feedback_private::FeedbackFlow::FEEDBACK_FLOW_REGULAR); + : feedback_private::FeedbackFlow::FEEDBACK_FLOW_REGULAR; + +#if defined(OS_CHROMEOS) + SigninManagerBase* signin_manager = + SigninManagerFactory::GetForProfile(profile); + if (signin_manager && + base::EndsWith(signin_manager->GetAuthenticatedAccountInfo().email, + kGoogleDotCom, base::CompareCase::INSENSITIVE_ASCII) && + IsFromUserInteraction(source)) { + flow = feedback_private::FeedbackFlow::FEEDBACK_FLOW_GOOGLEINTERNAL; + } +#endif + + api->RequestFeedbackForFlow(description_template, + description_placeholder_text, category_tag, + extra_diagnostics, page_url, flow); } } // namespace chrome
diff --git a/chrome/browser/file_select_helper.cc b/chrome/browser/file_select_helper.cc index e69763c8..c3cacba 100644 --- a/chrome/browser/file_select_helper.cc +++ b/chrome/browser/file_select_helper.cc
@@ -126,7 +126,6 @@ explicit ActiveDirectoryEnumeration(const base::FilePath& path) : rvh_(NULL), path_(path) {} - std::unique_ptr<DirectoryListerDispatchDelegate> delegate_; std::unique_ptr<net::DirectoryLister> lister_; RenderViewHost* rvh_; const base::FilePath path_; @@ -148,25 +147,6 @@ // away so they don't try and call back to us. if (select_file_dialog_.get()) select_file_dialog_->ListenerDestroyed(); - - // Stop any pending directory enumeration, prevent a callback, and free - // allocated memory. - std::map<int, ActiveDirectoryEnumeration*>::iterator iter; - for (iter = directory_enumerations_.begin(); - iter != directory_enumerations_.end(); - ++iter) { - iter->second->lister_.reset(); - delete iter->second; - } -} - -void FileSelectHelper::DirectoryListerDispatchDelegate::OnListFile( - const net::DirectoryLister::DirectoryListerData& data) { - parent_->OnListFile(id_, data); -} - -void FileSelectHelper::DirectoryListerDispatchDelegate::OnListDone(int error) { - parent_->OnListDone(id_, error); } void FileSelectHelper::FileSelected(const base::FilePath& path, @@ -245,25 +225,22 @@ void FileSelectHelper::StartNewEnumeration(const base::FilePath& path, int request_id, RenderViewHost* render_view_host) { + request_id_ = request_id; auto entry = std::make_unique<ActiveDirectoryEnumeration>(path); entry->rvh_ = render_view_host; - entry->delegate_.reset(new DirectoryListerDispatchDelegate(this, request_id)); entry->lister_.reset(new net::DirectoryLister( - path, net::DirectoryLister::NO_SORT_RECURSIVE, entry->delegate_.get())); + path, net::DirectoryLister::NO_SORT_RECURSIVE, this)); entry->lister_->Start(); - directory_enumerations_[request_id] = entry.release(); + directory_enumeration_ = std::move(entry); } void FileSelectHelper::OnListFile( - int id, const net::DirectoryLister::DirectoryListerData& data) { - ActiveDirectoryEnumeration* entry = directory_enumerations_[id]; - // Directory upload only cares about files. if (data.info.IsDirectory()) return; - entry->results_.push_back(data.path); + directory_enumeration_->results_.push_back(data.path); } void FileSelectHelper::LaunchConfirmationDialog( @@ -275,11 +252,10 @@ std::move(selected_files), web_contents_); } -void FileSelectHelper::OnListDone(int id, int error) { +void FileSelectHelper::OnListDone(int error) { // This entry needs to be cleaned up when this function is done. - std::unique_ptr<ActiveDirectoryEnumeration> entry( - directory_enumerations_[id]); - directory_enumerations_.erase(id); + std::unique_ptr<ActiveDirectoryEnumeration> entry = + std::move(directory_enumeration_); if (!entry->rvh_) return; if (error) { @@ -290,10 +266,10 @@ std::vector<ui::SelectedFileInfo> selected_files = FilePathListToSelectedFileInfoList(entry->results_); - if (id == kFileSelectEnumerationId) { + if (request_id_ == kFileSelectEnumerationId) { LaunchConfirmationDialog(entry->path_, std::move(selected_files)); } else { - entry->rvh_->DirectoryEnumerationFinished(id, entry->results_); + entry->rvh_->DirectoryEnumerationFinished(request_id_, entry->results_); EnumerateDirectoryEnd(); } }
diff --git a/chrome/browser/file_select_helper.h b/chrome/browser/file_select_helper.h index ddeab38..c755925 100644 --- a/chrome/browser/file_select_helper.h +++ b/chrome/browser/file_select_helper.h
@@ -45,7 +45,8 @@ content::BrowserThread::DeleteOnUIThread>, public ui::SelectFileDialog::Listener, public content::WebContentsObserver, - public content::RenderWidgetHostObserver { + public content::RenderWidgetHostObserver, + private net::DirectoryLister::DirectoryListerDelegate { public: // Show the file chooser dialog. static void RunFileChooser(content::RenderFrameHost* render_frame_host, @@ -69,27 +70,6 @@ explicit FileSelectHelper(Profile* profile); ~FileSelectHelper() override; - // Utility class which can listen for directory lister events and relay - // them to the main object with the correct tracking id. - class DirectoryListerDispatchDelegate - : public net::DirectoryLister::DirectoryListerDelegate { - public: - DirectoryListerDispatchDelegate(FileSelectHelper* parent, int id) - : parent_(parent), - id_(id) {} - ~DirectoryListerDispatchDelegate() override {} - void OnListFile( - const net::DirectoryLister::DirectoryListerData& data) override; - void OnListDone(int error) override; - - private: - // This FileSelectHelper owns this object. - FileSelectHelper* parent_; - int id_; - - DISALLOW_COPY_AND_ASSIGN(DirectoryListerDispatchDelegate); - }; - void RunFileChooser(content::RenderFrameHost* render_frame_host, std::unique_ptr<content::FileChooserParams> params); void GetFileTypesInThreadPool( @@ -146,11 +126,10 @@ int request_id, content::RenderViewHost* render_view_host); - // Callbacks from directory enumeration. - virtual void OnListFile( - int id, - const net::DirectoryLister::DirectoryListerData& data); - virtual void OnListDone(int id, int error); + // net::DirectoryLister::DirectoryListerDelegate overrides. + void OnListFile( + const net::DirectoryLister::DirectoryListerData& data) override; + void OnListDone(int error) override; void LaunchConfirmationDialog( const base::FilePath& path, @@ -244,11 +223,13 @@ // The mode of file dialog last shown. content::FileChooserParams::Mode dialog_mode_; - // Maintain a list of active directory enumerations. These could come from - // the file select dialog or from drag-and-drop of directories, so there could - // be more than one going on at a time. + // Maintain an active directory enumeration. These could come from the file + // select dialog or from drag-and-drop of directories. There could not be + // more than one going on at a time. struct ActiveDirectoryEnumeration; - std::map<int, ActiveDirectoryEnumeration*> directory_enumerations_; + std::unique_ptr<ActiveDirectoryEnumeration> directory_enumeration_; + // Keep |request_id| argument of EnumerateDirectory() to reply to RVH. + int request_id_; ScopedObserver<content::RenderWidgetHost, content::RenderWidgetHostObserver> observer_;
diff --git a/chrome/browser/flag_descriptions.cc b/chrome/browser/flag_descriptions.cc index 7ed258a..15bf224 100644 --- a/chrome/browser/flag_descriptions.cc +++ b/chrome/browser/flag_descriptions.cc
@@ -1123,7 +1123,7 @@ "Connect to Cast devices on all IP addresses"; const char kMediaRouterCastAllowAllIPsDescription[] = "Have the Media Router connect to Cast devices on all IP addresses, not " - "just RFC1918/RFC4913 private addresses."; + "just RFC1918/RFC4193 private addresses."; const char kMemoryCoordinatorName[] = "Memory coordinator"; const char kMemoryCoordinatorDescription[] = @@ -3136,6 +3136,12 @@ const char kDisableTabletSplitViewDescription[] = "Disable split view for Chrome OS tablet mode."; +const char kEnableAppListSearchAutocompleteName[] = + "App List Search Autocomplete"; +const char kEnableAppListSearchAutocompleteDescription[] = + "Allow App List search box to autocomplete queries for Google searches and " + "apps."; + const char kEnableAppShortcutSearchName[] = "Enable app shortcut search in launcher"; const char kEnableAppShortcutSearchDescription[] = @@ -3509,14 +3515,6 @@ const char kEnableInputImeApiDescription[] = "Enable the use of chrome.input.ime API."; -#if !defined(OS_CHROMEOS) - -const char kWarnBeforeQuittingFlagName[] = "Warn Before Quitting"; -const char kWarnBeforeQuittingFlagDescription[] = - "Confirm to quit by either holding the quit shortcut or pressing it twice."; - -#endif // !defined(OS_CHROMEOS) - #endif // defined(OS_WIN) || defined(OS_LINUX) #if defined(OS_WIN) || defined(OS_MACOSX)
diff --git a/chrome/browser/flag_descriptions.h b/chrome/browser/flag_descriptions.h index 1fd39d1..a2c89242 100644 --- a/chrome/browser/flag_descriptions.h +++ b/chrome/browser/flag_descriptions.h
@@ -1918,6 +1918,9 @@ extern const char kDisableTabletSplitViewName[]; extern const char kDisableTabletSplitViewDescription[]; +extern const char kEnableAppListSearchAutocompleteName[]; +extern const char kEnableAppListSearchAutocompleteDescription[]; + extern const char kEnableAppShortcutSearchName[]; extern const char kEnableAppShortcutSearchDescription[]; @@ -2142,13 +2145,6 @@ extern const char kEnableInputImeApiName[]; extern const char kEnableInputImeApiDescription[]; -#if !defined(OS_CHROMEOS) - -extern const char kWarnBeforeQuittingFlagName[]; -extern const char kWarnBeforeQuittingFlagDescription[]; - -#endif // !defined(OS_CHROMEOS) - #endif // defined(OS_WIN) || defined(OS_LINUX) extern const char kExperimentalUiName[];
diff --git a/chrome/browser/io_thread.cc b/chrome/browser/io_thread.cc index 7ac138b..f29a64b 100644 --- a/chrome/browser/io_thread.cc +++ b/chrome/browser/io_thread.cc
@@ -135,6 +135,12 @@ return g_cert_verifier_for_io_thread_testing->Verify( params, crl_set, verify_result, std::move(callback), out_req, net_log); } + + void SetConfig(const Config& config) override { + if (!g_cert_verifier_for_io_thread_testing) + return; + return g_cert_verifier_for_io_thread_testing->SetConfig(config); + } }; #if defined(OS_MACOSX)
diff --git a/chrome/browser/lifetime/browser_shutdown_browsertest.cc b/chrome/browser/lifetime/browser_shutdown_browsertest.cc index 3931fb3..11fbc38cd 100644 --- a/chrome/browser/lifetime/browser_shutdown_browsertest.cc +++ b/chrome/browser/lifetime/browser_shutdown_browsertest.cc
@@ -79,25 +79,12 @@ histogram_tester_.ExpectTotalCount("Shutdown.window_close.time_per_process", 1); } -#endif // !defined(OS_CHROMEOS) - -// EventGenerator doesn't work on Mac. See https://crbug.com/814675 -// Flaking on Windows. See https://crbug.com/874370 -#if defined(OS_MACOSX) || defined(OS_WIN) -#define MAYBE_ShutdownConfirmation DISABLED_ShutdownConfirmation #else -#define MAYBE_ShutdownConfirmation ShutdownConfirmation -#endif - // On Chrome OS, the shutdown accelerator is handled by Ash and requires // confirmation, so Chrome shouldn't try to shut down after it's been hit one // time. Regression test for crbug.com/834092 -IN_PROC_BROWSER_TEST_F(BrowserShutdownBrowserTest, MAYBE_ShutdownConfirmation) { -#if defined(OS_MACOSX) - const int modifiers = ui::EF_COMMAND_DOWN; -#else +IN_PROC_BROWSER_TEST_F(BrowserShutdownBrowserTest, ShutdownConfirmation) { const int modifiers = ui::EF_CONTROL_DOWN | ui::EF_SHIFT_DOWN; -#endif ui::test::EventGenerator generator(browser()->window()->GetNativeWindow()); @@ -106,9 +93,6 @@ generator.ReleaseKey(ui::VKEY_Q, modifiers); base::RunLoop().RunUntilIdle(); -#if defined(OS_CHROMEOS) EXPECT_FALSE(browser_shutdown::IsTryingToQuit()); -#else - EXPECT_TRUE(browser_shutdown::IsTryingToQuit()); -#endif } +#endif // !defined(OS_CHROMEOS)
diff --git a/chrome/browser/media/router/media_router_feature.h b/chrome/browser/media/router/media_router_feature.h index 16d8eaf..f65815f1 100644 --- a/chrome/browser/media/router/media_router_feature.h +++ b/chrome/browser/media/router/media_router_feature.h
@@ -38,7 +38,7 @@ void RegisterProfilePrefs(PrefRegistrySimple* registry); // If enabled, allows Media Router to connect to Cast devices on all IP -// addresses, not just RFC1918/RFC4913 private addresses. Workaround for +// addresses, not just RFC1918/RFC4193 private addresses. Workaround for // https://crbug.com/813974. extern const base::Feature kCastAllowAllIPsFeature;
diff --git a/chrome/browser/net/network_context_configuration_browsertest.cc b/chrome/browser/net/network_context_configuration_browsertest.cc index febb7bc..59fb3d6 100644 --- a/chrome/browser/net/network_context_configuration_browsertest.cc +++ b/chrome/browser/net/network_context_configuration_browsertest.cc
@@ -404,9 +404,7 @@ ASSERT_TRUE(simple_loader_helper.response_body()); EXPECT_EQ(*simple_loader_helper.response_body(), "Echo"); } else { - // TestHostResolver returns net::ERR_NOT_IMPLEMENTED for non-local host - // URLs. - EXPECT_EQ(net::ERR_NOT_IMPLEMENTED, simple_loader->NetError()); + EXPECT_EQ(net::ERR_NAME_NOT_RESOLVED, simple_loader->NetError()); ASSERT_FALSE(simple_loader_helper.response_body()); } } @@ -1211,18 +1209,17 @@ SetCookie(CookieType::kFirstParty, CookiePersistenceType::kPersistent); EXPECT_FALSE(GetCookies(embedded_test_server()->base_url()).empty()); + + // Flush CookieStore. The CookieStore batches disk operations, so may not have + // written the cookie to disk yet. + base::RunLoop run_loop; + network::mojom::CookieManagerPtr cookie_manager; + network_context()->GetCookieManager(mojo::MakeRequest(&cookie_manager)); + cookie_manager->FlushCookieStore(run_loop.QuitClosure()); + run_loop.Run(); } -#if defined(OS_MACOSX) -// Disable the test on Mac OSX since it fails on the bot. -// (https://crbug.com/847555) -#define MAYBE_CookiesEnabled DISABLED_CookiesEnabled -#else -#define MAYBE_CookiesEnabled CookiesEnabled -#endif - -IN_PROC_BROWSER_TEST_P(NetworkContextConfigurationBrowserTest, - MAYBE_CookiesEnabled) { +IN_PROC_BROWSER_TEST_P(NetworkContextConfigurationBrowserTest, CookiesEnabled) { // Check that the cookie from the first stage of the test was / was not // preserved between browser restarts, as expected. bool has_cookies = !GetCookies(embedded_test_server()->base_url()).empty();
diff --git a/chrome/browser/net/spdyproxy/data_reduction_proxy_chrome_io_data.cc b/chrome/browser/net/spdyproxy/data_reduction_proxy_chrome_io_data.cc index d215b80..6597f65 100644 --- a/chrome/browser/net/spdyproxy/data_reduction_proxy_chrome_io_data.cc +++ b/chrome/browser/net/spdyproxy/data_reduction_proxy_chrome_io_data.cc
@@ -30,6 +30,7 @@ #include "content/public/browser/browser_thread.h" #include "content/public/browser/navigation_controller.h" #include "content/public/browser/navigation_entry.h" +#include "content/public/browser/network_service_instance.h" #include "content/public/browser/web_contents.h" #include "url/gurl.h" @@ -98,7 +99,8 @@ data_reduction_proxy_io_data( new data_reduction_proxy::DataReductionProxyIOData( DataReductionProxyChromeSettings::GetClient(), prefs, net_log, - io_task_runner, ui_task_runner, enabled, GetUserAgent(), + content::GetNetworkConnectionTracker(), io_task_runner, + ui_task_runner, enabled, GetUserAgent(), version_info::GetChannelString(chrome::GetChannel()))); data_reduction_proxy_io_data->set_lofi_decider(
diff --git a/chrome/browser/net/trial_comparison_cert_verifier.cc b/chrome/browser/net/trial_comparison_cert_verifier.cc index b856e3d7..8cbace07 100644 --- a/chrome/browser/net/trial_comparison_cert_verifier.cc +++ b/chrome/browser/net/trial_comparison_cert_verifier.cc
@@ -44,9 +44,7 @@ namespace { -bool CheckTrialEligibility(void* profile_id, - base::TimeDelta primary_latency, - bool is_first_job) { +bool CheckTrialEligibility(void* profile_id) { DCHECK_CURRENTLY_ON(content::BrowserThread::UI); // g_browser_process is valid until after all threads are stopped. So it must @@ -59,29 +57,12 @@ // Only allow on non-incognito profiles which have SBER2 (Scout) opt-in set. // See design doc for more details: // https://docs.google.com/document/d/1AM1CD42bC6LHWjKg-Hkid_RLr2DH6OMzstH9-pGSi-g - bool allowed = !profile->IsOffTheRecord() && safe_browsing::IsScout(prefs) && - safe_browsing::IsExtendedReportingEnabled(prefs); - - if (allowed) { - // Only record the TrialPrimary histograms for the same set of requests - // that TrialSecondary histograms will be recorded for, in order to get a - // direct comparison. - UMA_HISTOGRAM_CUSTOM_TIMES("Net.CertVerifier_Job_Latency_TrialPrimary", - primary_latency, - base::TimeDelta::FromMilliseconds(1), - base::TimeDelta::FromMinutes(10), 100); - if (is_first_job) { - UMA_HISTOGRAM_CUSTOM_TIMES( - "Net.CertVerifier_First_Job_Latency_TrialPrimary", primary_latency, - base::TimeDelta::FromMilliseconds(1), - base::TimeDelta::FromMinutes(10), 100); - } - } - - return allowed; + return !profile->IsOffTheRecord() && safe_browsing::IsScout(prefs) && + safe_browsing::IsExtendedReportingEnabled(prefs); } void SendTrialVerificationReport(void* profile_id, + const net::CertVerifier::Config& config, const net::CertVerifier::RequestParams& params, const net::CertVerifyResult& primary_result, const net::CertVerifyResult& trial_result) { @@ -91,7 +72,7 @@ Profile* profile = reinterpret_cast<Profile*>(profile_id); CertificateErrorReport report(params.hostname(), *params.certificate(), - params.flags(), primary_result, trial_result); + config, primary_result, trial_result); report.AddNetworkTimeInfo(g_browser_process->network_time_tracker()); report.AddChromeChannel(chrome::GetChannel()); @@ -200,14 +181,17 @@ class TrialComparisonCertVerifier::TrialVerificationJob { public: - TrialVerificationJob(const net::CertVerifier::RequestParams& params, + TrialVerificationJob(const net::CertVerifier::Config& config, + const net::CertVerifier::RequestParams& params, const net::NetLogWithSource& source_net_log, scoped_refptr<net::CRLSet> crl_set, TrialComparisonCertVerifier* cert_verifier, int primary_error, const net::CertVerifyResult& primary_result, void* profile_id) - : params_(params), + : config_(config), + config_changed_(false), + params_(params), net_log_(net::NetLogWithSource::Make( source_net_log.net_log(), net::NetLogSourceType::TRIAL_CERT_VERIFIER_JOB)), @@ -241,6 +225,8 @@ OnJobCompleted(rv); } + void OnConfigChanged() { config_changed_ = true; } + void Finish(bool is_success, TrialComparisonResult result_code) { TrialComparisonCertVerifier* cert_verifier = cert_verifier_; cert_verifier_ = nullptr; @@ -256,9 +242,9 @@ !base::GetFieldTrialParamByFeatureAsBool( features::kCertDualVerificationTrialFeature, "uma_only", false)) { content::BrowserThread::GetTaskRunnerForThread(content::BrowserThread::UI) - ->PostTask(FROM_HERE, - base::BindOnce(&SendTrialVerificationReport, profile_id_, - params_, primary_result_, trial_result_)); + ->PostTask(FROM_HERE, base::BindOnce(&SendTrialVerificationReport, + profile_id_, config_, params_, + primary_result_, trial_result_)); } // |this| is deleted after RemoveJob returns. @@ -304,22 +290,21 @@ #if defined(OS_MACOSX) if (primary_error_ == net::ERR_CERT_REVOKED && - !(params_.flags() & net::CertVerifier::VERIFY_REV_CHECKING_ENABLED) && + !config_.enable_rev_checking && !(primary_result_.cert_status & net::CERT_STATUS_REV_CHECKING_ENABLED) && !(trial_result_.cert_status & (net::CERT_STATUS_REVOKED | net::CERT_STATUS_REV_CHECKING_ENABLED))) { + if (config_changed_) { + FinishSuccess(kIgnoredConfigurationChanged); + return; + } // CertVerifyProcMac does some revocation checking even if we didn't want // it. Try verifying with the trial verifier with revocation checking // enabled, see if it then returns REVOKED. - RequestParams reverification_params( - params_.certificate(), params_.hostname(), - params_.flags() | net::CertVerifier::VERIFY_REV_CHECKING_ENABLED, - params_.ocsp_response(), params_.additional_trust_anchors()); - - int rv = cert_verifier_->trial_verifier()->Verify( - reverification_params, crl_set_.get(), &reverification_result_, + int rv = cert_verifier_->revocation_trial_verifier()->Verify( + params_, crl_set_.get(), &reverification_result_, base::BindOnce( &TrialVerificationJob::OnMacRevcheckingReverificationJobCompleted, base::Unretained(this)), @@ -336,6 +321,10 @@ if (!chains_equal && (trial_error_ == net::OK || primary_error_ != net::OK)) { + if (config_changed_) { + FinishSuccess(kIgnoredConfigurationChanged); + return; + } // Chains were different, reverify the trial_result_.verified_cert chain // using the platform verifier and compare results again. RequestParams reverification_params( @@ -436,6 +425,8 @@ } private: + const net::CertVerifier::Config config_; + bool config_changed_; const net::CertVerifier::RequestParams params_; const net::NetLogWithSource net_log_; scoped_refptr<net::CRLSet> crl_set_; @@ -463,6 +454,7 @@ scoped_refptr<net::CertVerifyProc> primary_verify_proc, scoped_refptr<net::CertVerifyProc> trial_verify_proc) : profile_id_(profile_id), + config_id_(0), primary_verifier_( net::MultiThreadedCertVerifier::CreateForDualVerificationTrial( primary_verify_proc, @@ -483,7 +475,20 @@ &TrialComparisonCertVerifier::OnTrialVerifierComplete, base::Unretained(this)), false /* should_record_histograms */)), - weak_ptr_factory_(this) {} + revocation_trial_verifier_( + net::MultiThreadedCertVerifier::CreateForDualVerificationTrial( + trial_verify_proc, + // Unretained is safe since the callback won't be called after + // |trial_verifier_| is destroyed. + base::BindRepeating( + &TrialComparisonCertVerifier::OnTrialVerifierComplete, + base::Unretained(this)), + false /* should_record_histograms */)), + weak_ptr_factory_(this) { + net::CertVerifier::Config config; + config.enable_rev_checking = true; + revocation_trial_verifier_->SetConfig(config); +} TrialComparisonCertVerifier::~TrialComparisonCertVerifier() = default; @@ -504,6 +509,25 @@ std::move(callback), out_req, net_log); } +void TrialComparisonCertVerifier::SetConfig(const Config& config) { + config_ = config; + config_id_++; + + primary_verifier_->SetConfig(config); + primary_reverifier_->SetConfig(config); + trial_verifier_->SetConfig(config); + + // Always enable revocation checking for the revocation trial verifier. + net::CertVerifier::Config config_with_revocation = config; + config_with_revocation.enable_rev_checking = true; + revocation_trial_verifier_->SetConfig(config_with_revocation); + + // Notify all in-process jobs that the underlying configuration has changed. + for (auto& job : jobs_) { + job->OnConfigChanged(); + } +} + void TrialComparisonCertVerifier::OnPrimaryVerifierComplete( const RequestParams& params, scoped_refptr<net::CRLSet> crl_set, @@ -526,12 +550,11 @@ base::PostTaskAndReplyWithResult( content::BrowserThread::GetTaskRunnerForThread(content::BrowserThread::UI) .get(), - FROM_HERE, - base::BindOnce(CheckTrialEligibility, profile_id_, primary_latency, - is_first_job), + FROM_HERE, base::BindOnce(CheckTrialEligibility, profile_id_), base::BindOnce(&TrialComparisonCertVerifier::MaybeDoTrialVerification, weak_ptr_factory_.GetWeakPtr(), params, std::move(crl_set), - net_log, primary_error, primary_result, profile_id_)); + net_log, primary_error, primary_result, primary_latency, + is_first_job, config_id_, profile_id_)); } void TrialComparisonCertVerifier::OnTrialVerifierComplete( @@ -561,16 +584,35 @@ const net::NetLogWithSource& net_log, int primary_error, const net::CertVerifyResult& primary_result, + base::TimeDelta primary_latency, + bool is_first_job, + uint32_t config_id, void* profile_id, bool trial_allowed) { DCHECK_CALLED_ON_VALID_THREAD(thread_checker_); - if (!trial_allowed) + // If the trial is not allowed, or the configuration has changed while + // determining if the trial is allowed, no need to continue. + if (!trial_allowed || config_id != config_id_) return; + // Only record the TrialPrimary histograms for the same set of requests + // that TrialSecondary histograms will be recorded for, in order to get a + // direct comparison. + UMA_HISTOGRAM_CUSTOM_TIMES("Net.CertVerifier_Job_Latency_TrialPrimary", + primary_latency, + base::TimeDelta::FromMilliseconds(1), + base::TimeDelta::FromMinutes(10), 100); + if (is_first_job) { + UMA_HISTOGRAM_CUSTOM_TIMES( + "Net.CertVerifier_First_Job_Latency_TrialPrimary", primary_latency, + base::TimeDelta::FromMilliseconds(1), base::TimeDelta::FromMinutes(10), + 100); + } + std::unique_ptr<TrialVerificationJob> job = std::make_unique<TrialVerificationJob>( - params, net_log, std::move(crl_set), this, primary_error, + config_, params, net_log, std::move(crl_set), this, primary_error, primary_result, profile_id); TrialVerificationJob* job_ptr = job.get(); jobs_.insert(std::move(job));
diff --git a/chrome/browser/net/trial_comparison_cert_verifier.h b/chrome/browser/net/trial_comparison_cert_verifier.h index b7bdea2..08d0a88 100644 --- a/chrome/browser/net/trial_comparison_cert_verifier.h +++ b/chrome/browser/net/trial_comparison_cert_verifier.h
@@ -5,6 +5,8 @@ #ifndef CHROME_BROWSER_NET_TRIAL_COMPARISON_CERT_VERIFIER_H_ #define CHROME_BROWSER_NET_TRIAL_COMPARISON_CERT_VERIFIER_H_ +#include <stdint.h> + #include "base/containers/unique_ptr_adapters.h" #include "base/macros.h" #include "base/memory/ref_counted.h" @@ -32,7 +34,8 @@ kIgnoredMultipleEVPoliciesAndOneMatchesRoot = 7, kIgnoredDifferentPathReVerifiesEquivalent = 8, kIgnoredLocallyTrustedLeaf = 9, - kMaxValue = kIgnoredLocallyTrustedLeaf + kIgnoredConfigurationChanged = 10, + kMaxValue = kIgnoredConfigurationChanged }; TrialComparisonCertVerifier( @@ -53,6 +56,7 @@ net::CompletionOnceCallback callback, std::unique_ptr<Request>* out_req, const net::NetLogWithSource& net_log) override; + void SetConfig(const Config& config) override; // Returns a CertVerifier using the primary CertVerifyProc, which will not // cause OnPrimaryVerifierComplete to be called. This can be used to @@ -62,6 +66,9 @@ return primary_reverifier_.get(); } net::CertVerifier* trial_verifier() const { return trial_verifier_.get(); } + net::CertVerifier* revocation_trial_verifier() const { + return revocation_trial_verifier_.get(); + } private: class TrialVerificationJob; @@ -71,7 +78,7 @@ const net::NetLogWithSource& net_log, int primary_error, const net::CertVerifyResult& primary_result, - base::TimeDelta latency, + base::TimeDelta primary_latency, bool is_first_job); void OnTrialVerifierComplete(const RequestParams& params, scoped_refptr<net::CRLSet> crl_set, @@ -85,6 +92,9 @@ const net::NetLogWithSource& net_log, int primary_error, const net::CertVerifyResult& primary_result, + base::TimeDelta primary_latency, + bool is_first_job, + uint32_t config_id, void* profile_id, bool trial_allowed); @@ -94,9 +104,17 @@ // accidentally using it on IO thread. void* profile_id_; + // Unique identifier for the current configuration, to determine if a + // configuration has changed in between primary and trial verifications. + uint32_t config_id_; + net::CertVerifier::Config config_; + std::unique_ptr<net::CertVerifier> primary_verifier_; std::unique_ptr<net::CertVerifier> primary_reverifier_; std::unique_ptr<net::CertVerifier> trial_verifier_; + // Similar to |trial_verifier_|, except configured to always check + // revocation information. + std::unique_ptr<net::CertVerifier> revocation_trial_verifier_; std::set<std::unique_ptr<TrialVerificationJob>, base::UniquePtrComparator> jobs_;
diff --git a/chrome/browser/net/trial_comparison_cert_verifier_unittest.cc b/chrome/browser/net/trial_comparison_cert_verifier_unittest.cc index a8d7432..7112634 100644 --- a/chrome/browser/net/trial_comparison_cert_verifier_unittest.cc +++ b/chrome/browser/net/trial_comparison_cert_verifier_unittest.cc
@@ -900,12 +900,14 @@ base::MakeRefCounted<FakeCertVerifyProc>(net::OK, secondary_result); TrialComparisonCertVerifier verifier(profile(), verify_proc1, verify_proc2); + net::CertVerifier::Config config; + config.enable_rev_checking = true; + config.enable_sha1_local_anchors = true; + verifier.SetConfig(config); - net::CertVerifier::RequestParams params( - leaf_cert_1_, "127.0.0.1", - net::CertVerifier::VERIFY_ENABLE_SHA1_LOCAL_ANCHORS | - net::CertVerifier::VERIFY_REV_CHECKING_ENABLED, - std::string() /* ocsp_response */, {} /* additional_trust_anchors */); + net::CertVerifier::RequestParams params(leaf_cert_1_, "127.0.0.1", 0, + std::string() /* ocsp_response */, + {} /* additional_trust_anchors */); net::CertVerifyResult result; net::TestCompletionCallback callback; std::unique_ptr<net::CertVerifier::Request> request; @@ -1172,7 +1174,64 @@ histograms_.ExpectTotalCount("Net.CertVerifier_TrialComparisonResult", 0); } -TEST_F(TrialComparisonCertVerifierTest, DeletedDuringTrialVerification) { +TEST_F(TrialComparisonCertVerifierTest, DeletedBeforeTrialVerificationStarted) { + // Primary verifier returns an error status. + net::CertVerifyResult primary_result; + primary_result.verified_cert = cert_chain_1_; + primary_result.cert_status = net::CERT_STATUS_DATE_INVALID; + scoped_refptr<FakeCertVerifyProc> verify_proc1 = + base::MakeRefCounted<FakeCertVerifyProc>(net::ERR_CERT_DATE_INVALID, + primary_result); + + // Trial verifier has ok status. + net::CertVerifyResult secondary_result; + secondary_result.verified_cert = cert_chain_1_; + scoped_refptr<NotCalledCertVerifyProc> verify_proc2 = + base::MakeRefCounted<NotCalledCertVerifyProc>(); + + auto verifier = std::make_unique<TrialComparisonCertVerifier>( + profile(), verify_proc1, verify_proc2); + + net::CertVerifier::RequestParams params( + leaf_cert_1_, "127.0.0.1", 0 /* flags */, + std::string() /* ocsp_response */, {} /* additional_trust_anchors */); + net::CertVerifyResult result; + net::TestCompletionCallback callback; + std::unique_ptr<net::CertVerifier::Request> request; + int error = + verifier->Verify(params, nullptr /* crl_set */, &result, + callback.callback(), &request, net::NetLogWithSource()); + ASSERT_THAT(error, IsError(net::ERR_IO_PENDING)); + EXPECT_TRUE(request); + + // Wait for primary verifier to finish. + error = callback.WaitForResult(); + EXPECT_THAT(error, IsError(net::ERR_CERT_DATE_INVALID)); + + // Delete the TrialComparisonCertVerifier. + verifier.reset(); + + // Trial verification has not yet started, as it was waiting on the profile + // to determine whether or not it would be permitted. + + // Wait for any tasks to finish. + content::RunAllTasksUntilIdle(); + + // Expect no report. + reporting_service_test_helper()->ExpectNoRequests(service()); + + // The actual verification job should be completed, but neither the + // primary nor secondary job metrics should be recorded, as the verifier + // was deleted prior to determining whether a trial verification would be + // run. + histograms_.ExpectTotalCount("Net.CertVerifier_Job_Latency", 1); + histograms_.ExpectTotalCount("Net.CertVerifier_Job_Latency_TrialPrimary", 0); + histograms_.ExpectTotalCount("Net.CertVerifier_Job_Latency_TrialSecondary", + 0); + histograms_.ExpectTotalCount("Net.CertVerifier_TrialComparisonResult", 0); +} + +TEST_F(TrialComparisonCertVerifierTest, DeletedAfterTrialVerificationStarted) { // Primary verifier returns an error status. net::CertVerifyResult primary_result; primary_result.verified_cert = cert_chain_1_; @@ -1206,7 +1265,23 @@ error = callback.WaitForResult(); EXPECT_THAT(error, IsError(net::ERR_CERT_DATE_INVALID)); - // Delete the TrialComparisonCertVerifier. + // Allow the lookup on the UI thread for the profile to determine trial + // status. + std::unique_ptr<base::RunLoop> run_loop(std::make_unique<base::RunLoop>()); + content::BrowserThread::GetTaskRunnerForThread(content::BrowserThread::UI) + ->PostTask(FROM_HERE, run_loop->QuitClosure()); + run_loop->Run(); + + // Allow recording the metrics back on the IO thread, and starting the + // second verification, to run. + run_loop = std::make_unique<base::RunLoop>(); + content::BrowserThread::GetTaskRunnerForThread(content::BrowserThread::IO) + ->PostTask(FROM_HERE, run_loop->QuitClosure()); + run_loop->Run(); + + // Delete the TrialComparisonCertVerifier. The trial verification is still + // running on the task scheduler (or, depending on timing, has posted back + // to the IO thread after the Quit event). verifier.reset(); // The callback to the trial verifier does not run. The verification task @@ -1304,8 +1379,8 @@ // ...unless it was called with REV_CHECKING_ENABLED. EXPECT_CALL( *verify_proc2, - VerifyInternal(_, _, _, net::CertVerifier::VERIFY_REV_CHECKING_ENABLED, _, - _, _)) + VerifyInternal(_, _, _, net::CertVerifyProc::VERIFY_REV_CHECKING_ENABLED, + _, _, _)) .WillRepeatedly(DoAll(SetArgPointee<6>(revoked_result), Return(net::ERR_CERT_REVOKED)));
diff --git a/chrome/browser/offline_pages/android/evaluation/offline_page_evaluation_bridge.cc b/chrome/browser/offline_pages/android/evaluation/offline_page_evaluation_bridge.cc index 6dde0e0d2..f247439 100644 --- a/chrome/browser/offline_pages/android/evaluation/offline_page_evaluation_bridge.cc +++ b/chrome/browser/offline_pages/android/evaluation/offline_page_evaluation_bridge.cc
@@ -16,8 +16,7 @@ #include "base/bind.h" #include "base/sequenced_task_runner.h" #include "base/task/post_task.h" -#include "chrome/browser/net/nqe/ui_network_quality_estimator_service.h" -#include "chrome/browser/net/nqe/ui_network_quality_estimator_service_factory.h" +#include "chrome/browser/browser_process.h" #include "chrome/browser/offline_pages/android/background_scheduler_bridge.h" #include "chrome/browser/offline_pages/android/evaluation/evaluation_test_scheduler.h" #include "chrome/browser/offline_pages/background_loader_offliner.h" @@ -49,6 +48,10 @@ using base::android::ScopedJavaGlobalRef; using base::android::ScopedJavaLocalRef; +namespace network { +class NetworkQualityTracker; +} + namespace offline_pages { namespace android { @@ -149,15 +152,14 @@ std::unique_ptr<RequestQueue> queue(new RequestQueue(std::move(queue_store))); std::unique_ptr<android::EvaluationTestScheduler> scheduler( new android::EvaluationTestScheduler()); - net::NetworkQualityEstimator::NetworkQualityProvider* - network_quality_estimator = - UINetworkQualityEstimatorServiceFactory::GetForProfile(profile); + network::NetworkQualityTracker* network_quality_tracker = + g_browser_process->network_quality_tracker(); std::unique_ptr<OfflinePagesUkmReporter> ukm_reporter( new OfflinePagesUkmReporter()); std::unique_ptr<RequestCoordinator> request_coordinator = std::make_unique<RequestCoordinator>( std::move(policy), std::move(offliner), std::move(queue), - std::move(scheduler), network_quality_estimator, + std::move(scheduler), network_quality_tracker, std::move(ukm_reporter)); request_coordinator->SetInternalStartProcessingCallbackForTest( base::Bind(&android::EvaluationTestScheduler::ImmediateScheduleCallback,
diff --git a/chrome/browser/offline_pages/android/request_coordinator_factory.cc b/chrome/browser/offline_pages/android/request_coordinator_factory.cc index 3cd1a3b..eb9cebb 100644 --- a/chrome/browser/offline_pages/android/request_coordinator_factory.cc +++ b/chrome/browser/offline_pages/android/request_coordinator_factory.cc
@@ -9,8 +9,7 @@ #include "base/memory/singleton.h" #include "base/sequenced_task_runner.h" #include "base/task/post_task.h" -#include "chrome/browser/net/nqe/ui_network_quality_estimator_service.h" -#include "chrome/browser/net/nqe/ui_network_quality_estimator_service_factory.h" +#include "chrome/browser/browser_process.h" #include "chrome/browser/offline_pages/android/background_scheduler_bridge.h" #include "chrome/browser/offline_pages/android/cct_request_observer.h" #include "chrome/browser/offline_pages/android/load_termination_listener_impl.h" @@ -28,7 +27,10 @@ #include "components/offline_pages/core/background/scheduler.h" #include "components/offline_pages/core/offline_page_feature.h" #include "components/offline_pages/core/offline_pages_ukm_reporter.h" -#include "net/nqe/network_quality_estimator.h" + +namespace network { +class NetworkQualityTracker; +} namespace offline_pages { @@ -75,14 +77,13 @@ std::unique_ptr<RequestQueue> queue(new RequestQueue(std::move(queue_store))); std::unique_ptr<Scheduler> scheduler(new android::BackgroundSchedulerBridge()); - net::NetworkQualityEstimator::NetworkQualityProvider* - network_quality_estimator = - UINetworkQualityEstimatorServiceFactory::GetForProfile(profile); + network::NetworkQualityTracker* network_quality_tracker = + g_browser_process->network_quality_tracker(); std::unique_ptr<OfflinePagesUkmReporter> ukm_reporter( new OfflinePagesUkmReporter()); RequestCoordinator* request_coordinator = new RequestCoordinator( std::move(policy), std::move(offliner), std::move(queue), - std::move(scheduler), network_quality_estimator, std::move(ukm_reporter)); + std::move(scheduler), network_quality_tracker, std::move(ukm_reporter)); CCTRequestObserver::AttachToRequestCoordinator(request_coordinator);
diff --git a/chrome/browser/offline_pages/offline_page_utils_unittest.cc b/chrome/browser/offline_pages/offline_page_utils_unittest.cc index d8b91ace..5b05a2a 100644 --- a/chrome/browser/offline_pages/offline_page_utils_unittest.cc +++ b/chrome/browser/offline_pages/offline_page_utils_unittest.cc
@@ -26,7 +26,6 @@ #include "chrome/browser/offline_pages/test_request_coordinator_builder.h" #include "chrome/common/chrome_constants.h" #include "chrome/test/base/testing_profile.h" -#include "components/offline_pages/core/background/network_quality_provider_stub.h" #include "components/offline_pages/core/background/request_coordinator.h" #include "components/offline_pages/core/client_namespace_constants.h" #include "components/offline_pages/core/model/offline_page_model_taskified.h" @@ -147,8 +146,6 @@ &profile_, BuildTestOfflinePageModel); RunUntilIdle(); - NetworkQualityProviderStub::SetUserData( - &profile_, std::make_unique<NetworkQualityProviderStub>()); RequestCoordinatorFactory::GetInstance()->SetTestingFactoryAndUse( &profile_, BuildTestRequestCoordinator); RunUntilIdle();
diff --git a/chrome/browser/offline_pages/test_request_coordinator_builder.cc b/chrome/browser/offline_pages/test_request_coordinator_builder.cc index 280beb02..e76f49e 100644 --- a/chrome/browser/offline_pages/test_request_coordinator_builder.cc +++ b/chrome/browser/offline_pages/test_request_coordinator_builder.cc
@@ -6,7 +6,7 @@ #include <utility> -#include "components/offline_pages/core/background/network_quality_provider_stub.h" +#include "chrome/browser/browser_process.h" #include "components/offline_pages/core/background/offliner_policy.h" #include "components/offline_pages/core/background/offliner_stub.h" #include "components/offline_pages/core/background/request_coordinator.h" @@ -33,16 +33,12 @@ std::unique_ptr<Offliner> offliner(new OfflinerStub()); std::unique_ptr<Scheduler> scheduler_stub(new SchedulerStub()); - // NetworkQualityProviderStub should be set by the test on the context first. - NetworkQualityProviderStub* network_quality_provider = - NetworkQualityProviderStub::GetUserData(context); - std::unique_ptr<OfflinePagesUkmReporter> ukm_reporter_stub( new OfflinePagesUkmReporterStub()); return std::unique_ptr<RequestCoordinator>(new RequestCoordinator( std::move(policy), std::move(offliner), std::move(queue), - std::move(scheduler_stub), network_quality_provider, + std::move(scheduler_stub), g_browser_process->network_quality_tracker(), std::move(ukm_reporter_stub))); }
diff --git a/chrome/browser/page_load_metrics/observers/ukm_page_load_metrics_observer.cc b/chrome/browser/page_load_metrics/observers/ukm_page_load_metrics_observer.cc index 397b9281..7359e104f 100644 --- a/chrome/browser/page_load_metrics/observers/ukm_page_load_metrics_observer.cc +++ b/chrome/browser/page_load_metrics/observers/ukm_page_load_metrics_observer.cc
@@ -7,44 +7,30 @@ #include <memory> #include "chrome/browser/browser_process.h" -#include "chrome/browser/net/nqe/ui_network_quality_estimator_service.h" -#include "chrome/browser/net/nqe/ui_network_quality_estimator_service_factory.h" #include "chrome/browser/page_load_metrics/page_load_metrics_util.h" #include "chrome/browser/profiles/profile.h" #include "components/metrics/net/network_metrics_provider.h" -#include "content/public/browser/web_contents.h" #include "services/metrics/public/cpp/metrics_utils.h" #include "services/metrics/public/cpp/ukm_builders.h" #include "services/metrics/public/cpp/ukm_recorder.h" +#include "services/network/public/cpp/network_quality_tracker.h" #include "third_party/metrics_proto/system_profile.pb.h" -namespace { - -UINetworkQualityEstimatorService* GetNQEService( - content::WebContents* web_contents) { - Profile* profile = - Profile::FromBrowserContext(web_contents->GetBrowserContext()); - if (!profile) - return nullptr; - return UINetworkQualityEstimatorServiceFactory::GetForProfile(profile); -} - -} // namespace - // static std::unique_ptr<page_load_metrics::PageLoadMetricsObserver> -UkmPageLoadMetricsObserver::CreateIfNeeded(content::WebContents* web_contents) { +UkmPageLoadMetricsObserver::CreateIfNeeded() { if (!ukm::UkmRecorder::Get()) { return nullptr; } return std::make_unique<UkmPageLoadMetricsObserver>( - GetNQEService(web_contents)); + g_browser_process->network_quality_tracker()); } UkmPageLoadMetricsObserver::UkmPageLoadMetricsObserver( - net::NetworkQualityEstimator::NetworkQualityProvider* - network_quality_provider) - : network_quality_provider_(network_quality_provider) {} + network::NetworkQualityTracker* network_quality_tracker) + : network_quality_tracker_(network_quality_tracker) { + DCHECK(network_quality_tracker_); +} UkmPageLoadMetricsObserver::~UkmPageLoadMetricsObserver() = default; @@ -62,14 +48,12 @@ // record UKM metrics for that data once we've confirmed that we're observing // a web page load. - if (network_quality_provider_) { - effective_connection_type_ = - network_quality_provider_->GetEffectiveConnectionType(); - http_rtt_estimate_ = network_quality_provider_->GetHttpRTT(); - transport_rtt_estimate_ = network_quality_provider_->GetTransportRTT(); - downstream_kbps_estimate_ = - network_quality_provider_->GetDownstreamThroughputKbps(); - } + effective_connection_type_ = + network_quality_tracker_->GetEffectiveConnectionType(); + http_rtt_estimate_ = network_quality_tracker_->GetHttpRTT(); + transport_rtt_estimate_ = network_quality_tracker_->GetTransportRTT(); + downstream_kbps_estimate_ = + network_quality_tracker_->GetDownstreamThroughputKbps(); page_transition_ = navigation_handle->GetPageTransition(); return CONTINUE_OBSERVING; }
diff --git a/chrome/browser/page_load_metrics/observers/ukm_page_load_metrics_observer.h b/chrome/browser/page_load_metrics/observers/ukm_page_load_metrics_observer.h index d5e5fff..08dd239 100644 --- a/chrome/browser/page_load_metrics/observers/ukm_page_load_metrics_observer.h +++ b/chrome/browser/page_load_metrics/observers/ukm_page_load_metrics_observer.h
@@ -10,11 +10,10 @@ #include "base/time/time.h" #include "chrome/browser/page_load_metrics/page_load_metrics_observer.h" #include "components/ukm/ukm_source.h" -#include "net/nqe/network_quality_estimator.h" #include "ui/base/page_transition_types.h" -namespace content { -class WebContents; +namespace network { +class NetworkQualityTracker; } // If URL-Keyed-Metrics (UKM) is enabled in the system, this is used to @@ -24,11 +23,10 @@ public: // Returns a UkmPageLoadMetricsObserver, or nullptr if it is not needed. static std::unique_ptr<page_load_metrics::PageLoadMetricsObserver> - CreateIfNeeded(content::WebContents* web_contents); + CreateIfNeeded(); explicit UkmPageLoadMetricsObserver( - net::NetworkQualityEstimator::NetworkQualityProvider* - network_quality_provider); + network::NetworkQualityTracker* network_quality_tracker); ~UkmPageLoadMetricsObserver() override; // page_load_metrics::PageLoadMetricsObserver implementation: @@ -71,8 +69,8 @@ const page_load_metrics::PageLoadExtraInfo& info, base::TimeTicks app_background_time); - net::NetworkQualityEstimator::NetworkQualityProvider* const - network_quality_provider_; + // Guaranteed to be non-null during the lifetime of |this|. + network::NetworkQualityTracker* network_quality_tracker_; // The number of body (not header) prefilter bytes consumed by requests for // the page.
diff --git a/chrome/browser/page_load_metrics/observers/ukm_page_load_metrics_observer_unittest.cc b/chrome/browser/page_load_metrics/observers/ukm_page_load_metrics_observer_unittest.cc index e1106ee9..64cf979d 100644 --- a/chrome/browser/page_load_metrics/observers/ukm_page_load_metrics_observer_unittest.cc +++ b/chrome/browser/page_load_metrics/observers/ukm_page_load_metrics_observer_unittest.cc
@@ -15,9 +15,9 @@ #include "components/ukm/ukm_source.h" #include "content/public/test/navigation_simulator.h" #include "net/nqe/effective_connection_type.h" -#include "net/nqe/network_quality_provider.h" #include "services/metrics/public/cpp/metrics_utils.h" #include "services/metrics/public/cpp/ukm_builders.h" +#include "services/network/public/cpp/network_quality_tracker.h" #include "testing/gmock/include/gmock/gmock.h" #include "third_party/metrics_proto/system_profile.pb.h" @@ -32,13 +32,13 @@ const char kTestUrl1[] = "https://www.google.com/"; const char kTestUrl2[] = "https://www.example.com/"; -class MockNetworkQualityProvider : public net::NetworkQualityProvider { +class MockNetworkQualityProvider : public network::NetworkQualityTracker { public: MOCK_CONST_METHOD0(GetEffectiveConnectionType, net::EffectiveConnectionType()); - MOCK_CONST_METHOD0(GetHttpRTT, base::Optional<base::TimeDelta>()); - MOCK_CONST_METHOD0(GetTransportRTT, base::Optional<base::TimeDelta>()); - MOCK_CONST_METHOD0(GetDownstreamThroughputKbps, base::Optional<int32_t>()); + MOCK_CONST_METHOD0(GetHttpRTT, base::TimeDelta()); + MOCK_CONST_METHOD0(GetTransportRTT, base::TimeDelta()); + MOCK_CONST_METHOD0(GetDownstreamThroughputKbps, int32_t()); }; } // namespace @@ -60,15 +60,15 @@ EXPECT_CALL(mock_network_quality_provider_, GetHttpRTT()) .Times(AnyNumber()) - .WillRepeatedly(Return(base::Optional<base::TimeDelta>())); + .WillRepeatedly(Return(base::TimeDelta())); EXPECT_CALL(mock_network_quality_provider_, GetTransportRTT()) .Times(AnyNumber()) - .WillRepeatedly(Return(base::Optional<base::TimeDelta>())); + .WillRepeatedly(Return(base::TimeDelta())); EXPECT_CALL(mock_network_quality_provider_, GetDownstreamThroughputKbps()) .Times(AnyNumber()) - .WillRepeatedly(Return(base::Optional<int32_t>())); + .WillRepeatedly(Return(int32_t())); } MockNetworkQualityProvider& mock_network_quality_provider() {
diff --git a/chrome/browser/page_load_metrics/page_load_metrics_initialize.cc b/chrome/browser/page_load_metrics/page_load_metrics_initialize.cc index 4cd8abe..503a210c 100644 --- a/chrome/browser/page_load_metrics/page_load_metrics_initialize.cc +++ b/chrome/browser/page_load_metrics/page_load_metrics_initialize.cc
@@ -127,7 +127,7 @@ tracker->AddObserver(std::move(ads_observer)); std::unique_ptr<page_load_metrics::PageLoadMetricsObserver> ukm_observer = - UkmPageLoadMetricsObserver::CreateIfNeeded(web_contents_); + UkmPageLoadMetricsObserver::CreateIfNeeded(); if (ukm_observer) tracker->AddObserver(std::move(ukm_observer));
diff --git a/chrome/browser/prefs/pref_service_incognito_whitelist.cc b/chrome/browser/prefs/pref_service_incognito_whitelist.cc index cd6bbcb..6612276 100644 --- a/chrome/browser/prefs/pref_service_incognito_whitelist.cc +++ b/chrome/browser/prefs/pref_service_incognito_whitelist.cc
@@ -472,14 +472,7 @@ prefs::kDefaultAudioCaptureDevice, prefs::kDefaultVideoCaptureDevice, prefs::kMediaDeviceIdSalt, prefs::kMediaStorageIdSalt, - prefs::kPrintPreviewStickySettings, prefs::kCloudPrintRoot, - prefs::kCloudPrintProxyEnabled, prefs::kCloudPrintProxyId, - prefs::kCloudPrintAuthToken, prefs::kCloudPrintEmail, - prefs::kCloudPrintPrintSystemSettings, prefs::kCloudPrintEnableJobPoll, - prefs::kCloudPrintRobotRefreshToken, prefs::kCloudPrintRobotEmail, - prefs::kCloudPrintConnectNewPrinters, prefs::kCloudPrintXmppPingEnabled, - prefs::kCloudPrintXmppPingTimeout, prefs::kCloudPrintPrinters, - prefs::kCloudPrintSubmitEnabled, prefs::kCloudPrintUserSettings, + prefs::kPrintPreviewStickySettings, prefs::kMaxConnectionsPerProxy,
diff --git a/chrome/browser/printing/cloud_print/privet_notifications.cc b/chrome/browser/printing/cloud_print/privet_notifications.cc index 3ff101b..39c82b5d 100644 --- a/chrome/browser/printing/cloud_print/privet_notifications.cc +++ b/chrome/browser/printing/cloud_print/privet_notifications.cc
@@ -210,10 +210,6 @@ PrivetNotificationService::~PrivetNotificationService() { DCHECK_CURRENTLY_ON(content::BrowserThread::UI); -#if BUILDFLAG(ENABLE_MDNS) - if (traffic_detector_) - traffic_detector_->Stop(); -#endif } void PrivetNotificationService::DeviceChanged( @@ -329,18 +325,15 @@ void PrivetNotificationService::OnNotificationsEnabledChanged() { #if BUILDFLAG(ENABLE_MDNS) - if (traffic_detector_) - traffic_detector_->Stop(); - traffic_detector_ = nullptr; + traffic_detector_.reset(); if (IsForced()) { StartLister(); } else if (*enable_privet_notification_member_) { ReportPrivetUmaEvent(PRIVET_SERVICE_STARTED); - traffic_detector_ = base::MakeRefCounted<PrivetTrafficDetector>( + traffic_detector_ = std::make_unique<PrivetTrafficDetector>( profile_, base::BindRepeating(&PrivetNotificationService::StartLister, AsWeakPtr())); - traffic_detector_->Start(); } else { device_lister_.reset(); service_discovery_client_ = nullptr;
diff --git a/chrome/browser/printing/cloud_print/privet_notifications.h b/chrome/browser/printing/cloud_print/privet_notifications.h index 986245c..29e601b 100644 --- a/chrome/browser/printing/cloud_print/privet_notifications.h +++ b/chrome/browser/printing/cloud_print/privet_notifications.h
@@ -140,7 +140,7 @@ BooleanPrefMember enable_privet_notification_member_; #if BUILDFLAG(ENABLE_MDNS) - scoped_refptr<PrivetTrafficDetector> traffic_detector_; + std::unique_ptr<PrivetTrafficDetector> traffic_detector_; #endif };
diff --git a/chrome/browser/printing/cloud_print/privet_traffic_detector.cc b/chrome/browser/printing/cloud_print/privet_traffic_detector.cc index 18959f8..28857a72 100644 --- a/chrome/browser/printing/cloud_print/privet_traffic_detector.cc +++ b/chrome/browser/printing/cloud_print/privet_traffic_detector.cc
@@ -7,12 +7,12 @@ #include <utility> #include "base/metrics/histogram_macros.h" -#include "base/single_thread_task_runner.h" #include "base/sys_byteorder.h" #include "base/task/post_task.h" #include "base/threading/thread_restrictions.h" #include "base/threading/thread_task_runner_handle.h" #include "content/public/browser/browser_context.h" +#include "content/public/browser/browser_thread.h" #include "content/public/browser/network_service_instance.h" #include "content/public/browser/storage_partition.h" #include "net/base/address_family.h" @@ -73,33 +73,47 @@ PrivetTrafficDetector::PrivetTrafficDetector( content::BrowserContext* profile, const base::RepeatingClosure& on_traffic_detected) - : on_traffic_detected_(on_traffic_detected), - restart_attempts_(kMaxRestartAttempts), - receiver_binding_(this), - profile_(profile), - weak_ptr_factory_(this) { - DCHECK_CURRENTLY_ON(content::BrowserThread::UI); -} - -PrivetTrafficDetector::~PrivetTrafficDetector() { - DCHECK_CURRENTLY_ON(content::BrowserThread::IO); -} - -void PrivetTrafficDetector::Start() { + : helper_(new Helper(profile, on_traffic_detected)) { DCHECK_CURRENTLY_ON(content::BrowserThread::UI); content::GetNetworkConnectionTracker()->AddNetworkConnectionObserver(this); content::BrowserThread::PostTask( content::BrowserThread::IO, FROM_HERE, - base::BindOnce(&PrivetTrafficDetector::ScheduleRestart, - weak_ptr_factory_.GetWeakPtr())); + base::BindOnce(&PrivetTrafficDetector::Helper::ScheduleRestart, + base::Unretained(helper_))); } -void PrivetTrafficDetector::Stop() { +PrivetTrafficDetector::~PrivetTrafficDetector() { DCHECK_CURRENTLY_ON(content::BrowserThread::UI); content::GetNetworkConnectionTracker()->RemoveNetworkConnectionObserver(this); + content::BrowserThread::DeleteSoon(content::BrowserThread::IO, FROM_HERE, + helper_); } -void PrivetTrafficDetector::HandleConnectionChanged( +void PrivetTrafficDetector::OnConnectionChanged( + network::mojom::ConnectionType type) { + DCHECK_CURRENTLY_ON(content::BrowserThread::UI); + content::BrowserThread::PostTask( + content::BrowserThread::IO, FROM_HERE, + base::BindOnce(&PrivetTrafficDetector::Helper::HandleConnectionChanged, + base::Unretained(helper_), type)); +} + +PrivetTrafficDetector::Helper::Helper( + content::BrowserContext* profile, + const base::RepeatingClosure& on_traffic_detected) + : profile_(profile), + on_traffic_detected_(on_traffic_detected), + restart_attempts_(kMaxRestartAttempts), + receiver_binding_(this), + weak_ptr_factory_(this) { + DCHECK_CURRENTLY_ON(content::BrowserThread::UI); +} + +PrivetTrafficDetector::Helper::~Helper() { + DCHECK_CURRENTLY_ON(content::BrowserThread::IO); +} + +void PrivetTrafficDetector::Helper::HandleConnectionChanged( network::mojom::ConnectionType type) { DCHECK_CURRENTLY_ON(content::BrowserThread::IO); restart_attempts_ = kMaxRestartAttempts; @@ -108,25 +122,26 @@ } } -void PrivetTrafficDetector::ScheduleRestart() { +void PrivetTrafficDetector::Helper::ScheduleRestart() { DCHECK_CURRENTLY_ON(content::BrowserThread::IO); ResetConnection(); weak_ptr_factory_.InvalidateWeakPtrs(); base::PostDelayedTaskWithTraits( FROM_HERE, {base::TaskPriority::BEST_EFFORT, base::MayBlock()}, - base::BindOnce(&GetNetworkListInBackground, - base::BindOnce(&PrivetTrafficDetector::Restart, - weak_ptr_factory_.GetWeakPtr())), + base::BindOnce( + &GetNetworkListInBackground, + base::BindOnce(&Helper::Restart, weak_ptr_factory_.GetWeakPtr())), base::TimeDelta::FromSeconds(3)); } -void PrivetTrafficDetector::Restart(net::NetworkInterfaceList networks) { +void PrivetTrafficDetector::Helper::Restart( + net::NetworkInterfaceList networks) { DCHECK_CURRENTLY_ON(content::BrowserThread::IO); networks_ = std::move(networks); Bind(); } -void PrivetTrafficDetector::Bind() { +void PrivetTrafficDetector::Helper::Bind() { DCHECK_CURRENTLY_ON(content::BrowserThread::IO); if (!start_time_.is_null()) { base::TimeDelta time_delta = base::Time::Now() - start_time_; @@ -155,19 +170,19 @@ socket_options->multicast_loopback_mode = false; socket_->Bind(bind_endpoint, std::move(socket_options), - base::BindOnce(&PrivetTrafficDetector::OnBindComplete, this, - multicast_addr)); + base::BindOnce(&Helper::OnBindComplete, + weak_ptr_factory_.GetWeakPtr(), multicast_addr)); } -void PrivetTrafficDetector::OnBindComplete( +void PrivetTrafficDetector::Helper::OnBindComplete( net::IPEndPoint multicast_addr, int rv, const base::Optional<net::IPEndPoint>& ip_endpoint) { DCHECK_CURRENTLY_ON(content::BrowserThread::IO); if (rv == net::OK) { - socket_->JoinGroup( - multicast_addr.address(), - base::BindOnce(&PrivetTrafficDetector::OnJoinGroupComplete, this)); + socket_->JoinGroup(multicast_addr.address(), + base::BindOnce(&Helper::OnJoinGroupComplete, + weak_ptr_factory_.GetWeakPtr())); return; } @@ -175,7 +190,7 @@ ScheduleRestart(); } -bool PrivetTrafficDetector::IsSourceAcceptable() const { +bool PrivetTrafficDetector::Helper::IsSourceAcceptable() const { DCHECK_CURRENTLY_ON(content::BrowserThread::IO); for (const auto& network : networks_) { if (net::IPAddressMatchesPrefix(recv_addr_.address(), network.address, @@ -186,7 +201,7 @@ return false; } -bool PrivetTrafficDetector::IsPrivetPacket( +bool PrivetTrafficDetector::Helper::IsPrivetPacket( base::span<const uint8_t> data) const { DCHECK_CURRENTLY_ON(content::BrowserThread::IO); if (data.size() <= sizeof(net::dns_protocol::Header) || @@ -211,7 +226,7 @@ substring_end) != buffer_end; } -void PrivetTrafficDetector::OnJoinGroupComplete(int rv) { +void PrivetTrafficDetector::Helper::OnJoinGroupComplete(int rv) { DCHECK_CURRENTLY_ON(content::BrowserThread::IO); if (rv == net::OK) { // Reset on success. @@ -224,22 +239,13 @@ ScheduleRestart(); } -void PrivetTrafficDetector::ResetConnection() { +void PrivetTrafficDetector::Helper::ResetConnection() { DCHECK_CURRENTLY_ON(content::BrowserThread::IO); socket_.reset(); receiver_binding_.Close(); } -void PrivetTrafficDetector::OnConnectionChanged( - network::mojom::ConnectionType type) { - DCHECK_CURRENTLY_ON(content::BrowserThread::UI); - content::BrowserThread::PostTask( - content::BrowserThread::IO, FROM_HERE, - base::BindOnce(&PrivetTrafficDetector::HandleConnectionChanged, - weak_ptr_factory_.GetWeakPtr(), type)); -} - -void PrivetTrafficDetector::OnReceived( +void PrivetTrafficDetector::Helper::OnReceived( int32_t result, const base::Optional<net::IPEndPoint>& src_addr, base::Optional<base::span<const uint8_t>> data) {
diff --git a/chrome/browser/printing/cloud_print/privet_traffic_detector.h b/chrome/browser/printing/cloud_print/privet_traffic_detector.h index e749a0de..a9ebd08 100644 --- a/chrome/browser/printing/cloud_print/privet_traffic_detector.h +++ b/chrome/browser/printing/cloud_print/privet_traffic_detector.h
@@ -9,7 +9,6 @@ #include "base/callback.h" #include "base/macros.h" -#include "content/public/browser/browser_thread.h" #include "mojo/public/cpp/bindings/binding.h" #include "net/base/ip_endpoint.h" #include "services/network/public/cpp/network_connection_tracker.h" @@ -28,69 +27,70 @@ // listening for traffic. // When the network changes, restarts itself to start listening for traffic // again on the new network(s). +// The class lives on the UI thread, with a helper that lives on the IO thread. class PrivetTrafficDetector - : public base::RefCountedThreadSafe< - PrivetTrafficDetector, - content::BrowserThread::DeleteOnIOThread>, - private network::NetworkConnectionTracker::NetworkConnectionObserver, - public network::mojom::UDPSocketReceiver { + : public network::NetworkConnectionTracker::NetworkConnectionObserver { public: // Called on the UI thread. PrivetTrafficDetector(content::BrowserContext* profile, const base::RepeatingClosure& on_traffic_detected); - - // Called on the UI thread. - void Start(); - void Stop(); - - private: - friend struct content::BrowserThread::DeleteOnThread< - content::BrowserThread::IO>; - friend class base::DeleteHelper<PrivetTrafficDetector>; - ~PrivetTrafficDetector() override; - // Unless otherwise noted, all methods are called on the IO thread. - void HandleConnectionChanged(network::mojom::ConnectionType type); - void ScheduleRestart(); - void Restart(net::NetworkInterfaceList networks); - void Bind(); - void OnBindComplete(net::IPEndPoint multicast_addr, - int rv, - const base::Optional<net::IPEndPoint>& ip_address); - bool IsSourceAcceptable() const; - bool IsPrivetPacket(base::span<const uint8_t> data) const; - void OnJoinGroupComplete(int rv); - void ResetConnection(); - // network::NetworkConnectionTracker::NetworkConnectionObserver: - // Called on the UI thread. void OnConnectionChanged(network::mojom::ConnectionType type) override; - // network::mojom::UDPSocketReceiver implementation - void OnReceived(int32_t result, - const base::Optional<net::IPEndPoint>& src_addr, - base::Optional<base::span<const uint8_t>> data) override; + private: + // Constructed by PrivetTrafficDetector on the UI thread. but lives on the IO + // thread and destroyed on the IO thread. + class Helper : public network::mojom::UDPSocketReceiver { + public: + Helper(content::BrowserContext* profile, + const base::RepeatingClosure& on_traffic_detected); + ~Helper() override; - // Initialized on the UI thread, but only accessed on the IO thread. - base::RepeatingClosure on_traffic_detected_; - int restart_attempts_; + // network::mojom::UDPSocketReceiver: + void OnReceived(int32_t result, + const base::Optional<net::IPEndPoint>& src_addr, + base::Optional<base::span<const uint8_t>> data) override; - // Only accessed on the IO thread. - net::NetworkInterfaceList networks_; - net::IPEndPoint recv_addr_; - base::Time start_time_; - network::mojom::UDPSocketPtr socket_; + void HandleConnectionChanged(network::mojom::ConnectionType type); + void ScheduleRestart(); - // Implementation of socket receiver callback. - // Initialized on the UI thread, but only accessed on the IO thread. - mojo::Binding<network::mojom::UDPSocketReceiver> receiver_binding_; + private: + void Restart(net::NetworkInterfaceList networks); + void Bind(); + void OnBindComplete(net::IPEndPoint multicast_addr, + int rv, + const base::Optional<net::IPEndPoint>& ip_address); + bool IsSourceAcceptable() const; + bool IsPrivetPacket(base::span<const uint8_t> data) const; + void OnJoinGroupComplete(int rv); + void ResetConnection(); - // Initialized on the UI thread, but only accessed on the IO thread for the - // purpose of passing it back to the UI thread. Safe because it is const. - content::BrowserContext* const profile_; + // Initialized on the UI thread, but only accessed on the IO thread for the + // purpose of passing it back to the UI thread. Safe because it is const. + content::BrowserContext* const profile_; - base::WeakPtrFactory<PrivetTrafficDetector> weak_ptr_factory_; + // Initialized on the UI thread, but only accessed on the IO thread. + base::RepeatingClosure on_traffic_detected_; + int restart_attempts_; + + // Only accessed on the IO thread. + net::NetworkInterfaceList networks_; + net::IPEndPoint recv_addr_; + base::Time start_time_; + network::mojom::UDPSocketPtr socket_; + + // Implementation of socket receiver callback. + // Initialized on the UI thread, but only accessed on the IO thread. + mojo::Binding<network::mojom::UDPSocketReceiver> receiver_binding_; + + base::WeakPtrFactory<Helper> weak_ptr_factory_; + + DISALLOW_COPY_AND_ASSIGN(Helper); + }; + + Helper* const helper_; DISALLOW_COPY_AND_ASSIGN(PrivetTrafficDetector); };
diff --git a/chrome/browser/profiles/profile_io_data.cc b/chrome/browser/profiles/profile_io_data.cc index 65dc6d3a..3bf4c0fd 100644 --- a/chrome/browser/profiles/profile_io_data.cc +++ b/chrome/browser/profiles/profile_io_data.cc
@@ -204,6 +204,11 @@ return g_cert_verifier_for_profile_io_data_testing->Verify( params, crl_set, verify_result, std::move(callback), out_req, net_log); } + void SetConfig(const Config& config) override { + if (!g_cert_verifier_for_profile_io_data_testing) + return; + return g_cert_verifier_for_profile_io_data_testing->SetConfig(config); + } }; #if BUILDFLAG(DEBUG_DEVTOOLS)
diff --git a/chrome/browser/resource_coordinator/session_restore_policy.h b/chrome/browser/resource_coordinator/session_restore_policy.h index 3e3273c..15f91f77 100644 --- a/chrome/browser/resource_coordinator/session_restore_policy.h +++ b/chrome/browser/resource_coordinator/session_restore_policy.h
@@ -32,7 +32,9 @@ // session restore. If this returns false then session restore should mark the // tab load as deferred and move onto the next tab to restore. Note that this // always returns true if the policy logic is disabled. - bool ShouldLoad(content::WebContents* contents) const; + // + // Virtual for testing. + virtual bool ShouldLoad(content::WebContents* contents) const; // Intended to be called by the policy client whenever a tab load has been // initiated.
diff --git a/chrome/browser/resources/chromeos/assistant_optin/assistant_confirm_reject.css b/chrome/browser/resources/chromeos/assistant_optin/assistant_confirm_reject.css deleted file mode 100644 index 63c8c7b..0000000 --- a/chrome/browser/resources/chromeos/assistant_optin/assistant_confirm_reject.css +++ /dev/null
@@ -1,25 +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. */ - -.message { - color: rgba(0, 0, 0, .8); - font-size: 13px; - padding-top: 6px; -} - -.content { - padding-top: 6px; -} - -#accept, -#reject { - align-items: unset; - padding: 10px 0 10px 0; -} - -#confirm-reject-img { - display: block; - height: 150px; - margin: auto; -}
diff --git a/chrome/browser/resources/chromeos/assistant_optin/assistant_confirm_reject.html b/chrome/browser/resources/chromeos/assistant_optin/assistant_confirm_reject.html deleted file mode 100644 index e79112a..0000000 --- a/chrome/browser/resources/chromeos/assistant_optin/assistant_confirm_reject.html +++ /dev/null
@@ -1,41 +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. --> - -<link rel="import" href="chrome://resources/cr_elements/cr_radio_button/cr_radio_button.html"> -<link rel="import" href="chrome://resources/polymer/v1_0/paper-radio-group/paper-radio-group.html"> -<dom-module id="assistant-confirm-reject"> - <template> - <link rel="stylesheet" href="../login/oobe_flex_layout.css"> - <link rel="stylesheet" href="assistant_confirm_reject.css"> - <link rel="stylesheet" href="assistant_shared_styles.css"> - <oobe-dialog id="confirm-reject-dialog" role="dialog" has-buttons - hide-shadow no-footer-padding no-header> - <div slot="footer"> - <div class="container"> - <img id="logo" src="assistant_logo.png"> - <div class="title" id="title-text"></div> - <img id="confirm-reject-img" src="assistant_confirm_reject.svg"> - <paper-radio-group selected="accept" selectable="cr-radio-button"> - <cr-radio-button id="accept" name="accept"> - <div class="sub-title" id="accept-title-text"></div> - <div class="message" id="accept-message-text"></div> - <div class="content" id="accept-message-extra-text"></div> - </cr-radio-button> - <cr-radio-button id="reject" name="reject"> - <div class="sub-title" id="reject-title-text"></div> - <div class="message" id="reject-message-text"></div> - </cr-radio-button> - </paper-radio-group> - </div> - </div> - <div slot="bottom-buttons" class="flex layout horizontal"> - <div class="flex"></div> - <oobe-text-button id="next-button" inverse on-tap="onNextTap_" - disabled="[[buttonsDisabled]]" hidden="[[moreContents]]"> - <div id="next-button-text"></div> - </oobe-text-button> - </div> - </oobe-dialog> - </template> -</dom-module>
diff --git a/chrome/browser/resources/chromeos/assistant_optin/assistant_confirm_reject.js b/chrome/browser/resources/chromeos/assistant_optin/assistant_confirm_reject.js deleted file mode 100644 index bf2e048..0000000 --- a/chrome/browser/resources/chromeos/assistant_optin/assistant_confirm_reject.js +++ /dev/null
@@ -1,92 +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. - -/** - * @fileoverview Polymer element for displaying material design assistant - * confirm reject screen. - * - * Event 'loading' will be fired when the page is loading/reloading. - * Event 'loaded' will be fired when the page has been successfully loaded. - */ - -Polymer({ - is: 'assistant-confirm-reject', - - behaviors: [OobeDialogHostBehavior], - - properties: { - /** - * Buttons are disabled when the page content is loading. - */ - buttonsDisabled: { - type: Boolean, - value: true, - }, - }, - - /** - * Whether all the screen content has been successfully loaded. - * @type {boolean} - * @private - */ - pageLoaded_: false, - - /** - * On-tap event handler for next button. - * - * @private - */ - onNextTap_: function() { - var confirmResult = this.$['accept'].getAttribute('checked') != null; - chrome.send('AssistantConfirmRejectScreen.userActed', [confirmResult]); - }, - - /** - * Reloads the page. - */ - reloadPage: function() { - this.fire('loading'); - this.buttonsDisabled = true; - }, - - /** - * Reload the page with the given consent string text data. - */ - reloadContent: function(data) { - this.$['title-text'].textContent = data['confirmRejectTitle']; - this.$['next-button-text'].textContent = - data['confirmRejectContinueButton']; - this.$['accept-title-text'].textContent = data['confirmRejectAcceptTitle']; - this.$['accept-message-text'].textContent = - data['confirmRejectAcceptMessage']; - this.$['accept-message-extra-text'].textContent = - data['confirmRejectAcceptMessageExpanded']; - this.$['reject-title-text'].textContent = data['confirmRejectRejectTitle']; - this.$['reject-message-text'].textContent = - data['confirmRejectRejectMessage']; - - this.pageLoaded_ = true; - this.onPageLoaded(); - }, - - /** - * Handles event when all the page content has been loaded. - */ - onPageLoaded: function() { - this.fire('loaded'); - this.buttonsDisabled = false; - this.$['next-button'].focus(); - }, - - /** - * Signal from host to show the screen. - */ - onShow: function() { - if (!this.pageLoaded_) { - this.reloadPage(); - } else { - this.$['next-button'].focus(); - } - }, -});
diff --git a/chrome/browser/resources/chromeos/assistant_optin/assistant_confirm_reject.svg b/chrome/browser/resources/chromeos/assistant_optin/assistant_confirm_reject.svg deleted file mode 100644 index 0420bc4..0000000 --- a/chrome/browser/resources/chromeos/assistant_optin/assistant_confirm_reject.svg +++ /dev/null
@@ -1,208 +0,0 @@ -<svg xmlns="http://www.w3.org/2000/svg" - xmlns:xlink="http://www.w3.org/1999/xlink" viewBox="0 0 1586.38 846.63"> - <defs> - <style> .cls-15, .cls-16, .cls-20, .cls-21, .cls-23, .cls-29, .cls-33, .cls-46, .cls-47, .cls-5 { fill: none } - .cls-3 { fill: #f1f2f2 } - .cls-4 { fill: #e1e2e6 } - .cls-33, .cls-47, .cls-5 { stroke: #fff } - .cls-15, .cls-20, .cls-23, .cls-29, .cls-33, .cls-46, .cls-47, .cls-5 { stroke-linecap: round } - .cls-15, .cls-16, .cls-20, .cls-21, .cls-5 { stroke-miterlimit: 10 } - .cls-5 { stroke-width: 12.41px } - .cls-6 { fill: #fff } - .cls-23 { mix-blend-mode: multiply } - .cls-10 { fill: #4285f4 } - .cls-15 { stroke: #979da5 } - .cls-15, .cls-29 { stroke-width: 5.15px } - .cls-16, .cls-20, .cls-46 { stroke: #686c71 } - .cls-16, .cls-20, .cls-46, .cls-47 { stroke-width: 6.4px } - .cls-17 { fill: #979da5 } - .cls-19 { fill: #34a853 } - .cls-21 { stroke: #f2f3f4; stroke-width: 3.43px } - .cls-22 { fill: #ea4335 } - .cls-23, .cls-29 { stroke: #4285f4 } - .cls-23, .cls-29, .cls-33, .cls-46, .cls-47 { stroke-linejoin: round } - .cls-23 { stroke-width: 12px } - .cls-28 { fill: #fbbc05 } - .cls-33 { stroke-width: 5.64px } - .cls-36 { fill: #686c71 } - .cls-41 { fill: #2a2c33 } </style> - <linearGradient id="linear-gradient" x1="9424.34" y1="297.42" x2="9625.34" y2="297.42" gradientTransform="matrix(1.05 0 0 1 -9807.24 471.69)" gradientUnits="userSpaceOnUse"> - <stop offset="0" stop-color="#fff" /> - <stop offset="1" stop-color="#979da5" /> - </linearGradient> - <linearGradient id="linear-gradient-2" x1="10211.87" y1="301.85" x2="10461.84" y2="301.85" xlink:href="#linear-gradient" /> - <linearGradient id="linear-gradient-3" x1="10591.49" y1="305.35" x2="10705.62" y2="305.35" xlink:href="#linear-gradient" /> - <linearGradient id="linear-gradient-4" x1="1057.05" y1="644" x2="1418.97" y2="644" gradientTransform="matrix(-1 0 0 1 1928 0)" gradientUnits="userSpaceOnUse"> - <stop offset="0" stop-color="#686c71" /> - <stop offset=".32" stop-color="#9d9fa3" /> - <stop offset=".78" stop-color="#e3e4e5" /> - <stop offset="1" stop-color="#fff" /> - </linearGradient> - <linearGradient id="linear-gradient-5" x1="955.26" y1="129.27" x2="1021.33" y2="129.27" gradientTransform="rotate(180 894.015 222.815)" gradientUnits="userSpaceOnUse"> - <stop offset="0" stop-color="#979da5" /> - <stop offset="1" stop-color="#fff" /> - </linearGradient> - <linearGradient id="linear-gradient-6" x1="741.04" y1="121.29" x2="822.23" y2="121.29" gradientTransform="rotate(90 691.195 352.105)" xlink:href="#linear-gradient-5" /> - <linearGradient id="linear-gradient-7" x1="672.18" y1="632.75" x2="909.85" y2="395.08" xlink:href="#linear-gradient" /> - <linearGradient id="linear-gradient-8" x1="1124.31" y1="657.44" x2="1005.01" y2="657.44" xlink:href="#linear-gradient" /> - <linearGradient id="linear-gradient-9" x1="1291.74" y1="328.74" x2="1400.04" y2="437.04" gradientTransform="rotate(90 1368.5 322.5)" gradientUnits="userSpaceOnUse"> - <stop offset="0" stop-color="#e1e2e6" /> - <stop offset="1" stop-color="#fff" /> - </linearGradient> - <linearGradient id="linear-gradient-10" x1="890.9" y1="351.48" x2="843.75" y2="398.63" xlink:href="#linear-gradient-5" /> - <linearGradient id="linear-gradient-11" x1="882.1" y1="713.27" x2="896.32" y2="727.49" xlink:href="#linear-gradient-5" /> - <linearGradient id="linear-gradient-12" x1="585.8" y1="656.66" x2="585.8" y2="500.58" gradientTransform="rotate(-7.81 -260.353 1606.207)" xlink:href="#linear-gradient" /> - <linearGradient id="linear-gradient-13" x1="594.3" y1="502.49" x2="594.3" y2="628.88" gradientTransform="rotate(-7.81 -260.353 1606.207)" gradientUnits="userSpaceOnUse"> - <stop offset=".38" stop-color="#fff" stop-opacity="0" /> - <stop offset=".38" stop-color="#f9f9fa" stop-opacity=".06" /> - <stop offset=".38" stop-color="#e2e4e6" stop-opacity=".28" /> - <stop offset=".39" stop-color="#ced0d4" stop-opacity=".48" /> - <stop offset=".4" stop-color="#bcc0c5" stop-opacity=".64" /> - <stop offset=".4" stop-color="#afb3b9" stop-opacity=".77" /> - <stop offset=".41" stop-color="#a4a9b0" stop-opacity=".88" /> - <stop offset=".42" stop-color="#9ca2aa" stop-opacity=".95" /> - <stop offset=".43" stop-color="#989ea6" stop-opacity=".99" /> - <stop offset=".47" stop-color="#979da5" /> - <stop offset=".57" stop-color="#bfc3c8" stop-opacity=".61" /> - <stop offset=".66" stop-color="#e2e3e6" stop-opacity=".28" /> - <stop offset=".73" stop-color="#f7f7f8" stop-opacity=".08" /> - <stop offset=".77" stop-color="#fff" stop-opacity="0" /> - </linearGradient> - <linearGradient id="linear-gradient-14" x1="260.06" y1="560.5" x2="366.27" y2="560.5" xlink:href="#linear-gradient" /> - <linearGradient id="linear-gradient-15" x1="2123.45" y1="1680.93" x2="2059.86" y2="1680.93" gradientTransform="rotate(180 1271.845 1170.365)" gradientUnits="userSpaceOnUse"> - <stop offset="0" stop-color="#fff" /> - <stop offset="1" stop-color="#686c71" /> - </linearGradient> - <linearGradient id="linear-gradient-16" x1="2003.93" y1="1681.29" x2="2003.93" y2="1756.07" gradientTransform="translate(-1558.93 -1115.88)" gradientUnits="userSpaceOnUse"> - <stop offset="0" stop-color="#fff" /> - <stop offset="1" stop-color="#808285" /> - </linearGradient> - <linearGradient id="linear-gradient-17" x1="-17031.15" y1="3746.35" x2="-17031.15" y2="4024.29" gradientTransform="matrix(.21 0 0 .66 4090.12 -1587.95)" gradientUnits="userSpaceOnUse"> - <stop offset="0" stop-color="#fff" /> - <stop offset=".91" stop-color="#8c8d90" /> - <stop offset="1" stop-color="#808285" /> - </linearGradient> - <linearGradient id="linear-gradient-18" x1="3.51" y1="3618.68" x2="3.51" y2="3643.66" gradientTransform="translate(510.76 -2786.98)" gradientUnits="userSpaceOnUse"> - <stop offset="0" stop-color="#fff" /> - <stop offset=".91" stop-color="#fbc21d" /> - <stop offset="1" stop-color="#fbbc05" /> - </linearGradient> - <linearGradient id="linear-gradient-19" x1="-146.99" y1="-862.05" x2="-76.83" y2="-791.89" gradientTransform="rotate(111.7 193.858 577.349)" xlink:href="#linear-gradient-9" /> - <linearGradient id="linear-gradient-20" x1="9501.62" y1="75.44" x2="9556.03" y2="75.44" xlink:href="#linear-gradient" /> - <clipPath id="clip-path" transform="translate(-149.62 -106.37)"> - <path d="M1085.1 397H735.44v494h349.66a12.27 12.27 0 0 0 12.27-12.27V409.27A12.27 12.27 0 0 0 1085.1 397z" fill="none" /> - </clipPath> - </defs> - <g style="isolation:isolate"> - <g id="Background"> - <rect class="cls-3" x="649.46" width="298.45" height="512.27" rx="149.23" ry="149.23" /> - <rect class="cls-3" x="1287.92" width="298.45" height="512.27" rx="149.23" ry="149.23" /> - <path class="cls-4" d="M1444.72 209.78h284.1a149.28 149.28 0 0 0-142.05-103.41 149.28 149.28 0 0 0-142.05 103.41z" transform="translate(-149.62 -106.37)" /> - <path class="cls-5" d="M1392.15 74.69h90" /> - <path class="cls-6" d="M1306.37 461.82a46.49 46.49 0 0 1 64-39.76 103.65 103.65 0 0 1 194.07-11.69 61.75 61.75 0 0 1 88.07 51.46z" transform="translate(-149.62 -106.37)" /> - <path class="cls-4" d="M806.26 209.78h284.1a149.28 149.28 0 0 0-142.05-103.41 149.28 149.28 0 0 0-142.05 103.41z" transform="translate(-149.62 -106.37)" /> - <path class="cls-5" d="M753.69 74.69h90" /> - <rect class="cls-3" x="30.42" width="298.45" height="512.27" rx="149.23" ry="149.23" /> - <path class="cls-4" d="M187.22 209.78h284.1a149.28 149.28 0 0 0-142.05-103.41 149.28 149.28 0 0 0-142.05 103.41z" transform="translate(-149.62 -106.37)" /> - <path class="cls-5" d="M134.64 74.69h90.01" /> - <path class="cls-6" d="M987.73 304.24a42.64 42.64 0 0 1 18.27 4.13 71.8 71.8 0 0 1 137.48 28.94c0 2.26-.13 4.49-.34 6.69H945a42.85 42.85 0 0 1 42.73-39.76zM258.56 490.62a27.22 27.22 0 0 1 11.66 2.64A45.84 45.84 0 0 1 358 511.73c0 1.44-.09 2.87-.22 4.27H231.29a27.36 27.36 0 0 1 27.27-25.38zM482.56 246.62a27.22 27.22 0 0 1 11.66 2.64A45.84 45.84 0 0 1 582 267.73c0 1.44-.09 2.87-.22 4.27H455.29a27.36 27.36 0 0 1 27.27-25.38zM1661.2 531.43a17.77 17.77 0 0 0-7.61 1.72 29.92 29.92 0 0 0-57.3 12.06c0 .94.06 1.87.14 2.79H1679a17.86 17.86 0 0 0-17.8-16.57zM896.93 445.32a17.62 17.62 0 0 0-7.55 1.71 29.67 29.67 0 0 0-56.8 12c0 .93.06 1.85.14 2.77h81.86a17.71 17.71 0 0 0-17.65-16.48zM149.62 397a39.81 39.81 0 0 1 54.79-34 88.75 88.75 0 0 1 166.17-10A52.88 52.88 0 0 1 446 397z" transform="translate(-149.62 -106.37)" /> - </g> - <g id="Foreground"> - <path style="mix-blend-mode:multiply" fill="url(#linear-gradient)" d="M64.38 753.76h211.59v30.72H64.38z" /> - <path style="mix-blend-mode:multiply" fill="url(#linear-gradient-2)" d="M881.38 762.63h263.15v21.82H881.38z" /> - <path style="mix-blend-mode:multiply" fill="url(#linear-gradient-3)" d="M1314.38 770.63h120.15v12.82h-120.15z" /> - <rect class="cls-10" x="220.47" y="290.63" width="727.28" height="494" rx="12.27" ry="12.27" /> - <path d="M382.36 397H732v494H382.36a12.27 12.27 0 0 1-12.27-12.27V409.27A12.27 12.27 0 0 1 382.36 397z" transform="translate(-149.62 -106.37)" style="mix-blend-mode:multiply" fill="url(#linear-gradient-4)" opacity=".2" /> - <path style="mix-blend-mode:multiply" opacity=".7" fill="url(#linear-gradient-5)" d="M847.27 342.09l-51.89-51.46h-42.32v51.46h94.21z" /> - <path style="mix-blend-mode:multiply" fill="url(#linear-gradient-6)" opacity=".5" d="M947.74 421.85l-51.46-37.73V499.9h51.46v-78.05z" /> - <path style="mix-blend-mode:multiply" fill="url(#linear-gradient-7)" opacity=".5" d="M628.36 330.6L434.53 524.42l141.94 260.21h289.8l46.31-46.31L628.36 330.6z" /> - <rect class="cls-4" x="704.8" y="493.76" width="423.07" height="299.88" rx="24.28" ry="24.28" transform="rotate(90 894.71 515.7)" /> - <path class="cls-6" transform="rotate(90 894.71 511.41)" d="M748.65 505.06h335.37v268.69H748.65z" /> - <path class="cls-15" d="M751.59 347.02h30.25" /> - <circle class="cls-15" cx="766.72" cy="724.08" r="11.23" /> - <path class="cls-16" d="M1399 658.24a19.11 19.11 0 1 1 0-38.21M1270.44 658.24a19.11 19.11 0 1 1 0-38.21" transform="translate(-149.62 -106.37)" /> - <path class="cls-17" d="M1132.1 784.38l-55.11-253.85-20.79-.04-40.81 253.89h116.71z" /> - <path style="mix-blend-mode:multiply" fill="url(#linear-gradient-8)" opacity=".5" d="M1056.2 530.49l.05 253.89h119.25l-60.27-253.85-59.03-.04z" /> - <path class="cls-4" d="M1350.38 784.38l-40.82-253.23-253.36-.66 40.98 253.89h253.2z" /> - <path class="cls-19" d="M1319.28 591.66l-9.83-61.17H1056.2l9.89 61.17h253.19z" /> - <path class="cls-20" d="M1270.44 620a19.11 19.11 0 1 1 0 38.21M1399 620a19.11 19.11 0 1 1 0 38.21" transform="translate(-149.62 -106.37)" /> - <path class="cls-17" d="M664.72 395.27h181.82v144.08H664.72z" /> - <path class="cls-3" d="M683.46 436.96v230.52h183.6l.07-230.52H683.46z" /> - <path class="cls-4" d="M794.97 546.08h55.43v103.97h-55.43z" /> - <path class="cls-4" d="M700.66 528.32H850.3v103.43H700.66zM827.14 491.53h8.84v19.36h-8.84z" /> - <path class="cls-6" d="M700.66 528.32H850.3v14.37H700.66z" /> - <path class="cls-21" d="M793.45 660.37V526.38M696.76 560.55h159.43M696.76 543.4h159.43M697.14 578.12h159.44M696.14 596.16h159.43M697.03 614.14h159.44M695.67 631.87h159.44" /> - <circle class="cls-6" cx="885.47" cy="592" r="26.18" transform="rotate(-45 682.266 719.426)" /> - <path class="cls-6" d="M785.53 464.44h9.45v46.51h-9.45z" /> - <path class="cls-19" d="M799.94 483.03h9.03v27.92h-9.03z" /> - <path class="cls-10" d="M813.55 500.89h8.88v9.99h-8.88z" /> - <path class="cls-19" d="M904 573.49a26.1 26.1 0 0 0-18.51-7.67v25.9l26.15-.84a26.08 26.08 0 0 0-7.64-17.39z" transform="translate(-149.62 -106.37)" /> - <path class="cls-10" d="M664.72 395.27h181.82v18.01H664.72z" /> - <circle class="cls-6" cx="674.16" cy="404.7" r="4.29" /> - <path class="cls-6" d="M1273.5 455.3a120.8 120.8 0 1 1 120.8-120.8 120.94 120.94 0 0 1-120.8 120.8z" transform="translate(-149.62 -106.37)" /> - <path class="cls-22" d="M1273.5 222A112.5 112.5 0 1 1 1161 334.5 112.5 112.5 0 0 1 1273.5 222m0-16.6a129.1 129.1 0 1 0 91.29 37.81 128.25 128.25 0 0 0-91.29-37.81z" transform="translate(-149.62 -106.37)" /> - <path class="cls-23" d="M1124.74 235.92l39.81-39.81M1124.74 235.92l-51.06-51.06" /> - <circle class="cls-4" cx="1123.88" cy="134.67" r="7.63" /> - <circle class="cls-4" cx="1123.88" cy="321.6" r="7.63" /> - <circle class="cls-4" cx="1217.34" cy="228.13" r="7.63" /> - <circle class="cls-4" cx="1030.41" cy="228.13" r="7.63" /> - <path d="M1257.92 237.58a112.5 112.5 0 0 1 87 183.88 112.5 112.5 0 1 0-158.33-158.33 112 112 0 0 1 71.33-25.55z" transform="translate(-149.62 -106.37)" style="mix-blend-mode:multiply" fill="url(#linear-gradient-9)" /> - <path style="mix-blend-mode:multiply" fill="url(#linear-gradient-10)" opacity=".4" d="M834.53 325.8H800.8l115.78 115.78V400.7l-82.05-74.9z" /> - <path style="mix-blend-mode:multiply" fill="url(#linear-gradient-11)" opacity=".4" d="M916.87 689.44l-58.03 59.17h14.57l43.46-42.02v-17.15z" /> - <path class="cls-4" d="M885.53 591.73v26.45a26.16 26.16 0 0 0 26-24.16z" transform="translate(-149.62 -106.37)" /> - <path class="cls-10" d="M885.47 591.72l25.85 4.39a26.29 26.29 0 0 0-.95-12.17z" transform="translate(-149.62 -106.37)" /> - <path style="mix-blend-mode:multiply" fill="url(#linear-gradient-12)" d="M509.12 548.79l-118.98 16.32-11.93-118.31 115.05-15.77 15.86 117.76z" /> - <path class="cls-28" d="M516.72 508.15l-18.97-63.79-3.58-26.15-117.67 16.14 3.58 26.14 25.31 87.06 90.9-12.46 20.43-26.94z" /> - <path class="cls-29" d="M438.08 472.46l27.89 30.63M461.33 469.28l-18.61 37M432.06 490.78l39.83-5.46" /> - <path fill="#ffd364" d="M496.27 535.1l20.47-26.96-23.72 3.25 3.25 23.71z" /> - <path style="mix-blend-mode:color-burn" fill="url(#linear-gradient-13)" opacity=".4" d="M516.72 508.15l-18.97-63.79-3.58-26.15-117.67 16.14 3.58 26.14 25.31 87.06 90.9-12.46 20.43-26.94z" /> - <g> - <path d="M1433.91 493.8H1359a33.28 33.28 0 0 0-33.28 33.28 33.28 33.28 0 0 0 25.58 32.37V577l16.7-16.64h65.94a33.28 33.28 0 0 0 33.28-33.28 33.28 33.28 0 0 0-33.31-33.28z" transform="translate(-149.62 -106.37)" style="mix-blend-mode:multiply" fill="#4285f4" /> - <path class="cls-33" d="M1206.93 411.01h78.49M1206.93 431.15h78.49" /> - </g> - <path style="mix-blend-mode:multiply" fill="url(#linear-gradient-14)" opacity=".5" d="M284.5 422.56l-33.59 33.59v242.29l45.03-43.53-11.44-232.35z" /> - <g> - <path stroke-width="4.67" stroke-linejoin="round" stroke-linecap="round" stroke="#fff" fill="none" d="M307.92 437.91h8.6v54.45" /> - <path class="cls-36" transform="rotate(-90 317.37 670.32)" d="M362.8 637.59h165.13v22.21H362.8z" /> - <path transform="rotate(-90 317.37 681.43)" style="mix-blend-mode:multiply" fill="url(#linear-gradient-15)" opacity=".4" d="M373.91 648.69h142.92v22.21H373.91z" /> - <path class="cls-6" d="M456.12 731.26l-9.43 28.9a1.31 1.31 0 0 1-2.48 0l-10.07-28.93z" transform="translate(-149.62 -106.37)" /> - <path class="cls-36" d="M442.36 754.88l1.85 5.31a1.31 1.31 0 0 0 2.48 0l1.71-5.26z" transform="translate(-149.62 -106.37)" /> - <path class="cls-36" d="M418.42 551.08h67.43v28.66h-67.43a14.26 14.26 0 0 1-14.26-14.26v-.15a14.26 14.26 0 0 1 14.26-14.26z" transform="rotate(90 423.375 437.415)" /> - <path d="M418.42 551.08h67.43v28.66h-67.43a14.26 14.26 0 0 1-14.26-14.26v-.15a14.26 14.26 0 0 1 14.26-14.26z" transform="rotate(90 423.375 437.415)" style="mix-blend-mode:multiply" fill="url(#linear-gradient-16)" opacity=".4" /> - </g> - <rect class="cls-10" x="146.71" y="527.05" width="200.69" height="39.45" rx="19.73" ry="19.73" /> - <path transform="rotate(-90 322.645 970.395)" style="mix-blend-mode:multiply" fill="url(#linear-gradient-17)" opacity=".2" d="M446.4 819.13h8.47v259.28h-8.47z" /> - <g> - <path class="cls-28" d="M413.59 820.79h201.36v25.81H413.59z" /> - <path style="mix-blend-mode:multiply" fill="url(#linear-gradient-18)" opacity=".4" d="M413.59 820.79h201.36v25.81H413.59z" /> - <path class="cls-4" d="M413.59 846.6l-38.27-12.48 38.27-13.33v25.81z" /> - <path class="cls-41" d="M385.86 830.45l-10.54 3.67 10.51 3.41.03-7.08z" /> - <path class="cls-22" d="M764.69 927.15h-14V953h14a12.91 12.91 0 0 0 0-25.82z" transform="translate(-149.62 -106.37)" /> - <path class="cls-4" d="M598.79 820.79h5.91v25.82h-5.91z" /> - </g> - <path stroke="#e1e2e6" stroke-width="3.24" stroke-miterlimit="10" stroke-linecap="round" fill="none" d="M421.15 833.53h168.74" /> - <g> - <path stroke-width="8.85" stroke="#fbbc05" stroke-linecap="square" stroke-linejoin="round" fill="none" d="M1438.61 716.94l66-28.46" /> - <path stroke="#2a2c33" stroke-width="8.85" stroke-linejoin="round" stroke-linecap="round" fill="none" d="M1470.3 636.72l-10.85 27.33" /> - <path class="cls-6" d="M1588.53 885.06a62.67 62.67 0 1 1 58.25-39.54 62.36 62.36 0 0 1-58.25 39.54z" transform="translate(-149.62 -106.37)" /> - <path class="cls-28" d="M1588.56 764.68a57.7 57.7 0 1 1-53.63 36.4 57.52 57.52 0 0 1 53.63-36.4m0-10a67.71 67.71 0 1 0 25 4.79 67.56 67.56 0 0 0-25-4.79z" transform="translate(-149.62 -106.37)" /> - <path class="cls-28" transform="rotate(21.67 1822.347 299.971)" d="M1601.56 737.12h35.87v14.11h-35.87z" /> - <circle class="cls-4" cx="1605.59" cy="779.47" r="3.82" transform="rotate(-68.33 1452.5 836.499)" /> - <circle class="cls-4" cx="1571.08" cy="866.36" r="3.82" transform="rotate(-68.33 1417.981 923.397)" /> - <circle class="cls-4" cx="1631.78" cy="840.18" r="3.82" transform="rotate(-68.33 1478.69 897.208)" /> - <circle class="cls-4" cx="1544.89" cy="805.66" r="3.82" transform="rotate(-68.33 1391.8 862.693)" /> - <path d="M1600.16 775.19a57.69 57.69 0 0 1 15.32 98.19 57.68 57.68 0 1 0-63-96l1-.39a57.54 57.54 0 0 1 46.68-1.8z" transform="translate(-149.62 -106.37)" style="mix-blend-mode:multiply" fill="url(#linear-gradient-19)" /> - <path class="cls-36" d="M1582.63 820.27l15-30.87a3.13 3.13 0 0 1 5.84 2.19l-9 33.1a6.33 6.33 0 0 1-12.21-3.32 6.76 6.76 0 0 1 .37-1.1z" transform="translate(-149.62 -106.37)" /> - </g> - <g> - <path class="cls-46" d="M1382.68 740.17c-1.25-7.34 3.68-13.29 11-13.29s14.29 6 15.54 13.29-3.68 13.29-11 13.29M1398.25 753.62c9.95 0 19.39 8.07 21.08 18s-5 18-14.95 18-19.39-8.07-21.08-18" transform="translate(-149.62 -106.37)" /> - <path class="cls-46" d="M1280.72 631.67l8.87-11.5 10.06 63.15" /> - <path class="cls-47" d="M1105.16 623.59h81.03M1112.28 666.77h83.16M1120.47 709.96h185.21M1127.59 753.14h185.56" /> - </g> - <path style="mix-blend-mode:multiply" fill="url(#linear-gradient-20)" d="M174.38 527.63h46v39h-46z" /> - <g clip-path="url(#clip-path)"> - <path class="cls-41" d="M1133.12 586.81L893.84 347.53l19.41-19.41 239.28 239.28zM1152.53 712l-19.41-19.41L893.84 931.9l19.41 19.41z" transform="translate(-149.62 -106.37)" /> - </g> - </g> - </g> -</svg>
diff --git a/chrome/browser/resources/chromeos/assistant_optin/assistant_get_more.css b/chrome/browser/resources/chromeos/assistant_optin/assistant_get_more.css index 70d09dab..358ae3a1 100644 --- a/chrome/browser/resources/chromeos/assistant_optin/assistant_get_more.css +++ b/chrome/browser/resources/chromeos/assistant_optin/assistant_get_more.css
@@ -3,7 +3,7 @@ * found in the LICENSE file. */ #intro-text { - padding-bottom: 48px; + padding-bottom: 58px; } p {
diff --git a/chrome/browser/resources/chromeos/assistant_optin/assistant_get_more.html b/chrome/browser/resources/chromeos/assistant_optin/assistant_get_more.html index de1ee820..d903ce2 100644 --- a/chrome/browser/resources/chromeos/assistant_optin/assistant_get_more.html +++ b/chrome/browser/resources/chromeos/assistant_optin/assistant_get_more.html
@@ -13,17 +13,17 @@ <div class="container"> <img id="logo" src="assistant_logo.png"> <div class="title" id="title-text"></div> - <div class="sub-title" id="intro-text"></div> + <div class="content" id="intro-text"></div> <div class="line"></div> <div id="insertion-point"></div> </div> </div> <div slot="bottom-buttons" class="flex layout horizontal"> <div class="flex"></div> - <oobe-text-button id="next-button" inverse on-tap="onNextTap_" + <oobe-next-button id="next-button" inverse on-tap="onNextTap_" disabled="[[buttonsDisabled]]" hidden="[[moreContents]]"> <div id="next-button-text"></div> - </oobe-text-button> + </oobe-next-button> </div> </oobe-dialog> </template>
diff --git a/chrome/browser/resources/chromeos/assistant_optin/assistant_loading.css b/chrome/browser/resources/chromeos/assistant_optin/assistant_loading.css index 052ecae0..453108a7 100644 --- a/chrome/browser/resources/chromeos/assistant_optin/assistant_loading.css +++ b/chrome/browser/resources/chromeos/assistant_optin/assistant_loading.css
@@ -2,11 +2,11 @@ * Use of this source code is governed by a BSD-style license that can be * found in the LICENSE file. */ -#retry-button { +oobe-text-button { display: none; } -.error #retry-button { +.error oobe-text-button { display: block; } @@ -20,14 +20,16 @@ visibility: visible; } -.loading #retry-button { +.loading oobe-text-button { pointer-events: none; } #loading-message { - color: rgba(0, 0, 0, .54); - font-size: 13px; - padding: 210px 0 0 0; + padding-top: 240px; +} + +#retry-button { + margin-inline-end: 0; } paper-progress {
diff --git a/chrome/browser/resources/chromeos/assistant_optin/assistant_loading.html b/chrome/browser/resources/chromeos/assistant_optin/assistant_loading.html index 47941ac..aa8db30 100644 --- a/chrome/browser/resources/chromeos/assistant_optin/assistant_loading.html +++ b/chrome/browser/resources/chromeos/assistant_optin/assistant_loading.html
@@ -20,7 +20,7 @@ </div> </div> <div class="container" id="loading-container"> - <div id="loading-message"> + <div id="loading-message" class="content"> <div i18n-content="assistantOptinLoading"></div> </div> <paper-progress class="slow" indeterminate></paper-progress> @@ -28,6 +28,10 @@ </div> <div slot="bottom-buttons" class="flex layout horizontal"> <div class="flex"></div> + <oobe-text-button id="skip-button" on-tap="onSkipTap_" + disabled="[[buttonsDisabled]]"> + <div i18n-content="assistantOptinSkipButton"></div> + </oobe-text-button> <oobe-text-button id="retry-button" inverse android on-tap="onRetryTap_" disabled="[[buttonsDisabled]]"> <div i18n-content="assistantOptinRetryButton"></div>
diff --git a/chrome/browser/resources/chromeos/assistant_optin/assistant_loading.js b/chrome/browser/resources/chromeos/assistant_optin/assistant_loading.js index f7b3441..4ef86fb 100644 --- a/chrome/browser/resources/chromeos/assistant_optin/assistant_loading.js +++ b/chrome/browser/resources/chromeos/assistant_optin/assistant_loading.js
@@ -55,6 +55,15 @@ }, /** + * On-tap event handler for skip button. + * + * @private + */ + onSkipTap_: function() { + chrome.send('dialogClose'); + }, + + /** * Add class to the list of classes of root elements. * @param {string} className class to add *
diff --git a/chrome/browser/resources/chromeos/assistant_optin/assistant_optin.html b/chrome/browser/resources/chromeos/assistant_optin/assistant_optin.html index 4727f5a..8c5063d 100644 --- a/chrome/browser/resources/chromeos/assistant_optin/assistant_optin.html +++ b/chrome/browser/resources/chromeos/assistant_optin/assistant_optin.html
@@ -17,10 +17,10 @@ <link rel="import" href="chrome://resources/cr_elements/paper_button_style_css.html"> <link rel="import" href="chrome://resources/cr_elements/shared_style_css.html"> +<include src="../login/hd-iron-icon.html"> <include src="../login/oobe_buttons.html"> <include src="../login/oobe_change_picture.html"> <include src="../login/oobe_dialog.html"> -<include src="assistant_confirm_reject.html"> <include src="assistant_get_more.html"> <include src="assistant_loading.html"> <include src="assistant_ready.html">
diff --git a/chrome/browser/resources/chromeos/assistant_optin/assistant_optin.js b/chrome/browser/resources/chromeos/assistant_optin/assistant_optin.js index 2f408ea..55b68ad 100644 --- a/chrome/browser/resources/chromeos/assistant_optin/assistant_optin.js +++ b/chrome/browser/resources/chromeos/assistant_optin/assistant_optin.js
@@ -2,6 +2,7 @@ // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. +// <include src="../login/hd-iron-icon.js"> // <include src="../login/oobe_types.js"> // <include src="../login/oobe_buttons.js"> // <include src="../login/oobe_change_picture.js"> @@ -9,7 +10,6 @@ // <include src="../login/oobe_dialog.js"> // <include src="utils.js"> // <include src="setting_zippy.js"> -// <include src="assistant_confirm_reject.js"> // <include src="assistant_get_more.js"> // <include src="assistant_loading.js"> // <include src="assistant_ready.js"> @@ -43,7 +43,6 @@ loadTimeData.overrideValues(data); i18nTemplate.process(document, loadTimeData); $('value-prop').reloadContent(data); - $('confirm-reject').reloadContent(data); $('third-party').reloadContent(data); $('get-more').reloadContent(data); }, @@ -75,13 +74,6 @@ showNextScreen: function() { switch (this.currentScreen) { case $('value-prop'): - if ($('value-prop').userAccepted) { - this.showScreen($('third-party')); - } else { - this.showScreen($('confirm-reject')); - } - break; - case $('confirm-reject'): this.showScreen($('third-party')); break; case $('third-party'):
diff --git a/chrome/browser/resources/chromeos/assistant_optin/assistant_ready.css b/chrome/browser/resources/chromeos/assistant_optin/assistant_ready.css index 5affae8..2a52a01 100644 --- a/chrome/browser/resources/chromeos/assistant_optin/assistant_ready.css +++ b/chrome/browser/resources/chromeos/assistant_optin/assistant_ready.css
@@ -4,7 +4,11 @@ #ready-img { display: block; - height: 180px; + height: 186px; margin: auto; - padding: 72px 0 0 32px; + padding: 110px 0 0 72px; +} + +#button-text { + padding: 0 10px 0 10px; }
diff --git a/chrome/browser/resources/chromeos/assistant_optin/assistant_ready.html b/chrome/browser/resources/chromeos/assistant_optin/assistant_ready.html index 5af0408..1b607811 100644 --- a/chrome/browser/resources/chromeos/assistant_optin/assistant_ready.html +++ b/chrome/browser/resources/chromeos/assistant_optin/assistant_ready.html
@@ -13,7 +13,7 @@ <div class="container"> <img id="logo" src="assistant_logo.png"> <div class="title" i18n-content="assistantReadyTitle"></div> - <div class="sub-title" i18n-content="assistantReadyMessage"></div> + <div class="content" i18n-content="assistantReadyMessage"></div> <img id="ready-img" src="assistant_ready.svg"> </div> </div> @@ -21,7 +21,7 @@ <div class="flex"></div> <oobe-text-button id="next-button" inverse on-tap="onNextTap_" disabled="[[buttonsDisabled]]" hidden="[[moreContents]]"> - <div i18n-content="assistantReadyButton"></div> + <div id="button-text" i18n-content="assistantReadyButton"></div> </oobe-text-button> </div> </oobe-dialog>
diff --git a/chrome/browser/resources/chromeos/assistant_optin/assistant_shared_styles.css b/chrome/browser/resources/chromeos/assistant_optin/assistant_shared_styles.css index 52e8c555..b51c2047 100644 --- a/chrome/browser/resources/chromeos/assistant_optin/assistant_shared_styles.css +++ b/chrome/browser/resources/chromeos/assistant_optin/assistant_shared_styles.css
@@ -3,7 +3,7 @@ * found in the LICENSE file. */ a { - color: var(--google-blue-500); + color: var(--google-blue-600); font-weight: 400; text-decoration: none; } @@ -17,25 +17,27 @@ } .line { - background-color: rgba(0, 0, 0, .14); + background-color: rgb(218, 220, 224); height: 1px; margin: 8px 0 8px 0; } .title { - font: 28px 'Google Sans', sans-serif; - font-weight: 500; + color: var(--google-grey-900); + font-family: 'Google Sans', Roboto, sans-serif; + font-size: 28px; padding: 32px 0 16px 0; } .sub-title { + color: var(--google-grey-900); font: 13px Roboto, sans-serif; - font-weight: 400; } .content { - color: rgba(0, 0, 0, .54); - font-size: 13px; + color: var(--google-grey-700); + font: 13px Roboto, sans-serif; + line-height: 16px; } #logo { @@ -44,5 +46,5 @@ } #next-button { - margin-inline-end: 18px; + margin-inline-end: 0; }
diff --git a/chrome/browser/resources/chromeos/assistant_optin/assistant_third_party.css b/chrome/browser/resources/chromeos/assistant_optin/assistant_third_party.css index 181db8a..0a1c639b 100644 --- a/chrome/browser/resources/chromeos/assistant_optin/assistant_third_party.css +++ b/chrome/browser/resources/chromeos/assistant_optin/assistant_third_party.css
@@ -3,11 +3,10 @@ * found in the LICENSE file. */ .title { - font-size: 27px; + font-size: 26px; padding-bottom: 48px; } #footer-text { - font-size: 13px; - padding-top: 16px; + padding-top: 24px; }
diff --git a/chrome/browser/resources/chromeos/assistant_optin/assistant_third_party.html b/chrome/browser/resources/chromeos/assistant_optin/assistant_third_party.html index 4c8b42f..2f63a66 100644 --- a/chrome/browser/resources/chromeos/assistant_optin/assistant_third_party.html +++ b/chrome/browser/resources/chromeos/assistant_optin/assistant_third_party.html
@@ -15,15 +15,15 @@ <div class="title" id="title-text"></div> <div class="line"></div> <div id="insertion-point"></div> - <div id="footer-text"></div> + <div class="sub-title" id="footer-text"></div> </div> </div> <div slot="bottom-buttons" class="flex layout horizontal"> <div class="flex"></div> - <oobe-text-button id="next-button" inverse on-tap="onNextTap_" + <oobe-next-button id="next-button" inverse on-tap="onNextTap_" disabled="[[buttonsDisabled]]" hidden="[[moreContents]]"> <div id="next-button-text"></div> - </oobe-text-button> + </oobe-next-button> </div> </oobe-dialog> </template>
diff --git a/chrome/browser/resources/chromeos/assistant_optin/assistant_value_prop.css b/chrome/browser/resources/chromeos/assistant_optin/assistant_value_prop.css index 84f3a546..64fc874 100644 --- a/chrome/browser/resources/chromeos/assistant_optin/assistant_value_prop.css +++ b/chrome/browser/resources/chromeos/assistant_optin/assistant_value_prop.css
@@ -8,8 +8,8 @@ margin: auto; } -.sub-title { - padding-bottom: 16px; +#intro-text { + padding: 0 8px 16px 0; } #value-prop-container { @@ -17,37 +17,47 @@ } #consents-container { - border-left: 1px solid rgba(0, 0, 0, .14); + border-left: 1px solid rgb(218, 220, 224); padding-left: 24px; width: 50%; } #user-name { + color: #757575; padding-left: 8px; } #footer-text { + color: #757575; padding-top: 16px; } #user-image { border-radius: 50%; - height: 24px; + height: 20px; } .oobe-popup { border-radius: 8px; box-shadow: unset; + width: 512px; } #overlay-text { box-sizing: border-box; + font-size: 13px; margin: auto; min-height: 200px; - padding: 24px 24px 16px 24px; + padding: 16px; width: 100%; } +#overlay-additional-info-text { + color: rgb(128, 134, 139); + line-height: 20px; + padding-top: 20px; +} + #overlay-close-top { background-image: url(chrome://theme/IDR_CLOSE_DIALOG); background-position: center; @@ -68,8 +78,16 @@ background-image: url(chrome://theme/IDR_CLOSE_DIALOG_P); } +#overlay-close-bottom { + margin-right: 0; +} + +#close-button-text { + padding: 0 16px 0 16px; +} + .button-strip { display: flex; justify-content: flex-end; - margin: 8px; + margin: 16px; }
diff --git a/chrome/browser/resources/chromeos/assistant_optin/assistant_value_prop.html b/chrome/browser/resources/chromeos/assistant_optin/assistant_value_prop.html index e9da92f..0ad42daa 100644 --- a/chrome/browser/resources/chromeos/assistant_optin/assistant_value_prop.html +++ b/chrome/browser/resources/chromeos/assistant_optin/assistant_value_prop.html
@@ -16,7 +16,7 @@ <div class="container"> <img id="logo" src="assistant_logo.png"> <div class="title" id="title-text"></div> - <div class="sub-title" id="intro-text"></div> + <div class="content" id="intro-text"></div> <div class="flex layout horizontal"> <div id="value-prop-container"> <div class="flex layout horizontal center"> @@ -50,12 +50,13 @@ <div id="overlay-close-top"> </div> <div id="overlay-text"> - <b id="overlay-title-text"></b><p></p> + <div id="overlay-title-text"></div> <div id="overlay-additional-info-text"></div> </div> <div class="button-strip"> <oobe-text-button inverse id="overlay-close-bottom"> - <div i18n-content="assistantOptinOKButton"></div> + <div i18n-content="assistantOptinOKButton" id="close-button-text"> + </div> </oobe-text-button> </div> </div>
diff --git a/chrome/browser/resources/chromeos/assistant_optin/assistant_value_prop.js b/chrome/browser/resources/chromeos/assistant_optin/assistant_value_prop.js index 4730611..ec8cb20 100644 --- a/chrome/browser/resources/chromeos/assistant_optin/assistant_value_prop.js +++ b/chrome/browser/resources/chromeos/assistant_optin/assistant_value_prop.js
@@ -40,14 +40,6 @@ value: 'https://www.gstatic.com/opa-android/oobe/a02187e41eed9e42/v1_omni_en_us.html', }, - - /** - * Whether user accept the activity control. - */ - userAccepted: { - type: Boolean, - value: true, - }, }, /** @@ -119,7 +111,6 @@ * @private */ onSkipTap_: function() { - this.userAccepted = false; chrome.send('AssistantValuePropScreen.userActed', ['skip-pressed']); }, @@ -129,7 +120,6 @@ * @private */ onNextTap_: function() { - this.userAccepted = true; chrome.send('AssistantValuePropScreen.userActed', ['next-pressed']); },
diff --git a/chrome/browser/resources/chromeos/assistant_optin/setting_zippy.css b/chrome/browser/resources/chromeos/assistant_optin/setting_zippy.css index 05824506..d5541fdc 100644 --- a/chrome/browser/resources/chromeos/assistant_optin/setting_zippy.css +++ b/chrome/browser/resources/chromeos/assistant_optin/setting_zippy.css
@@ -2,36 +2,41 @@ * Use of this source code is governed by a BSD-style license that can be * found in the LICENSE file. */ -#setting_zippy { - padding-bottom: 14px; +#container[popupStyle] { + padding-top: 8px; +} + +#container:not([popupStyle]) { + align-items: center; + height: 48px; } .content { - padding: 6px 0 6px 0; -} - -.content[toggleStyle] { - padding-bottom: 0; + padding-top: 4px; } .content[popupStyle] { - padding-bottom: 24px; + padding: 4px 0 16px 0; } .icon { - min-width: 38px; + min-width: 36px; } .icon-view { display: block; - height: 24px; - width: 24px; + height: 20px; + width: 20px; +} + +cr-expand-button { + padding-right: 8px; } .toggle { - padding-top: 9px; + padding-right: 20px; } .indent { - padding: 6px 0 0 38px; + padding-left: 36px; }
diff --git a/chrome/browser/resources/chromeos/assistant_optin/setting_zippy.html b/chrome/browser/resources/chromeos/assistant_optin/setting_zippy.html index 02b2910..770f699c 100644 --- a/chrome/browser/resources/chromeos/assistant_optin/setting_zippy.html +++ b/chrome/browser/resources/chromeos/assistant_optin/setting_zippy.html
@@ -10,7 +10,8 @@ <link rel="stylesheet" href="../login/oobe_flex_layout.css"> <link rel="stylesheet" href="setting_zippy.css"> <link rel="stylesheet" href="assistant_shared_styles.css"> - <div class="flex layout horizontal"> + <div class="flex layout horizontal" id="container" + popupStyle$="[[popupStyle]]"> <div class="icon"> <webview class="icon-view" src="[[iconSrc]]"></webview> </div>
diff --git a/chrome/browser/resources/chromeos/assistant_optin/setting_zippy.js b/chrome/browser/resources/chromeos/assistant_optin/setting_zippy.js index 334ec85..c255d6a 100644 --- a/chrome/browser/resources/chromeos/assistant_optin/setting_zippy.js +++ b/chrome/browser/resources/chromeos/assistant_optin/setting_zippy.js
@@ -48,8 +48,8 @@ margin: 0; } #icon { - width: 24px; - height: 24px; + width: 20px; + height: 20px; } </style> <body><img id='icon' src="` +
diff --git a/chrome/browser/resources/chromeos/chromevox/host/chrome/tts_background.js b/chrome/browser/resources/chromeos/chromevox/host/chrome/tts_background.js index f392ea64..cb9c9cb0 100644 --- a/chrome/browser/resources/chromeos/chromevox/host/chrome/tts_background.js +++ b/chrome/browser/resources/chromeos/chromevox/host/chrome/tts_background.js
@@ -267,6 +267,29 @@ // pattern causes ChromeVox to read numbers as digits rather than words. textString = this.getNumberAsDigits_(textString); + // TODO(dtseng): some TTS engines don't handle strings that don't produce any + // speech very well. Handle empty and whitespace only strings (including + // non-breaking space) here to mitigate the issue somewhat. + if (cvox.TtsBackground.SKIP_WHITESPACE_.test(textString)) { + // Explicitly call start and end callbacks before skipping this text. + if (properties['startCallback']) { + try { + properties['startCallback'](); + } catch (e) { + } + } + if (properties['endCallback']) { + try { + properties['endCallback'](); + } catch (e) { + } + } + if (queueMode === cvox.QueueMode.FLUSH) { + this.stop(); + } + return this; + } + var mergedProperties = this.mergeProperties(properties); if (this.currentVoice && this.currentVoice !== constants.SYSTEM_VOICE) { @@ -759,3 +782,6 @@ cvox.AbstractTts.PERSONALITY_ANNOTATION); }); }; + +/** @private {RegExp} */ +cvox.TtsBackground.SKIP_WHITESPACE_ = /^[\s\u00a0]*$/;
diff --git a/chrome/browser/resources/component_extension_resources.grd b/chrome/browser/resources/component_extension_resources.grd index a4f5126..23ce86a 100644 --- a/chrome/browser/resources/component_extension_resources.grd +++ b/chrome/browser/resources/component_extension_resources.grd
@@ -40,6 +40,7 @@ <include name="IDR_HANGOUT_SERVICES_THUNK_JS" file="hangout_services/thunk.js" type="BINDATA" /> </if> <if expr="not is_android"> + <include name="IDR_FEEDBACK_BLUETOOTHLOGSINFO_HTML" file="feedback/html/bluetooth_logs_info.html" flattenhtml="true" allowexternalscript="true" type="BINDATA" /> <include name="IDR_FEEDBACK_DEFAULT_HTML" file="feedback/html/default.html" flattenhtml="true" allowexternalscript="true" type="BINDATA" /> <include name="IDR_FEEDBACK_SYSINFO_HTML" file="feedback/html/sys_info.html" flattenhtml="true" allowexternalscript="true" type="BINDATA" /> <include name="IDR_FEEDBACK_FEEDBACK_DATA_JS" file="feedback/js/data.js" flattenhtml="true" type="BINDATA" />
diff --git a/chrome/browser/resources/feedback/html/bluetooth_logs_info.html b/chrome/browser/resources/feedback/html/bluetooth_logs_info.html new file mode 100644 index 0000000..f246aae --- /dev/null +++ b/chrome/browser/resources/feedback/html/bluetooth_logs_info.html
@@ -0,0 +1,12 @@ +<!doctype html> +<html i18n-values="dir:textdirection;lang:language"> + <head> + <script src="chrome://resources/js/i18n_template_no_process.js"></script> + </head> + <body> + <div id="bluetooth-logs-info-container"> + <span i18n-content="bluetooth-logs-message"></span> + </div> + </body> +<html> +
diff --git a/chrome/browser/resources/feedback/html/default.html b/chrome/browser/resources/feedback/html/default.html index 8f83955..6caf36b 100644 --- a/chrome/browser/resources/feedback/html/default.html +++ b/chrome/browser/resources/feedback/html/default.html
@@ -81,6 +81,13 @@ </span> </div> <if expr="chromeos"> + <!-- Bluetooth Logs (Googler Internal Only) --> + <div id="bluetooth-checkbox-container" class="checkbox-field-container" + hidden> + <input id="bluetooth-logs-checkbox" type="checkbox" checked> + <label id="bluetooth-info-label" + i18n-values=".innerHTML:bluetooth-logs-info"></label> + </div> <!-- Performance Feedback --> <div id="performance-info-area" hidden> <input id="performance-info-checkbox" type="checkbox">
diff --git a/chrome/browser/resources/feedback/js/feedback.js b/chrome/browser/resources/feedback/js/feedback.js index 40cf123..afbb8b8 100644 --- a/chrome/browser/resources/feedback/js/feedback.js +++ b/chrome/browser/resources/feedback/js/feedback.js
@@ -78,6 +78,28 @@ var isShowingSrtPrompt = false; /** + * Regular expression to check for all variants of bluetooth, blutooth, with or + * without space between the words and for BT when used as an individual word, + * or as two individual characters. Case insensitive matching. + * @type {RegExp} + */ +const btRegEx = new RegExp('[b]lu[e]?[ ]?tooth|\b[b][ ]?[t]\b', 'i'); + +/** + * Regular expression to check for all strings indicating that a user can't + * connect to a HID or Audio device. This is also a likely indication of a + * Bluetooth related issue. + * Sample strings this will match: + * "I can't connect the speaker!", + * "The keyboard has connection problem." + * @type {RegExp} + */ +const cantConnectRegEx = new RegExp( + '((headphones|keyboard|mouse|speaker)((?!connect).*)connect)|' + + '(connect.*(headphones|keyboard|mouse|speaker))', + 'i'); + +/** * The callback used by the sys_info_page to receive the event that the system * information is ready. * @type {function(sysInfo)} @@ -159,6 +181,17 @@ } /** + * Checks if any keywords related to bluetooth have been typed. If they are, + * we show the bluetooth logs option, otherwise hide it. + * @param {Event} inputEvent The input event for the description textarea. + */ +function checkForBluetoothKeywords(inputEvent) { + var isRelatedToBluetooth = btRegEx.test(inputEvent.target.value) || + cantConnectRegEx.test(inputEvent.target.value); + $('bluetooth-checkbox-container').hidden = !isRelatedToBluetooth; +} + +/** * Sends the report; after the report is sent, we need to be redirected to * the landing page, but we shouldn't be able to navigate back, hence * we open the landing page in a new tab and sendReport closes this tab. @@ -193,6 +226,11 @@ useSystemInfo = useHistograms = true; } // <if expr="chromeos"> + if ($('bluetooth-logs-checkbox') != null && + $('bluetooth-logs-checkbox').checked) { + feedbackInfo.sendBluetoothLogs = true; + feedbackInfo.categoryTag = 'BluetoothReportWithLogs'; + } if ($('performance-info-checkbox') == null || !($('performance-info-checkbox').checked)) { feedbackInfo.traceId = null; @@ -332,6 +370,12 @@ chrome.feedbackPrivate.logSrtPromptResult(SrtPromptResult.CLOSED); } }); + } else if ( + feedbackInfo.flow == + chrome.feedbackPrivate.FeedbackFlow.GOOGLE_INTERNAL) { + $('description-text') + .addEventListener('input', checkForBluetoothKeywords); + $('srt-prompt').hidden = true; } else { $('srt-prompt').hidden = true; } @@ -491,6 +535,27 @@ termsOfServiceUrlElement, FEEDBACK_TERM_OF_SERVICE_URL); } + var bluetoothLogsInfoLinkElement = $('bluetooth-logs-info-link'); + if (bluetoothLogsInfoLinkElement) { + bluetoothLogsInfoLinkElement.onclick = function(e) { + e.preventDefault(); + + chrome.app.window.create( + '/html/bluetooth_logs_info.html', + {width: 360, height: 120, resizable: false}, + function(appWindow) { + appWindow.contentWindow.onload = function() { + i18nTemplate.process( + appWindow.contentWindow.document, loadTimeData); + }; + }); + + bluetoothLogsInfoLinkElement.onauxclick = function(e) { + e.preventDefault(); + }; + }; + } + // Make sure our focus starts on the description field. $('description-text').focus(); });
diff --git a/chrome/browser/resources/settings/multidevice_page/multidevice_browser_proxy.js b/chrome/browser/resources/settings/multidevice_page/multidevice_browser_proxy.js index 58a2c4fd..f6ac995 100644 --- a/chrome/browser/resources/settings/multidevice_page/multidevice_browser_proxy.js +++ b/chrome/browser/resources/settings/multidevice_page/multidevice_browser_proxy.js
@@ -10,6 +10,14 @@ /** @return {!Promise<!MultiDevicePageContentData>} */ getPageContentData() {} + /** + * @param {!settings.MultiDeviceFeature} feature The feature whose state + * should be set. + * @param {boolean} enabled Whether the feature should be turned off or on. + * @return {!Promise<boolean>} Whether the operation was successful. + */ + setFeatureEnabledState(feature, enabled) {} + retryPendingHostSetup() {} } @@ -28,6 +36,11 @@ } /** @override */ + setFeatureEnabledState(feature, enabled) { + return cr.sendWithPromise('setFeatureEnabledState'); + } + + /** @override */ retryPendingHostSetup() { chrome.send('retryPendingHostSetup'); }
diff --git a/chrome/browser/resources/settings/multidevice_page/multidevice_constants.js b/chrome/browser/resources/settings/multidevice_page/multidevice_constants.js index b2f5470..71b8970 100644 --- a/chrome/browser/resources/settings/multidevice_page/multidevice_constants.js +++ b/chrome/browser/resources/settings/multidevice_page/multidevice_constants.js
@@ -19,6 +19,19 @@ }; /** + * Enum of MultiDevice features. Note that this is copied from (and must + * include an analog of all values in) the Feature enum in + * //chromeos/services/multidevice_setup/public/mojom/multidevice_setup.mojom. + * @enum {number} + */ + MultiDeviceFeature = { + BETTER_TOGETHER_SUITE: 0, + INSTANT_TETHERING: 1, + MESSAGES: 2, + SMART_LOCK: 3, + }; + + /** * Possible states of MultiDevice features. Note that this is copied from (and * must include an analog of all values in) the FeatureState enum in * //chromeos/services/multidevice_setup/public/mojom/multidevice_setup.mojom. @@ -36,6 +49,7 @@ return { MultiDeviceSettingsMode: MultiDeviceSettingsMode, + MultiDeviceFeature: MultiDeviceFeature, MultiDeviceFeatureState: MultiDeviceFeatureState, }; });
diff --git a/chrome/browser/sessions/session_restore_browsertest.cc b/chrome/browser/sessions/session_restore_browsertest.cc index 0391630..260fdc70 100644 --- a/chrome/browser/sessions/session_restore_browsertest.cc +++ b/chrome/browser/sessions/session_restore_browsertest.cc
@@ -24,11 +24,13 @@ #include "chrome/browser/prefs/session_startup_pref.h" #include "chrome/browser/profiles/profile.h" #include "chrome/browser/profiles/profile_manager.h" -#include "chrome/browser/sessions/session_restore.h" +#include "chrome/browser/resource_coordinator/session_restore_policy.h" +#include "chrome/browser/resource_coordinator/tab_manager_features.h" #include "chrome/browser/sessions/session_restore_test_helper.h" #include "chrome/browser/sessions/session_service.h" #include "chrome/browser/sessions/session_service_factory.h" #include "chrome/browser/sessions/session_service_test_helper.h" +#include "chrome/browser/sessions/tab_loader_delegate.h" #include "chrome/browser/sessions/tab_restore_service_factory.h" #include "chrome/browser/ui/browser.h" #include "chrome/browser/ui/browser_commands.h" @@ -207,11 +209,33 @@ const BrowserList* active_browser_list_; }; +// SessionRestorePolicy that always allow tabs to load. +class TestSessionRestorePolicy + : public resource_coordinator::SessionRestorePolicy { + public: + // Always allow tabs to load so we can test the behavior of SessionRestore + // independently from the policy logic. + bool ShouldLoad(content::WebContents* contents) const override { + return true; + } +}; + // Activates the smart restore behaviour and tracks the loading of tabs. class SmartSessionRestoreTest : public SessionRestoreTest, public content::NotificationObserver { public: SmartSessionRestoreTest() {} + + void SetUp() override { + TabLoaderDelegate::SetSessionRestorePolicyForTesting(&test_policy_); + SessionRestoreTest::SetUp(); + } + + void TearDown() override { + TabLoaderDelegate::SetSessionRestorePolicyForTesting(nullptr); + SessionRestoreTest::TearDown(); + } + void StartObserving(size_t num_tabs) { // Start by clearing everything so it can be reused in the same test. web_contents_.clear(); @@ -253,6 +277,7 @@ std::vector<content::WebContents*> web_contents_; scoped_refptr<content::MessageLoopRunner> message_loop_runner_; size_t num_tabs_; + TestSessionRestorePolicy test_policy_; DISALLOW_COPY_AND_ASSIGN(SmartSessionRestoreTest); };
diff --git a/chrome/browser/sessions/tab_loader_delegate.cc b/chrome/browser/sessions/tab_loader_delegate.cc index 4cbaa52..103f4e5 100644 --- a/chrome/browser/sessions/tab_loader_delegate.cc +++ b/chrome/browser/sessions/tab_loader_delegate.cc
@@ -28,6 +28,8 @@ // first paint and interactivity of the foreground tab. static const int kFirstTabLoadTimeoutMS = 60000; +resource_coordinator::SessionRestorePolicy* g_testing_policy = nullptr; + class TabLoaderDelegateImpl : public TabLoaderDelegate, public network::NetworkConnectionTracker::NetworkConnectionObserver { @@ -47,23 +49,28 @@ // TabLoaderDelegate: size_t GetMaxSimultaneousTabLoads() const override { - return policy_.simultaneous_tab_loads(); + return policy_->simultaneous_tab_loads(); } // TabLoaderDelegate: bool ShouldLoad(content::WebContents* contents) const override { - return policy_.ShouldLoad(contents); + return policy_->ShouldLoad(contents); } // TabLoaderDelegate: - void NotifyTabLoadStarted() override { policy_.NotifyTabLoadStarted(); } + void NotifyTabLoadStarted() override { policy_->NotifyTabLoadStarted(); } // network::NetworkConnectionTracker::NetworkConnectionObserver: void OnConnectionChanged(network::mojom::ConnectionType type) override; private: - // The policy engine used to implement ShouldLoad. - resource_coordinator::SessionRestorePolicy policy_; + // The default policy engine used to implement ShouldLoad. + resource_coordinator::SessionRestorePolicy default_policy_; + + // The policy engine used to implement ShouldLoad. By default this is simply + // a pointer to |default_policy_|, but it can also point to externally + // injected policy engine for testing. + resource_coordinator::SessionRestorePolicy* policy_; // The function to call when the connection type changes. TabLoaderCallback* callback_; @@ -78,7 +85,7 @@ }; TabLoaderDelegateImpl::TabLoaderDelegateImpl(TabLoaderCallback* callback) - : callback_(callback), weak_factory_(this) { + : policy_(&default_policy_), callback_(callback), weak_factory_(this) { content::GetNetworkConnectionTracker()->AddNetworkConnectionObserver(this); auto type = network::mojom::ConnectionType::CONNECTION_UNKNOWN; content::GetNetworkConnectionTracker()->GetConnectionType( @@ -94,6 +101,11 @@ first_timeout_ = base::TimeDelta::FromMilliseconds(kFirstTabLoadTimeoutMS); timeout_ = base::TimeDelta::FromMilliseconds(kInitialDelayTimerMS); + + // Override |policy_| if a testing policy has been set. + if (g_testing_policy) { + policy_ = g_testing_policy; + } } TabLoaderDelegateImpl::~TabLoaderDelegateImpl() { @@ -114,3 +126,9 @@ return std::unique_ptr<TabLoaderDelegate>( new TabLoaderDelegateImpl(callback)); } + +// static +void TabLoaderDelegate::SetSessionRestorePolicyForTesting( + resource_coordinator::SessionRestorePolicy* policy) { + g_testing_policy = policy; +}
diff --git a/chrome/browser/sessions/tab_loader_delegate.h b/chrome/browser/sessions/tab_loader_delegate.h index 8195f2f1..2a3e18d7 100644 --- a/chrome/browser/sessions/tab_loader_delegate.h +++ b/chrome/browser/sessions/tab_loader_delegate.h
@@ -13,6 +13,10 @@ class WebContents; } +namespace resource_coordinator { +class SessionRestorePolicy; +} + class TabLoaderCallback { public: // This function will get called to suppress and to allow tab loading. Tab @@ -52,6 +56,10 @@ // Notifies the delegate that a tab load has been initiated. virtual void NotifyTabLoadStarted() = 0; + // Testing seam to inject a custom SessionRestorePolicy. + static void SetSessionRestorePolicyForTesting( + resource_coordinator::SessionRestorePolicy* policy); + protected: // The delegate should only be created via the factory function. TabLoaderDelegate() {}
diff --git a/chrome/browser/ssl/certificate_error_report.cc b/chrome/browser/ssl/certificate_error_report.cc index 2942cf64..2d8e6d6f 100644 --- a/chrome/browser/ssl/certificate_error_report.cc +++ b/chrome/browser/ssl/certificate_error_report.cc
@@ -75,18 +75,24 @@ } void AddVerifyFlagsToReport( - int verify_flags, + const net::CertVerifier::Config& config, ::google::protobuf::RepeatedField<int>* report_flags) { -#define COPY_VERIFY_FLAGS(flag) \ - if (verify_flags & net::CertVerifier::VERIFY_##flag) \ - report_flags->Add(chrome_browser_ssl::TrialVerificationInfo::VERIFY_##flag); - - COPY_VERIFY_FLAGS(REV_CHECKING_ENABLED); - COPY_VERIFY_FLAGS(REV_CHECKING_REQUIRED_LOCAL_ANCHORS); - COPY_VERIFY_FLAGS(ENABLE_SHA1_LOCAL_ANCHORS); - COPY_VERIFY_FLAGS(DISABLE_SYMANTEC_ENFORCEMENT); - -#undef COPY_VERIFY_FLAGS + if (config.enable_rev_checking) { + report_flags->Add( + chrome_browser_ssl::TrialVerificationInfo::VERIFY_REV_CHECKING_ENABLED); + } + if (config.require_rev_checking_local_anchors) { + report_flags->Add(chrome_browser_ssl::TrialVerificationInfo:: + VERIFY_REV_CHECKING_REQUIRED_LOCAL_ANCHORS); + } + if (config.enable_sha1_local_anchors) { + report_flags->Add(chrome_browser_ssl::TrialVerificationInfo:: + VERIFY_ENABLE_SHA1_LOCAL_ANCHORS); + } + if (config.disable_symantec_enforcement) { + report_flags->Add(chrome_browser_ssl::TrialVerificationInfo:: + VERIFY_DISABLE_SYMANTEC_ENFORCEMENT); + } } bool CertificateChainToString(const net::X509Certificate& cert, @@ -117,7 +123,7 @@ CertificateErrorReport::CertificateErrorReport( const std::string& hostname, const net::X509Certificate& unverified_cert, - int verify_flags, + const net::CertVerifier::Config& verifier_config, const net::CertVerifyResult& primary_result, const net::CertVerifyResult& trial_result) : CertificateErrorReport(hostname, @@ -139,7 +145,7 @@ trial_report->mutable_cert_error()); AddCertStatusToReportStatus(trial_result.cert_status, trial_report->mutable_cert_status()); - AddVerifyFlagsToReport(verify_flags, trial_report->mutable_verify_flags()); + AddVerifyFlagsToReport(verifier_config, trial_report->mutable_verify_flags()); } CertificateErrorReport::~CertificateErrorReport() {}
diff --git a/chrome/browser/ssl/certificate_error_report.h b/chrome/browser/ssl/certificate_error_report.h index e163e839..ab66e3a 100644 --- a/chrome/browser/ssl/certificate_error_report.h +++ b/chrome/browser/ssl/certificate_error_report.h
@@ -11,6 +11,7 @@ #include "chrome/browser/ssl/cert_logger.pb.h" #include "components/version_info/version_info.h" #include "net/cert/cert_status_flags.h" +#include "net/cert/cert_verifier.h" namespace base { class Time; @@ -62,7 +63,7 @@ // TODO(mattm): remove this when the trial is done. (https://crbug.com/649026) CertificateErrorReport(const std::string& hostname, const net::X509Certificate& unverified_cert, - int verify_flags, + const net::CertVerifier::Config& config, const net::CertVerifyResult& primary_result, const net::CertVerifyResult& trial_result);
diff --git a/chrome/browser/ssl/common_name_mismatch_handler.cc b/chrome/browser/ssl/common_name_mismatch_handler.cc index b873a1a2..2b7bbee 100644 --- a/chrome/browser/ssl/common_name_mismatch_handler.cc +++ b/chrome/browser/ssl/common_name_mismatch_handler.cc
@@ -75,7 +75,7 @@ })"); auto resource_request = std::make_unique<network::ResourceRequest>(); - // Can't safely use net::LOAD_DISABLE_CERT_REVOCATION_CHECKING here, + // Can't safely use net::LOAD_DISABLE_CERT_NETWORK_FETCHES here, // since then the connection may be reused without checking the cert. resource_request->url = check_url_; resource_request->method = "HEAD";
diff --git a/chrome/browser/ssl/ssl_config_service_manager_pref.cc b/chrome/browser/ssl/ssl_config_service_manager_pref.cc index f95bd9dd..bf28ee9 100644 --- a/chrome/browser/ssl/ssl_config_service_manager_pref.cc +++ b/chrome/browser/ssl/ssl_config_service_manager_pref.cc
@@ -24,6 +24,7 @@ #include "components/prefs/pref_registry_simple.h" #include "components/prefs/pref_service.h" #include "mojo/public/cpp/bindings/interface_ptr_set.h" +#include "net/cert/cert_verifier.h" #include "net/ssl/ssl_cipher_suite_names.h" #include "net/ssl/ssl_config_service.h" #include "url/url_canon.h" @@ -228,14 +229,18 @@ // static void SSLConfigServiceManagerPref::RegisterPrefs(PrefRegistrySimple* registry) { net::SSLConfig default_config; + net::CertVerifier::Config default_verifier_config; registry->RegisterBooleanPref(prefs::kCertRevocationCheckingEnabled, - default_config.rev_checking_enabled); + default_verifier_config.enable_rev_checking); registry->RegisterBooleanPref( prefs::kCertRevocationCheckingRequiredLocalAnchors, - default_config.rev_checking_required_local_anchors); - registry->RegisterBooleanPref(prefs::kCertEnableSha1LocalAnchors, false); - registry->RegisterBooleanPref(prefs::kCertEnableSymantecLegacyInfrastructure, - default_config.symantec_enforcement_disabled); + default_verifier_config.require_rev_checking_local_anchors); + registry->RegisterBooleanPref( + prefs::kCertEnableSha1LocalAnchors, + default_verifier_config.enable_sha1_local_anchors); + registry->RegisterBooleanPref( + prefs::kCertEnableSymantecLegacyInfrastructure, + default_verifier_config.disable_symantec_enforcement); registry->RegisterStringPref(prefs::kSSLVersionMin, std::string()); registry->RegisterStringPref(prefs::kSSLVersionMax, std::string()); registry->RegisterStringPref(prefs::kTLS13Variant, std::string());
diff --git a/chrome/browser/ssl/ssl_config_service_manager_pref_unittest.cc b/chrome/browser/ssl/ssl_config_service_manager_pref_unittest.cc index 74cadbc2..bbba430 100644 --- a/chrome/browser/ssl/ssl_config_service_manager_pref_unittest.cc +++ b/chrome/browser/ssl/ssl_config_service_manager_pref_unittest.cc
@@ -16,6 +16,7 @@ #include "components/prefs/testing_pref_service.h" #include "components/variations/variations_params_manager.h" #include "mojo/public/cpp/bindings/binding.h" +#include "net/cert/cert_verifier.h" #include "net/ssl/ssl_config.h" #include "services/network/public/mojom/network_service.mojom.h" #include "services/network/public/mojom/ssl_config.mojom.h" @@ -364,7 +365,7 @@ // By default, SHA-1 local trust anchors should not be enabled when not // not using any pref service. - EXPECT_FALSE(net::SSLConfig().sha1_local_anchors_enabled); + EXPECT_FALSE(net::CertVerifier::Config().enable_sha1_local_anchors); EXPECT_FALSE(network::mojom::SSLConfig::New()->sha1_local_anchors_enabled); // Using a pref service without any preference set should result in @@ -402,7 +403,7 @@ // By default, Symantec's legacy infrastructure should be disabled when // not using any pref service. - EXPECT_FALSE(net::SSLConfig().symantec_enforcement_disabled); + EXPECT_FALSE(net::CertVerifier::Config().disable_symantec_enforcement); EXPECT_FALSE(network::mojom::SSLConfig::New()->symantec_enforcement_disabled); // Using a pref service without any preference set should result in
diff --git a/chrome/browser/ui/BUILD.gn b/chrome/browser/ui/BUILD.gn index f676ec9..801a20b 100644 --- a/chrome/browser/ui/BUILD.gn +++ b/chrome/browser/ui/BUILD.gn
@@ -1920,8 +1920,6 @@ "webui/chromeos/assistant_optin/assistant_optin_screen_exit_code.h", "webui/chromeos/assistant_optin/assistant_optin_ui.cc", "webui/chromeos/assistant_optin/assistant_optin_ui.h", - "webui/chromeos/assistant_optin/confirm_reject_screen_handler.cc", - "webui/chromeos/assistant_optin/confirm_reject_screen_handler.h", "webui/chromeos/assistant_optin/get_more_screen_handler.cc", "webui/chromeos/assistant_optin/get_more_screen_handler.h", "webui/chromeos/assistant_optin/ready_screen_handler.cc", @@ -2323,10 +2321,11 @@ sources += [ "input_method/input_method_engine.cc", "input_method/input_method_engine.h", - "views/confirm_quit_bubble.cc", - "views/confirm_quit_bubble.h", - "views/confirm_quit_bubble_controller.cc", - "views/confirm_quit_bubble_controller.h", + "views/quit_instruction_bubble.cc", + "views/quit_instruction_bubble.h", + "views/quit_instruction_bubble_base.h", + "views/quit_instruction_bubble_controller.cc", + "views/quit_instruction_bubble_controller.h", ] } }
diff --git a/chrome/browser/ui/ash/chrome_browser_main_extra_parts_ash.cc b/chrome/browser/ui/ash/chrome_browser_main_extra_parts_ash.cc index fd8a99ae..19863de 100644 --- a/chrome/browser/ui/ash/chrome_browser_main_extra_parts_ash.cc +++ b/chrome/browser/ui/ash/chrome_browser_main_extra_parts_ash.cc
@@ -17,6 +17,7 @@ #include "chrome/browser/browser_process.h" #include "chrome/browser/chrome_notification_types.h" #include "chrome/browser/chromeos/night_light/night_light_client.h" +#include "chrome/browser/chromeos/policy/display_rotation_default_handler.h" #include "chrome/browser/chromeos/profiles/profile_helper.h" #include "chrome/browser/profiles/profile.h" #include "chrome/browser/signin/signin_error_notifier_factory_ash.h" @@ -242,6 +243,11 @@ login_screen_client_ = std::make_unique<LoginScreenClient>(); media_client_ = std::make_unique<MediaClient>(); + // Instantiate DisplayRotationDefaultHandler after CrosSettings has been + // initialized. + display_rotation_handler_ = + std::make_unique<policy::DisplayRotationDefaultHandler>(); + // Do not create a NetworkPortalNotificationController for tests since the // NetworkPortalDetector instance may be replaced. if (!base::CommandLine::ForCurrentProcess()->HasSwitch( @@ -286,20 +292,22 @@ vpn_list_forwarder_.reset(); volume_controller_.reset(); - system_tray_client_.reset(); - session_controller_client_.reset(); - chrome_new_window_client_.reset(); + // Initialized in PostProfileInit: network_portal_notification_controller_.reset(); + display_rotation_handler_.reset(); media_client_.reset(); login_screen_client_.reset(); - ime_controller_client_.reset(); cast_config_client_media_router_.reset(); - accessibility_controller_client_.reset(); + // Initialized in PreProfileInit: + system_tray_client_.reset(); + session_controller_client_.reset(); + ime_controller_client_.reset(); + chrome_new_window_client_.reset(); + accessibility_controller_client_.reset(); // AppListClientImpl indirectly holds WebContents for answer card and // needs to be released before destroying the profile. app_list_client_.reset(); - ash_shell_init_.reset(); chromeos::NetworkConnect::Shutdown();
diff --git a/chrome/browser/ui/ash/chrome_browser_main_extra_parts_ash.h b/chrome/browser/ui/ash/chrome_browser_main_extra_parts_ash.h index ace18e9cd..eb24d1a 100644 --- a/chrome/browser/ui/ash/chrome_browser_main_extra_parts_ash.h +++ b/chrome/browser/ui/ash/chrome_browser_main_extra_parts_ash.h
@@ -19,6 +19,10 @@ class NetworkPortalNotificationController; } +namespace policy { +class DisplayRotationDefaultHandler; +} + namespace ui { class UserActivityDetector; } @@ -115,6 +119,8 @@ std::unique_ptr<CastConfigClientMediaRouter> cast_config_client_media_router_; std::unique_ptr<LoginScreenClient> login_screen_client_; std::unique_ptr<MediaClient> media_client_; + std::unique_ptr<policy::DisplayRotationDefaultHandler> + display_rotation_handler_; // Initialized in PostBrowserStart in all configs: std::unique_ptr<DataPromoNotification> data_promo_notification_;
diff --git a/chrome/browser/ui/ash/chrome_shell_delegate.cc b/chrome/browser/ui/ash/chrome_shell_delegate.cc index 1a23157e..2001291 100644 --- a/chrome/browser/ui/ash/chrome_shell_delegate.cc +++ b/chrome/browser/ui/ash/chrome_shell_delegate.cc
@@ -16,7 +16,6 @@ #include "chrome/browser/browser_process_platform_part_chromeos.h" #include "chrome/browser/chromeos/accessibility/accessibility_manager.h" #include "chrome/browser/chromeos/accessibility/magnification_manager.h" -#include "chrome/browser/chromeos/policy/display_rotation_default_handler.h" #include "chrome/browser/profiles/profile.h" #include "chrome/browser/profiles/profile_manager.h" #include "chrome/browser/ui/ash/chrome_keyboard_ui.h" @@ -93,18 +92,6 @@ base::BindRepeating(&GetActiveBrowserContext)); } -void ChromeShellDelegate::PreInit() { - // TODO: port to multi-process mash. http://crbug.com/705713. - if (!features::IsAshInBrowserProcess()) - return; - - // Object owns itself and deletes itself in OnWindowTreeHostManagerShutdown(). - // Setup is done in OnShellInitialized() so this needs to be constructed after - // Shell is constructed but before OnShellInitialized() is called. Depends on - // CroSettings. TODO(stevenjb): Move to src/ash. - new policy::DisplayRotationDefaultHandler(); -} - void ChromeShellDelegate::OpenKeyboardShortcutHelpPage() const { chrome::ScopedTabbedBrowserDisplayer scoped_tabbed_browser_displayer( ProfileManager::GetActiveUserProfile());
diff --git a/chrome/browser/ui/ash/chrome_shell_delegate.h b/chrome/browser/ui/ash/chrome_shell_delegate.h index 6532405..f89856d 100644 --- a/chrome/browser/ui/ash/chrome_shell_delegate.h +++ b/chrome/browser/ui/ash/chrome_shell_delegate.h
@@ -23,7 +23,6 @@ // ash::ShellDelegate overrides; bool CanShowWindowForUser(aura::Window* window) const override; - void PreInit() override; std::unique_ptr<keyboard::KeyboardUI> CreateKeyboardUI() override; std::unique_ptr<ash::ScreenshotDelegate> CreateScreenshotDelegate() override; ash::AccessibilityDelegate* CreateAccessibilityDelegate() override;
diff --git a/chrome/browser/ui/autofill/chrome_autofill_client.cc b/chrome/browser/ui/autofill/chrome_autofill_client.cc index 1a4f12d8..c105be57 100644 --- a/chrome/browser/ui/autofill/chrome_autofill_client.cc +++ b/chrome/browser/ui/autofill/chrome_autofill_client.cc
@@ -25,6 +25,8 @@ #include "chrome/browser/ui/autofill/autofill_popup_controller_impl.h" #include "chrome/browser/ui/autofill/create_card_unmask_prompt_view.h" #include "chrome/browser/ui/autofill/credit_card_scanner_controller.h" +#include "chrome/browser/ui/autofill/local_card_migration_dialog_factory.h" +#include "chrome/browser/ui/autofill/local_card_migration_dialog_state.h" #include "chrome/browser/ui/browser_finder.h" #include "chrome/browser/ui/chrome_pages.h" #include "chrome/browser/ui/page_info/page_info_dialog.h" @@ -67,6 +69,7 @@ #include "ui/android/window_android.h" #else // !OS_ANDROID #include "chrome/browser/ui/autofill/local_card_migration_bubble_controller_impl.h" +#include "chrome/browser/ui/autofill/local_card_migration_dialog_controller_impl.h" #include "chrome/browser/ui/autofill/save_card_bubble_controller_impl.h" #include "chrome/browser/ui/browser.h" #include "chrome/browser/ui/browser_commands.h" @@ -195,15 +198,32 @@ unmask_controller_.OnVerificationResult(result); } -void ChromeAutofillClient::ShowLocalCardMigrationPrompt( - base::OnceClosure closure) { +void ChromeAutofillClient::ShowLocalCardMigrationDialog( + base::OnceClosure show_migration_dialog_closure) { #if !defined(OS_ANDROID) autofill::LocalCardMigrationBubbleControllerImpl::CreateForWebContents( web_contents()); autofill::LocalCardMigrationBubbleControllerImpl* controller = autofill::LocalCardMigrationBubbleControllerImpl::FromWebContents( web_contents()); - controller->ShowBubble(std::move(closure)); + controller->ShowBubble(std::move(show_migration_dialog_closure)); +#endif +} + +void ChromeAutofillClient::ConfirmMigrateLocalCardToCloud( + std::vector<MigratableCreditCard>& migratable_credit_cards, + base::OnceClosure start_migrating_cards_closure) { +#if !defined(OS_ANDROID) + autofill::LocalCardMigrationDialogControllerImpl::CreateForWebContents( + web_contents()); + autofill::LocalCardMigrationDialogControllerImpl* controller = + autofill::LocalCardMigrationDialogControllerImpl::FromWebContents( + web_contents()); + controller->SetViewState(LocalCardMigrationDialogState::kOffered); + controller->SetCardList(migratable_credit_cards); + controller->ShowDialog( + CreateLocalCardMigrationDialogView(controller, web_contents()), + std::move(start_migrating_cards_closure)); #endif }
diff --git a/chrome/browser/ui/autofill/chrome_autofill_client.h b/chrome/browser/ui/autofill/chrome_autofill_client.h index 57ceaaf8..72e61cb 100644 --- a/chrome/browser/ui/autofill/chrome_autofill_client.h +++ b/chrome/browser/ui/autofill/chrome_autofill_client.h
@@ -22,6 +22,7 @@ #if !defined(OS_ANDROID) #include "components/autofill/core/browser/ui/local_card_migration_bubble_controller.h" +#include "components/autofill/core/browser/ui/local_card_migration_dialog_controller.h" #include "components/autofill/core/browser/ui/save_card_bubble_controller.h" #include "components/zoom/zoom_observer.h" #endif // !defined(OS_ANDROID) @@ -62,7 +63,11 @@ UnmaskCardReason reason, base::WeakPtr<CardUnmaskDelegate> delegate) override; void OnUnmaskVerificationResult(PaymentsRpcResult result) override; - void ShowLocalCardMigrationPrompt(base::OnceClosure closure) override; + void ShowLocalCardMigrationDialog( + base::OnceClosure show_migration_dialog_closure) override; + void ConfirmMigrateLocalCardToCloud( + std::vector<MigratableCreditCard>& migratable_credit_cards, + base::OnceClosure start_migrating_cards_closure) override; void ConfirmSaveAutofillProfile(const AutofillProfile& profile, base::OnceClosure callback) override; void ConfirmSaveCreditCardLocally(const CreditCard& card,
diff --git a/chrome/browser/ui/autofill/local_card_migration_dialog_controller_impl.cc b/chrome/browser/ui/autofill/local_card_migration_dialog_controller_impl.cc index c229f99..637dd9e 100644 --- a/chrome/browser/ui/autofill/local_card_migration_dialog_controller_impl.cc +++ b/chrome/browser/ui/autofill/local_card_migration_dialog_controller_impl.cc
@@ -25,7 +25,8 @@ namespace autofill { -LocalCardMigrationDialogControllerImpl::LocalCardMigrationDialogControllerImpl() +LocalCardMigrationDialogControllerImpl::LocalCardMigrationDialogControllerImpl( + content::WebContents* web_contents) : local_card_migration_dialog_(nullptr) {} LocalCardMigrationDialogControllerImpl::
diff --git a/chrome/browser/ui/autofill/local_card_migration_dialog_controller_impl.h b/chrome/browser/ui/autofill/local_card_migration_dialog_controller_impl.h index ebf49d78..9759cd28 100644 --- a/chrome/browser/ui/autofill/local_card_migration_dialog_controller_impl.h +++ b/chrome/browser/ui/autofill/local_card_migration_dialog_controller_impl.h
@@ -36,7 +36,8 @@ void OnDialogClosed() override; protected: - explicit LocalCardMigrationDialogControllerImpl(); + explicit LocalCardMigrationDialogControllerImpl( + content::WebContents* web_contents); private: friend class content::WebContentsUserData<
diff --git a/chrome/browser/ui/browser_command_controller.cc b/chrome/browser/ui/browser_command_controller.cc index af26865..3d17b26 100644 --- a/chrome/browser/ui/browser_command_controller.cc +++ b/chrome/browser/ui/browser_command_controller.cc
@@ -691,11 +691,6 @@ ShowPageInfoDialog(browser_->tab_strip_model()->GetActiveWebContents(), bubble_anchor_util::kAppMenuButton); break; -#if defined(OS_WIN) || (defined(OS_LINUX) && !defined(OS_CHROMEOS)) - case IDC_TOGGLE_CONFIRM_TO_QUIT_OPTION: - ToggleConfirmToQuitOption(browser_); - break; -#endif default: LOG(WARNING) << "Received Unimplemented Command: " << id; @@ -890,8 +885,6 @@ !profile()->IsOffTheRecord()); command_updater_.UpdateCommandEnabled(IDC_CLEAR_BROWSING_DATA, !guest_session); - command_updater_.UpdateCommandEnabled(IDC_TOGGLE_CONFIRM_TO_QUIT_OPTION, - true); #if defined(OS_CHROMEOS) command_updater_.UpdateCommandEnabled(IDC_TAKE_SCREENSHOT, true); #else
diff --git a/chrome/browser/ui/cocoa/touchbar/text_suggestions_touch_bar_controller.mm b/chrome/browser/ui/cocoa/touchbar/text_suggestions_touch_bar_controller.mm index 462416c..471a2da1 100644 --- a/chrome/browser/ui/cocoa/touchbar/text_suggestions_touch_bar_controller.mm +++ b/chrome/browser/ui/cocoa/touchbar/text_suggestions_touch_bar_controller.mm
@@ -134,14 +134,14 @@ [[NSCandidateListTouchBarItem alloc] initWithIdentifier:kTextSuggestionsItemsTouchId]; - [candidateListItem setCandidates:suggestions_ - forSelectedRange:selectionRange_ - inString:text_]; - candidateListItem.delegate = self; if (selectionRange_.length) candidateListItem.collapsed = YES; + [candidateListItem setCandidates:suggestions_ + forSelectedRange:selectionRange_ + inString:text_]; + return candidateListItem; } @@ -173,6 +173,11 @@ return; } + if (!range.IsValid()) { + [self updateTextSelection:base::string16() range:gfx::Range() offset:0]; + return; + } + text_.reset([base::SysUTF16ToNSString(text) retain]); selectionRange_ = NSMakeRange(range.start() - offset, range.end() - range.start()); @@ -234,8 +239,10 @@ completionHandler:^( NSInteger sequenceNumber, NSArray<NSTextCheckingResult*>* candidates) { - suggestions_.reset([candidates copy]); - [controller_ invalidateTouchBar]; + dispatch_async(dispatch_get_main_queue(), ^{ + suggestions_.reset([candidates copy]); + [controller_ invalidateTouchBar]; + }); }]; } @@ -268,10 +275,8 @@ webContents_->GetTopLevelRenderWidgetHostView()->GetSelectedRange(); const size_t offset = webContents_->GetTopLevelRenderWidgetHostView() ->GetOffsetForSurroundingText(); - if (range.IsValid()) - [self updateTextSelection:text range:range offset:offset]; - else - [self updateTextSelection:base::string16() range:gfx::Range() offset:0]; + + [self updateTextSelection:text range:range offset:offset]; } - (content::WebContents*)webContents {
diff --git a/chrome/browser/ui/cocoa/touchbar/text_suggestions_touch_bar_controller_browsertest.mm b/chrome/browser/ui/cocoa/touchbar/text_suggestions_touch_bar_controller_browsertest.mm index a98b8b0..2fee623 100644 --- a/chrome/browser/ui/cocoa/touchbar/text_suggestions_touch_bar_controller_browsertest.mm +++ b/chrome/browser/ui/cocoa/touchbar/text_suggestions_touch_bar_controller_browsertest.mm
@@ -191,6 +191,17 @@ } } +// Tests that an invalid range does not crash the controller. +IN_PROC_BROWSER_TEST_F(TextSuggestionsTouchBarControllerTest, InvalidRange) { + FocusTextfield(); + [touch_bar_controller_ + updateTextSelection:base::string16(base::ASCIIToUTF16("text")) + range:gfx::Range::InvalidRange() + offset:0]; + EXPECT_STREQ("", [touch_bar_controller_ text].UTF8String); + EXPECT_EQ(gfx::Range(), [touch_bar_controller_ selectionRange]); +} + // Tests that a change in WebContents is handled properly. IN_PROC_BROWSER_TEST_F(TextSuggestionsTouchBarControllerTest, SetWebContents) { NSString* const kText = @"text";
diff --git a/chrome/browser/ui/cocoa/touchbar/text_suggestions_touch_bar_controller_unittest.mm b/chrome/browser/ui/cocoa/touchbar/text_suggestions_touch_bar_controller_unittest.mm index 4b8448b..7bc5975 100644 --- a/chrome/browser/ui/cocoa/touchbar/text_suggestions_touch_bar_controller_unittest.mm +++ b/chrome/browser/ui/cocoa/touchbar/text_suggestions_touch_bar_controller_unittest.mm
@@ -35,6 +35,7 @@ base::scoped_nsobject<TextSuggestionsTouchBarController> controller_; }; +// Tests that the NSCandidateListTouchBarItem collapses properly. TEST_F(TextSuggestionsTouchBarControllerTest, CollapsedCandidateList) { if (@available(macOS 10.12.2, *)) { base::scoped_nsobject<NSCandidateListTouchBarItem> item; @@ -133,6 +134,7 @@ EXPECT_EQ(gfx::Range(6, 11), GetEditingWordRange(kMultipleWords, 11)); } +// Tests that touch bar usage is properly logged. TEST_F(TextSuggestionsTouchBarControllerTest, TouchBarMetrics) { if (@available(macOS 10.12.2, *)) { base::HistogramTester histogram_tester;
diff --git a/chrome/browser/ui/javascript_dialogs/javascript_dialog_browsertest.cc b/chrome/browser/ui/javascript_dialogs/javascript_dialog_browsertest.cc index 20b7743..5131deb 100644 --- a/chrome/browser/ui/javascript_dialogs/javascript_dialog_browsertest.cc +++ b/chrome/browser/ui/javascript_dialogs/javascript_dialog_browsertest.cc
@@ -4,8 +4,11 @@ #include "base/logging.h" #include "base/strings/utf_string_conversions.h" +#include "base/test/metrics/histogram_tester.h" #include "base/test/scoped_command_line.h" +#include "build/build_config.h" #include "chrome/browser/ui/browser.h" +#include "chrome/browser/ui/browser_commands.h" #include "chrome/browser/ui/javascript_dialogs/javascript_dialog_tab_helper.h" #include "chrome/browser/ui/tabs/tab_strip_model.h" #include "chrome/common/chrome_switches.h" @@ -15,7 +18,12 @@ #include "content/public/test/browser_test_utils.h" #include "content/public/test/test_utils.h" -using JavaScriptDialogTest = InProcessBrowserTest; +using DismissalCause = JavaScriptDialogTabHelper::DismissalCause; + +class JavaScriptDialogTest : public InProcessBrowserTest { + private: + friend class JavaScriptDialogDismissalCauseTester; +}; IN_PROC_BROWSER_TEST_F(JavaScriptDialogTest, ReloadDoesntHang) { content::WebContents* tab = @@ -191,3 +199,144 @@ ASSERT_TRUE(callback_helper.last_success()); ASSERT_EQ(value1, callback_helper.last_input()); } + +class JavaScriptDialogDismissalCauseTester { + public: + explicit JavaScriptDialogDismissalCauseTester(JavaScriptDialogTest* test) + : tab_(test->browser()->tab_strip_model()->GetActiveWebContents()), + frame_(tab_->GetMainFrame()), + js_helper_(JavaScriptDialogTabHelper::FromWebContents(tab_)) {} + + void PopupDialog(content::JavaScriptDialogType type) { + bool did_suppress = false; + js_helper_->RunJavaScriptDialog( + tab_, frame_, type, base::ASCIIToUTF16("Label"), + base::ASCIIToUTF16("abc"), {}, &did_suppress); + } + + void ClickDialogButton(bool accept, const base::string16& user_input) { + EXPECT_TRUE(js_helper_->IsShowingDialogForTesting()); + js_helper_->ClickDialogButtonForTesting(accept, user_input); + } + + void Reload() { + tab_->GetController().Reload(content::ReloadType::NORMAL, false); + content::WaitForLoadStop(tab_); + } + + void CallHandleDialog(bool accept, const base::string16* prompt_override) { + EXPECT_TRUE(js_helper_->IsShowingDialogForTesting()); + js_helper_->HandleJavaScriptDialog(tab_, accept, prompt_override); + } + + void CallCancelDialogs(bool reset_state) { + EXPECT_TRUE(js_helper_->IsShowingDialogForTesting()); + js_helper_->CancelDialogs(tab_, reset_state); + } + + private: + content::WebContents* tab_; + content::RenderFrameHost* frame_; + JavaScriptDialogTabHelper* js_helper_; +}; + +IN_PROC_BROWSER_TEST_F(JavaScriptDialogTest, DismissalCausePromptAcceptButton) { + base::HistogramTester histogram_tester; + JavaScriptDialogDismissalCauseTester tester(this); + tester.PopupDialog(content::JAVASCRIPT_DIALOG_TYPE_PROMPT); + tester.ClickDialogButton(true, base::string16()); + histogram_tester.ExpectUniqueSample("JSDialogs.DismissalCause.Prompt", + DismissalCause::kDialogButtonClicked, 1); +} + +IN_PROC_BROWSER_TEST_F(JavaScriptDialogTest, DismissalCausePromptCancelButton) { + base::HistogramTester histogram_tester; + JavaScriptDialogDismissalCauseTester tester(this); + tester.PopupDialog(content::JAVASCRIPT_DIALOG_TYPE_PROMPT); + tester.ClickDialogButton(false, base::string16()); + histogram_tester.ExpectUniqueSample("JSDialogs.DismissalCause.Prompt", + DismissalCause::kDialogButtonClicked, 1); +} + +IN_PROC_BROWSER_TEST_F(JavaScriptDialogTest, DismissalCausePromptHandleDialog) { + base::HistogramTester histogram_tester; + JavaScriptDialogDismissalCauseTester tester(this); + tester.PopupDialog(content::JAVASCRIPT_DIALOG_TYPE_PROMPT); + tester.CallHandleDialog(true, nullptr); + histogram_tester.ExpectUniqueSample("JSDialogs.DismissalCause.Prompt", + DismissalCause::kHandleDialogCalled, 1); +} + +IN_PROC_BROWSER_TEST_F(JavaScriptDialogTest, + DismissalCausePromptCancelDialogs) { + base::HistogramTester histogram_tester; + JavaScriptDialogDismissalCauseTester tester(this); + tester.PopupDialog(content::JAVASCRIPT_DIALOG_TYPE_PROMPT); + tester.CallCancelDialogs(false); + histogram_tester.ExpectUniqueSample("JSDialogs.DismissalCause.Prompt", + DismissalCause::kCancelDialogsCalled, 1); +} + +IN_PROC_BROWSER_TEST_F(JavaScriptDialogTest, + DismissalCausePromptTabClosedByUser) { + base::HistogramTester histogram_tester; + JavaScriptDialogDismissalCauseTester tester(this); + tester.PopupDialog(content::JAVASCRIPT_DIALOG_TYPE_PROMPT); + chrome::CloseTab(browser()); +// There are differences in the implementations of Views on different platforms +// that cause different dismissal causes. +#if defined(OS_MACOSX) + histogram_tester.ExpectUniqueSample("JSDialogs.DismissalCause.Prompt", + DismissalCause::kCancelDialogsCalled, 1); +#else + histogram_tester.ExpectUniqueSample("JSDialogs.DismissalCause.Prompt", + DismissalCause::kDialogClosed, 1); +#endif +} + +IN_PROC_BROWSER_TEST_F(JavaScriptDialogTest, DismissalCausePromptTabHidden) { + base::HistogramTester histogram_tester; + JavaScriptDialogDismissalCauseTester tester(this); + tester.PopupDialog(content::JAVASCRIPT_DIALOG_TYPE_PROMPT); + chrome::NewTab(browser()); + histogram_tester.ExpectUniqueSample("JSDialogs.DismissalCause.Prompt", + DismissalCause::kTabHidden, 1); +} + +IN_PROC_BROWSER_TEST_F(JavaScriptDialogTest, + DismissalCausePromptBrowserSwitched) { + base::HistogramTester histogram_tester; + JavaScriptDialogDismissalCauseTester tester(this); + tester.PopupDialog(content::JAVASCRIPT_DIALOG_TYPE_PROMPT); + chrome::NewEmptyWindow(browser()->profile()); + histogram_tester.ExpectUniqueSample("JSDialogs.DismissalCause.Prompt", + DismissalCause::kBrowserSwitched, 1); +} + +IN_PROC_BROWSER_TEST_F(JavaScriptDialogTest, DismissalCausePromptTabNavigated) { + base::HistogramTester histogram_tester; + JavaScriptDialogDismissalCauseTester tester(this); + tester.PopupDialog(content::JAVASCRIPT_DIALOG_TYPE_PROMPT); + tester.Reload(); + histogram_tester.ExpectUniqueSample("JSDialogs.DismissalCause.Prompt", + DismissalCause::kTabNavigated, 1); +} + +IN_PROC_BROWSER_TEST_F(JavaScriptDialogTest, + DismissalCausePromptSubsequentDialogShown) { + base::HistogramTester histogram_tester; + JavaScriptDialogDismissalCauseTester tester(this); + tester.PopupDialog(content::JAVASCRIPT_DIALOG_TYPE_PROMPT); + tester.PopupDialog(content::JAVASCRIPT_DIALOG_TYPE_ALERT); + histogram_tester.ExpectUniqueSample("JSDialogs.DismissalCause.Prompt", + DismissalCause::kSubsequentDialogShown, + 1); +} + +IN_PROC_BROWSER_TEST_F(JavaScriptDialogTest, NoDismissalAlertTabHidden) { + base::HistogramTester histogram_tester; + JavaScriptDialogDismissalCauseTester tester(this); + tester.PopupDialog(content::JAVASCRIPT_DIALOG_TYPE_ALERT); + chrome::NewTab(browser()); + histogram_tester.ExpectTotalCount("JSDialogs.DismissalCause.Alert", 0); +}
diff --git a/chrome/browser/ui/javascript_dialogs/javascript_dialog_tab_helper.cc b/chrome/browser/ui/javascript_dialogs/javascript_dialog_tab_helper.cc index 5c82dca..2ac26510 100644 --- a/chrome/browser/ui/javascript_dialogs/javascript_dialog_tab_helper.cc +++ b/chrome/browser/ui/javascript_dialogs/javascript_dialog_tab_helper.cc
@@ -134,7 +134,8 @@ content::JavaScriptDialogType dialog_type, const base::string16& message_text, const base::string16& default_prompt_text, - content::JavaScriptDialogManager::DialogClosedCallback dialog_callback) { + content::JavaScriptDialogManager::DialogClosedCallback dialog_callback, + base::OnceClosure dialog_closed_callback) { #if defined(OS_ANDROID) return JavaScriptDialogAndroid::Create( parent_web_contents, alerting_web_contents, title, dialog_type, @@ -142,27 +143,13 @@ #else return JavaScriptDialogViews::Create( parent_web_contents, alerting_web_contents, title, dialog_type, - message_text, default_prompt_text, std::move(dialog_callback)); + message_text, default_prompt_text, std::move(dialog_callback), + std::move(dialog_closed_callback)); #endif } } // namespace -enum class JavaScriptDialogTabHelper::DismissalCause { - // This is used for a UMA histogram. Please never alter existing values, only - // append new ones. - TAB_HELPER_DESTROYED = 0, - SUBSEQUENT_DIALOG_SHOWN = 1, - HANDLE_DIALOG_CALLED = 2, - CANCEL_DIALOGS_CALLED = 3, - TAB_HIDDEN = 4, - BROWSER_SWITCHED = 5, - DIALOG_BUTTON_CLICKED = 6, - TAB_NAVIGATED = 7, - TAB_SWITCHED_OUT = 8, - COUNT, -}; - JavaScriptDialogTabHelper::JavaScriptDialogTabHelper( content::WebContents* web_contents) : content::WebContentsObserver(web_contents) { @@ -172,7 +159,7 @@ #if !defined(OS_ANDROID) DCHECK(!tab_strip_model_being_observed_); #endif - CloseDialog(DismissalCause::TAB_HELPER_DESTROYED, false, base::string16()); + CloseDialog(DismissalCause::kTabHelperDestroyed, false, base::string16()); } void JavaScriptDialogTabHelper::SetDialogShownCallbackForTesting( @@ -184,6 +171,13 @@ return !!dialog_; } +void JavaScriptDialogTabHelper::ClickDialogButtonForTesting( + bool accept, + const base::string16& user_input) { + DCHECK(!!dialog_); + CloseDialog(DismissalCause::kDialogButtonClicked, accept, user_input); +} + void JavaScriptDialogTabHelper::RunJavaScriptDialog( content::WebContents* alerting_web_contents, content::RenderFrameHost* render_frame_host, @@ -232,7 +226,7 @@ } // Close any dialog already showing. - CloseDialog(DismissalCause::SUBSEQUENT_DIALOG_SHOWN, false, base::string16()); + CloseDialog(DismissalCause::kSubsequentDialogShown, false, base::string16()); bool make_pending = false; if (!IsWebContentsForemost(parent_web_contents) && @@ -300,7 +294,10 @@ dialog_type, truncated_message_text, truncated_default_prompt_text, base::BindOnce(&JavaScriptDialogTabHelper::CloseDialog, base::Unretained(this), - DismissalCause::DIALOG_BUTTON_CLICKED)); + DismissalCause::kDialogButtonClicked), + base::BindOnce(&JavaScriptDialogTabHelper::CloseDialog, + base::Unretained(this), DismissalCause::kDialogClosed, + false, base::string16())); } else { DCHECK(!pending_dialog_); dialog_ = CreateNewDialog( @@ -308,7 +305,10 @@ truncated_message_text, truncated_default_prompt_text, base::BindOnce(&JavaScriptDialogTabHelper::CloseDialog, base::Unretained(this), - DismissalCause::DIALOG_BUTTON_CLICKED)); + DismissalCause::kDialogButtonClicked), + base::BindOnce(&JavaScriptDialogTabHelper::CloseDialog, + base::Unretained(this), DismissalCause::kDialogClosed, + false, base::string16())); } #if !defined(OS_ANDROID) @@ -370,7 +370,7 @@ bool accept, const base::string16* prompt_override) { if (dialog_ || pending_dialog_) { - CloseDialog(DismissalCause::HANDLE_DIALOG_CALLED, accept, + CloseDialog(DismissalCause::kHandleDialogCalled, accept, prompt_override ? *prompt_override : dialog_->GetUserInput()); return true; } @@ -383,7 +383,7 @@ void JavaScriptDialogTabHelper::CancelDialogs( content::WebContents* web_contents, bool reset_state) { - CloseDialog(DismissalCause::CANCEL_DIALOGS_CALLED, false, base::string16()); + CloseDialog(DismissalCause::kCancelDialogsCalled, false, base::string16()); // Cancel any app-modal dialogs being run by the app-modal dialog system. return AppModalDialogManager()->CancelDialogs(web_contents, reset_state); @@ -392,7 +392,7 @@ void JavaScriptDialogTabHelper::OnVisibilityChanged( content::Visibility visibility) { if (visibility == content::Visibility::HIDDEN) { - HandleTabSwitchAway(DismissalCause::TAB_HIDDEN); + HandleTabSwitchAway(DismissalCause::kTabHidden); } else if (pending_dialog_) { dialog_ = std::move(pending_dialog_).Run(); pending_dialog_.Reset(); @@ -408,7 +408,7 @@ content::NavigationHandle* navigation_handle) { // Close the dialog if the user started a new navigation. This allows reloads // and history navigations to proceed. - CloseDialog(DismissalCause::TAB_NAVIGATED, false, base::string16()); + CloseDialog(DismissalCause::kTabNavigated, false, base::string16()); } // This function handles the case where browser-side navigation (PlzNavigate) is @@ -420,7 +420,7 @@ content::ReloadType reload_type) { // Close the dialog if the user started a new navigation. This allows reloads // and history navigations to proceed. - CloseDialog(DismissalCause::TAB_NAVIGATED, false, base::string16()); + CloseDialog(DismissalCause::kTabNavigated, false, base::string16()); } #if !defined(OS_ANDROID) @@ -428,7 +428,7 @@ if (IsWebContentsForemost(web_contents())) { OnVisibilityChanged(content::Visibility::VISIBLE); } else { - HandleTabSwitchAway(DismissalCause::BROWSER_SWITCHED); + HandleTabSwitchAway(DismissalCause::kBrowserSwitched); } } @@ -443,7 +443,7 @@ // must be done here. SetTabNeedsAttentionImpl(false, tab_strip_model, index); - CloseDialog(DismissalCause::TAB_SWITCHED_OUT, false, base::string16()); + CloseDialog(DismissalCause::kTabSwitchedOut, false, base::string16()); } } @@ -461,29 +461,23 @@ DCHECK(tab_strip_model_being_observed_); tab_strip_model_being_observed_->RemoveObserver(this); tab_strip_model_being_observed_ = nullptr; - CloseDialog(DismissalCause::TAB_HELPER_DESTROYED, false, base::string16()); + CloseDialog(DismissalCause::kTabHelperDestroyed, false, base::string16()); } } #endif -void JavaScriptDialogTabHelper::LogDialogDismissalCause( - JavaScriptDialogTabHelper::DismissalCause cause) { +void JavaScriptDialogTabHelper::LogDialogDismissalCause(DismissalCause cause) { + // Log to UMA switch (dialog_type_) { case content::JAVASCRIPT_DIALOG_TYPE_ALERT: - UMA_HISTOGRAM_ENUMERATION("JSDialogs.DismissalCause.Alert", - static_cast<int>(cause), - static_cast<int>(DismissalCause::COUNT)); + UMA_HISTOGRAM_ENUMERATION("JSDialogs.DismissalCause.Alert", cause); break; case content::JAVASCRIPT_DIALOG_TYPE_CONFIRM: - UMA_HISTOGRAM_ENUMERATION("JSDialogs.DismissalCause.Confirm", - static_cast<int>(cause), - static_cast<int>(DismissalCause::COUNT)); + UMA_HISTOGRAM_ENUMERATION("JSDialogs.DismissalCause.Confirm", cause); break; case content::JAVASCRIPT_DIALOG_TYPE_PROMPT: - UMA_HISTOGRAM_ENUMERATION("JSDialogs.DismissalCause.Prompt", - static_cast<int>(cause), - static_cast<int>(DismissalCause::COUNT)); + UMA_HISTOGRAM_ENUMERATION("JSDialogs.DismissalCause.Prompt", cause); break; } } @@ -522,7 +516,8 @@ // // Using the |cause| to distinguish a call from JavaScriptDialog vs from // within JavaScriptDialogTabHelper is a bit hacky, but is the simplest way. - if (dialog_ && cause != DismissalCause::DIALOG_BUTTON_CLICKED) + if (dialog_ && cause != DismissalCause::kDialogButtonClicked && + cause != DismissalCause::kDialogClosed) dialog_->CloseDialogWithoutCallback(); // If there is a callback, call it. There might not be one, if a tab-modal @@ -534,8 +529,8 @@ // state; clear it out. However, if the tab was switched out, the turning off // of the "needs attention" state was done in TabReplacedAt() or // TabDetachedAt() because SetTabNeedsAttention won't work, so don't call it. - if (pending_dialog_ && cause != DismissalCause::TAB_SWITCHED_OUT && - cause != DismissalCause::TAB_HELPER_DESTROYED) { + if (pending_dialog_ && cause != DismissalCause::kTabSwitchedOut && + cause != DismissalCause::kTabHelperDestroyed) { SetTabNeedsAttention(false); }
diff --git a/chrome/browser/ui/javascript_dialogs/javascript_dialog_tab_helper.h b/chrome/browser/ui/javascript_dialogs/javascript_dialog_tab_helper.h index 580c5850..7a293dcd 100644 --- a/chrome/browser/ui/javascript_dialogs/javascript_dialog_tab_helper.h +++ b/chrome/browser/ui/javascript_dialogs/javascript_dialog_tab_helper.h
@@ -48,11 +48,61 @@ #endif public content::WebContentsUserData<JavaScriptDialogTabHelper> { public: + enum class DismissalCause { + // This is used for a UMA histogram. Please never alter existing values, + // only append new ones. + + // The tab helper is destroyed. By current design, the dialog is always torn + // down before the tab helper is destroyed, so we never see the + // |kTabHelperDestroyed| enum. However, that might not always be the case. + // It's better to have a simple rule in the code of "when you close a dialog + // you must provide a UMA enum reason why" and have some enums that never + // happen than have haphazard code that enforces no rules. + kTabHelperDestroyed = 0, + + // Subsequent dialog pops up. + kSubsequentDialogShown = 1, + + // HandleJavaScriptDialog() is called. In practice, this can happen whenever + // browser choose to accept/cancel the dialog without user's interaction. + kHandleDialogCalled = 2, + + // CancelDialogs() is called. In practice, this can happen whenever browser + // choose to close the dialog without user's interaction. Besides, this can + // also happen when tab is closed by user on a Mac platform. + kCancelDialogsCalled = 3, + + // Tab is made hidden by opening a new tab, switching to another tab, etc. + // Note that only Prompt() and Confirm() can be dismissed for this cause; + // it won't affect Alert(). + kTabHidden = 4, + + // Another browser instance is made active. + kBrowserSwitched = 5, + + // Accept/Cancel button is clicked by user. + kDialogButtonClicked = 6, + + // Navigation occurs. + kTabNavigated = 7, + + // TabReplacedAt() is called. + kTabSwitchedOut = 8, + + // CloseDialog() is called. In practice, this happens when tab is closed by + // user on a non-Mac platform. + kDialogClosed = 9, + + kMaxValue = kDialogClosed, + }; + explicit JavaScriptDialogTabHelper(content::WebContents* web_contents); ~JavaScriptDialogTabHelper() override; void SetDialogShownCallbackForTesting(base::OnceClosure callback); bool IsShowingDialogForTesting() const; + void ClickDialogButtonForTesting(bool accept, + const base::string16& user_input); // JavaScriptDialogManager: void RunJavaScriptDialog(content::WebContents* web_contents, @@ -96,7 +146,6 @@ private: friend class content::WebContentsUserData<JavaScriptDialogTabHelper>; - enum class DismissalCause; // Logs the cause of a dialog dismissal in UMA. void LogDialogDismissalCause(DismissalCause cause);
diff --git a/chrome/browser/ui/javascript_dialogs/javascript_dialog_views.cc b/chrome/browser/ui/javascript_dialogs/javascript_dialog_views.cc index efe61cd..ead533b 100644 --- a/chrome/browser/ui/javascript_dialogs/javascript_dialog_views.cc +++ b/chrome/browser/ui/javascript_dialogs/javascript_dialog_views.cc
@@ -19,15 +19,18 @@ content::JavaScriptDialogType dialog_type, const base::string16& message_text, const base::string16& default_prompt_text, - content::JavaScriptDialogManager::DialogClosedCallback dialog_callback) { + content::JavaScriptDialogManager::DialogClosedCallback dialog_callback, + base::OnceClosure dialog_force_closed_callback) { return (new JavaScriptDialogViews( parent_web_contents, alerting_web_contents, title, dialog_type, - message_text, default_prompt_text, std::move(dialog_callback))) + message_text, default_prompt_text, std::move(dialog_callback), + std::move(dialog_force_closed_callback))) ->weak_factory_.GetWeakPtr(); } void JavaScriptDialogViews::CloseDialogWithoutCallback() { dialog_callback_.Reset(); + dialog_force_closed_callback_.Reset(); GetWidget()->Close(); } @@ -61,8 +64,8 @@ } bool JavaScriptDialogViews::Close() { - if (dialog_callback_) - std::move(dialog_callback_).Run(false, base::string16()); + if (dialog_force_closed_callback_) + std::move(dialog_force_closed_callback_).Run(); return true; } @@ -102,12 +105,14 @@ content::JavaScriptDialogType dialog_type, const base::string16& message_text, const base::string16& default_prompt_text, - content::JavaScriptDialogManager::DialogClosedCallback dialog_callback) + content::JavaScriptDialogManager::DialogClosedCallback dialog_callback, + base::OnceClosure dialog_force_closed_callback) : title_(title), dialog_type_(dialog_type), message_text_(message_text), default_prompt_text_(default_prompt_text), dialog_callback_(std::move(dialog_callback)), + dialog_force_closed_callback_(std::move(dialog_force_closed_callback)), weak_factory_(this) { int options = views::MessageBoxView::DETECT_DIRECTIONALITY; if (dialog_type == content::JAVASCRIPT_DIALOG_TYPE_PROMPT)
diff --git a/chrome/browser/ui/javascript_dialogs/javascript_dialog_views.h b/chrome/browser/ui/javascript_dialogs/javascript_dialog_views.h index 6c52289..eb9589b 100644 --- a/chrome/browser/ui/javascript_dialogs/javascript_dialog_views.h +++ b/chrome/browser/ui/javascript_dialogs/javascript_dialog_views.h
@@ -24,6 +24,9 @@ public: ~JavaScriptDialogViews() override; + // Creates a new JS dialog. Note the two callbacks; |dialog_callback| is for + // user responses, while |dialog_force_closed_callback| is for when Views + // forces the dialog closed without a user reply. static base::WeakPtr<JavaScriptDialogViews> Create( content::WebContents* parent_web_contents, content::WebContents* alerting_web_contents, @@ -31,7 +34,8 @@ content::JavaScriptDialogType dialog_type, const base::string16& message_text, const base::string16& default_prompt_text, - content::JavaScriptDialogManager::DialogClosedCallback dialog_callback); + content::JavaScriptDialogManager::DialogClosedCallback dialog_callback, + base::OnceClosure dialog_force_closed_callback); // JavaScriptDialog: void CloseDialogWithoutCallback() override; @@ -62,13 +66,15 @@ content::JavaScriptDialogType dialog_type, const base::string16& message_text, const base::string16& default_prompt_text, - content::JavaScriptDialogManager::DialogClosedCallback dialog_callback); + content::JavaScriptDialogManager::DialogClosedCallback dialog_callback, + base::OnceClosure dialog_force_closed_callback); base::string16 title_; content::JavaScriptDialogType dialog_type_; base::string16 message_text_; base::string16 default_prompt_text_; content::JavaScriptDialogManager::DialogClosedCallback dialog_callback_; + base::OnceClosure dialog_force_closed_callback_; // The message box view whose commands we handle. views::MessageBoxView* message_box_view_;
diff --git a/chrome/browser/ui/toolbar/app_menu_model.cc b/chrome/browser/ui/toolbar/app_menu_model.cc index 92b7f16..231eefca 100644 --- a/chrome/browser/ui/toolbar/app_menu_model.cc +++ b/chrome/browser/ui/toolbar/app_menu_model.cc
@@ -634,12 +634,6 @@ return Profiling::BeingProfiled(); if (command_id == IDC_TOGGLE_REQUEST_TABLET_SITE) return chrome::IsRequestingTabletSite(browser_); -#if defined(OS_WIN) || (defined(OS_LINUX) && !defined(OS_CHROMEOS)) - if (command_id == IDC_TOGGLE_CONFIRM_TO_QUIT_OPTION) { - return browser_->profile()->GetPrefs()->GetBoolean( - prefs::kConfirmToQuitEnabled); - } -#endif return false; } @@ -807,16 +801,6 @@ if (browser_defaults::kShowExitMenuItem) { AddSeparator(ui::NORMAL_SEPARATOR); -#if defined(OS_WIN) || (defined(OS_LINUX) && !defined(OS_CHROMEOS)) - if (base::FeatureList::IsEnabled(features::kWarnBeforeQuitting)) { - AddCheckItem(IDC_TOGGLE_CONFIRM_TO_QUIT_OPTION, - l10n_util::GetStringFUTF16( - IDS_CONFIRM_TO_QUIT_OPTION, - ui::Accelerator(ui::VKEY_Q, - ui::EF_CONTROL_DOWN | ui::EF_SHIFT_DOWN) - .GetShortcutText())); - } -#endif AddItemWithStringId(IDC_EXIT, IDS_EXIT); } uma_action_recorded_ = false;
diff --git a/chrome/browser/ui/views/accelerator_table.cc b/chrome/browser/ui/views/accelerator_table.cc index e0d08c7a..1bb9442 100644 --- a/chrome/browser/ui/views/accelerator_table.cc +++ b/chrome/browser/ui/views/accelerator_table.cc
@@ -151,7 +151,6 @@ {ui::VKEY_BROWSER_SEARCH, ui::EF_NONE, IDC_FOCUS_SEARCH}, {ui::VKEY_M, ui::EF_SHIFT_DOWN | ui::EF_PLATFORM_ACCELERATOR, IDC_SHOW_AVATAR_MENU}, - {ui::VKEY_Q, ui::EF_SHIFT_DOWN | ui::EF_CONTROL_DOWN, IDC_EXIT}, #endif // !OS_CHROMEOS #if defined(GOOGLE_CHROME_BUILD) && !defined(OS_MACOSX)
diff --git a/chrome/browser/ui/views/confirm_quit_bubble_base.h b/chrome/browser/ui/views/confirm_quit_bubble_base.h deleted file mode 100644 index 8bd73c2..0000000 --- a/chrome/browser/ui/views/confirm_quit_bubble_base.h +++ /dev/null
@@ -1,19 +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_UI_VIEWS_CONFIRM_QUIT_BUBBLE_BASE_H_ -#define CHROME_BROWSER_UI_VIEWS_CONFIRM_QUIT_BUBBLE_BASE_H_ - -// Base class of ConfirmQuitBubble necessary for unit testing -// ConfirmQuitBubbleController. -class ConfirmQuitBubbleBase { - public: - ConfirmQuitBubbleBase() {} - virtual ~ConfirmQuitBubbleBase() {} - - virtual void Show() = 0; - virtual void Hide() = 0; -}; - -#endif // CHROME_BROWSER_UI_VIEWS_CONFIRM_QUIT_BUBBLE_BASE_H_
diff --git a/chrome/browser/ui/views/confirm_quit_bubble_controller.cc b/chrome/browser/ui/views/confirm_quit_bubble_controller.cc deleted file mode 100644 index 5fcf01f..0000000 --- a/chrome/browser/ui/views/confirm_quit_bubble_controller.cc +++ /dev/null
@@ -1,211 +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/ui/views/confirm_quit_bubble_controller.h" - -#include <utility> - -#include "base/feature_list.h" -#include "base/memory/singleton.h" -#include "chrome/browser/chrome_notification_types.h" -#include "chrome/browser/ui/browser_commands.h" -#include "chrome/browser/ui/browser_list.h" -#include "chrome/browser/ui/confirm_quit.h" -#include "chrome/browser/ui/views/confirm_quit_bubble.h" -#include "chrome/browser/ui/views/frame/browser_view.h" -#include "chrome/common/chrome_features.h" -#include "chrome/common/pref_names.h" -#include "content/public/browser/notification_service.h" -#include "ui/base/accelerators/accelerator.h" -#include "ui/events/keycodes/keyboard_codes.h" -#include "ui/gfx/animation/animation.h" -#include "ui/gfx/animation/slide_animation.h" - -namespace { - -constexpr ui::KeyboardCode kAcceleratorKeyCode = ui::VKEY_Q; -constexpr int kAcceleratorModifiers = ui::EF_SHIFT_DOWN | ui::EF_CONTROL_DOWN; - -} // namespace - -// static -ConfirmQuitBubbleController* ConfirmQuitBubbleController::GetInstance() { - return base::Singleton<ConfirmQuitBubbleController>::get(); -} - -ConfirmQuitBubbleController::ConfirmQuitBubbleController() - : ConfirmQuitBubbleController(std::make_unique<ConfirmQuitBubble>(), - std::make_unique<base::OneShotTimer>(), - std::make_unique<gfx::SlideAnimation>(this)) { -} - -ConfirmQuitBubbleController::ConfirmQuitBubbleController( - std::unique_ptr<ConfirmQuitBubbleBase> bubble, - std::unique_ptr<base::OneShotTimer> hide_timer, - std::unique_ptr<gfx::SlideAnimation> animation) - : view_(std::move(bubble)), - state_(State::kWaiting), - hide_timer_(std::move(hide_timer)), - browser_hide_animation_(std::move(animation)) { - browser_hide_animation_->SetSlideDuration( - confirm_quit::kWindowFadeOutDuration.InMilliseconds()); - BrowserList::AddObserver(this); - registrar_.Add(this, chrome::NOTIFICATION_APP_TERMINATING, - content::NotificationService::AllSources()); -} - -ConfirmQuitBubbleController::~ConfirmQuitBubbleController() { - BrowserList::RemoveObserver(this); -} - -void ConfirmQuitBubbleController::OnKeyEvent(ui::KeyEvent* event) { - const ui::Accelerator accelerator(*event); - if (state_ == State::kQuitting) - return; - if (accelerator.key_code() == kAcceleratorKeyCode && - accelerator.modifiers() == kAcceleratorModifiers && - accelerator.key_state() == ui::Accelerator::KeyState::PRESSED && - !accelerator.IsRepeat()) { - if (state_ == State::kWaiting) { - Browser* browser = BrowserList::GetInstance()->GetLastActive(); - PrefService* prefs = browser ? browser->profile()->GetPrefs() : nullptr; - if (!IsFeatureEnabled() || - (prefs && !prefs->GetBoolean(prefs::kConfirmToQuitEnabled))) { - confirm_quit::RecordHistogram(confirm_quit::kNoConfirm); - Quit(); - event->SetHandled(); - return; - } - if (browser) { - browser_ = browser; - pref_change_registrar_ = std::make_unique<PrefChangeRegistrar>(); - pref_change_registrar_->Init(prefs); - pref_change_registrar_->Add( - prefs::kConfirmToQuitEnabled, - base::BindRepeating( - &ConfirmQuitBubbleController::OnConfirmToQuitPrefChanged, - base::Unretained(this))); - } - state_ = State::kPressed; - view_->Show(); - hide_timer_->Start(FROM_HERE, confirm_quit::kShowDuration, this, - &ConfirmQuitBubbleController::OnTimerElapsed); - event->SetHandled(); - } else if (state_ == State::kReleased) { - // The accelerator was pressed while the bubble was showing. Consider - // this a confirmation to quit. - second_press_start_time_ = accelerator.time_stamp(); - ConfirmQuit(); - event->SetHandled(); - } - } else if (accelerator.key_code() == kAcceleratorKeyCode && - accelerator.key_state() == ui::Accelerator::KeyState::RELEASED) { - if (state_ == State::kPressed) { - state_ = State::kReleased; - event->SetHandled(); - } else if (state_ == State::kConfirmed) { - if (!second_press_start_time_.is_null()) { - if (accelerator.time_stamp() - second_press_start_time_ < - confirm_quit::kDoubleTapTimeDelta) { - confirm_quit::RecordHistogram(confirm_quit::kDoubleTap); - } else { - confirm_quit::RecordHistogram(confirm_quit::kTapHold); - } - } - Quit(); - event->SetHandled(); - } - } -} - -void ConfirmQuitBubbleController::OnBrowserRemoved(Browser* browser) { - // A browser is definitely no longer active if it is removed. - OnBrowserNoLongerActive(browser); -} - -void ConfirmQuitBubbleController::OnBrowserNoLongerActive(Browser* browser) { - if (browser == browser_) - Reset(); -} - -void ConfirmQuitBubbleController::DoQuit() { - chrome::Exit(); -} - -bool ConfirmQuitBubbleController::IsFeatureEnabled() { - return base::FeatureList::IsEnabled(features::kWarnBeforeQuitting); -} - -void ConfirmQuitBubbleController::AnimationProgressed( - const gfx::Animation* animation) { - float opacity = static_cast<float>(animation->CurrentValueBetween(1.0, 0.0)); - for (Browser* browser : *BrowserList::GetInstance()) { - BrowserView::GetBrowserViewForBrowser(browser)->GetWidget()->SetOpacity( - opacity); - } -} - -void ConfirmQuitBubbleController::AnimationEnded( - const gfx::Animation* animation) { - AnimationProgressed(animation); -} - -void ConfirmQuitBubbleController::Observe( - int type, - const content::NotificationSource& source, - const content::NotificationDetails& details) { - DCHECK_EQ(chrome::NOTIFICATION_APP_TERMINATING, type); - // The browser process is about to exit. Clean up |pref_change_registrar_| - // now, otherwise it will outlive PrefService which will result in a crash - // when it tries to remove itself as an observer of the PrefService in its - // destructor. Also explicitly set the state to quitting so we don't try to - // show any more UI etc. - pref_change_registrar_.reset(); - view_->Hide(); - state_ = State::kQuitting; -} - -void ConfirmQuitBubbleController::OnTimerElapsed() { - if (state_ == State::kPressed) { - // The accelerator was held down the entire time the bubble was showing. - confirm_quit::RecordHistogram(confirm_quit::kHoldDuration); - ConfirmQuit(); - } else if (state_ == State::kReleased) { - Reset(); - } -} - -void ConfirmQuitBubbleController::OnConfirmToQuitPrefChanged() { - if (browser_ && !browser_->profile()->GetPrefs()->GetBoolean( - prefs::kConfirmToQuitEnabled)) { - Reset(); - } -} - -void ConfirmQuitBubbleController::Reset() { - DCHECK_NE(state_, State::kQuitting); - if (state_ == State::kWaiting) - return; - state_ = State::kWaiting; - second_press_start_time_ = base::TimeTicks(); - browser_ = nullptr; - pref_change_registrar_.reset(); - view_->Hide(); - hide_timer_->Stop(); - browser_hide_animation_->Hide(); -} - -void ConfirmQuitBubbleController::ConfirmQuit() { - DCHECK(state_ == State::kPressed || state_ == State::kReleased); - state_ = State::kConfirmed; - hide_timer_->Stop(); - browser_hide_animation_->Show(); -} - -void ConfirmQuitBubbleController::Quit() { - DCHECK(state_ == State::kWaiting || state_ == State::kConfirmed); - state_ = State::kQuitting; - browser_ = nullptr; - DoQuit(); -}
diff --git a/chrome/browser/ui/views/confirm_quit_bubble_controller.h b/chrome/browser/ui/views/confirm_quit_bubble_controller.h deleted file mode 100644 index cc4285f..0000000 --- a/chrome/browser/ui/views/confirm_quit_bubble_controller.h +++ /dev/null
@@ -1,135 +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_UI_VIEWS_CONFIRM_QUIT_BUBBLE_CONTROLLER_H_ -#define CHROME_BROWSER_UI_VIEWS_CONFIRM_QUIT_BUBBLE_CONTROLLER_H_ - -#include <memory> - -#include "base/macros.h" -#include "base/timer/timer.h" -#include "chrome/browser/ui/browser_list_observer.h" -#include "content/public/browser/notification_observer.h" -#include "content/public/browser/notification_registrar.h" -#include "ui/events/event_handler.h" -#include "ui/gfx/animation/animation_delegate.h" - -class ConfirmQuitBubbleBase; -class PrefChangeRegistrar; - -namespace base { -template <typename T> -struct DefaultSingletonTraits; -} - -namespace gfx { -class SlideAnimation; -} - -// Manages showing and hiding the confirm-to-quit bubble. Requests Chrome to be -// closed if the quit accelerator is held down or pressed twice in succession. -// The singleton instance of this class is added as a PreTargetHandler for each -// browser window. -class ConfirmQuitBubbleController : public gfx::AnimationDelegate, - public BrowserListObserver, - public content::NotificationObserver, - public ui::EventHandler { - public: - static ConfirmQuitBubbleController* GetInstance(); - - ~ConfirmQuitBubbleController() override; - - // ui::EventHandler: - void OnKeyEvent(ui::KeyEvent* event) override; - - protected: - // |animation| is used to fade out all browser windows. - ConfirmQuitBubbleController(std::unique_ptr<ConfirmQuitBubbleBase> bubble, - std::unique_ptr<base::OneShotTimer> hide_timer, - std::unique_ptr<gfx::SlideAnimation> animation); - - // BrowserListObserver: - void OnBrowserRemoved(Browser* browser) override; - void OnBrowserNoLongerActive(Browser* browser) override; - - // Runs the quit action now. Virtual so tests can override the quit action. - virtual void DoQuit(); - - // Returns true if the confirm-to-quit feature is enabled. Virtual so tests - // can override the setting. - virtual bool IsFeatureEnabled(); - - private: - friend struct base::DefaultSingletonTraits<ConfirmQuitBubbleController>; - - enum class State { - // The accelerator has not been pressed. - kWaiting, - - // The accelerator was pressed, but not yet released. - kPressed, - - // The accelerator was pressed and released before the timer expired. - kReleased, - - // The accelerator was either held down for the entire duration of the - // timer, or was pressed a second time. Either way, the accelerator is - // currently held. - kConfirmed, - - // The accelerator was released and Chrome is now quitting. - kQuitting, - }; - - ConfirmQuitBubbleController(); - - // gfx::AnimationDelegate: - void AnimationProgressed(const gfx::Animation* animation) override; - void AnimationEnded(const gfx::Animation* animation) override; - - // content::NotificationObserver: - void Observe(int type, - const content::NotificationSource& source, - const content::NotificationDetails& details) override; - - void OnTimerElapsed(); - - // Called when the user changes their preference for the confirm-to-quit - // setting. - void OnConfirmToQuitPrefChanged(); - - // Resets back to the waiting state. Hides any UI and resets timers that may - // be active. - void Reset(); - - // Transitions to the confirmed state. Quit() will be run later when the user - // releases the accelerator. - void ConfirmQuit(); - - // Updates state and calls DoQuit(). - void Quit(); - - std::unique_ptr<ConfirmQuitBubbleBase> const view_; - - State state_; - - // Used only to distinguish between a double-press and a tap-and-hold when - // recording metrics. - base::TimeTicks second_press_start_time_; - - // The last active browser when the accelerator was pressed. - Browser* browser_ = nullptr; - - std::unique_ptr<PrefChangeRegistrar> pref_change_registrar_; - - std::unique_ptr<base::OneShotTimer> hide_timer_; - - std::unique_ptr<gfx::SlideAnimation> const browser_hide_animation_; - - content::NotificationRegistrar registrar_; - - DISALLOW_COPY_AND_ASSIGN(ConfirmQuitBubbleController); -}; - -#endif // CHROME_BROWSER_UI_VIEWS_CONFIRM_QUIT_BUBBLE_CONTROLLER_H_
diff --git a/chrome/browser/ui/views/confirm_quit_bubble_controller_unittest.cc b/chrome/browser/ui/views/confirm_quit_bubble_controller_unittest.cc deleted file mode 100644 index 674c779..0000000 --- a/chrome/browser/ui/views/confirm_quit_bubble_controller_unittest.cc +++ /dev/null
@@ -1,212 +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/ui/views/confirm_quit_bubble_controller.h" - -#include <memory> -#include <utility> - -#include "base/bind.h" -#include "base/macros.h" -#include "base/timer/mock_timer.h" -#include "chrome/browser/ui/views/confirm_quit_bubble.h" -#include "testing/gtest/include/gtest/gtest.h" -#include "ui/base/accelerators/accelerator.h" -#include "ui/events/event.h" -#include "ui/events/keycodes/keyboard_codes.h" -#include "ui/gfx/animation/slide_animation.h" - -class TestConfirmQuitBubble : public ConfirmQuitBubbleBase { - public: - TestConfirmQuitBubble() {} - ~TestConfirmQuitBubble() override {} - - void Show() override {} - void Hide() override {} - - private: - DISALLOW_COPY_AND_ASSIGN(TestConfirmQuitBubble); -}; - -class TestConfirmQuitBubbleController : public ConfirmQuitBubbleController { - public: - TestConfirmQuitBubbleController( - std::unique_ptr<ConfirmQuitBubbleBase> bubble, - std::unique_ptr<base::OneShotTimer> hide_timer, - std::unique_ptr<gfx::SlideAnimation> animation) - : ConfirmQuitBubbleController(std::move(bubble), - std::move(hide_timer), - std::move(animation)) {} - - void DeactivateBrowser() { OnBrowserNoLongerActive(nullptr); } - - bool quit_called() const { return quit_called_; } - - private: - void DoQuit() override { quit_called_ = true; } - - bool IsFeatureEnabled() override { return true; } - - bool quit_called_ = false; - - DISALLOW_COPY_AND_ASSIGN(TestConfirmQuitBubbleController); -}; - -class TestSlideAnimation : public gfx::SlideAnimation { - public: - TestSlideAnimation() : gfx::SlideAnimation(nullptr) {} - ~TestSlideAnimation() override {} - - void Reset() override {} - void Reset(double value) override {} - void Show() override {} - void Hide() override {} - void SetSlideDuration(int duration) override {} - - private: - DISALLOW_COPY_AND_ASSIGN(TestSlideAnimation); -}; - -class ConfirmQuitBubbleControllerTest : public testing::Test { - protected: - void SetUp() override { - std::unique_ptr<TestConfirmQuitBubble> bubble = - std::make_unique<TestConfirmQuitBubble>(); - auto timer = std::make_unique<base::MockOneShotTimer>(); - bubble_ = bubble.get(); - timer_ = timer.get(); - controller_.reset(new TestConfirmQuitBubbleController( - std::move(bubble), std::move(timer), - std::make_unique<TestSlideAnimation>())); - } - - void TearDown() override { controller_.reset(); } - - void SendKeyEvent(ui::KeyEvent* event) { controller_->OnKeyEvent(event); } - - void SendAccelerator(bool quit, bool press, bool repeat) { - ui::KeyboardCode key = quit ? ui::VKEY_Q : ui::VKEY_P; - int modifiers = ui::EF_SHIFT_DOWN | ui::EF_CONTROL_DOWN; - if (repeat) - modifiers |= ui::EF_IS_REPEAT; - ui::EventType type = press ? ui::ET_KEY_PRESSED : ui::ET_KEY_RELEASED; - ui::KeyEvent event(type, key, modifiers); - SendKeyEvent(&event); - } - - void PressQuitAccelerator() { SendAccelerator(true, true, false); } - - void ReleaseQuitAccelerator() { SendAccelerator(true, false, false); } - - void RepeatQuitAccelerator() { SendAccelerator(true, true, true); } - - void PressOtherAccelerator() { SendAccelerator(false, true, false); } - - void ReleaseOtherAccelerator() { SendAccelerator(false, false, false); } - - std::unique_ptr<TestConfirmQuitBubbleController> controller_; - - // Owned by |controller_|. - TestConfirmQuitBubble* bubble_; - - // Owned by |controller_|. - base::MockOneShotTimer* timer_; - - bool quit_called_ = false; -}; - -// Pressing and holding the shortcut should quit. -TEST_F(ConfirmQuitBubbleControllerTest, PressAndHold) { - PressQuitAccelerator(); - EXPECT_TRUE(timer_->IsRunning()); - timer_->Fire(); - EXPECT_FALSE(controller_->quit_called()); - ReleaseQuitAccelerator(); - EXPECT_TRUE(controller_->quit_called()); -} - -// Pressing the shortcut twice should quit. -TEST_F(ConfirmQuitBubbleControllerTest, DoublePress) { - PressQuitAccelerator(); - ReleaseQuitAccelerator(); - EXPECT_TRUE(timer_->IsRunning()); - PressQuitAccelerator(); - EXPECT_FALSE(timer_->IsRunning()); - EXPECT_FALSE(controller_->quit_called()); - ReleaseQuitAccelerator(); - EXPECT_TRUE(controller_->quit_called()); -} - -// Pressing the shortcut once should not quit. -TEST_F(ConfirmQuitBubbleControllerTest, SinglePress) { - PressQuitAccelerator(); - ReleaseQuitAccelerator(); - EXPECT_TRUE(timer_->IsRunning()); - timer_->Fire(); - EXPECT_FALSE(controller_->quit_called()); -} - -// Repeated presses should not be counted. -TEST_F(ConfirmQuitBubbleControllerTest, RepeatedPresses) { - PressQuitAccelerator(); - RepeatQuitAccelerator(); - ReleaseQuitAccelerator(); - EXPECT_TRUE(timer_->IsRunning()); - timer_->Fire(); - EXPECT_FALSE(controller_->quit_called()); -} - -// Other keys shouldn't matter. -TEST_F(ConfirmQuitBubbleControllerTest, OtherKeyPress) { - PressQuitAccelerator(); - ReleaseQuitAccelerator(); - PressOtherAccelerator(); - ReleaseOtherAccelerator(); - EXPECT_TRUE(timer_->IsRunning()); - PressQuitAccelerator(); - EXPECT_FALSE(timer_->IsRunning()); - EXPECT_FALSE(controller_->quit_called()); - ReleaseQuitAccelerator(); - EXPECT_TRUE(controller_->quit_called()); -} - -// The controller state should be reset when the browser loses focus. -TEST_F(ConfirmQuitBubbleControllerTest, BrowserLosesFocus) { - // Press but don't release the accelerator. - PressQuitAccelerator(); - EXPECT_TRUE(timer_->IsRunning()); - controller_->DeactivateBrowser(); - EXPECT_FALSE(timer_->IsRunning()); - EXPECT_FALSE(controller_->quit_called()); - ReleaseQuitAccelerator(); - - // Press and release the accelerator. - PressQuitAccelerator(); - ReleaseQuitAccelerator(); - EXPECT_TRUE(timer_->IsRunning()); - controller_->DeactivateBrowser(); - EXPECT_FALSE(timer_->IsRunning()); - EXPECT_FALSE(controller_->quit_called()); - - // Press and hold the accelerator. - PressQuitAccelerator(); - EXPECT_TRUE(timer_->IsRunning()); - timer_->Fire(); - EXPECT_FALSE(timer_->IsRunning()); - controller_->DeactivateBrowser(); - ReleaseQuitAccelerator(); - EXPECT_FALSE(controller_->quit_called()); -} - -// The controller should not consume keyup events on the 'Q' key -// (https://crbug.com/856868). -TEST_F(ConfirmQuitBubbleControllerTest, ControllerDoesNotHandleQKeyUp) { - ui::KeyEvent press_event(ui::ET_KEY_PRESSED, ui::VKEY_Q, 0); - SendKeyEvent(&press_event); - EXPECT_FALSE(press_event.handled()); - - ui::KeyEvent release_event(ui::ET_KEY_RELEASED, ui::VKEY_Q, 0); - SendKeyEvent(&release_event); - EXPECT_FALSE(release_event.handled()); -}
diff --git a/chrome/browser/ui/views/frame/browser_view.cc b/chrome/browser/ui/views/frame/browser_view.cc index 81127e8..5d1e433 100644 --- a/chrome/browser/ui/views/frame/browser_view.cc +++ b/chrome/browser/ui/views/frame/browser_view.cc
@@ -71,7 +71,6 @@ #include "chrome/browser/ui/views/autofill/save_card_sign_in_promo_bubble_views.h" #include "chrome/browser/ui/views/bookmarks/bookmark_bar_view.h" #include "chrome/browser/ui/views/bookmarks/bookmark_bubble_view.h" -#include "chrome/browser/ui/views/confirm_quit_bubble_controller.h" #include "chrome/browser/ui/views/download/download_in_progress_dialog_view.h" #include "chrome/browser/ui/views/download/download_shelf_view.h" #include "chrome/browser/ui/views/exclusive_access_bubble_views.h" @@ -92,6 +91,7 @@ #include "chrome/browser/ui/views/omnibox/omnibox_view_views.h" #include "chrome/browser/ui/views/page_action/page_action_icon_container_view.h" #include "chrome/browser/ui/views/profiles/profile_indicator_icon.h" +#include "chrome/browser/ui/views/quit_instruction_bubble_controller.h" #include "chrome/browser/ui/views/status_bubble_views.h" #include "chrome/browser/ui/views/tab_contents/chrome_web_contents_view_focus_helper.h" #include "chrome/browser/ui/views/tabs/browser_tab_strip_controller.h" @@ -1156,7 +1156,7 @@ void BrowserView::DestroyBrowser() { #if defined(OS_WIN) || (defined(OS_LINUX) && !defined(OS_CHROMEOS)) GetWidget()->GetNativeView()->RemovePreTargetHandler( - ConfirmQuitBubbleController::GetInstance()); + QuitInstructionBubbleController::GetInstance()); #endif // After this returns other parts of Chrome are going to be shutdown. Close @@ -2258,7 +2258,7 @@ #if defined(OS_WIN) || (defined(OS_LINUX) && !defined(OS_CHROMEOS)) GetWidget()->GetNativeView()->AddPreTargetHandler( - ConfirmQuitBubbleController::GetInstance()); + QuitInstructionBubbleController::GetInstance()); #endif #if defined(USE_AURA)
diff --git a/chrome/browser/ui/views/confirm_quit_bubble.cc b/chrome/browser/ui/views/quit_instruction_bubble.cc similarity index 78% rename from chrome/browser/ui/views/confirm_quit_bubble.cc rename to chrome/browser/ui/views/quit_instruction_bubble.cc index b01be11f..77533043 100644 --- a/chrome/browser/ui/views/confirm_quit_bubble.cc +++ b/chrome/browser/ui/views/quit_instruction_bubble.cc
@@ -2,7 +2,7 @@ // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. -#include "chrome/browser/ui/views/confirm_quit_bubble.h" +#include "chrome/browser/ui/views/quit_instruction_bubble.h" #include <utility> @@ -29,22 +29,23 @@ } // namespace -ConfirmQuitBubble::ConfirmQuitBubble() +QuitInstructionBubble::QuitInstructionBubble() : animation_(std::make_unique<gfx::SlideAnimation>(this)) { animation_->SetSlideDuration(kSlideDuration.InMilliseconds()); } -ConfirmQuitBubble::~ConfirmQuitBubble() {} +QuitInstructionBubble::~QuitInstructionBubble() {} -void ConfirmQuitBubble::Show() { +void QuitInstructionBubble::Show() { animation_->Show(); } -void ConfirmQuitBubble::Hide() { +void QuitInstructionBubble::Hide() { animation_->Hide(); } -void ConfirmQuitBubble::AnimationProgressed(const gfx::Animation* animation) { +void QuitInstructionBubble::AnimationProgressed( + const gfx::Animation* animation) { float opacity = static_cast<float>(animation->CurrentValueBetween(0.0, 1.0)); if (opacity == 0) { popup_.reset(); @@ -68,10 +69,10 @@ popup_->SetContentsView(view); view->UpdateContent(l10n_util::GetStringFUTF16( - IDS_CONFIRM_TO_QUIT_DESCRIPTION, - l10n_util::GetStringUTF16(IDS_APP_CTRL_KEY), - l10n_util::GetStringUTF16(IDS_APP_SHIFT_KEY), - ui::Accelerator(ui::VKEY_Q, 0).GetShortcutText())); + IDS_QUIT_ACCELERATOR_TUTORIAL, + l10n_util::GetStringUTF16(IDS_APP_ALT_KEY), + ui::Accelerator(ui::VKEY_F, 0).GetShortcutText(), + ui::Accelerator(ui::VKEY_X, 0).GetShortcutText())); popup_->CenterWindow(view->GetPreferredSize()); @@ -81,6 +82,6 @@ } } -void ConfirmQuitBubble::AnimationEnded(const gfx::Animation* animation) { +void QuitInstructionBubble::AnimationEnded(const gfx::Animation* animation) { AnimationProgressed(animation); }
diff --git a/chrome/browser/ui/views/confirm_quit_bubble.h b/chrome/browser/ui/views/quit_instruction_bubble.h similarity index 61% rename from chrome/browser/ui/views/confirm_quit_bubble.h rename to chrome/browser/ui/views/quit_instruction_bubble.h index b4de3d0..60fd412 100644 --- a/chrome/browser/ui/views/confirm_quit_bubble.h +++ b/chrome/browser/ui/views/quit_instruction_bubble.h
@@ -2,13 +2,13 @@ // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. -#ifndef CHROME_BROWSER_UI_VIEWS_CONFIRM_QUIT_BUBBLE_H_ -#define CHROME_BROWSER_UI_VIEWS_CONFIRM_QUIT_BUBBLE_H_ +#ifndef CHROME_BROWSER_UI_VIEWS_QUIT_INSTRUCTION_BUBBLE_H_ +#define CHROME_BROWSER_UI_VIEWS_QUIT_INSTRUCTION_BUBBLE_H_ #include <memory> #include "base/macros.h" -#include "chrome/browser/ui/views/confirm_quit_bubble_base.h" +#include "chrome/browser/ui/views/quit_instruction_bubble_base.h" #include "ui/gfx/animation/animation_delegate.h" namespace gfx { @@ -20,13 +20,13 @@ class Widget; } // namespace views -// Manages showing and hiding a notification bubble that gives instructions to -// continue holding the quit accelerator to quit. -class ConfirmQuitBubble : public ConfirmQuitBubbleBase, - public gfx::AnimationDelegate { +// Manages showing and hiding a notification bubble that gives instructions for +// how to quit using keyboard shortcuts. +class QuitInstructionBubble : public QuitInstructionBubbleBase, + public gfx::AnimationDelegate { public: - ConfirmQuitBubble(); - ~ConfirmQuitBubble() override; + QuitInstructionBubble(); + ~QuitInstructionBubble() override; void Show() override; void Hide() override; @@ -41,7 +41,7 @@ std::unique_ptr<views::Widget> popup_; - DISALLOW_COPY_AND_ASSIGN(ConfirmQuitBubble); + DISALLOW_COPY_AND_ASSIGN(QuitInstructionBubble); }; -#endif // CHROME_BROWSER_UI_VIEWS_CONFIRM_QUIT_BUBBLE_H_ +#endif // CHROME_BROWSER_UI_VIEWS_QUIT_INSTRUCTION_BUBBLE_H_
diff --git a/chrome/browser/ui/views/quit_instruction_bubble_base.h b/chrome/browser/ui/views/quit_instruction_bubble_base.h new file mode 100644 index 0000000..4b80276 --- /dev/null +++ b/chrome/browser/ui/views/quit_instruction_bubble_base.h
@@ -0,0 +1,19 @@ +// 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_UI_VIEWS_QUIT_INSTRUCTION_BUBBLE_BASE_H_ +#define CHROME_BROWSER_UI_VIEWS_QUIT_INSTRUCTION_BUBBLE_BASE_H_ + +// Base class of QuitInstructionBubble necessary for unit testing +// QuitInstructionBubbleController. +class QuitInstructionBubbleBase { + public: + QuitInstructionBubbleBase() {} + virtual ~QuitInstructionBubbleBase() {} + + virtual void Show() = 0; + virtual void Hide() = 0; +}; + +#endif // CHROME_BROWSER_UI_VIEWS_QUIT_INSTRUCTION_BUBBLE_BASE_H_
diff --git a/chrome/browser/ui/views/quit_instruction_bubble_controller.cc b/chrome/browser/ui/views/quit_instruction_bubble_controller.cc new file mode 100644 index 0000000..ec5681e --- /dev/null +++ b/chrome/browser/ui/views/quit_instruction_bubble_controller.cc
@@ -0,0 +1,57 @@ +// 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/ui/views/quit_instruction_bubble_controller.h" + +#include <utility> + +#include "base/memory/singleton.h" +#include "chrome/browser/ui/views/frame/browser_view.h" +#include "chrome/browser/ui/views/quit_instruction_bubble.h" +#include "ui/base/accelerators/accelerator.h" +#include "ui/events/keycodes/keyboard_codes.h" + +namespace { + +constexpr ui::KeyboardCode kAcceleratorKeyCode = ui::VKEY_Q; +constexpr int kAcceleratorModifiers = ui::EF_SHIFT_DOWN | ui::EF_CONTROL_DOWN; + +constexpr base::TimeDelta kShowDuration = + base::TimeDelta::FromMilliseconds(3000); + +} // namespace + +// static +QuitInstructionBubbleController* +QuitInstructionBubbleController::GetInstance() { + return base::Singleton<QuitInstructionBubbleController>::get(); +} + +QuitInstructionBubbleController::QuitInstructionBubbleController() + : QuitInstructionBubbleController(std::make_unique<QuitInstructionBubble>(), + std::make_unique<base::OneShotTimer>()) {} + +QuitInstructionBubbleController::QuitInstructionBubbleController( + std::unique_ptr<QuitInstructionBubbleBase> bubble, + std::unique_ptr<base::OneShotTimer> hide_timer) + : view_(std::move(bubble)), hide_timer_(std::move(hide_timer)) {} + +QuitInstructionBubbleController::~QuitInstructionBubbleController() {} + +void QuitInstructionBubbleController::OnKeyEvent(ui::KeyEvent* event) { + const ui::Accelerator accelerator(*event); + if (accelerator.key_code() == kAcceleratorKeyCode && + accelerator.modifiers() == kAcceleratorModifiers) { + event->SetHandled(); + if (accelerator.key_state() == ui::Accelerator::KeyState::PRESSED) { + view_->Show(); + hide_timer_->Start(FROM_HERE, kShowDuration, this, + &QuitInstructionBubbleController::OnTimerElapsed); + } + } +} + +void QuitInstructionBubbleController::OnTimerElapsed() { + view_->Hide(); +}
diff --git a/chrome/browser/ui/views/quit_instruction_bubble_controller.h b/chrome/browser/ui/views/quit_instruction_bubble_controller.h new file mode 100644 index 0000000..737c2a34 --- /dev/null +++ b/chrome/browser/ui/views/quit_instruction_bubble_controller.h
@@ -0,0 +1,52 @@ +// 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_UI_VIEWS_QUIT_INSTRUCTION_BUBBLE_CONTROLLER_H_ +#define CHROME_BROWSER_UI_VIEWS_QUIT_INSTRUCTION_BUBBLE_CONTROLLER_H_ + +#include <memory> + +#include "base/macros.h" +#include "base/timer/timer.h" +#include "ui/events/event_handler.h" + +class QuitInstructionBubbleBase; + +namespace base { +template <typename T> +struct DefaultSingletonTraits; +} + +// Manages showing and hiding the quit instruction bubble. The singleton +// instance of this class is added as a PreTargetHandler for each browser +// window. +class QuitInstructionBubbleController : public ui::EventHandler { + public: + static QuitInstructionBubbleController* GetInstance(); + + ~QuitInstructionBubbleController() override; + + // ui::EventHandler: + void OnKeyEvent(ui::KeyEvent* event) override; + + protected: + QuitInstructionBubbleController( + std::unique_ptr<QuitInstructionBubbleBase> bubble, + std::unique_ptr<base::OneShotTimer> hide_timer); + + private: + friend struct base::DefaultSingletonTraits<QuitInstructionBubbleController>; + + QuitInstructionBubbleController(); + + void OnTimerElapsed(); + + std::unique_ptr<QuitInstructionBubbleBase> const view_; + + std::unique_ptr<base::OneShotTimer> hide_timer_; + + DISALLOW_COPY_AND_ASSIGN(QuitInstructionBubbleController); +}; + +#endif // CHROME_BROWSER_UI_VIEWS_QUIT_INSTRUCTION_BUBBLE_CONTROLLER_H_
diff --git a/chrome/browser/ui/views/quit_instruction_bubble_controller_unittest.cc b/chrome/browser/ui/views/quit_instruction_bubble_controller_unittest.cc new file mode 100644 index 0000000..4a27424 --- /dev/null +++ b/chrome/browser/ui/views/quit_instruction_bubble_controller_unittest.cc
@@ -0,0 +1,144 @@ +// 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/ui/views/quit_instruction_bubble_controller.h" + +#include <memory> +#include <utility> + +#include "base/bind.h" +#include "base/macros.h" +#include "base/timer/mock_timer.h" +#include "chrome/browser/ui/views/quit_instruction_bubble.h" +#include "testing/gtest/include/gtest/gtest.h" +#include "ui/base/accelerators/accelerator.h" +#include "ui/events/event.h" +#include "ui/events/keycodes/keyboard_codes.h" +#include "ui/gfx/animation/slide_animation.h" + +class TestQuitInstructionBubble : public QuitInstructionBubbleBase { + public: + TestQuitInstructionBubble() {} + ~TestQuitInstructionBubble() override {} + + void Show() override {} + void Hide() override {} + + private: + DISALLOW_COPY_AND_ASSIGN(TestQuitInstructionBubble); +}; + +class TestQuitInstructionBubbleController + : public QuitInstructionBubbleController { + public: + TestQuitInstructionBubbleController( + std::unique_ptr<QuitInstructionBubbleBase> bubble, + std::unique_ptr<base::OneShotTimer> hide_timer, + std::unique_ptr<gfx::SlideAnimation> animation) + : QuitInstructionBubbleController(std::move(bubble), + std::move(hide_timer)) {} + + private: + DISALLOW_COPY_AND_ASSIGN(TestQuitInstructionBubbleController); +}; + +class TestSlideAnimation : public gfx::SlideAnimation { + public: + TestSlideAnimation() : gfx::SlideAnimation(nullptr) {} + ~TestSlideAnimation() override {} + + void Reset() override {} + void Reset(double value) override {} + void Show() override {} + void Hide() override {} + void SetSlideDuration(int duration) override {} + + private: + DISALLOW_COPY_AND_ASSIGN(TestSlideAnimation); +}; + +class QuitInstructionBubbleControllerTest : public testing::Test { + protected: + void SetUp() override { + std::unique_ptr<TestQuitInstructionBubble> bubble = + std::make_unique<TestQuitInstructionBubble>(); + auto timer = std::make_unique<base::MockOneShotTimer>(); + bubble_ = bubble.get(); + timer_ = timer.get(); + controller_.reset(new TestQuitInstructionBubbleController( + std::move(bubble), std::move(timer), + std::make_unique<TestSlideAnimation>())); + } + + void TearDown() override { controller_.reset(); } + + void SendKeyEvent(ui::KeyEvent* event) { controller_->OnKeyEvent(event); } + + void SendAccelerator(bool quit, bool press, bool repeat) { + ui::KeyboardCode key = quit ? ui::VKEY_Q : ui::VKEY_P; + int modifiers = ui::EF_SHIFT_DOWN | ui::EF_CONTROL_DOWN; + if (repeat) + modifiers |= ui::EF_IS_REPEAT; + ui::EventType type = press ? ui::ET_KEY_PRESSED : ui::ET_KEY_RELEASED; + ui::KeyEvent event(type, key, modifiers); + SendKeyEvent(&event); + } + + void PressQuitAccelerator() { SendAccelerator(true, true, false); } + + void ReleaseQuitAccelerator() { SendAccelerator(true, false, false); } + + void RepeatQuitAccelerator() { SendAccelerator(true, true, true); } + + void PressOtherAccelerator() { SendAccelerator(false, true, false); } + + void ReleaseOtherAccelerator() { SendAccelerator(false, false, false); } + + std::unique_ptr<TestQuitInstructionBubbleController> controller_; + + // Owned by |controller_|. + TestQuitInstructionBubble* bubble_; + + // Owned by |controller_|. + base::MockOneShotTimer* timer_; +}; + +// Pressing the shortcut should show the bubble. +TEST_F(QuitInstructionBubbleControllerTest, PressAndHold) { + PressQuitAccelerator(); + EXPECT_TRUE(timer_->IsRunning()); + ReleaseQuitAccelerator(); + EXPECT_TRUE(timer_->IsRunning()); +} + +// Repeated presses should keep showing the bubble. +TEST_F(QuitInstructionBubbleControllerTest, RepeatedPresses) { + PressQuitAccelerator(); + RepeatQuitAccelerator(); + ReleaseQuitAccelerator(); + EXPECT_TRUE(timer_->IsRunning()); +} + +// Other keys shouldn't matter. +TEST_F(QuitInstructionBubbleControllerTest, OtherKeyPress) { + PressQuitAccelerator(); + ReleaseQuitAccelerator(); + PressOtherAccelerator(); + ReleaseOtherAccelerator(); + EXPECT_TRUE(timer_->IsRunning()); + PressQuitAccelerator(); + EXPECT_TRUE(timer_->IsRunning()); +} + +// The controller should not consume keyup events on the 'Q' key +// (https://crbug.com/856868). +TEST_F(QuitInstructionBubbleControllerTest, ControllerDoesNotHandleQKeyUp) { + ui::KeyEvent press_event(ui::ET_KEY_PRESSED, ui::VKEY_Q, 0); + SendKeyEvent(&press_event); + EXPECT_FALSE(press_event.handled()); + + ui::KeyEvent release_event(ui::ET_KEY_RELEASED, ui::VKEY_Q, 0); + SendKeyEvent(&release_event); + EXPECT_FALSE(release_event.handled()); +}
diff --git a/chrome/browser/ui/views/webauthn/sheet_view_factory.cc b/chrome/browser/ui/views/webauthn/sheet_view_factory.cc index 8511661..1c298072 100644 --- a/chrome/browser/ui/views/webauthn/sheet_view_factory.cc +++ b/chrome/browser/ui/views/webauthn/sheet_view_factory.cc
@@ -34,7 +34,7 @@ std::unique_ptr<AuthenticatorRequestSheetView> sheet_view; switch (dialog_model->current_step()) { - case Step::kInitial: + case Step::kWelcomeScreen: sheet_view = std::make_unique<AuthenticatorRequestSheetView>( std::make_unique<AuthenticatorInitialSheetModel>(dialog_model)); break; @@ -43,15 +43,9 @@ std::make_unique<AuthenticatorTransportSelectorSheetModel>( dialog_model)); break; - case Step::kUsbInsertAndActivateOnRegister: + case Step::kUsbInsertAndActivate: sheet_view = std::make_unique<AuthenticatorRequestSheetView>( - std::make_unique< - AuthenticatorInsertAndActivateUsbOnRegisterSheetModel>( - dialog_model)); - break; - case Step::kUsbInsertAndActivateOnSign: - sheet_view = std::make_unique<AuthenticatorRequestSheetView>( - std::make_unique<AuthenticatorInsertAndActivateUsbOnSignSheetModel>( + std::make_unique<AuthenticatorInsertAndActivateUsbSheetModel>( dialog_model)); break; case Step::kErrorTimedOut:
diff --git a/chrome/browser/ui/webauthn/authenticator_dialog_browsertest.cc b/chrome/browser/ui/webauthn/authenticator_dialog_browsertest.cc index a91aaf11..4f2467a 100644 --- a/chrome/browser/ui/webauthn/authenticator_dialog_browsertest.cc +++ b/chrome/browser/ui/webauthn/authenticator_dialog_browsertest.cc
@@ -34,12 +34,9 @@ AuthenticatorTransport::kCloudAssistedBluetoothLowEnergy); model->SetCurrentStep( AuthenticatorRequestDialogModel::Step::kTransportSelection); - } else if (name == "insert_usb_register") { - model->SetCurrentStep(AuthenticatorRequestDialogModel::Step:: - kUsbInsertAndActivateOnRegister); - } else if (name == "insert_usb_sign") { + } else if (name == "activate_usb") { model->SetCurrentStep( - AuthenticatorRequestDialogModel::Step::kUsbInsertAndActivateOnSign); + AuthenticatorRequestDialogModel::Step::kUsbInsertAndActivate); } else if (name == "timeout") { model->SetCurrentStep( AuthenticatorRequestDialogModel::Step::kErrorTimedOut); @@ -91,11 +88,7 @@ ShowAndVerifyUi(); } -IN_PROC_BROWSER_TEST_F(AuthenticatorDialogTest, InvokeUi_insert_usb_register) { - ShowAndVerifyUi(); -} - -IN_PROC_BROWSER_TEST_F(AuthenticatorDialogTest, InvokeUi_insert_usb_sign) { +IN_PROC_BROWSER_TEST_F(AuthenticatorDialogTest, InvokeUi_activate_usb) { ShowAndVerifyUi(); }
diff --git a/chrome/browser/ui/webauthn/sheet_models.cc b/chrome/browser/ui/webauthn/sheet_models.cc index b18cf28..dc29919 100644 --- a/chrome/browser/ui/webauthn/sheet_models.cc +++ b/chrome/browser/ui/webauthn/sheet_models.cc
@@ -90,12 +90,12 @@ // TODO(hongjunchoi): Insert actual domain name from model to // |application_name|. base::string16 application_name = base::UTF8ToUTF16("example.com"); - return l10n_util::GetStringFUTF16(IDS_WEBAUTHN_INITIAL_SHEET_TITLE, + return l10n_util::GetStringFUTF16(IDS_WEBAUTHN_WELCOME_SCREEN_TITLE, application_name); } base::string16 AuthenticatorInitialSheetModel::GetStepDescription() const { - return l10n_util::GetStringUTF16(IDS_WEBAUTHN_INITIAL_SHEET_DESCRIPTION); + return l10n_util::GetStringUTF16(IDS_WEBAUTHN_WELCOME_SCREEN_DESCRIPTION); } bool AuthenticatorInitialSheetModel::IsAcceptButtonVisible() const { @@ -107,14 +107,14 @@ } base::string16 AuthenticatorInitialSheetModel::GetAcceptButtonLabel() const { - return l10n_util::GetStringUTF16(IDS_WEBAUTHN_INITIAL_SHEET_NEXT); + return l10n_util::GetStringUTF16(IDS_WEBAUTHN_WELCOME_SCREEN_NEXT); } void AuthenticatorInitialSheetModel::OnAccept() { // TODO(hongjunchoi): Check whether Bluetooth adapter is enabled and if it is, // set current step to |kTransportSelection|. dialog_model()->SetCurrentStep( - AuthenticatorRequestDialogModel::Step::kUsbInsertAndActivateOnRegister); + AuthenticatorRequestDialogModel::Step::kUsbInsertAndActivate); } // AuthenticatorTransportSelectorSheetModel ----------------------------------- @@ -143,44 +143,25 @@ dialog_model()->StartGuidedFlowForTransport(transport); } -// AuthenticatorInsertAndActivateUsbOnRegisterSheetModel ---------------------- +// AuthenticatorInsertAndActivateUsbSheetModel ---------------------- gfx::ImageSkia* -AuthenticatorInsertAndActivateUsbOnRegisterSheetModel::GetStepIllustration() - const { +AuthenticatorInsertAndActivateUsbSheetModel::GetStepIllustration() const { return GetImage(IDR_WEBAUTHN_ILLUSTRATION_USB_1X); } -base::string16 -AuthenticatorInsertAndActivateUsbOnRegisterSheetModel::GetStepTitle() const { - return l10n_util::GetStringUTF16(IDS_WEBAUTHN_USB_TITLE_ON_REGISTER); -} - -base::string16 -AuthenticatorInsertAndActivateUsbOnRegisterSheetModel::GetStepDescription() - const { - return l10n_util::GetStringUTF16(IDS_WEBAUTHN_USB_INSERT_DESCRIPTION); -} - -// AuthenticatorInsertAndActivateUsbOnSignSheetModel ---------------------- - -gfx::ImageSkia* -AuthenticatorInsertAndActivateUsbOnSignSheetModel::GetStepIllustration() const { - return GetImage(IDR_WEBAUTHN_ILLUSTRATION_USB_1X); -} - -base::string16 AuthenticatorInsertAndActivateUsbOnSignSheetModel::GetStepTitle() +base::string16 AuthenticatorInsertAndActivateUsbSheetModel::GetStepTitle() const { // TODO(hongjunchoi): Insert actual domain name from model to // |application_name|. base::string16 application_name = base::UTF8ToUTF16("example.com"); - return l10n_util::GetStringFUTF16(IDS_WEBAUTHN_USB_TITLE_ON_SIGNIN, + return l10n_util::GetStringFUTF16(IDS_WEBAUTHN_GENERIC_TITLE, application_name); } -base::string16 -AuthenticatorInsertAndActivateUsbOnSignSheetModel::GetStepDescription() const { - return l10n_util::GetStringUTF16(IDS_WEBAUTHN_USB_INSERT_DESCRIPTION); +base::string16 AuthenticatorInsertAndActivateUsbSheetModel::GetStepDescription() + const { + return l10n_util::GetStringUTF16(IDS_WEBAUTHN_USB_ACTIVATE_DESCRIPTION); } // AuthenticatorTimeoutErrorModel --------------------------------------------- @@ -190,11 +171,11 @@ } base::string16 AuthenticatorTimeoutErrorModel::GetStepTitle() const { - return l10n_util::GetStringUTF16(IDS_WEBAUTHN_TIMEOUT_TITLE); + return l10n_util::GetStringUTF16(IDS_WEBAUTHN_ERROR_GENERIC_TITLE); } base::string16 AuthenticatorTimeoutErrorModel::GetStepDescription() const { - return l10n_util::GetStringUTF16(IDS_WEBAUTHN_TIMEOUT_DESCRIPTION); + return l10n_util::GetStringUTF16(IDS_WEBAUTHN_ERROR_TIMEOUT_DESCRIPTION); } // AuthenticatorBlePowerOnManualSheetModel ------------------------------------ @@ -205,13 +186,14 @@ } base::string16 AuthenticatorBlePowerOnManualSheetModel::GetStepTitle() const { - return l10n_util::GetStringUTF16(IDS_WEBAUTHN_BLE_POWER_ON_MANUAL_TITLE); + return l10n_util::GetStringUTF16( + IDS_WEBAUTHN_BLUETOOTH_POWER_ON_MANUAL_TITLE); } base::string16 AuthenticatorBlePowerOnManualSheetModel::GetStepDescription() const { return l10n_util::GetStringUTF16( - IDS_WEBAUTHN_BLE_POWER_ON_MANUAL_DESCRIPTION); + IDS_WEBAUTHN_BLUETOOTH_POWER_ON_MANUAL_DESCRIPTION); } bool AuthenticatorBlePowerOnManualSheetModel::IsAcceptButtonVisible() const { @@ -224,7 +206,7 @@ base::string16 AuthenticatorBlePowerOnManualSheetModel::GetAcceptButtonLabel() const { - return l10n_util::GetStringUTF16(IDS_WEBAUTHN_BLE_POWER_ON_MANUAL_TRY_AGAIN); + return l10n_util::GetStringUTF16(IDS_WEBAUTHN_BLUETOOTH_POWER_ON_MANUAL_NEXT); } // AuthenticatorBlePairingBeginSheetModel ------------------------------------- @@ -253,7 +235,7 @@ base::string16 AuthenticatorBlePairingBeginSheetModel::GetAcceptButtonLabel() const { - return l10n_util::GetStringUTF16(IDS_WEBAUTHN_BLE_PAIRING_BEGIN_START); + return l10n_util::GetStringUTF16(IDS_WEBAUTHN_BLE_PAIRING_BEGIN_NEXT); } // AuthenticatorBleEnterPairingModeSheetModel --------------------------------- @@ -265,7 +247,11 @@ base::string16 AuthenticatorBleEnterPairingModeSheetModel::GetStepTitle() const { - return l10n_util::GetStringUTF16(IDS_WEBAUTHN_BLE_ENTER_PAIRING_MODE_TITLE); + // TODO(hongjunchoi): Insert actual domain name from model to + // |application_name|. + base::string16 application_name = base::UTF8ToUTF16("example.com"); + return l10n_util::GetStringFUTF16(IDS_WEBAUTHN_GENERIC_TITLE, + application_name); } base::string16 AuthenticatorBleEnterPairingModeSheetModel::GetStepDescription() @@ -348,7 +334,7 @@ // TODO(hongjunchoi): Insert actual domain name from model to // |application_name|. base::string16 application_name = base::UTF8ToUTF16("example.com"); - return l10n_util::GetStringFUTF16(IDS_WEBAUTHN_BLE_ACTIVATE_TITLE, + return l10n_util::GetStringFUTF16(IDS_WEBAUTHN_GENERIC_TITLE, application_name); }
diff --git a/chrome/browser/ui/webauthn/sheet_models.h b/chrome/browser/ui/webauthn/sheet_models.h index 4a81dedf..0f99534 100644 --- a/chrome/browser/ui/webauthn/sheet_models.h +++ b/chrome/browser/ui/webauthn/sheet_models.h
@@ -83,19 +83,7 @@ base::string16 GetStepDescription() const override; }; -class AuthenticatorInsertAndActivateUsbOnRegisterSheetModel - : public AuthenticatorSheetModelBase { - public: - using AuthenticatorSheetModelBase::AuthenticatorSheetModelBase; - - private: - // AuthenticatorSheetModelBase: - gfx::ImageSkia* GetStepIllustration() const override; - base::string16 GetStepTitle() const override; - base::string16 GetStepDescription() const override; -}; - -class AuthenticatorInsertAndActivateUsbOnSignSheetModel +class AuthenticatorInsertAndActivateUsbSheetModel : public AuthenticatorSheetModelBase { public: using AuthenticatorSheetModelBase::AuthenticatorSheetModelBase;
diff --git a/chrome/browser/ui/webui/chromeos/assistant_optin/assistant_optin_handler.cc b/chrome/browser/ui/webui/chromeos/assistant_optin/assistant_optin_handler.cc index a331fa8..2875d61 100644 --- a/chrome/browser/ui/webui/chromeos/assistant_optin/assistant_optin_handler.cc +++ b/chrome/browser/ui/webui/chromeos/assistant_optin/assistant_optin_handler.cc
@@ -158,7 +158,6 @@ base::Value GetSettingsUiStrings(const assistant::SettingsUi& settings_ui, bool activity_control_needed) { auto consent_ui = settings_ui.consent_flow_ui().consent_ui(); - auto confirm_reject_ui = consent_ui.activity_control_confirm_reject_ui(); auto activity_control_ui = consent_ui.activity_control_ui(); auto third_party_disclosure_ui = consent_ui.third_party_disclosure_ui(); base::Value dictionary(base::Value::Type::DICTIONARY); @@ -191,30 +190,6 @@ base::Value(consent_ui.reject_button_text())); } - // Add confirm reject screen string constants. - // TODO(updowndota) Use remote strings after server bug fixed. - dictionary.SetKey("confirmRejectTitle", - base::Value(l10n_util::GetStringUTF16( - IDS_ASSISTANT_CONFIRM_SCREEN_TITLE))); - dictionary.SetKey("confirmRejectAcceptTitle", - base::Value(l10n_util::GetStringUTF16( - IDS_ASSISTANT_CONFIRM_SCREEN_ACCEPT_TITLE))); - dictionary.SetKey("confirmRejectAcceptMessage", - base::Value(l10n_util::GetStringUTF16( - IDS_ASSISTANT_CONFIRM_SCREEN_ACCEPT_MESSAGE))); - dictionary.SetKey("confirmRejectAcceptMessageExpanded", - base::Value(l10n_util::GetStringUTF16( - IDS_ASSISTANT_CONFIRM_SCREEN_ACCEPT_MESSAGE_EXPANDED))); - dictionary.SetKey("confirmRejectRejectTitle", - base::Value(l10n_util::GetStringUTF16( - IDS_ASSISTANT_CONFIRM_SCREEN_REJECT_TITLE))); - dictionary.SetKey("confirmRejectRejectMessage", - base::Value(l10n_util::GetStringUTF16( - IDS_ASSISTANT_CONFIRM_SCREEN_REJECT_MESSAGE))); - dictionary.SetKey( - "confirmRejectContinueButton", - base::Value(l10n_util::GetStringUTF16(IDS_ASSISTANT_CONTINUE_BUTTON))); - // Add third party string constants. dictionary.SetKey("thirdPartyTitle", base::Value(l10n_util::GetStringUTF16( @@ -342,7 +317,6 @@ DCHECK(settings_ui.has_consent_flow_ui()); auto consent_ui = settings_ui.consent_flow_ui().consent_ui(); auto activity_control_ui = consent_ui.activity_control_ui(); - auto confirm_reject_ui = consent_ui.activity_control_confirm_reject_ui(); auto third_party_disclosure_ui = consent_ui.third_party_disclosure_ui(); consent_token_ = activity_control_ui.consent_token();
diff --git a/chrome/browser/ui/webui/chromeos/assistant_optin/assistant_optin_screen_exit_code.h b/chrome/browser/ui/webui/chromeos/assistant_optin/assistant_optin_screen_exit_code.h index 4098638..4903e12 100644 --- a/chrome/browser/ui/webui/chromeos/assistant_optin/assistant_optin_screen_exit_code.h +++ b/chrome/browser/ui/webui/chromeos/assistant_optin/assistant_optin_screen_exit_code.h
@@ -17,8 +17,6 @@ THIRD_PARTY_CONTINUED = 2, EMAIL_OPTED_IN = 3, EMAIL_OPTED_OUT = 4, - CONFIRM_ACCEPTED = 5, - CONFIRM_REJECTED = 6, EXIT_CODES_COUNT };
diff --git a/chrome/browser/ui/webui/chromeos/assistant_optin/assistant_optin_ui.cc b/chrome/browser/ui/webui/chromeos/assistant_optin/assistant_optin_ui.cc index d2244551..ca7ce752 100644 --- a/chrome/browser/ui/webui/chromeos/assistant_optin/assistant_optin_ui.cc +++ b/chrome/browser/ui/webui/chromeos/assistant_optin/assistant_optin_ui.cc
@@ -10,7 +10,6 @@ #include "base/macros.h" #include "chrome/browser/profiles/profile.h" #include "chrome/browser/profiles/profile_manager.h" -#include "chrome/browser/ui/webui/chromeos/assistant_optin/confirm_reject_screen_handler.h" #include "chrome/browser/ui/webui/chromeos/assistant_optin/get_more_screen_handler.h" #include "chrome/browser/ui/webui/chromeos/assistant_optin/ready_screen_handler.h" #include "chrome/browser/ui/webui/chromeos/assistant_optin/third_party_screen_handler.h" @@ -50,8 +49,6 @@ AddScreenHandler(std::make_unique<ValuePropScreenHandler>( base::BindOnce(&AssistantOptInUI::OnExit, weak_factory_.GetWeakPtr()))); - AddScreenHandler(std::make_unique<ConfirmRejectScreenHandler>( - base::BindOnce(&AssistantOptInUI::OnExit, weak_factory_.GetWeakPtr()))); AddScreenHandler(std::make_unique<ThirdPartyScreenHandler>( base::BindOnce(&AssistantOptInUI::OnExit, weak_factory_.GetWeakPtr()))); AddScreenHandler(std::make_unique<GetMoreScreenHandler>( @@ -85,17 +82,11 @@ void AssistantOptInUI::OnExit(AssistantOptInScreenExitCode exit_code) { switch (exit_code) { case AssistantOptInScreenExitCode::VALUE_PROP_SKIPPED: - assistant_handler_->ShowNextScreen(); + assistant_handler_->OnActivityControlOptInResult(false); break; case AssistantOptInScreenExitCode::VALUE_PROP_ACCEPTED: assistant_handler_->OnActivityControlOptInResult(true); break; - case AssistantOptInScreenExitCode::CONFIRM_ACCEPTED: - assistant_handler_->OnActivityControlOptInResult(true); - break; - case AssistantOptInScreenExitCode::CONFIRM_REJECTED: - assistant_handler_->OnActivityControlOptInResult(false); - break; case AssistantOptInScreenExitCode::THIRD_PARTY_CONTINUED: assistant_handler_->ShowNextScreen(); break;
diff --git a/chrome/browser/ui/webui/chromeos/assistant_optin/confirm_reject_screen_handler.cc b/chrome/browser/ui/webui/chromeos/assistant_optin/confirm_reject_screen_handler.cc deleted file mode 100644 index 821e080..0000000 --- a/chrome/browser/ui/webui/chromeos/assistant_optin/confirm_reject_screen_handler.cc +++ /dev/null
@@ -1,48 +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/ui/webui/chromeos/assistant_optin/confirm_reject_screen_handler.h" - -#include "chrome/browser/browser_process.h" -#include "chrome/grit/generated_resources.h" -#include "components/login/localized_values_builder.h" - -namespace { - -constexpr char kJsScreenPath[] = "AssistantConfirmRejectScreen"; - -} // namespace - -namespace chromeos { - -ConfirmRejectScreenHandler::ConfirmRejectScreenHandler( - OnAssistantOptInScreenExitCallback callback) - : BaseWebUIHandler(), exit_callback_(std::move(callback)) { - set_call_js_prefix(kJsScreenPath); -} - -ConfirmRejectScreenHandler::~ConfirmRejectScreenHandler() = default; - -void ConfirmRejectScreenHandler::DeclareLocalizedValues( - ::login::LocalizedValuesBuilder* builder) {} - -void ConfirmRejectScreenHandler::RegisterMessages() { - AddPrefixedCallback("userActed", - &ConfirmRejectScreenHandler::HandleUserAction); -} - -void ConfirmRejectScreenHandler::Initialize() {} - -void ConfirmRejectScreenHandler::HandleUserAction(bool confirm_result) { - DCHECK(exit_callback_); - if (confirm_result) { - std::move(exit_callback_) - .Run(AssistantOptInScreenExitCode::CONFIRM_ACCEPTED); - } else { - std::move(exit_callback_) - .Run(AssistantOptInScreenExitCode::CONFIRM_REJECTED); - } -} - -} // namespace chromeos
diff --git a/chrome/browser/ui/webui/chromeos/assistant_optin/confirm_reject_screen_handler.h b/chrome/browser/ui/webui/chromeos/assistant_optin/confirm_reject_screen_handler.h deleted file mode 100644 index b1022678..0000000 --- a/chrome/browser/ui/webui/chromeos/assistant_optin/confirm_reject_screen_handler.h +++ /dev/null
@@ -1,39 +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_UI_WEBUI_CHROMEOS_ASSISTANT_OPTIN_CONFIRM_REJECT_SCREEN_HANDLER_H_ -#define CHROME_BROWSER_UI_WEBUI_CHROMEOS_ASSISTANT_OPTIN_CONFIRM_REJECT_SCREEN_HANDLER_H_ - -#include <memory> -#include <string> - -#include "base/macros.h" -#include "chrome/browser/ui/webui/chromeos/assistant_optin/assistant_optin_screen_exit_code.h" -#include "chrome/browser/ui/webui/chromeos/login/base_webui_handler.h" - -namespace chromeos { - -class ConfirmRejectScreenHandler : public BaseWebUIHandler { - public: - explicit ConfirmRejectScreenHandler( - OnAssistantOptInScreenExitCallback callback); - ~ConfirmRejectScreenHandler() override; - - // BaseWebUIHandler: - void DeclareLocalizedValues( - ::login::LocalizedValuesBuilder* builder) override; - void RegisterMessages() override; - void Initialize() override; - - private: - void HandleUserAction(bool confirm_result); - - OnAssistantOptInScreenExitCallback exit_callback_; - - DISALLOW_COPY_AND_ASSIGN(ConfirmRejectScreenHandler); -}; - -} // namespace chromeos - -#endif // CHROME_BROWSER_UI_WEBUI_CHROMEOS_ASSISTANT_OPTIN_CONFIRM_REJECT_SCREEN_HANDLER_H_
diff --git a/chrome/browser/ui/webui/chromeos/assistant_optin/value_prop_screen_handler.cc b/chrome/browser/ui/webui/chromeos/assistant_optin/value_prop_screen_handler.cc index cd39e083..6b86834 100644 --- a/chrome/browser/ui/webui/chromeos/assistant_optin/value_prop_screen_handler.cc +++ b/chrome/browser/ui/webui/chromeos/assistant_optin/value_prop_screen_handler.cc
@@ -38,6 +38,8 @@ IDS_VOICE_INTERACTION_VALUE_PROP_LOAD_ERROR_TITLE); builder->Add("assistantOptinLoadErrorMessage", IDS_VOICE_INTERACTION_VALUE_PROP_LOAD_ERROR_MESSAGE); + builder->Add("assistantOptinSkipButton", + IDS_VOICE_INTERACTION_VALUE_PROP_SKIP_BUTTON); builder->Add("assistantOptinRetryButton", IDS_VOICE_INTERACTION_VALUE_PROP_RETRY_BUTTON); builder->Add("assistantOptinOKButton", IDS_OOBE_OK_BUTTON_TEXT);
diff --git a/chrome/browser/ui/webui/settings/chromeos/multidevice_handler.cc b/chrome/browser/ui/webui/settings/chromeos/multidevice_handler.cc index 7a93363..5cbb186a 100644 --- a/chrome/browser/ui/webui/settings/chromeos/multidevice_handler.cc +++ b/chrome/browser/ui/webui/settings/chromeos/multidevice_handler.cc
@@ -52,6 +52,10 @@ base::BindRepeating(&MultideviceHandler::HandleGetPageContent, base::Unretained(this))); web_ui()->RegisterMessageCallback( + "setFeatureEnabledState", + base::BindRepeating(&MultideviceHandler::HandleSetFeatureEnabledState, + base::Unretained(this))); + web_ui()->RegisterMessageCallback( "retryPendingHostSetup", base::BindRepeating(&MultideviceHandler::HandleRetryPendingHostSetup, base::Unretained(this))); @@ -131,6 +135,29 @@ callback_weak_ptr_factory_.GetWeakPtr(), callback_id)); } +void MultideviceHandler::HandleSetFeatureEnabledState( + const base::ListValue* args) { + std::string callback_id; + bool result = args->GetString(0, &callback_id); + DCHECK(result); + + int feature_as_int; + result = args->GetInteger(1, &feature_as_int); + DCHECK(result); + + auto feature = static_cast<multidevice_setup::mojom::Feature>(feature_as_int); + DCHECK(multidevice_setup::mojom::IsKnownEnumValue(feature)); + + bool enabled; + result = args->GetBoolean(2, &enabled); + DCHECK(result); + + multidevice_setup_client_->SetFeatureEnabledState( + feature, enabled, + base::BindOnce(&MultideviceHandler::OnSetFeatureStateEnabledResult, + callback_weak_ptr_factory_.GetWeakPtr(), callback_id)); +} + void MultideviceHandler::HandleRetryPendingHostSetup( const base::ListValue* args) { DCHECK(args->empty()); @@ -154,6 +181,12 @@ AttemptGetPageContentResponse(js_callback_id); } +void MultideviceHandler::OnSetFeatureStateEnabledResult( + const std::string& js_callback_id, + bool success) { + ResolveJavascriptCallback(base::Value(js_callback_id), base::Value(success)); +} + std::unique_ptr<base::DictionaryValue> MultideviceHandler::GeneratePageContentDataDictionary() { // Cannot generate page contents without all required data.
diff --git a/chrome/browser/ui/webui/settings/chromeos/multidevice_handler.h b/chrome/browser/ui/webui/settings/chromeos/multidevice_handler.h index 4f93a0eb..9bac8ea4 100644 --- a/chrome/browser/ui/webui/settings/chromeos/multidevice_handler.h +++ b/chrome/browser/ui/webui/settings/chromeos/multidevice_handler.h
@@ -53,6 +53,7 @@ void HandleShowMultiDeviceSetupDialog(const base::ListValue* args); void HandleGetPageContent(const base::ListValue* args); + void HandleSetFeatureEnabledState(const base::ListValue* args); void HandleRetryPendingHostSetup(const base::ListValue* args); void OnHostStatusFetched( @@ -63,6 +64,8 @@ const std::string& js_callback_id, const multidevice_setup::MultiDeviceSetupClient::FeatureStatesMap& feature_states_map); + void OnSetFeatureStateEnabledResult(const std::string& js_callback_id, + bool success); // Returns null if requisite data has not yet been fetched (i.e., if one or // both of |last_host_status_update_| and |last_feature_states_update_| is
diff --git a/chrome/browser/ui/webui/settings/chromeos/multidevice_handler_unittest.cc b/chrome/browser/ui/webui/settings/chromeos/multidevice_handler_unittest.cc index 363c22f..2b047874 100644 --- a/chrome/browser/ui/webui/settings/chromeos/multidevice_handler_unittest.cc +++ b/chrome/browser/ui/webui/settings/chromeos/multidevice_handler_unittest.cc
@@ -192,6 +192,33 @@ success); } + void CallSetFeatureEnabledState(multidevice_setup::mojom::Feature feature, + bool enabled, + bool success) { + size_t call_data_count_before_call = test_web_ui()->call_data().size(); + + base::ListValue args; + args.AppendString("handlerFunctionName"); + args.AppendInteger(static_cast<int>(feature)); + args.AppendBoolean(enabled); + + base::ListValue empty_args; + test_web_ui()->HandleReceivedMessage("setFeatureEnabledState", &args); + fake_multidevice_setup_client() + ->InvokePendingSetFeatureEnabledStateCallback( + feature /* expected_feature */, enabled /* expected_enabled */, + success); + + EXPECT_EQ(call_data_count_before_call + 1u, + test_web_ui()->call_data().size()); + const content::TestWebUI::CallData& call_data = + CallDataAtIndex(call_data_count_before_call); + EXPECT_EQ("cr.webUIResponse", call_data.function_name()); + EXPECT_EQ("handlerFunctionName", call_data.arg1()->GetString()); + EXPECT_TRUE(call_data.arg2()->GetBool()); + EXPECT_EQ(success, call_data.arg3()->GetBool()); + } + const content::TestWebUI::CallData& CallDataAtIndex(size_t index) { return *test_web_ui_->call_data()[index]; } @@ -271,6 +298,18 @@ CallRetryPendingHostSetup(false /* success */); } +TEST_F(MultideviceHandlerTest, SetFeatureEnabledState) { + CallSetFeatureEnabledState( + multidevice_setup::mojom::Feature::kBetterTogetherSuite, + true /* enabled */, true /* success */); + CallSetFeatureEnabledState( + multidevice_setup::mojom::Feature::kBetterTogetherSuite, + false /* enabled */, false /* success */); + CallSetFeatureEnabledState( + multidevice_setup::mojom::Feature::kBetterTogetherSuite, + false /* enabled */, true /* success */); +} + } // namespace settings } // namespace chromeos
diff --git a/chrome/browser/vr/BUILD.gn b/chrome/browser/vr/BUILD.gn index 102639e..03d4129 100644 --- a/chrome/browser/vr/BUILD.gn +++ b/chrome/browser/vr/BUILD.gn
@@ -224,6 +224,7 @@ "fps_meter.h", "gesture_detector.cc", "gesture_detector.h", + "platform_controller.h", "render_loop.cc", "render_loop.h", "render_loop_browser_interface.h", @@ -325,7 +326,6 @@ "model/toolbar_state.h", "model/ui_mode.h", "model/web_vr_model.h", - "platform_controller.h", "platform_input_handler.h", "platform_ui_input_delegate.cc", "platform_ui_input_delegate.h",
diff --git a/chrome/browser/vr/content_input_delegate.cc b/chrome/browser/vr/content_input_delegate.cc index c8fe916..04b5cc6 100644 --- a/chrome/browser/vr/content_input_delegate.cc +++ b/chrome/browser/vr/content_input_delegate.cc
@@ -6,7 +6,6 @@ #include "base/callback_helpers.h" #include "base/time/time.h" -#include "chrome/browser/vr/platform_controller.h" #include "chrome/browser/vr/platform_input_handler.h" namespace vr {
diff --git a/chrome/browser/vr/controller_delegate_for_testing.cc b/chrome/browser/vr/controller_delegate_for_testing.cc index 6d2c5f95..67ee0ff 100644 --- a/chrome/browser/vr/controller_delegate_for_testing.cc +++ b/chrome/browser/vr/controller_delegate_for_testing.cc
@@ -57,23 +57,23 @@ case VrControllerTestAction::kClick: // Add in the button down action. controller_model.touchpad_button_state = - PlatformController::ButtonState::kDown; + ControllerModel::ButtonState::kDown; controller_model_queue_.push(controller_model); // Add in the button up action. controller_model.touchpad_button_state = - PlatformController::ButtonState::kUp; + ControllerModel::ButtonState::kUp; controller_model_queue_.push(controller_model); break; case VrControllerTestAction::kHover: FALLTHROUGH; case VrControllerTestAction::kClickUp: controller_model.touchpad_button_state = - PlatformController::ButtonState::kUp; + ControllerModel::ButtonState::kUp; controller_model_queue_.push(controller_model); break; case VrControllerTestAction::kClickDown: controller_model.touchpad_button_state = - PlatformController::ButtonState::kDown; + ControllerModel::ButtonState::kDown; controller_model_queue_.push(controller_model); break; case VrControllerTestAction::kMove:
diff --git a/chrome/browser/vr/gesture_detector_unittest.cc b/chrome/browser/vr/gesture_detector_unittest.cc index 736e680..4a75ca26 100644 --- a/chrome/browser/vr/gesture_detector_unittest.cc +++ b/chrome/browser/vr/gesture_detector_unittest.cc
@@ -73,8 +73,8 @@ return base::TimeTicks(); } - vr::PlatformController::Handedness GetHandedness() const override { - return vr::PlatformController::kRightHanded; + vr::ControllerModel::Handedness GetHandedness() const override { + return vr::ControllerModel::kRightHanded; } bool GetRecentered() const override { return false; }
diff --git a/chrome/browser/vr/model/controller_model.h b/chrome/browser/vr/model/controller_model.h index 8011339..c01b285 100644 --- a/chrome/browser/vr/model/controller_model.h +++ b/chrome/browser/vr/model/controller_model.h
@@ -6,7 +6,6 @@ #define CHROME_BROWSER_VR_MODEL_CONTROLLER_MODEL_H_ #include "base/time/time.h" -#include "chrome/browser/vr/platform_controller.h" #include "chrome/browser/vr/vr_export.h" #include "ui/gfx/geometry/point3_f.h" #include "ui/gfx/transform.h" @@ -18,6 +17,16 @@ // UiInputManager (for generating gestures), and by the UI for rendering the // controller. struct VR_EXPORT ControllerModel { + enum ButtonState { + kUp, + kDown, + }; + + enum Handedness { + kRightHanded, + kLeftHanded, + }; + ControllerModel(); ControllerModel(const ControllerModel& other); ~ControllerModel(); @@ -25,18 +34,15 @@ gfx::Transform transform; gfx::Vector3dF laser_direction; gfx::Point3F laser_origin; - PlatformController::ButtonState touchpad_button_state = - PlatformController::ButtonState::kUp; - PlatformController::ButtonState app_button_state = - PlatformController::ButtonState::kUp; - PlatformController::ButtonState home_button_state = - PlatformController::ButtonState::kUp; + ButtonState touchpad_button_state = kUp; + ButtonState app_button_state = kUp; + ButtonState home_button_state = kUp; bool touching_touchpad = false; gfx::PointF touchpad_touch_position; float opacity = 1.0f; bool resting_in_viewport = false; bool recentered = false; - PlatformController::Handedness handedness = PlatformController::kRightHanded; + Handedness handedness = kRightHanded; base::TimeTicks last_orientation_timestamp; base::TimeTicks last_button_timestamp; int battery_level = 0;
diff --git a/chrome/browser/vr/platform_controller.h b/chrome/browser/vr/platform_controller.h index 7e1e294..7b5921f 100644 --- a/chrome/browser/vr/platform_controller.h +++ b/chrome/browser/vr/platform_controller.h
@@ -6,6 +6,7 @@ #define CHROME_BROWSER_VR_PLATFORM_CONTROLLER_H_ #include "base/time/time.h" +#include "chrome/browser/vr/model/controller_model.h" #include "chrome/browser/vr/vr_export.h" namespace gfx { @@ -30,16 +31,6 @@ kButtonTypeNumber, }; - enum ButtonState { - kUp, - kDown, - }; - - enum Handedness { - kRightHanded, - kLeftHanded, - }; - virtual ~PlatformController() {} virtual bool IsButtonDown(ButtonType type) const = 0; @@ -50,7 +41,7 @@ virtual base::TimeTicks GetLastOrientationTimestamp() const = 0; virtual base::TimeTicks GetLastTouchTimestamp() const = 0; virtual base::TimeTicks GetLastButtonTimestamp() const = 0; - virtual Handedness GetHandedness() const = 0; + virtual ControllerModel::Handedness GetHandedness() const = 0; virtual bool GetRecentered() const = 0; virtual int GetBatteryLevel() const = 0; };
diff --git a/chrome/browser/vr/platform_ui_input_delegate.cc b/chrome/browser/vr/platform_ui_input_delegate.cc index 601273cc4..4b609a1 100644 --- a/chrome/browser/vr/platform_ui_input_delegate.cc +++ b/chrome/browser/vr/platform_ui_input_delegate.cc
@@ -6,7 +6,6 @@ #include "base/callback_helpers.h" #include "base/time/time.h" -#include "chrome/browser/vr/platform_controller.h" #include "chrome/browser/vr/platform_input_handler.h" namespace vr {
diff --git a/chrome/browser/vr/service/xr_device_impl.cc b/chrome/browser/vr/service/xr_device_impl.cc index c53bb26..f044f4c 100644 --- a/chrome/browser/vr/service/xr_device_impl.cc +++ b/chrome/browser/vr/service/xr_device_impl.cc
@@ -249,7 +249,12 @@ void XRDeviceImpl::SetListeningForActivate( device::mojom::VRDisplayClientPtr client) { client_ = std::move(client); - if (immersive_runtime_ && client) { + if (!immersive_runtime_) { + // This function sets the runtimes. + GetCurrentVRDisplayInfo(); + } + + if (immersive_runtime_ && client_) { immersive_runtime_->UpdateListeningForActivate(this); } } @@ -265,6 +270,7 @@ void XRDeviceImpl::SetInFocusedFrame(bool in_focused_frame) { in_focused_frame_ = in_focused_frame; + if (ListeningForActivate() && immersive_runtime_) { // No change, except focus. immersive_runtime_->UpdateListeningForActivate(this);
diff --git a/chrome/browser/vr/test/ui_pixel_test.cc b/chrome/browser/vr/test/ui_pixel_test.cc index c65e78d..884214d 100644 --- a/chrome/browser/vr/test/ui_pixel_test.cc +++ b/chrome/browser/vr/test/ui_pixel_test.cc
@@ -63,7 +63,7 @@ void UiPixelTest::DrawUi(const gfx::Vector3dF& laser_direction, const gfx::Point3F& laser_origin, - PlatformController::ButtonState button_state, + ControllerModel::ButtonState button_state, float controller_opacity, const gfx::Transform& controller_transform, const gfx::Transform& view_matrix, @@ -74,8 +74,8 @@ controller_model.opacity = controller_opacity; controller_model.laser_origin = laser_origin; controller_model.touchpad_button_state = button_state; - controller_model.app_button_state = PlatformController::ButtonState::kUp; - controller_model.home_button_state = PlatformController::ButtonState::kUp; + controller_model.app_button_state = ControllerModel::ButtonState::kUp; + controller_model.home_button_state = ControllerModel::ButtonState::kUp; RenderInfo render_info; render_info.head_pose = view_matrix; render_info.left_eye_model.view_matrix = view_matrix;
diff --git a/chrome/browser/vr/test/ui_pixel_test.h b/chrome/browser/vr/test/ui_pixel_test.h index f62c29a0..e9c6119 100644 --- a/chrome/browser/vr/test/ui_pixel_test.h +++ b/chrome/browser/vr/test/ui_pixel_test.h
@@ -30,7 +30,7 @@ const ToolbarState& toolbar_state); void DrawUi(const gfx::Vector3dF& laser_direction, const gfx::Point3F& laser_origin, - PlatformController::ButtonState button_state, + ControllerModel::ButtonState button_state, float controller_opacity, const gfx::Transform& controller_transform, const gfx::Transform& view_matrix,
diff --git a/chrome/browser/vr/test/ui_test.cc b/chrome/browser/vr/test/ui_test.cc index 79f753d..886d9d5 100644 --- a/chrome/browser/vr/test/ui_test.cc +++ b/chrome/browser/vr/test/ui_test.cc
@@ -251,14 +251,13 @@ controller_model.laser_direction = direction; controller_model.laser_origin = origin; - controller_model.touchpad_button_state = - PlatformController::ButtonState::kDown; + controller_model.touchpad_button_state = ControllerModel::ButtonState::kDown; ui_instance_->input_manager()->HandleInput(current_time_, render_info, controller_model, &reticle_model, &input_event_list); OnBeginFrame(); - controller_model.touchpad_button_state = PlatformController::ButtonState::kUp; + controller_model.touchpad_button_state = ControllerModel::ButtonState::kUp; ui_instance_->input_manager()->HandleInput(current_time_, render_info, controller_model, &reticle_model, &input_event_list);
diff --git a/chrome/browser/vr/testapp/vr_test_context.cc b/chrome/browser/vr/testapp/vr_test_context.cc index 5205d5a..d47689e 100644 --- a/chrome/browser/vr/testapp/vr_test_context.cc +++ b/chrome/browser/vr/testapp/vr_test_context.cc
@@ -228,9 +228,9 @@ } break; case ui::DomCode::US_H: - handedness_ = handedness_ == PlatformController::kRightHanded - ? PlatformController::kLeftHanded - : PlatformController::kRightHanded; + handedness_ = handedness_ == ControllerModel::kRightHanded + ? ControllerModel::kLeftHanded + : ControllerModel::kRightHanded; break; case ui::DomCode::US_I: incognito_ = !incognito_; @@ -415,8 +415,8 @@ ControllerModel controller_model; controller_model.touchpad_button_state = - touchpad_pressed_ ? PlatformController::ButtonState::kDown - : PlatformController::ButtonState::kUp; + touchpad_pressed_ ? ControllerModel::ButtonState::kDown + : ControllerModel::ButtonState::kUp; controller_model.touchpad_touch_position = touchpad_touch_position_; controller_model.touching_touchpad = touching_touchpad_; controller_model.recentered = recentered_; @@ -796,7 +796,7 @@ gfx::Point3F VrTestContext::LaserOrigin() const { gfx::Point3F origin = kDefaultLaserOrigin; - if (handedness_ == PlatformController::kLeftHanded) { + if (handedness_ == ControllerModel::kLeftHanded) { origin.set_x(-origin.x()); } return origin;
diff --git a/chrome/browser/vr/testapp/vr_test_context.h b/chrome/browser/vr/testapp/vr_test_context.h index 4c4fdd4..333641e5 100644 --- a/chrome/browser/vr/testapp/vr_test_context.h +++ b/chrome/browser/vr/testapp/vr_test_context.h
@@ -120,7 +120,7 @@ CompositorDelegate* compositor_delegate_; TestKeyboardDelegate* keyboard_delegate_; - PlatformController::Handedness handedness_ = PlatformController::kRightHanded; + ControllerModel::Handedness handedness_ = ControllerModel::kRightHanded; std::queue<InputEventList> input_event_lists_;
diff --git a/chrome/browser/vr/ui.h b/chrome/browser/vr/ui.h index de54a5a..1621bd5 100644 --- a/chrome/browser/vr/ui.h +++ b/chrome/browser/vr/ui.h
@@ -16,7 +16,6 @@ #include "chrome/browser/vr/assets_load_status.h" #include "chrome/browser/vr/browser_ui_interface.h" #include "chrome/browser/vr/model/tab_model.h" -#include "chrome/browser/vr/platform_controller.h" #include "chrome/browser/vr/ui_element_renderer.h" #include "chrome/browser/vr/ui_initial_state.h" #include "chrome/browser/vr/ui_interface.h"
diff --git a/chrome/browser/vr/ui_input_manager.cc b/chrome/browser/vr/ui_input_manager.cc index f09ee00b..f03011a3 100644 --- a/chrome/browser/vr/ui_input_manager.cc +++ b/chrome/browser/vr/ui_input_manager.cc
@@ -11,7 +11,6 @@ #include "base/memory/ptr_util.h" #include "chrome/browser/vr/elements/ui_element.h" #include "chrome/browser/vr/input_event.h" -#include "chrome/browser/vr/model/controller_model.h" #include "chrome/browser/vr/model/reticle_model.h" #include "chrome/browser/vr/model/text_input_info.h" #include "chrome/browser/vr/render_info.h" @@ -155,10 +154,9 @@ fling_target_id_ = 0; } -void UiInputManager::SendScrollEnd( - InputEventList* input_event_list, - const gfx::PointF& target_point, - PlatformController::ButtonState button_state) { +void UiInputManager::SendScrollEnd(InputEventList* input_event_list, + const gfx::PointF& target_point, + ControllerModel::ButtonState button_state) { if (!in_scroll_) { return; } @@ -166,7 +164,7 @@ UiElement* element = scene_->GetUiElementById(input_capture_element_id_); if (previous_button_state_ != button_state && - button_state == PlatformController::ButtonState::kDown) { + button_state == ControllerModel::ButtonState::kDown) { DCHECK_GT(input_event_list->size(), 0LU); DCHECK_EQ(input_event_list->front()->type(), InputEvent::kScrollEnd); } @@ -245,10 +243,10 @@ } void UiInputManager::SendButtonUp(const gfx::PointF& target_point, - PlatformController::ButtonState button_state, + ControllerModel::ButtonState button_state, base::TimeTicks timestamp) { if (!in_click_ || previous_button_state_ == button_state || - button_state != PlatformController::ButtonState::kUp) { + button_state != ControllerModel::ButtonState::kUp) { return; } in_click_ = false; @@ -265,13 +263,12 @@ input_capture_element_id_ = 0; } -void UiInputManager::SendButtonDown( - UiElement* target, - const gfx::PointF& target_point, - PlatformController::ButtonState button_state, - base::TimeTicks timestamp) { +void UiInputManager::SendButtonDown(UiElement* target, + const gfx::PointF& target_point, + ControllerModel::ButtonState button_state, + base::TimeTicks timestamp) { if (previous_button_state_ == button_state || - button_state != PlatformController::ButtonState::kDown) { + button_state != ControllerModel::ButtonState::kDown) { return; } in_click_ = true;
diff --git a/chrome/browser/vr/ui_input_manager.h b/chrome/browser/vr/ui_input_manager.h index d9e047d1..8d529a0 100644 --- a/chrome/browser/vr/ui_input_manager.h +++ b/chrome/browser/vr/ui_input_manager.h
@@ -9,7 +9,7 @@ #include <vector> #include "base/time/time.h" -#include "chrome/browser/vr/platform_controller.h" +#include "chrome/browser/vr/model/controller_model.h" #include "chrome/browser/vr/vr_ui_export.h" #include "ui/gfx/geometry/point3_f.h" #include "ui/gfx/geometry/point_f.h" @@ -21,7 +21,6 @@ class UiScene; class UiElement; class InputEvent; -struct ControllerModel; struct RenderInfo; struct ReticleModel; struct EditedText; @@ -71,7 +70,7 @@ const gfx::PointF& target_point); void SendScrollEnd(InputEventList* input_event_list, const gfx::PointF& target_point, - PlatformController::ButtonState button_state); + ControllerModel::ButtonState button_state); void SendScrollBegin(UiElement* target, InputEventList* input_event_list, const gfx::PointF& target_point); @@ -87,11 +86,11 @@ base::TimeTicks timestamp); void SendButtonUp(const gfx::PointF& target_point, - PlatformController::ButtonState button_state, + ControllerModel::ButtonState button_state, base::TimeTicks timestamp); void SendButtonDown(UiElement* target, const gfx::PointF& target_point, - PlatformController::ButtonState button_state, + ControllerModel::ButtonState button_state, base::TimeTicks timestamp); void SendTouchMove(const gfx::PointF& target_point, base::TimeTicks timestamp); @@ -121,8 +120,8 @@ HitTestStrategy hit_test_strategy_ = HitTestStrategy::PROJECT_TO_WORLD_ORIGIN; - PlatformController::ButtonState previous_button_state_ = - PlatformController::ButtonState::kUp; + ControllerModel::ButtonState previous_button_state_ = + ControllerModel::ButtonState::kUp; base::TimeTicks last_controller_outside_viewport_time_; bool controller_resting_in_viewport_ = false;
diff --git a/chrome/browser/vr/ui_input_manager_unittest.cc b/chrome/browser/vr/ui_input_manager_unittest.cc index df15beb..b0d3ed00 100644 --- a/chrome/browser/vr/ui_input_manager_unittest.cc +++ b/chrome/browser/vr/ui_input_manager_unittest.cc
@@ -35,10 +35,9 @@ namespace { -constexpr PlatformController::ButtonState kUp = - PlatformController::ButtonState::kUp; -constexpr PlatformController::ButtonState kDown = - PlatformController::ButtonState::kDown; +constexpr ControllerModel::ButtonState kUp = ControllerModel::ButtonState::kUp; +constexpr ControllerModel::ButtonState kDown = + ControllerModel::ButtonState::kDown; constexpr gfx::Size kWindowSize = {1280, 720}; @@ -118,13 +117,13 @@ } void HandleInput(const gfx::Vector3dF& laser_direction, - PlatformController::ButtonState button_state) { + ControllerModel::ButtonState button_state) { HandleInput({0, 0, 0}, laser_direction, button_state); } void HandleInput(const gfx::Point3F& laser_origin, const gfx::Vector3dF& laser_direction, - PlatformController::ButtonState button_state) { + ControllerModel::ButtonState button_state) { RenderInfo render_info; controller_model_.laser_direction = laser_direction; controller_model_.laser_origin = laser_origin; @@ -504,8 +503,7 @@ ControllerModel controller_model; controller_model.laser_direction = content_quad_center - origin; controller_model.laser_origin = origin; - controller_model.touchpad_button_state = - PlatformController::ButtonState::kDown; + controller_model.touchpad_button_state = ControllerModel::ButtonState::kDown; ReticleModel reticle_model; InputEventList input_event_list; input_manager_->HandleInput(MsToTicks(1), RenderInfo(), controller_model, @@ -536,8 +534,7 @@ ControllerModel controller_model; controller_model.laser_direction = url_bar_center - origin; controller_model.laser_origin = origin; - controller_model.touchpad_button_state = - PlatformController::ButtonState::kDown; + controller_model.touchpad_button_state = ControllerModel::ButtonState::kDown; ReticleModel reticle_model; InputEventList input_event_list; input_manager_->HandleInput(MsToTicks(1), RenderInfo(), controller_model, @@ -563,8 +560,7 @@ ControllerModel controller_model; controller_model.laser_direction = content_quad_center - origin; controller_model.laser_origin = origin; - controller_model.touchpad_button_state = - PlatformController::ButtonState::kDown; + controller_model.touchpad_button_state = ControllerModel::ButtonState::kDown; ReticleModel reticle_model; InputEventList input_event_list; input_manager_->HandleInput(MsToTicks(1), RenderInfo(), controller_model,
diff --git a/chrome/browser/vr/ui_pixeltest.cc b/chrome/browser/vr/ui_pixeltest.cc index 89c3c5d..2d29e12 100644 --- a/chrome/browser/vr/ui_pixeltest.cc +++ b/chrome/browser/vr/ui_pixeltest.cc
@@ -37,7 +37,7 @@ // Draw UI. DrawUi(gfx::Vector3dF(0.0f, 0.0f, -1.0f), gfx::Point3F(0.5f, -0.5f, 0.0f), - PlatformController::ButtonState::kUp, 1.0f, kIdentity, kIdentity, + ControllerModel::ButtonState::kUp, 1.0f, kIdentity, kIdentity, GetPixelDaydreamProjMatrix()); // Read pixels into SkBitmap.
diff --git a/chrome/browser/vr/ui_scene_creator.cc b/chrome/browser/vr/ui_scene_creator.cc index a6000070..db9318a 100644 --- a/chrome/browser/vr/ui_scene_creator.cc +++ b/chrome/browser/vr/ui_scene_creator.cc
@@ -562,15 +562,15 @@ layout->set_contributes_to_parent_bounds(false); layout->AddBinding(VR_BIND_FUNC( LayoutAlignment, Model, model, - model->controller.handedness == PlatformController::kRightHanded ? LEFT - : RIGHT, + model->controller.handedness == ControllerModel::kRightHanded ? LEFT + : RIGHT, LinearLayout, layout.get(), set_x_centering)); - layout->AddBinding(VR_BIND_FUNC( - LinearLayout::Direction, Model, model, - model->controller.handedness == PlatformController::kRightHanded - ? LinearLayout::kRight - : LinearLayout::kLeft, - LinearLayout, layout.get(), set_direction)); + layout->AddBinding( + VR_BIND_FUNC(LinearLayout::Direction, Model, model, + model->controller.handedness == ControllerModel::kRightHanded + ? LinearLayout::kRight + : LinearLayout::kLeft, + LinearLayout, layout.get(), set_direction)); auto spacer = std::make_unique<UiElement>(); spacer->SetType(kTypeSpacer); @@ -624,7 +624,7 @@ touchpad_button->AddBinding( VR_BIND_FUNC(SkColor, Model, model, model->controller.touchpad_button_state == - PlatformController::ButtonState::kDown + ControllerModel::ButtonState::kDown ? model->color_scheme().controller_button_down : model->color_scheme().controller_button, Rect, touchpad_button.get(), SetColor)); @@ -637,13 +637,12 @@ app_button->SetSize(kControllerSmallButtonSize, kControllerSmallButtonSize); app_button->SetRotate(1, 0, 0, -base::kPiFloat / 2); app_button->SetTranslate(0.0f, 0.0f, kControllerAppButtonZ); - app_button->AddBinding( - VR_BIND_FUNC(SkColor, Model, model, - model->controller.app_button_state == - PlatformController::ButtonState::kDown - ? model->color_scheme().controller_button_down - : model->color_scheme().controller_button, - VectorIcon, app_button.get(), SetColor)); + app_button->AddBinding(VR_BIND_FUNC( + SkColor, Model, model, + model->controller.app_button_state == ControllerModel::ButtonState::kDown + ? model->color_scheme().controller_button_down + : model->color_scheme().controller_button, + VectorIcon, app_button.get(), SetColor)); controller->AddChild(std::move(app_button)); auto home_button = @@ -653,13 +652,12 @@ home_button->SetSize(kControllerSmallButtonSize, kControllerSmallButtonSize); home_button->SetRotate(1, 0, 0, -base::kPiFloat / 2); home_button->SetTranslate(0.0f, 0.0f, kControllerHomeButtonZ); - home_button->AddBinding( - VR_BIND_FUNC(SkColor, Model, model, - model->controller.home_button_state == - PlatformController::ButtonState::kDown - ? model->color_scheme().controller_button_down - : model->color_scheme().controller_button, - VectorIcon, home_button.get(), SetColor)); + home_button->AddBinding(VR_BIND_FUNC( + SkColor, Model, model, + model->controller.home_button_state == ControllerModel::ButtonState::kDown + ? model->color_scheme().controller_button_down + : model->color_scheme().controller_button, + VectorIcon, home_button.get(), SetColor)); controller->AddChild(std::move(home_button)); auto battery_layout =
diff --git a/chrome/browser/web_applications/components/web_app_helpers.cc b/chrome/browser/web_applications/components/web_app_helpers.cc index 55e3c63..6e402962 100644 --- a/chrome/browser/web_applications/components/web_app_helpers.cc +++ b/chrome/browser/web_applications/components/web_app_helpers.cc
@@ -4,7 +4,10 @@ #include "chrome/browser/web_applications/components/web_app_helpers.h" +#include "base/base64.h" #include "base/strings/strcat.h" +#include "components/crx_file/id_util.h" +#include "crypto/sha2.h" #include "url/gurl.h" namespace web_app { @@ -34,4 +37,29 @@ return app_name.substr(prefix.length()); } +static std::string GenerateExtensionHashFromURL(const GURL& url) { + return crypto::SHA256HashString(url.spec()); +} + +std::string GenerateExtensionIdFromURL(const GURL& url) { + return crx_file::id_util::GenerateId(GenerateExtensionHashFromURL(url)); +} + +// Generate the public key for the fake extension that we synthesize to contain +// a web app. +// +// Web apps are not signed, but the public key for an extension doubles as +// its unique identity, and we need one of those. A web app's unique identity +// is its manifest URL, so we hash that (*) to create a public key. There will +// be no corresponding private key, which means that these extensions cannot be +// auto-updated using ExtensionUpdater. +// +// (*) The comment above says that we hash the manifest URL, but in practice, +// it seems that we hash the start URL. +std::string GenerateExtensionKeyFromURL(const GURL& url) { + std::string key; + base::Base64Encode(GenerateExtensionHashFromURL(url), &key); + return key; +} + } // namespace web_app
diff --git a/chrome/browser/web_applications/components/web_app_helpers.h b/chrome/browser/web_applications/components/web_app_helpers.h index 642e9e3..e7b81cc 100644 --- a/chrome/browser/web_applications/components/web_app_helpers.h +++ b/chrome/browser/web_applications/components/web_app_helpers.h
@@ -22,6 +22,21 @@ // Extracts the application id from the app name. std::string GetAppIdFromApplicationName(const std::string& app_name); +// Compute the Extension ID (such as "fedbieoalmbobgfjapopkghdmhgncnaa") or +// Extension Key, from a web app's URL. Both are derived from a hash of the +// URL, but are subsequently encoded differently, for historical reasons. The +// ID is a Base-16 encoded (a=0, b=1, ..., p=15) subset of the hash, and is +// used as a directory name, sometimes on case-insensitive file systems +// (Windows). The Key is a Base-64 encoding of the hash. +// +// For PWAs (progressive web apps), the URL should be the Start URL, explicitly +// listed in the manifest. +// +// For non-PWA web apps, also known as "bookmark apps", the URL is just the +// bookmark URL. +std::string GenerateExtensionIdFromURL(const GURL& url); +std::string GenerateExtensionKeyFromURL(const GURL& url); + } // namespace web_app #endif // CHROME_BROWSER_WEB_APPLICATIONS_COMPONENTS_WEB_APP_HELPERS_H_
diff --git a/chrome/browser/web_applications/components/web_app_helpers_unittest.cc b/chrome/browser/web_applications/components/web_app_helpers_unittest.cc index fb881320..0a4a85e 100644 --- a/chrome/browser/web_applications/components/web_app_helpers_unittest.cc +++ b/chrome/browser/web_applications/components/web_app_helpers_unittest.cc
@@ -19,4 +19,17 @@ GenerateApplicationNameFromURL(GURL("https://example.com/path"))); } +TEST(WebAppHelpers, GenerateExtensionIdFromURL) { + EXPECT_EQ("fedbieoalmbobgfjapopkghdmhgncnaa", + GenerateExtensionIdFromURL( + GURL("https://www.chromestatus.com/features"))); + + // The io2016 example is also walked through at + // https://play.golang.org/p/VrIq_QKFjiV + EXPECT_EQ( + "mjgafbdfajpigcjmkgmeokfbodbcfijl", + GenerateExtensionIdFromURL(GURL( + "https://events.google.com/io2016/?utm_source=web_app_manifest"))); +} + } // namespace web_app
diff --git a/chrome/browser/webauthn/authenticator_request_dialog_model.cc b/chrome/browser/webauthn/authenticator_request_dialog_model.cc index 82dc77c5..4f25b871 100644 --- a/chrome/browser/webauthn/authenticator_request_dialog_model.cc +++ b/chrome/browser/webauthn/authenticator_request_dialog_model.cc
@@ -37,7 +37,7 @@ DCHECK_EQ(current_step(), Step::kTransportSelection); switch (transport) { case AuthenticatorTransport::kUsb: - SetCurrentStep(Step::kUsbInsertAndActivateOnRegister); + SetCurrentStep(Step::kUsbInsertAndActivate); break; case AuthenticatorTransport::kBluetoothLowEnergy: SetCurrentStep(Step::kBlePowerOnManual); @@ -73,7 +73,7 @@ } void AuthenticatorRequestDialogModel::TryUsbDevice() { - DCHECK_EQ(current_step(), Step::kUsbInsertAndActivateOnRegister); + DCHECK_EQ(current_step(), Step::kUsbInsertAndActivate); } void AuthenticatorRequestDialogModel::TryTouchId() { @@ -86,10 +86,10 @@ } void AuthenticatorRequestDialogModel::Back() { - if (current_step() == Step::kInitial) { + if (current_step() == Step::kWelcomeScreen) { Cancel(); } else { - SetCurrentStep(Step::kInitial); + SetCurrentStep(Step::kWelcomeScreen); } }
diff --git a/chrome/browser/webauthn/authenticator_request_dialog_model.h b/chrome/browser/webauthn/authenticator_request_dialog_model.h index 630de4ef..6168d6bf 100644 --- a/chrome/browser/webauthn/authenticator_request_dialog_model.h +++ b/chrome/browser/webauthn/authenticator_request_dialog_model.h
@@ -24,14 +24,13 @@ public: // Defines the potential steps of the Web Authentication API request UX flow. enum class Step { - kInitial, + kWelcomeScreen, kTransportSelection, kErrorTimedOut, kCompleted, // Universal Serial Bus (USB). - kUsbInsertAndActivateOnRegister, - kUsbInsertAndActivateOnSign, + kUsbInsertAndActivate, // Bluetooth Low Energy (BLE). kBlePowerOnAutomatic, @@ -159,7 +158,7 @@ private: // The current step of the request UX flow that is currently shown. - Step current_step_ = Step::kInitial; + Step current_step_ = Step::kWelcomeScreen; TransportListModel transport_list_model_; base::ObserverList<Observer> observers_;
diff --git a/chrome/browser/webauthn/chrome_authenticator_request_delegate.cc b/chrome/browser/webauthn/chrome_authenticator_request_delegate.cc index 7e873ca..7bc45df2 100644 --- a/chrome/browser/webauthn/chrome_authenticator_request_delegate.cc +++ b/chrome/browser/webauthn/chrome_authenticator_request_delegate.cc
@@ -63,6 +63,13 @@ switches::kWebAuthenticationUI); } +bool ShouldDispatchRequestImmediately( + const device::FidoAuthenticator& authenticator) { + // TODO(hongjunchoi): Change this so that requests for BLE and platform + // authenticators are not dispatched immediately if WebAuthN UI is enabled. + return true; +} + #if !defined(OS_ANDROID) void SetInitialUiModelBasedOnPreviouslyUsedTransport( AuthenticatorRequestDialogModel* model, @@ -74,8 +81,8 @@ // TouchID transports. switch (*previous_transport) { case device::FidoTransportProtocol::kUsbHumanInterfaceDevice: - model->SetCurrentStep(AuthenticatorRequestDialogModel::Step:: - kUsbInsertAndActivateOnRegister); + model->SetCurrentStep( + AuthenticatorRequestDialogModel::Step::kUsbInsertAndActivate); break; default: return; @@ -142,23 +149,11 @@ ->GetBrowserContext(); } -void ChromeAuthenticatorRequestDelegate::DidStartRequest( - base::OnceClosure cancel_callback) { -#if !defined(OS_ANDROID) - if (!IsWebAuthnUiEnabled()) - return; - - auto dialog_model = std::make_unique<AuthenticatorRequestDialogModel>(); - weak_dialog_model_ = dialog_model.get(); - SetInitialUiModelBasedOnPreviouslyUsedTransport(weak_dialog_model_, - GetLastTransportUsed()); +void ChromeAuthenticatorRequestDelegate::RegisterActionCallbacks( + base::OnceClosure cancel_callback, + device::FidoRequestHandlerBase::RequestCallback request_callback) { + request_callback_ = request_callback; cancel_callback_ = std::move(cancel_callback); - weak_dialog_model_->AddObserver(this); - - ShowAuthenticatorRequestDialog( - content::WebContents::FromRenderFrameHost(render_frame_host()), - std::move(dialog_model)); -#endif } bool ChromeAuthenticatorRequestDelegate::ShouldPermitIndividualAttestation( @@ -266,8 +261,28 @@ device::ToString(transport)); } +void ChromeAuthenticatorRequestDelegate::OnTransportAvailabilityEnumerated( + device::FidoRequestHandlerBase::TransportAvailabilityInfo data) { +#if !defined(OS_ANDROID) + if (!IsWebAuthnUiEnabled()) + return; + + weak_dialog_model_ = transient_dialog_model_holder_.get(); + SetInitialUiModelBasedOnPreviouslyUsedTransport(weak_dialog_model_, + GetLastTransportUsed()); + weak_dialog_model_->AddObserver(this); + ShowAuthenticatorRequestDialog( + content::WebContents::FromRenderFrameHost(render_frame_host()), + std::move(transient_dialog_model_holder_)); +#endif +} + void ChromeAuthenticatorRequestDelegate::FidoAuthenticatorAdded( - const device::FidoAuthenticator& authenticator) { + const device::FidoAuthenticator& authenticator, + bool* hold_off_request) { + if (!ShouldDispatchRequestImmediately(authenticator)) + *hold_off_request = true; + if (!IsWebAuthnUiEnabled()) return;
diff --git a/chrome/browser/webauthn/chrome_authenticator_request_delegate.h b/chrome/browser/webauthn/chrome_authenticator_request_delegate.h index c16d8db3..6022476c 100644 --- a/chrome/browser/webauthn/chrome_authenticator_request_delegate.h +++ b/chrome/browser/webauthn/chrome_authenticator_request_delegate.h
@@ -5,6 +5,7 @@ #ifndef CHROME_BROWSER_WEBAUTHN_CHROME_AUTHENTICATOR_REQUEST_DELEGATE_H_ #define CHROME_BROWSER_WEBAUTHN_CHROME_AUTHENTICATOR_REQUEST_DELEGATE_H_ +#include <memory> #include <string> #include "base/callback.h" @@ -63,7 +64,9 @@ content::BrowserContext* browser_context() const; // content::AuthenticatorRequestClientDelegate: - void DidStartRequest(base::OnceClosure cancel_callback) override; + void RegisterActionCallbacks(base::OnceClosure cancel_callback, + device::FidoRequestHandlerBase::RequestCallback + request_callback) override; bool ShouldPermitIndividualAttestation( const std::string& relying_party_id) override; void ShouldReturnAttestation( @@ -74,8 +77,10 @@ device::FidoTransportProtocol transport) override; // device::FidoRequestHandlerBase::TransportAvailabilityObserver: - void FidoAuthenticatorAdded( - const device::FidoAuthenticator& authenticator) override; + void OnTransportAvailabilityEnumerated( + device::FidoRequestHandlerBase::TransportAvailabilityInfo data) override; + void FidoAuthenticatorAdded(const device::FidoAuthenticator& authenticator, + bool* hold_off_request) override; void FidoAuthenticatorRemoved(base::StringPiece device_id) override; // AuthenticatorRequestDialogModel::Observer: @@ -84,7 +89,15 @@ content::RenderFrameHost* const render_frame_host_; AuthenticatorRequestDialogModel* weak_dialog_model_ = nullptr; + // Holds ownership of AuthenticatorRequestDialogModel until + // OnTransportAvailabilityEnumerated() is invoked, at which point the + // ownership of the model is transferred to AuthenticatorRequestDialogView and + // |this| instead holds weak pointer of the model via above + // |weak_dialog_model_|. + std::unique_ptr<AuthenticatorRequestDialogModel> + transient_dialog_model_holder_; base::OnceClosure cancel_callback_; + device::FidoRequestHandlerBase::RequestCallback request_callback_; base::WeakPtrFactory<ChromeAuthenticatorRequestDelegate> weak_ptr_factory_;
diff --git a/chrome/common/chrome_features.cc b/chrome/common/chrome_features.cc index 677b96ce..e62989f 100644 --- a/chrome/common/chrome_features.cc +++ b/chrome/common/chrome_features.cc
@@ -369,11 +369,6 @@ "AcknowledgeNtpOverrideOnDeactivate", base::FEATURE_DISABLED_BY_DEFAULT}; #endif -#if defined(OS_WIN) || (defined(OS_LINUX) && !defined(OS_CHROMEOS)) -const base::Feature kWarnBeforeQuitting{"WarnBeforeQuitting", - base::FEATURE_DISABLED_BY_DEFAULT}; -#endif - // The material redesign of the Incognito NTP. const base::Feature kMaterialDesignIncognitoNTP{ "MaterialDesignIncognitoNTP",
diff --git a/chrome/common/chrome_features.h b/chrome/common/chrome_features.h index bf26b67..5b8dff5 100644 --- a/chrome/common/chrome_features.h +++ b/chrome/common/chrome_features.h
@@ -202,10 +202,6 @@ extern const base::Feature kAcknowledgeNtpOverrideOnDeactivate; #endif -#if defined(OS_WIN) || (defined(OS_LINUX) && !defined(OS_CHROMEOS)) -extern const base::Feature kWarnBeforeQuitting; -#endif - extern const base::Feature kMaterialDesignIncognitoNTP; extern const base::Feature kModalPermissionPrompts;
diff --git a/chrome/common/extensions/api/notifications.idl b/chrome/common/extensions/api/notifications.idl index 114a6350..3100d6a 100644 --- a/chrome/common/extensions/api/notifications.idl +++ b/chrome/common/extensions/api/notifications.idl
@@ -121,6 +121,10 @@ // Indicates that the notification should remain visible on screen until the // user activates or dismisses the notification. This defaults to false. boolean? requireInteraction; + + // Indicates that no sounds or vibrations should be made when the + // notification is being shown. This defaults to false. + boolean? silent; }; callback CreateCallback = void (DOMString notificationId);
diff --git a/chrome/installer/util/create_dir_work_item.cc b/chrome/installer/util/create_dir_work_item.cc index 34215b9..659aa01 100644 --- a/chrome/installer/util/create_dir_work_item.cc +++ b/chrome/installer/util/create_dir_work_item.cc
@@ -35,9 +35,12 @@ if (top_path_.empty()) return true; - VLOG(1) << "top directory that needs to be created: " << top_path_.value(); + VLOG(1) << "Top directory that needs to be created: " << top_path_.value(); bool result = base::CreateDirectory(path_); - VLOG(1) << "directory creation result: " << result; + if (result) + VLOG(1) << "Created directory"; + else + PLOG(ERROR) << "Failed to create directory " << top_path_.value(); rollback_needed_ = true;
diff --git a/chrome/test/BUILD.gn b/chrome/test/BUILD.gn index 3d8d7b4b..5b5176f 100644 --- a/chrome/test/BUILD.gn +++ b/chrome/test/BUILD.gn
@@ -3325,7 +3325,7 @@ if (is_win || (is_linux && !is_chromeos)) { sources += - [ "../browser/ui/views/confirm_quit_bubble_controller_unittest.cc" ] + [ "../browser/ui/views/quit_instruction_bubble_controller_unittest.cc" ] } if (enable_native_notifications) {
diff --git a/chrome/test/chromedriver/element_commands.cc b/chrome/test/chromedriver/element_commands.cc index 55dd3c6..5f4c7cfd 100644 --- a/chrome/test/chromedriver/element_commands.cc +++ b/chrome/test/chromedriver/element_commands.cc
@@ -504,24 +504,24 @@ return Status(kUnknownError, "could not convert to DictionaryValue"); // grab values - int x, y, width, height; - if (!location_dict->GetInteger("x", &x)) - return Status(kUnknownError, "getting size failed to return x"); + double x, y, width, height; + if (!location_dict->GetDouble("x", &x)) + return Status(kUnknownError, "x coordinate is missing in element location"); - if (!location_dict->GetInteger("y", &y)) - return Status(kUnknownError, "getting size failed to return y"); + if (!location_dict->GetDouble("y", &y)) + return Status(kUnknownError, "y coordinate is missing in element location"); - if (!size_dict->GetInteger("height", &height)) - return Status(kUnknownError, "getting location failed to return height"); + if (!size_dict->GetDouble("height", &height)) + return Status(kUnknownError, "height is missing in element size"); - if (!size_dict->GetInteger("width", &width)) - return Status(kUnknownError, "getting location failed to return width"); + if (!size_dict->GetDouble("width", &width)) + return Status(kUnknownError, "width is missing in element size"); base::DictionaryValue ret; - ret.SetInteger("x", x); - ret.SetInteger("y", y); - ret.SetInteger("width", width); - ret.SetInteger("height", height); + ret.SetDouble("x", x); + ret.SetDouble("y", y); + ret.SetDouble("width", width); + ret.SetDouble("height", height); value->reset(ret.DeepCopy()); return Status(kOk); }
diff --git a/chrome/test/data/extensions/api_test/notifications/api/partial_update/background.js b/chrome/test/data/extensions/api_test/notifications/api/partial_update/background.js index b42572f7..ab4f046 100644 --- a/chrome/test/data/extensions/api_test/notifications/api/partial_update/background.js +++ b/chrome/test/data/extensions/api_test/notifications/api/partial_update/background.js
@@ -119,6 +119,7 @@ title: "Basic title", message: "Basic message", iconUrl: red_dot, + silent: false, buttons: [{title: "Button"}] }; @@ -128,7 +129,8 @@ .then(function() { return update("testId", { title: "Changed!", - message: "Too late! The show ended yesterday" + message: "Too late! The show ended yesterday", + silent: true }); }) // Then update a few more items
diff --git a/chrome/test/data/webui/md_history/md_history_browsertest.js b/chrome/test/data/webui/md_history/md_history_browsertest.js index 362b09e..33f64825 100644 --- a/chrome/test/data/webui/md_history/md_history_browsertest.js +++ b/chrome/test/data/webui/md_history/md_history_browsertest.js
@@ -82,9 +82,12 @@ ]), }; +// https://crbug.com/874976, fails on Mac. +GEN('#if !defined(OS_MACOSX)'); TEST_F('MaterialHistoryItemTest', 'All', function() { mocha.run(); }); +GEN('#endif'); function MaterialHistoryListTest() {}
diff --git a/chromecast/media/cma/backend/fuchsia/mixer_output_stream_fuchsia.cc b/chromecast/media/cma/backend/fuchsia/mixer_output_stream_fuchsia.cc index 8c527cbb..b9034cfa 100644 --- a/chromecast/media/cma/backend/fuchsia/mixer_output_stream_fuchsia.cc +++ b/chromecast/media/cma/backend/fuchsia/mixer_output_stream_fuchsia.cc
@@ -28,6 +28,11 @@ // MixerOutputStreamFuchsia::Write(). constexpr int kMaxOutputBufferSizeFrames = 4096; +// Current AudioOut implementation allows only one buffer with id=0. +// TODO(sergeyu): Replace with an incrementing buffer id once AddPayloadBuffer() +// and RemovePayloadBuffer() are implemented properly in AudioOut. +const uint32_t kBufferId = 0; + // static std::unique_ptr<MixerOutputStream> MixerOutputStream::Create() { return std::make_unique<MixerOutputStreamFuchsia>(); @@ -37,7 +42,7 @@ MixerOutputStreamFuchsia::~MixerOutputStreamFuchsia() = default; bool MixerOutputStreamFuchsia::Start(int requested_sample_rate, int channels) { - DCHECK(!audio_renderer_); + DCHECK(!audio_out_); DCHECK(reference_time_.is_null()); sample_rate_ = requested_sample_rate; @@ -45,12 +50,12 @@ target_packet_size_ = ::media::AudioTimestampHelper::TimeToFrames( kTargetWritePeriod, sample_rate_); - // Connect |audio_renderer_|. + // Connect |audio_out_|. fuchsia::media::AudioPtr audio_server = base::fuchsia::ComponentContext::GetDefault() ->ConnectToService<fuchsia::media::Audio>(); - audio_server->CreateAudioRenderer2(audio_renderer_.NewRequest()); - audio_renderer_.set_error_handler( + audio_server->CreateAudioOut(audio_out_.NewRequest()); + audio_out_.set_error_handler( fit::bind_member(this, &MixerOutputStreamFuchsia::OnRendererError)); // Configure the renderer. @@ -58,13 +63,13 @@ format.sample_format = fuchsia::media::AudioSampleFormat::FLOAT; format.channels = channels_; format.frames_per_second = sample_rate_; - audio_renderer_->SetPcmStreamType(std::move(format)); + audio_out_->SetPcmStreamType(std::move(format)); // Use number of samples to specify media position. - audio_renderer_->SetPtsUnits(sample_rate_, 1); + audio_out_->SetPtsUnits(sample_rate_, 1); - audio_renderer_->EnableMinLeadTimeEvents(true); - audio_renderer_.events().OnMinLeadTimeChanged = + audio_out_->EnableMinLeadTimeEvents(true); + audio_out_.events().OnMinLeadTimeChanged = fit::bind_member(this, &MixerOutputStreamFuchsia::OnMinLeadTimeChanged); return true; @@ -93,7 +98,7 @@ bool MixerOutputStreamFuchsia::Write(const float* data, int data_size, bool* out_playback_interrupted) { - if (!audio_renderer_) + if (!audio_out_) return false; DCHECK_EQ(data_size % channels_, 0); @@ -125,12 +130,13 @@ data, packet_size); // Send a new packet. - fuchsia::media::AudioPacket packet; - packet.timestamp = stream_position_samples_; + fuchsia::media::StreamPacket packet; + packet.pts = stream_position_samples_; + packet.payload_buffer_id = kBufferId; packet.payload_offset = payload_buffer_pos_; packet.payload_size = packet_size; packet.flags = 0; - audio_renderer_->SendPacketNoReply(std::move(packet)); + audio_out_->SendPacketNoReply(std::move(packet)); // Update stream position. int frames = data_size / channels_; @@ -139,8 +145,8 @@ if (reference_time_.is_null()) { reference_time_ = now + min_lead_time_; - audio_renderer_->PlayNoReply(reference_time_.ToZxTime(), - stream_position_samples_ - frames); + audio_out_->PlayNoReply(reference_time_.ToZxTime(), + stream_position_samples_ - frames); } else { // Block the thread to limit amount of buffered data. Currently // MixerOutputStreamAlsa uses blocking Write() and StreamMixer relies on @@ -162,7 +168,7 @@ void MixerOutputStreamFuchsia::Stop() { reference_time_ = base::TimeTicks(); - audio_renderer_.Unbind(); + audio_out_.Unbind(); } size_t MixerOutputStreamFuchsia::GetMinBufferSize() { @@ -184,8 +190,8 @@ } payload_buffer_pos_ = 0; - audio_renderer_->SetPayloadBuffer( - zx::vmo(payload_buffer_.handle().Duplicate().GetHandle())); + audio_out_->AddPayloadBuffer( + kBufferId, zx::vmo(payload_buffer_.handle().Duplicate().GetHandle())); return true; }
diff --git a/chromecast/media/cma/backend/fuchsia/mixer_output_stream_fuchsia.h b/chromecast/media/cma/backend/fuchsia/mixer_output_stream_fuchsia.h index 4257b7c..b82e1aa 100644 --- a/chromecast/media/cma/backend/fuchsia/mixer_output_stream_fuchsia.h +++ b/chromecast/media/cma/backend/fuchsia/mixer_output_stream_fuchsia.h
@@ -37,7 +37,7 @@ base::TimeTicks GetCurrentStreamTime(); - // Event handlers for |audio_renderer_|. + // Event handlers for |audio_out_|. void OnRendererError(); void OnMinLeadTimeChanged(int64_t min_lead_time); @@ -48,7 +48,7 @@ int target_packet_size_ = 0; // Audio renderer connection. - fuchsia::media::AudioRenderer2Ptr audio_renderer_; + fuchsia::media::AudioOutPtr audio_out_; base::SharedMemory payload_buffer_; size_t payload_buffer_pos_ = 0;
diff --git a/chromeos/CHROMEOS_LKGM b/chromeos/CHROMEOS_LKGM index 74f8379..4f18189a 100644 --- a/chromeos/CHROMEOS_LKGM +++ b/chromeos/CHROMEOS_LKGM
@@ -1 +1 @@ -10960.0.0 \ No newline at end of file +10974.0.0 \ No newline at end of file
diff --git a/chromeos/chromeos_paths.cc b/chromeos/chromeos_paths.cc index 4c210cf..e7a23a1 100644 --- a/chromeos/chromeos_paths.cc +++ b/chromeos/chromeos_paths.cc
@@ -59,6 +59,9 @@ const base::FilePath::CharType kSigninProfileComponentPolicy[] = FILE_PATH_LITERAL("/var/cache/signin_profile_component_policy"); +const base::FilePath::CharType kPreinstalledComponents[] = + FILE_PATH_LITERAL("/mnt/stateful_partition/unencrypted/"); + bool PathProvider(int key, base::FilePath* result) { switch (key) { case FILE_DEFAULT_APP_ORDER: @@ -103,6 +106,9 @@ case DIR_SIGNIN_PROFILE_COMPONENT_POLICY: *result = base::FilePath(kSigninProfileComponentPolicy); break; + case DIR_PREINSTALLED_COMPONENTS: + *result = base::FilePath(kPreinstalledComponents); + break; default: return false; }
diff --git a/chromeos/chromeos_paths.h b/chromeos/chromeos_paths.h index c35179f..488b404 100644 --- a/chromeos/chromeos_paths.h +++ b/chromeos/chromeos_paths.h
@@ -53,6 +53,8 @@ // is stored for the signin profile. // Currently this is used for policy for // extensions. + DIR_PREINSTALLED_COMPONENTS, // Directory that contains pre-installed + // components. PATH_END };
diff --git a/chromeos/services/assistant/BUILD.gn b/chromeos/services/assistant/BUILD.gn index a2b1ed6..5bdb759b 100644 --- a/chromeos/services/assistant/BUILD.gn +++ b/chromeos/services/assistant/BUILD.gn
@@ -69,7 +69,7 @@ "//chromeos/assistant/internal/proto/google3", "//libassistant/contrib/core", "//libassistant/contrib/platform/audio", - "//libassistant/shared/internal_api/c:api_wrappers_for_caller_no_chromium", + "//libassistant/shared/internal_api/c:api_wrappers_entrypoint", "//libassistant/shared/public", "//libassistant/shared/public:export", "//ui/base",
diff --git a/chromeos/services/assistant/assistant_manager_service_impl.cc b/chromeos/services/assistant/assistant_manager_service_impl.cc index 82b48e4..876317d3 100644 --- a/chromeos/services/assistant/assistant_manager_service_impl.cc +++ b/chromeos/services/assistant/assistant_manager_service_impl.cc
@@ -25,7 +25,7 @@ #include "chromeos/services/assistant/utils.h" #include "libassistant/shared/internal_api/assistant_manager_delegate.h" #include "libassistant/shared/internal_api/assistant_manager_internal.h" -#include "libassistant/shared/internal_api/media_manager.h" +#include "libassistant/shared/public/media_manager.h" #include "services/service_manager/public/cpp/connector.h" #include "url/gurl.h" @@ -122,8 +122,7 @@ void AssistantManagerServiceImpl::RegisterFallbackMediaHandler() { // Register handler for media actions. - auto* media_manager = assistant_manager_internal_->GetMediaManager(); - media_manager->RegisterFallbackMediaHandler( + assistant_manager_internal_->RegisterFallbackMediaHandler( [this](std::string play_media_args_proto) { std::string url = GetWebUrlFromMediaArgs(play_media_args_proto); if (!url.empty()) {
diff --git a/chromeos/services/assistant/platform/system_provider_impl.cc b/chromeos/services/assistant/platform/system_provider_impl.cc index b1c8f9807..51ab5e0 100644 --- a/chromeos/services/assistant/platform/system_provider_impl.cc +++ b/chromeos/services/assistant/platform/system_provider_impl.cc
@@ -66,5 +66,14 @@ battery_monitor_.FlushForTesting(); } +void SystemProviderImpl::ProcessTpm(TpmProcessingType type, + const std::string& data, + TpmCallback on_done) { + // This method is used for processing data from the TPM chip. This is inorder + // to access secure storage. The work is currently not complete (b:111559586). + // The default implementation by other platforms is to call on_done for now. + on_done(data); +} + } // namespace assistant } // namespace chromeos
diff --git a/chromeos/services/assistant/platform/system_provider_impl.h b/chromeos/services/assistant/platform/system_provider_impl.h index c3b035fd..c582736 100644 --- a/chromeos/services/assistant/platform/system_provider_impl.h +++ b/chromeos/services/assistant/platform/system_provider_impl.h
@@ -26,6 +26,9 @@ bool GetBatteryState(BatteryState* state) override; void UpdateTimezoneAndLocale(const std::string& timezone, const std::string& locale) override; + void ProcessTpm(TpmProcessingType type, + const std::string& data, + TpmCallback on_done) override; private: friend class SystemProviderImplTest;
diff --git a/components/autofill/core/browser/autofill_client.h b/components/autofill/core/browser/autofill_client.h index 9a8ab90..9b4fc1f6 100644 --- a/components/autofill/core/browser/autofill_client.h +++ b/components/autofill/core/browser/autofill_client.h
@@ -51,6 +51,7 @@ class CardUnmaskDelegate; class CreditCard; class FormStructure; +class MigratableCreditCard; class PersonalDataManager; struct Suggestion; @@ -138,8 +139,16 @@ base::WeakPtr<CardUnmaskDelegate> delegate) = 0; virtual void OnUnmaskVerificationResult(PaymentsRpcResult result) = 0; - // Runs |closure| if the user accepts the migration process. - virtual void ShowLocalCardMigrationPrompt(base::OnceClosure closure) = 0; + // Runs |closure| if the user accepts the card migration offer. This causes + // the card migration dialog to be shown. + virtual void ShowLocalCardMigrationDialog( + base::OnceClosure show_migration_dialog_closure) = 0; + + // Runs |closure| if the user would like the selected + // |migratable_credit_cards| to be uploaded to cloud. + virtual void ConfirmMigrateLocalCardToCloud( + std::vector<MigratableCreditCard>& migratable_credit_cards, + base::OnceClosure start_migrating_cards_closure) = 0; // Runs |callback| if the |card| should be imported as personal data. // |metric_logger| can be used to log user actions.
diff --git a/components/autofill/core/browser/local_card_migration_manager.cc b/components/autofill/core/browser/local_card_migration_manager.cc index 3bd77b1..00b1c555 100644 --- a/components/autofill/core/browser/local_card_migration_manager.cc +++ b/components/autofill/core/browser/local_card_migration_manager.cc
@@ -98,6 +98,11 @@ void LocalCardMigrationManager::OnUserAcceptedIntermediateMigrationDialog() { user_accepted_main_migration_dialog_ = false; // Pops up a larger, modal dialog showing the local cards to be uploaded. + client_->ConfirmMigrateLocalCardToCloud( + migratable_credit_cards_, + base::BindOnce( + &LocalCardMigrationManager::OnUserAcceptedMainMigrationDialog, + weak_ptr_factory_.GetWeakPtr())); } bool LocalCardMigrationManager::IsCreditCardMigrationEnabled() { @@ -125,8 +130,8 @@ legal_message_ = std::move(legal_message); // If we successfully received the legal docs, trigger the offer-to-migrate // dialog. - client_->ShowLocalCardMigrationPrompt(base::BindOnce( - &LocalCardMigrationManager::OnUserAcceptedMainMigrationDialog, + client_->ShowLocalCardMigrationDialog(base::BindOnce( + &LocalCardMigrationManager::OnUserAcceptedIntermediateMigrationDialog, weak_ptr_factory_.GetWeakPtr())); // TODO(crbug.com/852904): Call the client LoadRiskData() }
diff --git a/components/autofill/core/browser/test_autofill_client.cc b/components/autofill/core/browser/test_autofill_client.cc index ba53d73..15a517dc 100644 --- a/components/autofill/core/browser/test_autofill_client.cc +++ b/components/autofill/core/browser/test_autofill_client.cc
@@ -71,9 +71,15 @@ void TestAutofillClient::OnUnmaskVerificationResult(PaymentsRpcResult result) { } -void TestAutofillClient::ShowLocalCardMigrationPrompt( - base::OnceClosure closure) { - std::move(closure).Run(); +void TestAutofillClient::ShowLocalCardMigrationDialog( + base::OnceClosure show_migration_dialog_closure) { + std::move(show_migration_dialog_closure).Run(); +} + +void TestAutofillClient::ConfirmMigrateLocalCardToCloud( + std::vector<MigratableCreditCard>& migratable_credit_cards, + base::OnceClosure start_migrating_cards_closure) { + std::move(start_migrating_cards_closure).Run(); } void TestAutofillClient::ConfirmSaveAutofillProfile(
diff --git a/components/autofill/core/browser/test_autofill_client.h b/components/autofill/core/browser/test_autofill_client.h index 85ed7e5..f3f3748 100644 --- a/components/autofill/core/browser/test_autofill_client.h +++ b/components/autofill/core/browser/test_autofill_client.h
@@ -42,7 +42,11 @@ UnmaskCardReason reason, base::WeakPtr<CardUnmaskDelegate> delegate) override; void OnUnmaskVerificationResult(PaymentsRpcResult result) override; - void ShowLocalCardMigrationPrompt(base::OnceClosure closure) override; + void ShowLocalCardMigrationDialog( + base::OnceClosure show_migration_dialog_closure) override; + void ConfirmMigrateLocalCardToCloud( + std::vector<MigratableCreditCard>& migratable_credit_cards, + base::OnceClosure start_migrating_cards_closure) override; void ConfirmSaveAutofillProfile(const AutofillProfile& profile, base::OnceClosure callback) override; void ConfirmSaveCreditCardLocally(const CreditCard& card,
diff --git a/components/background_task_scheduler/android/java/src/org/chromium/components/background_task_scheduler/BackgroundTaskSchedulerJobService.java b/components/background_task_scheduler/android/java/src/org/chromium/components/background_task_scheduler/BackgroundTaskSchedulerJobService.java index 183aaed1..68380df 100644 --- a/components/background_task_scheduler/android/java/src/org/chromium/components/background_task_scheduler/BackgroundTaskSchedulerJobService.java +++ b/components/background_task_scheduler/android/java/src/org/chromium/components/background_task_scheduler/BackgroundTaskSchedulerJobService.java
@@ -145,9 +145,15 @@ if (!taskInfo.shouldUpdateCurrent() && hasPendingJob(jobScheduler, taskInfo.getTaskId())) { return true; } - - int result = jobScheduler.schedule(jobInfo); - return result == JobScheduler.RESULT_SUCCESS; + // This can fail on heavily modified android builds. Catch so we don't crash. + try { + return jobScheduler.schedule(jobInfo) == JobScheduler.RESULT_SUCCESS; + } catch (Exception e) { + // Typically we don't catch RuntimeException, but this time we do want to catch it + // because we are worried about android as modified by device manufacturers. + Log.e(TAG, "Unable to schedule with Android.", e); + return false; + } } @Override
diff --git a/components/browser_sync/profile_sync_service.cc b/components/browser_sync/profile_sync_service.cc index c7a629f..a520e040 100644 --- a/components/browser_sync/profile_sync_service.cc +++ b/components/browser_sync/profile_sync_service.cc
@@ -1411,13 +1411,14 @@ const syncer::ModelTypeSet current_types = GetPreferredDataTypes(); syncer::ModelTypeSet type_set = syncer::UserSelectableTypes(); - syncer::ModelTypeSet::Iterator it = type_set.First(); + syncer::ModelTypeSet::Iterator it = type_set.begin(); - DCHECK_EQ(arraysize(user_selectable_types), type_set.Size()); + DCHECK_EQ(base::size(user_selectable_types), type_set.Size()); - for (size_t i = 0; i < arraysize(user_selectable_types) && it.Good(); - ++i, it.Inc()) { - const syncer::ModelType type = it.Get(); + for (size_t i = 0; + i < base::size(user_selectable_types) && it != type_set.end(); + ++i, ++it) { + const syncer::ModelType type = *it; if (chosen_types.Has(type) && (!IsFirstSetupComplete() || !current_types.Has(type))) { // Selected type has changed - log it. @@ -1671,10 +1672,7 @@ syncer::ModelSafeRoutingInfo routing_info; engine_->GetModelSafeRoutingInfo(&routing_info); const syncer::ModelTypeSet registered = GetRegisteredDataTypes(); - for (syncer::ModelTypeSet::Iterator it = registered.First(); it.Good(); - it.Inc()) { - syncer::ModelType type = it.Get(); - + for (syncer::ModelType type : registered) { auto type_status = std::make_unique<base::DictionaryValue>(); type_status->SetString("name", ModelTypeToString(type)); type_status->SetString("group_type", @@ -1971,9 +1969,7 @@ scoped_refptr<GetAllNodesRequestHelper> helper = new GetAllNodesRequestHelper(all_types, callback); - for (syncer::ModelTypeSet::Iterator it = all_types.First(); it.Good(); - it.Inc()) { - syncer::ModelType type = it.Get(); + for (syncer::ModelType type : all_types) { const auto dtc_iter = data_type_controllers_.find(type); if (dtc_iter != data_type_controllers_.end()) { dtc_iter->second->GetAllNodes(base::BindRepeating( @@ -2234,9 +2230,8 @@ void ProfileSyncService::RecordMemoryUsageHistograms() { syncer::ModelTypeSet active_types = GetActiveDataTypes(); - for (syncer::ModelTypeSet::Iterator type_it = active_types.First(); - type_it.Good(); type_it.Inc()) { - auto dtc_it = data_type_controllers_.find(type_it.Get()); + for (syncer::ModelType type : active_types) { + auto dtc_it = data_type_controllers_.find(type); if (dtc_it != data_type_controllers_.end()) dtc_it->second->RecordMemoryUsageAndCountsHistograms(); }
diff --git a/components/browser_sync/profile_sync_service_startup_unittest.cc b/components/browser_sync/profile_sync_service_startup_unittest.cc index b3ec24d..6cdf1f0 100644 --- a/components/browser_sync/profile_sync_service_startup_unittest.cc +++ b/components/browser_sync/profile_sync_service_startup_unittest.cc
@@ -84,10 +84,9 @@ ON_CALL(*component_factory(), CreateCommonDataTypeControllers(_, _)) .WillByDefault(InvokeWithoutArgs([=]() { syncer::DataTypeController::TypeVector controllers; - for (syncer::ModelTypeSet::Iterator it = registered_types.First(); - it.Good(); it.Inc()) { + for (syncer::ModelType type : registered_types) { controllers.push_back( - std::make_unique<syncer::FakeDataTypeController>(it.Get())); + std::make_unique<syncer::FakeDataTypeController>(type)); } return controllers; })); @@ -587,10 +586,8 @@ // Clear the datatype preference fields (simulating bug 154940). pref_service()->ClearPref(syncer::prefs::kSyncKeepEverythingSynced); syncer::ModelTypeSet user_types = syncer::UserTypes(); - for (syncer::ModelTypeSet::Iterator iter = user_types.First(); iter.Good(); - iter.Inc()) { - pref_service()->ClearPref( - syncer::SyncPrefs::GetPrefNameForDataType(iter.Get())); + for (syncer::ModelType type : user_types) { + pref_service()->ClearPref(syncer::SyncPrefs::GetPrefNameForDataType(type)); } CreateSyncService(ProfileSyncService::MANUAL_START);
diff --git a/components/captive_portal/captive_portal_detector.cc b/components/captive_portal/captive_portal_detector.cc index cb15424..2902eb3 100644 --- a/components/captive_portal/captive_portal_detector.cc +++ b/components/captive_portal/captive_portal_detector.cc
@@ -38,7 +38,7 @@ auto resource_request = std::make_unique<network::ResourceRequest>(); resource_request->url = url; - // Can't safely use net::LOAD_DISABLE_CERT_REVOCATION_CHECKING here, + // Can't safely use net::LOAD_DISABLE_CERT_NETWORK_FETCHES here, // since then the connection may be reused without checking the cert. resource_request->load_flags = net::LOAD_BYPASS_CACHE; resource_request->allow_credentials = false;
diff --git a/components/cast_channel/cast_socket.cc b/components/cast_channel/cast_socket.cc index a7b3206..8aaff00 100644 --- a/components/cast_channel/cast_socket.cc +++ b/components/cast_channel/cast_socket.cc
@@ -85,6 +85,7 @@ verify_result->verified_cert = params.certificate(); return net::OK; } + void SetConfig(const Config& config) override {} }; } // namespace
diff --git a/components/cronet/android/sample/javatests/AndroidManifest.xml b/components/cronet/android/sample/javatests/AndroidManifest.xml index 5acebd8..1b07d9c 100644 --- a/components/cronet/android/sample/javatests/AndroidManifest.xml +++ b/components/cronet/android/sample/javatests/AndroidManifest.xml
@@ -18,9 +18,9 @@ </application> <instrumentation android:name="android.support.test.runner.AndroidJUnitRunner" android:targetPackage="org.chromium.cronet_sample_apk" - android:label="Tests for org.chromium.cronet_sample_apk" - chromium-junit4="true"/> + android:label="Tests for org.chromium.cronet_sample_apk"/> <instrumentation android:name="android.test.InstrumentationTestRunner" android:targetPackage="org.chromium.cronet_sample_apk" - android:label="Tests for org.chromium.cronet_sample_apk"/> + android:label="Tests for org.chromium.cronet_sample_apk" + chromium-junit3="true"/> </manifest>
diff --git a/components/cronet/android/test/javatests/AndroidManifest.xml b/components/cronet/android/test/javatests/AndroidManifest.xml index 9b144fa..68a5962 100644 --- a/components/cronet/android/test/javatests/AndroidManifest.xml +++ b/components/cronet/android/test/javatests/AndroidManifest.xml
@@ -18,8 +18,7 @@ </application> <instrumentation android:name="org.chromium.base.test.BaseChromiumAndroidJUnitRunner" android:targetPackage="org.chromium.net" - android:label="Tests for org.chromium.net" - chromium-junit4="true"> + android:label="Tests for org.chromium.net"> <!-- Meta data used for BaseChromiumAndroidJUnitRunner to scan only one package path for potential tests --> <meta-data android:name="org.chromium.base.test.BaseChromiumAndroidJUnitRunner.TestListPackage"
diff --git a/components/cronet/ios/Cronet.mm b/components/cronet/ios/Cronet.mm index 6f061d1..28b05fb 100644 --- a/components/cronet/ios/Cronet.mm +++ b/components/cronet/ios/Cronet.mm
@@ -86,6 +86,7 @@ verify_result->cert_status = net::MapNetErrorToCertStatus(result); return result; } + void SetConfig(const Config& config) override {} }; // net::HTTPProtocolHandlerDelegate for Cronet.
diff --git a/components/data_reduction_proxy/core/browser/data_reduction_proxy_bypass_protocol_unittest.cc b/components/data_reduction_proxy/core/browser/data_reduction_proxy_bypass_protocol_unittest.cc index ea6f613e..0df9ac6 100644 --- a/components/data_reduction_proxy/core/browser/data_reduction_proxy_bypass_protocol_unittest.cc +++ b/components/data_reduction_proxy/core/browser/data_reduction_proxy_bypass_protocol_unittest.cc
@@ -280,8 +280,8 @@ // to requests. context_->set_http_user_agent_settings(&http_user_agent_settings_); bypass_stats_.reset(new DataReductionProxyBypassStats( - test_context_->config(), - test_context_->unreachable_callback())); + test_context_->config(), test_context_->unreachable_callback(), + test_context_->test_network_connection_tracker())); DataReductionProxyInterceptor* interceptor = new DataReductionProxyInterceptor(
diff --git a/components/data_reduction_proxy/core/browser/data_reduction_proxy_bypass_stats.cc b/components/data_reduction_proxy/core/browser/data_reduction_proxy_bypass_stats.cc index 1c47b73d..fd85449b 100644 --- a/components/data_reduction_proxy/core/browser/data_reduction_proxy_bypass_stats.cc +++ b/components/data_reduction_proxy/core/browser/data_reduction_proxy_bypass_stats.cc
@@ -93,9 +93,11 @@ DataReductionProxyBypassStats::DataReductionProxyBypassStats( DataReductionProxyConfig* config, - UnreachableCallback unreachable_callback) + UnreachableCallback unreachable_callback, + network::NetworkConnectionTracker* network_connection_tracker) : data_reduction_proxy_config_(config), unreachable_callback_(unreachable_callback), + network_connection_tracker_(network_connection_tracker), last_bypass_type_(BYPASS_EVENT_TYPE_MAX), triggering_request_(true), successful_requests_through_proxy_count_(0), @@ -107,12 +109,12 @@ } DataReductionProxyBypassStats::~DataReductionProxyBypassStats() { - net::NetworkChangeNotifier::RemoveNetworkChangeObserver(this); + network_connection_tracker_->RemoveNetworkConnectionObserver(this); } void DataReductionProxyBypassStats::InitializeOnIOThread() { DCHECK(thread_checker_.CalledOnValidThread()); - net::NetworkChangeNotifier::AddNetworkChangeObserver(this); + network_connection_tracker_->AddNetworkConnectionObserver(this); } void DataReductionProxyBypassStats::OnUrlRequestCompleted( @@ -322,8 +324,8 @@ } } -void DataReductionProxyBypassStats::OnNetworkChanged( - net::NetworkChangeNotifier::ConnectionType type) { +void DataReductionProxyBypassStats::OnConnectionChanged( + network::mojom::ConnectionType type) { DCHECK(thread_checker_.CalledOnValidThread()); ClearRequestCounts(); }
diff --git a/components/data_reduction_proxy/core/browser/data_reduction_proxy_bypass_stats.h b/components/data_reduction_proxy/core/browser/data_reduction_proxy_bypass_stats.h index 4d2d383e..7cf885beb 100644 --- a/components/data_reduction_proxy/core/browser/data_reduction_proxy_bypass_stats.h +++ b/components/data_reduction_proxy/core/browser/data_reduction_proxy_bypass_stats.h
@@ -13,8 +13,8 @@ #include "base/threading/thread_checker.h" #include "components/data_reduction_proxy/core/common/data_reduction_proxy_headers.h" #include "net/base/host_port_pair.h" -#include "net/base/network_change_notifier.h" #include "net/url_request/url_request.h" +#include "services/network/public/cpp/network_connection_tracker.h" namespace net { class HttpResponseHeaders; @@ -27,7 +27,7 @@ class DataReductionProxyConfig; class DataReductionProxyBypassStats - : public net::NetworkChangeNotifier::NetworkChangeObserver { + : public network::NetworkConnectionTracker::NetworkConnectionObserver { public: typedef base::Callback<void(bool /* unreachable */)> UnreachableCallback; @@ -52,7 +52,8 @@ // |config| must not be null. DataReductionProxyBypassStats( DataReductionProxyConfig* config, - UnreachableCallback unreachable_callback); + UnreachableCallback unreachable_callback, + network::NetworkConnectionTracker* network_connection_tracker); ~DataReductionProxyBypassStats() override; @@ -110,9 +111,8 @@ BYPASSED_BYTES_TYPE_MAX /* This must always be last.*/ }; - // NetworkChangeNotifier::NetworkChangeObserver: - void OnNetworkChanged( - net::NetworkChangeNotifier::ConnectionType type) override; + // network::NetworkConnectionTracker::NetworkConnectionObserver: + void OnConnectionChanged(network::mojom::ConnectionType type) override; void RecordBypassedBytes(DataReductionProxyBypassType bypass_type, BypassedBytesType bypassed_bytes_type, @@ -122,6 +122,9 @@ UnreachableCallback unreachable_callback_; + // Watches for network changes. + network::NetworkConnectionTracker* network_connection_tracker_; + // The last reason for bypass as determined by // MaybeBypassProxyAndPrepareToRetry DataReductionProxyBypassType last_bypass_type_;
diff --git a/components/data_reduction_proxy/core/browser/data_reduction_proxy_bypass_stats_unittest.cc b/components/data_reduction_proxy/core/browser/data_reduction_proxy_bypass_stats_unittest.cc index bec30208..86e0a8f1 100644 --- a/components/data_reduction_proxy/core/browser/data_reduction_proxy_bypass_stats_unittest.cc +++ b/components/data_reduction_proxy/core/browser/data_reduction_proxy_bypass_stats_unittest.cc
@@ -111,7 +111,8 @@ protected: std::unique_ptr<DataReductionProxyBypassStats> BuildBypassStats() { return std::make_unique<DataReductionProxyBypassStats>( - test_context_->config(), test_context_->unreachable_callback()); + test_context_->config(), test_context_->unreachable_callback(), + test_context_->test_network_connection_tracker()); } MockDataReductionProxyConfig* config() const { @@ -382,8 +383,8 @@ net::MockClientSocketFactory mock_socket_factory_; net::TestURLRequestContext context_; net::URLRequestContextStorage context_storage_; - std::unique_ptr<net::ProxyDelegate> proxy_delegate_; std::unique_ptr<DataReductionProxyTestContext> drp_test_context_; + std::unique_ptr<net::ProxyDelegate> proxy_delegate_; }; TEST_F(DataReductionProxyBypassStatsEndToEndTest, BypassedBytesNoRetry) {
diff --git a/components/data_reduction_proxy/core/browser/data_reduction_proxy_config.cc b/components/data_reduction_proxy/core/browser/data_reduction_proxy_config.cc index 5171e50..b898de0e 100644 --- a/components/data_reduction_proxy/core/browser/data_reduction_proxy_config.cc +++ b/components/data_reduction_proxy/core/browser/data_reduction_proxy_config.cc
@@ -132,7 +132,18 @@ WarmupURLFetchAttemptEvent::kCount); } -std::string DoGetCurrentNetworkID() { +// Returns the current connection type if known, otherwise returns +// CONNECTION_UNKNOWN. +network::mojom::ConnectionType GetConnectionType( + network::NetworkConnectionTracker* network_connection_tracker) { + auto connection_type = network::mojom::ConnectionType::CONNECTION_UNKNOWN; + network_connection_tracker->GetConnectionType(&connection_type, + base::DoNothing()); + return connection_type; +} + +std::string DoGetCurrentNetworkID( + network::NetworkConnectionTracker* network_connection_tracker) { // It is possible that the connection type changed between when // GetConnectionType() was called and when the API to determine the // network name was called. Check if that happened and retry until the @@ -141,38 +152,38 @@ // (that are approximate to begin with). while (true) { - net::NetworkChangeNotifier::ConnectionType connection_type = - net::NetworkChangeNotifier::GetConnectionType(); + auto connection_type = GetConnectionType(network_connection_tracker); std::string ssid_mccmnc; switch (connection_type) { - case net::NetworkChangeNotifier::ConnectionType::CONNECTION_UNKNOWN: - case net::NetworkChangeNotifier::ConnectionType::CONNECTION_NONE: - case net::NetworkChangeNotifier::ConnectionType::CONNECTION_BLUETOOTH: - case net::NetworkChangeNotifier::ConnectionType::CONNECTION_ETHERNET: + case network::mojom::ConnectionType::CONNECTION_UNKNOWN: + case network::mojom::ConnectionType::CONNECTION_NONE: + case network::mojom::ConnectionType::CONNECTION_BLUETOOTH: + case network::mojom::ConnectionType::CONNECTION_ETHERNET: break; - case net::NetworkChangeNotifier::ConnectionType::CONNECTION_WIFI: + case network::mojom::ConnectionType::CONNECTION_WIFI: #if defined(OS_ANDROID) || defined(OS_LINUX) || defined(OS_WIN) ssid_mccmnc = net::GetWifiSSID(); #endif break; - case net::NetworkChangeNotifier::ConnectionType::CONNECTION_2G: - case net::NetworkChangeNotifier::ConnectionType::CONNECTION_3G: - case net::NetworkChangeNotifier::ConnectionType::CONNECTION_4G: + case network::mojom::ConnectionType::CONNECTION_2G: + case network::mojom::ConnectionType::CONNECTION_3G: + case network::mojom::ConnectionType::CONNECTION_4G: #if defined(OS_ANDROID) ssid_mccmnc = net::android::GetTelephonyNetworkOperator(); #endif break; } - if (connection_type == net::NetworkChangeNotifier::GetConnectionType()) { - if (connection_type >= net::NetworkChangeNotifier::CONNECTION_2G && - connection_type <= net::NetworkChangeNotifier::CONNECTION_4G) { + if (connection_type == GetConnectionType(network_connection_tracker)) { + if (connection_type >= network::mojom::ConnectionType::CONNECTION_2G && + connection_type <= network::mojom::ConnectionType::CONNECTION_4G) { // No need to differentiate cellular connections by the exact // connection type. return "cell," + ssid_mccmnc; } - return base::IntToString(connection_type) + "," + ssid_mccmnc; + return base::IntToString(static_cast<int>(connection_type)) + "," + + ssid_mccmnc; } } NOTREACHED(); @@ -185,6 +196,7 @@ DataReductionProxyConfig::DataReductionProxyConfig( scoped_refptr<base::SingleThreadTaskRunner> io_task_runner, net::NetLog* net_log, + network::NetworkConnectionTracker* network_connection_tracker, std::unique_ptr<DataReductionProxyConfigValues> config_values, DataReductionProxyConfigurator* configurator, DataReductionProxyEventCreator* event_creator) @@ -193,21 +205,24 @@ config_values_(std::move(config_values)), io_task_runner_(io_task_runner), net_log_(net_log), + network_connection_tracker_(network_connection_tracker), configurator_(configurator), event_creator_(event_creator), - connection_type_(net::NetworkChangeNotifier::GetConnectionType()), + connection_type_(network::mojom::ConnectionType::CONNECTION_UNKNOWN), ignore_long_term_black_list_rules_(false), network_properties_manager_(nullptr), weak_factory_(this) { DCHECK(io_task_runner_); + DCHECK(network_connection_tracker_); DCHECK(configurator); DCHECK(event_creator); + // Constructed on the UI thread, but should be checked on the IO thread. thread_checker_.DetachFromThread(); } DataReductionProxyConfig::~DataReductionProxyConfig() { - net::NetworkChangeNotifier::RemoveNetworkChangeObserver(this); + network_connection_tracker_->RemoveNetworkConnectionObserver(this); } void DataReductionProxyConfig::InitializeOnIOThread( @@ -232,7 +247,12 @@ if (ShouldAddDefaultProxyBypassRules()) AddDefaultProxyBypassRules(); - net::NetworkChangeNotifier::AddNetworkChangeObserver(this); + + network_connection_tracker_->AddNetworkConnectionObserver(this); + network_connection_tracker_->GetConnectionType( + &connection_type_, + base::BindOnce(&DataReductionProxyConfig::OnConnectionChanged, + weak_factory_.GetWeakPtr())); } bool DataReductionProxyConfig::ShouldAddDefaultProxyBypassRules() const { @@ -624,8 +644,8 @@ } } -void DataReductionProxyConfig::OnNetworkChanged( - net::NetworkChangeNotifier::ConnectionType type) { +void DataReductionProxyConfig::OnConnectionChanged( + network::mojom::ConnectionType type) { DCHECK(thread_checker_.CalledOnValidThread()); connection_type_ = type; @@ -635,7 +655,8 @@ if (get_network_id_asynchronously_) { base::PostTaskAndReplyWithResult( g_get_network_id_task_runner.Get().get(), FROM_HERE, - base::BindOnce(&DoGetCurrentNetworkID), + base::BindOnce(&DoGetCurrentNetworkID, + base::Unretained(network_connection_tracker_)), base::BindOnce(&DataReductionProxyConfig::ContinueNetworkChanged, weak_factory_.GetWeakPtr())); return; @@ -720,7 +741,7 @@ return; } - if (connection_type_ == net::NetworkChangeNotifier::CONNECTION_NONE) { + if (connection_type_ == network::mojom::ConnectionType::CONNECTION_NONE) { RecordWarmupURLFetchAttemptEvent( WarmupURLFetchAttemptEvent::kConnectionTypeNone); return; @@ -836,7 +857,7 @@ std::string DataReductionProxyConfig::GetCurrentNetworkID() const { DCHECK(thread_checker_.CalledOnValidThread()); - return DoGetCurrentNetworkID(); + return DoGetCurrentNetworkID(network_connection_tracker_); } const NetworkPropertiesManager&
diff --git a/components/data_reduction_proxy/core/browser/data_reduction_proxy_config.h b/components/data_reduction_proxy/core/browser/data_reduction_proxy_config.h index 468bda1..4d68166 100644 --- a/components/data_reduction_proxy/core/browser/data_reduction_proxy_config.h +++ b/components/data_reduction_proxy/core/browser/data_reduction_proxy_config.h
@@ -26,10 +26,10 @@ #include "components/data_reduction_proxy/core/common/data_reduction_proxy_type_info.h" #include "components/data_reduction_proxy/proto/client_config.pb.h" #include "components/previews/core/previews_experiments.h" -#include "net/base/network_change_notifier.h" #include "net/log/net_log_with_source.h" #include "net/proxy_resolution/proxy_config.h" #include "net/proxy_resolution/proxy_retry_info.h" +#include "services/network/public/cpp/network_connection_tracker.h" namespace base { class SingleThreadTaskRunner; @@ -88,7 +88,7 @@ // This object lives on the IO thread and all of its methods are expected to be // called from there. class DataReductionProxyConfig - : public net::NetworkChangeNotifier::NetworkChangeObserver { + : public network::NetworkConnectionTracker::NetworkConnectionObserver { public: // The caller must ensure that all parameters remain alive for the lifetime // of the |DataReductionProxyConfig| instance, with the exception of @@ -100,6 +100,7 @@ DataReductionProxyConfig( scoped_refptr<base::SingleThreadTaskRunner> io_task_runner, net::NetLog* net_log, + network::NetworkConnectionTracker* network_connection_tracker, std::unique_ptr<DataReductionProxyConfigValues> config_values, DataReductionProxyConfigurator* configurator, DataReductionProxyEventCreator* event_creator); @@ -276,9 +277,8 @@ // |configurator_|. Used by the Data Reduction Proxy config service client. void ReloadConfig(); - // NetworkChangeNotifier::NetworkChangeObserver implementation: - void OnNetworkChanged( - net::NetworkChangeNotifier::ConnectionType type) override; + // network::NetworkConnectionTracker::NetworkConnectionObserver: + void OnConnectionChanged(network::mojom::ConnectionType type) override; // Invoked to continue network changed handling after the network id is // retrieved. If |get_network_id_asynchronously_| is set, the network id is @@ -357,6 +357,9 @@ net::NetLog* net_log_; net::NetLogWithSource net_log_with_source_; + // Watches for network connection changes. + network::NetworkConnectionTracker* network_connection_tracker_; + // The caller must ensure that the |configurator_| outlives this instance. DataReductionProxyConfigurator* configurator_; @@ -367,7 +370,7 @@ base::ThreadChecker thread_checker_; // The current connection type. - net::NetworkChangeNotifier::ConnectionType connection_type_; + network::mojom::ConnectionType connection_type_; // Stores the properties of the proxy which is currently being probed. The // values are valid only if a probe (or warmup URL) fetch is currently
diff --git a/components/data_reduction_proxy/core/browser/data_reduction_proxy_config_service_client.cc b/components/data_reduction_proxy/core/browser/data_reduction_proxy_config_service_client.cc index 97cc1037bb..29ec2d2 100644 --- a/components/data_reduction_proxy/core/browser/data_reduction_proxy_config_service_client.cc +++ b/components/data_reduction_proxy/core/browser/data_reduction_proxy_config_service_client.cc
@@ -151,6 +151,7 @@ DataReductionProxyEventCreator* event_creator, DataReductionProxyIOData* io_data, net::NetLog* net_log, + network::NetworkConnectionTracker* network_connection_tracker, ConfigStorer config_storer) : params_(std::move(params)), request_options_(request_options), @@ -159,6 +160,7 @@ event_creator_(event_creator), io_data_(io_data), net_log_(net_log), + network_connection_tracker_(network_connection_tracker), config_storer_(config_storer), backoff_entry_(&backoff_policy), config_service_url_(util::AddApiKeyToUrl(params::GetConfigServiceURL())), @@ -191,7 +193,7 @@ DataReductionProxyConfigServiceClient:: ~DataReductionProxyConfigServiceClient() { - net::NetworkChangeNotifier::RemoveNetworkChangeObserver(this); + network_connection_tracker_->RemoveNetworkConnectionObserver(this); } base::TimeDelta @@ -235,8 +237,8 @@ &DataReductionProxyConfigServiceClient::OnApplicationStateChange, base::Unretained(this)))); #endif - net::NetworkChangeNotifier::AddNetworkChangeObserver(this); url_request_context_getter_ = url_request_context_getter; + network_connection_tracker_->AddNetworkConnectionObserver(this); } void DataReductionProxyConfigServiceClient::SetEnabled(bool enabled) { @@ -362,10 +364,12 @@ RetrieveConfig(); + auto connection_type = network::mojom::ConnectionType::CONNECTION_NONE; + network_connection_tracker_->GetConnectionType(&connection_type, + base::DoNothing()); if (!load_timing_info.send_start.is_null() && !load_timing_info.request_start.is_null() && - net::NetworkChangeNotifier::GetConnectionType() != - net::NetworkChangeNotifier::CONNECTION_NONE && + connection_type != network::mojom::ConnectionType::CONNECTION_NONE && last_ip_address_change_ < load_timing_info.request_start) { // Record only if there was no change in the IP address since the // request started. @@ -396,11 +400,11 @@ return base::Time::Now(); } -void DataReductionProxyConfigServiceClient::OnNetworkChanged( - net::NetworkChangeNotifier::ConnectionType type) { +void DataReductionProxyConfigServiceClient::OnConnectionChanged( + network::mojom::ConnectionType type) { DCHECK(thread_checker_.CalledOnValidThread()); - if (type == net::NetworkChangeNotifier::CONNECTION_NONE) + if (type == network::mojom::ConnectionType::CONNECTION_NONE) return; GetBackoffEntry()->Reset(); @@ -538,8 +542,10 @@ ClientConfig config; bool succeeded = false; - if (net::NetworkChangeNotifier::GetConnectionType() != - net::NetworkChangeNotifier::CONNECTION_NONE) { + auto connection_type = network::mojom::ConnectionType::CONNECTION_NONE; + network_connection_tracker_->GetConnectionType(&connection_type, + base::DoNothing()); + if (connection_type != network::mojom::ConnectionType::CONNECTION_NONE) { base::UmaHistogramSparse(kUMAConfigServiceFetchResponseCode, response_code); }
diff --git a/components/data_reduction_proxy/core/browser/data_reduction_proxy_config_service_client.h b/components/data_reduction_proxy/core/browser/data_reduction_proxy_config_service_client.h index 87aa6a52..c18e0e5 100644 --- a/components/data_reduction_proxy/core/browser/data_reduction_proxy_config_service_client.h +++ b/components/data_reduction_proxy/core/browser/data_reduction_proxy_config_service_client.h
@@ -17,9 +17,9 @@ #include "base/time/time.h" #include "base/timer/timer.h" #include "net/base/backoff_entry.h" -#include "net/base/network_change_notifier.h" #include "net/log/net_log_with_source.h" #include "net/url_request/url_fetcher_delegate.h" +#include "services/network/public/cpp/network_connection_tracker.h" #include "url/gurl.h" #if defined(OS_ANDROID) @@ -83,7 +83,7 @@ // fetch policy is different if Chrome is in the background. Every time a config // is fetched, it is written to the disk. class DataReductionProxyConfigServiceClient - : public net::NetworkChangeNotifier::NetworkChangeObserver, + : public network::NetworkConnectionTracker::NetworkConnectionObserver, public net::URLFetcherDelegate { public: // The caller must ensure that all parameters remain alive for the lifetime of @@ -98,6 +98,7 @@ DataReductionProxyEventCreator* event_creator, DataReductionProxyIOData* io_data, net::NetLog* net_log, + network::NetworkConnectionTracker* network_connection_tracker, ConfigStorer config_storer); ~DataReductionProxyConfigServiceClient() override; @@ -162,9 +163,8 @@ const base::TimeDelta& config_expiration, const base::TimeDelta& backoff_delay); - // Override of net::NetworkChangeNotifier::NetworkChangeObserver. - void OnNetworkChanged( - net::NetworkChangeNotifier::ConnectionType type) override; + // Override of network::NetworkConnectionTracker::NetworkConnectionObserver. + void OnConnectionChanged(network::mojom::ConnectionType type) override; // Override of net::URLFetcherDelegate. void OnURLFetchComplete(const net::URLFetcher* source) override; @@ -222,6 +222,9 @@ // The caller must ensure that the |net_log_| outlives this instance. net::NetLog* net_log_; + // Watches for network changes. + network::NetworkConnectionTracker* network_connection_tracker_; + // Used to persist a serialized Data Reduction Proxy configuration. ConfigStorer config_storer_;
diff --git a/components/data_reduction_proxy/core/browser/data_reduction_proxy_config_service_client_unittest.cc b/components/data_reduction_proxy/core/browser/data_reduction_proxy_config_service_client_unittest.cc index a7853c5..bd5d0b4 100644 --- a/components/data_reduction_proxy/core/browser/data_reduction_proxy_config_service_client_unittest.cc +++ b/components/data_reduction_proxy/core/browser/data_reduction_proxy_config_service_client_unittest.cc
@@ -537,6 +537,7 @@ base::HistogramTester histogram_tester; AddMockFailure(); AddMockFailure(); + AddMockSuccess(); EXPECT_EQ(0, config_client()->failed_attempts_before_success()); @@ -703,8 +704,8 @@ EXPECT_EQ(kFailureCount, config_client()->GetBackoffErrorCount()); // IP address change should reset. - config_client()->OnNetworkChanged( - net::NetworkChangeNotifier::CONNECTION_WIFI); + config_client()->OnConnectionChanged( + network::mojom::ConnectionType::CONNECTION_WIFI); EXPECT_EQ(0, config_client()->GetBackoffErrorCount()); EXPECT_EQ(i == 0, persisted_config().empty()); EXPECT_EQ(i == 0, persisted_config_retrieval_time().is_null()); @@ -746,8 +747,8 @@ EXPECT_EQ(kFailureCount, config_client()->GetBackoffErrorCount()); // IP address change should reset. - config_client()->OnNetworkChanged( - net::NetworkChangeNotifier::CONNECTION_WIFI); + config_client()->OnConnectionChanged( + network::mojom::ConnectionType::CONNECTION_WIFI); EXPECT_EQ(0, config_client()->GetBackoffErrorCount()); EXPECT_TRUE(persisted_config().empty()); EXPECT_TRUE(persisted_config_retrieval_time().is_null()); @@ -797,8 +798,8 @@ } EXPECT_EQ(0, config_client()->GetBackoffErrorCount()); - config_client()->OnNetworkChanged( - net::NetworkChangeNotifier::CONNECTION_WIFI); + config_client()->OnConnectionChanged( + network::mojom::ConnectionType::CONNECTION_WIFI); EXPECT_EQ(0, config_client()->GetBackoffErrorCount()); config_client()->RetrieveConfig();
diff --git a/components/data_reduction_proxy/core/browser/data_reduction_proxy_config_test_utils.cc b/components/data_reduction_proxy/core/browser/data_reduction_proxy_config_test_utils.cc index 6a8c2ba..966f9667 100644 --- a/components/data_reduction_proxy/core/browser/data_reduction_proxy_config_test_utils.cc +++ b/components/data_reduction_proxy/core/browser/data_reduction_proxy_config_test_utils.cc
@@ -24,12 +24,14 @@ TestDataReductionProxyConfig::TestDataReductionProxyConfig( scoped_refptr<base::SingleThreadTaskRunner> io_task_runner, net::NetLog* net_log, + network::NetworkConnectionTracker* network_connection_tracker, DataReductionProxyConfigurator* configurator, DataReductionProxyEventCreator* event_creator) : TestDataReductionProxyConfig( std::make_unique<TestDataReductionProxyParams>(), io_task_runner, net_log, + network_connection_tracker, configurator, event_creator) {} @@ -37,10 +39,12 @@ std::unique_ptr<DataReductionProxyConfigValues> config_values, scoped_refptr<base::SingleThreadTaskRunner> io_task_runner, net::NetLog* net_log, + network::NetworkConnectionTracker* network_connection_tracker, DataReductionProxyConfigurator* configurator, DataReductionProxyEventCreator* event_creator) : DataReductionProxyConfig(io_task_runner, net_log, + network_connection_tracker, std::move(config_values), configurator, event_creator), @@ -142,11 +146,13 @@ std::unique_ptr<DataReductionProxyConfigValues> config_values, scoped_refptr<base::SingleThreadTaskRunner> io_task_runner, net::NetLog* net_log, + network::NetworkConnectionTracker* network_connection_tracker, DataReductionProxyConfigurator* configurator, DataReductionProxyEventCreator* event_creator) : TestDataReductionProxyConfig(std::move(config_values), io_task_runner, net_log, + network_connection_tracker, configurator, event_creator) {}
diff --git a/components/data_reduction_proxy/core/browser/data_reduction_proxy_config_test_utils.h b/components/data_reduction_proxy/core/browser/data_reduction_proxy_config_test_utils.h index 3612ad2..1cd878b 100644 --- a/components/data_reduction_proxy/core/browser/data_reduction_proxy_config_test_utils.h +++ b/components/data_reduction_proxy/core/browser/data_reduction_proxy_config_test_utils.h
@@ -24,6 +24,10 @@ class NetLog; } +namespace network { +class NetworkConnectionTracker; +} + namespace data_reduction_proxy { class DataReductionProxyConfigurator; @@ -40,6 +44,7 @@ TestDataReductionProxyConfig( scoped_refptr<base::SingleThreadTaskRunner> io_task_runner, net::NetLog* net_log, + network::NetworkConnectionTracker* network_connection_tracker, DataReductionProxyConfigurator* configurator, DataReductionProxyEventCreator* event_creator); @@ -50,6 +55,7 @@ std::unique_ptr<DataReductionProxyConfigValues> config_values, scoped_refptr<base::SingleThreadTaskRunner> io_task_runner, net::NetLog* net_log, + network::NetworkConnectionTracker* network_connection_tracker, DataReductionProxyConfigurator* configurator, DataReductionProxyEventCreator* event_creator); @@ -78,7 +84,7 @@ void SetIsCaptivePortal(bool is_captive_portal); void SetConnectionTypeForTesting( - net::NetworkChangeNotifier::ConnectionType connection_type) { + network::mojom::ConnectionType connection_type) { connection_type_ = connection_type; } @@ -144,6 +150,7 @@ std::unique_ptr<DataReductionProxyConfigValues> config_values, scoped_refptr<base::SingleThreadTaskRunner> io_task_runner, net::NetLog* net_log, + network::NetworkConnectionTracker* network_connection_tracker, DataReductionProxyConfigurator* configurator, DataReductionProxyEventCreator* event_creator); ~MockDataReductionProxyConfig() override;
diff --git a/components/data_reduction_proxy/core/browser/data_reduction_proxy_config_unittest.cc b/components/data_reduction_proxy/core/browser/data_reduction_proxy_config_unittest.cc index d30bf2f..439d150a 100644 --- a/components/data_reduction_proxy/core/browser/data_reduction_proxy_config_unittest.cc +++ b/components/data_reduction_proxy/core/browser/data_reduction_proxy_config_unittest.cc
@@ -94,9 +94,7 @@ ~DataReductionProxyConfigTest() override {} void SetUp() override { - net::NetworkChangeNotifier::SetTestNotificationsOnly(true); base::RunLoop().RunUntilIdle(); - network_change_notifier_.reset(net::NetworkChangeNotifier::CreateMock()); test_context_ = DataReductionProxyTestContext::Builder() .WithMockDataReductionProxyService() @@ -142,7 +140,7 @@ }; void CheckSecureProxyCheckOnNetworkChange( - net::NetworkChangeNotifier::ConnectionType connection_type, + network::mojom::ConnectionType connection_type, const std::string& response, bool is_captive_portal, int response_code, @@ -150,8 +148,7 @@ SecureProxyCheckFetchResult expected_fetch_result, const std::vector<net::ProxyServer>& expected_proxies_for_http) { base::HistogramTester histogram_tester; - net::NetworkChangeNotifier::NotifyObserversOfNetworkChangeForTests( - connection_type); + test_network_connection_tracker()->SetConnectionType(connection_type); TestResponder responder; responder.response = response; @@ -184,7 +181,8 @@ std::unique_ptr<DataReductionProxyConfig> BuildConfig( std::unique_ptr<DataReductionProxyParams> params) { return std::make_unique<DataReductionProxyConfig>( - task_runner(), test_context_->net_log(), std::move(params), + task_runner(), test_context_->net_log(), + test_context_->test_network_connection_tracker(), std::move(params), test_context_->configurator(), test_context_->event_creator()); } @@ -212,6 +210,11 @@ net::NetLog* net_log() const { return test_context_->net_log(); } + network::TestNetworkConnectionTracker* test_network_connection_tracker() + const { + return test_context_->test_network_connection_tracker(); + } + std::vector<net::ProxyServer> GetConfiguredProxiesForHttp() const { return test_context_->GetConfiguredProxiesForHttp(); } @@ -221,7 +224,6 @@ std::unique_ptr<DataReductionProxyTestContext> test_context_; private: - std::unique_ptr<net::NetworkChangeNotifier> network_change_notifier_; std::unique_ptr<TestDataReductionProxyParams> expected_params_; bool mock_config_used_; @@ -261,8 +263,8 @@ GetConfiguredProxiesForHttp()); test_config()->SetCurrentNetworkID("wifi,test"); - net::NetworkChangeNotifier::NotifyObserversOfNetworkChangeForTests( - net::NetworkChangeNotifier::CONNECTION_WIFI); + test_network_connection_tracker()->SetConnectionType( + network::mojom::ConnectionType::CONNECTION_WIFI); base::RunLoop().RunUntilIdle(); test_config()->UpdateConfigForTesting(true /* enabled */, false /* secure_proxies_allowed */, @@ -273,8 +275,8 @@ base::RunLoop().RunUntilIdle(); test_config()->SetCurrentNetworkID("cell,test"); - net::NetworkChangeNotifier::NotifyObserversOfNetworkChangeForTests( - net::NetworkChangeNotifier::CONNECTION_2G); + test_network_connection_tracker()->SetConnectionType( + network::mojom::ConnectionType::CONNECTION_2G); base::RunLoop().RunUntilIdle(); test_config()->UpdateConfigForTesting(true /* enabled */, false /* secure_proxies_allowed */, @@ -284,8 +286,8 @@ // On network change, persisted config should be read, and config reloaded. test_config()->SetCurrentNetworkID("wifi,test"); - net::NetworkChangeNotifier::NotifyObserversOfNetworkChangeForTests( - net::NetworkChangeNotifier::CONNECTION_WIFI); + test_network_connection_tracker()->SetConnectionType( + network::mojom::ConnectionType::CONNECTION_WIFI); base::RunLoop().RunUntilIdle(); EXPECT_EQ(std::vector<net::ProxyServer>({kHttpProxy}), GetConfiguredProxiesForHttp()); @@ -309,41 +311,43 @@ // Connection change triggers a secure proxy check that succeeds. Proxy // remains unrestricted. CheckSecureProxyCheckOnNetworkChange( - net::NetworkChangeNotifier::CONNECTION_WIFI, "OK", false, net::HTTP_OK, - kSuccess, SUCCEEDED_PROXY_ALREADY_ENABLED, {kHttpsProxy, kHttpProxy}); + network::mojom::ConnectionType::CONNECTION_WIFI, "OK", false, + net::HTTP_OK, kSuccess, SUCCEEDED_PROXY_ALREADY_ENABLED, + {kHttpsProxy, kHttpProxy}); // Connection change triggers a secure proxy check that succeeds but captive // portal fails. Proxy is restricted. CheckSecureProxyCheckOnNetworkChange( - net::NetworkChangeNotifier::CONNECTION_WIFI, "OK", true, net::HTTP_OK, + network::mojom::ConnectionType::CONNECTION_WIFI, "OK", true, net::HTTP_OK, kSuccess, SUCCEEDED_PROXY_ALREADY_ENABLED, std::vector<net::ProxyServer>(1, kHttpProxy)); // Connection change triggers a secure proxy check that fails. Proxy is // restricted. CheckSecureProxyCheckOnNetworkChange( - net::NetworkChangeNotifier::CONNECTION_WIFI, "Bad", false, net::HTTP_OK, - kSuccess, FAILED_PROXY_DISABLED, + network::mojom::ConnectionType::CONNECTION_WIFI, "Bad", false, + net::HTTP_OK, kSuccess, FAILED_PROXY_DISABLED, std::vector<net::ProxyServer>(1, kHttpProxy)); // Connection change triggers a secure proxy check that succeeds. Proxies // are unrestricted. CheckSecureProxyCheckOnNetworkChange( - net::NetworkChangeNotifier::CONNECTION_WIFI, "OK", false, net::HTTP_OK, - kSuccess, SUCCEEDED_PROXY_ENABLED, {kHttpsProxy, kHttpProxy}); + network::mojom::ConnectionType::CONNECTION_WIFI, "OK", false, + net::HTTP_OK, kSuccess, SUCCEEDED_PROXY_ENABLED, + {kHttpsProxy, kHttpProxy}); // Connection change triggers a secure proxy check that fails. Proxy is // restricted. CheckSecureProxyCheckOnNetworkChange( - net::NetworkChangeNotifier::CONNECTION_WIFI, "Bad", true, net::HTTP_OK, - kSuccess, FAILED_PROXY_DISABLED, + network::mojom::ConnectionType::CONNECTION_WIFI, "Bad", true, + net::HTTP_OK, kSuccess, FAILED_PROXY_DISABLED, std::vector<net::ProxyServer>(1, kHttpProxy)); // Connection change triggers a secure proxy check that fails due to the // network changing again. This should be ignored, so the proxy should remain // unrestricted. CheckSecureProxyCheckOnNetworkChange( - net::NetworkChangeNotifier::CONNECTION_WIFI, std::string(), false, + network::mojom::ConnectionType::CONNECTION_WIFI, std::string(), false, net::URLFetcher::RESPONSE_CODE_INVALID, net::URLRequestStatus(net::URLRequestStatus::FAILED, net::ERR_INTERNET_DISCONNECTED), @@ -352,21 +356,22 @@ // Connection change triggers a secure proxy check that fails. Proxy remains // restricted. CheckSecureProxyCheckOnNetworkChange( - net::NetworkChangeNotifier::CONNECTION_WIFI, "Bad", false, net::HTTP_OK, - kSuccess, FAILED_PROXY_ALREADY_DISABLED, + network::mojom::ConnectionType::CONNECTION_WIFI, "Bad", false, + net::HTTP_OK, kSuccess, FAILED_PROXY_ALREADY_DISABLED, std::vector<net::ProxyServer>(1, kHttpProxy)); // Connection change triggers a secure proxy check that succeeds. Proxy is // unrestricted. CheckSecureProxyCheckOnNetworkChange( - net::NetworkChangeNotifier::CONNECTION_WIFI, "OK", false, net::HTTP_OK, - kSuccess, SUCCEEDED_PROXY_ENABLED, {kHttpsProxy, kHttpProxy}); + network::mojom::ConnectionType::CONNECTION_WIFI, "OK", false, + net::HTTP_OK, kSuccess, SUCCEEDED_PROXY_ENABLED, + {kHttpsProxy, kHttpProxy}); // Connection change triggers a secure proxy check that fails due to the // network changing again. This should be ignored, so the proxy should remain // unrestricted. CheckSecureProxyCheckOnNetworkChange( - net::NetworkChangeNotifier::CONNECTION_WIFI, std::string(), false, + network::mojom::ConnectionType::CONNECTION_WIFI, std::string(), false, net::URLFetcher::RESPONSE_CODE_INVALID, net::URLRequestStatus(net::URLRequestStatus::FAILED, net::ERR_INTERNET_DISCONNECTED), @@ -375,7 +380,7 @@ // Connection change triggers a secure proxy check that fails because of a // redirect response, e.g. by a captive portal. Proxy is restricted. CheckSecureProxyCheckOnNetworkChange( - net::NetworkChangeNotifier::CONNECTION_WIFI, "Bad", false, + network::mojom::ConnectionType::CONNECTION_WIFI, "Bad", false, net::HTTP_FOUND, net::URLRequestStatus(net::URLRequestStatus::CANCELED, net::ERR_ABORTED), FAILED_PROXY_DISABLED, std::vector<net::ProxyServer>(1, kHttpProxy)); @@ -426,8 +431,9 @@ "Enabled"); base::CommandLine::ForCurrentProcess()->InitFromArgv(0, nullptr); - TestDataReductionProxyConfig config(task_runner(), nullptr, configurator(), - event_creator()); + TestDataReductionProxyConfig config(task_runner(), nullptr, + test_network_connection_tracker(), + configurator(), event_creator()); NetworkPropertiesManager network_properties_manager( base::DefaultClock::GetInstance(), test_context_->pref_service(), @@ -442,7 +448,7 @@ // Set the connection type to WiFi so that warm up URL is fetched even if // the test device does not have connectivity. - config.connection_type_ = net::NetworkChangeNotifier::CONNECTION_WIFI; + config.connection_type_ = network::mojom::ConnectionType::CONNECTION_WIFI; config.SetProxyConfig(test.data_reduction_proxy_enabled, true); ASSERT_TRUE(params::FetchWarmupProbeURLEnabled()); @@ -463,8 +469,9 @@ base::HistogramTester histogram_tester; // Set the connection type to 4G so that warm up URL is fetched even if // the test device does not have connectivity. - net::NetworkChangeNotifier::NotifyObserversOfNetworkChangeForTests( - net::NetworkChangeNotifier::CONNECTION_4G); + + test_network_connection_tracker()->SetConnectionType( + network::mojom::ConnectionType::CONNECTION_4G); RunUntilIdle(); if (test.data_reduction_proxy_enabled) { @@ -493,8 +500,8 @@ base::HistogramTester histogram_tester; // Warm up URL should not be fetched since the device does not have // connectivity. - net::NetworkChangeNotifier::NotifyObserversOfNetworkChangeForTests( - net::NetworkChangeNotifier::CONNECTION_NONE); + test_network_connection_tracker()->SetConnectionType( + network::mojom::ConnectionType::CONNECTION_NONE); RunUntilIdle(); if (test.data_reduction_proxy_enabled) { @@ -780,8 +787,9 @@ params->proxies_for_http(); ASSERT_LT(0U, expected_proxies.size()); - DataReductionProxyConfig config(task_runner(), net_log(), std::move(params), - configurator(), event_creator()); + DataReductionProxyConfig config( + task_runner(), net_log(), test_network_connection_tracker(), + std::move(params), configurator(), event_creator()); for (size_t expected_proxy_index = 0U; expected_proxy_index < expected_proxies.size(); ++expected_proxy_index) { @@ -854,8 +862,8 @@ config_values->UpdateValues(proxies_for_http); std::unique_ptr<DataReductionProxyConfig> config(new DataReductionProxyConfig( - task_runner(), net_log(), std::move(config_values), configurator(), - event_creator())); + task_runner(), net_log(), test_network_connection_tracker(), + std::move(config_values), configurator(), event_creator())); for (const auto& test : tests) { base::Optional<DataReductionProxyTypeInfo> proxy_type_info = config->FindConfiguredDataReductionProxy( @@ -1422,8 +1430,8 @@ // A change in the connection type should reset the probe fetch attempt count, // and trigger fetching of the probe URL. test_config()->SetCurrentNetworkID("wifi,test"); - net::NetworkChangeNotifier::NotifyObserversOfNetworkChangeForTests( - net::NetworkChangeNotifier::CONNECTION_WIFI); + test_network_connection_tracker()->SetConnectionType( + network::mojom::ConnectionType::CONNECTION_WIFI); base::RunLoop().RunUntilIdle(); EXPECT_EQ(std::make_pair(true, false), test_config()->GetInFlightWarmupProxyDetails());
diff --git a/components/data_reduction_proxy/core/browser/data_reduction_proxy_delegate.cc b/components/data_reduction_proxy/core/browser/data_reduction_proxy_delegate.cc index c58414a..a1e05ee 100644 --- a/components/data_reduction_proxy/core/browser/data_reduction_proxy_delegate.cc +++ b/components/data_reduction_proxy/core/browser/data_reduction_proxy_delegate.cc
@@ -39,14 +39,16 @@ const DataReductionProxyConfigurator* configurator, DataReductionProxyEventCreator* event_creator, DataReductionProxyBypassStats* bypass_stats, - net::NetLog* net_log) + net::NetLog* net_log, + network::NetworkConnectionTracker* network_connection_tracker) : config_(config), configurator_(configurator), event_creator_(event_creator), bypass_stats_(bypass_stats), tick_clock_(base::DefaultTickClock::GetInstance()), io_data_(nullptr), - net_log_(net_log) { + net_log_(net_log), + network_connection_tracker_(network_connection_tracker) { DCHECK(config_); DCHECK(configurator_); DCHECK(event_creator_); @@ -58,14 +60,14 @@ DataReductionProxyDelegate::~DataReductionProxyDelegate() { DCHECK(thread_checker_.CalledOnValidThread()); - net::NetworkChangeNotifier::RemoveNetworkChangeObserver(this); + network_connection_tracker_->RemoveNetworkConnectionObserver(this); } void DataReductionProxyDelegate::InitializeOnIOThread( DataReductionProxyIOData* io_data) { DCHECK(io_data); DCHECK(thread_checker_.CalledOnValidThread()); - net::NetworkChangeNotifier::AddNetworkChangeObserver(this); + network_connection_tracker_->AddNetworkConnectionObserver(this); io_data_ = io_data; } @@ -238,11 +240,11 @@ QUIC_PROXY_STATUS_BOUNDARY); } -void DataReductionProxyDelegate::OnNetworkChanged( - net::NetworkChangeNotifier::ConnectionType type) { +void DataReductionProxyDelegate::OnConnectionChanged( + network::mojom::ConnectionType type) { DCHECK(thread_checker_.CalledOnValidThread()); - if (type == net::NetworkChangeNotifier::CONNECTION_NONE) + if (type == network::mojom::ConnectionType::CONNECTION_NONE) return; last_network_change_time_ = tick_clock_->NowTicks();
diff --git a/components/data_reduction_proxy/core/browser/data_reduction_proxy_delegate.h b/components/data_reduction_proxy/core/browser/data_reduction_proxy_delegate.h index dd575589..165ad2c7 100644 --- a/components/data_reduction_proxy/core/browser/data_reduction_proxy_delegate.h +++ b/components/data_reduction_proxy/core/browser/data_reduction_proxy_delegate.h
@@ -9,9 +9,9 @@ #include "base/macros.h" #include "base/threading/thread_checker.h" -#include "net/base/network_change_notifier.h" #include "net/base/proxy_delegate.h" #include "net/proxy_resolution/proxy_retry_info.h" +#include "services/network/public/cpp/network_connection_tracker.h" #include "url/gurl.h" namespace base { @@ -34,15 +34,17 @@ class DataReductionProxyDelegate : public net::ProxyDelegate, - public net::NetworkChangeNotifier::NetworkChangeObserver { + public network::NetworkConnectionTracker::NetworkConnectionObserver { public: // ProxyDelegate instance is owned by io_thread. |auth_handler| and |config| // outlives this class instance. - DataReductionProxyDelegate(DataReductionProxyConfig* config, - const DataReductionProxyConfigurator* configurator, - DataReductionProxyEventCreator* event_creator, - DataReductionProxyBypassStats* bypass_stats, - net::NetLog* net_log); + DataReductionProxyDelegate( + DataReductionProxyConfig* config, + const DataReductionProxyConfigurator* configurator, + DataReductionProxyEventCreator* event_creator, + DataReductionProxyBypassStats* bypass_stats, + net::NetLog* net_log, + network::NetworkConnectionTracker* network_connection_tracker); ~DataReductionProxyDelegate() override; @@ -77,9 +79,8 @@ // Records the availability status of data reduction proxy. void RecordQuicProxyStatus(QuicProxyStatus status) const; - // NetworkChangeNotifier::NetworkChangeObserver: - void OnNetworkChanged( - net::NetworkChangeNotifier::ConnectionType type) override; + // network::NetworkConnectionTracker::NetworkConnectionObserver: + void OnConnectionChanged(network::mojom::ConnectionType type) override; // Checks if the first proxy server in |result| supports QUIC and if so // adds an alternative proxy configuration to |result|. @@ -103,6 +104,8 @@ net::NetLog* net_log_; + network::NetworkConnectionTracker* network_connection_tracker_; + base::ThreadChecker thread_checker_; DISALLOW_COPY_AND_ASSIGN(DataReductionProxyDelegate);
diff --git a/components/data_reduction_proxy/core/browser/data_reduction_proxy_delegate_unittest.cc b/components/data_reduction_proxy/core/browser/data_reduction_proxy_delegate_unittest.cc index 967c584..dfbe2d27 100644 --- a/components/data_reduction_proxy/core/browser/data_reduction_proxy_delegate_unittest.cc +++ b/components/data_reduction_proxy/core/browser/data_reduction_proxy_delegate_unittest.cc
@@ -41,7 +41,6 @@ #include "components/data_reduction_proxy/proto/client_config.pb.h" #include "net/base/host_port_pair.h" #include "net/base/net_errors.h" -#include "net/base/network_change_notifier.h" #include "net/base/proxy_delegate.h" #include "net/base/proxy_server.h" #include "net/http/http_request_headers.h" @@ -88,12 +87,14 @@ DataReductionProxyEventCreator* event_creator, DataReductionProxyBypassStats* bypass_stats, bool proxy_supports_quic, - net::NetLog* net_log) + net::NetLog* net_log, + network::NetworkConnectionTracker* network_connection_tracker) : DataReductionProxyDelegate(config, configurator, event_creator, bypass_stats, - net_log), + net_log, + network_connection_tracker), proxy_supports_quic_(proxy_supports_quic) {} ~TestDataReductionProxyDelegate() override {} @@ -187,11 +188,6 @@ lofi_ui_service_ = lofi_ui_service.get(); test_context_->io_data()->set_lofi_ui_service(std::move(lofi_ui_service)); - // Create a mock network change notifier to make it possible to call its - // static methods. - network_change_notifier_.reset(net::NetworkChangeNotifier::CreateMock()); - base::RunLoop().RunUntilIdle(); - proxy_delegate_ = test_context_->io_data()->CreateProxyDelegate(); context_.set_proxy_delegate(proxy_delegate_.get()); @@ -262,6 +258,10 @@ return proxy_delegate_.get(); } + network::NetworkConnectionTracker* network_connection_tracker() const { + return test_context_->test_network_connection_tracker(); + } + private: int64_t GetSessionNetworkStatsInfoInt64(const char* key) const { std::unique_ptr<base::DictionaryValue> session_network_stats_info = @@ -285,9 +285,8 @@ TestLoFiUIService* lofi_ui_service_; - std::unique_ptr<net::NetworkChangeNotifier> network_change_notifier_; - std::unique_ptr<DataReductionProxyDelegate> proxy_delegate_; std::unique_ptr<DataReductionProxyTestContext> test_context_; + std::unique_ptr<DataReductionProxyDelegate> proxy_delegate_; }; TEST_F(DataReductionProxyDelegateTest, OnResolveProxy) { @@ -484,7 +483,7 @@ TestDataReductionProxyDelegate delegate( config(), io_data()->configurator(), io_data()->event_creator(), io_data()->bypass_stats(), test.proxy_supports_quic, - io_data()->net_log()); + io_data()->net_log(), network_connection_tracker()); base::FieldTrialList field_trial_list(nullptr); base::FieldTrialList::CreateFieldTrial(
diff --git a/components/data_reduction_proxy/core/browser/data_reduction_proxy_interceptor_unittest.cc b/components/data_reduction_proxy/core/browser/data_reduction_proxy_interceptor_unittest.cc index a78df3f..5d0f3620 100644 --- a/components/data_reduction_proxy/core/browser/data_reduction_proxy_interceptor_unittest.cc +++ b/components/data_reduction_proxy/core/browser/data_reduction_proxy_interceptor_unittest.cc
@@ -359,8 +359,8 @@ net::MockClientSocketFactory mock_socket_factory_; net::TestURLRequestContext context_; net::URLRequestContextStorage context_storage_; - std::unique_ptr<net::ProxyDelegate> proxy_delegate_; std::unique_ptr<DataReductionProxyTestContext> drp_test_context_; + std::unique_ptr<net::ProxyDelegate> proxy_delegate_; }; const std::string kBody = "response body";
diff --git a/components/data_reduction_proxy/core/browser/data_reduction_proxy_io_data.cc b/components/data_reduction_proxy/core/browser/data_reduction_proxy_io_data.cc index 29b7657..be62e0ef 100644 --- a/components/data_reduction_proxy/core/browser/data_reduction_proxy_io_data.cc +++ b/components/data_reduction_proxy/core/browser/data_reduction_proxy_io_data.cc
@@ -98,6 +98,7 @@ Client client, PrefService* prefs, net::NetLog* net_log, + network::NetworkConnectionTracker* network_connection_tracker, scoped_refptr<base::SingleThreadTaskRunner> io_task_runner, scoped_refptr<base::SingleThreadTaskRunner> ui_task_runner, bool enabled, @@ -105,6 +106,7 @@ const std::string& channel) : client_(client), net_log_(net_log), + network_connection_tracker_(network_connection_tracker), io_task_runner_(io_task_runner), ui_task_runner_(ui_task_runner), data_use_observer_(nullptr), @@ -131,20 +133,22 @@ std::make_unique<DataReductionProxyMutableConfigValues>(); raw_mutable_config = mutable_config.get(); config_.reset(new DataReductionProxyConfig( - io_task_runner, net_log, std::move(mutable_config), configurator_.get(), - event_creator_.get())); + io_task_runner, net_log, network_connection_tracker_, + std::move(mutable_config), configurator_.get(), event_creator_.get())); } else { config_.reset(new DataReductionProxyConfig( - io_task_runner, net_log, std::move(params), configurator_.get(), - event_creator_.get())); + io_task_runner, net_log, network_connection_tracker_, std::move(params), + configurator_.get(), event_creator_.get())); } // It is safe to use base::Unretained here, since it gets executed // synchronously on the IO thread, and |this| outlives the caller (since the // caller is owned by |this|. bypass_stats_.reset(new DataReductionProxyBypassStats( - config_.get(), base::Bind(&DataReductionProxyIOData::SetUnreachable, - base::Unretained(this)))); + config_.get(), + base::BindRepeating(&DataReductionProxyIOData::SetUnreachable, + base::Unretained(this)), + network_connection_tracker_)); request_options_.reset( new DataReductionProxyRequestOptions(client_, config_.get())); request_options_->Init(); @@ -162,13 +166,14 @@ config_client_.reset(new DataReductionProxyConfigServiceClient( std::move(params), GetBackoffPolicy(), request_options_.get(), raw_mutable_config, config_.get(), event_creator_.get(), this, net_log_, + network_connection_tracker_, base::Bind(&DataReductionProxyIOData::StoreSerializedConfig, base::Unretained(this)))); } proxy_delegate_.reset(new DataReductionProxyDelegate( config_.get(), configurator_.get(), event_creator_.get(), - bypass_stats_.get(), net_log_)); + bypass_stats_.get(), net_log_, network_connection_tracker_)); network_properties_manager_.reset(new NetworkPropertiesManager( base::DefaultClock::GetInstance(), prefs, ui_task_runner_)); } @@ -179,6 +184,7 @@ scoped_refptr<base::SingleThreadTaskRunner> io_task_runner) : client_(Client::UNKNOWN), net_log_(nullptr), + network_connection_tracker_(nullptr), io_task_runner_(io_task_runner), ui_task_runner_(ui_task_runner), url_request_context_getter_(nullptr), @@ -291,7 +297,7 @@ DCHECK(io_task_runner_->BelongsToCurrentThread()); return std::make_unique<DataReductionProxyDelegate>( config_.get(), configurator_.get(), event_creator_.get(), - bypass_stats_.get(), net_log_); + bypass_stats_.get(), net_log_, network_connection_tracker_); } // TODO(kundaji): Rename this method to something more descriptive.
diff --git a/components/data_reduction_proxy/core/browser/data_reduction_proxy_io_data.h b/components/data_reduction_proxy/core/browser/data_reduction_proxy_io_data.h index 3a024c25..199ba0b 100644 --- a/components/data_reduction_proxy/core/browser/data_reduction_proxy_io_data.h +++ b/components/data_reduction_proxy/core/browser/data_reduction_proxy_io_data.h
@@ -37,6 +37,10 @@ class URLRequestInterceptor; } +namespace network { +class NetworkConnectionTracker; +} + namespace previews { class PreviewsDecider; } @@ -61,6 +65,7 @@ Client client, PrefService* prefs, net::NetLog* net_log, + network::NetworkConnectionTracker* network_connection_tracker, scoped_refptr<base::SingleThreadTaskRunner> io_task_runner, scoped_refptr<base::SingleThreadTaskRunner> ui_task_runner, bool enabled, @@ -304,6 +309,9 @@ // A net log. net::NetLog* net_log_; + // Watches for network connection changes. + network::NetworkConnectionTracker* network_connection_tracker_; + // IO and UI task runners, respectively. scoped_refptr<base::SingleThreadTaskRunner> io_task_runner_; scoped_refptr<base::SingleThreadTaskRunner> ui_task_runner_;
diff --git a/components/data_reduction_proxy/core/browser/data_reduction_proxy_io_data_unittest.cc b/components/data_reduction_proxy/core/browser/data_reduction_proxy_io_data_unittest.cc index 7c9c066..342fc94 100644 --- a/components/data_reduction_proxy/core/browser/data_reduction_proxy_io_data_unittest.cc +++ b/components/data_reduction_proxy/core/browser/data_reduction_proxy_io_data_unittest.cc
@@ -10,7 +10,6 @@ #include "base/memory/ref_counted.h" #include "base/metrics/field_trial.h" #include "base/run_loop.h" -#include "base/single_thread_task_runner.h" #include "base/strings/string_number_conversions.h" #include "base/test/scoped_task_environment.h" #include "base/time/time.h" @@ -33,6 +32,7 @@ #include "net/url_request/url_request_context_getter.h" #include "net/url_request/url_request_interceptor.h" #include "net/url_request/url_request_test_util.h" +#include "services/network/test/test_network_connection_tracker.h" #include "testing/gtest/include/gtest/gtest.h" namespace { @@ -104,9 +104,12 @@ }; TEST_F(DataReductionProxyIODataTest, TestConstruction) { + network::TestNetworkConnectionTracker network_connection_tracker( + true, network::mojom::ConnectionType::CONNECTION_UNKNOWN); + std::unique_ptr<DataReductionProxyIOData> io_data( new DataReductionProxyIOData( - Client::UNKNOWN, prefs(), net_log(), + Client::UNKNOWN, prefs(), net_log(), &network_connection_tracker, scoped_task_environment_.GetMainThreadTaskRunner(), scoped_task_environment_.GetMainThreadTaskRunner(), false /* enabled */, std::string() /* user_agent */,
diff --git a/components/data_reduction_proxy/core/browser/data_reduction_proxy_test_utils.cc b/components/data_reduction_proxy/core/browser/data_reduction_proxy_test_utils.cc index d1d1cd1..1b37914 100644 --- a/components/data_reduction_proxy/core/browser/data_reduction_proxy_test_utils.cc +++ b/components/data_reduction_proxy/core/browser/data_reduction_proxy_test_utils.cc
@@ -130,6 +130,7 @@ DataReductionProxyEventCreator* event_creator, DataReductionProxyIOData* io_data, net::NetLog* net_log, + network::NetworkConnectionTracker* network_connection_tracker, ConfigStorer config_storer) : DataReductionProxyConfigServiceClient(std::move(params), kTestBackoffPolicy, @@ -139,6 +140,7 @@ event_creator, io_data, net_log, + network_connection_tracker, config_storer), #if defined(OS_ANDROID) is_application_state_background_(false), @@ -261,6 +263,7 @@ std::unique_ptr<TestDataReductionProxyRequestOptions> request_options, std::unique_ptr<DataReductionProxyConfigurator> configurator, net::NetLog* net_log, + network::NetworkConnectionTracker* network_connection_tracker, bool enabled) : DataReductionProxyIOData(prefs, task_runner, task_runner), service_set_(false), @@ -273,9 +276,12 @@ request_options_ = std::move(request_options); configurator_ = std::move(configurator); net_log_ = net_log; + network_connection_tracker_ = network_connection_tracker; bypass_stats_.reset(new DataReductionProxyBypassStats( - config_.get(), base::Bind(&DataReductionProxyIOData::SetUnreachable, - base::Unretained(this)))); + config_.get(), + base::BindRepeating(&DataReductionProxyIOData::SetUnreachable, + base::Unretained(this)), + network_connection_tracker)); enabled_ = enabled; } @@ -420,6 +426,9 @@ std::unique_ptr<TestingPrefServiceSimple> pref_service( new TestingPrefServiceSimple()); std::unique_ptr<net::TestNetLog> net_log(new net::TestNetLog()); + std::unique_ptr<network::TestNetworkConnectionTracker> + test_network_connection_tracker(new network::TestNetworkConnectionTracker( + true, network::mojom::ConnectionType::CONNECTION_UNKNOWN)); std::unique_ptr<TestConfigStorer> config_storer( new TestConfigStorer(pref_service.get())); @@ -460,11 +469,13 @@ raw_mutable_config = mutable_config.get(); config.reset(new TestDataReductionProxyConfig( std::move(mutable_config), task_runner, net_log.get(), - configurator.get(), event_creator.get())); + test_network_connection_tracker.get(), configurator.get(), + event_creator.get())); } else if (use_mock_config_) { test_context_flags |= USE_MOCK_CONFIG; config.reset(new MockDataReductionProxyConfig( - std::move(params), task_runner, net_log.get(), configurator.get(), + std::move(params), task_runner, net_log.get(), + test_network_connection_tracker.get(), configurator.get(), event_creator.get())); } else { test_context_flags ^= USE_MOCK_CONFIG; @@ -472,7 +483,8 @@ params->SetProxiesForHttp(proxy_servers_); } config.reset(new TestDataReductionProxyConfig( - std::move(params), task_runner, net_log.get(), configurator.get(), + std::move(params), task_runner, net_log.get(), + test_network_connection_tracker.get(), configurator.get(), event_creator.get())); } @@ -506,7 +518,8 @@ new TestDataReductionProxyIOData( pref_service.get(), task_runner, std::move(config), std::move(event_creator), std::move(request_options), - std::move(configurator), net_log.get(), true /* enabled */)); + std::move(configurator), net_log.get(), + test_network_connection_tracker.get(), true /* enabled */)); io_data->SetSimpleURLRequestContextGetter(request_context_getter); if (use_test_config_client_) { @@ -514,13 +527,14 @@ config_client.reset(new TestDataReductionProxyConfigServiceClient( std::move(params), io_data->request_options(), raw_mutable_config, io_data->config(), io_data->event_creator(), io_data.get(), - net_log.get(), base::Bind(&TestConfigStorer::StoreSerializedConfig, - base::Unretained(config_storer.get())))); + net_log.get(), test_network_connection_tracker.get(), + base::BindRepeating(&TestConfigStorer::StoreSerializedConfig, + base::Unretained(config_storer.get())))); } else if (use_config_client_) { config_client.reset(new DataReductionProxyConfigServiceClient( std::move(params), GetBackoffPolicy(), io_data->request_options(), raw_mutable_config, io_data->config(), io_data->event_creator(), - io_data.get(), net_log.get(), + io_data.get(), net_log.get(), test_network_connection_tracker.get(), base::Bind(&TestConfigStorer::StoreSerializedConfig, base::Unretained(config_storer.get())))); } @@ -528,14 +542,16 @@ io_data->set_proxy_delegate(base::WrapUnique(new DataReductionProxyDelegate( io_data->config(), io_data->configurator(), io_data->event_creator(), - io_data->bypass_stats(), net_log.get()))); + io_data->bypass_stats(), net_log.get(), + test_network_connection_tracker.get()))); std::unique_ptr<DataReductionProxyTestContext> test_context( new DataReductionProxyTestContext( task_runner, std::move(pref_service), std::move(net_log), - request_context_getter, mock_socket_factory_, std::move(io_data), - std::move(settings), std::move(storage_delegate), - std::move(config_storer), raw_params, test_context_flags)); + std::move(test_network_connection_tracker), request_context_getter, + mock_socket_factory_, std::move(io_data), std::move(settings), + std::move(storage_delegate), std::move(config_storer), raw_params, + test_context_flags)); if (!skip_settings_initialization_) test_context->InitSettingsWithoutCheck(); @@ -547,6 +563,8 @@ const scoped_refptr<base::SingleThreadTaskRunner>& task_runner, std::unique_ptr<TestingPrefServiceSimple> simple_pref_service, std::unique_ptr<net::TestNetLog> net_log, + std::unique_ptr<network::TestNetworkConnectionTracker> + test_network_connection_tracker, scoped_refptr<net::URLRequestContextGetter> request_context_getter, net::MockClientSocketFactory* mock_socket_factory, std::unique_ptr<TestDataReductionProxyIOData> io_data, @@ -560,6 +578,8 @@ task_runner_(task_runner), simple_pref_service_(std::move(simple_pref_service)), net_log_(std::move(net_log)), + test_network_connection_tracker_( + std::move(test_network_connection_tracker)), request_context_getter_(request_context_getter), mock_socket_factory_(mock_socket_factory), io_data_(std::move(io_data)), @@ -619,9 +639,6 @@ settings_->data_reduction_proxy_service()->event_store()); io_data_->SetDataReductionProxyService( settings_->data_reduction_proxy_service()->GetWeakPtr()); - if (io_data_->config_client()) - io_data_->config_client()->InitializeOnIOThread( - request_context_getter_.get()); settings_->data_reduction_proxy_service()->SetIOData(io_data_->GetWeakPtr()); }
diff --git a/components/data_reduction_proxy/core/browser/data_reduction_proxy_test_utils.h b/components/data_reduction_proxy/core/browser/data_reduction_proxy_test_utils.h index 3c3f3c2..309a492d 100644 --- a/components/data_reduction_proxy/core/browser/data_reduction_proxy_test_utils.h +++ b/components/data_reduction_proxy/core/browser/data_reduction_proxy_test_utils.h
@@ -31,6 +31,7 @@ #include "net/base/proxy_server.h" #include "net/log/test_net_log.h" #include "net/url_request/url_request_context_getter.h" +#include "services/network/test/test_network_connection_tracker.h" #include "testing/gmock/include/gmock/gmock.h" class GURL; @@ -108,11 +109,12 @@ DataReductionProxyEventCreator* event_creator, DataReductionProxyIOData* io_data, net::NetLog* net_log, + network::NetworkConnectionTracker* network_connection_tracker, ConfigStorer config_storer); ~TestDataReductionProxyConfigServiceClient() override; - using DataReductionProxyConfigServiceClient::OnNetworkChanged; + using DataReductionProxyConfigServiceClient::OnConnectionChanged; void SetNow(const base::Time& time); @@ -222,6 +224,7 @@ std::unique_ptr<TestDataReductionProxyRequestOptions> request_options, std::unique_ptr<DataReductionProxyConfigurator> configurator, net::NetLog* net_log, + network::NetworkConnectionTracker* network_connection_tracker, bool enabled); ~TestDataReductionProxyIOData() override; @@ -459,6 +462,11 @@ return net_log_.get(); } + network::TestNetworkConnectionTracker* test_network_connection_tracker() + const { + return test_network_connection_tracker_.get(); + } + net::URLRequestContextGetter* request_context_getter() const { return request_context_getter_.get(); } @@ -515,6 +523,8 @@ const scoped_refptr<base::SingleThreadTaskRunner>& task_runner, std::unique_ptr<TestingPrefServiceSimple> simple_pref_service, std::unique_ptr<net::TestNetLog> net_log, + std::unique_ptr<network::TestNetworkConnectionTracker> + test_network_connection_tracker, scoped_refptr<net::URLRequestContextGetter> request_context_getter, net::MockClientSocketFactory* mock_socket_factory, std::unique_ptr<TestDataReductionProxyIOData> io_data, @@ -533,6 +543,8 @@ scoped_refptr<base::SingleThreadTaskRunner> task_runner_; std::unique_ptr<TestingPrefServiceSimple> simple_pref_service_; std::unique_ptr<net::TestNetLog> net_log_; + std::unique_ptr<network::TestNetworkConnectionTracker> + test_network_connection_tracker_; scoped_refptr<net::URLRequestContextGetter> request_context_getter_; // Non-owned pointer. Will be NULL if |this| was built without specifying a // |net::MockClientSocketFactory|.
diff --git a/components/download/content/factory/download_service_factory.cc b/components/download/content/factory/download_service_factory.cc index a2f01ef2..9f0713b 100644 --- a/components/download/content/factory/download_service_factory.cc +++ b/components/download/content/factory/download_service_factory.cc
@@ -46,6 +46,7 @@ std::unique_ptr<Store> store, std::unique_ptr<TaskScheduler> task_scheduler, std::unique_ptr<FileMonitor> file_monitor, + network::NetworkConnectionTracker* network_connection_tracker, const base::FilePath& files_storage_dir) { auto client_set = std::make_unique<ClientSet>(std::move(clients)); auto model = std::make_unique<ModelImpl>(std::move(store)); @@ -60,7 +61,7 @@ auto device_status_listener = std::make_unique<DeviceStatusListener>( config->network_startup_delay, config->network_change_delay, - std::move(battery_listener)); + std::move(battery_listener), network_connection_tracker); NavigationMonitor* navigation_monitor = NavigationMonitorFactory::GetForBrowserContext(browser_context); auto scheduler = std::make_unique<SchedulerImpl>( @@ -81,6 +82,7 @@ DownloadService* BuildDownloadService( content::BrowserContext* browser_context, std::unique_ptr<DownloadClientMap> clients, + network::NetworkConnectionTracker* network_connection_tracker, const base::FilePath& storage_dir, const scoped_refptr<base::SequencedTaskRunner>& background_task_runner, std::unique_ptr<TaskScheduler> task_scheduler) { @@ -103,13 +105,14 @@ return CreateDownloadServiceInternal( browser_context, std::move(clients), std::move(config), std::move(driver), std::move(store), std::move(task_scheduler), std::move(file_monitor), - files_storage_dir); + network_connection_tracker, files_storage_dir); } // Create download service for incognito mode without any database or file IO. DownloadService* BuildInMemoryDownloadService( content::BrowserContext* browser_context, std::unique_ptr<DownloadClientMap> clients, + network::NetworkConnectionTracker* network_connection_tracker, const base::FilePath& storage_dir, BlobTaskProxy::BlobContextGetter blob_context_getter, scoped_refptr<base::SingleThreadTaskRunner> io_task_runner) { @@ -134,7 +137,7 @@ return CreateDownloadServiceInternal( browser_context, std::move(clients), std::move(config), std::move(driver), std::move(store), std::move(task_scheduler), std::move(file_monitor), - files_storage_dir); + network_connection_tracker, files_storage_dir); } } // namespace download
diff --git a/components/download/content/factory/download_service_factory.h b/components/download/content/factory/download_service_factory.h index 0f7a1dc..e571180 100644 --- a/components/download/content/factory/download_service_factory.h +++ b/components/download/content/factory/download_service_factory.h
@@ -18,6 +18,10 @@ class BrowserContext; } // namespace content +namespace network { +class NetworkConnectionTracker; +} + namespace download { class DownloadService; @@ -36,6 +40,7 @@ DownloadService* BuildDownloadService( content::BrowserContext* browser_context, std::unique_ptr<DownloadClientMap> clients, + network::NetworkConnectionTracker* network_connection_tracker, const base::FilePath& storage_dir, const scoped_refptr<base::SequencedTaskRunner>& background_task_runner, std::unique_ptr<TaskScheduler> task_scheduler); @@ -45,6 +50,7 @@ DownloadService* BuildInMemoryDownloadService( content::BrowserContext* browser_context, std::unique_ptr<DownloadClientMap> clients, + network::NetworkConnectionTracker* network_connection_tracker, const base::FilePath& storage_dir, BlobTaskProxy::BlobContextGetter blob_context_getter, scoped_refptr<base::SingleThreadTaskRunner> io_task_runner);
diff --git a/components/download/internal/background_service/android/network_status_listener_android.cc b/components/download/internal/background_service/android/network_status_listener_android.cc index 0de9b90..62676aa 100644 --- a/components/download/internal/background_service/android/network_status_listener_android.cc +++ b/components/download/internal/background_service/android/network_status_listener_android.cc
@@ -18,7 +18,7 @@ const base::android::JavaRef<jobject>& jobj, jint connectionType) { DCHECK(observer_); - using ConnectionType = net::NetworkChangeNotifier::ConnectionType; + using ConnectionType = network::mojom::ConnectionType; ConnectionType connection_type = static_cast<ConnectionType>(connectionType); observer_->OnNetworkChanged(connection_type); } @@ -39,13 +39,12 @@ base::android::AttachCurrentThread(), java_obj_); } -net::NetworkChangeNotifier::ConnectionType +network::mojom::ConnectionType NetworkStatusListenerAndroid::GetConnectionType() { int connection_type = Java_NetworkStatusListenerAndroid_getCurrentConnectionType( base::android::AttachCurrentThread(), java_obj_); - return static_cast<net::NetworkChangeNotifier::ConnectionType>( - connection_type); + return static_cast<network::mojom::ConnectionType>(connection_type); } } // namespace download
diff --git a/components/download/internal/background_service/android/network_status_listener_android.h b/components/download/internal/background_service/android/network_status_listener_android.h index 0362231..ceb8daa0 100644 --- a/components/download/internal/background_service/android/network_status_listener_android.h +++ b/components/download/internal/background_service/android/network_status_listener_android.h
@@ -25,7 +25,7 @@ // NetworkStatusListener implementation. void Start(NetworkStatusListener::Observer* observer) override; void Stop() override; - net::NetworkChangeNotifier::ConnectionType GetConnectionType() override; + network::mojom::ConnectionType GetConnectionType() override; void NotifyNetworkChange(JNIEnv* env, const base::android::JavaRef<jobject>& jobj,
diff --git a/components/download/internal/background_service/scheduler/device_status_listener.cc b/components/download/internal/background_service/scheduler/device_status_listener.cc index 116c5b8..56dd1f4 100644 --- a/components/download/internal/background_service/scheduler/device_status_listener.cc +++ b/components/download/internal/background_service/scheduler/device_status_listener.cc
@@ -23,18 +23,18 @@ } // Converts a ConnectionType to NetworkStatus. -NetworkStatus ToNetworkStatus(net::NetworkChangeNotifier::ConnectionType type) { +NetworkStatus ToNetworkStatus(network::mojom::ConnectionType type) { switch (type) { - case net::NetworkChangeNotifier::CONNECTION_ETHERNET: - case net::NetworkChangeNotifier::CONNECTION_WIFI: + case network::mojom::ConnectionType::CONNECTION_ETHERNET: + case network::mojom::ConnectionType::CONNECTION_WIFI: return NetworkStatus::UNMETERED; - case net::NetworkChangeNotifier::CONNECTION_2G: - case net::NetworkChangeNotifier::CONNECTION_3G: - case net::NetworkChangeNotifier::CONNECTION_4G: + case network::mojom::ConnectionType::CONNECTION_2G: + case network::mojom::ConnectionType::CONNECTION_3G: + case network::mojom::ConnectionType::CONNECTION_4G: return NetworkStatus::METERED; - case net::NetworkChangeNotifier::CONNECTION_UNKNOWN: - case net::NetworkChangeNotifier::CONNECTION_NONE: - case net::NetworkChangeNotifier::CONNECTION_BLUETOOTH: + case network::mojom::ConnectionType::CONNECTION_UNKNOWN: + case network::mojom::ConnectionType::CONNECTION_NONE: + case network::mojom::ConnectionType::CONNECTION_BLUETOOTH: return NetworkStatus::DISCONNECTED; } NOTREACHED(); @@ -97,13 +97,18 @@ DeviceStatusListener::DeviceStatusListener( const base::TimeDelta& startup_delay, const base::TimeDelta& online_delay, - std::unique_ptr<BatteryStatusListener> battery_listener) + std::unique_ptr<BatteryStatusListener> battery_listener, + network::NetworkConnectionTracker* network_connection_tracker) : observer_(nullptr), listening_(false), is_valid_state_(false), startup_delay_(startup_delay), online_delay_(online_delay), - battery_listener_(std::move(battery_listener)) {} +#if !defined(OS_ANDROID) + network_connection_tracker_(network_connection_tracker), +#endif + battery_listener_(std::move(battery_listener)) { +} DeviceStatusListener::~DeviceStatusListener() { Stop(); @@ -170,7 +175,7 @@ } void DeviceStatusListener::OnNetworkChanged( - net::NetworkChangeNotifier::ConnectionType type) { + network::mojom::ConnectionType type) { pending_network_status_ = ToNetworkStatus(type); if (pending_network_status_ == status_.network_status) { @@ -221,7 +226,8 @@ #if defined(OS_ANDROID) network_listener_ = std::make_unique<NetworkStatusListenerAndroid>(); #else - network_listener_ = std::make_unique<NetworkStatusListenerImpl>(); + network_listener_ = + std::make_unique<NetworkStatusListenerImpl>(network_connection_tracker_); #endif }
diff --git a/components/download/internal/background_service/scheduler/device_status_listener.h b/components/download/internal/background_service/scheduler/device_status_listener.h index 715f2e3..3f9189d 100644 --- a/components/download/internal/background_service/scheduler/device_status_listener.h +++ b/components/download/internal/background_service/scheduler/device_status_listener.h
@@ -9,9 +9,10 @@ #include "base/power_monitor/power_observer.h" #include "base/timer/timer.h" +#include "build/build_config.h" #include "components/download/internal/background_service/scheduler/device_status.h" #include "components/download/internal/background_service/scheduler/network_status_listener.h" -#include "net/base/network_change_notifier.h" +#include "services/network/public/cpp/network_connection_tracker.h" namespace download { @@ -73,10 +74,11 @@ virtual void OnDeviceStatusChanged(const DeviceStatus& device_status) = 0; }; - explicit DeviceStatusListener( + DeviceStatusListener( const base::TimeDelta& startup_delay, const base::TimeDelta& online_delay, - std::unique_ptr<BatteryStatusListener> battery_listener); + std::unique_ptr<BatteryStatusListener> battery_listener, + network::NetworkConnectionTracker* network_connection_tracker); ~DeviceStatusListener() override; bool is_valid_state() { return is_valid_state_; } @@ -94,6 +96,9 @@ // Creates the instance of |network_listener_|, visible for testing. virtual void BuildNetworkStatusListener(); + // NetworkStatusListener::Observer implementation. Visible for testing. + void OnNetworkChanged(network::mojom::ConnectionType type) override; + // Used to listen to network connectivity changes. std::unique_ptr<NetworkStatusListener> network_listener_; @@ -112,10 +117,6 @@ // Start after a delay to wait for potential network stack setup. void StartAfterDelay(); - // NetworkStatusListener::Observer implementation. - void OnNetworkChanged( - net::NetworkChangeNotifier::ConnectionType type) override; - // BatteryStatusListener::Observer implementation. void OnPowerStateChange(bool on_battery_power) override; @@ -137,6 +138,11 @@ // Pending network status used to update the current network status. NetworkStatus pending_network_status_ = NetworkStatus::DISCONNECTED; +#if !defined(OS_ANDROID) + // Used to listen for network connection changes. + network::NetworkConnectionTracker* network_connection_tracker_; +#endif + // Used to listen to battery status. std::unique_ptr<BatteryStatusListener> battery_listener_;
diff --git a/components/download/internal/background_service/scheduler/device_status_listener_unittest.cc b/components/download/internal/background_service/scheduler/device_status_listener_unittest.cc index 74ceabe5..89939a8 100644 --- a/components/download/internal/background_service/scheduler/device_status_listener_unittest.cc +++ b/components/download/internal/background_service/scheduler/device_status_listener_unittest.cc
@@ -10,6 +10,7 @@ #include "base/run_loop.h" #include "base/test/power_monitor_test_base.h" #include "components/download/internal/background_service/scheduler/network_status_listener.h" +#include "services/network/test/test_network_connection_tracker.h" #include "testing/gmock/include/gmock/gmock.h" #include "testing/gtest/include/gtest/gtest.h" @@ -17,7 +18,7 @@ using testing::InSequence; using ConnectionTypeObserver = net::NetworkChangeNotifier::ConnectionTypeObserver; -using ConnectionType = net::NetworkChangeNotifier::ConnectionType; +using ConnectionType = network::mojom::ConnectionType; namespace download { namespace { @@ -30,29 +31,6 @@ return arg.battery_status == value; } -// NetworkChangeNotifier that can change network type in tests. -class TestNetworkChangeNotifier : public net::NetworkChangeNotifier { - public: - TestNetworkChangeNotifier() - : conn_type_(ConnectionType::CONNECTION_UNKNOWN) {} - - // net::NetworkChangeNotifier implementation. - ConnectionType GetCurrentConnectionType() const override { - return conn_type_; - } - - // Changes the network type. - void ChangeNetworkType(ConnectionType type) { - conn_type_ = type; - net::NetworkChangeNotifier::NotifyObserversOfNetworkChangeForTests(type); - } - - private: - ConnectionType conn_type_; - - DISALLOW_COPY_AND_ASSIGN(TestNetworkChangeNotifier); -}; - class MockObserver : public DeviceStatusListener::Observer { public: MOCK_METHOD1(OnDeviceStatusChanged, void(const DeviceStatus&)); @@ -79,18 +57,30 @@ class TestDeviceStatusListener : public DeviceStatusListener { public: explicit TestDeviceStatusListener( - std::unique_ptr<TestBatteryStatusListener> battery_listener) + std::unique_ptr<TestBatteryStatusListener> battery_listener, + network::NetworkConnectionTracker* network_connection_tracker) : DeviceStatusListener(base::TimeDelta(), base::TimeDelta(), - std::move(battery_listener)) {} + std::move(battery_listener), + network_connection_tracker), + network_connection_tracker_(network_connection_tracker) {} void BuildNetworkStatusListener() override { - network_listener_ = std::make_unique<NetworkStatusListenerImpl>(); + network_listener_ = std::make_unique<NetworkStatusListenerImpl>( + network_connection_tracker_); } + + private: + network::NetworkConnectionTracker* network_connection_tracker_; + + friend class DeviceStatusListenerTest; }; class DeviceStatusListenerTest : public testing::Test { public: + DeviceStatusListenerTest() + : network_connection_tracker_(true, ConnectionType::CONNECTION_UNKNOWN) {} + void SetUp() override { auto power_source = std::make_unique<base::PowerMonitorTestSource>(); power_source_ = power_source.get(); @@ -99,8 +89,8 @@ auto battery_listener = std::make_unique<TestBatteryStatusListener>(); test_battery_listener_ = battery_listener.get(); - listener_ = - std::make_unique<TestDeviceStatusListener>(std::move(battery_listener)); + listener_ = std::make_unique<TestDeviceStatusListener>( + std::move(battery_listener), &network_connection_tracker_); } void TearDown() override { listener_.reset(); } @@ -122,15 +112,14 @@ // Simulates a network change call, the event will be broadcasted // asynchronously. void ChangeNetworkType(ConnectionType type) { - test_network_notifier_.ChangeNetworkType(type); + network_connection_tracker_.SetConnectionType(type); } // Simulates a network change call, the event will be sent to client // immediately. void ChangeNetworkTypeImmediately(ConnectionType type) { DCHECK(listener_); - static_cast<NetworkStatusListener::Observer*>(listener_.get()) - ->OnNetworkChanged(type); + listener_->OnNetworkChanged(type); } // Simulates a battery change call. @@ -148,7 +137,7 @@ // Needed for network change notifier and power monitor. base::MessageLoop message_loop_; - TestNetworkChangeNotifier test_network_notifier_; + network::TestNetworkConnectionTracker network_connection_tracker_; std::unique_ptr<base::PowerMonitor> power_monitor_; base::PowerMonitorTestSource* power_source_; TestBatteryStatusListener* test_battery_listener_;
diff --git a/components/download/internal/background_service/scheduler/network_status_listener.cc b/components/download/internal/background_service/scheduler/network_status_listener.cc index fd3389ca..0ddb3c43 100644 --- a/components/download/internal/background_service/scheduler/network_status_listener.cc +++ b/components/download/internal/background_service/scheduler/network_status_listener.cc
@@ -4,6 +4,8 @@ #include "components/download/internal/background_service/scheduler/network_status_listener.h" +#include "services/network/public/cpp/network_connection_tracker.h" + namespace download { NetworkStatusListener::NetworkStatusListener() = default; @@ -16,28 +18,34 @@ observer_ = nullptr; } -NetworkStatusListenerImpl::NetworkStatusListenerImpl() = default; +NetworkStatusListenerImpl::NetworkStatusListenerImpl( + network::NetworkConnectionTracker* network_connection_tracker) + : network_connection_tracker_(network_connection_tracker), + connection_type_(network::mojom::ConnectionType::CONNECTION_UNKNOWN) {} NetworkStatusListenerImpl::~NetworkStatusListenerImpl() = default; void NetworkStatusListenerImpl::Start( NetworkStatusListener::Observer* observer) { NetworkStatusListener::Start(observer); - net::NetworkChangeNotifier::AddNetworkChangeObserver(this); + network_connection_tracker_->AddNetworkConnectionObserver(this); + network_connection_tracker_->GetConnectionType( + &connection_type_, + base::BindOnce(&NetworkStatusListenerImpl::OnConnectionChanged, + base::Unretained(this))); } void NetworkStatusListenerImpl::Stop() { - net::NetworkChangeNotifier::RemoveNetworkChangeObserver(this); + network_connection_tracker_->RemoveNetworkConnectionObserver(this); NetworkStatusListener::Stop(); } -net::NetworkChangeNotifier::ConnectionType -NetworkStatusListenerImpl::GetConnectionType() { - return net::NetworkChangeNotifier::GetConnectionType(); +network::mojom::ConnectionType NetworkStatusListenerImpl::GetConnectionType() { + return connection_type_; } -void NetworkStatusListenerImpl::OnNetworkChanged( - net::NetworkChangeNotifier::ConnectionType type) { +void NetworkStatusListenerImpl::OnConnectionChanged( + network::mojom::ConnectionType type) { DCHECK(observer_); observer_->OnNetworkChanged(type); }
diff --git a/components/download/internal/background_service/scheduler/network_status_listener.h b/components/download/internal/background_service/scheduler/network_status_listener.h index 4e68380e..b3a43b1 100644 --- a/components/download/internal/background_service/scheduler/network_status_listener.h +++ b/components/download/internal/background_service/scheduler/network_status_listener.h
@@ -5,7 +5,7 @@ #ifndef COMPONENTS_DOWNLOAD_INTERNAL_BACKGROUND_SERVICE_SCHEDULER_NETWORK_STATUS_LISTENER_H_ #define COMPONENTS_DOWNLOAD_INTERNAL_BACKGROUND_SERVICE_SCHEDULER_NETWORK_STATUS_LISTENER_H_ -#include "net/base/network_change_notifier.h" +#include "services/network/public/cpp/network_connection_tracker.h" namespace download { @@ -18,8 +18,7 @@ // Observer to receive network connection type change notifications. class Observer { public: - virtual void OnNetworkChanged( - net::NetworkChangeNotifier::ConnectionType type) = 0; + virtual void OnNetworkChanged(network::mojom::ConnectionType type) = 0; protected: virtual ~Observer() {} @@ -32,7 +31,7 @@ virtual void Stop(); // Gets the current connection type. - virtual net::NetworkChangeNotifier::ConnectionType GetConnectionType() = 0; + virtual network::mojom::ConnectionType GetConnectionType() = 0; virtual ~NetworkStatusListener() {} @@ -43,31 +42,34 @@ Observer* observer_ = nullptr; // The current network status. - net::NetworkChangeNotifier::ConnectionType network_status_ = - net::NetworkChangeNotifier::ConnectionType::CONNECTION_NONE; + network::mojom::ConnectionType network_status_ = + network::mojom::ConnectionType::CONNECTION_NONE; private: DISALLOW_COPY_AND_ASSIGN(NetworkStatusListener); }; // Default implementation of NetworkStatusListener using -// net::NetworkChangeNotifier to listen to connectivity changes. +// NetworkConnectionTracker to listen to connectivity changes. class NetworkStatusListenerImpl - : public net::NetworkChangeNotifier::NetworkChangeObserver, + : public network::NetworkConnectionTracker::NetworkConnectionObserver, public NetworkStatusListener { public: - NetworkStatusListenerImpl(); + explicit NetworkStatusListenerImpl( + network::NetworkConnectionTracker* network_connection_tracker); ~NetworkStatusListenerImpl() override; // NetworkStatusListener implementation. void Start(NetworkStatusListener::Observer* observer) override; void Stop() override; - net::NetworkChangeNotifier::ConnectionType GetConnectionType() override; + network::mojom::ConnectionType GetConnectionType() override; private: - // net::NetworkChangeNotifier::NetworkChangeObserver implementation. - void OnNetworkChanged( - net::NetworkChangeNotifier::ConnectionType type) override; + // network::NetworkConnectionTracker::NetworkConnectionObserver. + void OnConnectionChanged(network::mojom::ConnectionType type) override; + + network::NetworkConnectionTracker* network_connection_tracker_; + network::mojom::ConnectionType connection_type_; DISALLOW_COPY_AND_ASSIGN(NetworkStatusListenerImpl); };
diff --git a/components/download/internal/background_service/test/BUILD.gn b/components/download/internal/background_service/test/BUILD.gn index 0ed3e44..5a0f649 100644 --- a/components/download/internal/background_service/test/BUILD.gn +++ b/components/download/internal/background_service/test/BUILD.gn
@@ -43,6 +43,7 @@ deps = [ "//components/download/internal/background_service:internal", + "//services/network:test_support", "//services/network/public/cpp", ] }
diff --git a/components/download/internal/background_service/test/test_device_status_listener.cc b/components/download/internal/background_service/test/test_device_status_listener.cc index f6b1920..15bfdf40f 100644 --- a/components/download/internal/background_service/test/test_device_status_listener.cc +++ b/components/download/internal/background_service/test/test_device_status_listener.cc
@@ -24,7 +24,11 @@ TestDeviceStatusListener::TestDeviceStatusListener() : DeviceStatusListener(base::TimeDelta(), /* startup_delay */ base::TimeDelta(), /* online_delay */ - std::make_unique<FakeBatteryStatusListener>()), + std::make_unique<FakeBatteryStatusListener>(), + &test_network_connection_tracker_), + test_network_connection_tracker_( + true, + network::mojom::ConnectionType::CONNECTION_UNKNOWN), weak_ptr_factory_(this) {} TestDeviceStatusListener::~TestDeviceStatusListener() {
diff --git a/components/download/internal/background_service/test/test_device_status_listener.h b/components/download/internal/background_service/test/test_device_status_listener.h index aa717cc..4f42198 100644 --- a/components/download/internal/background_service/test/test_device_status_listener.h +++ b/components/download/internal/background_service/test/test_device_status_listener.h
@@ -7,6 +7,7 @@ #include "base/memory/weak_ptr.h" #include "components/download/internal/background_service/scheduler/device_status_listener.h" +#include "services/network/test/test_network_connection_tracker.h" namespace download { namespace test { @@ -32,6 +33,7 @@ private: void StartAfterDelay(); + network::TestNetworkConnectionTracker test_network_connection_tracker_; base::WeakPtrFactory<TestDeviceStatusListener> weak_ptr_factory_; DISALLOW_COPY_AND_ASSIGN(TestDeviceStatusListener);
diff --git a/components/exo/client_controlled_shell_surface.cc b/components/exo/client_controlled_shell_surface.cc index 48078d6..ac6ac5c 100644 --- a/components/exo/client_controlled_shell_surface.cc +++ b/components/exo/client_controlled_shell_surface.cc
@@ -371,9 +371,6 @@ if (!widget_) CreateShellSurfaceWidget(ui::SHOW_STATE_NORMAL); - // Note: This will ask client to configure its surface even if pinned - // state doesn't change. - ScopedConfigure scoped_configure(this, true); widget_->GetNativeWindow()->SetProperty(ash::kWindowPinTypeKey, type); } @@ -622,11 +619,6 @@ //////////////////////////////////////////////////////////////////////////////// // aura::WindowObserver overrides: -void ClientControlledShellSurface::OnWindowBoundsChanged( - aura::Window* window, - const gfx::Rect& old_bounds, - const gfx::Rect& new_bounds, - ui::PropertyChangeReason reason) {} void ClientControlledShellSurface::OnWindowAddedToRootWindow( aura::Window* window) { @@ -828,7 +820,8 @@ return scale_; } -gfx::Rect ClientControlledShellSurface::GetWidgetBounds() const { +base::Optional<gfx::Rect> ClientControlledShellSurface::GetWidgetBounds() + const { const ash::NonClientFrameViewAsh* frame_view = GetFrameView(); if (frame_view->visible()) { // The client's geometry uses entire display area in client @@ -844,7 +837,6 @@ } gfx::Point ClientControlledShellSurface::GetSurfaceOrigin() const { - DCHECK(resize_component_ == HTCAPTION); return gfx::Point(); }
diff --git a/components/exo/client_controlled_shell_surface.h b/components/exo/client_controlled_shell_surface.h index 62321a2..dbb0c204 100644 --- a/components/exo/client_controlled_shell_surface.h +++ b/components/exo/client_controlled_shell_surface.h
@@ -202,10 +202,6 @@ void OnDeviceScaleFactorChanged(float old_dsf, float new_dsf) override; // Overridden from aura::WindowObserver: - void OnWindowBoundsChanged(aura::Window* window, - const gfx::Rect& old_bounds, - const gfx::Rect& new_bounds, - ui::PropertyChangeReason reason) override; void OnWindowAddedToRootWindow(aura::Window* window) override; // Overridden from display::DisplayObserver: @@ -234,7 +230,7 @@ gfx::Rect GetShadowBounds() const override; void InitializeWindowState(ash::wm::WindowState* window_state) override; float GetScale() const override; - gfx::Rect GetWidgetBounds() const override; + base::Optional<gfx::Rect> GetWidgetBounds() const override; gfx::Point GetSurfaceOrigin() const override; void OnPreWidgetCommit() override; void OnPostWidgetCommit() override;
diff --git a/components/exo/shell_surface.cc b/components/exo/shell_surface.cc index 6df863c..8c89343 100644 --- a/components/exo/shell_surface.cc +++ b/components/exo/shell_surface.cc
@@ -71,6 +71,56 @@ } //////////////////////////////////////////////////////////////////////////////// +// ShellSurface, Config: + +// Surface state associated with each configure request. +struct ShellSurface::Config { + Config(uint32_t serial, + const gfx::Vector2d& origin_offset, + int resize_component, + std::unique_ptr<ui::CompositorLock> compositor_lock); + ~Config() = default; + + uint32_t serial; + gfx::Vector2d origin_offset; + int resize_component; + std::unique_ptr<ui::CompositorLock> compositor_lock; +}; + +ShellSurface::Config::Config( + uint32_t serial, + const gfx::Vector2d& origin_offset, + int resize_component, + std::unique_ptr<ui::CompositorLock> compositor_lock) + : serial(serial), + origin_offset(origin_offset), + resize_component(resize_component), + compositor_lock(std::move(compositor_lock)) {} + +//////////////////////////////////////////////////////////////////////////////// +// ShellSurface, ScopedConfigure: + +ShellSurface::ScopedConfigure::ScopedConfigure(ShellSurface* shell_surface, + bool force_configure) + : shell_surface_(shell_surface), force_configure_(force_configure) { + // ScopedConfigure instances cannot be nested. + DCHECK(!shell_surface_->scoped_configure_); + shell_surface_->scoped_configure_ = this; +} + +ShellSurface::ScopedConfigure::~ScopedConfigure() { + DCHECK_EQ(shell_surface_->scoped_configure_, this); + shell_surface_->scoped_configure_ = nullptr; + if (needs_configure_ || force_configure_) + shell_surface_->Configure(); + // ScopedConfigure instance might have suppressed a widget bounds update. + if (shell_surface_->widget_) { + shell_surface_->UpdateWidgetBounds(); + shell_surface_->UpdateShadow(); + } +} + +//////////////////////////////////////////////////////////////////////////////// // ShellSurface, public: ShellSurface::ShellSurface(Surface* surface, @@ -88,10 +138,39 @@ ash::kShellWindowId_DefaultContainer) {} ShellSurface::~ShellSurface() { + DCHECK(!scoped_configure_); if (widget_) ash::wm::GetWindowState(widget_->GetNativeWindow())->RemoveObserver(this); } +void ShellSurface::AcknowledgeConfigure(uint32_t serial) { + TRACE_EVENT1("exo", "ShellSurface::AcknowledgeConfigure", "serial", serial); + + // Apply all configs that are older or equal to |serial|. The result is that + // the origin of the main surface will move and the resize direction will + // change to reflect the acknowledgement of configure request with |serial| + // at the next call to Commit(). + while (!pending_configs_.empty()) { + std::unique_ptr<Config> config = std::move(pending_configs_.front()); + pending_configs_.pop_front(); + + // Add the config offset to the accumulated offset that will be applied when + // Commit() is called. + pending_origin_offset_ += config->origin_offset; + + // Set the resize direction that will be applied when Commit() is called. + pending_resize_component_ = config->resize_component; + + if (config->serial == serial) + break; + } + + if (widget_) { + UpdateWidgetBounds(); + UpdateShadow(); + } +} + void ShellSurface::SetParent(ShellSurface* parent) { TRACE_EVENT1("exo", "ShellSurface::SetParent", "parent", parent ? base::UTF16ToASCII(parent->title_) : "null"); @@ -176,6 +255,47 @@ AttemptToStartDrag(component); } +//////////////////////////////////////////////////////////////////////////////// +// SurfaceDelegate overrides: + +void ShellSurface::OnSetParent(Surface* parent, const gfx::Point& position) { + views::Widget* parent_widget = + parent ? views::Widget::GetTopLevelWidgetForNativeView(parent->window()) + : nullptr; + if (parent_widget) { + // Set parent window if using default container and the container itself + // is not the parent. + if (container_ == ash::kShellWindowId_DefaultContainer) + SetParentWindow(parent_widget->GetNativeWindow()); + + origin_ = position; + views::View::ConvertPointToScreen( + parent_widget->widget_delegate()->GetContentsView(), &origin_); + + if (!widget_) + return; + + ash::wm::WindowState* window_state = + ash::wm::GetWindowState(widget_->GetNativeWindow()); + if (window_state->is_dragged()) + return; + + gfx::Rect widget_bounds = widget_->GetWindowBoundsInScreen(); + gfx::Rect new_widget_bounds(origin_, widget_bounds.size()); + if (new_widget_bounds != widget_bounds) { + base::AutoReset<bool> auto_ignore_window_bounds_changes( + &ignore_window_bounds_changes_, true); + widget_->SetBounds(new_widget_bounds); + UpdateSurfaceBounds(); + } + } else { + SetParentWindow(nullptr); + } +} + +//////////////////////////////////////////////////////////////////////////////// +// ShellSurfaceBase overrides: + void ShellSurface::InitializeWindowState(ash::wm::WindowState* window_state) { window_state->AddObserver(this); window_state->set_allow_set_bounds_direct(false); @@ -183,6 +303,98 @@ window_state->set_ignore_keyboard_bounds_change(movement_disabled_); } +base::Optional<gfx::Rect> ShellSurface::GetWidgetBounds() const { + // Defer if configure requests are pending. + if (!pending_configs_.empty() || scoped_configure_) + return base::nullopt; + + gfx::Rect visible_bounds = GetVisibleBounds(); + gfx::Rect new_widget_bounds = + widget_->non_client_view() + ? widget_->non_client_view()->GetWindowBoundsForClientBounds( + visible_bounds) + : visible_bounds; + + if (movement_disabled_) { + new_widget_bounds.set_origin(origin_); + } else if (resize_component_ == HTCAPTION) { + // Preserve widget position. + new_widget_bounds.set_origin(widget_->GetWindowBoundsInScreen().origin()); + } else { + // Compute widget origin using surface origin if the current location of + // surface is being anchored to one side of the widget as a result of a + // resize operation. + gfx::Rect visible_bounds = GetVisibleBounds(); + gfx::Point origin = GetSurfaceOrigin() + visible_bounds.OffsetFromOrigin(); + wm::ConvertPointToScreen(widget_->GetNativeWindow(), &origin); + new_widget_bounds.set_origin(origin); + } + return new_widget_bounds; +} + +gfx::Point ShellSurface::GetSurfaceOrigin() const { + DCHECK(!movement_disabled_ || resize_component_ == HTCAPTION); + + gfx::Rect visible_bounds = GetVisibleBounds(); + gfx::Rect client_bounds = GetClientViewBounds(); + + switch (resize_component_) { + case HTCAPTION: + return gfx::Point() + origin_offset_ - visible_bounds.OffsetFromOrigin(); + case HTBOTTOM: + case HTRIGHT: + case HTBOTTOMRIGHT: + return gfx::Point() - visible_bounds.OffsetFromOrigin(); + case HTTOP: + case HTTOPRIGHT: + return gfx::Point(0, client_bounds.height() - visible_bounds.height()) - + visible_bounds.OffsetFromOrigin(); + case HTLEFT: + case HTBOTTOMLEFT: + return gfx::Point(client_bounds.width() - visible_bounds.width(), 0) - + visible_bounds.OffsetFromOrigin(); + case HTTOPLEFT: + return gfx::Point(client_bounds.width() - visible_bounds.width(), + client_bounds.height() - visible_bounds.height()) - + visible_bounds.OffsetFromOrigin(); + default: + NOTREACHED(); + return gfx::Point(); + } +} + +//////////////////////////////////////////////////////////////////////////////// +// aura::WindowObserver overrides: + +void ShellSurface::OnWindowBoundsChanged(aura::Window* window, + const gfx::Rect& old_bounds, + const gfx::Rect& new_bounds, + ui::PropertyChangeReason reason) { + if (!widget_ || !root_surface() || ignore_window_bounds_changes_) + return; + + if (window == widget_->GetNativeWindow()) { + if (new_bounds.size() == old_bounds.size()) + return; + + // If size changed then give the client a chance to produce new contents + // before origin on screen is changed. Retain the old origin by reverting + // the origin delta until the next configure is acknowledged. + gfx::Vector2d delta = new_bounds.origin() - old_bounds.origin(); + origin_offset_ -= delta; + pending_origin_offset_accumulator_ += delta; + + UpdateSurfaceBounds(); + + // The shadow size may be updated to match the widget. Change it back + // to the shadow content size. Note that this relies on wm::ShadowController + // being notified of the change before |this|. + UpdateShadow(); + + Configure(); + } +} + //////////////////////////////////////////////////////////////////////////////// // ash::wm::WindowStateObserver overrides: @@ -239,6 +451,18 @@ //////////////////////////////////////////////////////////////////////////////// // ShellSurfaceBase overrides: +void ShellSurface::SetWidgetBounds(const gfx::Rect& bounds) { + // Set |ignore_window_bounds_changes_| as this change to window bounds + // should not result in a configure request. + DCHECK(!ignore_window_bounds_changes_); + ignore_window_bounds_changes_ = true; + + widget_->SetBounds(bounds); + UpdateSurfaceBounds(); + + ignore_window_bounds_changes_ = false; +} + void ShellSurface::OnPreWidgetCommit() { if (!widget_ && enabled()) { // Defer widget creation until surface contains some contents. @@ -249,13 +473,88 @@ CreateShellSurfaceWidget(ui::SHOW_STATE_NORMAL); } + + // Apply the accumulated pending origin offset to reflect acknowledged + // configure requests. + origin_offset_ += pending_origin_offset_; + pending_origin_offset_ = gfx::Vector2d(); + + // Update resize direction to reflect acknowledged configure requests. + resize_component_ = pending_resize_component_; } void ShellSurface::OnPostWidgetCommit() {} //////////////////////////////////////////////////////////////////////////////// +// wm::ActivationChangeObserver overrides: + +void ShellSurface::OnWindowActivated(ActivationReason reason, + aura::Window* gained_active, + aura::Window* lost_active) { + ShellSurfaceBase::OnWindowActivated(reason, gained_active, lost_active); + + if (!widget_) + return; + + if (gained_active == widget_->GetNativeWindow() || + lost_active == widget_->GetNativeWindow()) { + Configure(); + } +} + +//////////////////////////////////////////////////////////////////////////////// // ShellSurface, private: +void ShellSurface::Configure() { + // Delay configure callback if |scoped_configure_| is set. + if (scoped_configure_) { + scoped_configure_->set_needs_configure(); + return; + } + + gfx::Vector2d origin_offset = pending_origin_offset_accumulator_; + pending_origin_offset_accumulator_ = gfx::Vector2d(); + + int resize_component = HTCAPTION; + if (widget_) { + ash::wm::WindowState* window_state = + ash::wm::GetWindowState(widget_->GetNativeWindow()); + + // If surface is being resized, save the resize direction. + if (window_state->is_dragged()) + resize_component = window_state->drag_details()->window_component; + } + + uint32_t serial = 0; + if (!configure_callback_.is_null()) { + if (widget_) { + serial = configure_callback_.Run( + GetClientViewBounds().size(), + ash::wm::GetWindowState(widget_->GetNativeWindow())->GetStateType(), + IsResizing(), widget_->IsActive(), origin_offset); + } else { + serial = configure_callback_.Run(gfx::Size(), + ash::mojom::WindowStateType::NORMAL, + false, false, origin_offset); + } + } + + if (!serial) { + pending_origin_offset_ += origin_offset; + pending_resize_component_ = resize_component; + return; + } + + // Apply origin offset and resize component at the first Commit() after this + // configure request has been acknowledged. + pending_configs_.push_back( + std::make_unique<Config>(serial, origin_offset, resize_component, + std::move(configure_compositor_lock_))); + LOG_IF(WARNING, pending_configs_.size() > 100) + << "Number of pending configure acks for shell surface has reached: " + << pending_configs_.size(); +} + void ShellSurface::AttemptToStartDrag(int component) { ash::wm::WindowState* window_state = ash::wm::GetWindowState(widget_->GetNativeWindow());
diff --git a/components/exo/shell_surface.h b/components/exo/shell_surface.h index 90b2688..3789163 100644 --- a/components/exo/shell_surface.h +++ b/components/exo/shell_surface.h
@@ -7,9 +7,14 @@ #include "ash/wm/window_state_observer.h" #include "ash/wm/wm_toplevel_window_event_handler.h" +#include "base/containers/circular_deque.h" #include "base/macros.h" #include "components/exo/shell_surface_base.h" +namespace ui { +class CompositorLock; +} // namespace ui + namespace exo { class Surface; @@ -28,6 +33,25 @@ explicit ShellSurface(Surface* surface); ~ShellSurface() override; + // Set the callback to run when the client is asked to configure the surface. + // The size is a hint, in the sense that the client is free to ignore it if + // it doesn't resize, pick a smaller size (to satisfy aspect ratio or resize + // in steps of NxM pixels). + using ConfigureCallback = + base::RepeatingCallback<uint32_t(const gfx::Size& size, + ash::mojom::WindowStateType state_type, + bool resizing, + bool activated, + const gfx::Vector2d& origin_offset)>; + void set_configure_callback(const ConfigureCallback& configure_callback) { + configure_callback_ = configure_callback; + } + + // When the client is asked to configure the surface, it should acknowledge + // the configure request sometime before the commit. |serial| is the serial + // from the configure callback. + void AcknowledgeConfigure(uint32_t serial); + // Set the "parent" of this surface. This window should be stacked above a // parent. void SetParent(ShellSurface* parent); @@ -58,8 +82,19 @@ // Start an interactive move of surface. void StartMove(); + // Overridden from SurfaceDelegate: + void OnSetParent(Surface* parent, const gfx::Point& position) override; + // Overridden from ShellSurfaceBase: void InitializeWindowState(ash::wm::WindowState* window_state) override; + base::Optional<gfx::Rect> GetWidgetBounds() const override; + gfx::Point GetSurfaceOrigin() const override; + + // Overridden from aura::WindowObserver: + void OnWindowBoundsChanged(aura::Window* window, + const gfx::Rect& old_bounds, + const gfx::Rect& new_bounds, + ui::PropertyChangeReason reason) override; // Overridden from ash::wm::WindowStateObserver: void OnPreWindowStateTypeChange( @@ -69,19 +104,63 @@ ash::wm::WindowState* window_state, ash::mojom::WindowStateType old_type) override; + // Overridden from wm::ActivationChangeObserver: + void OnWindowActivated(ActivationReason reason, + aura::Window* gained_active, + aura::Window* lost_active) override; + private: class ScopedAnimationsDisabled; + struct Config; + + // Helper class used to coalesce a number of changes into one "configure" + // callback. Callbacks are suppressed while an instance of this class is + // instantiated and instead called when the instance is destroyed. + // If |force_configure_| is true ShellSurface::Configure() will be called + // even if no changes to shell surface took place during the lifetime of the + // ScopedConfigure instance. + class ScopedConfigure { + public: + ScopedConfigure(ShellSurface* shell_surface, bool force_configure); + ~ScopedConfigure(); + + void set_needs_configure() { needs_configure_ = true; } + + private: + ShellSurface* const shell_surface_; + const bool force_configure_; + bool needs_configure_ = false; + + DISALLOW_COPY_AND_ASSIGN(ScopedConfigure); + }; // Overridden from ShellSurfaceBase: + void SetWidgetBounds(const gfx::Rect& bounds) override; void OnPreWidgetCommit() override; void OnPostWidgetCommit() override; + // Asks the client to configure its surface. + void Configure(); + void AttemptToStartDrag(int component); void EndDrag(); std::unique_ptr<ScopedAnimationsDisabled> scoped_animations_disabled_; + std::unique_ptr<ui::CompositorLock> configure_compositor_lock_; + ConfigureCallback configure_callback_; + ScopedConfigure* scoped_configure_ = nullptr; + base::circular_deque<std::unique_ptr<Config>> pending_configs_; + + gfx::Vector2d origin_offset_; + gfx::Vector2d pending_origin_offset_; + gfx::Vector2d pending_origin_offset_accumulator_; + int resize_component_ = HTCAPTION; // HT constant (see ui/base/hit_test.h) + int pending_resize_component_ = HTCAPTION; + + bool ignore_window_bounds_changes_ = false; + DISALLOW_COPY_AND_ASSIGN(ShellSurface); };
diff --git a/components/exo/shell_surface_base.cc b/components/exo/shell_surface_base.cc index 13b0dc2..7000261 100644 --- a/components/exo/shell_surface_base.cc +++ b/components/exo/shell_surface_base.cc
@@ -341,59 +341,6 @@ } // namespace -// Surface state associated with each configure request. -struct ShellSurfaceBase::Config { - Config(uint32_t serial, - const gfx::Vector2d& origin_offset, - int resize_component, - std::unique_ptr<ui::CompositorLock> compositor_lock); - ~Config(); - - uint32_t serial; - gfx::Vector2d origin_offset; - int resize_component; - std::unique_ptr<ui::CompositorLock> compositor_lock; -}; - -//////////////////////////////////////////////////////////////////////////////// -// ShellSurfaceBase, Config: - -ShellSurfaceBase::Config::Config( - uint32_t serial, - const gfx::Vector2d& origin_offset, - int resize_component, - std::unique_ptr<ui::CompositorLock> compositor_lock) - : serial(serial), - origin_offset(origin_offset), - resize_component(resize_component), - compositor_lock(std::move(compositor_lock)) {} - -ShellSurfaceBase::Config::~Config() {} - -//////////////////////////////////////////////////////////////////////////////// -// ShellSurfaceBase, ScopedConfigure: - -ShellSurfaceBase::ScopedConfigure::ScopedConfigure( - ShellSurfaceBase* shell_surface, - bool force_configure) - : shell_surface_(shell_surface), force_configure_(force_configure) { - // ScopedConfigure instances cannot be nested. - DCHECK(!shell_surface_->scoped_configure_); - shell_surface_->scoped_configure_ = this; -} - -ShellSurfaceBase::ScopedConfigure::~ScopedConfigure() { - DCHECK_EQ(shell_surface_->scoped_configure_, this); - shell_surface_->scoped_configure_ = nullptr; - if (needs_configure_ || force_configure_) - shell_surface_->Configure(); - // ScopedConfigure instance might have suppressed a widget bounds update. - if (shell_surface_->widget_) { - shell_surface_->UpdateWidgetBounds(); - shell_surface_->UpdateShadow(); - } -} - //////////////////////////////////////////////////////////////////////////////// // ShellSurfaceBase, public: @@ -415,7 +362,6 @@ } ShellSurfaceBase::~ShellSurfaceBase() { - DCHECK(!scoped_configure_); // Remove activation observer before hiding widget to prevent it from // casuing the configure callback to be called. WMHelper::GetInstance()->RemoveActivationObserver(this); @@ -436,35 +382,6 @@ wm::CaptureController::Get()->RemoveObserver(this); } -void ShellSurfaceBase::AcknowledgeConfigure(uint32_t serial) { - TRACE_EVENT1("exo", "ShellSurfaceBase::AcknowledgeConfigure", "serial", - serial); - - // Apply all configs that are older or equal to |serial|. The result is that - // the origin of the main surface will move and the resize direction will - // change to reflect the acknowledgement of configure request with |serial| - // at the next call to Commit(). - while (!pending_configs_.empty()) { - std::unique_ptr<Config> config = std::move(pending_configs_.front()); - pending_configs_.pop_front(); - - // Add the config offset to the accumulated offset that will be applied when - // Commit() is called. - pending_origin_offset_ += config->origin_offset; - - // Set the resize direction that will be applied when Commit() is called. - pending_resize_component_ = config->resize_component; - - if (config->serial == serial) - break; - } - - if (widget_) { - UpdateWidgetBounds(); - UpdateShadow(); - } -} - void ShellSurfaceBase::Activate() { TRACE_EVENT0("exo", "ShellSurfaceBase::Activate"); @@ -808,42 +725,6 @@ } } -void ShellSurfaceBase::OnSetParent(Surface* parent, - const gfx::Point& position) { - views::Widget* parent_widget = - parent ? views::Widget::GetTopLevelWidgetForNativeView(parent->window()) - : nullptr; - if (parent_widget) { - // Set parent window if using default container and the container itself - // is not the parent. - if (container_ == ash::kShellWindowId_DefaultContainer) - SetParentWindow(parent_widget->GetNativeWindow()); - - origin_ = position; - views::View::ConvertPointToScreen( - parent_widget->widget_delegate()->GetContentsView(), &origin_); - - if (!widget_) - return; - - ash::wm::WindowState* window_state = - ash::wm::GetWindowState(widget_->GetNativeWindow()); - if (window_state->is_dragged()) - return; - - gfx::Rect widget_bounds = widget_->GetWindowBoundsInScreen(); - gfx::Rect new_widget_bounds(origin_, widget_bounds.size()); - if (new_widget_bounds != widget_bounds) { - base::AutoReset<bool> auto_ignore_window_bounds_changes( - &ignore_window_bounds_changes_, true); - widget_->SetBounds(new_widget_bounds); - UpdateSurfaceBounds(); - } - } else { - SetParentWindow(nullptr); - } -} - void ShellSurfaceBase::OnSetStartupId(const char* startup_id) { SetStartupId(startup_id); } @@ -1021,35 +902,6 @@ //////////////////////////////////////////////////////////////////////////////// // aura::WindowObserver overrides: -void ShellSurfaceBase::OnWindowBoundsChanged(aura::Window* window, - const gfx::Rect& old_bounds, - const gfx::Rect& new_bounds, - ui::PropertyChangeReason reason) { - if (!widget_ || !root_surface() || ignore_window_bounds_changes_) - return; - - if (window == widget_->GetNativeWindow()) { - if (new_bounds.size() == old_bounds.size()) - return; - - // If size changed then give the client a chance to produce new contents - // before origin on screen is changed. Retain the old origin by reverting - // the origin delta until the next configure is acknowledged. - gfx::Vector2d delta = new_bounds.origin() - old_bounds.origin(); - origin_offset_ -= delta; - pending_origin_offset_accumulator_ += delta; - - UpdateSurfaceBounds(); - - // The shadow size may be updated to match the widget. Change it back - // to the shadow content size. Note that this relies on wm::ShadowController - // being notified of the change before |this|. - UpdateShadow(); - - Configure(); - } -} - void ShellSurfaceBase::OnWindowDestroying(aura::Window* window) { if (window == parent_) { parent_ = nullptr; @@ -1072,7 +924,6 @@ if (gained_active == widget_->GetNativeWindow() || lost_active == widget_->GetNativeWindow()) { DCHECK(CanActivate()); - Configure(); UpdateShadow(); } } @@ -1169,56 +1020,6 @@ pending_show_widget_ = true; } -void ShellSurfaceBase::Configure() { - // Delay configure callback if |scoped_configure_| is set. - if (scoped_configure_) { - scoped_configure_->set_needs_configure(); - return; - } - - gfx::Vector2d origin_offset = pending_origin_offset_accumulator_; - pending_origin_offset_accumulator_ = gfx::Vector2d(); - - int resize_component = HTCAPTION; - if (widget_) { - ash::wm::WindowState* window_state = - ash::wm::GetWindowState(widget_->GetNativeWindow()); - - // If surface is being resized, save the resize direction. - if (window_state->is_dragged()) - resize_component = window_state->drag_details()->window_component; - } - - uint32_t serial = 0; - if (!configure_callback_.is_null()) { - if (widget_) { - serial = configure_callback_.Run( - GetClientViewBounds().size(), - ash::wm::GetWindowState(widget_->GetNativeWindow())->GetStateType(), - IsResizing(), widget_->IsActive(), origin_offset); - } else { - serial = configure_callback_.Run(gfx::Size(), - ash::mojom::WindowStateType::NORMAL, - false, false, origin_offset); - } - } - - if (!serial) { - pending_origin_offset_ += origin_offset; - pending_resize_component_ = resize_component; - return; - } - - // Apply origin offset and resize component at the first Commit() after this - // configure request has been acknowledged. - pending_configs_.push_back( - std::make_unique<Config>(serial, origin_offset, resize_component, - std::move(configure_compositor_lock_))); - LOG_IF(WARNING, pending_configs_.size() > 100) - << "Number of pending configure acks for shell surface has reached: " - << pending_configs_.size(); -} - bool ShellSurfaceBase::IsResizing() const { ash::wm::WindowState* window_state = ash::wm::GetWindowState(widget_->GetNativeWindow()); @@ -1251,24 +1052,12 @@ return; } - // Return early if there is pending configure requests. - if (!pending_configs_.empty() || scoped_configure_) + base::Optional<gfx::Rect> new_widget_bounds = GetWidgetBounds(); + if (!new_widget_bounds) return; - gfx::Rect new_widget_bounds = GetWidgetBounds(); - - // Set |ignore_window_bounds_changes_| as this change to window bounds - // should not result in a configure request. - DCHECK(!ignore_window_bounds_changes_); - ignore_window_bounds_changes_ = true; - if (new_widget_bounds != widget_->GetWindowBoundsInScreen()) - SetWidgetBounds(new_widget_bounds); - ignore_window_bounds_changes_ = false; -} - -void ShellSurfaceBase::SetWidgetBounds(const gfx::Rect& bounds) { - widget_->SetBounds(bounds); - UpdateSurfaceBounds(); + if (*new_widget_bounds != widget_->GetWindowBoundsInScreen()) + SetWidgetBounds(*new_widget_bounds); } void ShellSurfaceBase::UpdateSurfaceBounds() { @@ -1354,62 +1143,6 @@ return 1.f; } -gfx::Rect ShellSurfaceBase::GetWidgetBounds() const { - gfx::Rect visible_bounds = GetVisibleBounds(); - gfx::Rect new_widget_bounds = - widget_->non_client_view() - ? widget_->non_client_view()->GetWindowBoundsForClientBounds( - visible_bounds) - : visible_bounds; - - if (movement_disabled_) { - new_widget_bounds.set_origin(origin_); - } else if (resize_component_ == HTCAPTION) { - // Preserve widget position. - new_widget_bounds.set_origin(widget_->GetWindowBoundsInScreen().origin()); - } else { - // Compute widget origin using surface origin if the current location of - // surface is being anchored to one side of the widget as a result of a - // resize operation. - gfx::Rect visible_bounds = GetVisibleBounds(); - gfx::Point origin = GetSurfaceOrigin() + visible_bounds.OffsetFromOrigin(); - wm::ConvertPointToScreen(widget_->GetNativeWindow(), &origin); - new_widget_bounds.set_origin(origin); - } - return new_widget_bounds; -} - -gfx::Point ShellSurfaceBase::GetSurfaceOrigin() const { - DCHECK(!movement_disabled_ || resize_component_ == HTCAPTION); - - gfx::Rect visible_bounds = GetVisibleBounds(); - gfx::Rect client_bounds = GetClientViewBounds(); - - switch (resize_component_) { - case HTCAPTION: - return gfx::Point() + origin_offset_ - visible_bounds.OffsetFromOrigin(); - case HTBOTTOM: - case HTRIGHT: - case HTBOTTOMRIGHT: - return gfx::Point() - visible_bounds.OffsetFromOrigin(); - case HTTOP: - case HTTOPRIGHT: - return gfx::Point(0, client_bounds.height() - visible_bounds.height()) - - visible_bounds.OffsetFromOrigin(); - case HTLEFT: - case HTBOTTOMLEFT: - return gfx::Point(client_bounds.width() - visible_bounds.width(), 0) - - visible_bounds.OffsetFromOrigin(); - case HTTOPLEFT: - return gfx::Point(client_bounds.width() - visible_bounds.width(), - client_bounds.height() - visible_bounds.height()) - - visible_bounds.OffsetFromOrigin(); - default: - NOTREACHED(); - return gfx::Point(); - } -} - void ShellSurfaceBase::SetParentWindow(aura::Window* parent) { if (parent_) { parent_->RemoveObserver(this); @@ -1436,14 +1169,6 @@ } void ShellSurfaceBase::CommitWidget() { - // Apply the accumulated pending origin offset to reflect acknowledged - // configure requests. - origin_offset_ += pending_origin_offset_; - pending_origin_offset_ = gfx::Vector2d(); - - // Update resize direction to reflect acknowledged configure requests. - resize_component_ = pending_resize_component_; - // Apply new window geometry. geometry_ = pending_geometry_;
diff --git a/components/exo/shell_surface_base.h b/components/exo/shell_surface_base.h index baa6598..00fe22f 100644 --- a/components/exo/shell_surface_base.h +++ b/components/exo/shell_surface_base.h
@@ -11,7 +11,6 @@ #include "ash/display/window_tree_host_manager.h" #include "ash/public/interfaces/window_state_type.mojom.h" -#include "base/containers/circular_deque.h" #include "base/macros.h" #include "base/optional.h" #include "base/strings/string16.h" @@ -20,7 +19,6 @@ #include "ui/aura/client/capture_client_observer.h" #include "ui/aura/window_observer.h" #include "ui/base/hit_test.h" -#include "ui/compositor/compositor_lock.h" #include "ui/display/display_observer.h" #include "ui/gfx/geometry/point.h" #include "ui/gfx/geometry/rect.h" @@ -40,10 +38,6 @@ } } // namespace base -namespace ui { -class CompositorLock; -} // namespace ui - namespace exo { class Surface; @@ -79,25 +73,6 @@ surface_destroyed_callback_ = std::move(surface_destroyed_callback); } - // Set the callback to run when the client is asked to configure the surface. - // The size is a hint, in the sense that the client is free to ignore it if - // it doesn't resize, pick a smaller size (to satisfy aspect ratio or resize - // in steps of NxM pixels). - using ConfigureCallback = - base::RepeatingCallback<uint32_t(const gfx::Size& size, - ash::mojom::WindowStateType state_type, - bool resizing, - bool activated, - const gfx::Vector2d& origin_offset)>; - void set_configure_callback(const ConfigureCallback& configure_callback) { - configure_callback_ = configure_callback; - } - - // When the client is asked to configure the surface, it should acknowledge - // the configure request sometime before the commit. |serial| is the serial - // from the configure callback. - void AcknowledgeConfigure(uint32_t serial); - // Activates the shell surface. void Activate(); @@ -180,7 +155,6 @@ bool IsInputEnabled(Surface* surface) const override; void OnSetFrame(SurfaceFrameType type) override; void OnSetFrameColors(SkColor active_color, SkColor inactive_color) override; - void OnSetParent(Surface* parent, const gfx::Point& position) override; void OnSetStartupId(const char* startup_id) override; void OnSetApplicationId(const char* application_id) override; @@ -214,10 +188,6 @@ void GetAccessibleNodeData(ui::AXNodeData* node_data) override; // Overridden from aura::WindowObserver: - void OnWindowBoundsChanged(aura::Window* window, - const gfx::Rect& old_bounds, - const gfx::Rect& new_bounds, - ui::PropertyChangeReason reason) override; void OnWindowDestroying(aura::Window* window) override; // Overridden from wm::ActivationChangeObserver: @@ -236,34 +206,10 @@ Surface* surface_for_testing() { return root_surface(); } protected: - // Helper class used to coalesce a number of changes into one "configure" - // callback. Callbacks are suppressed while an instance of this class is - // instantiated and instead called when the instance is destroyed. - // If |force_configure_| is true ShellSurfaceBase::Configure() will be called - // even if no changes to shell surface took place during the lifetime of the - // ScopedConfigure instance. - class ScopedConfigure { - public: - ScopedConfigure(ShellSurfaceBase* shell_surface, bool force_configure); - ~ScopedConfigure(); - - void set_needs_configure() { needs_configure_ = true; } - - private: - ShellSurfaceBase* const shell_surface_; - const bool force_configure_; - bool needs_configure_ = false; - - DISALLOW_COPY_AND_ASSIGN(ScopedConfigure); - }; - // Creates the |widget_| for |surface_|. |show_state| is the initial state // of the widget (e.g. maximized). void CreateShellSurfaceWidget(ui::WindowShowState show_state); - // Asks the client to configure its surface. - void Configure(); - // Returns true if surface is currently being resized. bool IsResizing() const; @@ -271,7 +217,7 @@ void UpdateWidgetBounds(); // Called by UpdateWidgetBounds to set widget bounds. - virtual void SetWidgetBounds(const gfx::Rect& bounds); + virtual void SetWidgetBounds(const gfx::Rect& bounds) = 0; // Updates the bounds of surface to match the current widget bounds. void UpdateSurfaceBounds(); @@ -310,19 +256,11 @@ // Container Window Id (see ash/public/cpp/shell_window_ids.h) int container_; - bool ignore_window_bounds_changes_ = false; - gfx::Vector2d origin_offset_; - gfx::Vector2d pending_origin_offset_; - gfx::Vector2d pending_origin_offset_accumulator_; - int resize_component_ = HTCAPTION; // HT constant (see ui/base/hit_test.h) - int pending_resize_component_ = HTCAPTION; gfx::Rect geometry_; gfx::Rect pending_geometry_; base::Optional<gfx::Rect> shadow_bounds_; bool shadow_bounds_changed_ = false; base::string16 title_; - std::unique_ptr<ui::CompositorLock> configure_compositor_lock_; - ConfigureCallback configure_callback_; // TODO(oshima): Remove this once the transition to new drag/resize // complete. https://crbug.com/801666. bool client_controlled_move_resize_ = true; @@ -331,8 +269,6 @@ bool has_grab_ = false; private: - struct Config; - // Called on widget creation to initialize its window state. // TODO(reveman): Remove virtual functions below to avoid FBC problem. virtual void InitializeWindowState(ash::wm::WindowState* window_state) = 0; @@ -342,8 +278,8 @@ // Return the bounds of the widget/origin of surface taking visible // bounds and current resize direction into account. - virtual gfx::Rect GetWidgetBounds() const; - virtual gfx::Point GetSurfaceOrigin() const; + virtual base::Optional<gfx::Rect> GetWidgetBounds() const = 0; + virtual gfx::Point GetSurfaceOrigin() const = 0; virtual void OnPreWidgetCommit() = 0; virtual void OnPostWidgetCommit() = 0; @@ -360,8 +296,6 @@ base::Optional<std::string> startup_id_; base::RepeatingClosure close_callback_; base::OnceClosure surface_destroyed_callback_; - ScopedConfigure* scoped_configure_ = nullptr; - base::circular_deque<std::unique_ptr<Config>> pending_configs_; bool system_modal_ = false; bool non_system_modal_window_was_active_ = false; gfx::ImageSkia icon_;
diff --git a/components/exo/wayland/server.cc b/components/exo/wayland/server.cc index 6e887289..ac11f41 100644 --- a/components/exo/wayland/server.cc +++ b/components/exo/wayland/server.cc
@@ -2296,7 +2296,7 @@ void remote_surface_ack_configure(wl_client* client, wl_resource* resource, uint32_t serial) { - GetUserDataAs<ShellSurfaceBase>(resource)->AcknowledgeConfigure(serial); + // DEPRECATED } void remote_surface_move(wl_client* client, wl_resource* resource) { @@ -2818,26 +2818,6 @@ wl_client_flush(wl_resource_get_client(resource)); } -uint32_t HandleRemoteSurfaceConfigureCallback( - wl_resource* resource, - const gfx::Size& size, - ash::mojom::WindowStateType state_type, - bool resizing, - bool activated, - const gfx::Vector2d& origin_offset) { - wl_array states; - wl_array_init(&states); - uint32_t serial = wl_display_next_serial( - wl_client_get_display(wl_resource_get_client(resource))); - zcr_remote_surface_v1_send_configure(resource, - origin_offset.x(), - origin_offset.y(), - &states, serial); - wl_client_flush(wl_resource_get_client(resource)); - wl_array_release(&states); - return serial; -} - void HandleRemoteSurfaceGeometryChangedCallback(wl_resource* resource, const gfx::Rect& geometry) { zcr_remote_surface_v1_send_window_geometry_changed( @@ -2876,9 +2856,6 @@ shell_surface->set_state_changed_callback( base::Bind(&HandleRemoteSurfaceStateChangedCallback, base::Unretained(remote_surface_resource))); - shell_surface->set_configure_callback( - base::Bind(&HandleRemoteSurfaceConfigureCallback, - base::Unretained(remote_surface_resource))); shell_surface->set_geometry_changed_callback( base::BindRepeating(&HandleRemoteSurfaceGeometryChangedCallback, base::Unretained(remote_surface_resource)));
diff --git a/components/feed/core/BUILD.gn b/components/feed/core/BUILD.gn index f2d06c4..9f4d11c 100644 --- a/components/feed/core/BUILD.gn +++ b/components/feed/core/BUILD.gn
@@ -8,6 +8,12 @@ source_set("feed_core") { sources = [ + "feed_content_database.cc", + "feed_content_database.h", + "feed_content_mutation.cc", + "feed_content_mutation.h", + "feed_content_operation.cc", + "feed_content_operation.h", "feed_host_service.cc", "feed_host_service.h", "feed_image_database.cc", @@ -66,6 +72,7 @@ source_set("core_unit_tests") { testonly = true sources = [ + "feed_content_database_unittest.cc", "feed_image_database_unittest.cc", "feed_image_manager_unittest.cc", "feed_networking_host_unittest.cc",
diff --git a/components/feed/core/feed_content_database.cc b/components/feed/core/feed_content_database.cc new file mode 100644 index 0000000..455dc9d5 --- /dev/null +++ b/components/feed/core/feed_content_database.cc
@@ -0,0 +1,292 @@ +// Copyright 2018 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#include "components/feed/core/feed_content_database.h" + +#include <unordered_set> + +#include "base/bind.h" +#include "base/files/file_path.h" +#include "base/strings/string_util.h" +#include "base/sys_info.h" +#include "base/task/post_task.h" +#include "base/threading/thread_task_runner_handle.h" +#include "components/feed/core/proto/content_storage.pb.h" +#include "components/leveldb_proto/proto_database_impl.h" + +namespace feed { + +namespace { +using StorageEntryVector = + leveldb_proto::ProtoDatabase<ContentStorageProto>::KeyEntryVector; + +// Statistics are logged to UMA with this string as part of histogram name. They +// can all be found under LevelDB.*.FeedContentDatabase. Changing this needs to +// synchronize with histograms.xml, AND will also become incompatible with older +// browsers still reporting the previous values. +const char kContentDatabaseUMAClientName[] = "FeedContentDatabase"; + +const char kContentDatabaseFolder[] = "content"; + +const size_t kDatabaseWriteBufferSizeBytes = 512 * 1024; +const size_t kDatabaseWriteBufferSizeBytesForLowEndDevice = 128 * 1024; + +bool DatabaseKeyFilter(const std::unordered_set<std::string>& key_set, + const std::string& key) { + return key_set.find(key) != key_set.end(); +} + +bool DatabasePrefixFilter(const std::string& key_prefix, + const std::string& key) { + return base::StartsWith(key, key_prefix, base::CompareCase::SENSITIVE); +} + +} // namespace + +FeedContentDatabase::FeedContentDatabase(const base::FilePath& database_folder) + : FeedContentDatabase( + database_folder, + std::make_unique< + leveldb_proto::ProtoDatabaseImpl<ContentStorageProto>>( + base::CreateSequencedTaskRunnerWithTraits( + {base::MayBlock(), base::TaskPriority::BEST_EFFORT, + base::TaskShutdownBehavior::CONTINUE_ON_SHUTDOWN}))) {} + +FeedContentDatabase::FeedContentDatabase( + const base::FilePath& database_folder, + std::unique_ptr<leveldb_proto::ProtoDatabase<ContentStorageProto>> + storage_database) + : database_status_(UNINITIALIZED), + storage_database_(std::move(storage_database)), + weak_ptr_factory_(this) { + leveldb_env::Options options = leveldb_proto::CreateSimpleOptions(); + if (base::SysInfo::IsLowEndDevice()) { + options.write_buffer_size = kDatabaseWriteBufferSizeBytesForLowEndDevice; + } else { + options.write_buffer_size = kDatabaseWriteBufferSizeBytes; + } + + base::FilePath storage_folder = + database_folder.AppendASCII(kContentDatabaseFolder); + storage_database_->Init( + kContentDatabaseUMAClientName, storage_folder, options, + base::BindOnce(&FeedContentDatabase::OnDatabaseInitialized, + weak_ptr_factory_.GetWeakPtr())); +} + +FeedContentDatabase::~FeedContentDatabase() = default; + +bool FeedContentDatabase::IsInitialized() const { + return INITIALIZED == database_status_; +} + +void FeedContentDatabase::LoadContent(const std::vector<std::string>& keys, + ContentLoadCallback callback) { + DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_); + + std::unordered_set<std::string> key_set(keys.begin(), keys.end()); + + storage_database_->LoadEntriesWithFilter( + base::BindRepeating(&DatabaseKeyFilter, std::move(key_set)), + base::BindOnce(&FeedContentDatabase::OnLoadEntriesForLoadContent, + weak_ptr_factory_.GetWeakPtr(), std::move(callback))); +} + +void FeedContentDatabase::LoadContentByPrefix(const std::string& prefix, + ContentLoadCallback callback) { + DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_); + + storage_database_->LoadEntriesWithFilter( + base::BindRepeating(&DatabasePrefixFilter, std::move(prefix)), + base::BindOnce(&FeedContentDatabase::OnLoadEntriesForLoadContent, + weak_ptr_factory_.GetWeakPtr(), std::move(callback))); +} + +void FeedContentDatabase::LoadAllContentKeys(ContentKeyCallback callback) { + DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_); + + storage_database_->LoadKeys( + base::BindOnce(&FeedContentDatabase::OnLoadKeysForLoadAllContentKeys, + weak_ptr_factory_.GetWeakPtr(), std::move(callback))); +} + +void FeedContentDatabase::CommitContentMutation( + std::unique_ptr<ContentMutation> content_mutation, + ConfirmationCallback callback) { + DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_); + DCHECK(content_mutation); + + PerformNextOperation(content_mutation->TakeOperations(), std::move(callback)); +} + +void FeedContentDatabase::PerformNextOperation( + ContentOperationList operations_list, + ConfirmationCallback callback) { + DCHECK(!operations_list.empty()); + + ContentOperation operation(operations_list.front()); + operations_list.pop_front(); + + switch (operation.type()) { + case ContentOperation::CONTENT_DELETE: + // TODO(gangwu): If deletes are continuous, we should combine them into + // one commit. + DeleteContent(std::move(operation), std::move(operations_list), + std::move(callback)); + break; + case ContentOperation::CONTENT_DELETE_BY_PREFIX: + DeleteContentByPrefix(std::move(operation), std::move(operations_list), + std::move(callback)); + break; + case ContentOperation::CONTENT_UPSERT: + // TODO(gangwu): If upserts are continuous, we should combine them into + // one commit. + UpsertContent(std::move(operation), std::move(operations_list), + std::move(callback)); + break; + case ContentOperation::CONTENT_DELETE_ALL: + DeleteAllContent(std::move(operation), std::move(operations_list), + std::move(callback)); + break; + default: + // Operation type is not supported, therefore failing immediately. + base::ThreadTaskRunnerHandle::Get()->PostTask( + FROM_HERE, base::BindOnce(std::move(callback), false)); + } +} + +void FeedContentDatabase::UpsertContent(ContentOperation operation, + ContentOperationList operations_list, + ConfirmationCallback callback) { + DCHECK_EQ(operation.type(), ContentOperation::CONTENT_UPSERT); + + auto contents_to_save = std::make_unique<StorageEntryVector>(); + ContentStorageProto proto; + proto.set_key(operation.key()); + proto.set_content_data(operation.value()); + contents_to_save->emplace_back(proto.key(), std::move(proto)); + + storage_database_->UpdateEntries( + std::move(contents_to_save), std::make_unique<std::vector<std::string>>(), + base::BindOnce(&FeedContentDatabase::OnOperationCommitted, + weak_ptr_factory_.GetWeakPtr(), std::move(operations_list), + std::move(callback))); +} + +void FeedContentDatabase::DeleteContent(ContentOperation operation, + ContentOperationList operations_list, + ConfirmationCallback callback) { + DCHECK_EQ(operation.type(), ContentOperation::CONTENT_DELETE); + + auto content_to_delete = std::make_unique<std::vector<std::string>>( + std::initializer_list<std::string>({operation.key()})); + + storage_database_->UpdateEntries( + std::make_unique<StorageEntryVector>(), std::move(content_to_delete), + base::BindOnce(&FeedContentDatabase::OnOperationCommitted, + weak_ptr_factory_.GetWeakPtr(), std::move(operations_list), + std::move(callback))); +} + +void FeedContentDatabase::DeleteContentByPrefix( + ContentOperation operation, + ContentOperationList operations_list, + ConfirmationCallback callback) { + DCHECK_EQ(operation.type(), ContentOperation::CONTENT_DELETE_BY_PREFIX); + + storage_database_->UpdateEntriesWithRemoveFilter( + std::make_unique<StorageEntryVector>(), + base::BindRepeating(&DatabasePrefixFilter, operation.prefix()), + base::BindOnce(&FeedContentDatabase::OnOperationCommitted, + weak_ptr_factory_.GetWeakPtr(), std::move(operations_list), + std::move(callback))); +} + +void FeedContentDatabase::DeleteAllContent(ContentOperation operation, + ContentOperationList operations_list, + ConfirmationCallback callback) { + DCHECK_EQ(operation.type(), ContentOperation::CONTENT_DELETE_ALL); + + std::string key_prefix = ""; + storage_database_->UpdateEntriesWithRemoveFilter( + std::make_unique<StorageEntryVector>(), + base::BindRepeating(&DatabasePrefixFilter, std::move(key_prefix)), + base::BindOnce(&FeedContentDatabase::OnOperationCommitted, + weak_ptr_factory_.GetWeakPtr(), std::move(operations_list), + std::move(callback))); +} + +void FeedContentDatabase::OnDatabaseInitialized(bool success) { + DCHECK_EQ(database_status_, UNINITIALIZED); + + if (success) { + database_status_ = INITIALIZED; + } else { + database_status_ = INIT_FAILURE; + DVLOG(1) << "FeedContentDatabase init failed."; + } +} + +void FeedContentDatabase::OnLoadEntriesForLoadContent( + ContentLoadCallback callback, + bool success, + std::unique_ptr<std::vector<ContentStorageProto>> content) { + std::vector<KeyAndData> results; + + if (!success || !content) { + DVLOG_IF(1, !success) << "FeedContentDatabase load content failed."; + std::move(callback).Run(std::move(results)); + return; + } + + for (const auto& proto : *content) { + DCHECK(proto.has_key()); + DCHECK(proto.has_content_data()); + + results.emplace_back(proto.key(), proto.content_data()); + } + + std::move(callback).Run(std::move(results)); +} + +void FeedContentDatabase::OnLoadKeysForLoadAllContentKeys( + ContentKeyCallback callback, + bool success, + std::unique_ptr<std::vector<std::string>> keys) { + if (!success || !keys) { + DVLOG_IF(1, !success) << "FeedContentDatabase load content keys failed."; + std::vector<std::string> results; + std::move(callback).Run(std::move(results)); + return; + } + + // We std::move the |*keys|'s entries to |callback|, after that, |keys| become + // a pointer holding an empty vector, then we can safely delete unique_ptr + // |keys| when it out of scope. + std::move(callback).Run(std::move(*keys)); +} + +void FeedContentDatabase::OnOperationCommitted( + ContentOperationList operations_list, + ConfirmationCallback callback, + bool success) { + // Commit is unsuccessful, skip processing the other operations since + // ContentStorage.java requires "In the event of a failure, processing is + // halted immediately". + if (!success) { + DVLOG(1) << "FeedContentDatabase committed failed."; + std::move(callback).Run(success); + return; + } + + // All operations were committed successfully, call |callback|. + if (operations_list.empty()) { + std::move(callback).Run(success); + return; + } + + PerformNextOperation(std::move(operations_list), std::move(callback)); +} + +} // namespace feed
diff --git a/components/feed/core/feed_content_database.h b/components/feed/core/feed_content_database.h new file mode 100644 index 0000000..f7faa19 --- /dev/null +++ b/components/feed/core/feed_content_database.h
@@ -0,0 +1,133 @@ +// 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 COMPONENTS_FEED_CORE_FEED_CONTENT_DATABASE_H_ +#define COMPONENTS_FEED_CORE_FEED_CONTENT_DATABASE_H_ + +#include <memory> +#include <string> +#include <utility> +#include <vector> + +#include "base/memory/weak_ptr.h" +#include "base/sequenced_task_runner.h" +#include "components/feed/core/feed_content_mutation.h" +#include "components/feed/core/feed_content_operation.h" +#include "components/leveldb_proto/proto_database.h" + +namespace feed { + +class ContentStorageProto; + +// FeedContentDatabase is leveldb backend store for Feed's content storage data. +// Feed's content data are key-value pairs. +class FeedContentDatabase { + public: + enum State { + UNINITIALIZED, + INITIALIZED, + INIT_FAILURE, + }; + + using KeyAndData = std::pair<std::string, std::string>; + + // Returns the storage data as a vector of key-value pairs when calling + // loading data. + using ContentLoadCallback = base::OnceCallback<void(std::vector<KeyAndData>)>; + + // Returns the content keys as a vector when calling loading all content keys. + using ContentKeyCallback = base::OnceCallback<void(std::vector<std::string>)>; + + // Returns whether the commit operation succeeded when calling for database + // operations, or return whether the entry exists when calling for checking + // the entry's existence. + using ConfirmationCallback = base::OnceCallback<void(bool)>; + + // Initializes the database with |database_folder|. + explicit FeedContentDatabase(const base::FilePath& database_folder); + + // Initializes the database with |database_folder|. Creates storage using the + // given |storage_database| for local storage. Useful for testing. + FeedContentDatabase( + const base::FilePath& database_folder, + std::unique_ptr<leveldb_proto::ProtoDatabase<ContentStorageProto>> + storage_database); + + ~FeedContentDatabase(); + + // Returns true if initialization has finished successfully, else false. + // While this is false, initialization may already started, or initialization + // failed. + bool IsInitialized() const; + + // Loads the content data for the |keys| and passes them to |callback|. + void LoadContent(const std::vector<std::string>& keys, + ContentLoadCallback callback); + + // Loads the content data whose key matches |prefix|, and passes them to + // |callback|. + void LoadContentByPrefix(const std::string& prefix, + ContentLoadCallback callback); + + // Loads all content keys in the storage, and passes them to |callback|. + void LoadAllContentKeys(ContentKeyCallback callback); + + // Commits the operations in the |content_mutation|. |callback| will be called + // when all the operations are committed. Or if any operation failed, database + // will stop process any operations and passed error to |callback|. + void CommitContentMutation(std::unique_ptr<ContentMutation> content_mutation, + ConfirmationCallback callback); + + private: + friend class FeedContentDatabaseTest; + + // These methods work with |CommitContentMutation|. They process + // |ContentOperation| in |ContentMutation| which is passed to + // |PerformNextOperation| by |CommitContentMutation|. + void PerformNextOperation(ContentOperationList operations_list, + ConfirmationCallback callback); + void UpsertContent(ContentOperation operation, + ContentOperationList operations_list, + ConfirmationCallback callback); + void DeleteContent(ContentOperation operation, + ContentOperationList operations_list, + ConfirmationCallback callback); + void DeleteContentByPrefix(ContentOperation operation, + ContentOperationList operations_list, + ConfirmationCallback callback); + void DeleteAllContent(ContentOperation operation, + ContentOperationList operations_list, + ConfirmationCallback callback); + + // Callback methods given to |storage_database_| for async responses. + void OnDatabaseInitialized(bool success); + void OnLoadEntriesForLoadContent( + ContentLoadCallback callback, + bool success, + std::unique_ptr<std::vector<ContentStorageProto>> content); + void OnLoadKeysForLoadAllContentKeys( + ContentKeyCallback callback, + bool success, + std::unique_ptr<std::vector<std::string>> keys); + void OnOperationCommitted(ContentOperationList operations_list, + ConfirmationCallback callback, + bool success); + + // Status of the database initialization. + State database_status_; + + // The database for storing content storage information. + std::unique_ptr<leveldb_proto::ProtoDatabase<ContentStorageProto>> + storage_database_; + + SEQUENCE_CHECKER(sequence_checker_); + + base::WeakPtrFactory<FeedContentDatabase> weak_ptr_factory_; + + DISALLOW_COPY_AND_ASSIGN(FeedContentDatabase); +}; + +} // namespace feed + +#endif // COMPONENTS_FEED_CORE_FEED_CONTENT_DATABASE_H_
diff --git a/components/feed/core/feed_content_database_unittest.cc b/components/feed/core/feed_content_database_unittest.cc new file mode 100644 index 0000000..6154222 --- /dev/null +++ b/components/feed/core/feed_content_database_unittest.cc
@@ -0,0 +1,335 @@ +// Copyright 2018 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#include "components/feed/core/feed_content_database.h" + +#include <map> + +#include "base/test/scoped_task_environment.h" +#include "components/feed/core/feed_content_mutation.h" +#include "components/feed/core/proto/content_storage.pb.h" +#include "components/feed/core/time_serialization.h" +#include "components/leveldb_proto/testing/fake_db.h" +#include "testing/gmock/include/gmock/gmock.h" +#include "testing/gtest/include/gtest/gtest.h" + +using leveldb_proto::test::FakeDB; +using testing::Mock; +using testing::NotNull; +using testing::_; + +namespace feed { + +namespace { + +const char kContentKeyPrefix[] = "ContentKey"; +const char kContentKey1[] = "ContentKey1"; +const char kContentKey2[] = "ContentKey2"; +const char kContentKey3[] = "ContentKey3"; +const char kContentData1[] = "Content Data1"; +const char kContentData2[] = "Content Data2"; + +} // namespace + +class FeedContentDatabaseTest : public testing::Test { + public: + FeedContentDatabaseTest() : content_db_(nullptr) {} + + void CreateDatabase(bool init_database) { + // The FakeDBs are owned by |feed_db_|, so clear our pointers before + // resetting |feed_db_| itself. + content_db_ = nullptr; + // Explicitly destroy any existing database before creating a new one. + feed_db_.reset(); + + auto storage_db = + std::make_unique<FakeDB<ContentStorageProto>>(&content_db_storage_); + + content_db_ = storage_db.get(); + feed_db_ = std::make_unique<FeedContentDatabase>(base::FilePath(), + std::move(storage_db)); + if (init_database) { + content_db_->InitCallback(true); + ASSERT_TRUE(db()->IsInitialized()); + } + } + + void InjectContentStorageProto(const std::string& key, + const std::string& data) { + ContentStorageProto storage_proto; + storage_proto.set_key(key); + storage_proto.set_content_data(data); + content_db_storage_[key] = storage_proto; + } + + void RunUntilIdle() { scoped_task_environment_.RunUntilIdle(); } + + FakeDB<ContentStorageProto>* storage_db() { return content_db_; } + + FeedContentDatabase* db() { return feed_db_.get(); } + + MOCK_METHOD1(OnContentEntriesReceived, + void(std::vector<std::pair<std::string, std::string>>)); + MOCK_METHOD1(OnContentKeyReceived, void(std::vector<std::string>)); + MOCK_METHOD1(OnStorageCommitted, void(bool)); + + private: + base::test::ScopedTaskEnvironment scoped_task_environment_; + + std::map<std::string, ContentStorageProto> content_db_storage_; + + // Owned by |feed_db_|. + FakeDB<ContentStorageProto>* content_db_; + + std::unique_ptr<FeedContentDatabase> feed_db_; + + DISALLOW_COPY_AND_ASSIGN(FeedContentDatabaseTest); +}; + +TEST_F(FeedContentDatabaseTest, Init) { + ASSERT_FALSE(db()); + + CreateDatabase(/*init_database=*/false); + + storage_db()->InitCallback(true); + EXPECT_TRUE(db()->IsInitialized()); +} + +TEST_F(FeedContentDatabaseTest, LoadContentAfterInitSuccess) { + CreateDatabase(/*init_database=*/true); + + EXPECT_CALL(*this, OnContentEntriesReceived(_)); + db()->LoadContent( + {kContentKey1}, + base::BindOnce(&FeedContentDatabaseTest::OnContentEntriesReceived, + base::Unretained(this))); + storage_db()->LoadCallback(true); +} + +TEST_F(FeedContentDatabaseTest, LoadContentsEntries) { + CreateDatabase(/*init_database=*/true); + + // Store |kContentKey1| and |kContentKey2|. + InjectContentStorageProto(kContentKey1, kContentData1); + InjectContentStorageProto(kContentKey2, kContentData2); + + // Try to Load |kContentKey2| and |kContentKey3|, only |kContentKey2| should + // return. + EXPECT_CALL(*this, OnContentEntriesReceived(_)) + .WillOnce([](std::vector<std::pair<std::string, std::string>> results) { + ASSERT_EQ(results.size(), 1U); + EXPECT_EQ(results[0].first, kContentKey2); + EXPECT_EQ(results[0].second, kContentData2); + }); + db()->LoadContent( + {kContentKey2, kContentKey3}, + base::BindOnce(&FeedContentDatabaseTest::OnContentEntriesReceived, + base::Unretained(this))); + storage_db()->LoadCallback(true); +} + +TEST_F(FeedContentDatabaseTest, LoadContentsEntriesByPrefix) { + CreateDatabase(/*init_database=*/true); + + // Store |kContentKey1|, |kContentKey2|. + InjectContentStorageProto(kContentKey1, kContentData1); + InjectContentStorageProto(kContentKey2, kContentData2); + + // Try to Load "ContentKey", both |kContentKey1| and |kContentKey2| should + // return. + EXPECT_CALL(*this, OnContentEntriesReceived(_)) + .WillOnce([](std::vector<std::pair<std::string, std::string>> results) { + ASSERT_EQ(results.size(), 2U); + EXPECT_EQ(results[0].first, kContentKey1); + EXPECT_EQ(results[0].second, kContentData1); + EXPECT_EQ(results[1].first, kContentKey2); + EXPECT_EQ(results[1].second, kContentData2); + }); + db()->LoadContentByPrefix( + kContentKeyPrefix, + base::BindOnce(&FeedContentDatabaseTest::OnContentEntriesReceived, + base::Unretained(this))); + storage_db()->LoadCallback(true); +} + +TEST_F(FeedContentDatabaseTest, LoadAllContentKeys) { + CreateDatabase(/*init_database=*/true); + + // Store |kContentKey1|, |kContentKey2|. + InjectContentStorageProto(kContentKey1, kContentData1); + InjectContentStorageProto(kContentKey2, kContentData2); + + EXPECT_CALL(*this, OnContentKeyReceived(_)) + .WillOnce([](std::vector<std::string> results) { + ASSERT_EQ(results.size(), 2U); + EXPECT_EQ(results[0], kContentKey1); + EXPECT_EQ(results[1], kContentKey2); + }); + db()->LoadAllContentKeys(base::BindOnce( + &FeedContentDatabaseTest::OnContentKeyReceived, base::Unretained(this))); + storage_db()->LoadKeysCallback(true); +} + +TEST_F(FeedContentDatabaseTest, SaveContent) { + CreateDatabase(/*init_database=*/true); + + // Store |kContentKey1|, |kContentKey2|. + std::unique_ptr<ContentMutation> content_mutation = + std::make_unique<ContentMutation>(); + content_mutation->AppendUpsertOperation(kContentKey1, kContentData1); + content_mutation->AppendUpsertOperation(kContentKey2, kContentData2); + EXPECT_CALL(*this, OnStorageCommitted(true)); + db()->CommitContentMutation( + std::move(content_mutation), + base::BindOnce(&FeedContentDatabaseTest::OnStorageCommitted, + base::Unretained(this))); + storage_db()->UpdateCallback(true); + storage_db()->UpdateCallback(true); + + // Make sure they're there. + EXPECT_CALL(*this, OnContentEntriesReceived(_)) + .WillOnce([](std::vector<std::pair<std::string, std::string>> results) { + ASSERT_EQ(results.size(), 2U); + EXPECT_EQ(results[0].first, kContentKey1); + EXPECT_EQ(results[0].second, kContentData1); + EXPECT_EQ(results[1].first, kContentKey2); + EXPECT_EQ(results[1].second, kContentData2); + }); + db()->LoadContent( + {kContentKey1, kContentKey2}, + base::BindOnce(&FeedContentDatabaseTest::OnContentEntriesReceived, + base::Unretained(this))); + storage_db()->LoadCallback(true); +} + +TEST_F(FeedContentDatabaseTest, DeleteContent) { + CreateDatabase(/*init_database=*/true); + + // Store |kContentKey1| and |kContentKey2|. + InjectContentStorageProto(kContentKey1, kContentData1); + InjectContentStorageProto(kContentKey2, kContentData2); + + // Delete |kContentKey2| and |kContentKey3| + std::unique_ptr<ContentMutation> content_mutation = + std::make_unique<ContentMutation>(); + content_mutation->AppendDeleteOperation(kContentKey2); + content_mutation->AppendDeleteOperation(kContentKey3); + EXPECT_CALL(*this, OnStorageCommitted(true)); + db()->CommitContentMutation( + std::move(content_mutation), + base::BindOnce(&FeedContentDatabaseTest::OnStorageCommitted, + base::Unretained(this))); + storage_db()->UpdateCallback(true); + storage_db()->UpdateCallback(true); + + // Make sure only |kContentKey2| got deleted. + EXPECT_CALL(*this, OnContentEntriesReceived(_)) + .WillOnce([](std::vector<std::pair<std::string, std::string>> results) { + EXPECT_EQ(results.size(), 1U); + EXPECT_EQ(results[0].first, kContentKey1); + EXPECT_EQ(results[0].second, kContentData1); + }); + db()->LoadContent( + {kContentKey1, kContentKey2}, + base::BindOnce(&FeedContentDatabaseTest::OnContentEntriesReceived, + base::Unretained(this))); + storage_db()->LoadCallback(true); +} + +TEST_F(FeedContentDatabaseTest, DeleteContentByPrefix) { + CreateDatabase(/*init_database=*/true); + + // Store |kContentKey1| and |kContentKey2|. + InjectContentStorageProto(kContentKey1, kContentData1); + InjectContentStorageProto(kContentKey2, kContentData2); + + // Delete |kContentKey1| and |kContentKey2| + std::unique_ptr<ContentMutation> content_mutation = + std::make_unique<ContentMutation>(); + content_mutation->AppendDeleteByPrefixOperation(kContentKeyPrefix); + EXPECT_CALL(*this, OnStorageCommitted(true)); + db()->CommitContentMutation( + std::move(content_mutation), + base::BindOnce(&FeedContentDatabaseTest::OnStorageCommitted, + base::Unretained(this))); + storage_db()->UpdateCallback(true); + + // Make sure |kContentKey1| and |kContentKey2| got deleted. + EXPECT_CALL(*this, OnContentEntriesReceived(_)) + .WillOnce([](std::vector<std::pair<std::string, std::string>> results) { + EXPECT_EQ(results.size(), 0U); + }); + db()->LoadContent( + {kContentKey1, kContentKey2}, + base::BindOnce(&FeedContentDatabaseTest::OnContentEntriesReceived, + base::Unretained(this))); + storage_db()->LoadCallback(true); +} + +TEST_F(FeedContentDatabaseTest, DeleteAllContent) { + CreateDatabase(/*init_database=*/true); + + // Store |kContentKey1| and |kContentKey2|. + InjectContentStorageProto(kContentKey1, kContentData1); + InjectContentStorageProto(kContentKey2, kContentData2); + + // Delete all content, meaning |kContentKey1| and |kContentKey2| are expected + // to be deleted. + std::unique_ptr<ContentMutation> content_mutation = + std::make_unique<ContentMutation>(); + content_mutation->AppendDeleteAllOperation(); + EXPECT_CALL(*this, OnStorageCommitted(true)); + db()->CommitContentMutation( + std::move(content_mutation), + base::BindOnce(&FeedContentDatabaseTest::OnStorageCommitted, + base::Unretained(this))); + storage_db()->UpdateCallback(true); + + // Make sure |kContentKey1| and |kContentKey2| got deleted. + EXPECT_CALL(*this, OnContentEntriesReceived(_)) + .WillOnce([](std::vector<std::pair<std::string, std::string>> results) { + EXPECT_EQ(results.size(), 0U); + }); + db()->LoadContent( + {kContentKey1, kContentKey2}, + base::BindOnce(&FeedContentDatabaseTest::OnContentEntriesReceived, + base::Unretained(this))); + storage_db()->LoadCallback(true); +} + +TEST_F(FeedContentDatabaseTest, SaveAndDeleteContent) { + CreateDatabase(/*init_database=*/true); + + // Store |kContentKey1|, |kContentKey2|. + std::unique_ptr<ContentMutation> content_mutation = + std::make_unique<ContentMutation>(); + content_mutation->AppendUpsertOperation(kContentKey1, kContentData1); + content_mutation->AppendUpsertOperation(kContentKey2, kContentData2); + content_mutation->AppendDeleteOperation(kContentKey2); + content_mutation->AppendDeleteOperation(kContentKey3); + EXPECT_CALL(*this, OnStorageCommitted(true)); + db()->CommitContentMutation( + std::move(content_mutation), + base::BindOnce(&FeedContentDatabaseTest::OnStorageCommitted, + base::Unretained(this))); + storage_db()->UpdateCallback(true); + storage_db()->UpdateCallback(true); + storage_db()->UpdateCallback(true); + storage_db()->UpdateCallback(true); + + // Make sure only |kContentKey2| got deleted. + EXPECT_CALL(*this, OnContentEntriesReceived(_)) + .WillOnce([](std::vector<std::pair<std::string, std::string>> results) { + EXPECT_EQ(results.size(), 1U); + EXPECT_EQ(results[0].first, kContentKey1); + EXPECT_EQ(results[0].second, kContentData1); + }); + db()->LoadContent( + {kContentKey1, kContentKey2}, + base::BindOnce(&FeedContentDatabaseTest::OnContentEntriesReceived, + base::Unretained(this))); + storage_db()->LoadCallback(true); +} + +} // namespace feed
diff --git a/components/feed/core/feed_content_mutation.cc b/components/feed/core/feed_content_mutation.cc new file mode 100644 index 0000000..607b425 --- /dev/null +++ b/components/feed/core/feed_content_mutation.cc
@@ -0,0 +1,40 @@ +// Copyright 2018 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#include "components/feed/core/feed_content_mutation.h" + +#include <utility> + +#include "components/feed/core/feed_content_operation.h" + +namespace feed { + +ContentMutation::ContentMutation() {} + +ContentMutation::~ContentMutation() {} + +void ContentMutation::AppendDeleteOperation(const std::string& key) { + operations_list_.emplace_back(ContentOperation::CreateDeleteOperation(key)); +} + +void ContentMutation::AppendDeleteAllOperation() { + operations_list_.emplace_back(ContentOperation::CreateDeleteAllOperation()); +} + +void ContentMutation::AppendDeleteByPrefixOperation(const std::string& prefix) { + operations_list_.emplace_back( + ContentOperation::CreateDeleteByPrefixOperation(prefix)); +} + +void ContentMutation::AppendUpsertOperation(const std::string& key, + const std::string& value) { + operations_list_.emplace_back( + ContentOperation::CreateUpsertOperation(key, value)); +} + +ContentOperationList ContentMutation::TakeOperations() { + return std::move(operations_list_); +} + +} // namespace feed
diff --git a/components/feed/core/feed_content_mutation.h b/components/feed/core/feed_content_mutation.h new file mode 100644 index 0000000..e719549 --- /dev/null +++ b/components/feed/core/feed_content_mutation.h
@@ -0,0 +1,44 @@ +// 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 COMPONENTS_FEED_CORE_FEED_CONTENT_MUTATION_H_ +#define COMPONENTS_FEED_CORE_FEED_CONTENT_MUTATION_H_ + +#include <list> +#include <string> + +#include "base/macros.h" + +namespace feed { + +class ContentOperation; +using ContentOperationList = std::list<ContentOperation>; + +// Native counterpart of ContentMutation.java. +// To commit a set of ContentOperation into FeedContentDatabase, user need to +// create a ContentMutation, next use Append* methods to append operations +// into the mutation, and then pass the ContentMutation to +// |FeedContentDatabase::CommitContentMutation| to commit operations. +class ContentMutation { + public: + ContentMutation(); + ~ContentMutation(); + + void AppendDeleteOperation(const std::string& key); + void AppendDeleteAllOperation(); + void AppendDeleteByPrefixOperation(const std::string& prefix); + void AppendUpsertOperation(const std::string& key, const std::string& value); + + // This will std::move the |operations_list_| out. + ContentOperationList TakeOperations(); + + private: + ContentOperationList operations_list_; + + DISALLOW_COPY_AND_ASSIGN(ContentMutation); +}; + +} // namespace feed + +#endif // COMPONENTS_FEED_CORE_FEED_CONTENT_MUTATION_H_
diff --git a/components/feed/core/feed_content_operation.cc b/components/feed/core/feed_content_operation.cc new file mode 100644 index 0000000..1cd4b35 --- /dev/null +++ b/components/feed/core/feed_content_operation.cc
@@ -0,0 +1,70 @@ +// Copyright 2018 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#include "components/feed/core/feed_content_operation.h" + +#include <utility> + +#include "base/logging.h" + +namespace feed { + +ContentOperation::ContentOperation(const ContentOperation& operation) + : type_(operation.type_), + key_(operation.key_), + value_(operation.value_), + prefix_(operation.prefix_) {} + +ContentOperation::ContentOperation(ContentOperation&& operation) + : type_(operation.type_), + key_(std::move(operation.key_)), + value_(std::move(operation.value_)), + prefix_(std::move(operation.prefix_)) {} + +ContentOperation ContentOperation::CreateDeleteOperation(std::string key) { + return ContentOperation(CONTENT_DELETE, key, std::string(), std::string()); +} + +ContentOperation ContentOperation::CreateDeleteAllOperation() { + return ContentOperation(CONTENT_DELETE_ALL, std::string(), std::string(), + std::string()); +} + +ContentOperation ContentOperation::CreateDeleteByPrefixOperation( + std::string prefix) { + return ContentOperation(CONTENT_DELETE_BY_PREFIX, std::string(), + std::string(), prefix); +} + +ContentOperation ContentOperation::CreateUpsertOperation(std::string key, + std::string value) { + return ContentOperation(CONTENT_UPSERT, key, value, std::string()); +} + +ContentOperation::Type ContentOperation::type() { + return type_; +} + +const std::string& ContentOperation::key() { + DCHECK(type_ == CONTENT_UPSERT || type_ == CONTENT_DELETE); + return key_; +} + +const std::string& ContentOperation::value() { + DCHECK_EQ(type_, CONTENT_UPSERT); + return value_; +} + +const std::string& ContentOperation::prefix() { + DCHECK_EQ(type_, CONTENT_DELETE_BY_PREFIX); + return prefix_; +} + +ContentOperation::ContentOperation(Type type, + std::string key, + std::string value, + std::string prefix) + : type_(type), key_(key), value_(value), prefix_(prefix) {} + +} // namespace feed
diff --git a/components/feed/core/feed_content_operation.h b/components/feed/core/feed_content_operation.h new file mode 100644 index 0000000..cd15123 --- /dev/null +++ b/components/feed/core/feed_content_operation.h
@@ -0,0 +1,54 @@ +// 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 COMPONENTS_FEED_CORE_FEED_CONTENT_OPERATION_H_ +#define COMPONENTS_FEED_CORE_FEED_CONTENT_OPERATION_H_ + +#include <list> +#include <string> + +namespace feed { + +// Native counterpart of ContentOperation.java. +class ContentOperation { + public: + enum Type { + CONTENT_DELETE, + CONTENT_DELETE_ALL, + CONTENT_DELETE_BY_PREFIX, + CONTENT_UPSERT, + }; + + static ContentOperation CreateDeleteOperation(std::string key); + static ContentOperation CreateDeleteAllOperation(); + static ContentOperation CreateDeleteByPrefixOperation(std::string prefix); + static ContentOperation CreateUpsertOperation(std::string key, + std::string value); + + // Copy constructor + explicit ContentOperation(const ContentOperation& operation); + + // Move constructor + ContentOperation(ContentOperation&& operation); + + Type type(); + const std::string& key(); + const std::string& value(); + const std::string& prefix(); + + private: + ContentOperation(Type type, + std::string key, + std::string value, + std::string prefix); + + const Type type_; + const std::string key_; + const std::string value_; + const std::string prefix_; +}; + +} // namespace feed + +#endif // COMPONENTS_FEED_CORE_FEED_CONTENT_OPERATION_H_
diff --git a/components/feed/core/feed_host_service.cc b/components/feed/core/feed_host_service.cc index fe202d6..41df695 100644 --- a/components/feed/core/feed_host_service.cc +++ b/components/feed/core/feed_host_service.cc
@@ -12,11 +12,13 @@ std::unique_ptr<FeedImageManager> image_manager, std::unique_ptr<FeedNetworkingHost> networking_host, std::unique_ptr<FeedSchedulerHost> scheduler_host, - std::unique_ptr<FeedStorageDatabase> storage_database) + std::unique_ptr<FeedStorageDatabase> storage_database, + std::unique_ptr<FeedContentDatabase> content_database) : image_manager_(std::move(image_manager)), networking_host_(std::move(networking_host)), scheduler_host_(std::move(scheduler_host)), - storage_database_(std::move(storage_database)) {} + storage_database_(std::move(storage_database)), + content_database_(std::move(content_database)) {} FeedHostService::~FeedHostService() = default; @@ -36,4 +38,8 @@ return storage_database_.get(); } +FeedContentDatabase* FeedHostService::GetContentDatabase() { + return content_database_.get(); +} + } // namespace feed
diff --git a/components/feed/core/feed_host_service.h b/components/feed/core/feed_host_service.h index 223f6687..9fea389 100644 --- a/components/feed/core/feed_host_service.h +++ b/components/feed/core/feed_host_service.h
@@ -8,6 +8,7 @@ #include <memory> #include "base/macros.h" +#include "components/feed/core/feed_content_database.h" #include "components/feed/core/feed_image_manager.h" #include "components/feed/core/feed_networking_host.h" #include "components/feed/core/feed_scheduler_host.h" @@ -26,19 +27,22 @@ FeedHostService(std::unique_ptr<FeedImageManager> image_manager, std::unique_ptr<FeedNetworkingHost> networking_host, std::unique_ptr<FeedSchedulerHost> scheduler_host, - std::unique_ptr<FeedStorageDatabase> storage_database); + std::unique_ptr<FeedStorageDatabase> storage_database, + std::unique_ptr<FeedContentDatabase> content_database); ~FeedHostService() override; FeedImageManager* GetImageManager(); FeedNetworkingHost* GetNetworkingHost(); FeedSchedulerHost* GetSchedulerHost(); FeedStorageDatabase* GetStorageDatabase(); + FeedContentDatabase* GetContentDatabase(); private: std::unique_ptr<FeedImageManager> image_manager_; std::unique_ptr<FeedNetworkingHost> networking_host_; std::unique_ptr<FeedSchedulerHost> scheduler_host_; std::unique_ptr<FeedStorageDatabase> storage_database_; + std::unique_ptr<FeedContentDatabase> content_database_; DISALLOW_COPY_AND_ASSIGN(FeedHostService); };
diff --git a/components/feed/core/proto/BUILD.gn b/components/feed/core/proto/BUILD.gn index 98626a9..489e3656d 100644 --- a/components/feed/core/proto/BUILD.gn +++ b/components/feed/core/proto/BUILD.gn
@@ -7,6 +7,7 @@ proto_library("proto") { sources = [ "cached_image.proto", + "content_storage.proto", "feed_storage.proto", ] }
diff --git a/components/feed/core/proto/content_storage.proto b/components/feed/core/proto/content_storage.proto new file mode 100644 index 0000000..750a15c --- /dev/null +++ b/components/feed/core/proto/content_storage.proto
@@ -0,0 +1,18 @@ +// 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. + +syntax = "proto2"; + +option optimize_for = LITE_RUNTIME; + +package feed; + +// Used for storing content data in content storage. +message ContentStorageProto { + // Original key for data. + optional string key = 1; + + // Content data. + optional bytes content_data = 2; +}
diff --git a/components/metrics/call_stack_profile_builder.cc b/components/metrics/call_stack_profile_builder.cc index 14b0cf2..c16fcfd0 100644 --- a/components/metrics/call_stack_profile_builder.cc +++ b/components/metrics/call_stack_profile_builder.cc
@@ -79,7 +79,7 @@ const std::vector<base::ModuleCache::Module>& modules, CallStackProfile::Sample* proto_sample) { for (const auto& frame : sample.frames) { - CallStackProfile::Entry* entry = proto_sample->add_entry(); + CallStackProfile::Location* location = proto_sample->add_frame(); // A frame may not have a valid module. If so, we can't compute the // instruction pointer offset, and we don't want to send bare pointers, // so leave call_stack_entry empty. @@ -89,8 +89,8 @@ reinterpret_cast<const char*>(frame.instruction_pointer) - reinterpret_cast<const char*>(modules[frame.module_index].base_address); DCHECK_GE(module_offset, 0); - entry->set_address(static_cast<uint64_t>(module_offset)); - entry->set_module_id_index(frame.module_index); + location->set_address(static_cast<uint64_t>(module_offset)); + location->set_module_id_index(frame.module_index); } }
diff --git a/components/metrics/call_stack_profile_builder_unittest.cc b/components/metrics/call_stack_profile_builder_unittest.cc index 415f95c..2037fcc 100644 --- a/components/metrics/call_stack_profile_builder_unittest.cc +++ b/components/metrics/call_stack_profile_builder_unittest.cc
@@ -113,14 +113,14 @@ const CallStackProfile& profile = proto.call_stack_profile(); ASSERT_EQ(2, profile.sample_size()); - ASSERT_EQ(2, profile.sample(0).entry_size()); - ASSERT_TRUE(profile.sample(0).entry(0).has_module_id_index()); - EXPECT_EQ(0, profile.sample(0).entry(0).module_id_index()); - ASSERT_TRUE(profile.sample(0).entry(1).has_module_id_index()); - EXPECT_EQ(1, profile.sample(0).entry(1).module_id_index()); - ASSERT_EQ(1, profile.sample(1).entry_size()); - ASSERT_TRUE(profile.sample(1).entry(0).has_module_id_index()); - EXPECT_EQ(2, profile.sample(1).entry(0).module_id_index()); + ASSERT_EQ(2, profile.sample(0).frame_size()); + ASSERT_TRUE(profile.sample(0).frame(0).has_module_id_index()); + EXPECT_EQ(0, profile.sample(0).frame(0).module_id_index()); + ASSERT_TRUE(profile.sample(0).frame(1).has_module_id_index()); + EXPECT_EQ(1, profile.sample(0).frame(1).module_id_index()); + ASSERT_EQ(1, profile.sample(1).frame_size()); + ASSERT_TRUE(profile.sample(1).frame(0).has_module_id_index()); + EXPECT_EQ(2, profile.sample(1).frame(0).module_id_index()); ASSERT_EQ(3, profile.module_id().size()); ASSERT_TRUE(profile.module_id(0).has_build_id()); @@ -268,15 +268,15 @@ const CallStackProfile& profile = proto.call_stack_profile(); ASSERT_EQ(1, profile.sample_size()); - ASSERT_EQ(2, profile.sample(0).entry_size()); + ASSERT_EQ(2, profile.sample(0).frame_size()); - ASSERT_FALSE(profile.sample(0).entry(0).has_module_id_index()); - ASSERT_FALSE(profile.sample(0).entry(0).has_address()); + ASSERT_FALSE(profile.sample(0).frame(0).has_module_id_index()); + ASSERT_FALSE(profile.sample(0).frame(0).has_address()); - ASSERT_TRUE(profile.sample(0).entry(1).has_module_id_index()); - EXPECT_EQ(0, profile.sample(0).entry(1).module_id_index()); - ASSERT_TRUE(profile.sample(0).entry(1).has_address()); - EXPECT_EQ(0x10ULL, profile.sample(0).entry(1).address()); + ASSERT_TRUE(profile.sample(0).frame(1).has_module_id_index()); + EXPECT_EQ(0, profile.sample(0).frame(1).module_id_index()); + ASSERT_TRUE(profile.sample(0).frame(1).has_address()); + EXPECT_EQ(0x10ULL, profile.sample(0).frame(1).address()); ASSERT_EQ(1, profile.module_id().size()); ASSERT_TRUE(profile.module_id(0).has_build_id()); @@ -318,19 +318,19 @@ const CallStackProfile& profile = proto.call_stack_profile(); ASSERT_EQ(1, profile.sample_size()); - ASSERT_EQ(2, profile.sample(0).entry_size()); + ASSERT_EQ(2, profile.sample(0).frame_size()); // Since module1 and module2 have the same base address, they are considered // the same module and therefore deduped. - ASSERT_TRUE(profile.sample(0).entry(0).has_module_id_index()); - EXPECT_EQ(0, profile.sample(0).entry(0).module_id_index()); - ASSERT_TRUE(profile.sample(0).entry(0).has_address()); - EXPECT_EQ(0x10ULL, profile.sample(0).entry(0).address()); + ASSERT_TRUE(profile.sample(0).frame(0).has_module_id_index()); + EXPECT_EQ(0, profile.sample(0).frame(0).module_id_index()); + ASSERT_TRUE(profile.sample(0).frame(0).has_address()); + EXPECT_EQ(0x10ULL, profile.sample(0).frame(0).address()); - ASSERT_TRUE(profile.sample(0).entry(1).has_module_id_index()); - EXPECT_EQ(0, profile.sample(0).entry(1).module_id_index()); - ASSERT_TRUE(profile.sample(0).entry(1).has_address()); - EXPECT_EQ(0x20ULL, profile.sample(0).entry(1).address()); + ASSERT_TRUE(profile.sample(0).frame(1).has_module_id_index()); + EXPECT_EQ(0, profile.sample(0).frame(1).module_id_index()); + ASSERT_TRUE(profile.sample(0).frame(1).has_address()); + EXPECT_EQ(0x20ULL, profile.sample(0).frame(1).address()); ASSERT_EQ(1, profile.module_id().size()); ASSERT_TRUE(profile.module_id(0).has_build_id());
diff --git a/components/metrics/call_stack_profile_metrics_provider.cc b/components/metrics/call_stack_profile_metrics_provider.cc index e73d9ec2..50fd6e5 100644 --- a/components/metrics/call_stack_profile_metrics_provider.cc +++ b/components/metrics/call_stack_profile_metrics_provider.cc
@@ -164,10 +164,8 @@ // CallStackProfileMetricsProvider. PendingProfiles::PendingProfiles() : collection_enabled_(true) {} -// Functions to process completed profile ------------------------------------ - // Invoked on an arbitrary thread. Ignores the provided profile. -void IgnoreCompletedProfile(SampledProfile profile) {} +void IgnoreCompletedProfile(SampledProfile /*profile*/) {} } // namespace
diff --git a/components/metrics/public/cpp/call_stack_profile_struct_traits_unittest.cc b/components/metrics/public/cpp/call_stack_profile_struct_traits_unittest.cc index c40e5ae..81e4841 100644 --- a/components/metrics/public/cpp/call_stack_profile_struct_traits_unittest.cc +++ b/components/metrics/public/cpp/call_stack_profile_struct_traits_unittest.cc
@@ -54,9 +54,9 @@ CallStackProfile::Sample* proto_sample = proto_profile->add_sample(); proto_sample->set_count(1); - CallStackProfile::Entry* entry = proto_sample->add_entry(); - entry->set_address(0x10ULL); - entry->set_module_id_index(0); + CallStackProfile::Location* location = proto_sample->add_frame(); + location->set_address(0x10ULL); + location->set_module_id_index(0); CallStackProfile::ModuleIdentifier* module_id = proto_profile->add_module_id(); @@ -74,13 +74,13 @@ const CallStackProfile& out_profile = output_proto.call_stack_profile(); ASSERT_EQ(1, out_profile.sample_size()); - ASSERT_EQ(1, out_profile.sample(0).entry_size()); + ASSERT_EQ(1, out_profile.sample(0).frame_size()); - ASSERT_TRUE(out_profile.sample(0).entry(0).has_address()); - EXPECT_EQ(0x10ULL, out_profile.sample(0).entry(0).address()); + ASSERT_TRUE(out_profile.sample(0).frame(0).has_address()); + EXPECT_EQ(0x10ULL, out_profile.sample(0).frame(0).address()); - ASSERT_TRUE(out_profile.sample(0).entry(0).has_module_id_index()); - EXPECT_EQ(0, out_profile.sample(0).entry(0).module_id_index()); + ASSERT_TRUE(out_profile.sample(0).frame(0).has_module_id_index()); + EXPECT_EQ(0, out_profile.sample(0).frame(0).module_id_index()); ASSERT_EQ(1, out_profile.module_id().size());
diff --git a/components/offline_pages/core/background/BUILD.gn b/components/offline_pages/core/background/BUILD.gn index 18a8833f..75d9e18 100644 --- a/components/offline_pages/core/background/BUILD.gn +++ b/components/offline_pages/core/background/BUILD.gn
@@ -67,6 +67,7 @@ "//components/offline_pages/core", "//components/offline_pages/core:switches", "//net", + "//services/network/public/cpp", "//sql:sql", "//url", ] @@ -75,8 +76,6 @@ static_library("test_support") { testonly = true sources = [ - "network_quality_provider_stub.cc", - "network_quality_provider_stub.h", "offliner_stub.cc", "offliner_stub.h", "request_coordinator_stub_taco.cc", @@ -93,6 +92,8 @@ "//components/offline_items_collection/core/test_support", "//components/offline_pages/core", "//net", + "//services/network:test_support", + "//services/network/public/cpp", ] } @@ -125,6 +126,8 @@ "//components/offline_items_collection/core", "//components/offline_pages/core", "//components/offline_pages/core:switches", + "//services/network:test_support", + "//services/network/public/cpp", "//sql:sql", "//testing/gtest", "//url",
diff --git a/components/offline_pages/core/background/DEPS b/components/offline_pages/core/background/DEPS index 5f8ec85..8eb14492 100644 --- a/components/offline_pages/core/background/DEPS +++ b/components/offline_pages/core/background/DEPS
@@ -1,4 +1,6 @@ include_rules = [ "+sql", "+net", + "+services/network/public", + "+services/network/test", ]
diff --git a/components/offline_pages/core/background/network_quality_provider_stub.cc b/components/offline_pages/core/background/network_quality_provider_stub.cc deleted file mode 100644 index 168d277e..0000000 --- a/components/offline_pages/core/background/network_quality_provider_stub.cc +++ /dev/null
@@ -1,37 +0,0 @@ -// Copyright 2016 The Chromium Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -#include "components/offline_pages/core/background/network_quality_provider_stub.h" - -namespace offline_pages { - -const char kOfflineNQPKey[] = "OfflineNQP"; - -NetworkQualityProviderStub::NetworkQualityProviderStub() - : connection_type_( - net::EffectiveConnectionType::EFFECTIVE_CONNECTION_TYPE_3G) {} - -NetworkQualityProviderStub::~NetworkQualityProviderStub() {} - -// static -NetworkQualityProviderStub* NetworkQualityProviderStub::GetUserData( - base::SupportsUserData* supports_user_data) { - return static_cast<NetworkQualityProviderStub*>( - supports_user_data->GetUserData(&kOfflineNQPKey)); -} - -// static -void NetworkQualityProviderStub::SetUserData( - base::SupportsUserData* supports_user_data, - std::unique_ptr<NetworkQualityProviderStub> stub) { - DCHECK(supports_user_data); - DCHECK(stub); - supports_user_data->SetUserData(&kOfflineNQPKey, std::move(stub)); -} - -net::EffectiveConnectionType -NetworkQualityProviderStub::GetEffectiveConnectionType() const { - return connection_type_; -} -} // namespace offline_pages
diff --git a/components/offline_pages/core/background/network_quality_provider_stub.h b/components/offline_pages/core/background/network_quality_provider_stub.h deleted file mode 100644 index b6341b9..0000000 --- a/components/offline_pages/core/background/network_quality_provider_stub.h +++ /dev/null
@@ -1,39 +0,0 @@ -// Copyright 2016 The Chromium Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -#ifndef COMPONENTS_OFFLINE_PAGES_CORE_BACKGROUND_NETWORK_QUALITY_PROVIDER_STUB_H_ -#define COMPONENTS_OFFLINE_PAGES_CORE_BACKGROUND_NETWORK_QUALITY_PROVIDER_STUB_H_ - -#include "base/supports_user_data.h" -#include "net/nqe/effective_connection_type.h" -#include "net/nqe/network_quality_provider.h" - -namespace offline_pages { - -// Test class stubbing out the functionality of NQE::NetworkQualityProvider. -// It is only used for test support. -class NetworkQualityProviderStub : public net::NetworkQualityProvider, - public base::SupportsUserData::Data { - public: - NetworkQualityProviderStub(); - ~NetworkQualityProviderStub() override; - - static NetworkQualityProviderStub* GetUserData( - base::SupportsUserData* supports_user_data); - static void SetUserData(base::SupportsUserData* supports_user_data, - std::unique_ptr<NetworkQualityProviderStub> stub); - - net::EffectiveConnectionType GetEffectiveConnectionType() const override; - - void SetEffectiveConnectionTypeForTest(net::EffectiveConnectionType type) { - connection_type_ = type; - } - - private: - net::EffectiveConnectionType connection_type_; -}; - -} // namespace offline_pages - -#endif // COMPONENTS_OFFLINE_PAGES_CORE_BACKGROUND_NETWORK_QUALITY_PROVIDER_STUB_H_
diff --git a/components/offline_pages/core/background/request_coordinator.cc b/components/offline_pages/core/background/request_coordinator.cc index f940ed4..a70bf17 100644 --- a/components/offline_pages/core/background/request_coordinator.cc +++ b/components/offline_pages/core/background/request_coordinator.cc
@@ -24,6 +24,7 @@ #include "components/offline_pages/core/offline_page_model.h" #include "components/offline_pages/core/offline_pages_ukm_reporter.h" #include "components/offline_pages/core/offline_store_utils.h" +#include "services/network/public/cpp/network_quality_tracker.h" namespace offline_pages { @@ -229,8 +230,7 @@ std::unique_ptr<Offliner> offliner, std::unique_ptr<RequestQueue> queue, std::unique_ptr<Scheduler> scheduler, - net::NetworkQualityEstimator::NetworkQualityProvider* - network_quality_estimator, + network::NetworkQualityTracker* network_quality_tracker, std::unique_ptr<OfflinePagesUkmReporter> ukm_reporter) : is_low_end_device_(base::SysInfo::IsLowEndDevice()), state_(RequestCoordinatorState::IDLE), @@ -241,7 +241,7 @@ queue_(std::move(queue)), scheduler_(std::move(scheduler)), policy_controller_(new ClientPolicyController()), - network_quality_estimator_(network_quality_estimator), + network_quality_tracker_(network_quality_tracker), ukm_reporter_(std::move(ukm_reporter)), network_quality_at_request_start_(net::EFFECTIVE_CONNECTION_TYPE_UNKNOWN), active_request_id_(0), @@ -251,6 +251,7 @@ pending_state_updater_(this), weak_ptr_factory_(this) { DCHECK(policy_ != nullptr); + DCHECK(network_quality_tracker_); std::unique_ptr<CleanupTaskFactory> cleanup_factory( new CleanupTaskFactory(policy_.get(), this, &event_logger_)); queue_->SetCleanupFactory(std::move(cleanup_factory)); @@ -305,11 +306,10 @@ save_page_later_params.availability)); // Record the network quality when this request is made. - if (network_quality_estimator_) { - RecordSavePageLaterNetworkQuality( - save_page_later_params.client_id, - network_quality_estimator_->GetEffectiveConnectionType()); - } + + RecordSavePageLaterNetworkQuality( + save_page_later_params.client_id, + network_quality_tracker_->GetEffectiveConnectionType()); // Record UKM for this page offlining attempt. if (ukm_reporter_) { @@ -459,12 +459,10 @@ RequestNotifier::BackgroundSavePageResult::USER_CANCELED)); // Record the network quality when this request is removed. - if (network_quality_estimator_) { - UMA_HISTOGRAM_ENUMERATION( - "OfflinePages.Background.EffectiveConnectionType.RemoveRequests", - network_quality_estimator_->GetEffectiveConnectionType(), - net::EFFECTIVE_CONNECTION_TYPE_LAST); - } + UMA_HISTOGRAM_ENUMERATION( + "OfflinePages.Background.EffectiveConnectionType.RemoveRequests", + network_quality_tracker_->GetEffectiveConnectionType(), + net::EFFECTIVE_CONNECTION_TYPE_LAST); if (canceled) TryNextRequest(!kStartOfProcessing); @@ -488,12 +486,10 @@ weak_ptr_factory_.GetWeakPtr())); // Record the network quality when this request is paused. - if (network_quality_estimator_) { - UMA_HISTOGRAM_ENUMERATION( - "OfflinePages.Background.EffectiveConnectionType.PauseRequests", - network_quality_estimator_->GetEffectiveConnectionType(), - net::EFFECTIVE_CONNECTION_TYPE_LAST); - } + UMA_HISTOGRAM_ENUMERATION( + "OfflinePages.Background.EffectiveConnectionType.PauseRequests", + network_quality_tracker_->GetEffectiveConnectionType(), + net::EFFECTIVE_CONNECTION_TYPE_LAST); if (canceled) TryNextRequest(!kStartOfProcessing); @@ -509,12 +505,10 @@ weak_ptr_factory_.GetWeakPtr())); // Record the network quality when this request is resumed. - if (network_quality_estimator_) { - UMA_HISTOGRAM_ENUMERATION( - "OfflinePages.Background.EffectiveConnectionType.ResumeRequests", - network_quality_estimator_->GetEffectiveConnectionType(), - net::EFFECTIVE_CONNECTION_TYPE_LAST); - } + UMA_HISTOGRAM_ENUMERATION( + "OfflinePages.Background.EffectiveConnectionType.ResumeRequests", + network_quality_tracker_->GetEffectiveConnectionType(), + net::EFFECTIVE_CONNECTION_TYPE_LAST); // Schedule a task, in case there is not one scheduled. ScheduleAsNeeded(); @@ -963,7 +957,7 @@ active_request_id_ = request_id; network_quality_at_request_start_ = - network_quality_estimator_->GetEffectiveConnectionType(); + network_quality_tracker_->GetEffectiveConnectionType(); // Start the load and save process in the offliner (Async). if (offliner_->LoadAndSave( @@ -1199,7 +1193,6 @@ } void RequestCoordinator::Shutdown() { - network_quality_estimator_ = nullptr; } } // namespace offline_pages
diff --git a/components/offline_pages/core/background/request_coordinator.h b/components/offline_pages/core/background/request_coordinator.h index 938abf2..bd951b519 100644 --- a/components/offline_pages/core/background/request_coordinator.h +++ b/components/offline_pages/core/background/request_coordinator.h
@@ -29,6 +29,10 @@ #include "net/nqe/network_quality_estimator.h" #include "url/gurl.h" +namespace network { +class NetworkQualityTracker; +} + namespace offline_pages { struct ClientId; @@ -116,8 +120,7 @@ std::unique_ptr<Offliner> offliner, std::unique_ptr<RequestQueue> queue, std::unique_ptr<Scheduler> scheduler, - net::NetworkQualityEstimator::NetworkQualityProvider* - network_quality_estimator, + network::NetworkQualityTracker* network_quality_tracker, std::unique_ptr<OfflinePagesUkmReporter> ukm_reporter); ~RequestCoordinator() override; @@ -461,9 +464,9 @@ std::unique_ptr<Scheduler> scheduler_; // Controller of client policies. Owned. std::unique_ptr<ClientPolicyController> policy_controller_; - // Unowned pointer to the Network Quality Estimator. - net::NetworkQualityEstimator::NetworkQualityProvider* - network_quality_estimator_; + // Unowned pointer. Guaranteed to be non-null during the lifetime of |this|. + // Must be accessed only on the UI thread. + network::NetworkQualityTracker* network_quality_tracker_; // Object that can record Url Keyed Metrics (UKM). std::unique_ptr<OfflinePagesUkmReporter> ukm_reporter_; net::EffectiveConnectionType network_quality_at_request_start_;
diff --git a/components/offline_pages/core/background/request_coordinator_stub_taco.cc b/components/offline_pages/core/background/request_coordinator_stub_taco.cc index 3e90426..c468d4a 100644 --- a/components/offline_pages/core/background/request_coordinator_stub_taco.cc +++ b/components/offline_pages/core/background/request_coordinator_stub_taco.cc
@@ -4,7 +4,6 @@ #include "components/offline_pages/core/background/request_coordinator_stub_taco.h" -#include "components/offline_pages/core/background/network_quality_provider_stub.h" #include "components/offline_pages/core/background/offliner_stub.h" #include "components/offline_pages/core/background/request_queue.h" #include "components/offline_pages/core/background/request_queue_in_memory_store.h" @@ -12,6 +11,7 @@ #include "components/offline_pages/core/background/scheduler.h" #include "components/offline_pages/core/background/scheduler_stub.h" #include "components/offline_pages/core/offline_pages_ukm_reporter_stub.h" +#include "services/network/test/test_network_quality_tracker.h" namespace offline_pages { @@ -21,7 +21,8 @@ std::make_unique<RequestQueueInMemoryStore>()); offliner_ = std::make_unique<OfflinerStub>(); scheduler_ = std::make_unique<SchedulerStub>(); - network_quality_provider_ = std::make_unique<NetworkQualityProviderStub>(); + network_quality_tracker_ = + std::make_unique<network::TestNetworkQualityTracker>(); ukm_reporter_ = std::make_unique<OfflinePagesUkmReporterStub>(); } @@ -61,10 +62,9 @@ } void RequestCoordinatorStubTaco::SetNetworkQualityProvider( - std::unique_ptr<net::NetworkQualityEstimator::NetworkQualityProvider> - network_quality_provider) { + std::unique_ptr<network::NetworkQualityTracker> network_quality_tracker) { CHECK(!request_coordinator_); - network_quality_provider_ = std::move(network_quality_provider); + network_quality_tracker_ = std::move(network_quality_tracker); } void RequestCoordinatorStubTaco::SetOfflinePagesUkmReporter( @@ -75,7 +75,7 @@ void RequestCoordinatorStubTaco::CreateRequestCoordinator() { request_coordinator_ = std::make_unique<RequestCoordinator>( std::move(policy_), std::move(offliner_), std::move(queue_), - std::move(scheduler_), network_quality_provider_.get(), + std::move(scheduler_), network_quality_tracker_.get(), std::move(ukm_reporter_)); }
diff --git a/components/offline_pages/core/background/request_coordinator_stub_taco.h b/components/offline_pages/core/background/request_coordinator_stub_taco.h index 14f23d5..d99d16a01 100644 --- a/components/offline_pages/core/background/request_coordinator_stub_taco.h +++ b/components/offline_pages/core/background/request_coordinator_stub_taco.h
@@ -13,7 +13,10 @@ #include "components/offline_pages/core/background/request_queue.h" #include "components/offline_pages/core/background/request_queue_store.h" #include "components/offline_pages/core/background/scheduler.h" -#include "net/nqe/network_quality_estimator.h" + +namespace network { +class NetworkQualityTracker; +} namespace offline_pages { @@ -38,8 +41,7 @@ void SetOffliner(std::unique_ptr<Offliner> offliner); void SetScheduler(std::unique_ptr<Scheduler> scheduler); void SetNetworkQualityProvider( - std::unique_ptr<net::NetworkQualityEstimator::NetworkQualityProvider> - network_quality_provider); + std::unique_ptr<network::NetworkQualityTracker> network_quality_tracker); void SetOfflinePagesUkmReporter( std::unique_ptr<OfflinePagesUkmReporter> ukm_reporter); @@ -61,8 +63,7 @@ std::unique_ptr<RequestQueue> queue_; std::unique_ptr<Offliner> offliner_; std::unique_ptr<Scheduler> scheduler_; - std::unique_ptr<net::NetworkQualityEstimator::NetworkQualityProvider> - network_quality_provider_; + std::unique_ptr<network::NetworkQualityTracker> network_quality_tracker_; std::unique_ptr<OfflinePagesUkmReporter> ukm_reporter_; std::unique_ptr<RequestCoordinator> request_coordinator_;
diff --git a/components/offline_pages/core/background/request_coordinator_unittest.cc b/components/offline_pages/core/background/request_coordinator_unittest.cc index cf16cb620..0002b5e 100644 --- a/components/offline_pages/core/background/request_coordinator_unittest.cc +++ b/components/offline_pages/core/background/request_coordinator_unittest.cc
@@ -22,7 +22,6 @@ #include "base/time/time.h" #include "components/offline_items_collection/core/pending_state.h" #include "components/offline_pages/core/background/device_conditions.h" -#include "components/offline_pages/core/background/network_quality_provider_stub.h" #include "components/offline_pages/core/background/offliner.h" #include "components/offline_pages/core/background/offliner_policy.h" #include "components/offline_pages/core/background/offliner_stub.h" @@ -33,6 +32,7 @@ #include "components/offline_pages/core/background/scheduler.h" #include "components/offline_pages/core/background/scheduler_stub.h" #include "components/offline_pages/core/offline_page_feature.h" +#include "services/network/test/test_network_quality_tracker.h" #include "testing/gtest/include/gtest/gtest.h" namespace offline_pages { @@ -198,7 +198,7 @@ } void SetEffectiveConnectionTypeForTest(net::EffectiveConnectionType type) { - network_quality_provider_->SetEffectiveConnectionTypeForTest(type); + network_quality_tracker_->ReportEffectiveConnectionTypeForTesting(type); } void SetNetworkConnected(bool connected) { @@ -344,7 +344,7 @@ std::vector<std::unique_ptr<SavePageRequest>> last_requests_; scoped_refptr<base::TestMockTimeTaskRunner> task_runner_; base::ThreadTaskRunnerHandle task_runner_handle_; - NetworkQualityProviderStub* network_quality_provider_; + network::NetworkQualityTracker* network_quality_tracker_; std::unique_ptr<RequestCoordinatorStubTaco> coordinator_taco_; OfflinerStub* offliner_; base::WaitableEvent waiter_; @@ -384,12 +384,12 @@ offliner_ = offliner.get(); coordinator_taco_->SetOffliner(std::move(offliner)); - std::unique_ptr<NetworkQualityProviderStub> network_quality_provider = - std::make_unique<NetworkQualityProviderStub>(); + std::unique_ptr<network::NetworkQualityTracker> test_network_quality_tracker( + std::make_unique<network::TestNetworkQualityTracker>()); // Save raw pointer for use by the tests. - network_quality_provider_ = network_quality_provider.get(); + network_quality_tracker_ = test_network_quality_tracker.get(); coordinator_taco_->SetNetworkQualityProvider( - std::move(network_quality_provider)); + std::move(test_network_quality_tracker)); coordinator_taco_->CreateRequestCoordinator();
diff --git a/components/offline_pages/core/prefetch/BUILD.gn b/components/offline_pages/core/prefetch/BUILD.gn index b0a9af5..00f782d7 100644 --- a/components/offline_pages/core/prefetch/BUILD.gn +++ b/components/offline_pages/core/prefetch/BUILD.gn
@@ -88,6 +88,7 @@ "store/prefetch_store_utils.h", "suggested_articles_observer.cc", "suggested_articles_observer.h", + "suggestions_provider.h", "thumbnail_fetcher.h", ]
diff --git a/components/offline_pages/core/prefetch/prefetch_service.h b/components/offline_pages/core/prefetch/prefetch_service.h index d9561d5..e07ef69 100644 --- a/components/offline_pages/core/prefetch/prefetch_service.h +++ b/components/offline_pages/core/prefetch/prefetch_service.h
@@ -7,6 +7,8 @@ #include "components/keyed_service/core/keyed_service.h" +class GURL; + namespace ntp_snippets { class ContentSuggestionsService; } @@ -24,26 +26,57 @@ class PrefetchNetworkRequestFactory; class PrefetchStore; class SuggestedArticlesObserver; +class SuggestionsProvider; class ThumbnailFetcher; +// TODO(https://crbug.com/874293): This class is midway through a refactoring so +// it might look as it offers an inconsistent API. +// +// External doc (will remain here): +// Main entry point for the Offline Prefetch feature for external users. +// +// Internal doc (to be eventually moved out of here): // Main class and entry point for the Offline Pages Prefetching feature, that // controls the lifetime of all major subcomponents of the prefetching system. +// Setup and creation of concrete instances must be lightweight. All heavy work +// will be delayed to be done on-demand only. class PrefetchService : public KeyedService { public: ~PrefetchService() override = default; - virtual void SetContentSuggestionsService( - ntp_snippets::ContentSuggestionsService* content_suggestions) {} + // Externally used functions. They will remain part of this class. - // Subobjects that are created and owned by this service. Creation should be - // lightweight, all heavy work must be done on-demand only. + // Sets the SuggestionsProvider instance. Should be called at startup time and + // before any other suggestion related calls are made. + virtual void SetContentSuggestionsService( + ntp_snippets::ContentSuggestionsService* content_suggestions) = 0; + + // Sets the SuggestionsProvider instance. Should be called at startup time and + // before any other suggestion related calls are made. + virtual void SetSuggestionProvider( + SuggestionsProvider* suggestions_provider) = 0; + + // Notifies that the list of suggestions has changed and contains fresh + // content. This should be called any time new suggestions are fetched. + virtual void NewSuggestionsAvailable() = 0; + + // Signals that a specific suggestion was removed due to user action (i.e. + // user swiped out the item). This will cause the full removal of the + // suggestion from the Prefetching pipeline and/or the Offline Pages database. + virtual void RemoveSuggestion(GURL url) = 0; + + virtual PrefetchGCMHandler* GetPrefetchGCMHandler() = 0; + + // Internal usage only functions. They will eventually be moved out of this + // class. + + // Sub-components that are created and owned by this service. // The service manages lifetime, hookup and initialization of Prefetch // system that consists of multiple specialized objects, all vended by this - // service. + // class. virtual OfflineEventLogger* GetLogger() = 0; virtual OfflineMetricsCollector* GetOfflineMetricsCollector() = 0; virtual PrefetchDispatcher* GetPrefetchDispatcher() = 0; - virtual PrefetchGCMHandler* GetPrefetchGCMHandler() = 0; virtual PrefetchNetworkRequestFactory* GetPrefetchNetworkRequestFactory() = 0; virtual PrefetchDownloader* GetPrefetchDownloader() = 0; virtual PrefetchStore* GetPrefetchStore() = 0;
diff --git a/components/offline_pages/core/prefetch/prefetch_service_impl.cc b/components/offline_pages/core/prefetch/prefetch_service_impl.cc index c3850fe4..eb39fff 100644 --- a/components/offline_pages/core/prefetch/prefetch_service_impl.cc +++ b/components/offline_pages/core/prefetch/prefetch_service_impl.cc
@@ -7,6 +7,7 @@ #include <utility> #include "base/bind.h" +#include "base/logging.h" #include "components/offline_pages/core/client_id.h" #include "components/offline_pages/core/client_namespace_constants.h" #include "components/offline_pages/core/prefetch/offline_metrics_collector.h" @@ -19,6 +20,7 @@ #include "components/offline_pages/core/prefetch/prefetch_network_request_factory.h" #include "components/offline_pages/core/prefetch/store/prefetch_store.h" #include "components/offline_pages/core/prefetch/suggested_articles_observer.h" +#include "components/offline_pages/core/prefetch/suggestions_provider.h" #include "components/offline_pages/core/prefetch/thumbnail_fetcher.h" namespace offline_pages { @@ -69,6 +71,22 @@ thumbnail_fetcher_->SetContentSuggestionsService(content_suggestions); } +void PrefetchServiceImpl::SetSuggestionProvider( + SuggestionsProvider* suggestions_provider) { + // TODO(https://crbug.com/841516): to be implemented soon. + NOTIMPLEMENTED(); +} + +void PrefetchServiceImpl::NewSuggestionsAvailable() { + // TODO(https://crbug.com/841516): to be implemented soon. + NOTIMPLEMENTED(); +} + +void PrefetchServiceImpl::RemoveSuggestion(GURL url) { + // TODO(https://crbug.com/841516): to be implemented soon. + NOTIMPLEMENTED(); +} + OfflineMetricsCollector* PrefetchServiceImpl::GetOfflineMetricsCollector() { return offline_metrics_collector_.get(); }
diff --git a/components/offline_pages/core/prefetch/prefetch_service_impl.h b/components/offline_pages/core/prefetch/prefetch_service_impl.h index 12c0ce5c..7b4335b 100644 --- a/components/offline_pages/core/prefetch/prefetch_service_impl.h +++ b/components/offline_pages/core/prefetch/prefetch_service_impl.h
@@ -33,13 +33,18 @@ ~PrefetchServiceImpl() override; + // PrefetchService implementation: + // Externally used functions. void SetContentSuggestionsService( ntp_snippets::ContentSuggestionsService* content_suggestions) override; - - // PrefetchService implementation: + void SetSuggestionProvider( + SuggestionsProvider* suggestions_provider) override; + void NewSuggestionsAvailable() override; + void RemoveSuggestion(GURL url) override; + PrefetchGCMHandler* GetPrefetchGCMHandler() override; + // Internal usage only functions. OfflineMetricsCollector* GetOfflineMetricsCollector() override; PrefetchDispatcher* GetPrefetchDispatcher() override; - PrefetchGCMHandler* GetPrefetchGCMHandler() override; PrefetchNetworkRequestFactory* GetPrefetchNetworkRequestFactory() override; OfflinePageModel* GetOfflinePageModel() override; PrefetchStore* GetPrefetchStore() override;
diff --git a/components/offline_pages/core/prefetch/suggestions_provider.h b/components/offline_pages/core/prefetch/suggestions_provider.h new file mode 100644 index 0000000..3a94567 --- /dev/null +++ b/components/offline_pages/core/prefetch/suggestions_provider.h
@@ -0,0 +1,62 @@ +// 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 COMPONENTS_OFFLINE_PAGES_CORE_PREFETCH_SUGGESTIONS_PROVIDER_H_ +#define COMPONENTS_OFFLINE_PAGES_CORE_PREFETCH_SUGGESTIONS_PROVIDER_H_ + +#include <string> +#include <vector> + +#include "base/callback.h" +#include "url/gurl.h" + +namespace offline_pages { + +// Data struct for a suggestion of an article to be prefetched. +struct PrefetchSuggestion { + PrefetchSuggestion(); + ~PrefetchSuggestion(); + + // The URL of the suggested article. It acts as a unique key for the + // suggestion and may be de-duplicated if the same URL is suggested more than + // once. + GURL article_url; + // The title of the suggested article. + std::string article_title; + // The publisher name/web site the article is attributed to. + std::string article_attribution; + // A snippet of the article's contents. + std::string article_snippet; + // The URL to the thumbnail image representing the suggested article. + GURL thumbnail_url; + // The URL to the favicon image of the article's hosting web site. + GURL favicon_url; +}; + +// Interface implemented by the suggestions provider. +class SuggestionsProvider { + using SuggestionCallback = + base::OnceCallback<void(std::vector<PrefetchSuggestion>)>; + + // Request the list of current article suggestions, to be returned via the + // provided callback in descending priority order. Freshest articles are + // prefetched first based both on the order they are listed and on the + // timestamp at which the suggestion was last seen. + virtual void GetCurrentArticleSuggestions( + SuggestionCallback suggestions_callback) = 0; + + // Notifies that a non-empty list of prefetched articles was presented to the + // user. + virtual void ReportArticleListViewed() = 0; + + // Notifies that the a specific prefetched article was presented to the user. + // This will always provide the original suggested URL, not the potentially + // different downloaded one in case redirects take place during archive + // generation. + virtual void ReportArticleViewed(GURL article_url) = 0; +}; + +} // namespace offline_pages + +#endif // COMPONENTS_OFFLINE_PAGES_CORE_PREFETCH_SUGGESTIONS_PROVIDER_H_
diff --git a/components/policy/resources/policy_templates.json b/components/policy/resources/policy_templates.json index 1c1e1e7..60a5e87 100644 --- a/components/policy/resources/policy_templates.json +++ b/components/policy/resources/policy_templates.json
@@ -10155,11 +10155,11 @@ 'id': 437, 'caption': '''Allow <ph name="PRODUCT_NAME">Google Cast</ph> to connect to Cast devices on all IP addresses.''', 'tags': [], - 'desc': '''If this policy is set to true, <ph name="PRODUCT_NAME">Google Cast</ph> will connect to Cast devices on all IP addresses, not just RFC1918/RFC4913 private addresses. + 'desc': '''If this policy is set to true, <ph name="PRODUCT_NAME">Google Cast</ph> will connect to Cast devices on all IP addresses, not just RFC1918/RFC4193 private addresses. - If this policy is set to false, <ph name="PRODUCT_NAME">Google Cast</ph> will connect to Cast devices on RFC1918/RFC4913 private addresses only. + If this policy is set to false, <ph name="PRODUCT_NAME">Google Cast</ph> will connect to Cast devices on RFC1918/RFC4193 private addresses only. - If this policy is not set, <ph name="PRODUCT_NAME">Google Cast</ph> will connect to Cast devices on RFC1918/RFC4913 private addresses only, unless the CastAllowAllIPs feature is enabled. + If this policy is not set, <ph name="PRODUCT_NAME">Google Cast</ph> will connect to Cast devices on RFC1918/RFC4193 private addresses only, unless the CastAllowAllIPs feature is enabled. If the policy "EnableMediaRouter" is set to false, then this policy's value would have no effect.''' },
diff --git a/components/sync/base/invalidation_helper.cc b/components/sync/base/invalidation_helper.cc index bc7fcdc..128a17c 100644 --- a/components/sync/base/invalidation_helper.cc +++ b/components/sync/base/invalidation_helper.cc
@@ -23,10 +23,10 @@ ObjectIdSet ModelTypeSetToObjectIdSet(ModelTypeSet model_types) { ObjectIdSet ids; - for (ModelTypeSet::Iterator it = model_types.First(); it.Good(); it.Inc()) { + for (ModelType type : model_types) { invalidation::ObjectId model_type_as_id; - if (!RealModelTypeToObjectId(it.Get(), &model_type_as_id)) { - DLOG(WARNING) << "Invalid model type " << it.Get(); + if (!RealModelTypeToObjectId(type, &model_type_as_id)) { + DLOG(WARNING) << "Invalid model type " << type; continue; } ids.insert(model_type_as_id);
diff --git a/components/sync/base/sync_prefs.cc b/components/sync/base/sync_prefs.cc index cb39560..7b427ad 100644 --- a/components/sync/base/sync_prefs.cc +++ b/components/sync/base/sync_prefs.cc
@@ -115,9 +115,9 @@ // forces a configuration to explicitly enable them. GetPreferredTypes() will // ensure that any new implicit types are enabled when their pref group is, or // via KeepEverythingSynced. - for (ModelTypeSet::Iterator it = user_types.First(); it.Good(); it.Inc()) { - RegisterDataTypePreferredPref(registry, it.Get(), - AlwaysPreferredUserTypes().Has(it.Get())); + for (ModelType type : user_types) { + RegisterDataTypePreferredPref(registry, type, + AlwaysPreferredUserTypes().Has(type)); } registry->RegisterBooleanPref(prefs::kSyncManaged, false); @@ -276,10 +276,9 @@ } ModelTypeSet preferred_types; - for (ModelTypeSet::Iterator it = registered_types.First(); it.Good(); - it.Inc()) { - if (GetDataTypePreferred(it.Get())) { - preferred_types.Put(it.Get()); + for (ModelType type : registered_types) { + if (GetDataTypePreferred(type)) { + preferred_types.Put(type); } } return ResolvePrefGroups(registered_types, preferred_types, @@ -293,8 +292,8 @@ preferred_types = ResolvePrefGroups(registered_types, preferred_types, user_events_separate_pref_group); DCHECK(registered_types.HasAll(preferred_types)); - for (ModelTypeSet::Iterator i = registered_types.First(); i.Good(); i.Inc()) { - SetDataTypePreferred(i.Get(), preferred_types.Has(i.Get())); + for (ModelType type : registered_types) { + SetDataTypePreferred(type, preferred_types.Has(type)); } } @@ -544,15 +543,15 @@ const base::DictionaryValue* invalidation_dictionary = pref_service_->GetDictionary(prefs::kSyncInvalidationVersions); ModelTypeSet protocol_types = ProtocolTypes(); - for (auto iter = protocol_types.First(); iter.Good(); iter.Inc()) { - std::string key = ModelTypeToString(iter.Get()); + for (ModelType type : protocol_types) { + std::string key = ModelTypeToString(type); std::string version_str; if (!invalidation_dictionary->GetString(key, &version_str)) continue; int64_t version = 0; if (!base::StringToInt64(version_str, &version)) continue; - (*invalidation_versions)[iter.Get()] = version; + (*invalidation_versions)[type] = version; } }
diff --git a/components/sync/base/sync_prefs_unittest.cc b/components/sync/base/sync_prefs_unittest.cc index c4c92f0..1072ea14 100644 --- a/components/sync/base/sync_prefs_unittest.cc +++ b/components/sync/base/sync_prefs_unittest.cc
@@ -207,10 +207,9 @@ const ModelTypeSet user_types = UserTypes(); EXPECT_EQ(user_types, GetPreferredDataTypes(user_types)); const ModelTypeSet user_visible_types = UserSelectableTypes(); - for (ModelTypeSet::Iterator it = user_visible_types.First(); it.Good(); - it.Inc()) { + for (ModelType type : user_visible_types) { ModelTypeSet preferred_types; - preferred_types.Put(it.Get()); + preferred_types.Put(type); SetPreferredDataTypes(user_types, preferred_types); EXPECT_EQ(user_types, GetPreferredDataTypes(user_types)); } @@ -222,32 +221,31 @@ const ModelTypeSet user_types = UserTypes(); EXPECT_NE(user_types, GetPreferredDataTypes(user_types)); const ModelTypeSet user_visible_types = UserSelectableTypes(); - for (ModelTypeSet::Iterator it = user_visible_types.First(); it.Good(); - it.Inc()) { + for (ModelType type : user_visible_types) { ModelTypeSet preferred_types; - preferred_types.Put(it.Get()); + preferred_types.Put(type); ModelTypeSet expected_preferred_types(preferred_types); - if (it.Get() == AUTOFILL) { + if (type == AUTOFILL) { expected_preferred_types.Put(AUTOFILL_PROFILE); expected_preferred_types.Put(AUTOFILL_WALLET_DATA); expected_preferred_types.Put(AUTOFILL_WALLET_METADATA); } - if (it.Get() == PREFERENCES) { + if (type == PREFERENCES) { expected_preferred_types.Put(DICTIONARY); expected_preferred_types.Put(PRIORITY_PREFERENCES); expected_preferred_types.Put(SEARCH_ENGINES); } - if (it.Get() == APPS) { + if (type == APPS) { expected_preferred_types.Put(APP_LIST); expected_preferred_types.Put(APP_NOTIFICATIONS); expected_preferred_types.Put(APP_SETTINGS); expected_preferred_types.Put(ARC_PACKAGE); expected_preferred_types.Put(READING_LIST); } - if (it.Get() == EXTENSIONS) { + if (type == EXTENSIONS) { expected_preferred_types.Put(EXTENSION_SETTINGS); } - if (it.Get() == TYPED_URLS) { + if (type == TYPED_URLS) { expected_preferred_types.Put(HISTORY_DELETE_DIRECTIVES); expected_preferred_types.Put(SESSIONS); expected_preferred_types.Put(FAVICON_IMAGES); @@ -256,7 +254,7 @@ expected_preferred_types.Put(USER_EVENTS); } } - if (it.Get() == PROXY_TABS) { + if (type == PROXY_TABS) { expected_preferred_types.Put(SESSIONS); expected_preferred_types.Put(FAVICON_IMAGES); expected_preferred_types.Put(FAVICON_TRACKING);
diff --git a/components/sync/driver/data_type_manager_impl.cc b/components/sync/driver/data_type_manager_impl.cc index 8022e4c..bdc4776a 100644 --- a/components/sync/driver/data_type_manager_impl.cc +++ b/components/sync/driver/data_type_manager_impl.cc
@@ -31,10 +31,9 @@ DataTypeStatusTable::TypeErrorMap GenerateCryptoErrorsForTypes( ModelTypeSet encrypted_types) { DataTypeStatusTable::TypeErrorMap crypto_errors; - for (ModelTypeSet::Iterator iter = encrypted_types.First(); iter.Good(); - iter.Inc()) { - crypto_errors[iter.Get()] = - SyncError(FROM_HERE, SyncError::CRYPTO_ERROR, "", iter.Get()); + for (ModelType type : encrypted_types) { + crypto_errors[type] = + SyncError(FROM_HERE, SyncError::CRYPTO_ERROR, "", type); } return crypto_errors; } @@ -163,9 +162,8 @@ } void DataTypeManagerImpl::RegisterTypesWithBackend() { - for (auto type_iter = last_enabled_types_.First(); type_iter.Good(); - type_iter.Inc()) { - const auto& dtc_iter = controllers_->find(type_iter.Get()); + for (ModelType type : last_enabled_types_) { + const auto& dtc_iter = controllers_->find(type); if (dtc_iter == controllers_->end()) continue; DataTypeController* dtc = dtc_iter->second.get(); @@ -198,8 +196,8 @@ void DataTypeManagerImpl::SetDataTypesState(DataTypeConfigState state, ModelTypeSet types, DataTypeConfigStateMap* state_map) { - for (ModelTypeSet::Iterator it = types.First(); it.Good(); it.Inc()) { - (*state_map)[it.Get()] = state; + for (ModelType type : types) { + (*state_map)[type] = state; } } @@ -259,11 +257,10 @@ if (reason == CONFIGURE_REASON_RECONFIGURATION || reason == CONFIGURE_REASON_NEW_CLIENT || reason == CONFIGURE_REASON_NEWLY_ENABLED_DATA_TYPE) { - for (ModelTypeSet::Iterator iter = last_requested_types_.First(); - iter.Good(); iter.Inc()) { + for (ModelType type : last_requested_types_) { // TODO(wychen): enum uma should be strongly typed. crbug.com/661401 UMA_HISTOGRAM_ENUMERATION("Sync.ConfigureDataTypes", - ModelTypeToHistogramInt(iter.Get()), + ModelTypeToHistogramInt(type), static_cast<int>(MODEL_TYPE_COUNT)); } } @@ -354,24 +351,23 @@ void DataTypeManagerImpl::UpdateUnreadyTypeErrors( const ModelTypeSet& desired_types) { - for (ModelTypeSet::Iterator type = desired_types.First(); type.Good(); - type.Inc()) { - const auto& iter = controllers_->find(type.Get()); + for (ModelType type : desired_types) { + const auto& iter = controllers_->find(type); if (iter == controllers_->end()) continue; const DataTypeController* dtc = iter->second.get(); bool unready_status = - data_type_status_table_.GetUnreadyErrorTypes().Has(type.Get()); + data_type_status_table_.GetUnreadyErrorTypes().Has(type); if (dtc->ReadyForStart() != (unready_status == false)) { // Adjust data_type_status_table_ if unready state in it doesn't match // DataTypeController::ReadyForStart(). if (dtc->ReadyForStart()) { - data_type_status_table_.ResetUnreadyErrorFor(type.Get()); + data_type_status_table_.ResetUnreadyErrorFor(type); } else { SyncError error(FROM_HERE, SyncError::UNREADY_ERROR, - "Datatype not ready at config time.", type.Get()); + "Datatype not ready at config time.", type); std::map<ModelType, SyncError> errors; - errors[type.Get()] = error; + errors[type] = error; data_type_status_table_.UpdateFailedDataTypes(errors); } } @@ -428,11 +424,10 @@ if (!failed_configuration_types.Empty()) { DataTypeStatusTable::TypeErrorMap errors; - for (ModelTypeSet::Iterator iter = failed_configuration_types.First(); - iter.Good(); iter.Inc()) { + for (ModelType type : failed_configuration_types) { SyncError error(FROM_HERE, SyncError::DATATYPE_ERROR, - "Backend failed to download type.", iter.Get()); - errors[iter.Get()] = error; + "Backend failed to download type.", type); + errors[type] = error; } data_type_status_table_.UpdateFailedDataTypes(errors); needs_reconfigure_ = true;
diff --git a/components/sync/driver/data_type_manager_impl_unittest.cc b/components/sync/driver/data_type_manager_impl_unittest.cc index 7e90746..21ca0d2 100644 --- a/components/sync/driver/data_type_manager_impl_unittest.cc +++ b/components/sync/driver/data_type_manager_impl_unittest.cc
@@ -44,26 +44,21 @@ ModelTypeSet unready_errors, ModelTypeSet unrecoverable_errors) { DataTypeStatusTable::TypeErrorMap error_map; - for (ModelTypeSet::Iterator iter = crypto_errors.First(); iter.Good(); - iter.Inc()) { - error_map[iter.Get()] = SyncError(FROM_HERE, SyncError::CRYPTO_ERROR, - "crypto error expected", iter.Get()); + for (ModelType type : crypto_errors) { + error_map[type] = SyncError(FROM_HERE, SyncError::CRYPTO_ERROR, + "crypto error expected", type); } - for (ModelTypeSet::Iterator iter = association_errors.First(); iter.Good(); - iter.Inc()) { - error_map[iter.Get()] = SyncError(FROM_HERE, SyncError::DATATYPE_ERROR, - "association error expected", iter.Get()); + for (ModelType type : association_errors) { + error_map[type] = SyncError(FROM_HERE, SyncError::DATATYPE_ERROR, + "association error expected", type); } - for (ModelTypeSet::Iterator iter = unready_errors.First(); iter.Good(); - iter.Inc()) { - error_map[iter.Get()] = SyncError(FROM_HERE, SyncError::UNREADY_ERROR, - "unready error expected", iter.Get()); + for (ModelType type : unready_errors) { + error_map[type] = SyncError(FROM_HERE, SyncError::UNREADY_ERROR, + "unready error expected", type); } - for (ModelTypeSet::Iterator iter = unrecoverable_errors.First(); iter.Good(); - iter.Inc()) { - error_map[iter.Get()] = - SyncError(FROM_HERE, SyncError::UNRECOVERABLE_ERROR, - "unrecoverable error expected", iter.Get()); + for (ModelType type : unrecoverable_errors) { + error_map[type] = SyncError(FROM_HERE, SyncError::UNRECOVERABLE_ERROR, + "unrecoverable error expected", type); } DataTypeStatusTable status_table; status_table.UpdateFailedDataTypes(error_map);
diff --git a/components/sync/driver/data_type_status_table.cc b/components/sync/driver/data_type_status_table.cc index db38de5c..8b79c04 100644 --- a/components/sync/driver/data_type_status_table.cc +++ b/components/sync/driver/data_type_status_table.cc
@@ -75,9 +75,8 @@ void DataTypeStatusTable::ResetPersistenceErrorsFrom( ModelTypeSet purged_types) { - for (ModelTypeSet::Iterator iter = purged_types.First(); iter.Good(); - iter.Inc()) { - persistence_errors_.erase(iter.Get()); + for (ModelType type : purged_types) { + persistence_errors_.erase(type); } }
diff --git a/components/sync/driver/generic_change_processor_unittest.cc b/components/sync/driver/generic_change_processor_unittest.cc index 0ee8f1a..88896f3f 100644 --- a/components/sync/driver/generic_change_processor_unittest.cc +++ b/components/sync/driver/generic_change_processor_unittest.cc
@@ -71,8 +71,8 @@ sync_merge_result_.get()); ModelTypeSet types = ProtocolTypes(); - for (ModelTypeSet::Iterator iter = types.First(); iter.Good(); iter.Inc()) { - TestUserShare::CreateRoot(iter.Get(), test_user_share_->user_share()); + for (ModelType type : types) { + TestUserShare::CreateRoot(type, test_user_share_->user_share()); } test_user_share_->encryption_handler()->Init(); ConstructGenericChangeProcessor(type);
diff --git a/components/sync/driver/glue/sync_backend_host_core.cc b/components/sync/driver/glue/sync_backend_host_core.cc index dbfa6e9..056cff5 100644 --- a/components/sync/driver/glue/sync_backend_host_core.cc +++ b/components/sync/driver/glue/sync_backend_host_core.cc
@@ -148,8 +148,8 @@ ModelTypeConnector* model_type_connector = sync_manager_->GetModelTypeConnector(); ModelTypeSet control_types = ControlTypes(); - for (auto it = control_types.First(); it.Good(); it.Inc()) { - model_type_connector->RegisterDirectoryType(it.Get(), GROUP_PASSIVE); + for (ModelType type : control_types) { + model_type_connector->RegisterDirectoryType(type, GROUP_PASSIVE); } ModelSafeRoutingInfo routing_info;
diff --git a/components/sync/driver/model_association_manager.cc b/components/sync/driver/model_association_manager.cc index b37569e1..99bb800 100644 --- a/components/sync/driver/model_association_manager.cc +++ b/components/sync/driver/model_association_manager.cc
@@ -114,9 +114,9 @@ // Only keep types that have controllers. desired_types_.Clear(); - for (ModelTypeSet::Iterator it = desired_types.First(); it.Good(); it.Inc()) { - if (controllers_->find(it.Get()) != controllers_->end()) - desired_types_.Put(it.Get()); + for (ModelType type : desired_types) { + if (controllers_->find(type) != controllers_->end()) + desired_types_.Put(type); } DVLOG(1) << "ModelAssociationManager: Initializing for " @@ -174,8 +174,8 @@ } void ModelAssociationManager::LoadEnabledTypes() { - for (auto it = desired_types_.First(); it.Good(); it.Inc()) { - auto dtc_iter = controllers_->find(it.Get()); + for (ModelType type : desired_types_) { + auto dtc_iter = controllers_->find(type); DCHECK(dtc_iter != controllers_->end()); DataTypeController* dtc = dtc_iter->second.get(); if (dtc->state() == DataTypeController::NOT_RUNNING) {
diff --git a/components/sync/engine/engine_components_factory_impl.cc b/components/sync/engine/engine_components_factory_impl.cc index 41d73c9..7fcbb5d 100644 --- a/components/sync/engine/engine_components_factory_impl.cc +++ b/components/sync/engine/engine_components_factory_impl.cc
@@ -50,9 +50,8 @@ // Only protocol types can have their delay customized. ModelTypeSet protocol_types = syncer::ProtocolTypes(); std::map<ModelType, base::TimeDelta> nudge_delays; - for (ModelTypeSet::Iterator it = protocol_types.First(); it.Good(); - it.Inc()) { - nudge_delays[it.Get()] = + for (ModelType type : protocol_types) { + nudge_delays[type] = TimeDelta::FromMilliseconds(kShortNudgeDelayDurationMS); } scheduler->OnReceivedCustomNudgeDelays(nudge_delays);
diff --git a/components/sync/engine/fake_sync_manager.cc b/components/sync/engine/fake_sync_manager.cc index f365c53..8725954 100644 --- a/components/sync/engine/fake_sync_manager.cc +++ b/components/sync/engine/fake_sync_manager.cc
@@ -77,9 +77,8 @@ test_user_share_.SetUp(); UserShare* share = test_user_share_.user_share(); - for (ModelTypeSet::Iterator it = initial_sync_ended_types_.First(); it.Good(); - it.Inc()) { - TestUserShare::CreateRoot(it.Get(), share); + for (ModelType type : initial_sync_ended_types_) { + TestUserShare::CreateRoot(type, share); } for (auto& observer : observers_) { @@ -102,10 +101,9 @@ void FakeSyncManager::PurgePartiallySyncedTypes() { ModelTypeSet partial_types; - for (ModelTypeSet::Iterator i = progress_marker_types_.First(); i.Good(); - i.Inc()) { - if (!initial_sync_ended_types_.Has(i.Get())) - partial_types.Put(i.Get()); + for (ModelType type : progress_marker_types_) { + if (!initial_sync_ended_types_.Has(type)) + partial_types.Put(type); } progress_marker_types_.RemoveAll(partial_types); purged_types_.PutAll(partial_types); @@ -158,10 +156,10 @@ // Update our fake directory by clearing and fake-downloading as necessary. UserShare* share = GetUserShare(); - for (ModelTypeSet::Iterator it = success_types.First(); it.Good(); it.Inc()) { + for (ModelType type : success_types) { // We must be careful to not create the same root node twice. - if (!initial_sync_ended_types_.Has(it.Get())) { - TestUserShare::CreateRoot(it.Get(), share); + if (!initial_sync_ended_types_.Has(type)) { + TestUserShare::CreateRoot(type, share); } }
diff --git a/components/sync/engine/sync_backend_registrar.cc b/components/sync/engine/sync_backend_registrar.cc index f8086aa..1d68cac 100644 --- a/components/sync/engine/sync_backend_registrar.cc +++ b/components/sync/engine/sync_backend_registrar.cc
@@ -52,12 +52,12 @@ // Set our initial state to reflect the current status of the sync directory. // This will ensure that our calculations in ConfigureDataTypes() will always // return correct results. - for (ModelTypeSet::Iterator it = initial_types.First(); it.Good(); it.Inc()) { + for (ModelType type : initial_types) { // If this type is also registered as NonBlocking, assume that it shouldn't // be registered as passive. The NonBlocking path will eventually take care // of adding to routing_info_ later on. - if (!non_blocking_types_.Has(it.Get())) { - routing_info_[it.Get()] = GROUP_PASSIVE; + if (!non_blocking_types_.Has(type)) { + routing_info_[type] = GROUP_PASSIVE; } } @@ -108,18 +108,16 @@ base::AutoLock lock(lock_); ModelTypeSet newly_added_types; - for (ModelTypeSet::Iterator it = filtered_types_to_add.First(); it.Good(); - it.Inc()) { + for (ModelType type : filtered_types_to_add) { // Add a newly specified data type corresponding initial group into the // routing_info, if it does not already exist. - if (routing_info_.count(it.Get()) == 0) { - routing_info_[it.Get()] = GetInitialGroupForType(it.Get()); - newly_added_types.Put(it.Get()); + if (routing_info_.count(type) == 0) { + routing_info_[type] = GetInitialGroupForType(type); + newly_added_types.Put(type); } } - for (ModelTypeSet::Iterator it = types_to_remove.First(); it.Good(); - it.Inc()) { - routing_info_.erase(it.Get()); + for (ModelType type : types_to_remove) { + routing_info_.erase(type); } // TODO(akalin): Use SVLOG/SLOG if we add any more logging.
diff --git a/components/sync/engine_impl/apply_control_data_updates.cc b/components/sync/engine_impl/apply_control_data_updates.cc index 553d765..1e14dee 100644 --- a/components/sync/engine_impl/apply_control_data_updates.cc +++ b/components/sync/engine_impl/apply_control_data_updates.cc
@@ -34,9 +34,7 @@ // TODO(sync): if at some point we support control datatypes with actual // hierarchies we'll need to revisit this logic. ModelTypeSet control_types = ControlTypes(); - for (ModelTypeSet::Iterator iter = control_types.First(); iter.Good(); - iter.Inc()) { - ModelType type = iter.Get(); + for (ModelType type : control_types) { syncable::MutableEntry entry(&trans, syncable::GET_TYPE_ROOT, type); if (!entry.good()) continue;
diff --git a/components/sync/engine_impl/commit_processor.cc b/components/sync/engine_impl/commit_processor.cc index 05f9b02..f81ed6e 100644 --- a/components/sync/engine_impl/commit_processor.cc +++ b/components/sync/engine_impl/commit_processor.cc
@@ -28,12 +28,11 @@ bool cookie_jar_empty, Commit::ContributionMap* contributions) { size_t num_entries = 0; - for (ModelTypeSet::Iterator it = commit_types.First(); it.Good(); it.Inc()) { - CommitContributorMap::iterator cm_it = - commit_contributor_map_->find(it.Get()); + for (ModelType type : commit_types) { + CommitContributorMap::iterator cm_it = commit_contributor_map_->find(type); if (cm_it == commit_contributor_map_->end()) { - DLOG(ERROR) << "Could not find requested type " - << ModelTypeToString(it.Get()) << " in contributor map."; + DLOG(ERROR) << "Could not find requested type " << ModelTypeToString(type) + << " in contributor map."; continue; } size_t spaces_remaining = max_entries - num_entries; @@ -41,9 +40,9 @@ cm_it->second->GetContribution(spaces_remaining); if (contribution) { num_entries += contribution->GetNumEntries(); - contributions->insert(std::make_pair(it.Get(), std::move(contribution))); + contributions->insert(std::make_pair(type, std::move(contribution))); - if (it.Get() == SESSIONS) { + if (type == SESSIONS) { UMA_HISTOGRAM_BOOLEAN("Sync.CookieJarMatchOnNavigation", !cookie_jar_mismatch); if (cookie_jar_mismatch) {
diff --git a/components/sync/engine_impl/commit_util.cc b/components/sync/engine_impl/commit_util.cc index 30cfb56..5e456ad6 100644 --- a/components/sync/engine_impl/commit_util.cc +++ b/components/sync/engine_impl/commit_util.cc
@@ -62,10 +62,10 @@ bool cookie_jar_mismatch, sync_pb::CommitMessage* message) { sync_pb::ClientConfigParams* config_params = message->mutable_config_params(); - for (ModelTypeSet::Iterator it = enabled_types.First(); it.Good(); it.Inc()) { - if (ProxyTypes().Has(it.Get())) + for (ModelType type : enabled_types) { + if (ProxyTypes().Has(type)) continue; - int field_number = GetSpecificsFieldNumberFromModelType(it.Get()); + int field_number = GetSpecificsFieldNumberFromModelType(type); config_params->mutable_enabled_type_ids()->Add(field_number); } config_params->set_tabs_datatype_enabled(enabled_types.Has(PROXY_TABS));
diff --git a/components/sync/engine_impl/cycle/nudge_tracker.cc b/components/sync/engine_impl/cycle/nudge_tracker.cc index 8b327e6..8720ec4 100644 --- a/components/sync/engine_impl/cycle/nudge_tracker.cc +++ b/components/sync/engine_impl/cycle/nudge_tracker.cc
@@ -53,10 +53,9 @@ base::TimeDelta::FromMilliseconds(kSyncSchedulerDelayMilliseconds)) { ModelTypeSet protocol_types = ProtocolTypes(); // Default initialize all the type trackers. - for (ModelTypeSet::Iterator it = protocol_types.First(); it.Good(); - it.Inc()) { + for (ModelType type : protocol_types) { type_trackers_.insert( - std::make_pair(it.Get(), std::make_unique<DataTypeTracker>())); + std::make_pair(type, std::make_unique<DataTypeTracker>())); } } @@ -120,18 +119,15 @@ // Start with the longest delay. base::TimeDelta delay = base::TimeDelta::FromSeconds(kDefaultShortPollIntervalSeconds); - for (ModelTypeSet::Iterator type_it = types.First(); type_it.Good(); - type_it.Inc()) { - TypeTrackerMap::const_iterator tracker_it = - type_trackers_.find(type_it.Get()); + for (ModelType type : types) { + TypeTrackerMap::const_iterator tracker_it = type_trackers_.find(type); DCHECK(tracker_it != type_trackers_.end()); // Only if the type tracker has a valid delay (non-zero) that is shorter // than the calculated delay do we update the calculated delay. base::TimeDelta type_delay = tracker_it->second->RecordLocalChange(); if (type_delay.is_zero()) { - type_delay = - GetDefaultDelayForType(type_it.Get(), minimum_local_nudge_delay_); + type_delay = GetDefaultDelayForType(type, minimum_local_nudge_delay_); } if (type_delay < delay) delay = type_delay; @@ -140,9 +136,9 @@ } base::TimeDelta NudgeTracker::RecordLocalRefreshRequest(ModelTypeSet types) { - for (ModelTypeSet::Iterator it = types.First(); it.Good(); it.Inc()) { - TypeTrackerMap::const_iterator tracker_it = type_trackers_.find(it.Get()); - DCHECK(tracker_it != type_trackers_.end()) << ModelTypeToString(it.Get()); + for (ModelType type : types) { + TypeTrackerMap::const_iterator tracker_it = type_trackers_.find(type); + DCHECK(tracker_it != type_trackers_.end()) << ModelTypeToString(type); tracker_it->second->RecordLocalRefreshRequest(); } return local_refresh_nudge_delay_; @@ -182,8 +178,8 @@ void NudgeTracker::SetTypesThrottledUntil(ModelTypeSet types, base::TimeDelta length, base::TimeTicks now) { - for (ModelTypeSet::Iterator it = types.First(); it.Good(); it.Inc()) { - TypeTrackerMap::const_iterator tracker_it = type_trackers_.find(it.Get()); + for (ModelType type : types) { + TypeTrackerMap::const_iterator tracker_it = type_trackers_.find(type); tracker_it->second->ThrottleType(length, now); } }
diff --git a/components/sync/engine_impl/cycle/nudge_tracker_unittest.cc b/components/sync/engine_impl/cycle/nudge_tracker_unittest.cc index 50c8eeea..112f5358 100644 --- a/components/sync/engine_impl/cycle/nudge_tracker_unittest.cc +++ b/components/sync/engine_impl/cycle/nudge_tracker_unittest.cc
@@ -853,16 +853,14 @@ std::map<ModelType, base::TimeDelta> delay_map; ModelTypeSet protocol_types = ProtocolTypes(); - for (ModelTypeSet::Iterator iter = protocol_types.First(); iter.Good(); - iter.Inc()) { - delay_map[iter.Get()] = base::TimeDelta(); + for (ModelType type : protocol_types) { + delay_map[type] = base::TimeDelta(); } nudge_tracker_.OnReceivedCustomNudgeDelays(delay_map); // All types should still have a nudge greater than or equal to the minimum. - for (ModelTypeSet::Iterator iter = protocol_types.First(); iter.Good(); - iter.Inc()) { - EXPECT_GE(nudge_tracker_.RecordLocalChange(ModelTypeSet(iter.Get())), + for (ModelType type : protocol_types) { + EXPECT_GE(nudge_tracker_.RecordLocalChange(ModelTypeSet(type)), base::TimeDelta::FromMilliseconds(500)); } }
diff --git a/components/sync/engine_impl/debug_info_event_listener.cc b/components/sync/engine_impl/debug_info_event_listener.cc index 237798e..067781b 100644 --- a/components/sync/engine_impl/debug_info_event_listener.cc +++ b/components/sync/engine_impl/debug_info_event_listener.cc
@@ -214,20 +214,16 @@ configuration_stats[i] .association_wait_time_for_high_priority.InMicroseconds()); - for (ModelTypeSet::Iterator it = - configuration_stats[i] - .high_priority_types_configured_before.First(); - it.Good(); it.Inc()) { + for (ModelType type : + configuration_stats[i].high_priority_types_configured_before) { datatype_stats->add_high_priority_type_configured_before( - GetSpecificsFieldNumberFromModelType(it.Get())); + GetSpecificsFieldNumberFromModelType(type)); } - for (ModelTypeSet::Iterator it = - configuration_stats[i] - .same_priority_types_configured_before.First(); - it.Good(); it.Inc()) { + for (ModelType type : + configuration_stats[i].same_priority_types_configured_before) { datatype_stats->add_same_priority_type_configured_before( - GetSpecificsFieldNumberFromModelType(it.Get())); + GetSpecificsFieldNumberFromModelType(type)); } AddEventToQueue(association_event);
diff --git a/components/sync/engine_impl/get_updates_processor.cc b/components/sync/engine_impl/get_updates_processor.cc index 5ac5d88..08c074e7 100644 --- a/components/sync/engine_impl/get_updates_processor.cc +++ b/components/sync/engine_impl/get_updates_processor.cc
@@ -62,9 +62,8 @@ ModelTypeSet requested_types, TypeSyncEntityMap* updates_by_type) { int update_count = gu_response.entries().size(); - for (ModelTypeSet::Iterator it = requested_types.First(); it.Good(); - it.Inc()) { - updates_by_type->insert(std::make_pair(it.Get(), SyncEntityList())); + for (ModelType type : requested_types) { + updates_by_type->insert(std::make_pair(type, SyncEntityList())); } for (int i = 0; i < update_count; ++i) { const sync_pb::SyncEntity& update = gu_response.entries(i); @@ -184,10 +183,10 @@ sync_pb::ClientToServerMessage* message) { sync_pb::GetUpdatesMessage* get_updates = message->mutable_get_updates(); - for (ModelTypeSet::Iterator it = gu_types.First(); it.Good(); it.Inc()) { - UpdateHandlerMap::iterator handler_it = update_handler_map_->find(it.Get()); + for (ModelType type : gu_types) { + UpdateHandlerMap::iterator handler_it = update_handler_map_->find(type); DCHECK(handler_it != update_handler_map_->end()) - << "Failed to look up handler for " << ModelTypeToString(it.Get()); + << "Failed to look up handler for " << ModelTypeToString(type); sync_pb::DataTypeProgressMarker* progress_marker = get_updates->add_from_progress_marker(); handler_it->second->GetDownloadProgress(progress_marker);
diff --git a/components/sync/engine_impl/get_updates_processor_unittest.cc b/components/sync/engine_impl/get_updates_processor_unittest.cc index b461126..bd9a07ab 100644 --- a/components/sync/engine_impl/get_updates_processor_unittest.cc +++ b/components/sync/engine_impl/get_updates_processor_unittest.cc
@@ -57,13 +57,13 @@ void InitFakeUpdateResponse(sync_pb::GetUpdatesResponse* response) { ModelTypeSet types = enabled_types(); - for (ModelTypeSet::Iterator it = types.First(); it.Good(); it.Inc()) { + for (ModelType type : types) { sync_pb::DataTypeProgressMarker* marker = response->add_new_progress_marker(); - marker->set_data_type_id(GetSpecificsFieldNumberFromModelType(it.Get())); + marker->set_data_type_id(GetSpecificsFieldNumberFromModelType(type)); marker->set_token("foobarbaz"); sync_pb::DataTypeContext* context = response->add_context_mutations(); - context->set_data_type_id(GetSpecificsFieldNumberFromModelType(it.Get())); + context->set_data_type_id(GetSpecificsFieldNumberFromModelType(type)); context->set_version(1); context->set_context("context"); }
diff --git a/components/sync/engine_impl/loopback_server/loopback_server.cc b/components/sync/engine_impl/loopback_server/loopback_server.cc index 5d049175..1b0de9f 100644 --- a/components/sync/engine_impl/loopback_server/loopback_server.cc +++ b/components/sync/engine_impl/loopback_server/loopback_server.cc
@@ -178,10 +178,7 @@ ModelTypeSet permanent_folder_types = ModelTypeSet(syncer::BOOKMARKS, syncer::NIGORI); - for (ModelTypeSet::Iterator it = permanent_folder_types.First(); it.Good(); - it.Inc()) { - ModelType model_type = it.Get(); - + for (ModelType model_type : permanent_folder_types) { std::unique_ptr<LoopbackServerEntity> top_level_entity = PersistentPermanentEntity::CreateTopLevel(model_type); if (!top_level_entity) { @@ -498,8 +495,8 @@ // Initialize an empty ListValue for all ModelTypes. ModelTypeSet all_types = ModelTypeSet::All(); - for (ModelTypeSet::Iterator it = all_types.First(); it.Good(); it.Inc()) { - dictionary->Set(ModelTypeToString(it.Get()), + for (ModelType type : all_types) { + dictionary->Set(ModelTypeToString(type), std::make_unique<base::ListValue>()); }
diff --git a/components/sync/engine_impl/model_type_registry_unittest.cc b/components/sync/engine_impl/model_type_registry_unittest.cc index 6d71e32..f2aa337 100644 --- a/components/sync/engine_impl/model_type_registry_unittest.cc +++ b/components/sync/engine_impl/model_type_registry_unittest.cc
@@ -178,8 +178,8 @@ EXPECT_EQ(current_types, registry()->GetEnabledTypes()); // Add some directory types. - for (auto it = directory_types.First(); it.Good(); it.Inc()) - registry()->RegisterDirectoryType(it.Get(), GROUP_PASSIVE); + for (ModelType type : directory_types) + registry()->RegisterDirectoryType(type, GROUP_PASSIVE); current_types.PutAll(directory_types); EXPECT_EQ(current_types, registry()->GetEnabledTypes()); @@ -196,8 +196,8 @@ EXPECT_EQ(current_types, registry()->GetEnabledTypes()); // Clear all directory types. - for (auto it = directory_types.First(); it.Good(); it.Inc()) - registry()->UnregisterDirectoryType(it.Get()); + for (ModelType type : directory_types) + registry()->UnregisterDirectoryType(type); current_types.RemoveAll(directory_types); EXPECT_EQ(current_types, registry()->GetEnabledTypes()); }
diff --git a/components/sync/engine_impl/sync_encryption_handler_impl.cc b/components/sync/engine_impl/sync_encryption_handler_impl.cc index df09440..79b4bc4b 100644 --- a/components/sync/engine_impl/sync_encryption_handler_impl.cc +++ b/components/sync/engine_impl/sync_encryption_handler_impl.cc
@@ -804,14 +804,12 @@ void SyncEncryptionHandlerImpl::ReEncryptEverything(WriteTransaction* trans) { DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_); DCHECK(UnlockVault(trans->GetWrappedTrans()).cryptographer.is_ready()); - for (ModelTypeSet::Iterator iter = - UnlockVault(trans->GetWrappedTrans()).encrypted_types.First(); - iter.Good(); iter.Inc()) { - if (iter.Get() == PASSWORDS || IsControlType(iter.Get())) + for (ModelType type : UnlockVault(trans->GetWrappedTrans()).encrypted_types) { + if (type == PASSWORDS || IsControlType(type)) continue; // These types handle encryption differently. ReadNode type_root(trans); - if (type_root.InitTypeRoot(iter.Get()) != BaseNode::INIT_OK) + if (type_root.InitTypeRoot(type) != BaseNode::INIT_OK) continue; // Don't try to reencrypt if the type's data is unavailable. // Iterate through all children of this datatype.
diff --git a/components/sync/engine_impl/sync_manager_for_profile_sync_test.cc b/components/sync/engine_impl/sync_manager_for_profile_sync_test.cc index 3af98e71..4c8688f 100644 --- a/components/sync/engine_impl/sync_manager_for_profile_sync_test.cc +++ b/components/sync/engine_impl/sync_manager_for_profile_sync_test.cc
@@ -27,10 +27,9 @@ ModelTypeSet early_download_types; early_download_types.PutAll(ControlTypes()); early_download_types.PutAll(PriorityUserTypes()); - for (ModelTypeSet::Iterator it = early_download_types.First(); it.Good(); - it.Inc()) { - if (!directory->InitialSyncEndedForType(it.Get())) { - TestUserShare::CreateRoot(it.Get(), user_share); + for (ModelType type : early_download_types) { + if (!directory->InitialSyncEndedForType(type)) { + TestUserShare::CreateRoot(type, user_share); } }
diff --git a/components/sync/engine_impl/sync_manager_impl.cc b/components/sync/engine_impl/sync_manager_impl.cc index 1a860f2e..a8d4221 100644 --- a/components/sync/engine_impl/sync_manager_impl.cc +++ b/components/sync/engine_impl/sync_manager_impl.cc
@@ -152,12 +152,12 @@ ModelTypeSet SyncManagerImpl::GetTypesWithEmptyProgressMarkerToken( ModelTypeSet types) { ModelTypeSet result; - for (ModelTypeSet::Iterator i = types.First(); i.Good(); i.Inc()) { + for (ModelType type : types) { sync_pb::DataTypeProgressMarker marker; - directory()->GetDownloadProgress(i.Get(), &marker); + directory()->GetDownloadProgress(type, &marker); if (marker.token().empty()) - result.Put(i.Get()); + result.Put(type); } return result; } @@ -585,11 +585,10 @@ return; // Call commit. - for (ModelTypeSet::Iterator it = models_with_changes.First(); it.Good(); - it.Inc()) { - change_delegate_->OnChangesComplete(it.Get()); + for (ModelType type : models_with_changes) { + change_delegate_->OnChangesComplete(type); change_observer_.Call( - FROM_HERE, &SyncManager::ChangeObserver::OnChangesComplete, it.Get()); + FROM_HERE, &SyncManager::ChangeObserver::OnChangesComplete, type); } } @@ -761,7 +760,7 @@ void SyncManagerImpl::RequestNudgeForDataTypes( const base::Location& nudge_location, ModelTypeSet types) { - debug_info_event_listener_.OnNudgeFromDatatype(types.First().Get()); + debug_info_event_listener_.OnNudgeFromDatatype(*(types.begin())); scheduler_->ScheduleLocalNudge(types, nudge_location); }
diff --git a/components/sync/engine_impl/sync_manager_impl_unittest.cc b/components/sync/engine_impl/sync_manager_impl_unittest.cc index 46b80a2f63..6baca938 100644 --- a/components/sync/engine_impl/sync_manager_impl_unittest.cc +++ b/components/sync/engine_impl/sync_manager_impl_unittest.cc
@@ -980,9 +980,8 @@ if (initialization_succeeded_) { ModelTypeSet enabled_types = GetEnabledTypes(); - for (auto it = enabled_types.First(); it.Good(); it.Inc()) { - type_roots_[it.Get()] = - MakeTypeRoot(sync_manager_.GetUserShare(), it.Get()); + for (ModelType type : enabled_types) { + type_roots_[type] = MakeTypeRoot(sync_manager_.GetUserShare(), type); } } @@ -2578,12 +2577,12 @@ { ReadTransaction read_trans(FROM_HERE, sync_manager_.GetUserShare()); ModelTypeSet enabled_types = GetEnabledTypes(); - for (auto it = enabled_types.First(); it.Good(); it.Inc()) { + for (ModelType type : enabled_types) { // Transaction version is incremented when SyncManagerTest::SetUp() // creates a node of each type. - EXPECT_EQ(1, - sync_manager_.GetUserShare()->directory->GetTransactionVersion( - it.Get())); + EXPECT_EQ( + 1, + sync_manager_.GetUserShare()->directory->GetTransactionVersion(type)); } } @@ -2598,10 +2597,10 @@ { ReadTransaction read_trans(FROM_HERE, sync_manager_.GetUserShare()); ModelTypeSet enabled_types = GetEnabledTypes(); - for (auto it = enabled_types.First(); it.Good(); it.Inc()) { - EXPECT_EQ(it.Get() == BOOKMARKS ? 2 : 1, - sync_manager_.GetUserShare()->directory->GetTransactionVersion( - it.Get())); + for (ModelType type : enabled_types) { + EXPECT_EQ( + type == BOOKMARKS ? 2 : 1, + sync_manager_.GetUserShare()->directory->GetTransactionVersion(type)); } } } @@ -2722,9 +2721,8 @@ ModelTypeSet disabled_types = Difference(ModelTypeSet::All(), enabled_types); // Set data for all types. ModelTypeSet protocol_types = ProtocolTypes(); - for (ModelTypeSet::Iterator iter = protocol_types.First(); iter.Good(); - iter.Inc()) { - SetProgressMarkerForType(iter.Get(), true); + for (ModelType type : protocol_types) { + SetProgressMarkerForType(type, true); } sync_manager_.PurgeDisabledTypes(disabled_types, ModelTypeSet(), @@ -2833,9 +2831,8 @@ // Set progress markers for all types. ModelTypeSet protocol_types = ProtocolTypes(); - for (ModelTypeSet::Iterator iter = protocol_types.First(); iter.Good(); - iter.Inc()) { - SetProgressMarkerForType(iter.Get(), true); + for (ModelType type : protocol_types) { + SetProgressMarkerForType(type, true); } // Verify all the enabled types remain after cleanup, and all the disabled @@ -2875,9 +2872,8 @@ // Set progress markers for all types. ModelTypeSet protocol_types = ProtocolTypes(); - for (ModelTypeSet::Iterator iter = protocol_types.First(); iter.Good(); - iter.Inc()) { - SetProgressMarkerForType(iter.Get(), true); + for (ModelType type : protocol_types) { + SetProgressMarkerForType(type, true); } // Add the following kinds of items:
diff --git a/components/sync/engine_impl/sync_scheduler_impl.cc b/components/sync/engine_impl/sync_scheduler_impl.cc index 062c919d..051c0d918 100644 --- a/components/sync/engine_impl/sync_scheduler_impl.cc +++ b/components/sync/engine_impl/sync_scheduler_impl.cc
@@ -820,15 +820,13 @@ ModelTypeSet types = nudge_tracker_.GetBlockedTypes(); ModelTypeSet throttled_types; ModelTypeSet backed_off_types; - for (ModelTypeSet::Iterator type_it = types.First(); type_it.Good(); - type_it.Inc()) { - WaitInterval::BlockingMode mode = - nudge_tracker_.GetTypeBlockingMode(type_it.Get()); + for (ModelType type : types) { + WaitInterval::BlockingMode mode = nudge_tracker_.GetTypeBlockingMode(type); if (mode == WaitInterval::THROTTLED) { - throttled_types.Put(type_it.Get()); + throttled_types.Put(type); } else if (mode == WaitInterval::EXPONENTIAL_BACKOFF || mode == WaitInterval::EXPONENTIAL_BACKOFF_RETRYING) { - backed_off_types.Put(type_it.Get()); + backed_off_types.Put(type); } } @@ -873,17 +871,17 @@ void SyncSchedulerImpl::OnTypesBackedOff(ModelTypeSet types) { DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_); - for (ModelTypeSet::Iterator type = types.First(); type.Good(); type.Inc()) { + for (ModelType type : types) { TimeDelta last_backoff_time = TimeDelta::FromSeconds(kInitialBackoffRetrySeconds); - if (nudge_tracker_.GetTypeBlockingMode(type.Get()) == + if (nudge_tracker_.GetTypeBlockingMode(type) == WaitInterval::EXPONENTIAL_BACKOFF_RETRYING) { - last_backoff_time = nudge_tracker_.GetTypeLastBackoffInterval(type.Get()); + last_backoff_time = nudge_tracker_.GetTypeLastBackoffInterval(type); } TimeDelta length = delay_provider_->GetDelay(last_backoff_time); - nudge_tracker_.SetTypeBackedOff(type.Get(), length, TimeTicks::Now()); - SDVLOG(1) << "Backing off " << ModelTypeToString(type.Get()) << " for " + nudge_tracker_.SetTypeBackedOff(type, length, TimeTicks::Now()); + SDVLOG(1) << "Backing off " << ModelTypeToString(type) << " for " << length.InSeconds() << " second."; } RestartWaiting();
diff --git a/components/sync/engine_impl/sync_scheduler_impl_unittest.cc b/components/sync/engine_impl/sync_scheduler_impl_unittest.cc index 77dd8b5..ee4e50c 100644 --- a/components/sync/engine_impl/sync_scheduler_impl_unittest.cc +++ b/components/sync/engine_impl/sync_scheduler_impl_unittest.cc
@@ -228,11 +228,10 @@ ModelTypeSet GetThrottledTypes() { ModelTypeSet throttled_types; ModelTypeSet blocked_types = scheduler_->nudge_tracker_.GetBlockedTypes(); - for (ModelTypeSet::Iterator type_it = blocked_types.First(); type_it.Good(); - type_it.Inc()) { - if (scheduler_->nudge_tracker_.GetTypeBlockingMode(type_it.Get()) == + for (ModelType type : blocked_types) { + if (scheduler_->nudge_tracker_.GetTypeBlockingMode(type) == WaitInterval::THROTTLED) { - throttled_types.Put(type_it.Get()); + throttled_types.Put(type); } } return throttled_types; @@ -241,11 +240,10 @@ ModelTypeSet GetBackedOffTypes() { ModelTypeSet backed_off_types; ModelTypeSet blocked_types = scheduler_->nudge_tracker_.GetBlockedTypes(); - for (ModelTypeSet::Iterator type_it = blocked_types.First(); type_it.Good(); - type_it.Inc()) { - if (scheduler_->nudge_tracker_.GetTypeBlockingMode(type_it.Get()) == + for (ModelType type : blocked_types) { + if (scheduler_->nudge_tracker_.GetTypeBlockingMode(type) == WaitInterval::EXPONENTIAL_BACKOFF) { - backed_off_types.Put(type_it.Get()); + backed_off_types.Put(type); } } return backed_off_types; @@ -631,7 +629,7 @@ TimeDelta delay = TimeDelta::FromDays(1); std::map<ModelType, TimeDelta> delay_map; - delay_map[types1.First().Get()] = delay; + delay_map[*(types1.begin())] = delay; scheduler()->OnReceivedCustomNudgeDelays(delay_map); scheduler()->ScheduleLocalNudge(types1, FROM_HERE); scheduler()->ScheduleLocalNudge(types2, FROM_HERE);
diff --git a/components/test/android/browsertests_apk/AndroidManifest.xml.jinja2 b/components/test/android/browsertests_apk/AndroidManifest.xml.jinja2 index 8315e36..49c50321 100644 --- a/components/test/android/browsertests_apk/AndroidManifest.xml.jinja2 +++ b/components/test/android/browsertests_apk/AndroidManifest.xml.jinja2
@@ -63,5 +63,6 @@ <instrumentation android:name="org.chromium.native_test.NativeTestInstrumentationTestRunner" android:label="ComponentsBrowserTests" - android:targetPackage="org.chromium.components_browsertests_apk"/> + android:targetPackage="org.chromium.components_browsertests_apk" + chromium-junit3="true"/> </manifest>
diff --git a/components/viz/service/main/viz_compositor_thread_runner.cc b/components/viz/service/main/viz_compositor_thread_runner.cc index 193499d2..9f445162 100644 --- a/components/viz/service/main/viz_compositor_thread_runner.cc +++ b/components/viz/service/main/viz_compositor_thread_runner.cc
@@ -14,8 +14,12 @@ #include "build/build_config.h" #include "components/viz/common/switches.h" #include "components/viz/service/display_embedder/gpu_display_provider.h" +#include "components/viz/service/display_embedder/in_process_gpu_memory_buffer_manager.h" #include "components/viz/service/display_embedder/server_shared_bitmap_manager.h" #include "components/viz/service/frame_sinks/frame_sink_manager_impl.h" +#include "components/viz/service/gl/gpu_service_impl.h" +#include "gpu/ipc/command_buffer_task_executor.h" +#include "gpu/ipc/service/gpu_memory_buffer_factory.h" #include "ui/gfx/switches.h" namespace viz { @@ -23,7 +27,13 @@ const char kThreadName[] = "VizCompositorThread"; -std::unique_ptr<base::Thread> CreateAndStartCompositorThread() { +std::unique_ptr<VizCompositorThreadType> CreateAndStartCompositorThread() { +#if defined(OS_ANDROID) + auto thread = std::make_unique<base::android::JavaHandlerThread>( + kThreadName, base::ThreadPriority::DISPLAY); + thread->Start(); + return thread; +#else // !defined(OS_ANDROID) auto thread = std::make_unique<base::Thread>(kThreadName); base::Thread::Options thread_options; @@ -37,6 +47,7 @@ CHECK(thread->StartWithOptions(thread_options)); return thread; +#endif // !defined(OS_ANDROID) } } // namespace @@ -59,27 +70,72 @@ FROM_HERE, base::BindOnce( &VizCompositorThreadRunner::CreateFrameSinkManagerOnCompositorThread, - base::Unretained(this), std::move(params))); + base::Unretained(this), std::move(params), nullptr, nullptr, nullptr, + nullptr)); +} + +void VizCompositorThreadRunner::CreateFrameSinkManager( + mojom::FrameSinkManagerParamsPtr params, + scoped_refptr<gpu::CommandBufferTaskExecutor> task_executor, + GpuServiceImpl* gpu_service) { + auto* gpu_channel_manager = gpu_service->gpu_channel_manager(); + auto* image_factory = gpu_service->gpu_image_factory(); + + // All of the unretained objects are owned on the GPU thread and destroyed + // after VizCompositorThread has been shutdown. + task_runner_->PostTask( + FROM_HERE, + base::BindOnce( + &VizCompositorThreadRunner::CreateFrameSinkManagerOnCompositorThread, + base::Unretained(this), std::move(params), std::move(task_executor), + base::Unretained(gpu_service), base::Unretained(image_factory), + base::Unretained(gpu_channel_manager))); +} + +void VizCompositorThreadRunner::CleanupForShutdown( + base::OnceClosure cleanup_finished_callback) { + task_runner_->PostTaskAndReply( + FROM_HERE, + base::BindOnce( + &VizCompositorThreadRunner::CleanupForShutdownOnCompositorThread, + base::Unretained(this)), + std::move(cleanup_finished_callback)); } void VizCompositorThreadRunner::CreateFrameSinkManagerOnCompositorThread( - mojom::FrameSinkManagerParamsPtr params) { + mojom::FrameSinkManagerParamsPtr params, + scoped_refptr<gpu::CommandBufferTaskExecutor> task_executor, + GpuServiceImpl* gpu_service, + gpu::ImageFactory* image_factory, + gpu::GpuChannelManager* gpu_channel_manager) { DCHECK(task_runner_->BelongsToCurrentThread()); DCHECK(!frame_sink_manager_); - base::CommandLine* command_line = base::CommandLine::ForCurrentProcess(); - server_shared_bitmap_manager_ = std::make_unique<ServerSharedBitmapManager>(); base::trace_event::MemoryDumpManager::GetInstance()->RegisterDumpProvider( server_shared_bitmap_manager_.get(), "ServerSharedBitmapManager", - base::ThreadTaskRunnerHandle::Get()); + task_runner_); - // Create GpuDisplayProvider usable for software compositing only. - display_provider_ = std::make_unique<GpuDisplayProvider>( - params->restart_id, server_shared_bitmap_manager_.get(), - command_line->HasSwitch(switches::kHeadless), - command_line->HasSwitch(switches::kRunAllCompositorStagesBeforeDraw)); + base::CommandLine* command_line = base::CommandLine::ForCurrentProcess(); + const bool headless = command_line->HasSwitch(switches::kHeadless); + const bool run_all_compositor_stages_before_draw = + command_line->HasSwitch(switches::kRunAllCompositorStagesBeforeDraw); + if (task_executor) { + // Create DisplayProvider usable for GPU + software compositing. + display_provider_ = std::make_unique<GpuDisplayProvider>( + params->restart_id, gpu_service, std::move(task_executor), gpu_service, + std::make_unique<InProcessGpuMemoryBufferManager>(gpu_channel_manager), + image_factory, server_shared_bitmap_manager_.get(), headless, + run_all_compositor_stages_before_draw); + } else { + // Create DisplayProvider usable for software compositing only. + display_provider_ = std::make_unique<GpuDisplayProvider>( + params->restart_id, server_shared_bitmap_manager_.get(), headless, + run_all_compositor_stages_before_draw); + } + + // Create FrameSinkManagerImpl. base::Optional<uint32_t> activation_deadline_in_frames; if (params->use_activation_deadline) activation_deadline_in_frames = params->activation_deadline_in_frames; @@ -92,6 +148,13 @@ std::move(params->frame_sink_manager_client))); } +void VizCompositorThreadRunner::CleanupForShutdownOnCompositorThread() { + DCHECK(task_runner_->BelongsToCurrentThread()); + + if (frame_sink_manager_) + frame_sink_manager_->ForceShutdown(); +} + void VizCompositorThreadRunner::TearDownOnCompositorThread() { DCHECK(task_runner_->BelongsToCurrentThread());
diff --git a/components/viz/service/main/viz_compositor_thread_runner.h b/components/viz/service/main/viz_compositor_thread_runner.h index 93c8e9d..f7a627b7 100644 --- a/components/viz/service/main/viz_compositor_thread_runner.h +++ b/components/viz/service/main/viz_compositor_thread_runner.h
@@ -9,37 +9,79 @@ #include "base/macros.h" #include "base/memory/scoped_refptr.h" +#include "build/build_config.h" #include "components/viz/service/viz_service_export.h" #include "services/viz/privileged/interfaces/viz_main.mojom.h" +#if defined(OS_ANDROID) +#include "base/android/java_handler_thread.h" +#endif + namespace base { class SingleThreadTaskRunner; class Thread; } // namespace base +namespace gpu { +class CommandBufferTaskExecutor; +class GpuChannelManager; +class ImageFactory; +} // namespace gpu + namespace viz { class DisplayProvider; class FrameSinkManagerImpl; +class GpuServiceImpl; class ServerSharedBitmapManager; +#if defined(OS_ANDROID) +using VizCompositorThreadType = base::android::JavaHandlerThread; +#else +using VizCompositorThreadType = base::Thread; +#endif + // Starts and runs the VizCompositorThread. The thread will be started when this // object is constructed. Objects on the thread will be initialized after // calling CreateFrameSinkManager(). Destructor will teardown objects on thread // and then stop the thread. -// TODO(kylechar): Convert VizMainImpl to use VizCompositorThreadRunner. class VIZ_SERVICE_EXPORT VizCompositorThreadRunner { public: VizCompositorThreadRunner(); // Performs teardown on thread and then stops thread. ~VizCompositorThreadRunner(); - // Create FrameSinkManager from |params|. This can be called from the thread - // that owns |this| to initialize state on VizCompositorThreadRunner. + // Returns the TaskRunner for VizCompositorThread. + base::SingleThreadTaskRunner* task_runner() { return task_runner_.get(); } + + // Creates FrameSinkManager from |params|. The version with |gpu_service| and + // |task_executor| supports both GPU and software compositing, while the + // version without supports only software compositing. Should be called from + // the thread that owns |this| to initialize state on VizCompositorThread. void CreateFrameSinkManager(mojom::FrameSinkManagerParamsPtr params); + void CreateFrameSinkManager( + mojom::FrameSinkManagerParamsPtr params, + scoped_refptr<gpu::CommandBufferTaskExecutor> task_executor, + GpuServiceImpl* gpu_service); + + // Performs cleanup on VizCompositorThread needed before forcing thread to + // shut down. Ensures VizCompositorThread teardown during the destructor + // doesn't block on PostTasks back to the GPU thread. After cleanup has + // finished |cleanup_finished_callback| will be run. Should be called from the + // thread that owns |this|. + // + // This is intended to be used when the GPU thread wants to force restart. The + // cleanup is normally handled by the browser process before GPU process + // shutdown, except if the GPU thread is forcing restart. + void CleanupForShutdown(base::OnceClosure cleanup_finished_callback); private: void CreateFrameSinkManagerOnCompositorThread( - mojom::FrameSinkManagerParamsPtr params); + mojom::FrameSinkManagerParamsPtr params, + scoped_refptr<gpu::CommandBufferTaskExecutor> task_executor, + GpuServiceImpl* gpu_service, + gpu::ImageFactory* image_factory, + gpu::GpuChannelManager* gpu_channel_manager); + void CleanupForShutdownOnCompositorThread(); void TearDownOnCompositorThread(); // Start variables to be accessed only on |task_runner_|. @@ -48,7 +90,7 @@ std::unique_ptr<FrameSinkManagerImpl> frame_sink_manager_; // End variables to be accessed only on |task_runner_|. - std::unique_ptr<base::Thread> thread_; + std::unique_ptr<VizCompositorThreadType> thread_; scoped_refptr<base::SingleThreadTaskRunner> task_runner_; DISALLOW_COPY_AND_ASSIGN(VizCompositorThreadRunner);
diff --git a/components/viz/service/main/viz_main_impl.cc b/components/viz/service/main/viz_main_impl.cc index b4e081d..80fc32a1d 100644 --- a/components/viz/service/main/viz_main_impl.cc +++ b/components/viz/service/main/viz_main_impl.cc
@@ -11,21 +11,13 @@ #include "base/message_loop/message_loop.h" #include "base/power_monitor/power_monitor_device_source.h" #include "base/single_thread_task_runner.h" -#include "base/threading/sequenced_task_runner_handle.h" #include "base/trace_event/memory_dump_manager.h" #include "build/build_config.h" -#include "components/viz/common/switches.h" -#include "components/viz/service/display_embedder/gpu_display_provider.h" -#include "components/viz/service/display_embedder/in_process_gpu_memory_buffer_manager.h" -#include "components/viz/service/display_embedder/server_shared_bitmap_manager.h" -#include "components/viz/service/frame_sinks/frame_sink_manager_impl.h" #include "components/viz/service/gl/gpu_service_impl.h" #include "gpu/command_buffer/common/activity_flags.h" #include "gpu/config/gpu_preferences.h" #include "gpu/config/gpu_switches.h" -#include "gpu/ipc/common/gpu_memory_buffer_support.h" #include "gpu/ipc/gpu_in_process_thread_service.h" -#include "gpu/ipc/service/gpu_memory_buffer_factory.h" #include "gpu/ipc/service/gpu_watchdog_thread.h" #include "media/gpu/buildflags.h" #include "services/metrics/public/cpp/delegating_ukm_recorder.h" @@ -33,7 +25,6 @@ #include "services/metrics/public/mojom/constants.mojom.h" #include "services/service_manager/public/cpp/connector.h" #include "third_party/skia/include/core/SkFontLCDConfig.h" -#include "ui/gfx/switches.h" #if defined(OS_CHROMEOS) && BUILDFLAG(USE_VAAPI) #include "media/gpu/vaapi/vaapi_wrapper.h" @@ -45,31 +36,6 @@ namespace { -std::unique_ptr<viz::CompositorThreadType> CreateAndStartCompositorThread() { - const char* thread_name = "VizCompositorThread"; - -#if defined(OS_ANDROID) - auto thread = std::make_unique<base::android::JavaHandlerThread>( - thread_name, base::ThreadPriority::DISPLAY); - thread->Start(); - return thread; -#else - auto thread = std::make_unique<base::Thread>(thread_name); - base::Thread::Options thread_options; -#if defined(OS_WIN) - // Windows needs a UI message loop for child HWND. Other platforms can use the - // default message loop type. - thread_options.message_loop_type = base::MessageLoop::TYPE_UI; -#endif - -#if defined(OS_CHROMEOS) - thread_options.priority = base::ThreadPriority::DISPLAY; -#endif - CHECK(thread->StartWithOptions(thread_options)); - return thread; -#endif -} - std::unique_ptr<base::Thread> CreateAndStartIOThread() { // TODO(sad): We do not need the IO thread once gpu has a separate process. // It should be possible to use |main_task_runner_| for doing IO tasks. @@ -145,29 +111,23 @@ if (!dependencies_.io_thread_task_runner) io_thread_ = CreateAndStartIOThread(); if (dependencies_.create_display_compositor) { - compositor_thread_ = CreateAndStartCompositorThread(); - compositor_thread_task_runner_ = compositor_thread_->task_runner(); - if (delegate_) + viz_compositor_thread_runner_ = + std::make_unique<VizCompositorThreadRunner>(); + if (delegate_) { delegate_->PostCompositorThreadCreated( - compositor_thread_task_runner_.get()); + viz_compositor_thread_runner_->task_runner()); + } } CreateUkmRecorderIfNeeded(dependencies.connector); - // We need to provide GpuServiceImpl a callback to exit the GPU process. With - // OOP-D this requires destroying RootCompositorFrameSinkImpls on the - // compositor thread while the GPU thread is still running to avoid deadlock. - // For non OOP-D we can simply quit the GPU thread RunLoop. - base::OnceClosure exit_callback = - compositor_thread_ - ? base::BindOnce(&VizMainImpl::ExitProcess, base::Unretained(this)) - : base::BindOnce(&base::RunLoop::QuitCurrentDeprecated); gpu_service_ = std::make_unique<GpuServiceImpl>( gpu_init_->gpu_info(), gpu_init_->TakeWatchdogThread(), io_task_runner(), gpu_init_->gpu_feature_info(), gpu_init_->gpu_preferences(), gpu_init_->gpu_info_for_hardware_gpu(), gpu_init_->gpu_feature_info_for_hardware_gpu(), - gpu_init_->vulkan_implementation(), std::move(exit_callback)); + gpu_init_->vulkan_implementation(), + base::BindOnce(&VizMainImpl::ExitProcess, base::Unretained(this))); if (dependencies_.create_display_compositor) gpu_service_->set_oopd_enabled(); } @@ -182,18 +142,11 @@ binding_.Close(); associated_binding_.Close(); - if (compositor_thread_) { - // Destroy all objects owned on the compositor thread before shutting down - // the thread. All RootCompositorFrameSinks must be destroyed before now, - // otherwise the compositor thread will deadlock waiting for a response from - // the blocked GPU thread. - compositor_thread_task_runner_->PostTask( - FROM_HERE, base::BindOnce(&VizMainImpl::TearDownOnCompositorThread, - base::Unretained(this))); - compositor_thread_->Stop(); - compositor_thread_.reset(); - compositor_thread_task_runner_.reset(); - } + // If the VizCompositorThread was started then this will block until the + // thread has been shutdown. All RootCompositorFrameSinks must be destroyed + // before now, otherwise the compositor thread will deadlock waiting for a + // response from the blocked GPU thread. + viz_compositor_thread_runner_.reset(); if (ukm_recorder_) ukm::DelegatingUkmRecorder::Get()->RemoveDelegate(ukm_recorder_.get()); @@ -283,7 +236,7 @@ void VizMainImpl::CreateFrameSinkManager( mojom::FrameSinkManagerParamsPtr params) { - DCHECK(compositor_thread_task_runner_); + DCHECK(viz_compositor_thread_runner_); DCHECK(gpu_thread_task_runner_->BelongsToCurrentThread()); if (!gpu_service_ || !gpu_service_->is_initialized()) { DCHECK(pending_frame_sink_manager_params_.is_null()); @@ -295,7 +248,6 @@ void VizMainImpl::CreateFrameSinkManagerInternal( mojom::FrameSinkManagerParamsPtr params) { - DCHECK(!task_executor_); DCHECK(gpu_service_); DCHECK(gpu_thread_task_runner_->BelongsToCurrentThread()); @@ -315,84 +267,26 @@ gpu_service_->gpu_feature_info(), gpu_service_->gpu_channel_manager()->gpu_preferences()); - compositor_thread_task_runner_->PostTask( - FROM_HERE, - base::BindOnce(&VizMainImpl::CreateFrameSinkManagerOnCompositorThread, - base::Unretained(this), std::move(params))); -} - -void VizMainImpl::CreateFrameSinkManagerOnCompositorThread( - mojom::FrameSinkManagerParamsPtr params) { - DCHECK(compositor_thread_task_runner_->BelongsToCurrentThread()); - DCHECK(!frame_sink_manager_); - - base::CommandLine* command_line = base::CommandLine::ForCurrentProcess(); - - server_shared_bitmap_manager_ = std::make_unique<ServerSharedBitmapManager>(); - base::trace_event::MemoryDumpManager::GetInstance()->RegisterDumpProvider( - server_shared_bitmap_manager_.get(), "viz::ServerSharedBitmapManager", - base::ThreadTaskRunnerHandle::Get()); - - auto* gpu_channel_manager = gpu_service_->gpu_channel_manager(); - gpu::ImageFactory* image_factory = nullptr; - if (gpu_channel_manager->gpu_memory_buffer_factory()) { - image_factory = - gpu_channel_manager->gpu_memory_buffer_factory()->AsImageFactory(); - } - display_provider_ = std::make_unique<GpuDisplayProvider>( - params->restart_id, gpu_service_.get(), task_executor_, - gpu_channel_manager->delegate(), - std::make_unique<InProcessGpuMemoryBufferManager>(gpu_channel_manager), - image_factory, server_shared_bitmap_manager_.get(), - command_line->HasSwitch(switches::kHeadless), - command_line->HasSwitch(switches::kRunAllCompositorStagesBeforeDraw)); - - mojom::FrameSinkManagerClientPtr client( - std::move(params->frame_sink_manager_client)); - base::Optional<uint32_t> activation_deadline_in_frames; - if (params->use_activation_deadline) - activation_deadline_in_frames = params->activation_deadline_in_frames; - frame_sink_manager_ = std::make_unique<FrameSinkManagerImpl>( - server_shared_bitmap_manager_.get(), activation_deadline_in_frames, - display_provider_.get()); - frame_sink_manager_->BindAndSetClient(std::move(params->frame_sink_manager), - nullptr, std::move(client)); -} - -void VizMainImpl::TearDownOnCompositorThread() { - DCHECK(compositor_thread_task_runner_->BelongsToCurrentThread()); - - base::trace_event::MemoryDumpManager::GetInstance()->UnregisterDumpProvider( - server_shared_bitmap_manager_.get()); - - frame_sink_manager_.reset(); - display_provider_.reset(); - server_shared_bitmap_manager_.reset(); -} - -void VizMainImpl::CleanupForShutdownOnCompositorThread() { - DCHECK(compositor_thread_task_runner_->BelongsToCurrentThread()); - - if (frame_sink_manager_) - frame_sink_manager_->ForceShutdown(); + viz_compositor_thread_runner_->CreateFrameSinkManager( + std::move(params), task_executor_, gpu_service_.get()); } void VizMainImpl::ExitProcess() { DCHECK(gpu_thread_task_runner_->BelongsToCurrentThread()); - DCHECK(compositor_thread_task_runner_); // Close mojom::VizMain bindings first so the browser can't try to reconnect. binding_.Close(); associated_binding_.Close(); - // PostTask to the compositor thread to cleanup and then exit the GPU thread - // RunLoop once that is finished. Unretained is safe here because |this| owns - // |compositor_thread_|. - compositor_thread_task_runner_->PostTaskAndReply( - FROM_HERE, - base::BindOnce(&VizMainImpl::CleanupForShutdownOnCompositorThread, - base::Unretained(this)), - base::BindOnce([]() { base::RunLoop::QuitCurrentDeprecated(); })); + if (viz_compositor_thread_runner_) { + // OOP-D requires destroying RootCompositorFrameSinkImpls on the compositor + // thread while the GPU thread is still running to avoid deadlock. Quit GPU + // thread TaskRunner after cleanup on compositor thread is finished. + viz_compositor_thread_runner_->CleanupForShutdown( + base::BindOnce([]() { base::RunLoop::QuitCurrentDeprecated(); })); + } else { + base::RunLoop::QuitCurrentDeprecated(); + } } void VizMainImpl::PreSandboxStartup() {
diff --git a/components/viz/service/main/viz_main_impl.h b/components/viz/service/main/viz_main_impl.h index 273c74c..c83792f 100644 --- a/components/viz/service/main/viz_main_impl.h +++ b/components/viz/service/main/viz_main_impl.h
@@ -10,6 +10,7 @@ #include "base/threading/thread.h" #include "build/build_config.h" #include "components/discardable_memory/client/client_discardable_shared_memory_manager.h" +#include "components/viz/service/main/viz_compositor_thread_runner.h" #include "gpu/ipc/in_process_command_buffer.h" #include "gpu/ipc/service/gpu_init.h" #include "mojo/public/cpp/bindings/associated_binding_set.h" @@ -18,10 +19,6 @@ #include "services/viz/privileged/interfaces/viz_main.mojom.h" #include "ui/gfx/font_render_params.h" -#if defined(OS_ANDROID) -#include "base/android/java_handler_thread.h" -#endif - namespace gpu { class SyncPointManager; } // namespace gpu @@ -35,10 +32,7 @@ } namespace viz { -class DisplayProvider; -class FrameSinkManagerImpl; class GpuServiceImpl; -class ServerSharedBitmapManager; #if defined(OS_ANDROID) using CompositorThreadType = base::android::JavaHandlerThread; @@ -121,17 +115,8 @@ void CreateUkmRecorderIfNeeded(service_manager::Connector* connector); void CreateFrameSinkManagerInternal(mojom::FrameSinkManagerParamsPtr params); - void CreateFrameSinkManagerOnCompositorThread( - mojom::FrameSinkManagerParamsPtr params); - void TearDownOnCompositorThread(); - - // Performs necessary cleanup on the compositor thread to allow for a clean - // process exit. - void CleanupForShutdownOnCompositorThread(); - - // Cleanly exits the process. This is only used with OOP-D when there is a - // compositor thread. + // Cleanly exits the process. void ExitProcess(); // gpu::GpuSandboxHelper: @@ -162,24 +147,24 @@ // This is created for OOP-D only. It allows the display compositor to use // InProcessCommandBuffer to send GPU commands to the GPU thread from the // compositor thread. + // TODO(kylechar): The only reason this member variable exists is so the last + // reference is released and the object is destroyed on the GPU thread. This + // works because |task_executor_| is destroyed after the VizCompositorThread + // has been shutdown. All usage of CommandBufferTaskExecutor has the same + // pattern, where the last scoped_refptr is released on the GPU thread after + // all InProcessCommandBuffers are destroyed, so the class doesn't need to be + // RefCountedThreadSafe. scoped_refptr<gpu::CommandBufferTaskExecutor> task_executor_; // If the gpu service is not yet ready then we stash pending // FrameSinkManagerParams. mojom::FrameSinkManagerParamsPtr pending_frame_sink_manager_params_; - // Provides mojo interfaces for creating and managing FrameSinks. These live - // on the compositor thread. - std::unique_ptr<ServerSharedBitmapManager> server_shared_bitmap_manager_; - std::unique_ptr<DisplayProvider> display_provider_; - std::unique_ptr<FrameSinkManagerImpl> frame_sink_manager_; + // Runs the VizCompositorThread for the display compositor with OOP-D. + std::unique_ptr<VizCompositorThreadRunner> viz_compositor_thread_runner_; const scoped_refptr<base::SingleThreadTaskRunner> gpu_thread_task_runner_; - // The main thread for the display compositor. - std::unique_ptr<CompositorThreadType> compositor_thread_; - scoped_refptr<base::SingleThreadTaskRunner> compositor_thread_task_runner_; - std::unique_ptr<ukm::MojoUkmRecorder> ukm_recorder_; std::unique_ptr<base::PowerMonitor> power_monitor_; mojo::Binding<mojom::VizMain> binding_;
diff --git a/content/browser/accessibility/browser_accessibility.cc b/content/browser/accessibility/browser_accessibility.cc index 7c190d9..b84774d90 100644 --- a/content/browser/accessibility/browser_accessibility.cc +++ b/content/browser/accessibility/browser_accessibility.cc
@@ -691,20 +691,24 @@ return GetData().HasAction(action_enum); } -bool BrowserAccessibility::HasCaret() const { - if (IsPlainTextField() && - HasIntAttribute(ax::mojom::IntAttribute::kTextSelStart) && - HasIntAttribute(ax::mojom::IntAttribute::kTextSelEnd)) { - return true; - } - - // The caret is always at the focus of the selection. +bool BrowserAccessibility::HasVisibleCaretOrSelection() const { int32_t focus_id = manager()->GetTreeData().sel_focus_object_id; BrowserAccessibility* focus_object = manager()->GetFromID(focus_id); if (!focus_object) return false; - return focus_object->IsDescendantOf(this); + // Selection or caret will be visible in a focused editable area. + if (HasState(ax::mojom::State::kEditable)) { + return IsPlainTextField() ? focus_object == this + : focus_object->IsDescendantOf(this); + } + + // The selection will be visible in non-editable content only if it is not + // collapsed into a caret. + return (focus_id != manager()->GetTreeData().sel_anchor_object_id || + manager()->GetTreeData().sel_focus_offset != + manager()->GetTreeData().sel_anchor_offset) && + focus_object->IsDescendantOf(this); } bool BrowserAccessibility::IsWebAreaForPresentationalIframe() const {
diff --git a/content/browser/accessibility/browser_accessibility.h b/content/browser/accessibility/browser_accessibility.h index a953e561..494ad2e8 100644 --- a/content/browser/accessibility/browser_accessibility.h +++ b/content/browser/accessibility/browser_accessibility.h
@@ -303,8 +303,8 @@ bool HasState(ax::mojom::State state_enum) const; bool HasAction(ax::mojom::Action action_enum) const; - // Returns true if the caret is active on this object. - bool HasCaret() const; + // Returns true if the caret or selection is visible on this object. + bool HasVisibleCaretOrSelection() const; // True if this is a web area, and its grandparent is a presentational iframe. bool IsWebAreaForPresentationalIframe() const;
diff --git a/content/browser/accessibility/browser_accessibility_manager_win.cc b/content/browser/accessibility/browser_accessibility_manager_win.cc index 2251fd169..52fd978 100644 --- a/content/browser/accessibility/browser_accessibility_manager_win.cc +++ b/content/browser/accessibility/browser_accessibility_manager_win.cc
@@ -169,7 +169,7 @@ // Fire the event on the object where the focus of the selection is. int32_t focus_id = GetTreeData().sel_focus_object_id; BrowserAccessibility* focus_object = GetFromID(focus_id); - if (focus_object) + if (focus_object->HasVisibleCaretOrSelection()) FireWinAccessibilityEvent(IA2_EVENT_TEXT_CARET_MOVED, focus_object); break; }
diff --git a/content/browser/browser_child_process_host_impl.cc b/content/browser/browser_child_process_host_impl.cc index faf2e2d..b199dab 100644 --- a/content/browser/browser_child_process_host_impl.cc +++ b/content/browser/browser_child_process_host_impl.cc
@@ -178,7 +178,6 @@ // Create a persistent memory segment for subprocess histograms. CreateMetricsAllocator(); - ShareMetricsAllocatorToProcess(); } BrowserChildProcessHostImpl::~BrowserChildProcessHostImpl() { @@ -390,6 +389,7 @@ delegate_->OnChannelConnected(peer_pid); if (IsProcessLaunched()) { + ShareMetricsAllocatorToProcess(); BrowserThread::PostTask( BrowserThread::UI, FROM_HERE, base::BindOnce(&NotifyProcessLaunchedAndConnected, data_.Duplicate())); @@ -608,6 +608,7 @@ delegate_->OnProcessLaunched(); if (is_channel_connected_) { + ShareMetricsAllocatorToProcess(); BrowserThread::PostTask( BrowserThread::UI, FROM_HERE, base::BindOnce(&NotifyProcessLaunchedAndConnected, data_.Duplicate()));
diff --git a/content/browser/cache_storage/cache_storage_cache.cc b/content/browser/cache_storage/cache_storage_cache.cc index 2c4f2d3..2b2797e 100644 --- a/content/browser/cache_storage/cache_storage_cache.cc +++ b/content/browser/cache_storage/cache_storage_cache.cc
@@ -168,63 +168,6 @@ return true; } -// Check batch operation list for duplicate entries. -bool HasDuplicateOperations( - const std::vector<blink::mojom::BatchOperationPtr>& operations) { - using blink::mojom::BatchOperation; - - if (operations.size() < 2) { - return false; - } - - // Create a temporary sorted vector of the operations to support quickly - // finding potentially duplicate entries. Multiple entries may have the - // same URL, but differ by VARY header, so a sorted list is easier to - // work with than a map. - // - // Note, this will use 512 bytes of stack space on 64-bit devices. The - // static size attempts to accommodate most typical Cache.addAll() uses in - // service worker install events while not blowing up the stack too much. - base::StackVector<BatchOperation*, 64> sorted; - sorted->reserve(operations.size()); - for (const auto& op : operations) { - sorted->push_back(op.get()); - } - std::sort(sorted->begin(), sorted->end(), - [](BatchOperation* left, BatchOperation* right) { - return left->request.url < right->request.url; - }); - - // Check each entry in the sorted vector for any duplicates. Since the - // list is sorted we only need to inspect the immediate neighbors that - // have the same URL. This results in an average complexity of O(n log n). - // If the entire list has entries with the same URL and different VARY - // headers then this devolves into O(n^2). - for (auto outer = sorted->cbegin(); outer != sorted->cend(); ++outer) { - const BatchOperation* outer_op = *outer; - for (auto inner = std::next(outer); inner != sorted->cend(); ++inner) { - const BatchOperation* inner_op = *inner; - // Since the list is sorted we can stop looking at neighbors after - // the first different URL. - if (outer_op->request.url != inner_op->request.url) { - break; - } - // VaryMatches() is asymmetric since the operation depends on the VARY - // header in the target response. Since we only visit each pair of - // entries once we need to perform the VaryMatches() call in both - // directions. - if (VaryMatches(outer_op->request.headers, inner_op->request.headers, - inner_op->response->headers) || - VaryMatches(outer_op->request.headers, inner_op->request.headers, - outer_op->response->headers)) { - return true; - } - } - } - - return false; -} - GURL RemoveQueryParam(const GURL& url) { url::Replacements<char> replacements; replacements.ClearQuery(); @@ -601,26 +544,6 @@ return; } - // From BatchCacheOperations: - // - // https://w3c.github.io/ServiceWorker/#batch-cache-operations-algorithm - // - // "If the result of running Query Cache with operation’s request, - // operation’s options, and addedItems is not empty, throw an - // InvalidStateError DOMException." - // - // Note, the spec checks CacheQueryOptions like ignoreSearch, etc, but - // currently there is no way for script to trigger a batch operation with - // those set. The only exposed API is addAll() which does not allow - // options to be passed. Therefore, assume default options below. This - // is enforced in the mojo interface by not passing any options arguments. - if (HasDuplicateOperations(operations)) { - base::ThreadTaskRunnerHandle::Get()->PostTask( - FROM_HERE, base::BindOnce(std::move(callback), - CacheStorageError::kErrorDuplicateOperation)); - return; - } - // Estimate the required size of the put operations. The size of the deletes // is unknown and not considered. base::CheckedNumeric<uint64_t> safe_space_required = 0;
diff --git a/content/browser/cache_storage/cache_storage_cache_unittest.cc b/content/browser/cache_storage/cache_storage_cache_unittest.cc index 78fe095..4a2b0f49 100644 --- a/content/browser/cache_storage/cache_storage_cache_unittest.cc +++ b/content/browser/cache_storage/cache_storage_cache_unittest.cc
@@ -910,17 +910,15 @@ } TEST_P(CacheStorageCacheTestP, PutBadMessage) { - // Two unique puts that will collectively overflow unit64_t size of the - // batch operation. blink::mojom::BatchOperationPtr operation1 = blink::mojom::BatchOperation::New(blink::mojom::OperationType::kPut, body_request_, CreateBlobBodyResponse(), nullptr /* match_params */); operation1->response->blob->size = std::numeric_limits<uint64_t>::max(); blink::mojom::BatchOperationPtr operation2 = - blink::mojom::BatchOperation::New( - blink::mojom::OperationType::kPut, body_request_with_query_, - CreateBlobBodyResponse(), nullptr /* match_params */); + blink::mojom::BatchOperation::New(blink::mojom::OperationType::kPut, + body_request_, CreateBlobBodyResponse(), + nullptr /* match_params */); operation2->response->blob->size = std::numeric_limits<uint64_t>::max(); std::vector<blink::mojom::BatchOperationPtr> operations; @@ -947,7 +945,7 @@ EXPECT_FALSE(callback_response_->blob); } -TEST_P(CacheStorageCacheTestP, PutReplaceInBatchFails) { +TEST_P(CacheStorageCacheTestP, PutReplaceInBatch) { blink::mojom::BatchOperationPtr operation1 = blink::mojom::BatchOperation::New(); operation1->operation_type = blink::mojom::OperationType::kPut; @@ -964,11 +962,11 @@ operations.push_back(std::move(operation1)); operations.push_back(std::move(operation2)); - EXPECT_EQ(CacheStorageError::kErrorDuplicateOperation, - BatchOperation(std::move(operations))); + EXPECT_EQ(CacheStorageError::kSuccess, BatchOperation(std::move(operations))); - // Neither operation should have completed. - EXPECT_FALSE(Match(body_request_)); + // |operation2| should win. + EXPECT_TRUE(Match(body_request_)); + EXPECT_TRUE(callback_response_->blob); } TEST_P(CacheStorageCacheTestP, MatchNoBody) {
diff --git a/content/browser/compositor/viz_process_transport_factory.cc b/content/browser/compositor/viz_process_transport_factory.cc index f02da8e..042df248 100644 --- a/content/browser/compositor/viz_process_transport_factory.cc +++ b/content/browser/compositor/viz_process_transport_factory.cc
@@ -286,6 +286,8 @@ } void VizProcessTransportFactory::OnContextLost() { + // PostTask to avoid destroying |main_context_provider_| while it's still + // informing observers about the context loss. base::ThreadTaskRunnerHandle::Get()->PostTask( FROM_HERE, base::BindOnce(&VizProcessTransportFactory::OnLostMainThreadSharedContext, @@ -301,19 +303,18 @@ compositing_mode_reporter_->SetUsingSoftwareCompositing(); - // Consumers of the shared main thread context aren't CompositingModeWatchers, - // so inform them about the compositing mode switch by acting like the context - // was lost. This also destroys the contexts since they aren't created when - // gpu compositing isn't being used. - OnLostMainThreadSharedContext(); - // Drop our reference on the gpu contexts for the compositors. - worker_context_provider_ = nullptr; + worker_context_provider_.reset(); if (main_context_provider_) { main_context_provider_->RemoveObserver(this); - main_context_provider_ = nullptr; + main_context_provider_.reset(); } + // Consumers of the shared main thread context aren't CompositingModeWatchers, + // so inform them about the context loss due to switching to software + // compositing. + OnLostMainThreadSharedContext(); + // Reemove the FrameSink from every compositor that needs to fall back to // software compositing. for (ui::Compositor* compositor : GetAllCompositors()) { @@ -400,7 +401,7 @@ if (worker_context_provider_ && IsWorkerContextLost(worker_context_provider_.get())) - worker_context_provider_ = nullptr; + worker_context_provider_.reset(); if (!worker_context_provider_) { constexpr bool kSharedWorkerContextSupportsLocking = true; @@ -422,14 +423,14 @@ // when recreating LayerTreeFrameSink(s). auto context_result = worker_context_provider_->BindToCurrentThread(); if (context_result != gpu::ContextResult::kSuccess) { - worker_context_provider_ = nullptr; + worker_context_provider_.reset(); return context_result; } } if (main_context_provider_ && IsContextLost(main_context_provider_.get())) { main_context_provider_->RemoveObserver(this); - main_context_provider_ = nullptr; + main_context_provider_.reset(); } if (!main_context_provider_) { @@ -447,8 +448,7 @@ auto context_result = main_context_provider_->BindToCurrentThread(); if (context_result != gpu::ContextResult::kSuccess) { - worker_context_provider_ = nullptr; - main_context_provider_ = nullptr; + main_context_provider_.reset(); return context_result; } @@ -463,7 +463,7 @@ // OnEstablishedGpuChannel(), so check if it's lost before resetting here. if (main_context_provider_ && IsContextLost(main_context_provider_.get())) { main_context_provider_->RemoveObserver(this); - main_context_provider_ = nullptr; + main_context_provider_.reset(); } for (auto& observer : observer_list_)
diff --git a/content/browser/renderer_host/render_process_host_impl.cc b/content/browser/renderer_host/render_process_host_impl.cc index e07459a..4e81b65 100644 --- a/content/browser/renderer_host/render_process_host_impl.cc +++ b/content/browser/renderer_host/render_process_host_impl.cc
@@ -2787,6 +2787,7 @@ switches::kDisableLogging, switches::kDisableMediaSuspend, switches::kDisableNotifications, + switches::kDisableOopRasterization, switches::kDisableOriginTrialControlledBlinkFeatures, switches::kDisablePepper3DImageChromium, switches::kDisablePermissionsAPI, @@ -2816,6 +2817,7 @@ switches::kEnableLCDText, switches::kEnableLogging, switches::kEnableNetworkInformationDownlinkMax, + switches::kEnableOopRasterization, switches::kEnablePluginPlaceholderTesting, switches::kEnablePreciseMemoryInfo, switches::kEnablePrintBrowser,
diff --git a/content/browser/renderer_host/render_widget_host_view_aura.cc b/content/browser/renderer_host/render_widget_host_view_aura.cc index e78fc2b..c9e67f81 100644 --- a/content/browser/renderer_host/render_widget_host_view_aura.cc +++ b/content/browser/renderer_host/render_widget_host_view_aura.cc
@@ -2389,6 +2389,16 @@ if (!region) return; + // Do not notify of change unless selection or caret is visible. + if (region->anchor == region->focus) { + // If selection is collapsed, check to see if user is editing (caret will be + // visible). + const TextInputState* state = GetTextInputManager()->GetTextInputState(); + if (!state || (state->type == ui::TEXT_INPUT_TYPE_NONE && + state->mode == ui::TEXT_INPUT_MODE_NONE)) + return; + } + const gfx::Rect caret_rect = ConvertRectToScreen(gfx::Rect( region->focus.edge_top_rounded().x(), region->focus.edge_top_rounded().y(), 1, region->focus.GetHeight()));
diff --git a/content/browser/web_package/signed_exchange_handler.cc b/content/browser/web_package/signed_exchange_handler.cc index b068987c..a148b07 100644 --- a/content/browser/web_package/signed_exchange_handler.cc +++ b/content/browser/web_package/signed_exchange_handler.cc
@@ -322,7 +322,7 @@ int result = cert_verifier->Verify( net::CertVerifier::RequestParams( unverified_cert_chain_->cert(), envelope_->request_url().host(), - config.GetCertVerifyFlags(), unverified_cert_chain_->ocsp(), + 0 /* cert_verify_flags */, unverified_cert_chain_->ocsp(), net::CertificateList()), net::SSLConfigService::GetCRLSet().get(), &cert_verify_result_, base::BindRepeating(&SignedExchangeHandler::OnCertVerifyComplete,
diff --git a/content/browser/web_package/signed_exchange_handler_unittest.cc b/content/browser/web_package/signed_exchange_handler_unittest.cc index d41021f..fb6b81b 100644 --- a/content/browser/web_package/signed_exchange_handler_unittest.cc +++ b/content/browser/web_package/signed_exchange_handler_unittest.cc
@@ -124,6 +124,7 @@ net::CertVerifyResult* verify_result, std::unique_ptr<net::CertVerifier::Request>* out_req, const net::NetLogWithSource& net_log)); + MOCK_METHOD1(SetConfig, void(const net::CertVerifier::Config& config)); }; class MockCTVerifier : public net::CTVerifier {
diff --git a/content/browser/webauth/authenticator_impl.cc b/content/browser/webauth/authenticator_impl.cc index 04da603..b6565e1f 100644 --- a/content/browser/webauth/authenticator_impl.cc +++ b/content/browser/webauth/authenticator_impl.cc
@@ -452,9 +452,6 @@ DCHECK(make_credential_response_callback_.is_null()); make_credential_response_callback_ = std::move(callback); - request_delegate_->DidStartRequest( - base::BindOnce(&AuthenticatorImpl::Cancel, - weak_factory_.GetWeakPtr()) /* cancel_callback */); timer_->Start( FROM_HERE, options->adjusted_timeout, @@ -496,6 +493,13 @@ weak_factory_.GetWeakPtr()), base::BindOnce(&AuthenticatorImpl::CreatePlatformAuthenticatorIfAvailable, base::Unretained(this))); + + request_delegate_->RegisterActionCallbacks( + base::BindOnce(&AuthenticatorImpl::Cancel, + weak_factory_.GetWeakPtr()) /* cancel_callback */, + base::BindRepeating( + &device::FidoRequestHandlerBase::StartAuthenticatorRequest, + request_->GetWeakPtr()) /* request_callback */); request_->set_observer(request_delegate_.get()); } @@ -549,9 +553,6 @@ DCHECK(get_assertion_response_callback_.is_null()); get_assertion_response_callback_ = std::move(callback); - request_delegate_->DidStartRequest( - base::BindOnce(&AuthenticatorImpl::Cancel, - weak_factory_.GetWeakPtr()) /* cancel_callback */); timer_->Start( FROM_HERE, options->adjusted_timeout, @@ -575,6 +576,13 @@ weak_factory_.GetWeakPtr()), base::BindOnce(&AuthenticatorImpl::CreatePlatformAuthenticatorIfAvailable, base::Unretained(this))); + + request_delegate_->RegisterActionCallbacks( + base::BindOnce(&AuthenticatorImpl::Cancel, + weak_factory_.GetWeakPtr()) /* cancel_callback */, + base::BindRepeating( + &device::FidoRequestHandlerBase::StartAuthenticatorRequest, + request_->GetWeakPtr()) /* request_callback */); request_->set_observer(request_delegate_.get()); }
diff --git a/content/browser/webauth/authenticator_impl_unittest.cc b/content/browser/webauth/authenticator_impl_unittest.cc index 8208ae3..9fec26df 100644 --- a/content/browser/webauth/authenticator_impl_unittest.cc +++ b/content/browser/webauth/authenticator_impl_unittest.cc
@@ -1104,20 +1104,25 @@ class TestAuthenticatorRequestDelegate : public AuthenticatorRequestClientDelegate { public: - TestAuthenticatorRequestDelegate(RenderFrameHost* render_frame_host, - base::OnceClosure did_start_request_callback, - IndividualAttestation individual_attestation, - AttestationConsent attestation_consent, - bool is_focused) - : did_start_request_callback_(std::move(did_start_request_callback)), + TestAuthenticatorRequestDelegate( + RenderFrameHost* render_frame_host, + base::OnceClosure action_callbacks_registered_callback, + IndividualAttestation individual_attestation, + AttestationConsent attestation_consent, + bool is_focused) + : action_callbacks_registered_callback_( + std::move(action_callbacks_registered_callback)), individual_attestation_(individual_attestation), attestation_consent_(attestation_consent), is_focused_(is_focused) {} ~TestAuthenticatorRequestDelegate() override {} - void DidStartRequest(base::OnceClosure cancel_callback) override { - ASSERT_TRUE(did_start_request_callback_) << "DidStartRequest called twice."; - std::move(did_start_request_callback_).Run(); + void RegisterActionCallbacks(base::OnceClosure cancel_callback, + device::FidoRequestHandlerBase::RequestCallback + request_callback) override { + ASSERT_TRUE(action_callbacks_registered_callback_) + << "RegisterActionCallbacks called twice."; + std::move(action_callbacks_registered_callback_).Run(); } bool ShouldPermitIndividualAttestation( @@ -1134,7 +1139,7 @@ bool IsFocused() override { return is_focused_; } - base::OnceClosure did_start_request_callback_; + base::OnceClosure action_callbacks_registered_callback_; const IndividualAttestation individual_attestation_; const AttestationConsent attestation_consent_; const bool is_focused_; @@ -1152,8 +1157,9 @@ return nullptr; return std::make_unique<TestAuthenticatorRequestDelegate>( render_frame_host, - request_started_callback ? std::move(request_started_callback) - : base::DoNothing(), + action_callbacks_registered_callback + ? std::move(action_callbacks_registered_callback) + : base::DoNothing(), individual_attestation, attestation_consent, is_focused); } @@ -1167,7 +1173,7 @@ // If set, this closure will be called when the subsequently constructed // delegate is informed that the request has started. - base::OnceClosure request_started_callback; + base::OnceClosure action_callbacks_registered_callback; IndividualAttestation individual_attestation = IndividualAttestation::NOT_REQUESTED; @@ -1565,7 +1571,8 @@ GetTestPublicKeyCredentialCreationOptions(); TestRequestStartedCallback request_started; - test_client_.request_started_callback = request_started.callback(); + test_client_.action_callbacks_registered_callback = + request_started.callback(); authenticator->MakeCredential(std::move(options), base::DoNothing()); request_started.WaitForCallback(); } @@ -1580,7 +1587,8 @@ GetTestPublicKeyCredentialRequestOptions(); TestRequestStartedCallback request_started; - test_client_.request_started_callback = request_started.callback(); + test_client_.action_callbacks_registered_callback = + request_started.callback(); authenticator->GetAssertion(std::move(options), base::DoNothing()); request_started.WaitForCallback(); } @@ -1601,7 +1609,8 @@ TestMakeCredentialCallback cb; TestRequestStartedCallback request_started; - test_client_.request_started_callback = request_started.callback(); + test_client_.action_callbacks_registered_callback = + request_started.callback(); authenticator->MakeCredential(std::move(options), cb.callback()); cb.WaitForCallback(); @@ -1627,7 +1636,8 @@ TestGetAssertionCallback cb; TestRequestStartedCallback request_started; - test_client_.request_started_callback = request_started.callback(); + test_client_.action_callbacks_registered_callback = + request_started.callback(); authenticator->GetAssertion(std::move(options), cb.callback()); cb.WaitForCallback(); @@ -1750,7 +1760,8 @@ MOCK_METHOD1( OnTransportAvailabilityEnumerated, void(device::FidoRequestHandlerBase::TransportAvailabilityInfo data)); - MOCK_METHOD1(FidoAuthenticatorAdded, void(const device::FidoAuthenticator&)); + MOCK_METHOD2(FidoAuthenticatorAdded, + void(const device::FidoAuthenticator&, bool*)); MOCK_METHOD1(FidoAuthenticatorRemoved, void(base::StringPiece)); private: @@ -1863,7 +1874,7 @@ EXPECT_CALL(*mock_delegate_ptr, OnTransportAvailabilityEnumerated(_)); base::RunLoop ble_device_found_done; - EXPECT_CALL(*mock_delegate_ptr, FidoAuthenticatorAdded(_)) + EXPECT_CALL(*mock_delegate_ptr, FidoAuthenticatorAdded(_, _)) .WillOnce(testing::InvokeWithoutArgs( [&ble_device_found_done]() { ble_device_found_done.Quit(); }));
diff --git a/content/child/child_thread_impl.cc b/content/child/child_thread_impl.cc index 408e3795..f797ee88 100644 --- a/content/child/child_thread_impl.cc +++ b/content/child/child_thread_impl.cc
@@ -21,7 +21,6 @@ #include "base/message_loop/timer_slack.h" #include "base/metrics/field_trial.h" #include "base/metrics/histogram_macros.h" -#include "base/no_destructor.h" #include "base/optional.h" #include "base/process/process.h" #include "base/process/process_handle.h" @@ -78,26 +77,9 @@ #include "content/public/common/content_descriptors.h" #endif -#if defined(CLANG_COVERAGE) -extern "C" int __llvm_profile_dump(void); -#endif - namespace content { namespace { -void WriteClangCoverageProfile() { -#if defined(CLANG_COVERAGE) - // __llvm_profile_dump() guarantees that it will not dump coverage information - // if it is being called twice or more. However, it is not thread safe, as it - // is supposed to be called from atexit() handler rather than being called - // directly from random places. Since we have to call it ourselves, we must - // ensure thread safety in order to prevent duplication of coverage counters. - static base::NoDestructor<base::Lock> lock; - base::AutoLock auto_lock(*lock); - __llvm_profile_dump(); -#endif -} - // How long to wait for a connection to the browser process before giving up. const int kConnectionTimeoutS = 15; @@ -112,8 +94,8 @@ #if defined(ADDRESS_SANITIZER) || defined(LEAK_SANITIZER) || \ defined(MEMORY_SANITIZER) || defined(THREAD_SANITIZER) || \ defined(UNDEFINED_SANITIZER) -// A thread delegate that waits for |duration| and then exits the process with -// _exit(0). +// A thread delegate that waits for |duration| and then exits the process +// immediately, without executing finalizers. class WaitAndExitDelegate : public base::PlatformThread::Delegate { public: explicit WaitAndExitDelegate(base::TimeDelta duration) @@ -121,8 +103,7 @@ void ThreadMain() override { base::PlatformThread::Sleep(duration_); - WriteClangCoverageProfile(); - _exit(0); + base::Process::TerminateCurrentProcessImmediately(0); } private: @@ -182,8 +163,7 @@ __lsan_do_leak_check(); #endif #else - WriteClangCoverageProfile(); - _exit(0); + base::Process::TerminateCurrentProcessImmediately(0); #endif } @@ -649,12 +629,7 @@ g_lazy_tls.Pointer()->Set(nullptr); } -void ChildThreadImpl::Shutdown() { - // The renderer process (and others) can to fast shutdown by calling _exit(0), - // in which case the clang-coverage profile does not get written to the file. - // So force write the profile here before shutting down. - WriteClangCoverageProfile(); -} +void ChildThreadImpl::Shutdown() {} bool ChildThreadImpl::ShouldBeDestroyed() { return true;
diff --git a/content/common/sandbox_policy_fuchsia.cc b/content/common/sandbox_policy_fuchsia.cc index 7080c3b..3564f89 100644 --- a/content/common/sandbox_policy_fuchsia.cc +++ b/content/common/sandbox_policy_fuchsia.cc
@@ -28,8 +28,10 @@ SandboxPolicyFuchsia::SandboxPolicyFuchsia() = default; SandboxPolicyFuchsia::~SandboxPolicyFuchsia() { - service_directory_task_runner_->DeleteSoon(FROM_HERE, - std::move(service_directory_)); + if (service_directory_) { + service_directory_task_runner_->DeleteSoon(FROM_HERE, + std::move(service_directory_)); + } } void SandboxPolicyFuchsia::Initialize(service_manager::SandboxType type) {
diff --git a/content/public/browser/authenticator_request_client_delegate.cc b/content/public/browser/authenticator_request_client_delegate.cc index eca877b7..8275010 100644 --- a/content/public/browser/authenticator_request_client_delegate.cc +++ b/content/public/browser/authenticator_request_client_delegate.cc
@@ -16,8 +16,9 @@ AuthenticatorRequestClientDelegate::~AuthenticatorRequestClientDelegate() = default; -void AuthenticatorRequestClientDelegate::DidStartRequest( - base::OnceClosure cancel_callback) {} +void AuthenticatorRequestClientDelegate::RegisterActionCallbacks( + base::OnceClosure cancel_callback, + device::FidoRequestHandlerBase::RequestCallback request_callback) {} bool AuthenticatorRequestClientDelegate::ShouldPermitIndividualAttestation( const std::string& relying_party_id) { @@ -51,7 +52,8 @@ bool is_powered_on) {} void AuthenticatorRequestClientDelegate::FidoAuthenticatorAdded( - const device::FidoAuthenticator& authenticator) {} + const device::FidoAuthenticator& authenticator, + bool* hold_off_request) {} void AuthenticatorRequestClientDelegate::FidoAuthenticatorRemoved( base::StringPiece device_id) {}
diff --git a/content/public/browser/authenticator_request_client_delegate.h b/content/public/browser/authenticator_request_client_delegate.h index 39a5277..0fc7278 100644 --- a/content/public/browser/authenticator_request_client_delegate.h +++ b/content/public/browser/authenticator_request_client_delegate.h
@@ -32,8 +32,12 @@ AuthenticatorRequestClientDelegate(); ~AuthenticatorRequestClientDelegate() override; - // Notifies the delegate that the request is actually starting. - virtual void DidStartRequest(base::OnceClosure cancel_callback); + // Supplies callbacks that the embedder can invoke to initiate certain + // actions, namely: initiate BLE pairing process, cancel WebAuthN request, and + // dispatch request to connected authenticators. + virtual void RegisterActionCallbacks( + base::OnceClosure cancel_callback, + device::FidoRequestHandlerBase::RequestCallback request_callback); // Returns true if the given relying party ID is permitted to receive // individual attestation certificates. This: @@ -91,8 +95,8 @@ void OnTransportAvailabilityEnumerated( device::FidoRequestHandlerBase::TransportAvailabilityInfo data) override; void BluetoothAdapterPowerChanged(bool is_powered_on) override; - void FidoAuthenticatorAdded( - const device::FidoAuthenticator& authenticator) override; + void FidoAuthenticatorAdded(const device::FidoAuthenticator& authenticator, + bool* hold_off_request) override; void FidoAuthenticatorRemoved(base::StringPiece device_id) override; private:
diff --git a/content/public/common/content_features.cc b/content/public/common/content_features.cc index 89da7bd..8c8367e5 100644 --- a/content/public/common/content_features.cc +++ b/content/public/common/content_features.cc
@@ -271,6 +271,13 @@ #endif }; +// A secondary switch used in combination with kMojoVideoCapture. +// This is intended as a kill switch to allow disabling the service on +// particular groups of devices even if they forcibly enable kMojoVideoCapture +// via a command-line argument. +const base::Feature kMojoVideoCaptureSecondary{ + "MojoVideoCaptureSecondary", base::FEATURE_ENABLED_BY_DEFAULT}; + // If the network service is enabled, runs it in process. const base::Feature kNetworkServiceInProcess{"NetworkServiceInProcess", base::FEATURE_DISABLED_BY_DEFAULT}; @@ -505,11 +512,7 @@ // https://w3c.github.io/webauthn const base::Feature kWebAuth { "WebAuthentication", -#if defined(OS_ANDROID) - base::FEATURE_DISABLED_BY_DEFAULT -#else base::FEATURE_ENABLED_BY_DEFAULT -#endif }; // Controls whether BLE authenticators can be used via the WebAuthentication @@ -691,8 +694,13 @@ kDisabled }; +bool ShouldEnableVideoCaptureService() { + return base::FeatureList::IsEnabled(features::kMojoVideoCapture) && + base::FeatureList::IsEnabled(features::kMojoVideoCaptureSecondary); +} + VideoCaptureServiceConfiguration GetVideoCaptureServiceConfiguration() { - if (!base::FeatureList::IsEnabled(features::kMojoVideoCapture)) + if (!ShouldEnableVideoCaptureService()) return VideoCaptureServiceConfiguration::kDisabled; #if defined(OS_ANDROID)
diff --git a/content/public/common/content_features.h b/content/public/common/content_features.h index c3dcac0..ae18650 100644 --- a/content/public/common/content_features.h +++ b/content/public/common/content_features.h
@@ -69,6 +69,7 @@ CONTENT_EXPORT extern const base::Feature kModuleScriptsImportMetaUrl; CONTENT_EXPORT extern const base::Feature kMojoSessionStorage; CONTENT_EXPORT extern const base::Feature kMojoVideoCapture; +CONTENT_EXPORT extern const base::Feature kMojoVideoCaptureSecondary; CONTENT_EXPORT extern const base::Feature kNetworkServiceInProcess; CONTENT_EXPORT extern const base::Feature kNotificationContentImage; CONTENT_EXPORT extern const base::Feature kOriginPolicy;
diff --git a/content/public/test/browser_test_base.cc b/content/public/test/browser_test_base.cc index eb8f5ad5..5b84ebd 100644 --- a/content/public/test/browser_test_base.cc +++ b/content/public/test/browser_test_base.cc
@@ -492,6 +492,20 @@ // For now, this covers all the rules used in content's tests. // TODO(jam: expand this when we try to make browser_tests and // components_browsertests work. + if (rule.resolver_type == + net::RuleBasedHostResolverProc::Rule::kResolverTypeFail) { + // The host "wpad" is added automatically in TestHostResolver, so we don't + // need to send it to NetworkServiceTest. + if (rule.host_pattern != "wpad") { + network::mojom::RulePtr mojo_rule = network::mojom::Rule::New(); + mojo_rule->resolver_type = + network::mojom::ResolverType::kResolverTypeFail; + mojo_rule->host_pattern = rule.host_pattern; + mojo_rules.push_back(std::move(mojo_rule)); + } + continue; + } + if ((rule.resolver_type != net::RuleBasedHostResolverProc::Rule::kResolverTypeSystem && rule.resolver_type != @@ -500,6 +514,14 @@ !!rule.latency_ms || rule.replacement.empty()) continue; network::mojom::RulePtr mojo_rule = network::mojom::Rule::New(); + if (rule.resolver_type == + net::RuleBasedHostResolverProc::Rule::kResolverTypeSystem) { + mojo_rule->resolver_type = + network::mojom::ResolverType::kResolverTypeSystem; + } else { + mojo_rule->resolver_type = + network::mojom::ResolverType::kResolverTypeIPLiteral; + } mojo_rule->host_pattern = rule.host_pattern; mojo_rule->replacement = rule.replacement; mojo_rules.push_back(std::move(mojo_rule));
diff --git a/content/public/test/network_service_test_helper.cc b/content/public/test/network_service_test_helper.cc index 812c837..2d81fbb5a 100644 --- a/content/public/test/network_service_test_helper.cc +++ b/content/public/test/network_service_test_helper.cc
@@ -40,6 +40,19 @@ namespace content { namespace { + +#define STATIC_ASSERT_ENUM(a, b) \ + static_assert(static_cast<int>(a) == static_cast<int>(b), \ + "mismatching enums: " #a) + +STATIC_ASSERT_ENUM(network::mojom::ResolverType::kResolverTypeFail, + net::RuleBasedHostResolverProc::Rule::kResolverTypeFail); +STATIC_ASSERT_ENUM(network::mojom::ResolverType::kResolverTypeSystem, + net::RuleBasedHostResolverProc::Rule::kResolverTypeSystem); +STATIC_ASSERT_ENUM( + network::mojom::ResolverType::kResolverTypeIPLiteral, + net::RuleBasedHostResolverProc::Rule::kResolverTypeIPLiteral); + void CrashResolveHost(const std::string& host_to_crash, const std::string& host) { if (host_to_crash == host) @@ -68,8 +81,14 @@ void AddRules(std::vector<network::mojom::RulePtr> rules, AddRulesCallback callback) override { for (const auto& rule : rules) { - test_host_resolver_.host_resolver()->AddRule(rule->host_pattern, - rule->replacement); + if (rule->resolver_type == + network::mojom::ResolverType::kResolverTypeFail) { + test_host_resolver_.host_resolver()->AddSimulatedFailure( + rule->host_pattern); + } else { + test_host_resolver_.host_resolver()->AddRule(rule->host_pattern, + rule->replacement); + } } std::move(callback).Run(); }
diff --git a/content/renderer/pepper/pepper_plugin_instance_impl.cc b/content/renderer/pepper/pepper_plugin_instance_impl.cc index e2491c2..894124ac 100644 --- a/content/renderer/pepper/pepper_plugin_instance_impl.cc +++ b/content/renderer/pepper/pepper_plugin_instance_impl.cc
@@ -2655,20 +2655,19 @@ // them. if (find_identifier_ == -1) return; - if (render_frame_) { - render_frame_->GetWebFrame()->ReportFindInPageMatchCount( - find_identifier_, total, PP_ToBool(final_result)); - } + if (!container_) + return; + container_->ReportFindInPageMatchCount(find_identifier_, total, + PP_ToBool(final_result)); } void PepperPluginInstanceImpl::SelectedFindResultChanged(PP_Instance instance, int32_t index) { if (find_identifier_ == -1) return; - if (render_frame_ && render_frame_->GetWebFrame()) { - render_frame_->GetWebFrame()->ReportFindInPageSelection( - find_identifier_, index + 1, blink::WebRect(), false /* final_update*/); - } + if (!container_) + return; + container_->ReportFindInPageSelection(find_identifier_, index + 1); } void PepperPluginInstanceImpl::SetTickmarks(PP_Instance instance,
diff --git a/content/shell/android/browsertests_apk/AndroidManifest.xml.jinja2 b/content/shell/android/browsertests_apk/AndroidManifest.xml.jinja2 index cd48452..03ae460c3 100644 --- a/content/shell/android/browsertests_apk/AndroidManifest.xml.jinja2 +++ b/content/shell/android/browsertests_apk/AndroidManifest.xml.jinja2
@@ -62,5 +62,6 @@ <instrumentation android:name="org.chromium.native_test.NativeTestInstrumentationTestRunner" android:label="ContentBrowserTests" - android:targetPackage="org.chromium.content_browsertests_apk"/> + android:targetPackage="org.chromium.content_browsertests_apk" + chromium-junit3="true"/> </manifest>
diff --git a/content/shell/android/javatests/AndroidManifest.xml b/content/shell/android/javatests/AndroidManifest.xml index 5539636..496e46c 100644 --- a/content/shell/android/javatests/AndroidManifest.xml +++ b/content/shell/android/javatests/AndroidManifest.xml
@@ -19,6 +19,5 @@ <instrumentation android:name="org.chromium.base.test.BaseChromiumAndroidJUnitRunner" android:targetPackage="org.chromium.content_shell_apk" - chromium-junit4="true" android:label="JUnit4-based tests for org.chromium.content_shell_apk" /> </manifest>
diff --git a/content/shell/browser/layout_test/layout_test_background_fetch_delegate.cc b/content/shell/browser/layout_test/layout_test_background_fetch_delegate.cc index c58dc94..4aa72c2 100644 --- a/content/shell/browser/layout_test/layout_test_background_fetch_delegate.cc +++ b/content/shell/browser/layout_test/layout_test_background_fetch_delegate.cc
@@ -17,6 +17,7 @@ #include "content/public/browser/background_fetch_response.h" #include "content/public/browser/browser_context.h" #include "content/public/browser/browser_thread.h" +#include "content/public/browser/network_service_instance.h" #include "net/traffic_annotation/network_traffic_annotation.h" #include "services/network/public/cpp/resource_request_body.h" #include "ui/gfx/geometry/size.h" @@ -206,7 +207,8 @@ download_service_ = base::WrapUnique(download::BuildInMemoryDownloadService( - browser_context_, std::move(clients), base::FilePath(), + browser_context_, std::move(clients), + GetNetworkConnectionTracker(), base::FilePath(), BrowserContext::GetBlobStorageContext(browser_context_), BrowserThread::GetTaskRunnerForThread(BrowserThread::IO))); }
diff --git a/device/fido/fido_request_handler_base.cc b/device/fido/fido_request_handler_base.cc index b1a7a6d..e6c04bf0 100644 --- a/device/fido/fido_request_handler_base.cc +++ b/device/fido/fido_request_handler_base.cc
@@ -19,16 +19,6 @@ namespace device { -namespace { - -bool ShouldDeferRequestDispatchToUi(const FidoAuthenticator& authenticator) { - // TODO(hongjunchoi): Change this to be dependent on authenticator transport - // type once UI component is in place. - return false; -} - -} // namespace - // FidoRequestHandlerBase::TransportAvailabilityInfo -------------------------- FidoRequestHandlerBase::TransportAvailabilityInfo::TransportAvailabilityInfo() = @@ -111,12 +101,22 @@ transport_availability_info_.available_transports = available_transports; notify_observer_callback_ = base::BarrierClosure( transport_info_callback_count, - base::BindOnce(&FidoRequestHandlerBase::NotifyObserverUiData, - weak_factory_.GetWeakPtr())); + base::BindOnce( + &FidoRequestHandlerBase::NotifyObserverTransportAvailability, + weak_factory_.GetWeakPtr())); } FidoRequestHandlerBase::~FidoRequestHandlerBase() = default; +void FidoRequestHandlerBase::StartAuthenticatorRequest( + const std::string& authenticator_id) { + auto authenticator = active_authenticators_.find(authenticator_id); + if (authenticator == active_authenticators_.end()) + return; + + DispatchRequest(authenticator->second.get()); +} + void FidoRequestHandlerBase::CancelOngoingTasks( base::StringPiece exclude_device_id) { for (auto task_it = active_authenticators_.begin(); @@ -132,11 +132,22 @@ } } +base::WeakPtr<FidoRequestHandlerBase> FidoRequestHandlerBase::GetWeakPtr() { + return weak_factory_.GetWeakPtr(); +} + void FidoRequestHandlerBase::Start() { for (const auto& discovery : discoveries_) discovery->Start(); - MaybeAddPlatformAuthenticator(); + // Post |MaybeAddPlatformAuthenticator| into its own task. This avoids + // FidoAuthenticatorAdded() to be called synchronously from the constructor of + // FidoRequestHandlerBase prior to any TransportAvailabilityObserver being + // set. + base::SequencedTaskRunnerHandle::Get()->PostTask( + FROM_HERE, + base::BindOnce(&FidoRequestHandlerBase::MaybeAddPlatformAuthenticator, + weak_factory_.GetWeakPtr())); } void FidoRequestHandlerBase::DiscoveryStarted(FidoDiscovery* discovery, @@ -195,16 +206,23 @@ FidoAuthenticator* authenticator_ptr = authenticator.get(); active_authenticators_.emplace(authenticator->GetId(), std::move(authenticator)); - if (!ShouldDeferRequestDispatchToUi(*authenticator_ptr)) { - // Post |DispatchRequest| into its own task. This avoids hairpinning, even - // if the authenticator immediately invokes the request callback. - base::SequencedTaskRunnerHandle::Get()->PostTask( - FROM_HERE, base::BindOnce(&FidoRequestHandlerBase::DispatchRequest, - GetWeakPtr(), authenticator_ptr)); - } + // If |observer_| exists, dispatching request to |authenticator_ptr| is + // delegated to |observer_|. Else, dispatch request to |authenticator_ptr| + // immediately. + bool should_delay_request = false; if (observer_) - observer_->FidoAuthenticatorAdded(*authenticator_ptr); + observer_->FidoAuthenticatorAdded(*authenticator_ptr, + &should_delay_request); + + if (should_delay_request) + return; + + // Post |DispatchRequest| into its own task. This avoids hairpinning, even + // if the authenticator immediately invokes the request callback. + base::SequencedTaskRunnerHandle::Get()->PostTask( + FROM_HERE, base::BindOnce(&FidoRequestHandlerBase::DispatchRequest, + GetWeakPtr(), authenticator_ptr)); } void FidoRequestHandlerBase::MaybeAddPlatformAuthenticator() { @@ -226,9 +244,8 @@ notify_observer_callback_.Run(); } -void FidoRequestHandlerBase::NotifyObserverUiData() { +void FidoRequestHandlerBase::NotifyObserverTransportAvailability() { DCHECK(observer_); - observer_->OnTransportAvailabilityEnumerated(transport_availability_info_); }
diff --git a/device/fido/fido_request_handler_base.h b/device/fido/fido_request_handler_base.h index c923479c..9356a2d 100644 --- a/device/fido/fido_request_handler_base.h +++ b/device/fido/fido_request_handler_base.h
@@ -45,6 +45,7 @@ std::map<std::string, std::unique_ptr<FidoAuthenticator>, std::less<>>; using AddPlatformAuthenticatorCallback = base::OnceCallback<std::unique_ptr<FidoAuthenticator>()>; + using RequestCallback = base::RepeatingCallback<void(const std::string&)>; enum class RequestType { kMakeCredential, kGetAssertion }; @@ -60,6 +61,10 @@ const TransportAvailabilityInfo& other); ~TransportAvailabilityInfo(); + // TODO(hongjunchoi): Factor |rp_id| and |request_type| from + // TransportAvailabilityInfo. + // See: https://crbug.com/875011 + std::string rp_id; RequestType request_type = RequestType::kMakeCredential; // The intersection of transports supported by the client and allowed by the @@ -79,8 +84,8 @@ virtual void OnTransportAvailabilityEnumerated( TransportAvailabilityInfo data) = 0; virtual void BluetoothAdapterPowerChanged(bool is_powered_on) = 0; - virtual void FidoAuthenticatorAdded( - const FidoAuthenticator& authenticator) = 0; + virtual void FidoAuthenticatorAdded(const FidoAuthenticator& authenticator, + bool* hold_off_request) = 0; virtual void FidoAuthenticatorRemoved(base::StringPiece device_id) = 0; }; @@ -97,6 +102,10 @@ AddPlatformAuthenticatorCallback add_platform_authenticator); ~FidoRequestHandlerBase() override; + // Triggers DispatchRequest() if |active_authenticators_| hold + // FidoAuthenticator with given |authenticator_id|. + void StartAuthenticatorRequest(const std::string& authenticator_id); + // Triggers cancellation of all per-device FidoTasks, except for the device // with |exclude_device_id|, if one is provided. Cancelled tasks are // immediately removed from |ongoing_tasks_|. @@ -109,6 +118,8 @@ // https://w3c.github.io/webauthn/#iface-pkcredential void CancelOngoingTasks(base::StringPiece exclude_device_id = nullptr); + base::WeakPtr<FidoRequestHandlerBase> GetWeakPtr(); + void set_observer(TransportAvailabilityObserver* observer) { DCHECK(!observer_) << "Only one observer is supported."; observer_ = observer; @@ -122,8 +133,6 @@ } protected: - virtual base::WeakPtr<FidoRequestHandlerBase> GetWeakPtr() = 0; - // Subclasses implement this method to dispatch their request onto the given // FidoAuthenticator. The FidoAuthenticator is owned by this // FidoRequestHandler and stored in active_authenticators(). @@ -150,7 +159,7 @@ void AddAuthenticator(std::unique_ptr<FidoAuthenticator> authenticator); void MaybeAddPlatformAuthenticator(); - void NotifyObserverUiData(); + void NotifyObserverTransportAvailability(); AuthenticatorMap active_authenticators_; std::vector<std::unique_ptr<FidoDiscovery>> discoveries_;
diff --git a/device/fido/fido_request_handler_unittest.cc b/device/fido/fido_request_handler_unittest.cc index f071f2c2..f4729f0 100644 --- a/device/fido/fido_request_handler_unittest.cc +++ b/device/fido/fido_request_handler_unittest.cc
@@ -72,8 +72,8 @@ } void BluetoothAdapterPowerChanged(bool is_powered_on) override {} - void FidoAuthenticatorAdded(const FidoAuthenticator& authenticator) override { - } + void FidoAuthenticatorAdded(const FidoAuthenticator& authenticator, + bool* hold_off_request) override {} void FidoAuthenticatorRemoved(base::StringPiece device_id) override {} private: @@ -126,7 +126,8 @@ class FakeFidoAuthenticator : public FidoDeviceAuthenticator { public: - FakeFidoAuthenticator(FidoDevice* device) : FidoDeviceAuthenticator(device) {} + explicit FakeFidoAuthenticator(FidoDevice* device) + : FidoDeviceAuthenticator(device) {} void RunFakeTask(FakeTaskCallback callback) { SetTaskForTesting( @@ -150,10 +151,6 @@ } ~FakeFidoRequestHandler() override = default; - base::WeakPtr<FidoRequestHandlerBase> GetWeakPtr() override { - return weak_factory_.GetWeakPtr(); - } - void DispatchRequest(FidoAuthenticator* authenticator) override { static_cast<FakeFidoAuthenticator*>(authenticator) ->RunFakeTask(
diff --git a/device/fido/get_assertion_request_handler.cc b/device/fido/get_assertion_request_handler.cc index b1f6a49..2429c3fe 100644 --- a/device/fido/get_assertion_request_handler.cc +++ b/device/fido/get_assertion_request_handler.cc
@@ -172,6 +172,7 @@ std::move(add_platform_authenticator)), request_(std::move(request)), weak_factory_(this) { + transport_availability_info().rp_id = request.rp_id(); transport_availability_info().request_type = FidoRequestHandlerBase::RequestType::kGetAssertion; @@ -190,10 +191,6 @@ GetAssertionRequestHandler::~GetAssertionRequestHandler() = default; -base::WeakPtr<FidoRequestHandlerBase> GetAssertionRequestHandler::GetWeakPtr() { - return weak_factory_.GetWeakPtr(); -} - void GetAssertionRequestHandler::DispatchRequest( FidoAuthenticator* authenticator) { // The user verification field of the request may be adjusted to the
diff --git a/device/fido/get_assertion_request_handler.h b/device/fido/get_assertion_request_handler.h index 1cf7255..5cc27a2 100644 --- a/device/fido/get_assertion_request_handler.h +++ b/device/fido/get_assertion_request_handler.h
@@ -48,7 +48,6 @@ private: // FidoRequestHandlerBase: - base::WeakPtr<FidoRequestHandlerBase> GetWeakPtr() final; void DispatchRequest(FidoAuthenticator* authenticator) override; void HandleResponse(
diff --git a/device/fido/make_credential_request_handler.cc b/device/fido/make_credential_request_handler.cc index 0212e608..6551a98b 100644 --- a/device/fido/make_credential_request_handler.cc +++ b/device/fido/make_credential_request_handler.cc
@@ -123,6 +123,7 @@ authenticator_selection_criteria_( std::move(authenticator_selection_criteria)), weak_factory_(this) { + transport_availability_info().rp_id = request.rp().rp_id(); transport_availability_info().request_type = FidoRequestHandlerBase::RequestType::kMakeCredential; Start(); @@ -130,11 +131,6 @@ MakeCredentialRequestHandler::~MakeCredentialRequestHandler() = default; -base::WeakPtr<FidoRequestHandlerBase> -MakeCredentialRequestHandler::GetWeakPtr() { - return weak_factory_.GetWeakPtr(); -} - void MakeCredentialRequestHandler::DispatchRequest( FidoAuthenticator* authenticator) { // The user verification field of the request may be adjusted to the
diff --git a/device/fido/make_credential_request_handler.h b/device/fido/make_credential_request_handler.h index 1151dfa..47272c72 100644 --- a/device/fido/make_credential_request_handler.h +++ b/device/fido/make_credential_request_handler.h
@@ -52,7 +52,6 @@ private: // FidoRequestHandlerBase: - base::WeakPtr<FidoRequestHandlerBase> GetWeakPtr() final; void DispatchRequest(FidoAuthenticator* authenticator) final; void HandleResponse(
diff --git a/extensions/browser/api/dns/dns_api.cc b/extensions/browser/api/dns/dns_api.cc index 8fc6557e..ea444b7 100644 --- a/extensions/browser/api/dns/dns_api.cc +++ b/extensions/browser/api/dns/dns_api.cc
@@ -13,9 +13,6 @@ #include "extensions/common/api/dns.h" #include "net/base/host_port_pair.h" #include "net/base/net_errors.h" -#include "net/log/net_log_with_source.h" -#include "net/url_request/url_request_context.h" -#include "net/url_request/url_request_context_getter.h" using content::BrowserThread; using extensions::api::dns::ResolveCallbackResolveInfo; @@ -24,79 +21,51 @@ namespace extensions { -DnsResolveFunction::DnsResolveFunction() - : response_(false), addresses_(new net::AddressList) {} +DnsResolveFunction::DnsResolveFunction() : binding_(this) {} DnsResolveFunction::~DnsResolveFunction() {} ExtensionFunction::ResponseAction DnsResolveFunction::Run() { + DCHECK_CURRENTLY_ON(BrowserThread::UI); std::unique_ptr<Resolve::Params> params(Resolve::Params::Create(*args_)); EXTENSION_FUNCTION_VALIDATE(params.get()); - hostname_ = params->hostname; - url_request_context_getter_ = - content::BrowserContext::GetDefaultStoragePartition(browser_context()) - ->GetURLRequestContext(); - - bool result = BrowserThread::PostTask( - BrowserThread::IO, - FROM_HERE, - base::Bind(&DnsResolveFunction::WorkOnIOThread, this)); - DCHECK(result); - return RespondLater(); -} - -void DnsResolveFunction::WorkOnIOThread() { - DCHECK_CURRENTLY_ON(BrowserThread::IO); - - net::HostResolver* host_resolver = - HostResolverWrapper::GetInstance()->GetHostResolver( - url_request_context_getter_.get()); - DCHECK(host_resolver); - + network::mojom::ResolveHostClientPtr client_ptr; + binding_.Bind(mojo::MakeRequest(&client_ptr)); + binding_.set_connection_error_handler( + base::BindOnce(&DnsResolveFunction::OnComplete, base::Unretained(this), + net::ERR_FAILED, base::nullopt)); // Yes, we are passing zero as the port. There are some interesting but not // presently relevant reasons why HostResolver asks for the port of the // hostname you'd like to resolve, even though it doesn't use that value in // determining its answer. - net::HostPortPair host_port_pair(hostname_, 0); + net::HostPortPair host_port_pair(params->hostname, 0); + content::BrowserContext::GetDefaultStoragePartition(browser_context()) + ->GetNetworkContext() + ->ResolveHost(host_port_pair, nullptr, std::move(client_ptr)); - net::HostResolver::RequestInfo request_info(host_port_pair); - int resolve_result = host_resolver->Resolve( - request_info, net::DEFAULT_PRIORITY, addresses_.get(), - base::Bind(&DnsResolveFunction::OnLookupFinished, this), &request_, - net::NetLogWithSource()); - - // Balanced in OnLookupFinished. + // Balanced in OnComplete(). AddRef(); - - if (resolve_result != net::ERR_IO_PENDING) - OnLookupFinished(resolve_result); + return RespondLater(); } -void DnsResolveFunction::RespondOnUIThread( - std::unique_ptr<base::ListValue> results) { +void DnsResolveFunction::OnComplete( + int result, + const base::Optional<net::AddressList>& resolved_addresses) { DCHECK_CURRENTLY_ON(BrowserThread::UI); - Respond(response_ ? ArgumentList(std::move(results)) - : Error(kUnknownErrorDoNotUse)); -} + binding_.Close(); -void DnsResolveFunction::OnLookupFinished(int resolve_result) { - auto resolve_info = std::make_unique<ResolveCallbackResolveInfo>(); - resolve_info->result_code = resolve_result; - if (resolve_result == net::OK) { - DCHECK(!addresses_->empty()); - resolve_info->address.reset( - new std::string(addresses_->front().ToStringWithoutPort())); + ResolveCallbackResolveInfo resolve_info; + resolve_info.result_code = result; + if (result == net::OK) { + DCHECK(resolved_addresses.has_value() && !resolved_addresses->empty()); + resolve_info.address = std::make_unique<std::string>( + resolved_addresses->front().ToStringWithoutPort()); } - response_ = true; - bool post_task_result = BrowserThread::PostTask( - BrowserThread::UI, FROM_HERE, - base::BindOnce(&DnsResolveFunction::RespondOnUIThread, this, - Resolve::Results::Create(*resolve_info))); - DCHECK(post_task_result); + Respond(ArgumentList(Resolve::Results::Create(resolve_info))); - Release(); // Added in WorkOnIOThread(). + Release(); // Added in Run(). } } // namespace extensions
diff --git a/extensions/browser/api/dns/dns_api.h b/extensions/browser/api/dns/dns_api.h index e301fd2..72c26740 100644 --- a/extensions/browser/api/dns/dns_api.h +++ b/extensions/browser/api/dns/dns_api.h
@@ -8,17 +8,16 @@ #include <string> #include "extensions/browser/extension_function.h" +#include "mojo/public/cpp/bindings/binding.h" #include "net/base/address_list.h" #include "net/base/completion_callback.h" #include "net/dns/host_resolver.h" - -namespace net { -class URLRequestContextGetter; -} +#include "services/network/public/mojom/network_context.mojom.h" namespace extensions { -class DnsResolveFunction : public UIThreadExtensionFunction { +class DnsResolveFunction : public UIThreadExtensionFunction, + public network::mojom::ResolveHostClient { public: DECLARE_EXTENSION_FUNCTION("dns.resolve", DNS_RESOLVE) @@ -31,19 +30,14 @@ ResponseAction Run() override; private: - void WorkOnIOThread(); - void RespondOnUIThread(std::unique_ptr<base::ListValue> results); + // network::mojom::ResolveHostClient implementation: + void OnComplete( + int result, + const base::Optional<net::AddressList>& resolved_addresses) override; - void OnLookupFinished(int result); - - std::string hostname_; - - scoped_refptr<net::URLRequestContextGetter> url_request_context_getter_; - - bool response_; // The value sent in SendResponse(). - - std::unique_ptr<net::HostResolver::Request> request_; - std::unique_ptr<net::AddressList> addresses_; + // A reference to |this| must be taken while the request is being made on this + // binding so the object is alive when the request completes. + mojo::Binding<network::mojom::ResolveHostClient> binding_; }; } // namespace extensions
diff --git a/extensions/browser/api/dns/dns_apitest.cc b/extensions/browser/api/dns/dns_apitest.cc index 2080808b..689a12bd 100644 --- a/extensions/browser/api/dns/dns_apitest.cc +++ b/extensions/browser/api/dns/dns_apitest.cc
@@ -9,40 +9,29 @@ #include "content/public/browser/notification_service.h" #include "content/public/test/test_utils.h" #include "extensions/browser/api/dns/dns_api.h" -#include "extensions/browser/api/dns/host_resolver_wrapper.h" -#include "extensions/browser/api/dns/mock_host_resolver_creator.h" #include "extensions/browser/api_test_utils.h" #include "extensions/browser/notification_types.h" #include "extensions/common/extension.h" #include "extensions/common/extension_builder.h" #include "extensions/shell/test/shell_apitest.h" #include "net/base/net_errors.h" - -using extensions::api_test_utils::RunFunctionAndReturnSingleResult; +#include "net/dns/mock_host_resolver.h" namespace extensions { +namespace { +using extensions::api_test_utils::RunFunctionAndReturnSingleResult; + +constexpr char kHostname[] = "www.sowbug.com"; +constexpr char kAddress[] = "9.8.7.6"; +} // namespace class DnsApiTest : public ShellApiTest { - public: - DnsApiTest() : resolver_creator_(new MockHostResolverCreator()) {} - private: void SetUpOnMainThread() override { ShellApiTest::SetUpOnMainThread(); - HostResolverWrapper::GetInstance()->SetHostResolverForTesting( - resolver_creator_->CreateMockHostResolver()); + host_resolver()->AddRule(kHostname, kAddress); + host_resolver()->AddSimulatedFailure("this.hostname.is.bogus"); } - - void TearDownOnMainThread() override { - HostResolverWrapper::GetInstance()->SetHostResolverForTesting(NULL); - resolver_creator_->DeleteMockHostResolver(); - ShellApiTest::TearDownOnMainThread(); - } - - // The MockHostResolver asserts that it's used on the same thread on which - // it's created, which is actually a stronger rule than its real counterpart. - // But that's fine; it's good practice. - scoped_refptr<MockHostResolverCreator> resolver_creator_; }; IN_PROC_BROWSER_TEST_F(DnsApiTest, DnsResolveIPLiteral) { @@ -74,7 +63,7 @@ resolve_function->set_has_callback(true); std::string function_arguments("[\""); - function_arguments += MockHostResolverCreator::kHostname; + function_arguments += kHostname; function_arguments += "\"]"; std::unique_ptr<base::Value> result(RunFunctionAndReturnSingleResult( resolve_function.get(), function_arguments, browser_context())); @@ -87,7 +76,7 @@ std::string address; EXPECT_TRUE(dict->GetString("address", &address)); - EXPECT_EQ(MockHostResolverCreator::kAddress, address); + EXPECT_EQ(kAddress, address); } IN_PROC_BROWSER_TEST_F(DnsApiTest, DnsExtension) {
diff --git a/extensions/browser/api/feedback_private/feedback_private_api.cc b/extensions/browser/api/feedback_private/feedback_private_api.cc index ac029ad832..dcc9c8f 100644 --- a/extensions/browser/api/feedback_private/feedback_private_api.cc +++ b/extensions/browser/api/feedback_private/feedback_private_api.cc
@@ -313,10 +313,12 @@ delegate->FetchAndMergeIwlwifiDumpLogsIfPresent( std::move(sys_logs), browser_context(), base::Bind(&FeedbackPrivateSendFeedbackFunction::OnAllLogsFetched, this, - feedback_data, feedback_info.send_histograms)); + feedback_data, feedback_info.send_histograms, + feedback_info.send_bluetooth_logs && + *feedback_info.send_bluetooth_logs)); #else OnAllLogsFetched(feedback_data, feedback_info.send_histograms, - std::move(sys_logs)); + false /* send_bluetooth_logs */, std::move(sys_logs)); #endif // defined(OS_CHROMEOS) return RespondLater(); @@ -325,6 +327,7 @@ void FeedbackPrivateSendFeedbackFunction::OnAllLogsFetched( scoped_refptr<FeedbackData> feedback_data, bool send_histograms, + bool send_bluetooth_logs, std::unique_ptr<system_logs::SystemLogsResponse> sys_logs) { feedback_data->SetAndCompressSystemInfo(std::move(sys_logs)); @@ -341,6 +344,11 @@ feedback_data->SetAndCompressHistograms(std::move(histograms)); } + if (send_bluetooth_logs) { + // TODO(rkc): Implement this once the platforms changes land. + LOG(WARNING) << "Not sending Bluetooth logs. Not implemented yet."; + } + service->SendFeedback( feedback_data, base::Bind(&FeedbackPrivateSendFeedbackFunction::OnCompleted, this,
diff --git a/extensions/browser/api/feedback_private/feedback_private_api.h b/extensions/browser/api/feedback_private/feedback_private_api.h index 6944526..ca14c38f 100644 --- a/extensions/browser/api/feedback_private/feedback_private_api.h +++ b/extensions/browser/api/feedback_private/feedback_private_api.h
@@ -141,6 +141,7 @@ void OnAllLogsFetched( scoped_refptr<feedback::FeedbackData> feedback_data, bool send_histograms, + bool send_bluetooth_logs, std::unique_ptr<FeedbackCommon::SystemLogsMap> sys_logs); void OnCompleted(api::feedback_private::LandingPageType type, bool success); };
diff --git a/extensions/browser/guest_view/web_view/web_view_apitest.cc b/extensions/browser/guest_view/web_view/web_view_apitest.cc index 4be182fa..d583f625 100644 --- a/extensions/browser/guest_view/web_view/web_view_apitest.cc +++ b/extensions/browser/guest_view/web_view/web_view_apitest.cc
@@ -45,6 +45,7 @@ #include "net/test/embedded_test_server/embedded_test_server.h" #include "net/test/embedded_test_server/http_request.h" #include "net/test/embedded_test_server/http_response.h" +#include "services/network/public/cpp/features.h" #include "ui/display/display_switches.h" #if defined(USE_AURA) @@ -754,6 +755,12 @@ #define MAYBE_TestWebRequestAPIWithHeaders TestWebRequestAPIWithHeaders #endif IN_PROC_BROWSER_TEST_F(WebViewAPITest, MAYBE_TestWebRequestAPIWithHeaders) { +#if defined(OS_LINUX) + if (base::FeatureList::IsEnabled(network::features::kNetworkService)) { + // Flaky on Linux, https://crbug.com/873792 + return; + } +#endif // defined(OS_LINUX) std::string app_location = "web_view/apitest"; StartTestServer(app_location); RunTest("testWebRequestAPIWithHeaders", app_location);
diff --git a/extensions/common/api/feedback_private.idl b/extensions/common/api/feedback_private.idl index f33a3154..499557e 100644 --- a/extensions/common/api/feedback_private.idl +++ b/extensions/common/api/feedback_private.idl
@@ -31,7 +31,10 @@ // Flow when the feedback is requested from the sad tab ("Aw, Snap!") page // when the renderer crashes. - sadTabCrash + sadTabCrash, + + // Flow for internal Google users. + googleInternal }; dictionary FeedbackInfo { @@ -82,6 +85,9 @@ // Whether to use the system-provided window frame or custom frame controls. boolean? useSystemWindowFrame; + + // Whether or not to send bluetooth logs with this report. + boolean? sendBluetoothLogs; }; // Status of the sending of a feedback report.
diff --git a/google_apis/gcm/tools/mcs_probe.cc b/google_apis/gcm/tools/mcs_probe.cc index 26800cf..1f9a4a7 100644 --- a/google_apis/gcm/tools/mcs_probe.cc +++ b/google_apis/gcm/tools/mcs_probe.cc
@@ -152,6 +152,7 @@ const net::NetLogWithSource& net_log) override { return net::OK; } + void SetConfig(const Config& config) override {} }; class MCSProbeAuthPreferences : public net::HttpAuthPreferences {
diff --git a/gpu/ipc/common/android/surface_owner_android.cc b/gpu/ipc/common/android/surface_owner_android.cc index 088aa98..8d0ea2d 100644 --- a/gpu/ipc/common/android/surface_owner_android.cc +++ b/gpu/ipc/common/android/surface_owner_android.cc
@@ -105,10 +105,13 @@ int32_t width = 1, height = 1, max_images = 3; AIMAGE_FORMATS format = AIMAGE_FORMAT_YUV_420_888; AImageReader* reader = nullptr; + // The usage flag below should be used when the buffer will be read from by + // the GPU as a texture. + const uint64_t usage = AHARDWAREBUFFER_USAGE_GPU_SAMPLED_IMAGE; // Create a new reader for images of the desired size and format. - media_status_t return_code = - loader_.AImageReader_new(width, height, format, max_images, &reader); + media_status_t return_code = loader_.AImageReader_newWithUsage( + width, height, format, usage, max_images, &reader); if (return_code != AMEDIA_OK) { LOG(ERROR) << " Image reader creation failed."; if (return_code == AMEDIA_ERROR_INVALID_PARAMETER) {
diff --git a/infra/config/global/cr-buildbucket-dev.cfg b/infra/config/global/cr-buildbucket-dev.cfg index d237306..bea01791 100644 --- a/infra/config/global/cr-buildbucket-dev.cfg +++ b/infra/config/global/cr-buildbucket-dev.cfg
@@ -51,7 +51,6 @@ execution_timeout_secs: 10800 # 3h service_account: "chromium-ci-builder-dev@chops-service-accounts.iam.gserviceaccount.com" build_numbers: YES - auto_builder_dimension: YES recipe { cipd_package: "infra/recipe_bundles/chromium.googlesource.com/chromium/tools/build" cipd_version: "refs/heads/master"
diff --git a/infra/config/global/luci-milo.cfg b/infra/config/global/luci-milo.cfg index 397f4c0..135b1363 100644 --- a/infra/config/global/luci-milo.cfg +++ b/infra/config/global/luci-milo.cfg
@@ -593,6 +593,12 @@ short_name: "cro" } builders { + name: "buildbot/chromium.memory/win-asan" + name: "buildbucket/luci.chromium.ci/win-asan" + category: "chromium.memory|win" + short_name: "asn" + } + builders { name: "buildbot/chromium.memory/Mac ASan 64 Builder" name: "buildbucket/luci.chromium.ci/Mac ASan 64 Builder" category: "chromium.memory|mac" @@ -1039,6 +1045,12 @@ refs: "refs/heads/master" manifest_name: "REVISION" builders { + name: "buildbot/chromium.memory/win-asan" + name: "buildbucket/luci.chromium.ci/win-asan" + category: "win" + short_name: "asn" + } + builders { name: "buildbot/chromium.memory/Mac ASan 64 Builder" name: "buildbucket/luci.chromium.ci/Mac ASan 64 Builder" category: "mac|asan"
diff --git a/infra/config/global/luci-scheduler.cfg b/infra/config/global/luci-scheduler.cfg index 7cb47dc..e4d46e1 100644 --- a/infra/config/global/luci-scheduler.cfg +++ b/infra/config/global/luci-scheduler.cfg
@@ -210,9 +210,6 @@ triggers: "android-cronet-arm64-dbg" triggers: "android-cronet-arm64-rel" triggers: "android-cronet-asan-arm-rel" - triggers: "android-cronet-kitkat-arm-rel" - triggers: "android-cronet-lollipop-arm-rel" - triggers: "android-cronet-marshmallow-arm64-rel" triggers: "android-cronet-x86-dbg" triggers: "android-cronet-x86-rel" triggers: "android-kitkat-arm-rel" @@ -569,6 +566,28 @@ } job { + id: "android-cronet-kitkat-arm-rel" + # Triggered by "android-cronet-arm-rel". + acl_sets: "triggered-by-parent-builders" + buildbucket: { + server: "cr-buildbucket.appspot.com" + bucket: "luci.chromium.ci" + builder: "android-cronet-kitkat-arm-rel" + } +} + +job { + id: "android-cronet-lollipop-arm-rel" + # Triggered by "android-cronet-arm-rel". + acl_sets: "triggered-by-parent-builders" + buildbucket: { + server: "cr-buildbucket.appspot.com" + bucket: "luci.chromium.ci" + builder: "android-cronet-lollipop-arm-rel" + } +} + +job { id: "android-cronet-arm64-dbg" acl_sets: "default" buildbucket: { @@ -589,6 +608,17 @@ } job { + id: "android-cronet-marshmallow-arm64-rel" + # Triggered by "android-cronet-arm64-rel". + acl_sets: "triggered-by-parent-builders" + buildbucket: { + server: "cr-buildbucket.appspot.com" + bucket: "luci.chromium.ci" + builder: "android-cronet-marshmallow-arm64-rel" + } +} + +job { id: "android-cronet-asan-arm-rel" acl_sets: "default" buildbucket: { @@ -599,36 +629,6 @@ } job { - id: "android-cronet-kitkat-arm-rel" - acl_sets: "default" - buildbucket: { - server: "cr-buildbucket.appspot.com" - bucket: "luci.chromium.ci" - builder: "android-cronet-kitkat-arm-rel" - } -} - -job { - id: "android-cronet-lollipop-arm-rel" - acl_sets: "default" - buildbucket: { - server: "cr-buildbucket.appspot.com" - bucket: "luci.chromium.ci" - builder: "android-cronet-lollipop-arm-rel" - } -} - -job { - id: "android-cronet-marshmallow-arm64-rel" - acl_sets: "default" - buildbucket: { - server: "cr-buildbucket.appspot.com" - bucket: "luci.chromium.ci" - builder: "android-cronet-marshmallow-arm64-rel" - } -} - -job { id: "android-cronet-x86-dbg" acl_sets: "default" buildbucket: {
diff --git a/ios/chrome/app/strings/ios_strings.grd b/ios/chrome/app/strings/ios_strings.grd index dc0ee53..52dd8e5 100644 --- a/ios/chrome/app/strings/ios_strings.grd +++ b/ios/chrome/app/strings/ios_strings.grd
@@ -939,6 +939,9 @@ <message name="IDS_IOS_OPEN_TABS_RECENTLY_SYNCED" desc="Relative time display for small time deltas, anything less than a minute [Length: 10em] [iOS only]"> Seconds ago </message> + <message name="IDS_IOS_OPEN_TABS_SYNCED_YESTERDAY" desc="Relative time display for time deltas that cover yesterday [Length: 10em] [iOS only]"> + Yesterday + </message> <message name="IDS_IOS_OPTIONS_ACCOUNTS_ADD_ACCOUNT_BUTTON" desc="The title of the Add account button on the accounts settings screen [iOS only] [30em]"> Add Account… </message>
diff --git a/ios/chrome/browser/ui/autofill/chrome_autofill_client_ios.h b/ios/chrome/browser/ui/autofill/chrome_autofill_client_ios.h index aacc106..b97854f 100644 --- a/ios/chrome/browser/ui/autofill/chrome_autofill_client_ios.h +++ b/ios/chrome/browser/ui/autofill/chrome_autofill_client_ios.h
@@ -56,7 +56,11 @@ UnmaskCardReason reason, base::WeakPtr<CardUnmaskDelegate> delegate) override; void OnUnmaskVerificationResult(PaymentsRpcResult result) override; - void ShowLocalCardMigrationPrompt(base::OnceClosure closure) override; + void ShowLocalCardMigrationDialog( + base::OnceClosure show_migration_dialog_closure) override; + void ConfirmMigrateLocalCardToCloud( + std::vector<MigratableCreditCard>& migratable_credit_cards, + base::OnceClosure start_migrating_cards_closure) override; void ConfirmSaveAutofillProfile(const AutofillProfile& profile, base::OnceClosure callback) override; void ConfirmSaveCreditCardLocally(const CreditCard& card,
diff --git a/ios/chrome/browser/ui/autofill/chrome_autofill_client_ios.mm b/ios/chrome/browser/ui/autofill/chrome_autofill_client_ios.mm index f7240db..1cf66e8 100644 --- a/ios/chrome/browser/ui/autofill/chrome_autofill_client_ios.mm +++ b/ios/chrome/browser/ui/autofill/chrome_autofill_client_ios.mm
@@ -170,9 +170,15 @@ /*local_save_card_callback=*/callback, GetPrefs()))); } -void ChromeAutofillClientIOS::ShowLocalCardMigrationPrompt( - base::OnceClosure closure) { - NOTREACHED(); +void ChromeAutofillClientIOS::ShowLocalCardMigrationDialog( + base::OnceClosure show_migration_dialog_closure) { + NOTIMPLEMENTED(); +} + +void ChromeAutofillClientIOS::ConfirmMigrateLocalCardToCloud( + std::vector<MigratableCreditCard>& migratable_credit_cards, + base::OnceClosure start_migrating_cards_closure) { + NOTIMPLEMENTED(); } void ChromeAutofillClientIOS::ConfirmSaveCreditCardToCloud(
diff --git a/ios/chrome/browser/ui/recent_tabs/recent_tabs_table_view_controller.mm b/ios/chrome/browser/ui/recent_tabs/recent_tabs_table_view_controller.mm index 2eee0b1..9779793 100644 --- a/ios/chrome/browser/ui/recent_tabs/recent_tabs_table_view_controller.mm +++ b/ios/chrome/browser/ui/recent_tabs/recent_tabs_table_view_controller.mm
@@ -90,9 +90,6 @@ const CGFloat kEstimatedRowHeight = 56; // Separation space between sections. const CGFloat kSeparationSpaceBetweenSections = 9; -// The UI displays relative time for up to this number of hours and then -// switches to absolute values. -const int kRelativeTimeMaxHours = 4; // Section index for recently closed tabs. const int kRecentlyClosedTabsSectionIndex = 0; @@ -832,16 +829,8 @@ if (last_used_delta.InMicroseconds() < base::Time::kMicrosecondsPerMinute) { timeString = l10n_util::GetNSString(IDS_IOS_OPEN_TABS_RECENTLY_SYNCED); - // This will return something similar to "Seconds ago mm/dd/yy" - return [NSString stringWithFormat:@"%@ %@", timeString, dateString]; - } - - if (last_used_delta.InHours() < kRelativeTimeMaxHours) { - timeString = base::SysUTF16ToNSString( - ui::TimeFormat::Simple(ui::TimeFormat::FORMAT_ELAPSED, - ui::TimeFormat::LENGTH_SHORT, last_used_delta)); - // This will return something similar to "1 min/hour ago mm/dd/yy" - return [NSString stringWithFormat:@"%@ %@", timeString, dateString]; + // This will return something similar to "Seconds ago" + return [NSString stringWithFormat:@"%@", timeString]; } NSDate* date = [NSDate dateWithTimeIntervalSince1970:time.ToTimeT()]; @@ -849,6 +838,26 @@ [NSDateFormatter localizedStringFromDate:date dateStyle:NSDateFormatterNoStyle timeStyle:NSDateFormatterShortStyle]; + + NSInteger today = [[NSCalendar currentCalendar] component:NSCalendarUnitDay + fromDate:[NSDate date]]; + NSInteger dateDay = + [[NSCalendar currentCalendar] component:NSCalendarUnitDay fromDate:date]; + + if (today == dateDay) { + timeString = base::SysUTF16ToNSString( + ui::TimeFormat::Simple(ui::TimeFormat::FORMAT_ELAPSED, + ui::TimeFormat::LENGTH_SHORT, last_used_delta)); + // This will return something similar to "1 min/hour ago" + return [NSString stringWithFormat:@"%@", timeString]; + } + + if (today - dateDay == 1) { + dateString = l10n_util::GetNSString(IDS_IOS_OPEN_TABS_SYNCED_YESTERDAY); + // This will return something similar to "H:MM Yesterday" + return [NSString stringWithFormat:@"%@ %@", timeString, dateString]; + } + // This will return something similar to "H:MM mm/dd/yy" return [NSString stringWithFormat:@"%@ %@", timeString, dateString]; }
diff --git a/ios/web_view/internal/autofill/web_view_autofill_client_ios.h b/ios/web_view/internal/autofill/web_view_autofill_client_ios.h index 1358772c..b0b703b 100644 --- a/ios/web_view/internal/autofill/web_view_autofill_client_ios.h +++ b/ios/web_view/internal/autofill/web_view_autofill_client_ios.h
@@ -48,7 +48,11 @@ UnmaskCardReason reason, base::WeakPtr<CardUnmaskDelegate> delegate) override; void OnUnmaskVerificationResult(PaymentsRpcResult result) override; - void ShowLocalCardMigrationPrompt(base::OnceClosure closure) override; + void ShowLocalCardMigrationDialog( + base::OnceClosure show_migration_dialog_closure) override; + void ConfirmMigrateLocalCardToCloud( + std::vector<MigratableCreditCard>& migratable_credit_cards, + base::OnceClosure start_migrating_cards_closure) override; void ConfirmSaveAutofillProfile(const AutofillProfile& profile, base::OnceClosure callback) override; void ConfirmSaveCreditCardLocally(const CreditCard& card,
diff --git a/ios/web_view/internal/autofill/web_view_autofill_client_ios.mm b/ios/web_view/internal/autofill/web_view_autofill_client_ios.mm index 33d8106..7c5c06c4 100644 --- a/ios/web_view/internal/autofill/web_view_autofill_client_ios.mm +++ b/ios/web_view/internal/autofill/web_view_autofill_client_ios.mm
@@ -90,9 +90,15 @@ [bridge_ didReceiveUnmaskVerificationResult:result]; } -void WebViewAutofillClientIOS::ShowLocalCardMigrationPrompt( - base::OnceClosure closure) { - NOTREACHED(); +void WebViewAutofillClientIOS::ShowLocalCardMigrationDialog( + base::OnceClosure show_migration_dialog_closure) { + NOTIMPLEMENTED(); +} + +void WebViewAutofillClientIOS::ConfirmMigrateLocalCardToCloud( + std::vector<MigratableCreditCard>& migratable_credit_cards, + base::OnceClosure start_migrating_cards_closure) { + NOTIMPLEMENTED(); } void WebViewAutofillClientIOS::ConfirmSaveAutofillProfile(
diff --git a/media/audio/audio_output_unittest.cc b/media/audio/audio_output_unittest.cc index d1e80b7..fb65539 100644 --- a/media/audio/audio_output_unittest.cc +++ b/media/audio/audio_output_unittest.cc
@@ -98,13 +98,7 @@ } // This test produces actual audio for .25 seconds on the default device. -#if defined(OS_FUCHSIA) -// TODO(https://crbug.com/873676): Test flakes started when SDK rolled. -#define MAYBE_Play200HzTone DISABLED_Play200HzTone -#else -#define MAYBE_Play200HzTone Play200HzTone -#endif -TEST_F(AudioOutputTest, MAYBE_Play200HzTone) { +TEST_F(AudioOutputTest, Play200HzTone) { ABORT_AUDIO_TEST_IF_NOT(audio_manager_device_info_->HasAudioOutputDevices()); stream_params_ =
diff --git a/media/audio/fuchsia/audio_output_stream_fuchsia.cc b/media/audio/fuchsia/audio_output_stream_fuchsia.cc index 0417433..03adca55e 100644 --- a/media/audio/fuchsia/audio_output_stream_fuchsia.cc +++ b/media/audio/fuchsia/audio_output_stream_fuchsia.cc
@@ -13,6 +13,11 @@ namespace media { +// Current AudioOut implementation allows only one buffer with id=0. +// TODO(sergeyu): Replace with an incrementing buffer id once AddPayloadBuffer() +// and RemovePayloadBuffer() are implemented properly in AudioOut. +const uint32_t kBufferId = 0; + AudioOutputStreamFuchsia::AudioOutputStreamFuchsia( AudioManagerFuchsia* manager, const AudioParameters& parameters) @@ -22,36 +27,36 @@ AudioOutputStreamFuchsia::~AudioOutputStreamFuchsia() { // Close() must be called first. - DCHECK(!audio_renderer_); + DCHECK(!audio_out_); } bool AudioOutputStreamFuchsia::Open() { - DCHECK(!audio_renderer_); + DCHECK(!audio_out_); - // Connect |audio_renderer_| to the audio service. + // Connect |audio_out_| to the audio service. fuchsia::media::AudioPtr audio_server = base::fuchsia::ComponentContext::GetDefault() ->ConnectToService<fuchsia::media::Audio>(); - audio_server->CreateAudioRenderer2(audio_renderer_.NewRequest()); - audio_renderer_.set_error_handler( + audio_server->CreateAudioOut(audio_out_.NewRequest()); + audio_out_.set_error_handler( fit::bind_member(this, &AudioOutputStreamFuchsia::OnRendererError)); - // Inform the |audio_renderer_| of the format required by the caller. + // Inform the |audio_out_| of the format required by the caller. fuchsia::media::AudioStreamType format; format.sample_format = fuchsia::media::AudioSampleFormat::FLOAT; format.channels = parameters_.channels(); format.frames_per_second = parameters_.sample_rate(); - audio_renderer_->SetPcmStreamType(std::move(format)); + audio_out_->SetPcmStreamType(std::move(format)); // Use number of samples to specify media position. - audio_renderer_->SetPtsUnits(parameters_.sample_rate(), 1); + audio_out_->SetPtsUnits(parameters_.sample_rate(), 1); // Setup OnMinLeadTimeChanged event listener. This event is used to get // |min_lead_time_|, which indicates how far ahead audio samples need to be // sent to the renderer. - audio_renderer_.events().OnMinLeadTimeChanged = + audio_out_.events().OnMinLeadTimeChanged = fit::bind_member(this, &AudioOutputStreamFuchsia::OnMinLeadTimeChanged); - audio_renderer_->EnableMinLeadTimeEvents(true); + audio_out_->EnableMinLeadTimeEvents(true); // The renderer may fail initialization asynchronously, which is handled in // OnRendererError(). @@ -70,7 +75,7 @@ void AudioOutputStreamFuchsia::Stop() { callback_ = nullptr; reference_time_ = base::TimeTicks(); - audio_renderer_->FlushNoReply(); + audio_out_->PauseNoReply(); timer_.Stop(); } @@ -85,7 +90,7 @@ void AudioOutputStreamFuchsia::Close() { Stop(); - audio_renderer_.Unbind(); + audio_out_.Unbind(); // Signal to the manager that we're closed and can be removed. This should be // the last call in the function as it deletes |this|. @@ -119,8 +124,8 @@ } payload_buffer_pos_ = 0; - audio_renderer_->SetPayloadBuffer( - zx::vmo(payload_buffer_.handle().Duplicate().GetHandle())); + audio_out_->AddPayloadBuffer( + kBufferId, zx::vmo(payload_buffer_.handle().Duplicate().GetHandle())); return true; } @@ -140,18 +145,23 @@ } void AudioOutputStreamFuchsia::OnRendererError() { - LOG(WARNING) << "AudioRenderer has failed."; - Stop(); - callback_->OnError(); + LOG(WARNING) << "AudioOut has failed."; + ReportError(); +} + +void AudioOutputStreamFuchsia::ReportError() { + reference_time_ = base::TimeTicks(); + timer_.Stop(); + if (callback_) + callback_->OnError(); } void AudioOutputStreamFuchsia::PumpSamples() { - DCHECK(audio_renderer_); + DCHECK(audio_out_); // Allocate payload buffer if necessary. if (!payload_buffer_.mapped_size() && !InitializePayloadBuffer()) { - Stop(); - callback_->OnError(); + ReportError(); return; } @@ -186,20 +196,21 @@ reinterpret_cast<uint8_t*>(payload_buffer_.memory()) + payload_buffer_pos_)); - fuchsia::media::AudioPacket packet; - packet.timestamp = stream_position_samples_; + fuchsia::media::StreamPacket packet; + packet.pts = stream_position_samples_; + packet.payload_buffer_id = kBufferId; packet.payload_offset = payload_buffer_pos_; packet.payload_size = packet_size; packet.flags = 0; - audio_renderer_->SendPacketNoReply(std::move(packet)); + audio_out_->SendPacketNoReply(std::move(packet)); stream_position_samples_ += frames_filled; payload_buffer_pos_ = (payload_buffer_pos_ + packet_size) % payload_buffer_.mapped_size(); if (reference_time_.is_null()) { - audio_renderer_->Play( + audio_out_->Play( fuchsia::media::NO_TIMESTAMP, stream_position_samples_ - frames_filled, [this](int64_t reference_time, int64_t media_time) { if (!callback_)
diff --git a/media/audio/fuchsia/audio_output_stream_fuchsia.h b/media/audio/fuchsia/audio_output_stream_fuchsia.h index a6eff58..da710f0d 100644 --- a/media/audio/fuchsia/audio_output_stream_fuchsia.h +++ b/media/audio/fuchsia/audio_output_stream_fuchsia.h
@@ -41,12 +41,15 @@ base::TimeTicks GetCurrentStreamTime(); - // Event handler for |audio_renderer_|. + // Event handler for |audio_out_|. void OnMinLeadTimeChanged(int64_t min_lead_time); - // Error handler for |audio_renderer_|. + // Error handler for |audio_out_|. void OnRendererError(); + // Resets internal state and reports an error to |callback_|. + void ReportError(); + // Requests data from AudioSourceCallback, passes it to the mixer and // schedules |timer_| for the next call. void PumpSamples(); @@ -58,8 +61,7 @@ AudioManagerFuchsia* manager_; AudioParameters parameters_; - // Audio renderer connection. - fuchsia::media::AudioRenderer2Ptr audio_renderer_; + fuchsia::media::AudioOutPtr audio_out_; // |audio_bus_| is used only in PumpSamples(). It is kept here to avoid // reallocating the memory every time.
diff --git a/media/gpu/android/image_reader_gl_owner.cc b/media/gpu/android/image_reader_gl_owner.cc index 33fd945..1b7ef78 100644 --- a/media/gpu/android/image_reader_gl_owner.cc +++ b/media/gpu/android/image_reader_gl_owner.cc
@@ -61,10 +61,13 @@ int32_t width = 1, height = 1, max_images = 3; AIMAGE_FORMATS format = AIMAGE_FORMAT_YUV_420_888; AImageReader* reader = nullptr; + // The usage flag below should be used when the buffer will be read from by + // the GPU as a texture. + const uint64_t usage = AHARDWAREBUFFER_USAGE_GPU_SAMPLED_IMAGE; // Create a new reader for images of the desired size and format. - media_status_t return_code = - loader_.AImageReader_new(width, height, format, max_images, &reader); + media_status_t return_code = loader_.AImageReader_newWithUsage( + width, height, format, usage, max_images, &reader); if (return_code != AMEDIA_OK) { LOG(ERROR) << " Image reader creation failed."; if (return_code == AMEDIA_ERROR_INVALID_PARAMETER)
diff --git a/media/gpu/v4l2/v4l2_slice_video_decode_accelerator.cc b/media/gpu/v4l2/v4l2_slice_video_decode_accelerator.cc index feb0f9c4..32c3a86 100644 --- a/media/gpu/v4l2/v4l2_slice_video_decode_accelerator.cc +++ b/media/gpu/v4l2/v4l2_slice_video_decode_accelerator.cc
@@ -2580,7 +2580,8 @@ Reset(); - v4l2_dec_->DecodeSurface(dec_surface); + DVLOGF(4) << "Submitting decode for surface: " << dec_surface->ToString(); + v4l2_dec_->Enqueue(dec_surface); return Status::kOk; } @@ -2815,7 +2816,8 @@ frame_hdr->frame_size)) return false; - v4l2_dec_->DecodeSurface(dec_surface); + DVLOGF(4) << "Submitting decode for surface: " << dec_surface->ToString(); + v4l2_dec_->Enqueue(dec_surface); return true; } @@ -3118,7 +3120,8 @@ frame_hdr->frame_size)) return false; - v4l2_dec_->DecodeSurface(dec_surface); + DVLOGF(4) << "Submitting decode for surface: " << dec_surface->ToString(); + v4l2_dec_->Enqueue(dec_surface); return true; } @@ -3202,14 +3205,6 @@ return v4l2_pic->dec_surface(); } -void V4L2SliceVideoDecodeAccelerator::DecodeSurface( - const scoped_refptr<V4L2DecodeSurface>& dec_surface) { - DCHECK(decoder_thread_task_runner_->BelongsToCurrentThread()); - - DVLOGF(4) << "Submitting decode for surface: " << dec_surface->ToString(); - Enqueue(dec_surface); -} - void V4L2SliceVideoDecodeAccelerator::SurfaceReady( int32_t bitstream_id, const scoped_refptr<V4L2DecodeSurface>& dec_surface) {
diff --git a/media/gpu/v4l2/v4l2_slice_video_decode_accelerator.h b/media/gpu/v4l2/v4l2_slice_video_decode_accelerator.h index 317d99e..bdab5000 100644 --- a/media/gpu/v4l2/v4l2_slice_video_decode_accelerator.h +++ b/media/gpu/v4l2/v4l2_slice_video_decode_accelerator.h
@@ -134,10 +134,6 @@ // Return true if the driver exposes V4L2 control |ctrl_id|, false otherwise. bool IsCtrlExposed(uint32_t ctrl_id); - // Decode of |dec_surface| is ready to be submitted and all codec-specific - // settings are set in hardware. - void DecodeSurface(const scoped_refptr<V4L2DecodeSurface>& dec_surface); - // |dec_surface| is ready to be outputted once decode is finished. // This can be called before decode is actually done in hardware, and this // method is responsible for maintaining the ordering, i.e. the surfaces will
diff --git a/mojo/README.md b/mojo/README.md index 46d14fa4..b7ce83f 100644 --- a/mojo/README.md +++ b/mojo/README.md
@@ -46,7 +46,7 @@ process binaries are linking against precisely the same revision of Mojo Core. To support other scenarios, use dynamic linking. -## Dynamic Linking +### Dynamic Linking On some platforms, it's also possible for applications to rely on a dynamically-linked Mojo Core library (`libmojo_core.so` or `mojo_core.dll`) instead of statically linking against Mojo Core.
diff --git a/mojo/public/cpp/system/README.md b/mojo/public/cpp/system/README.md index d1f6889..abc722ce 100644 --- a/mojo/public/cpp/system/README.md +++ b/mojo/public/cpp/system/README.md
@@ -47,7 +47,7 @@ // NOTE: Because pipes are bi-directional there is no implicit semantic // difference between |handle0| or |handle1| here. They're just two ends of a // pipe. The choice to treat one as a "client" and one as a "server" is entirely -// a the API user's decision. +// the API user's decision. mojo::ScopedMessagePipeHandle client = std::move(pipe.handle0); mojo::ScopedMessagePipeHandle server = std::move(pipe.handle1); ``` @@ -124,7 +124,7 @@ ## Shared Buffers -A new shared buffers can be allocated like so: +A new shared buffer can be allocated like so: ``` cpp mojo::ScopedSharedBufferHandle buffer =
diff --git a/mojo/public/java/system/javatests/AndroidManifest.xml b/mojo/public/java/system/javatests/AndroidManifest.xml index 37fc407..56aabd8 100644 --- a/mojo/public/java/system/javatests/AndroidManifest.xml +++ b/mojo/public/java/system/javatests/AndroidManifest.xml
@@ -24,7 +24,6 @@ <instrumentation android:name="android.support.test.runner.AndroidJUnitRunner" android:targetPackage="org.chromium.mojo.tests" - android:label="Tests for org.chromium.mojo" - chromium-junit4="true"/> + android:label="Tests for org.chromium.mojo"/> </manifest>
diff --git a/mojo/public/tools/bindings/README.md b/mojo/public/tools/bindings/README.md index d1ffc44..76c6f321 100644 --- a/mojo/public/tools/bindings/README.md +++ b/mojo/public/tools/bindings/README.md
@@ -283,7 +283,7 @@ ### Enumeration Types Enumeration types may be defined using the **enum** keyword either directly -within a module or within the namespace of some struct or interface: +within a module or nested within the namespace of some struct or interface: ``` module business.mojom; @@ -304,8 +304,8 @@ }; ``` -That that similar to C-style enums, individual values may be explicitly assigned -within an enum definition. By default values are based at zero and incremenet by +Similar to C-style enums, individual values may be explicitly assigned within an +enum definition. By default, values are based at zero and increment by 1 sequentially. The effect of nested definitions on generated bindings varies depending on the @@ -314,7 +314,7 @@ ### Constants Constants may be defined using the **const** keyword either directly within a -module or within the namespace of some struct or interface: +module or nested within the namespace of some struct or interface: ``` module business.mojom; @@ -341,7 +341,7 @@ An **interface** is a logical bundle of parameterized request messages. Each request message may optionally define a parameterized response message. Here's -syntax to define an interface `Foo` with various kinds of requests: +an example to define an interface `Foo` with various kinds of requests: ``` interface Foo {
diff --git a/net/BUILD.gn b/net/BUILD.gn index 59a8968..326b22e 100644 --- a/net/BUILD.gn +++ b/net/BUILD.gn
@@ -399,6 +399,7 @@ if (!is_nacl) { sources += [ + "android/android_http_util.cc", "android/cellular_signal_strength.cc", "android/cellular_signal_strength.h", "android/cert_verify_result_android.cc", @@ -406,7 +407,6 @@ "android/gurl_utils.cc", "android/http_auth_negotiate_android.cc", "android/http_auth_negotiate_android.h", - "android/android_http_util.cc", "android/keystore.cc", "android/keystore.h", "android/legacy_openssl.h", @@ -2508,6 +2508,7 @@ "data/ssl/certificates/websocket_cacert.pem", "data/ssl/certificates/websocket_client_cert.p12", "data/ssl/certificates/wildcard.pem", + "data/ssl/certificates/www.ahrn.com.pem", "data/ssl/certificates/x509_verify_results.chain.pem", ] outputs = [
diff --git a/net/android/unittest_support/AndroidManifest.xml b/net/android/unittest_support/AndroidManifest.xml index a7f04e7..9293618 100644 --- a/net/android/unittest_support/AndroidManifest.xml +++ b/net/android/unittest_support/AndroidManifest.xml
@@ -50,6 +50,7 @@ <instrumentation android:name="org.chromium.native_test.NativeTestInstrumentationTestRunner" android:targetPackage="org.chromium.native_test" - android:label="Instrumentation entry point for org.chromium.native_test"/> + android:label="Instrumentation entry point for org.chromium.native_test" + chromium-junit3="true"/> </manifest>
diff --git a/net/base/load_flags_list.h b/net/base/load_flags_list.h index fd80563..798863f 100644 --- a/net/base/load_flags_list.h +++ b/net/base/load_flags_list.h
@@ -37,9 +37,9 @@ // impact the HTTP request headers or use of the host cache. LOAD_FLAG(DISABLE_CACHE, 1 << 4) -// If present, causes certificate revocation checks to be skipped on secure -// connections. -LOAD_FLAG(DISABLE_CERT_REVOCATION_CHECKING, 1 << 5) +// If present, causes dependent network fetches (AIA, CRLs, OCSP) to be +// skipped on secure connections. +LOAD_FLAG(DISABLE_CERT_NETWORK_FETCHES, 1 << 5) // This load will not make any changes to cookies, including storing new // cookies or updating existing ones.
diff --git a/net/cert/caching_cert_verifier.cc b/net/cert/caching_cert_verifier.cc index d3c5787..e1c3625 100644 --- a/net/cert/caching_cert_verifier.cc +++ b/net/cert/caching_cert_verifier.cc
@@ -23,6 +23,7 @@ CachingCertVerifier::CachingCertVerifier(std::unique_ptr<CertVerifier> verifier) : verifier_(std::move(verifier)), + config_id_(0u), cache_(kMaxCacheEntries), requests_(0u), cache_hits_(0u) { @@ -53,18 +54,24 @@ base::Time start_time = base::Time::Now(); CompletionOnceCallback caching_callback = base::BindOnce( - &CachingCertVerifier::OnRequestFinished, base::Unretained(this), params, - start_time, std::move(callback), verify_result); + &CachingCertVerifier::OnRequestFinished, base::Unretained(this), + config_id_, params, start_time, std::move(callback), verify_result); int result = verifier_->Verify(params, crl_set, verify_result, std::move(caching_callback), out_req, net_log); if (result != ERR_IO_PENDING) { // Synchronous completion; add directly to cache. - AddResultToCache(params, start_time, *verify_result, result); + AddResultToCache(config_id_, params, start_time, *verify_result, result); } return result; } +void CachingCertVerifier::SetConfig(const CertVerifier::Config& config) { + verifier_->SetConfig(config); + config_id_++; + ClearCache(); +} + CachingCertVerifier::CachedResult::CachedResult() : error(ERR_FAILED) {} CachingCertVerifier::CachedResult::~CachedResult() = default; @@ -112,22 +119,29 @@ now.verification_time < expiration.expiration_time; }; -void CachingCertVerifier::OnRequestFinished(const RequestParams& params, +void CachingCertVerifier::OnRequestFinished(uint32_t config_id, + const RequestParams& params, base::Time start_time, CompletionOnceCallback callback, CertVerifyResult* verify_result, int error) { - AddResultToCache(params, start_time, *verify_result, error); + AddResultToCache(config_id, params, start_time, *verify_result, error); // Now chain to the user's callback, which may delete |this|. std::move(callback).Run(error); } void CachingCertVerifier::AddResultToCache( + uint32_t config_id, const RequestParams& params, base::Time start_time, const CertVerifyResult& verify_result, int error) { + // If the configuration has changed since this verification was started, + // don't add it to the cache. + if (config_id != config_id_) + return; + // When caching, this uses the time that validation started as the // beginning of the validity, rather than the time that it ended (aka // base::Time::Now()), to account for the fact that during validation, @@ -161,6 +175,7 @@ } void CachingCertVerifier::OnCertDBChanged() { + config_id_++; ClearCache(); }
diff --git a/net/cert/caching_cert_verifier.h b/net/cert/caching_cert_verifier.h index 387229f..145c6eb 100644 --- a/net/cert/caching_cert_verifier.h +++ b/net/cert/caching_cert_verifier.h
@@ -49,6 +49,7 @@ CompletionOnceCallback callback, std::unique_ptr<Request>* out_req, const NetLogWithSource& net_log) override; + void SetConfig(const Config& config) override; private: FRIEND_TEST_ALL_PREFIXES(CachingCertVerifierTest, CacheHit); @@ -93,18 +94,21 @@ CacheExpirationFunctor>; // Handles completion of the request matching |params|, which started at - // |start_time|, completing. |verify_result| and |result| are added to the - // cache, and then |callback| (the original caller's callback) is invoked. - void OnRequestFinished(const RequestParams& params, + // |start_time| and with config |config_id|, completing. |verify_result| and + // |result| are added to the cache, and then |callback| (the original caller's + // callback) is invoked. + void OnRequestFinished(uint32_t config_id, + const RequestParams& params, base::Time start_time, CompletionOnceCallback callback, CertVerifyResult* verify_result, int error); // Adds |verify_result| and |error| to the cache for |params|, whose - // verification attempt began at |start_time|. See the implementation - // for more details about the necessity of |start_time|. - void AddResultToCache(const RequestParams& params, + // verification attempt began at |start_time| with config |config_id|. See the + // implementation for more details about the necessity of |start_time|. + void AddResultToCache(uint32_t config_id, + const RequestParams& params, base::Time start_time, const CertVerifyResult& verify_result, int error); @@ -120,6 +124,7 @@ std::unique_ptr<CertVerifier> verifier_; + uint32_t config_id_; CertVerificationCache cache_; uint64_t requests_;
diff --git a/net/cert/cert_verifier.cc b/net/cert/cert_verifier.cc index 89ba98a9..18ab114 100644 --- a/net/cert/cert_verifier.cc +++ b/net/cert/cert_verifier.cc
@@ -81,4 +81,18 @@ #endif } +bool operator==(const CertVerifier::Config& lhs, + const CertVerifier::Config& rhs) { + return std::tie( + lhs.enable_rev_checking, lhs.require_rev_checking_local_anchors, + lhs.enable_sha1_local_anchors, lhs.disable_symantec_enforcement) == + std::tie( + rhs.enable_rev_checking, rhs.require_rev_checking_local_anchors, + rhs.enable_sha1_local_anchors, rhs.disable_symantec_enforcement); +} +bool operator!=(const CertVerifier::Config& lhs, + const CertVerifier::Config& rhs) { + return !(lhs == rhs); +} + } // namespace net
diff --git a/net/cert/cert_verifier.h b/net/cert/cert_verifier.h index 7abc4071a..6fb008e8 100644 --- a/net/cert/cert_verifier.h +++ b/net/cert/cert_verifier.h
@@ -27,6 +27,26 @@ // CertVerifiers can handle multiple requests at a time. class NET_EXPORT CertVerifier { public: + struct Config { + // Enable online revocation checking via CRLs and OCSP for the certificate + // chain. Note that revocation checking is soft-fail. + bool enable_rev_checking = false; + + // Enable online revocation checking via CRLs and OCSP for the certificate + // chain if the constructed chain terminates in a locally-installed, + // non-public trust anchor. A revocation error, such as a failure to + // obtain fresh revocation information, is treated as a hard failure. + bool require_rev_checking_local_anchors = false; + + // Enable support for SHA-1 signatures if the constructed chain terminates + // in a locally-installed, non-public trust anchor. + bool enable_sha1_local_anchors = false; + + // Disable enforcement of the policies described at + // https://security.googleblog.com/2017/09/chromes-plan-to-distrust-symantec.html + bool disable_symantec_enforcement = false; + }; + class Request { public: Request() {} @@ -39,35 +59,16 @@ }; enum VerifyFlags { - // If set, enables online revocation checking via CRLs and OCSP for the - // certificate chain. - VERIFY_REV_CHECKING_ENABLED = 1 << 0, - - // 1 << 1 is reserved (used to be VERIFY_EV_CERT). - // 1 << 2 is reserved (used to be VERIY_CERT_IO_ENABLED). - // 1 << 3 is reserved (used to be VERIFY_REV_CHECKING_ENABLED_EV_ONLY). - - // If set, this is equivalent to VERIFY_REV_CHECKING_ENABLED, in that it - // enables online revocation checking via CRLs or OCSP, but only - // for certificates issued by non-public trust anchors. Failure to check - // revocation is treated as a hard failure. - // Note: If VERIFY_CERT_IO_ENABLE is not also supplied, certificates - // that chain to local trust anchors will likely fail - for example, due to - // lacking fresh cached revocation issue (Windows) or because OCSP stapling - // can only provide information for the leaf, and not for any - // intermediates. - VERIFY_REV_CHECKING_REQUIRED_LOCAL_ANCHORS = 1 << 4, - - // If set, certificates with SHA-1 signatures will be allowed, but only if - // they are issued by non-public trust anchors. - VERIFY_ENABLE_SHA1_LOCAL_ANCHORS = 1 << 5, - - // 1 << 6 is reserved (used to be - // VERIFY_ENABLE_COMMON_NAME_FALLBACK_LOCAL_ANCHORS). - - // If set, disables the policy enforcement described at - // https://security.googleblog.com/2017/09/chromes-plan-to-distrust-symantec.html - VERIFY_DISABLE_SYMANTEC_ENFORCEMENT = 1 << 7, + // If set, actively overrides the current CertVerifier::Config to disable + // dependent network fetches. This can be used to avoid triggering + // re-entrancy in the network stack. For example, fetching a PAC script + // over HTTPS may cause AIA, OCSP, or CRL fetches to block on retrieving + // the PAC script, while the PAC script fetch is waiting for those + // dependent fetches, creating a deadlock. When set, this flag prevents + // those fetches from being started (best effort). + // Note that cached information may still be used, if it can be accessed + // without accessing the network. + VERIFY_DISABLE_NETWORK_FETCHES = 1 << 0, }; // Parameters to verify |certificate| against the supplied @@ -158,11 +159,29 @@ std::unique_ptr<Request>* out_req, const NetLogWithSource& net_log) = 0; + // Sets the configuration for new certificate verifications to be |config|. + // Any in-progress verifications (i.e. those with outstanding Request + // handles) will continue using the old configuration. This may be called + // throughout the CertVerifier's lifetime in response to configuration + // changes from embedders. + // Note: As configuration changes will replace any existing configuration, + // this should only be called by the logical 'owner' of this CertVerifier. + // Callers should NOT attempt to change configuration for single calls, and + // should NOT attempt to change configuration for CertVerifiers they do not + // explicitly manage. + virtual void SetConfig(const Config& config) = 0; + // Creates a CertVerifier implementation that verifies certificates using - // the preferred underlying cryptographic libraries. + // the preferred underlying cryptographic libraries, using the specified + // configuration. static std::unique_ptr<CertVerifier> CreateDefault(); }; +NET_EXPORT bool operator==(const CertVerifier::Config& lhs, + const CertVerifier::Config& rhs); +NET_EXPORT bool operator!=(const CertVerifier::Config& lhs, + const CertVerifier::Config& rhs); + } // namespace net #endif // NET_CERT_CERT_VERIFIER_H_
diff --git a/net/cert/cert_verifier_unittest.cc b/net/cert/cert_verifier_unittest.cc index c61e996d..cccb12d 100644 --- a/net/cert/cert_verifier_unittest.cc +++ b/net/cert/cert_verifier_unittest.cc
@@ -86,9 +86,10 @@ { // The same certificate, chain, and host, but with different flags // are different validation keys. - CertVerifier::RequestParams(ok_cert, "www.example.test", - CertVerifier::VERIFY_REV_CHECKING_ENABLED, - std::string(), empty_list), + CertVerifier::RequestParams( + ok_cert, "www.example.test", + CertVerifier::VERIFY_DISABLE_NETWORK_FETCHES, std::string(), + empty_list), CertVerifier::RequestParams(ok_cert, "www.example.test", 0, std::string(), empty_list), false,
diff --git a/net/cert/cert_verify_proc.cc b/net/cert/cert_verify_proc.cc index 57cfa782..6177891b 100644 --- a/net/cert/cert_verify_proc.cc +++ b/net/cert/cert_verify_proc.cc
@@ -600,7 +600,7 @@ // allowed for that platform. See https://crbug.com/588789 bool current_sha1_issue = (verify_result->is_issued_by_known_root || - !(flags & CertVerifier::VERIFY_ENABLE_SHA1_LOCAL_ANCHORS)) && + !(flags & VERIFY_ENABLE_SHA1_LOCAL_ANCHORS)) && (verify_result->has_sha1_leaf || (verify_result->has_sha1 && !AreSHA1IntermediatesAllowed())); @@ -617,7 +617,7 @@ // Distrust Symantec-issued certificates, as described at // https://security.googleblog.com/2017/09/chromes-plan-to-distrust-symantec.html - if (!(flags & CertVerifier::VERIFY_DISABLE_SYMANTEC_ENFORCEMENT) && + if (!(flags & VERIFY_DISABLE_SYMANTEC_ENFORCEMENT) && IsLegacySymantecCert(verify_result->public_key_hashes)) { if (base::FeatureList::IsEnabled(kLegacySymantecPKIEnforcement) || IsUntrustedSymantecCert(*verify_result->verified_cert)) {
diff --git a/net/cert/cert_verify_proc.h b/net/cert/cert_verify_proc.h index 64b2bdd..c89c1379 100644 --- a/net/cert/cert_verify_proc.h +++ b/net/cert/cert_verify_proc.h
@@ -28,6 +28,31 @@ class NET_EXPORT CertVerifyProc : public base::RefCountedThreadSafe<CertVerifyProc> { public: + enum VerifyFlags { + // If set, enables online revocation checking via CRLs and OCSP for the + // certificate chain. + VERIFY_REV_CHECKING_ENABLED = 1 << 0, + + // If set, this is equivalent to VERIFY_REV_CHECKING_ENABLED, in that it + // enables online revocation checking via CRLs or OCSP, but only + // for certificates issued by non-public trust anchors. Failure to check + // revocation is treated as a hard failure. + // Note: If VERIFY_CERT_IO_ENABLE is not also supplied, certificates + // that chain to local trust anchors will likely fail - for example, due to + // lacking fresh cached revocation issue (Windows) or because OCSP stapling + // can only provide information for the leaf, and not for any + // intermediates. + VERIFY_REV_CHECKING_REQUIRED_LOCAL_ANCHORS = 1 << 1, + + // If set, certificates with SHA-1 signatures will be allowed, but only if + // they are issued by non-public trust anchors. + VERIFY_ENABLE_SHA1_LOCAL_ANCHORS = 1 << 2, + + // If set, disables the policy enforcement described at + // https://security.googleblog.com/2017/09/chromes-plan-to-distrust-symantec.html + VERIFY_DISABLE_SYMANTEC_ENFORCEMENT = 1 << 3, + }; + // Creates and returns the default CertVerifyProc. static scoped_refptr<CertVerifyProc> CreateDefault(); @@ -49,9 +74,6 @@ // based revocation checking is always enabled, regardless of this flag, if // |crl_set| is given. // - // If VERIFY_EV_CERT is set in |flags| too, EV certificate verification is - // performed. - // // |crl_set| points to an optional CRLSet structure which can be used to // avoid revocation checks over the network. //
diff --git a/net/cert/cert_verify_proc_builtin.cc b/net/cert/cert_verify_proc_builtin.cc index 62e84937..9345b47 100644 --- a/net/cert/cert_verify_proc_builtin.cc +++ b/net/cert/cert_verify_proc_builtin.cc
@@ -183,7 +183,7 @@ // Use hard-fail revocation checking for local trust anchors, if requested // by the load flag and the chain uses a non-public root. - if ((flags_ & CertVerifier::VERIFY_REV_CHECKING_REQUIRED_LOCAL_ANCHORS) && + if ((flags_ & CertVerifyProc::VERIFY_REV_CHECKING_REQUIRED_LOCAL_ANCHORS) && !certs.empty() && !ssl_trust_store_->IsKnownRoot(certs.back().get())) { RevocationPolicy policy; policy.check_revocation = true; @@ -214,7 +214,7 @@ } // Use soft-fail revocation checking for VERIFY_REV_CHECKING_ENABLED. - if (flags_ & CertVerifier::VERIFY_REV_CHECKING_ENABLED) { + if (flags_ & CertVerifyProc::VERIFY_REV_CHECKING_ENABLED) { RevocationPolicy policy; policy.check_revocation = true; policy.networking_allowed = true;
diff --git a/net/cert/cert_verify_proc_mac.cc b/net/cert/cert_verify_proc_mac.cc index 1257ac5..ae80b29 100644 --- a/net/cert/cert_verify_proc_mac.cc +++ b/net/cert/cert_verify_proc_mac.cc
@@ -182,7 +182,7 @@ // revocation checking policies and instead respect the application-level // revocation preference. status = x509_util::CreateRevocationPolicies( - (flags & CertVerifier::VERIFY_REV_CHECKING_ENABLED), local_policies); + (flags & CertVerifyProc::VERIFY_REV_CHECKING_ENABLED), local_policies); if (status) return status; @@ -546,7 +546,7 @@ // Note: For EV certificates, the Apple TP will handle setting these flags // as part of EV evaluation. - if (flags & CertVerifier::VERIFY_REV_CHECKING_ENABLED) { + if (flags & CertVerifyProc::VERIFY_REV_CHECKING_ENABLED) { // Require a positive result from an OCSP responder or a CRL (or both) // for every certificate in the chain. The Apple TP automatically // excludes the self-signed root from this requirement. If a certificate @@ -830,7 +830,7 @@ break; } - if (flags & CertVerifier::VERIFY_REV_CHECKING_ENABLED) + if (flags & CertVerifyProc::VERIFY_REV_CHECKING_ENABLED) verify_result->cert_status |= CERT_STATUS_REV_CHECKING_ENABLED; if (*completed_chain_crl_result == kCRLSetRevoked) @@ -908,7 +908,7 @@ weak_key_or_signature_algorithm = true; policy_fail_already_mapped = true; } else if (policy_failed && - (flags & CertVerifier::VERIFY_REV_CHECKING_ENABLED) && + (flags & CertVerifyProc::VERIFY_REV_CHECKING_ENABLED) && chain_info[index].StatusCodes[status_code_index] == CSSMERR_TP_VERIFY_ACTION_FAILED && base::mac::IsOS10_12()) { @@ -1013,17 +1013,17 @@ // EV policies check out and the verification succeeded. See if revocation // checking still needs to be done before it can be marked as EV. if (completed_chain_crl_result == kCRLSetUnknown && - !(flags & CertVerifier::VERIFY_REV_CHECKING_ENABLED)) { + !(flags & VERIFY_REV_CHECKING_ENABLED)) { // If this is an EV cert and it wasn't covered by CRLSets and revocation // checking wasn't already on, try again with revocation forced on. // // Restore the input state of |*verify_result|, so that the // re-verification starts with a clean slate. *verify_result = input_verify_result; - int tmp_rv = VerifyWithGivenFlags( - verify_result->verified_cert.get(), hostname, - flags | CertVerifier::VERIFY_REV_CHECKING_ENABLED, crl_set, - verify_result, &completed_chain_crl_result); + int tmp_rv = + VerifyWithGivenFlags(verify_result->verified_cert.get(), hostname, + flags | VERIFY_REV_CHECKING_ENABLED, crl_set, + verify_result, &completed_chain_crl_result); // If re-verification failed, return those results without setting EV // status. if (tmp_rv != OK)
diff --git a/net/cert/cert_verify_proc_nss.cc b/net/cert/cert_verify_proc_nss.cc index d98b304..9c11b054 100644 --- a/net/cert/cert_verify_proc_nss.cc +++ b/net/cert/cert_verify_proc_nss.cc
@@ -892,8 +892,7 @@ SECOidTag ev_policy_oid = SEC_OID_UNKNOWN; bool is_ev_candidate = IsEVCandidate(metadata, cert_handle, &ev_policy_oid); - bool check_revocation = - (flags & CertVerifier::VERIFY_REV_CHECKING_ENABLED); + bool check_revocation = (flags & VERIFY_REV_CHECKING_ENABLED); if (check_revocation) verify_result->cert_status |= CERT_STATUS_REV_CHECKING_ENABLED; @@ -917,8 +916,7 @@ } if (status == SECSuccess && - (flags & CertVerifier::VERIFY_REV_CHECKING_REQUIRED_LOCAL_ANCHORS) && - !known_root) { + (flags & VERIFY_REV_CHECKING_REQUIRED_LOCAL_ANCHORS) && !known_root) { // TODO(rsleevi): Optimize this by supplying the constructed chain to // libpkix via cvin. Omitting for now, due to lack of coverage in upstream // NSS tests for that feature.
diff --git a/net/cert/cert_verify_proc_unittest.cc b/net/cert/cert_verify_proc_unittest.cc index 5e3ad57..65785fa 100644 --- a/net/cert/cert_verify_proc_unittest.cc +++ b/net/cert/cert_verify_proc_unittest.cc
@@ -1208,7 +1208,7 @@ ASSERT_TRUE(cert_chain); CertVerifyResult verify_result; - int flags = CertVerifier::VERIFY_REV_CHECKING_ENABLED; + int flags = CertVerifyProc::VERIFY_REV_CHECKING_ENABLED; int error = Verify(cert_chain.get(), "mail.google.com", flags, NULL, CertificateList(), &verify_result); EXPECT_NE(OK, error); @@ -2002,7 +2002,7 @@ CertVerifyResult test_result_3; error = verify_proc->Verify(cert.get(), "127.0.0.1", std::string(), - CertVerifier::VERIFY_DISABLE_SYMANTEC_ENFORCEMENT, + CertVerifyProc::VERIFY_DISABLE_SYMANTEC_ENFORCEMENT, nullptr, CertificateList(), &test_result_3); EXPECT_THAT(error, IsOk()); EXPECT_FALSE(test_result_3.cert_status & CERT_STATUS_SYMANTEC_LEGACY); @@ -2062,7 +2062,7 @@ CertVerifyResult test_result_3; error = verify_proc->Verify(cert.get(), "127.0.0.1", std::string(), - CertVerifier::VERIFY_DISABLE_SYMANTEC_ENFORCEMENT, + CertVerifyProc::VERIFY_DISABLE_SYMANTEC_ENFORCEMENT, nullptr, CertificateList(), &test_result_3); EXPECT_THAT(error, IsOk()); EXPECT_FALSE(test_result_3.cert_status & CERT_STATUS_SYMANTEC_LEGACY); @@ -3221,7 +3221,7 @@ EXPECT_TRUE(verify_result.cert_status & CERT_STATUS_SHA1_SIGNATURE_PRESENT); // ... unless VERIFY_ENABLE_SHA1_LOCAL_ANCHORS was supplied. - flags = CertVerifier::VERIFY_ENABLE_SHA1_LOCAL_ANCHORS; + flags = CertVerifyProc::VERIFY_ENABLE_SHA1_LOCAL_ANCHORS; verify_result.Reset(); error = verify_proc->Verify(cert.get(), "127.0.0.1", std::string(), flags, nullptr /* crl_set */, CertificateList(),
diff --git a/net/cert/cert_verify_proc_win.cc b/net/cert/cert_verify_proc_win.cc index 65f41ca1..272288d 100644 --- a/net/cert/cert_verify_proc_win.cc +++ b/net/cert/cert_verify_proc_win.cc
@@ -911,8 +911,7 @@ // Note: The root cert is also checked for revocation status, so that CRLSets // will cover revoked SPKIs. DWORD chain_flags = CERT_CHAIN_REVOCATION_CHECK_CHAIN; - bool rev_checking_enabled = - (flags & CertVerifier::VERIFY_REV_CHECKING_ENABLED); + bool rev_checking_enabled = (flags & VERIFY_REV_CHECKING_ENABLED); if (rev_checking_enabled) { verify_result->cert_status |= CERT_STATUS_REV_CHECKING_ENABLED; } else { @@ -1067,7 +1066,7 @@ CertVerifyResult temp_verify_result = *verify_result; GetCertChainInfo(chain_context, verify_result); if (!verify_result->is_issued_by_known_root && - (flags & CertVerifier::VERIFY_REV_CHECKING_REQUIRED_LOCAL_ANCHORS)) { + (flags & VERIFY_REV_CHECKING_REQUIRED_LOCAL_ANCHORS)) { *verify_result = temp_verify_result; rev_checking_enabled = true;
diff --git a/net/cert/mock_cert_verifier.h b/net/cert/mock_cert_verifier.h index 77b403a..db7bea5f 100644 --- a/net/cert/mock_cert_verifier.h +++ b/net/cert/mock_cert_verifier.h
@@ -33,6 +33,7 @@ CompletionOnceCallback callback, std::unique_ptr<Request>* out_req, const NetLogWithSource& net_log) override; + void SetConfig(const Config& config) override {} // Sets the default return value for Verify() for certificates/hosts that do // not have explicit results added via the AddResult*() methods.
diff --git a/net/cert/multi_threaded_cert_verifier.cc b/net/cert/multi_threaded_cert_verifier.cc index 7ebdf94..217d9046 100644 --- a/net/cert/multi_threaded_cert_verifier.cc +++ b/net/cert/multi_threaded_cert_verifier.cc
@@ -5,6 +5,7 @@ #include "net/cert/multi_threaded_cert_verifier.h" #include <algorithm> +#include <iterator> #include <utility> #include "base/bind.h" @@ -119,6 +120,21 @@ CertVerifyResult result; }; +int GetFlagsForConfig(const CertVerifier::Config& config) { + int flags = 0; + + if (config.enable_rev_checking) + flags |= CertVerifyProc::VERIFY_REV_CHECKING_ENABLED; + if (config.require_rev_checking_local_anchors) + flags |= CertVerifyProc::VERIFY_REV_CHECKING_REQUIRED_LOCAL_ANCHORS; + if (config.enable_sha1_local_anchors) + flags |= CertVerifyProc::VERIFY_ENABLE_SHA1_LOCAL_ANCHORS; + if (config.disable_symantec_enforcement) + flags |= CertVerifyProc::VERIFY_DISABLE_SYMANTEC_ENFORCEMENT; + + return flags; +} + } // namespace // Represents the output and result callback of a request. The @@ -225,15 +241,22 @@ // Posts a task to TaskScheduler to do the verification. Once the verification // has completed, it will call OnJobCompleted() on the origin thread. void Start(const scoped_refptr<CertVerifyProc>& verify_proc, + const CertVerifier::Config& config, + uint32_t config_id, const scoped_refptr<CRLSet>& crl_set) { + int flags = GetFlagsForConfig(config); + if (key_.flags() & CertVerifier::VERIFY_DISABLE_NETWORK_FETCHES) { + flags &= ~CertVerifyProc::VERIFY_REV_CHECKING_ENABLED; + flags &= ~CertVerifyProc::VERIFY_REV_CHECKING_REQUIRED_LOCAL_ANCHORS; + } base::PostTaskWithTraitsAndReplyWithResult( FROM_HERE, {base::MayBlock(), base::TaskShutdownBehavior::CONTINUE_ON_SHUTDOWN}, base::BindOnce(&DoVerifyOnWorkerThread, verify_proc, key_.certificate(), - key_.hostname(), key_.ocsp_response(), key_.flags(), - crl_set, key_.additional_trust_anchors()), + key_.hostname(), key_.ocsp_response(), flags, crl_set, + key_.additional_trust_anchors()), base::BindOnce(&CertVerifierJob::OnJobCompleted, - weak_ptr_factory_.GetWeakPtr(), crl_set)); + weak_ptr_factory_.GetWeakPtr(), config_id, crl_set)); } ~CertVerifierJob() { @@ -290,14 +313,16 @@ } } - void OnJobCompleted(scoped_refptr<CRLSet> crl_set, + void OnJobCompleted(uint32_t config_id, + scoped_refptr<CRLSet> crl_set, std::unique_ptr<ResultHelper> verify_result) { TRACE_EVENT0(kNetTracingCategory, "CertVerifierJob::OnJobCompleted"); std::unique_ptr<CertVerifierJob> keep_alive = cert_verifier_->RemoveJob(this); LogMetrics(*verify_result); - if (cert_verifier_->verify_complete_callback_) { + if (cert_verifier_->verify_complete_callback_ && + config_id == cert_verifier_->config_id_) { cert_verifier_->verify_complete_callback_.Run( key_, std::move(crl_set), net_log_, verify_result->error, verify_result->result, base::TimeTicks::Now() - start_time_, @@ -374,10 +399,10 @@ std::unique_ptr<CertVerifierJob> new_job = std::make_unique<CertVerifierJob>(params, net_log.net_log(), this); - new_job->Start(verify_proc_, crl_set); + new_job->Start(verify_proc_, config_, config_id_, crl_set); job = new_job.get(); - inflight_[job] = std::move(new_job); + joinable_[job] = std::move(new_job); if (requests_ == 1) job->set_is_first_job(true); @@ -389,6 +414,17 @@ return ERR_IO_PENDING; } +void MultiThreadedCertVerifier::SetConfig(const CertVerifier::Config& config) { + ++config_id_; + config_ = config; + + // In C++17, this would be a .merge() call to combine |joinable_| into + // |inflight_|. + inflight_.insert(std::make_move_iterator(joinable_.begin()), + std::make_move_iterator(joinable_.end())); + joinable_.clear(); +} + bool MultiThreadedCertVerifier::JobComparator::operator()( const CertVerifierJob* job1, const CertVerifierJob* job2) const { @@ -399,7 +435,8 @@ scoped_refptr<CertVerifyProc> verify_proc, VerifyCompleteCallback verify_complete_callback, bool should_record_histograms) - : requests_(0), + : config_id_(0), + requests_(0), inflight_joins_(0), verify_proc_(verify_proc), verify_complete_callback_(std::move(verify_complete_callback)), @@ -408,6 +445,16 @@ std::unique_ptr<CertVerifierJob> MultiThreadedCertVerifier::RemoveJob( CertVerifierJob* job) { DCHECK_CALLED_ON_VALID_THREAD(thread_checker_); + + // See if it's a job from the current generation. + auto joinable_it = joinable_.find(job); + if (joinable_it != joinable_.end()) { + std::unique_ptr<CertVerifierJob> job_ptr = std::move(joinable_it->second); + joinable_.erase(joinable_it); + return job_ptr; + } + + // Otherwise, find it and remove it from previous generations. auto it = inflight_.find(job); DCHECK(it != inflight_.end()); std::unique_ptr<CertVerifierJob> job_ptr = std::move(it->second); @@ -428,9 +475,9 @@ // The JobSet is kept in sorted order so items can be found using binary // search. - auto it = std::lower_bound(inflight_.begin(), inflight_.end(), key, + auto it = std::lower_bound(joinable_.begin(), joinable_.end(), key, JobToRequestParamsComparator()); - if (it != inflight_.end() && !(key < it->first->key())) + if (it != joinable_.end() && !(key < it->first->key())) return it->first; return nullptr; }
diff --git a/net/cert/multi_threaded_cert_verifier.h b/net/cert/multi_threaded_cert_verifier.h index 13c02e7..4ce98ca 100644 --- a/net/cert/multi_threaded_cert_verifier.h +++ b/net/cert/multi_threaded_cert_verifier.h
@@ -67,6 +67,7 @@ CompletionOnceCallback callback, std::unique_ptr<Request>* out_req, const NetLogWithSource& net_log) override; + void SetConfig(const CertVerifier::Config& config) override; private: struct JobToRequestParamsComparator; @@ -88,8 +89,8 @@ VerifyCompleteCallback verify_complete_callback, bool should_record_histograms); - // Returns an inflight job for |key|. If there is no such job then returns - // null. + // Returns an inflight job for |key|, if it can be joined. If there is no + // such job then returns null. CertVerifierJob* FindJob(const RequestParams& key); // Removes |job| from the inflight set, and passes ownership back to the @@ -100,13 +101,23 @@ uint64_t requests() const { return requests_; } uint64_t inflight_joins() const { return inflight_joins_; } - // inflight_ holds the jobs for which an active verification is taking place, - // mapping the job's raw pointer to an owned pointer. Would be a - // set<unique_ptr> but extraction of owned objects from a set of owned types - // doesn't come until C++17. + // |joinable_| holds the jobs for which an active verification is taking + // place and can be joined by new requests (e.g. the config is the same), + // mapping the job's raw pointer to an owned pointer. + // TODO(rsleevi): Once C++17 is supported, switch this to be a std::set<>, + // which supports extracting owned objects from the set. + std::map<CertVerifierJob*, std::unique_ptr<CertVerifierJob>, JobComparator> + joinable_; + + // |inflight_| contains all jobs that are still undergoing active + // verification, but which can no longer be joined - such as due to the + // underlying configuration changing. std::map<CertVerifierJob*, std::unique_ptr<CertVerifierJob>, JobComparator> inflight_; + uint32_t config_id_; + Config config_; + uint64_t requests_; uint64_t inflight_joins_;
diff --git a/net/cert/multi_threaded_cert_verifier_unittest.cc b/net/cert/multi_threaded_cert_verifier_unittest.cc index 74508e6..36dc29c 100644 --- a/net/cert/multi_threaded_cert_verifier_unittest.cc +++ b/net/cert/multi_threaded_cert_verifier_unittest.cc
@@ -25,6 +25,9 @@ using net::test::IsError; using net::test::IsOk; +using testing::_; +using testing::DoAll; +using testing::Return; namespace net { @@ -36,36 +39,53 @@ class MockCertVerifyProc : public CertVerifyProc { public: - MockCertVerifyProc() = default; + MOCK_METHOD7(VerifyInternal, + int(X509Certificate*, + const std::string&, + const std::string&, + int, + CRLSet*, + const CertificateList&, + CertVerifyResult*)); + MOCK_CONST_METHOD0(SupportsAdditionalTrustAnchors, bool()); private: ~MockCertVerifyProc() override = default; - - // CertVerifyProc implementation - bool SupportsAdditionalTrustAnchors() const override { return false; } - - int VerifyInternal(X509Certificate* cert, - const std::string& hostname, - const std::string& ocsp_response, - int flags, - CRLSet* crl_set, - const CertificateList& additional_trust_anchors, - CertVerifyResult* verify_result) override { - verify_result->Reset(); - verify_result->verified_cert = cert; - verify_result->cert_status = CERT_STATUS_COMMON_NAME_INVALID; - return ERR_CERT_COMMON_NAME_INVALID; - } }; +ACTION(SetCertVerifyResult) { + X509Certificate* cert = arg0; + CertVerifyResult* result = arg6; + result->Reset(); + result->verified_cert = cert; + result->cert_status = CERT_STATUS_COMMON_NAME_INVALID; +} + +ACTION(SetCertVerifyRevokedResult) { + X509Certificate* cert = arg0; + CertVerifyResult* result = arg6; + result->Reset(); + result->verified_cert = cert; + result->cert_status = CERT_STATUS_REVOKED; +} + } // namespace class MultiThreadedCertVerifierTest : public TestWithScopedTaskEnvironment { public: - MultiThreadedCertVerifierTest() : verifier_(new MockCertVerifyProc()) {} + MultiThreadedCertVerifierTest() + : mock_verify_proc_(base::MakeRefCounted<MockCertVerifyProc>()), + verifier_(mock_verify_proc_) { + EXPECT_CALL(*mock_verify_proc_, SupportsAdditionalTrustAnchors()) + .WillRepeatedly(Return(true)); + EXPECT_CALL(*mock_verify_proc_, VerifyInternal(_, _, _, _, _, _, _)) + .WillRepeatedly( + DoAll(SetCertVerifyResult(), Return(ERR_CERT_COMMON_NAME_INVALID))); + } ~MultiThreadedCertVerifierTest() override = default; protected: + scoped_refptr<MockCertVerifyProc> mock_verify_proc_; MultiThreadedCertVerifier verifier_; }; @@ -256,4 +276,53 @@ ASSERT_EQ(2u, verifier_.inflight_joins()); } +// Tests propagation of configuration options into CertVerifyProc flags +TEST_F(MultiThreadedCertVerifierTest, ConvertsConfigToFlags) { + base::FilePath certs_dir = GetTestCertsDirectory(); + scoped_refptr<X509Certificate> test_cert( + ImportCertFromFile(certs_dir, "ok_cert.pem")); + ASSERT_TRUE(test_cert); + + const struct TestConfig { + bool CertVerifier::Config::*config_ptr; + int expected_flag; + } kTestConfig[] = { + {&CertVerifier::Config::enable_rev_checking, + CertVerifyProc::VERIFY_REV_CHECKING_ENABLED}, + {&CertVerifier::Config::require_rev_checking_local_anchors, + CertVerifyProc::VERIFY_REV_CHECKING_REQUIRED_LOCAL_ANCHORS}, + {&CertVerifier::Config::enable_sha1_local_anchors, + CertVerifyProc::VERIFY_ENABLE_SHA1_LOCAL_ANCHORS}, + {&CertVerifier::Config::disable_symantec_enforcement, + CertVerifyProc::VERIFY_DISABLE_SYMANTEC_ENFORCEMENT}, + }; + for (const auto& test_config : kTestConfig) { + CertVerifier::Config config; + config.*test_config.config_ptr = true; + + verifier_.SetConfig(config); + + EXPECT_CALL(*mock_verify_proc_, + VerifyInternal(_, _, _, test_config.expected_flag, _, _, _)) + .WillRepeatedly( + DoAll(SetCertVerifyRevokedResult(), Return(ERR_CERT_REVOKED))); + + CertVerifyResult verify_result; + TestCompletionCallback callback; + std::unique_ptr<CertVerifier::Request> request; + int error = verifier_.Verify( + CertVerifier::RequestParams(test_cert, "www.example.com", 0, + std::string(), CertificateList()), + nullptr, &verify_result, callback.callback(), &request, + NetLogWithSource()); + ASSERT_THAT(error, IsError(ERR_IO_PENDING)); + EXPECT_TRUE(request); + error = callback.WaitForResult(); + EXPECT_TRUE(IsCertificateError(error)); + EXPECT_THAT(error, IsError(ERR_CERT_REVOKED)); + + testing::Mock::VerifyAndClearExpectations(mock_verify_proc_.get()); + } +} + } // namespace net
diff --git a/net/data/ssl/certificates/README b/net/data/ssl/certificates/README index ed5dbf47..3594a94 100644 --- a/net/data/ssl/certificates/README +++ b/net/data/ssl/certificates/README
@@ -66,6 +66,9 @@ Trust the certificate in verisign_class3_g5_crosssigned.pem (Generated by scripts/generate-verisign_class3_g5_crosssigned-trusted-keychain.sh) +- www.ahrn.com.pem: A certificate issued by the Legacy Symantec PKI in 2014, + expires on 2019-10-27. + ===== Manually generated certificates - client.p12 : A PKCS #12 file containing a client certificate and a private key created for testing. The password is "12345".
diff --git a/net/data/ssl/certificates/www.ahrn.com.pem b/net/data/ssl/certificates/www.ahrn.com.pem new file mode 100644 index 0000000..b050b18 --- /dev/null +++ b/net/data/ssl/certificates/www.ahrn.com.pem
@@ -0,0 +1,299 @@ +Certificate: + Data: + Version: 3 (0x2) + Serial Number: + 4b:55:a8:9e:db:00:a8:b5:62:d7:5c:a3:2c:b3:70:0f + Signature Algorithm: sha256WithRSAEncryption + Issuer: C = US, O = Symantec Corporation, OU = Symantec Trust Network, CN = Symantec Class 3 Secure Server CA - G4 + Validity + Not Before: Oct 28 00:00:00 2014 GMT + Not After : Oct 27 23:59:59 2019 GMT + Subject: C = US, ST = Wisconsin, L = Waterford, O = Runzheimer International LTD, OU = IT, CN = www.ahrn.com + Subject Public Key Info: + Public Key Algorithm: rsaEncryption + Public-Key: (2048 bit) + Modulus: + 00:d1:30:e0:95:77:78:37:76:72:63:76:d8:7d:f7: + e0:ca:c8:3f:3d:43:70:bb:ed:50:8f:8e:50:16:0d: + 28:64:8f:e6:0c:5c:eb:cd:a9:24:93:1a:51:fa:9f: + 7f:52:da:32:7a:1d:86:7c:b7:3f:be:be:76:a3:4f: + 4e:b9:ab:38:79:69:9a:ab:1f:77:7a:94:80:77:5f: + 6c:c8:25:2b:b0:9d:60:0a:78:88:27:33:c5:ac:1a: + 35:2f:a9:65:f9:c0:0e:8f:8f:e5:66:06:df:bb:60: + bf:67:85:2f:c1:26:57:78:ac:ce:dd:39:a9:fd:04: + 17:f3:0b:53:bb:b4:76:fc:fb:e3:2e:21:87:fd:40: + 4f:12:9a:43:8f:b3:15:4a:6f:bc:0c:0b:4e:94:33: + 06:a5:2c:66:50:ff:7a:2f:6f:f7:83:83:9d:a8:52: + 9a:36:97:ea:97:88:96:96:0b:e9:d9:c6:37:7c:e1: + b4:63:b7:4a:a8:2c:e6:75:fe:0f:33:dd:28:7a:5a: + 4a:7a:c8:26:b1:cb:7d:1a:f4:b1:63:5b:c7:01:3c: + 53:86:33:4e:b6:5a:2c:81:42:41:12:85:60:a7:38: + a7:7b:05:ea:b0:7b:ef:ec:f4:ba:5d:8b:63:dc:ba: + 3d:aa:78:d8:66:9c:d1:35:b3:0d:97:a3:62:95:1f: + 64:af + Exponent: 65537 (0x10001) + X509v3 extensions: + X509v3 Subject Alternative Name: + DNS:www.ahrn.com + X509v3 Basic Constraints: + CA:FALSE + X509v3 Key Usage: critical + Digital Signature, Key Encipherment + X509v3 CRL Distribution Points: + + Full Name: + URI:http://ss.symcb.com/ss.crl + + X509v3 Certificate Policies: + Policy: 2.16.840.1.113733.1.7.54 + CPS: https://d.symcb.com/cps + User Notice: + Explicit Text: https://d.symcb.com/rpa + + X509v3 Extended Key Usage: + TLS Web Server Authentication, TLS Web Client Authentication + X509v3 Authority Key Identifier: + keyid:5F:60:CF:61:90:55:DF:84:43:14:8A:60:2A:B2:F5:7A:F4:43:18:EF + + Authority Information Access: + OCSP - URI:http://ss.symcd.com + CA Issuers - URI:http://ss.symcb.com/ss.crt + + Signature Algorithm: sha256WithRSAEncryption + b0:e7:ed:25:04:03:bc:86:9a:1c:4d:93:99:c1:a0:18:6d:61: + 4d:ab:e1:a8:74:c0:34:71:99:1b:90:9a:62:88:b4:92:ca:c5: + 3a:ba:b3:a6:4f:6a:00:3f:75:9b:fe:69:d7:68:8c:26:63:a8: + 22:ee:8e:ed:3e:20:2e:54:5d:c7:d3:82:ac:18:42:28:ef:7b: + 69:f3:86:f6:55:d1:67:1b:cf:28:0c:0f:82:2b:d6:f4:07:4b: + de:57:3d:02:3e:88:01:59:3d:7c:cd:80:68:61:e3:ac:0b:7f: + 16:4e:1e:54:9b:7d:80:26:31:eb:0c:da:f4:53:5e:bc:62:2a: + 8a:ff:6a:df:f5:b4:07:89:82:b4:67:68:68:54:b9:d5:1b:a0: + f1:35:de:e7:18:b0:64:08:4f:93:13:88:02:8a:9f:42:c5:c3: + 67:a0:d7:aa:dd:54:84:8d:c7:5a:a5:3c:5e:d1:9a:1c:3d:36: + 45:6a:66:a3:10:ad:3e:bf:95:a2:27:8d:a6:7a:7a:6b:59:d3: + 66:79:10:05:fb:3f:0c:f6:b3:b5:85:83:e1:a4:49:02:56:db: + 5b:9d:36:ea:59:e7:b5:f4:9a:aa:59:21:ab:54:a7:fc:b7:15: + 0c:41:29:39:15:ff:83:1f:5e:d3:73:85:96:6e:a4:dc:01:bd: + 7d:21:34:3f +-----BEGIN CERTIFICATE----- +MIIE8DCCA9igAwIBAgIQS1WontsAqLVi11yjLLNwDzANBgkqhkiG9w0BAQsFADB+ +MQswCQYDVQQGEwJVUzEdMBsGA1UEChMUU3ltYW50ZWMgQ29ycG9yYXRpb24xHzAd +BgNVBAsTFlN5bWFudGVjIFRydXN0IE5ldHdvcmsxLzAtBgNVBAMTJlN5bWFudGVj +IENsYXNzIDMgU2VjdXJlIFNlcnZlciBDQSAtIEc0MB4XDTE0MTAyODAwMDAwMFoX +DTE5MTAyNzIzNTk1OVowgYAxCzAJBgNVBAYTAlVTMRIwEAYDVQQIDAlXaXNjb25z +aW4xEjAQBgNVBAcMCVdhdGVyZm9yZDElMCMGA1UECgwcUnVuemhlaW1lciBJbnRl +cm5hdGlvbmFsIExURDELMAkGA1UECwwCSVQxFTATBgNVBAMMDHd3dy5haHJuLmNv +bTCCASIwDQYJKoZIhvcNAQEBBQADggEPADCCAQoCggEBANEw4JV3eDd2cmN22H33 +4MrIPz1DcLvtUI+OUBYNKGSP5gxc682pJJMaUfqff1LaMnodhny3P76+dqNPTrmr +OHlpmqsfd3qUgHdfbMglK7CdYAp4iCczxawaNS+pZfnADo+P5WYG37tgv2eFL8Em +V3iszt05qf0EF/MLU7u0dvz74y4hh/1ATxKaQ4+zFUpvvAwLTpQzBqUsZlD/ei9v +94ODnahSmjaX6peIlpYL6dnGN3zhtGO3Sqgs5nX+DzPdKHpaSnrIJrHLfRr0sWNb +xwE8U4YzTrZaLIFCQRKFYKc4p3sF6rB77+z0ul2LY9y6Pap42Gac0TWzDZejYpUf +ZK8CAwEAAaOCAWUwggFhMBcGA1UdEQQQMA6CDHd3dy5haHJuLmNvbTAJBgNVHRME +AjAAMA4GA1UdDwEB/wQEAwIFoDArBgNVHR8EJDAiMCCgHqAchhpodHRwOi8vc3Mu +c3ltY2IuY29tL3NzLmNybDBlBgNVHSAEXjBcMFoGCmCGSAGG+EUBBzYwTDAjBggr +BgEFBQcCARYXaHR0cHM6Ly9kLnN5bWNiLmNvbS9jcHMwJQYIKwYBBQUHAgIwGQwX +aHR0cHM6Ly9kLnN5bWNiLmNvbS9ycGEwHQYDVR0lBBYwFAYIKwYBBQUHAwEGCCsG +AQUFBwMCMB8GA1UdIwQYMBaAFF9gz2GQVd+EQxSKYCqy9Xr0QxjvMFcGCCsGAQUF +BwEBBEswSTAfBggrBgEFBQcwAYYTaHR0cDovL3NzLnN5bWNkLmNvbTAmBggrBgEF +BQcwAoYaaHR0cDovL3NzLnN5bWNiLmNvbS9zcy5jcnQwDQYJKoZIhvcNAQELBQAD +ggEBALDn7SUEA7yGmhxNk5nBoBhtYU2r4ah0wDRxmRuQmmKItJLKxTq6s6ZPagA/ +dZv+addojCZjqCLuju0+IC5UXcfTgqwYQijve2nzhvZV0WcbzygMD4Ir1vQHS95X +PQI+iAFZPXzNgGhh46wLfxZOHlSbfYAmMesM2vRTXrxiKor/at/1tAeJgrRnaGhU +udUboPE13ucYsGQIT5MTiAKKn0LFw2eg16rdVISNx1qlPF7Rmhw9NkVqZqMQrT6/ +laInjaZ6emtZ02Z5EAX7Pwz2s7WFg+GkSQJW21udNupZ57X0mqpZIatUp/y3FQxB +KTkV/4MfXtNzhZZupNwBvX0hND8= +-----END CERTIFICATE----- +Certificate: + Data: + Version: 3 (0x2) + Serial Number: + 13:b3:e3:02:18:03:97:66:8d:50:34:e0:e6:74:e2:8d + Signature Algorithm: sha256WithRSAEncryption + Issuer: C = US, O = "VeriSign, Inc.", OU = VeriSign Trust Network, OU = "(c) 2006 VeriSign, Inc. - For authorized use only", CN = VeriSign Class 3 Public Primary Certification Authority - G5 + Validity + Not Before: Oct 31 00:00:00 2013 GMT + Not After : Oct 30 23:59:59 2023 GMT + Subject: C = US, O = Symantec Corporation, OU = Symantec Trust Network, CN = Symantec Class 3 Secure Server CA - G4 + Subject Public Key Info: + Public Key Algorithm: rsaEncryption + Public-Key: (2048 bit) + Modulus: + 00:b2:d8:05:ca:1c:74:2d:b5:17:56:39:c5:4a:52: + 09:96:e8:4b:d8:0c:f1:68:9f:9a:42:28:62:c3:a5: + 30:53:7e:55:11:82:5b:03:7a:0d:2f:e1:79:04:c9: + b4:96:77:19:81:01:94:59:f9:bc:f7:7a:99:27:82: + 2d:b7:83:dd:5a:27:7f:b2:03:7a:9c:53:25:e9:48: + 1f:46:4f:c8:9d:29:f8:be:79:56:f6:f7:fd:d9:3a: + 68:da:8b:4b:82:33:41:12:c3:c8:3c:cc:d6:96:7a: + 84:21:1a:22:04:03:27:17:8b:1c:68:61:93:0f:0e: + 51:80:33:1d:b4:b5:ce:eb:7e:d0:62:ac:ee:b3:7b: + 01:74:ef:69:35:eb:ca:d5:3d:a9:ee:97:98:ca:8d: + aa:44:0e:25:99:4a:15:96:a4:ce:6d:02:54:1f:2a: + 6a:26:e2:06:3a:63:48:ac:b4:4c:d1:75:93:50:ff: + 13:2f:d6:da:e1:c6:18:f5:9f:c9:25:5d:f3:00:3a: + de:26:4d:b4:29:09:cd:0f:3d:23:6f:16:4a:81:16: + fb:f2:83:10:c3:b8:d6:d8:55:32:3d:f1:bd:0f:bd: + 8c:52:95:4a:16:97:7a:52:21:63:75:2f:16:f9:c4: + 66:be:f5:b5:09:d8:ff:27:00:cd:44:7c:6f:4b:3f: + b0:f7 + Exponent: 65537 (0x10001) + X509v3 extensions: + X509v3 Basic Constraints: critical + CA:TRUE, pathlen:0 + X509v3 CRL Distribution Points: + + Full Name: + URI:http://s1.symcb.com/pca3-g5.crl + + X509v3 Key Usage: critical + Certificate Sign, CRL Sign + X509v3 Subject Alternative Name: + DirName:/CN=SymantecPKI-1-534 + X509v3 Subject Key Identifier: + 5F:60:CF:61:90:55:DF:84:43:14:8A:60:2A:B2:F5:7A:F4:43:18:EF + X509v3 Certificate Policies: + Policy: 2.23.140.1.2.2 + CPS: http://www.symauth.com/cps + User Notice: + Explicit Text: http://www.symauth.com/rpa + + Authority Information Access: + OCSP - URI:http://s2.symcb.com + + X509v3 Authority Key Identifier: + keyid:7F:D3:65:A7:C2:DD:EC:BB:F0:30:09:F3:43:39:FA:02:AF:33:31:33 + + Signature Algorithm: sha256WithRSAEncryption + 16:19:9a:85:c5:85:ea:47:56:4f:40:37:ad:34:e5:a3:2d:74: + 82:be:3a:cd:25:fe:62:70:25:bb:98:09:35:be:77:80:5b:ae: + 28:66:e7:37:34:c0:da:0f:b5:b4:2e:97:78:3e:c8:53:3f:a6: + b1:ae:d5:a4:fd:bc:43:af:7a:20:7b:c8:15:a6:ed:5a:e5:1c: + 8c:a6:81:ef:61:a4:a8:50:76:bd:d0:e0:a2:95:99:78:5f:50: + 88:89:e6:e0:8a:db:ae:f2:e5:be:7a:7d:a0:a9:cf:48:ef:7b: + c6:09:d0:1a:46:11:c5:f8:99:90:5e:6f:c5:91:0d:f6:9e:3f: + 78:95:fe:84:af:73:64:ec:8d:6a:d2:6e:70:08:00:cc:88:a9: + 4e:85:95:f3:31:8a:9e:10:e2:62:23:3d:0b:5c:97:96:7e:db: + 36:64:fb:c9:d6:55:44:21:77:0f:0a:64:26:e2:15:2f:96:31: + 50:eb:f5:bd:ee:1d:e3:dd:d1:50:7e:c4:86:9a:31:fe:a8:7f: + cd:2b:bc:93:c1:2f:67:60:f0:30:59:0d:d6:f5:05:2b:55:31: + 8f:60:b0:b9:f3:1a:de:bc:8d:50:aa:12:39:87:54:38:2a:b7: + 9b:1c:1f:51:ef:9e:a0:fc:8e:fd:c4:4a:de:8a:62:82:9c:a1: + 9d:97:5c:92 +-----BEGIN CERTIFICATE----- +MIIFNDCCBBygAwIBAgIQE7PjAhgDl2aNUDTg5nTijTANBgkqhkiG9w0BAQsFADCB +yjELMAkGA1UEBhMCVVMxFzAVBgNVBAoTDlZlcmlTaWduLCBJbmMuMR8wHQYDVQQL +ExZWZXJpU2lnbiBUcnVzdCBOZXR3b3JrMTowOAYDVQQLEzEoYykgMjAwNiBWZXJp +U2lnbiwgSW5jLiAtIEZvciBhdXRob3JpemVkIHVzZSBvbmx5MUUwQwYDVQQDEzxW +ZXJpU2lnbiBDbGFzcyAzIFB1YmxpYyBQcmltYXJ5IENlcnRpZmljYXRpb24gQXV0 +aG9yaXR5IC0gRzUwHhcNMTMxMDMxMDAwMDAwWhcNMjMxMDMwMjM1OTU5WjB+MQsw +CQYDVQQGEwJVUzEdMBsGA1UEChMUU3ltYW50ZWMgQ29ycG9yYXRpb24xHzAdBgNV +BAsTFlN5bWFudGVjIFRydXN0IE5ldHdvcmsxLzAtBgNVBAMTJlN5bWFudGVjIENs +YXNzIDMgU2VjdXJlIFNlcnZlciBDQSAtIEc0MIIBIjANBgkqhkiG9w0BAQEFAAOC +AQ8AMIIBCgKCAQEAstgFyhx0LbUXVjnFSlIJluhL2AzxaJ+aQihiw6UwU35VEYJb +A3oNL+F5BMm0lncZgQGUWfm893qZJ4Itt4PdWid/sgN6nFMl6UgfRk/InSn4vnlW +9vf92Tpo2otLgjNBEsPIPMzWlnqEIRoiBAMnF4scaGGTDw5RgDMdtLXO637QYqzu +s3sBdO9pNevK1T2p7peYyo2qRA4lmUoVlqTObQJUHypqJuIGOmNIrLRM0XWTUP8T +L9ba4cYY9Z/JJV3zADreJk20KQnNDz0jbxZKgRb78oMQw7jW2FUyPfG9D72MUpVK +Fpd6UiFjdS8W+cRmvvW1Cdj/JwDNRHxvSz+w9wIDAQABo4IBXzCCAVswEgYDVR0T +AQH/BAgwBgEB/wIBADAwBgNVHR8EKTAnMCWgI6Ahhh9odHRwOi8vczEuc3ltY2Iu +Y29tL3BjYTMtZzUuY3JsMA4GA1UdDwEB/wQEAwIBBjApBgNVHREEIjAgpB4wHDEa +MBgGA1UEAxMRU3ltYW50ZWNQS0ktMS01MzQwHQYDVR0OBBYEFF9gz2GQVd+EQxSK +YCqy9Xr0QxjvMGcGA1UdIARgMF4wXAYGZ4EMAQICMFIwJgYIKwYBBQUHAgEWGmh0 +dHA6Ly93d3cuc3ltYXV0aC5jb20vY3BzMCgGCCsGAQUFBwICMBwaGmh0dHA6Ly93 +d3cuc3ltYXV0aC5jb20vcnBhMC8GCCsGAQUFBwEBBCMwITAfBggrBgEFBQcwAYYT +aHR0cDovL3MyLnN5bWNiLmNvbTAfBgNVHSMEGDAWgBR/02Wnwt3su/AwCfNDOfoC +rzMxMzANBgkqhkiG9w0BAQsFAAOCAQEAFhmahcWF6kdWT0A3rTTloy10gr46zSX+ +YnAlu5gJNb53gFuuKGbnNzTA2g+1tC6XeD7IUz+msa7VpP28Q696IHvIFabtWuUc +jKaB72GkqFB2vdDgopWZeF9QiInm4IrbrvLlvnp9oKnPSO97xgnQGkYRxfiZkF5v +xZEN9p4/eJX+hK9zZOyNatJucAgAzIipToWV8zGKnhDiYiM9C1yXln7bNmT7ydZV +RCF3DwpkJuIVL5YxUOv1ve4d493RUH7Ehpox/qh/zSu8k8EvZ2DwMFkN1vUFK1Ux +j2CwufMa3ryNUKoSOYdUOCq3mxwfUe+eoPyO/cRK3opigpyhnZdckg== +-----END CERTIFICATE----- +Certificate: + Data: + Version: 3 (0x2) + Serial Number: + 18:da:d1:9e:26:7d:e8:bb:4a:21:58:cd:cc:6b:3b:4a + Signature Algorithm: sha1WithRSAEncryption + Issuer: C = US, O = "VeriSign, Inc.", OU = VeriSign Trust Network, OU = "(c) 2006 VeriSign, Inc. - For authorized use only", CN = VeriSign Class 3 Public Primary Certification Authority - G5 + Validity + Not Before: Nov 8 00:00:00 2006 GMT + Not After : Jul 16 23:59:59 2036 GMT + Subject: C = US, O = "VeriSign, Inc.", OU = VeriSign Trust Network, OU = "(c) 2006 VeriSign, Inc. - For authorized use only", CN = VeriSign Class 3 Public Primary Certification Authority - G5 + Subject Public Key Info: + Public Key Algorithm: rsaEncryption + Public-Key: (2048 bit) + Modulus: + 00:af:24:08:08:29:7a:35:9e:60:0c:aa:e7:4b:3b: + 4e:dc:7c:bc:3c:45:1c:bb:2b:e0:fe:29:02:f9:57: + 08:a3:64:85:15:27:f5:f1:ad:c8:31:89:5d:22:e8: + 2a:aa:a6:42:b3:8f:f8:b9:55:b7:b1:b7:4b:b3:fe: + 8f:7e:07:57:ec:ef:43:db:66:62:15:61:cf:60:0d: + a4:d8:de:f8:e0:c3:62:08:3d:54:13:eb:49:ca:59: + 54:85:26:e5:2b:8f:1b:9f:eb:f5:a1:91:c2:33:49: + d8:43:63:6a:52:4b:d2:8f:e8:70:51:4d:d1:89:69: + 7b:c7:70:f6:b3:dc:12:74:db:7b:5d:4b:56:d3:96: + bf:15:77:a1:b0:f4:a2:25:f2:af:1c:92:67:18:e5: + f4:06:04:ef:90:b9:e4:00:e4:dd:3a:b5:19:ff:02: + ba:f4:3c:ee:e0:8b:eb:37:8b:ec:f4:d7:ac:f2:f6: + f0:3d:af:dd:75:91:33:19:1d:1c:40:cb:74:24:19: + 21:93:d9:14:fe:ac:2a:52:c7:8f:d5:04:49:e4:8d: + 63:47:88:3c:69:83:cb:fe:47:bd:2b:7e:4f:c5:95: + ae:0e:9d:d4:d1:43:c0:67:73:e3:14:08:7e:e5:3f: + 9f:73:b8:33:0a:cf:5d:3f:34:87:96:8a:ee:53:e8: + 25:15 + Exponent: 65537 (0x10001) + X509v3 extensions: + X509v3 Basic Constraints: critical + CA:TRUE + X509v3 Key Usage: critical + Certificate Sign, CRL Sign + 1.3.6.1.5.5.7.1.12: + 0_.].[0Y0W0U..image/gif0!0.0...+..............k...j.H.,{..0%.#http://logo.verisign.com/vslogo.gif + X509v3 Subject Key Identifier: + 7F:D3:65:A7:C2:DD:EC:BB:F0:30:09:F3:43:39:FA:02:AF:33:31:33 + Signature Algorithm: sha1WithRSAEncryption + 93:24:4a:30:5f:62:cf:d8:1a:98:2f:3d:ea:dc:99:2d:bd:77: + f6:a5:79:22:38:ec:c4:a7:a0:78:12:ad:62:0e:45:70:64:c5: + e7:97:66:2d:98:09:7e:5f:af:d6:cc:28:65:f2:01:aa:08:1a: + 47:de:f9:f9:7c:92:5a:08:69:20:0d:d9:3e:6d:6e:3c:0d:6e: + d8:e6:06:91:40:18:b9:f8:c1:ed:df:db:41:aa:e0:96:20:c9: + cd:64:15:38:81:c9:94:ee:a2:84:29:0b:13:6f:8e:db:0c:dd: + 25:02:db:a4:8b:19:44:d2:41:7a:05:69:4a:58:4f:60:ca:7e: + 82:6a:0b:02:aa:25:17:39:b5:db:7f:e7:84:65:2a:95:8a:bd: + 86:de:5e:81:16:83:2d:10:cc:de:fd:a8:82:2a:6d:28:1f:0d: + 0b:c4:e5:e7:1a:26:19:e1:f4:11:6f:10:b5:95:fc:e7:42:05: + 32:db:ce:9d:51:5e:28:b6:9e:85:d3:5b:ef:a5:7d:45:40:72: + 8e:b7:0e:6b:0e:06:fb:33:35:48:71:b8:9d:27:8b:c4:65:5f: + 0d:86:76:9c:44:7a:f6:95:5c:f6:5d:32:08:33:a4:54:b6:18: + 3f:68:5c:f2:42:4a:85:38:54:83:5f:d1:e8:2c:f2:ac:11:d6: + a8:ed:63:6a +-----BEGIN CERTIFICATE----- +MIIE0zCCA7ugAwIBAgIQGNrRniZ96LtKIVjNzGs7SjANBgkqhkiG9w0BAQUFADCB +yjELMAkGA1UEBhMCVVMxFzAVBgNVBAoTDlZlcmlTaWduLCBJbmMuMR8wHQYDVQQL +ExZWZXJpU2lnbiBUcnVzdCBOZXR3b3JrMTowOAYDVQQLEzEoYykgMjAwNiBWZXJp +U2lnbiwgSW5jLiAtIEZvciBhdXRob3JpemVkIHVzZSBvbmx5MUUwQwYDVQQDEzxW +ZXJpU2lnbiBDbGFzcyAzIFB1YmxpYyBQcmltYXJ5IENlcnRpZmljYXRpb24gQXV0 +aG9yaXR5IC0gRzUwHhcNMDYxMTA4MDAwMDAwWhcNMzYwNzE2MjM1OTU5WjCByjEL +MAkGA1UEBhMCVVMxFzAVBgNVBAoTDlZlcmlTaWduLCBJbmMuMR8wHQYDVQQLExZW +ZXJpU2lnbiBUcnVzdCBOZXR3b3JrMTowOAYDVQQLEzEoYykgMjAwNiBWZXJpU2ln +biwgSW5jLiAtIEZvciBhdXRob3JpemVkIHVzZSBvbmx5MUUwQwYDVQQDEzxWZXJp +U2lnbiBDbGFzcyAzIFB1YmxpYyBQcmltYXJ5IENlcnRpZmljYXRpb24gQXV0aG9y +aXR5IC0gRzUwggEiMA0GCSqGSIb3DQEBAQUAA4IBDwAwggEKAoIBAQCvJAgIKXo1 +nmAMqudLO07cfLw8RRy7K+D+KQL5VwijZIUVJ/XxrcgxiV0i6CqqpkKzj/i5Vbex +t0uz/o9+B1fs70PbZmIVYc9gDaTY3vjgw2IIPVQT60nKWVSFJuUrjxuf6/WhkcIz +SdhDY2pSS9KP6HBRTdGJaXvHcPaz3BJ023tdS1bTlr8Vd6Gw9KIl8q8ckmcY5fQG +BO+QueQA5N06tRn/Arr0PO7gi+s3i+z016zy9vA9r911kTMZHRxAy3QkGSGT2RT+ +rCpSx4/VBEnkjWNHiDxpg8v+R70rfk/Fla4OndTRQ8Bnc+MUCH7lP59zuDMKz10/ +NIeWiu5T6CUVAgMBAAGjgbIwga8wDwYDVR0TAQH/BAUwAwEB/zAOBgNVHQ8BAf8E +BAMCAQYwbQYIKwYBBQUHAQwEYTBfoV2gWzBZMFcwVRYJaW1hZ2UvZ2lmMCEwHzAH +BgUrDgMCGgQUj+XTGoasjY5rw8+AatRIGCx7GS4wJRYjaHR0cDovL2xvZ28udmVy +aXNpZ24uY29tL3ZzbG9nby5naWYwHQYDVR0OBBYEFH/TZafC3ey78DAJ80M5+gKv +MzEzMA0GCSqGSIb3DQEBBQUAA4IBAQCTJEowX2LP2BqYLz3q3JktvXf2pXkiOOzE +p6B4Eq1iDkVwZMXnl2YtmAl+X6/WzChl8gGqCBpH3vn5fJJaCGkgDdk+bW48DW7Y +5gaRQBi5+MHt39tBquCWIMnNZBU4gcmU7qKEKQsTb47bDN0lAtukixlE0kF6BWlK +WE9gyn6CagsCqiUXObXbf+eEZSqVir2G3l6BFoMtEMze/aiCKm0oHw0LxOXnGiYZ +4fQRbxC1lfznQgUy286dUV4otp6F01vvpX1FQHKOtw5rDgb7MzVIcbidJ4vEZV8N +hnacRHr2lVz2XTIIM6RUthg/aFzyQkqFOFSDX9HoLPKsEdao7WNq +-----END CERTIFICATE-----
diff --git a/net/http/http_network_transaction.cc b/net/http/http_network_transaction.cc index 526e9e7d..cd6b96b 100644 --- a/net/http/http_network_transaction.cc +++ b/net/http/http_network_transaction.cc
@@ -147,9 +147,9 @@ // Now that we have an HttpRequestInfo object, update server_ssl_config_. session_->GetSSLConfig(*request_, &server_ssl_config_, &proxy_ssl_config_); - if (request_->load_flags & LOAD_DISABLE_CERT_REVOCATION_CHECKING) { - server_ssl_config_.rev_checking_enabled = false; - proxy_ssl_config_.rev_checking_enabled = false; + if (request_->load_flags & LOAD_DISABLE_CERT_NETWORK_FETCHES) { + server_ssl_config_.disable_cert_verification_network_fetches = true; + proxy_ssl_config_.disable_cert_verification_network_fetches = true; } if (HttpUtil::IsMethodSafe(request_info->method)) {
diff --git a/net/http/http_stream_factory_job.cc b/net/http/http_stream_factory_job.cc index a04327d2..75e62eb1 100644 --- a/net/http/http_stream_factory_job.cc +++ b/net/http/http_stream_factory_job.cc
@@ -863,9 +863,9 @@ if (proxy_info_.is_https() || proxy_info_.is_quic()) { InitSSLConfig(&proxy_ssl_config_, /*is_proxy=*/true); - // Disable revocation checking for HTTPS proxies since the revocation - // requests are probably going to need to go through the proxy too. - proxy_ssl_config_.rev_checking_enabled = false; + // Disable network fetches for HTTPS proxies, since the network requests + // are probably going to need to go through the proxy too. + proxy_ssl_config_.disable_cert_verification_network_fetches = true; } if (using_ssl_) { InitSSLConfig(&server_ssl_config_, /*is_proxy=*/false);
diff --git a/net/proxy_resolution/pac_file_fetcher_impl.cc b/net/proxy_resolution/pac_file_fetcher_impl.cc index 0201c27..a688c00 100644 --- a/net/proxy_resolution/pac_file_fetcher_impl.cc +++ b/net/proxy_resolution/pac_file_fetcher_impl.cc
@@ -171,7 +171,7 @@ // the proxy might be the only way to the outside world. IGNORE_LIMITS is // used to avoid blocking proxy resolution on other network requests. cur_request_->SetLoadFlags(LOAD_BYPASS_PROXY | LOAD_DISABLE_CACHE | - LOAD_DISABLE_CERT_REVOCATION_CHECKING | + LOAD_DISABLE_CERT_NETWORK_FETCHES | LOAD_IGNORE_LIMITS); // Save the caller's info for notification on completion.
diff --git a/net/proxy_resolution/pac_file_fetcher_impl_unittest.cc b/net/proxy_resolution/pac_file_fetcher_impl_unittest.cc index 029c025..b658df8 100644 --- a/net/proxy_resolution/pac_file_fetcher_impl_unittest.cc +++ b/net/proxy_resolution/pac_file_fetcher_impl_unittest.cc
@@ -154,7 +154,7 @@ int OnBeforeURLRequest(URLRequest* request, CompletionOnceCallback callback, GURL* new_url) override { - EXPECT_TRUE(request->load_flags() & LOAD_DISABLE_CERT_REVOCATION_CHECKING); + EXPECT_TRUE(request->load_flags() & LOAD_DISABLE_CERT_NETWORK_FETCHES); return OK; }
diff --git a/net/quic/crypto/proof_verifier_chromium_test.cc b/net/quic/crypto/proof_verifier_chromium_test.cc index c35ae43..af39290 100644 --- a/net/quic/crypto/proof_verifier_chromium_test.cc +++ b/net/quic/crypto/proof_verifier_chromium_test.cc
@@ -52,6 +52,7 @@ ADD_FAILURE() << "CertVerifier::Verify() should not be called"; return ERR_FAILED; } + void SetConfig(const Config& config) override {} }; // A mock CTPolicyEnforcer that returns a custom verification result.
diff --git a/net/quic/quic_chromium_client_session.cc b/net/quic/quic_chromium_client_session.cc index 39a1ae2..16a107b 100644 --- a/net/quic/quic_chromium_client_session.cc +++ b/net/quic/quic_chromium_client_session.cc
@@ -1442,7 +1442,15 @@ } NotifyRequestsOfConfirmation(OK); - // TODO(zhongyi): spin up the timer to migrate back to the default network. + // Attempt to migrate back to the default network after handshake has been + // confirmed if the session is not created on the default network. + if (migrate_session_on_network_change_v2_ && + default_network_ != NetworkChangeNotifier::kInvalidNetworkHandle && + GetDefaultSocket()->GetBoundNetwork() != default_network_) { + current_connection_migration_cause_ = ON_MIGRATE_BACK_TO_DEFAULT_NETWORK; + StartMigrateBackToDefaultNetworkTimer( + base::TimeDelta::FromSeconds(kMinRetryTimeForDefaultNetworkSecs)); + } } quic::QuicSpdySession::OnCryptoHandshakeEvent(event); }
diff --git a/net/quic/quic_stream_factory_test.cc b/net/quic/quic_stream_factory_test.cc index 1ba3ef9..da78e63 100644 --- a/net/quic/quic_stream_factory_test.cc +++ b/net/quic/quic_stream_factory_test.cc
@@ -4804,6 +4804,18 @@ quic::QUIC_HANDSHAKE_TIMEOUT); } +// Sets up a test to verify that a new connection will be created on the +// alternate network after the initial connection fails before handshake with +// signals delivered in the following order (alternate network is available): +// - the default network is not able to complete crypto handshake; +// - the original connection is closed with |quic_error|; +// - a new connection is created on the alternate network and is able to finish +// crypto handshake; +// - the new session on the alternate network attempts to migrate back to the +// default network by sending probes; +// - default network being disconnected is delivered: session will stop probing +// the original network. +// - alternate network is made by default. void QuicStreamFactoryTestBase:: TestNewConnectionOnAlternateNetworkBeforeHandshake( quic::QuicErrorCode quic_error) { @@ -4844,10 +4856,17 @@ socket_data2.AddRead(SYNCHRONOUS, ERR_IO_PENDING); socket_data2.AddWrite(SYNCHRONOUS, client_maker_.MakeAckAndRstPacket( - 4, false, GetNthClientInitiatedStreamId(0), + 5, false, GetNthClientInitiatedStreamId(0), quic::QUIC_STREAM_CANCELLED, 1, 1, 1, true)); socket_data2.AddSocketDataToFactory(socket_factory_.get()); + // Socket data for probing on the default network. + MockQuicData probing_data; + probing_data.AddRead(SYNCHRONOUS, ERR_IO_PENDING); // Hanging read. + probing_data.AddWrite(SYNCHRONOUS, + client_maker_.MakeConnectivityProbingPacket(4, false)); + probing_data.AddSocketDataToFactory(socket_factory_.get()); + // Create request and QuicHttpStream. QuicStreamRequest request(factory_.get()); EXPECT_EQ(ERR_IO_PENDING, @@ -4913,6 +4932,30 @@ EXPECT_EQ(OK, stream->ReadResponseHeaders(callback_.callback())); EXPECT_EQ(200, response.headers->response_code()); + // There should be a new task posted to migrate back to the default network. + EXPECT_EQ(1u, task_runner->GetPendingTaskCount()); + base::TimeDelta next_task_delay = task_runner->NextPendingTaskDelay(); + EXPECT_EQ(base::TimeDelta::FromSeconds(kMinRetryTimeForDefaultNetworkSecs), + next_task_delay); + task_runner->FastForwardBy(next_task_delay); + + // There should be two tasks posted. One will retry probing and the other + // will retry migrate back. + EXPECT_EQ(2u, task_runner->GetPendingTaskCount()); + next_task_delay = task_runner->NextPendingTaskDelay(); + EXPECT_EQ(base::TimeDelta::FromMilliseconds(2 * kDefaultRTTMilliSecs), + next_task_delay); + + // Deliver the signal that the default network is disconnected. + scoped_mock_network_change_notifier_->mock_network_change_notifier() + ->NotifyNetworkDisconnected(kDefaultNetworkForTests); + // Verify no connectivity probes will be sent as probing will be cancelled. + task_runner->FastForwardUntilNoTasksRemain(); + // Deliver the signal that the alternate network is made default. + scoped_mock_network_change_notifier_->mock_network_change_notifier() + ->NotifyNetworkMadeDefault(kNewNetworkForTests); + EXPECT_EQ(0u, task_runner->GetPendingTaskCount()); + stream.reset(); EXPECT_TRUE(socket_data.AllReadDataConsumed()); EXPECT_TRUE(socket_data.AllWriteDataConsumed());
diff --git a/net/ssl/ssl_config.cc b/net/ssl/ssl_config.cc index 515c410..dd7273a 100644 --- a/net/ssl/ssl_config.cc +++ b/net/ssl/ssl_config.cc
@@ -22,11 +22,7 @@ SSLConfig::CertAndStatus::~CertAndStatus() = default; SSLConfig::SSLConfig() - : rev_checking_enabled(false), - rev_checking_required_local_anchors(false), - sha1_local_anchors_enabled(false), - symantec_enforcement_disabled(false), - version_min(kDefaultSSLVersionMin), + : version_min(kDefaultSSLVersionMin), version_max(kDefaultSSLVersionMax), tls13_variant(kDefaultTLS13Variant), early_data_enabled(false), @@ -34,6 +30,7 @@ channel_id_enabled(false), false_start_enabled(true), require_ecdhe(false), + disable_cert_verification_network_fetches(false), send_client_cert(false), renego_allowed_default(false) {} @@ -55,14 +52,8 @@ int SSLConfig::GetCertVerifyFlags() const { int flags = 0; - if (rev_checking_enabled) - flags |= CertVerifier::VERIFY_REV_CHECKING_ENABLED; - if (rev_checking_required_local_anchors) - flags |= CertVerifier::VERIFY_REV_CHECKING_REQUIRED_LOCAL_ANCHORS; - if (sha1_local_anchors_enabled) - flags |= CertVerifier::VERIFY_ENABLE_SHA1_LOCAL_ANCHORS; - if (symantec_enforcement_disabled) - flags |= CertVerifier::VERIFY_DISABLE_SYMANTEC_ENFORCEMENT; + if (disable_cert_verification_network_fetches) + flags |= CertVerifier::VERIFY_DISABLE_NETWORK_FETCHES; return flags; }
diff --git a/net/ssl/ssl_config.h b/net/ssl/ssl_config.h index 6604979..2d7782e0 100644 --- a/net/ssl/ssl_config.h +++ b/net/ssl/ssl_config.h
@@ -66,31 +66,6 @@ // configuration. int GetCertVerifyFlags() const; - // rev_checking_enabled is true if online certificate revocation checking is - // enabled (i.e. OCSP and CRL fetching). - // - // Regardless of this flag, CRLSet checking is always enabled and locally - // cached revocation information will be considered. - bool rev_checking_enabled; - - // rev_checking_required_local_anchors is true if revocation checking is - // required to succeed when certificates chain to local trust anchors (that - // is, non-public CAs). If revocation information cannot be obtained, such - // certificates will be treated as revoked ("hard-fail"). - // Note: This is distinct from rev_checking_enabled. If true, it is - // equivalent to also setting rev_checking_enabled, but only when the - // certificate chain chains to a local (non-public) trust anchor. - bool rev_checking_required_local_anchors; - - // sha1_local_anchors_enabled is true if SHA-1 signed certificates issued by a - // local (non-public) trust anchor should be allowed. - bool sha1_local_anchors_enabled; - - // symantec_enforcement_disabled is true if the policies outlined in - // https://security.googleblog.com/2017/09/chromes-plan-to-distrust-symantec.html - // should not be enforced. - bool symantec_enforcement_disabled; - // The minimum and maximum protocol versions that are enabled. // (Use the SSL_PROTOCOL_VERSION_xxx enumerators defined above.) // SSL 2.0 and SSL 3.0 are not supported. If version_max < version_min, it @@ -162,6 +137,14 @@ // response to the user explicitly accepting the bad certificate. std::vector<CertAndStatus> allowed_bad_certs; + // True if, for a single connection, any dependent network fetches should + // be disabled. This can be used to avoid triggering re-entrancy in the + // network layer. For example, fetching a PAC script over HTTPS may cause + // AIA, OCSP, or CRL fetches to block on retrieving the PAC script, while + // the PAC script fetch is waiting for those dependent fetches, creating a + // deadlock. + bool disable_cert_verification_network_fetches; + // True if we should send client_cert to the server. bool send_client_cert;
diff --git a/net/ssl/ssl_config_service.cc b/net/ssl/ssl_config_service.cc index c53a449d..cb6799e 100644 --- a/net/ssl/ssl_config_service.cc +++ b/net/ssl/ssl_config_service.cc
@@ -17,20 +17,14 @@ // Checks if the config-service managed fields in two SSLConfigs are the same. bool SSLConfigsAreEqual(const net::SSLConfig& config1, const net::SSLConfig& config2) { - return std::tie(config1.rev_checking_enabled, - config1.rev_checking_required_local_anchors, - config1.sha1_local_anchors_enabled, - config1.symantec_enforcement_disabled, config1.version_min, - config1.version_max, config1.tls13_variant, - config1.disabled_cipher_suites, config1.channel_id_enabled, - config1.false_start_enabled, config1.require_ecdhe) == - std::tie(config2.rev_checking_enabled, - config2.rev_checking_required_local_anchors, - config2.sha1_local_anchors_enabled, - config2.symantec_enforcement_disabled, config2.version_min, - config2.version_max, config2.tls13_variant, - config2.disabled_cipher_suites, config2.channel_id_enabled, - config2.false_start_enabled, config2.require_ecdhe); + return std::tie(config1.version_min, config1.version_max, + config1.tls13_variant, config1.disabled_cipher_suites, + config1.channel_id_enabled, config1.false_start_enabled, + config1.require_ecdhe) == + std::tie(config2.version_min, config2.version_max, + config2.tls13_variant, config2.disabled_cipher_suites, + config2.channel_id_enabled, config2.false_start_enabled, + config2.require_ecdhe); } } // namespace
diff --git a/net/ssl/ssl_config_service.h b/net/ssl/ssl_config_service.h index 21e686c..b1157bb 100644 --- a/net/ssl/ssl_config_service.h +++ b/net/ssl/ssl_config_service.h
@@ -27,13 +27,13 @@ // Notify observers if SSL settings have changed. We don't check all of the // data in SSLConfig, just those that qualify as a user config change. // The following settings are considered user changes: - // rev_checking_enabled // version_min // version_max + // tls13_variant // disabled_cipher_suites // channel_id_enabled // false_start_enabled - // require_forward_secrecy + // require_ecdhe virtual void OnSSLConfigChanged() = 0; protected:
diff --git a/net/ssl/ssl_config_service_unittest.cc b/net/ssl/ssl_config_service_unittest.cc index 391d663..4763a7b6 100644 --- a/net/ssl/ssl_config_service_unittest.cc +++ b/net/ssl/ssl_config_service_unittest.cc
@@ -52,7 +52,6 @@ TEST(SSLConfigServiceTest, NoChangesWontNotifyObservers) { SSLConfig initial_config; - initial_config.rev_checking_enabled = true; initial_config.false_start_enabled = false; initial_config.version_min = SSL_PROTOCOL_VERSION_TLS1; initial_config.version_max = SSL_PROTOCOL_VERSION_TLS1_2; @@ -69,7 +68,6 @@ TEST(SSLConfigServiceTest, ForceNotificationNotifiesObservers) { SSLConfig initial_config; - initial_config.rev_checking_enabled = true; initial_config.false_start_enabled = false; initial_config.version_min = SSL_PROTOCOL_VERSION_TLS1; initial_config.version_max = SSL_PROTOCOL_VERSION_TLS1_2; @@ -86,9 +84,6 @@ TEST(SSLConfigServiceTest, ConfigUpdatesNotifyObservers) { SSLConfig initial_config; - initial_config.rev_checking_enabled = true; - initial_config.rev_checking_required_local_anchors = false; - initial_config.sha1_local_anchors_enabled = true; initial_config.false_start_enabled = false; initial_config.require_ecdhe = false; initial_config.version_min = SSL_PROTOCOL_VERSION_TLS1; @@ -99,18 +94,6 @@ mock_service.AddObserver(&observer); // Test that the basic boolean preferences trigger updates. - initial_config.rev_checking_enabled = false; - EXPECT_CALL(observer, OnSSLConfigChanged()).Times(1); - mock_service.SetSSLConfig(initial_config); - - initial_config.rev_checking_required_local_anchors = true; - EXPECT_CALL(observer, OnSSLConfigChanged()).Times(1); - mock_service.SetSSLConfig(initial_config); - - initial_config.sha1_local_anchors_enabled = false; - EXPECT_CALL(observer, OnSSLConfigChanged()).Times(1); - mock_service.SetSSLConfig(initial_config); - initial_config.false_start_enabled = true; EXPECT_CALL(observer, OnSSLConfigChanged()).Times(1); mock_service.SetSSLConfig(initial_config);
diff --git a/net/ssl/ssl_config_unittest.cc b/net/ssl/ssl_config_unittest.cc index 11001b4..9dde2242 100644 --- a/net/ssl/ssl_config_unittest.cc +++ b/net/ssl/ssl_config_unittest.cc
@@ -12,22 +12,13 @@ namespace { void CheckCertVerifyFlags(SSLConfig* ssl_config, - bool rev_checking_enabled, - bool rev_checking_required_local_anchors, - bool symantec_enforcement_disabled) { - ssl_config->rev_checking_enabled = rev_checking_enabled; - ssl_config->rev_checking_required_local_anchors = - rev_checking_required_local_anchors; - ssl_config->symantec_enforcement_disabled = symantec_enforcement_disabled; + bool disable_cert_verification_network_fetches) { + ssl_config->disable_cert_verification_network_fetches = + disable_cert_verification_network_fetches; int flags = ssl_config->GetCertVerifyFlags(); - EXPECT_EQ(rev_checking_enabled, - !!(flags & CertVerifier::VERIFY_REV_CHECKING_ENABLED)); - EXPECT_EQ( - rev_checking_required_local_anchors, - !!(flags & CertVerifier::VERIFY_REV_CHECKING_REQUIRED_LOCAL_ANCHORS)); - EXPECT_EQ(symantec_enforcement_disabled, - !!(flags & CertVerifier::VERIFY_DISABLE_SYMANTEC_ENFORCEMENT)); + EXPECT_EQ(disable_cert_verification_network_fetches, + !!(flags & CertVerifier::VERIFY_DISABLE_NETWORK_FETCHES)); } } // namespace @@ -35,29 +26,9 @@ TEST(SSLConfigTest, GetCertVerifyFlags) { SSLConfig ssl_config; CheckCertVerifyFlags(&ssl_config, - /*rev_checking_enabled=*/true, - /*rev_checking_required_local_anchors=*/true, - /*symantec_enforcement_disabled=*/true); - + /*disable_cert_verification_network_fetches*/ false); CheckCertVerifyFlags(&ssl_config, - /*rev_checking_enabled=*/true, - /*rev_checking_required_local_anchors=*/false, - /*symantec_enforcement_disabled=*/false); - - CheckCertVerifyFlags(&ssl_config, - /*rev_checking_enabled=*/false, - /*rev_checking_required_local_anchors=*/true, - /*symantec_enforcement_disabled=*/false); - - CheckCertVerifyFlags(&ssl_config, - /*rev_checking_enabled=*/false, - /*rev_checking_required_local_anchors=*/false, - /*symantec_enforcement_disabled=*/true); - - CheckCertVerifyFlags(&ssl_config, - /*rev_checking_enabled=*/false, - /*rev_checking_required_local_anchors=*/false, - /*symantec_enforcement_disabled=*/false); + /*disable_cert_verification_network_fetches*/ true); } } // namespace net
diff --git a/net/url_request/url_request_unittest.cc b/net/url_request/url_request_unittest.cc index 4a58166e..278b254 100644 --- a/net/url_request/url_request_unittest.cc +++ b/net/url_request/url_request_unittest.cc
@@ -4128,13 +4128,8 @@ class TestSSLConfigService : public SSLConfigService { public: - TestSSLConfigService(bool online_rev_checking, - bool rev_checking_required_local_anchors, - bool token_binding_enabled) - : online_rev_checking_(online_rev_checking), - rev_checking_required_local_anchors_( - rev_checking_required_local_anchors), - token_binding_enabled_(token_binding_enabled), + explicit TestSSLConfigService(bool token_binding_enabled) + : token_binding_enabled_(token_binding_enabled), min_version_(kDefaultSSLVersionMin), max_version_(kDefaultSSLVersionMax) {} ~TestSSLConfigService() override = default; @@ -4145,9 +4140,6 @@ // SSLConfigService: void GetSSLConfig(SSLConfig* config) override { *config = SSLConfig(); - config->rev_checking_enabled = online_rev_checking_; - config->rev_checking_required_local_anchors = - rev_checking_required_local_anchors_; config->version_min = min_version_; config->version_max = max_version_; if (token_binding_enabled_) { @@ -4161,8 +4153,6 @@ } private: - const bool online_rev_checking_; - const bool rev_checking_required_local_anchors_; const bool token_binding_enabled_; uint16_t min_version_; uint16_t max_version_; @@ -4177,8 +4167,8 @@ TokenBindingURLRequestTest() = default; void SetUp() override { - ssl_config_service_ = - std::make_unique<TestSSLConfigService>(false, false, true); + ssl_config_service_ = std::make_unique<TestSSLConfigService>( + true /* token_binding_enabled */); default_context().set_ssl_config_service(ssl_config_service_.get()); channel_id_service_ = std::make_unique<ChannelIDService>(new DefaultChannelIDStore(NULL)); @@ -10816,8 +10806,6 @@ public: HTTPSFallbackTest() : context_(true) { ssl_config_service_ = std::make_unique<TestSSLConfigService>( - false /* online revocation checking */, - false /* require rev. checking for local anchors */, false /* token binding enabled */); context_.set_ssl_config_service(ssl_config_service_.get()); } @@ -11024,9 +11012,10 @@ void SetUp() override { context_.SetCTPolicyEnforcer(std::make_unique<DefaultCTPolicyEnforcer>()); - SetupContext(); context_.Init(); + context_.cert_verifier()->SetConfig(GetCertVerifierConfig()); + scoped_refptr<X509Certificate> root_cert = ImportCertFromFile(GetTestCertsDirectory(), "ocsp-test-root.pem"); CHECK_NE(static_cast<X509Certificate*>(NULL), root_cert.get()); @@ -11090,15 +11079,13 @@ } protected: - // SetupContext configures the URLRequestContext that will be used for making - // connetions to testserver. This can be overridden in test subclasses for - // different behaviour. - virtual void SetupContext() { - ssl_config_service_ = std::make_unique<TestSSLConfigService>( - true /* online revocation checking */, - false /* require rev. checking for local anchors */, - false /* token binding enabled */); - context_.set_ssl_config_service(ssl_config_service_.get()); + // GetCertVerifierConfig() configures the URLRequestContext that will be used + // for making connections to the testserver. This can be overridden in test + // subclasses for different behaviour. + virtual CertVerifier::Config GetCertVerifierConfig() { + CertVerifier::Config config; + config.enable_rev_checking = true; + return config; } std::unique_ptr<ScopedTestRoot> test_root_; @@ -11697,12 +11684,9 @@ class HTTPSAIATest : public HTTPSOCSPTest { public: - void SetupContext() override { - ssl_config_service_ = std::make_unique<TestSSLConfigService>( - false /* online revocation checking */, - false /* require rev. checking for local anchors */, - false /* token binding enabled */); - context_.set_ssl_config_service(ssl_config_service_.get()); + CertVerifier::Config GetCertVerifierConfig() override { + CertVerifier::Config config; + return config; } }; @@ -11742,12 +11726,10 @@ class HTTPSHardFailTest : public HTTPSOCSPTest { protected: - void SetupContext() override { - ssl_config_service_ = std::make_unique<TestSSLConfigService>( - false /* online revocation checking */, - true /* require rev. checking for local anchors */, - false /* token binding enabled */); - context_.set_ssl_config_service(ssl_config_service_.get()); + CertVerifier::Config GetCertVerifierConfig() override { + CertVerifier::Config config; + config.require_rev_checking_local_anchors = true; + return config; } }; @@ -11787,12 +11769,9 @@ class HTTPSEVCRLSetTest : public HTTPSOCSPTest { protected: - void SetupContext() override { - ssl_config_service_ = std::make_unique<TestSSLConfigService>( - false /* online revocation checking */, - false /* require rev. checking for local anchors */, - false /* token binding enabled */); - context_.set_ssl_config_service(ssl_config_service_.get()); + CertVerifier::Config GetCertVerifierConfig() override { + CertVerifier::Config config; + return config; } }; @@ -11962,12 +11941,9 @@ class HTTPSCRLSetTest : public HTTPSOCSPTest { protected: - void SetupContext() override { - ssl_config_service_ = std::make_unique<TestSSLConfigService>( - false /* online revocation checking */, - false /* require rev. checking for local anchors */, - false /* token binding enabled */); - context_.set_ssl_config_service(ssl_config_service_.get()); + CertVerifier::Config GetCertVerifierConfig() override { + CertVerifier::Config config; + return config; } void SetUp() override {
diff --git a/remoting/android/javatests/AndroidManifest.xml.jinja2 b/remoting/android/javatests/AndroidManifest.xml.jinja2 index 4163919..e1d14ff 100644 --- a/remoting/android/javatests/AndroidManifest.xml.jinja2 +++ b/remoting/android/javatests/AndroidManifest.xml.jinja2
@@ -18,6 +18,5 @@ </application> <instrumentation android:name="org.chromium.base.test.BaseChromiumAndroidJUnitRunner" android:targetPackage="{{ APK_PACKAGE_NAME }}" - android:label="Tests for {{ APK_PACKAGE_NAME }}" - chromium-junit4="true"/> + android:label="Tests for {{ APK_PACKAGE_NAME }}"/> </manifest>
diff --git a/remoting/protocol/ssl_hmac_channel_authenticator.cc b/remoting/protocol/ssl_hmac_channel_authenticator.cc index e78926e5..bf905eb8 100644 --- a/remoting/protocol/ssl_hmac_channel_authenticator.cc +++ b/remoting/protocol/ssl_hmac_channel_authenticator.cc
@@ -93,6 +93,7 @@ verify_result->cert_status = net::CERT_STATUS_INVALID; return net::ERR_CERT_INVALID; } + void SetConfig(const Config& config) override {} }; // Implements net::StreamSocket interface on top of P2PStreamSocket to be passed @@ -287,11 +288,6 @@ ct_policy_enforcer_.reset(new net::DefaultCTPolicyEnforcer); net::SSLConfig ssl_config; - // Certificate verification and revocation checking are not needed - // because we use self-signed certs. Disable it so that the SSL - // layer doesn't try to initialize OCSP (OCSP works only on the IO - // thread). - ssl_config.rev_checking_enabled = false; ssl_config.require_ecdhe = true; scoped_refptr<net::X509Certificate> cert =
diff --git a/services/network/BUILD.gn b/services/network/BUILD.gn index bbf55585..bc00fb74 100644 --- a/services/network/BUILD.gn +++ b/services/network/BUILD.gn
@@ -10,6 +10,8 @@ component("network_service") { sources = [ + "cert_verifier_config_type_converter.cc", + "cert_verifier_config_type_converter.h", "chunked_data_pipe_upload_data_stream.cc", "chunked_data_pipe_upload_data_stream.h", "conditional_cache_deletion_helper.cc",
diff --git a/services/network/cert_verifier_config_type_converter.cc b/services/network/cert_verifier_config_type_converter.cc new file mode 100644 index 0000000..bcbb045 --- /dev/null +++ b/services/network/cert_verifier_config_type_converter.cc
@@ -0,0 +1,26 @@ +// 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 "services/network/cert_verifier_config_type_converter.h" + +namespace mojo { + +net::CertVerifier::Config +TypeConverter<net::CertVerifier::Config, network::mojom::SSLConfigPtr>::Convert( + const network::mojom::SSLConfigPtr& mojo_config) { + DCHECK(mojo_config); + + net::CertVerifier::Config net_config; + net_config.enable_rev_checking = mojo_config->rev_checking_enabled; + net_config.require_rev_checking_local_anchors = + mojo_config->rev_checking_required_local_anchors; + net_config.enable_sha1_local_anchors = + mojo_config->sha1_local_anchors_enabled; + net_config.disable_symantec_enforcement = + mojo_config->symantec_enforcement_disabled; + + return net_config; +} + +} // namespace mojo
diff --git a/services/network/cert_verifier_config_type_converter.h b/services/network/cert_verifier_config_type_converter.h new file mode 100644 index 0000000..5a05579 --- /dev/null +++ b/services/network/cert_verifier_config_type_converter.h
@@ -0,0 +1,24 @@ +// 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 SERVICES_NETWORK_CERT_VERIFIER_CONFIG_TYPE_CONVERTER_H_ +#define SERVICES_NETWORK_CERT_VERIFIER_CONFIG_TYPE_CONVERTER_H_ + +#include "mojo/public/cpp/bindings/type_converter.h" +#include "net/cert/cert_verifier.h" +#include "services/network/public/mojom/ssl_config.mojom.h" + +namespace mojo { + +// Converts a network::mojom::SSLConfigPtr to a net::CertVerifier::Config. +// Tested in SSLConfigServiceMojo's unittests. +template <> +struct TypeConverter<net::CertVerifier::Config, network::mojom::SSLConfigPtr> { + static net::CertVerifier::Config Convert( + const network::mojom::SSLConfigPtr& mojo_config); +}; + +} // namespace mojo + +#endif // SERVICES_NETWORK_CERT_VERIFIER_CONFIG_TYPE_CONVERTER_H_
diff --git a/services/network/ignore_errors_cert_verifier.cc b/services/network/ignore_errors_cert_verifier.cc index b6a67488..0df80e72 100644 --- a/services/network/ignore_errors_cert_verifier.cc +++ b/services/network/ignore_errors_cert_verifier.cc
@@ -133,6 +133,10 @@ out_req, net_log); } +void IgnoreErrorsCertVerifier::SetConfig(const Config& config) { + verifier_->SetConfig(config); +} + void IgnoreErrorsCertVerifier::set_whitelist(const SPKIHashSet& whitelist) { whitelist_ = whitelist; }
diff --git a/services/network/ignore_errors_cert_verifier.h b/services/network/ignore_errors_cert_verifier.h index ce0984c..ad895ec 100644 --- a/services/network/ignore_errors_cert_verifier.h +++ b/services/network/ignore_errors_cert_verifier.h
@@ -64,6 +64,7 @@ net::CompletionOnceCallback callback, std::unique_ptr<Request>* out_req, const net::NetLogWithSource& net_log) override; + void SetConfig(const Config& config) override; private: friend class IgnoreErrorsCertVerifierTest;
diff --git a/services/network/network_context.cc b/services/network/network_context.cc index 9350af9f..6fc736e 100644 --- a/services/network/network_context.cc +++ b/services/network/network_context.cc
@@ -139,6 +139,11 @@ return g_cert_verifier_for_testing->Verify( params, crl_set, verify_result, std::move(callback), out_req, net_log); } + void SetConfig(const Config& config) override { + if (!g_cert_verifier_for_testing) + return; + g_cert_verifier_for_testing->SetConfig(config); + } }; // Predicate function to determine if the given |domain| matches the @@ -1017,9 +1022,12 @@ builder->EnableHttpCache(cache_params); } - builder->set_ssl_config_service(std::make_unique<SSLConfigServiceMojo>( - std::move(params_->initial_ssl_config), - std::move(params_->ssl_config_client_request))); + std::unique_ptr<SSLConfigServiceMojo> ssl_config_service = + std::make_unique<SSLConfigServiceMojo>( + std::move(params_->initial_ssl_config), + std::move(params_->ssl_config_client_request)); + SSLConfigServiceMojo* ssl_config_service_raw = ssl_config_service.get(); + builder->set_ssl_config_service(std::move(ssl_config_service)); if (!params_->initial_proxy_config && !params_->proxy_config_client_request.is_pending()) { @@ -1153,6 +1161,12 @@ auto result = URLRequestContextOwner(std::move(pref_service), builder->Build()); + // Subscribe the CertVerifier to configuration changes that are exposed via + // the mojom::SSLConfig, but which are not part of the + // net::SSLConfig[Service] interfaces. + ssl_config_service_raw->SetCertVerifierForConfiguring( + result.url_request_context->cert_verifier()); + // Attach some things to the URLRequestContextBuilder's // TransportSecurityState. Since no requests have been made yet, safe to do // this even after the call to Build().
diff --git a/services/network/public/cpp/network_quality_tracker.h b/services/network/public/cpp/network_quality_tracker.h index 2ffedae..217f7ec 100644 --- a/services/network/public/cpp/network_quality_tracker.h +++ b/services/network/public/cpp/network_quality_tracker.h
@@ -76,21 +76,21 @@ ~NetworkQualityTracker() override; // Returns the current estimate of the effective connection type. - net::EffectiveConnectionType GetEffectiveConnectionType() const; + virtual net::EffectiveConnectionType GetEffectiveConnectionType() const; // Returns the current HTTP RTT estimate. The RTT at the HTTP layer measures // the time from when the request was sent (this happens after the connection // is established) to the time when the response headers were received. - base::TimeDelta GetHttpRTT() const; + virtual base::TimeDelta GetHttpRTT() const; // Returns the current transport-layer RTT estimate. The RTT at the transport // layer provides an aggregate estimate of the transport RTT as computed by // various underlying TCP and QUIC connections. - base::TimeDelta GetTransportRTT() const; + virtual base::TimeDelta GetTransportRTT() const; // Returns the current downstream throughput estimate (in kilobits per // second). - int32_t GetDownstreamThroughputKbps() const; + virtual int32_t GetDownstreamThroughputKbps() const; // Registers |observer| to receive notifications of network changes. The // thread on which this is called is the thread on which |observer| will be
diff --git a/services/network/public/mojom/network_service_test.mojom b/services/network/public/mojom/network_service_test.mojom index 000451ba..9014971 100644 --- a/services/network/public/mojom/network_service_test.mojom +++ b/services/network/public/mojom/network_service_test.mojom
@@ -8,7 +8,15 @@ import "services/network/public/mojom/network_param.mojom"; import "services/network/public/mojom/network_types.mojom"; +// Maps to net::RuleBasedHostResolverProc::Rule::ResolverType. +enum ResolverType { + kResolverTypeFail, + kResolverTypeSystem, + kResolverTypeIPLiteral, +}; + struct Rule { + ResolverType resolver_type; string host_pattern; string replacement; };
diff --git a/services/network/ssl_config_service_mojo.cc b/services/network/ssl_config_service_mojo.cc index 36c6512..4fa16e5 100644 --- a/services/network/ssl_config_service_mojo.cc +++ b/services/network/ssl_config_service_mojo.cc
@@ -6,6 +6,7 @@ #include "base/strings/string_piece.h" #include "mojo/public/cpp/bindings/type_converter.h" +#include "services/network/cert_verifier_config_type_converter.h" #include "services/network/ssl_config_type_converter.h" namespace network { @@ -34,25 +35,44 @@ mojom::SSLConfigPtr initial_config, mojom::SSLConfigClientRequest ssl_config_client_request) : binding_(this), + client_cert_pooling_policy_( initial_config ? initial_config->client_cert_pooling_policy : std::vector<std::string>()) { - if (initial_config) + if (initial_config) { + cert_verifier_config_ = + mojo::ConvertTo<net::CertVerifier::Config>(initial_config->Clone()); ssl_config_ = mojo::ConvertTo<net::SSLConfig>(std::move(initial_config)); + } if (ssl_config_client_request) binding_.Bind(std::move(ssl_config_client_request)); } SSLConfigServiceMojo::~SSLConfigServiceMojo() = default; +void SSLConfigServiceMojo::SetCertVerifierForConfiguring( + net::CertVerifier* cert_verifier) { + cert_verifier_ = cert_verifier; + if (cert_verifier_) { + cert_verifier_->SetConfig(cert_verifier_config_); + } +} + void SSLConfigServiceMojo::OnSSLConfigUpdated(mojom::SSLConfigPtr ssl_config) { bool force_notification = client_cert_pooling_policy_ != ssl_config->client_cert_pooling_policy; client_cert_pooling_policy_ = ssl_config->client_cert_pooling_policy; net::SSLConfig old_config = ssl_config_; - ssl_config_ = mojo::ConvertTo<net::SSLConfig>(std::move(ssl_config)); + ssl_config_ = mojo::ConvertTo<net::SSLConfig>(ssl_config->Clone()); ProcessConfigUpdate(old_config, ssl_config_, force_notification); + + net::CertVerifier::Config old_cert_verifier_config = cert_verifier_config_; + cert_verifier_config_ = + mojo::ConvertTo<net::CertVerifier::Config>(std::move(ssl_config)); + if (cert_verifier_ && (old_cert_verifier_config != cert_verifier_config_)) { + cert_verifier_->SetConfig(cert_verifier_config_); + } } void SSLConfigServiceMojo::GetSSLConfig(net::SSLConfig* ssl_config) {
diff --git a/services/network/ssl_config_service_mojo.h b/services/network/ssl_config_service_mojo.h index 28bd7dc..8fee4bd 100644 --- a/services/network/ssl_config_service_mojo.h +++ b/services/network/ssl_config_service_mojo.h
@@ -7,6 +7,7 @@ #include "base/component_export.h" #include "mojo/public/cpp/bindings/binding.h" +#include "net/cert/cert_verifier.h" #include "net/ssl/ssl_config.h" #include "net/ssl/ssl_config_service.h" #include "services/network/public/mojom/ssl_config.mojom.h" @@ -25,6 +26,12 @@ mojom::SSLConfigClientRequest ssl_config_client_request); ~SSLConfigServiceMojo() override; + // Sets |cert_verifier| to be configured by certificate-related settings + // provided by the mojom::SSLConfigClient via OnSSLConfigUpdated. Once set, + // |cert_verifier| must outlive the SSLConfigServiceMojo or be cleared by + // passing nullptr as |cert_verifier| prior to destruction. + void SetCertVerifierForConfiguring(net::CertVerifier* cert_verifier); + // mojom::SSLConfigClient implementation: void OnSSLConfigUpdated(const mojom::SSLConfigPtr ssl_config) override; @@ -37,6 +44,9 @@ mojo::Binding<mojom::SSLConfigClient> binding_; net::SSLConfig ssl_config_; + net::CertVerifier::Config cert_verifier_config_; + + net::CertVerifier* cert_verifier_; // The list of domains and subdomains from enterprise policy where connection // coalescing is allowed when client certs are in use if the hosts being
diff --git a/services/network/ssl_config_service_mojo_unittest.cc b/services/network/ssl_config_service_mojo_unittest.cc index 1bd8f08..5e8a2e8 100644 --- a/services/network/ssl_config_service_mojo_unittest.cc +++ b/services/network/ssl_config_service_mojo_unittest.cc
@@ -8,6 +8,7 @@ #include "base/stl_util.h" #include "base/test/scoped_task_environment.h" #include "mojo/public/cpp/bindings/interface_request.h" +#include "net/cert/cert_verifier.h" #include "net/ssl/ssl_config.h" #include "net/ssl/ssl_config_service.h" #include "net/url_request/url_request_context.h" @@ -15,6 +16,7 @@ #include "services/network/network_service.h" #include "services/network/public/mojom/network_service.mojom.h" #include "services/network/public/mojom/ssl_config.mojom.h" +#include "testing/gmock/include/gmock/gmock.h" #include "testing/gtest/include/gtest/gtest.h" namespace network { @@ -72,12 +74,69 @@ std::unique_ptr<base::RunLoop> run_loop_; }; +class TestCertVerifierConfigObserver : public net::CertVerifier { + public: + TestCertVerifierConfigObserver() = default; + ~TestCertVerifierConfigObserver() override { + EXPECT_EQ(observed_changes_, changes_to_wait_for_); + } + + // CertVerifier implementation: + int Verify(const net::CertVerifier::RequestParams& params, + net::CRLSet* crl_set, + net::CertVerifyResult* verify_result, + net::CompletionOnceCallback callback, + std::unique_ptr<net::CertVerifier::Request>* out_req, + const net::NetLogWithSource& net_log) override { + ADD_FAILURE() << "Verify should not be called by tests"; + return net::ERR_FAILED; + } + void SetConfig(const Config& config) override { + ++observed_changes_; + verifier_config_during_change_ = config; + if (run_loop_) + run_loop_->Quit(); + } + + // Waits for a SSLConfig change. The first time it's called, waits for the + // first change, if one hasn't been observed already, the second time, waits + // for the second, etc. Must be called once for each change that happens, and + // fails it more than once change happens between calls, or during a call. + void WaitForChange() { + EXPECT_FALSE(run_loop_); + ++changes_to_wait_for_; + if (changes_to_wait_for_ == observed_changes_) + return; + EXPECT_LT(observed_changes_, changes_to_wait_for_); + + run_loop_ = std::make_unique<base::RunLoop>(); + run_loop_->Run(); + run_loop_.reset(); + EXPECT_EQ(observed_changes_, changes_to_wait_for_); + } + + const net::CertVerifier::Config& verifier_config_during_change() const { + return verifier_config_during_change_; + } + + int observed_changes() const { return observed_changes_; } + + private: + int observed_changes_ = 0; + int changes_to_wait_for_ = 0; + net::CertVerifier::Config verifier_config_during_change_; + std::unique_ptr<base::RunLoop> run_loop_; +}; + class NetworkServiceSSLConfigServiceTest : public testing::Test { public: NetworkServiceSSLConfigServiceTest() : scoped_task_environment_( base::test::ScopedTaskEnvironment::MainThreadType::IO), network_service_(NetworkService::CreateForTesting()) {} + ~NetworkServiceSSLConfigServiceTest() override { + NetworkContext::SetCertVerifierForTesting(nullptr); + } // Creates a NetworkContext using the specified NetworkContextParams, and // stores it in |network_context_|. @@ -143,6 +202,49 @@ observer.ssl_config_during_change(), expected_net_config)); } + // Runs two conversion tests for |mojo_config|. Uses it as an initial + // net::CertVerifier::Config for a NetworkContext, making sure it matches + // |expected_net_config|. Then switches to the default configuration and then + // back to |mojo_config|, to make sure it works as a new configuration. The + // expected configuration must not be the default configuration. + void RunCertConversionTests( + const mojom::SSLConfig& mojo_config, + const net::CertVerifier::Config& expected_net_config) { + TestCertVerifierConfigObserver observer; + NetworkContext::SetCertVerifierForTesting(&observer); + + EXPECT_NE(net::CertVerifier::Config(), expected_net_config); + + // Set up |mojo_config| as the initial configuration of a NetworkContext. + mojom::NetworkContextParamsPtr network_context_params = + mojom::NetworkContextParams::New(); + network_context_params->initial_ssl_config = mojo_config.Clone(); + SetUpNetworkContext(std::move(network_context_params)); + + // Make sure the initial configuration is set. + observer.WaitForChange(); + EXPECT_EQ(observer.verifier_config_during_change(), expected_net_config); + // Sanity check. + EXPECT_NE(observer.verifier_config_during_change(), + net::CertVerifier::Config()); + + // Reset the configuration to the default ones, and check the results. + ssl_config_client_->OnSSLConfigUpdated(mojom::SSLConfig::New()); + observer.WaitForChange(); + EXPECT_EQ(observer.verifier_config_during_change(), + net::CertVerifier::Config()); + // Sanity check. + EXPECT_NE(observer.verifier_config_during_change(), expected_net_config); + + // Set the configuration to |mojo_config| again, and check the results. + ssl_config_client_->OnSSLConfigUpdated(mojo_config.Clone()); + observer.WaitForChange(); + EXPECT_EQ(observer.verifier_config_during_change(), expected_net_config); + + // Reset the CertVerifier for subsequent invocations. + NetworkContext::SetCertVerifierForTesting(nullptr); + } + protected: base::test::ScopedTaskEnvironment scoped_task_environment_; std::unique_ptr<NetworkService> network_service_; @@ -180,56 +282,75 @@ EXPECT_EQ(net::kDefaultTLS13Variant, GetSSLConfig().tls13_variant); } +// Check that passing in the default mojom::SSLConfig matches the default +// net::CertVerifier::Config. +TEST_F(NetworkServiceSSLConfigServiceTest, DefaultCertConfig) { + TestCertVerifierConfigObserver observer; + NetworkContext::SetCertVerifierForTesting(&observer); + + mojom::NetworkContextParamsPtr network_context_params = + mojom::NetworkContextParams::New(); + network_context_params->initial_ssl_config = mojom::SSLConfig::New(); + SetUpNetworkContext(std::move(network_context_params)); + + observer.WaitForChange(); + + net::CertVerifier::Config default_config; + EXPECT_EQ(observer.verifier_config_during_change(), default_config); + + NetworkContext::SetCertVerifierForTesting(nullptr); +} + TEST_F(NetworkServiceSSLConfigServiceTest, RevCheckingEnabled) { - net::SSLConfig expected_net_config; + net::CertVerifier::Config expected_net_config; // Use the opposite of the default value. - expected_net_config.rev_checking_enabled = - !expected_net_config.rev_checking_enabled; + expected_net_config.enable_rev_checking = + !expected_net_config.enable_rev_checking; mojom::SSLConfigPtr mojo_config = mojom::SSLConfig::New(); - mojo_config->rev_checking_enabled = expected_net_config.rev_checking_enabled; + mojo_config->rev_checking_enabled = expected_net_config.enable_rev_checking; - RunConversionTests(*mojo_config, expected_net_config); + RunCertConversionTests(*mojo_config, expected_net_config); } TEST_F(NetworkServiceSSLConfigServiceTest, RevCheckingRequiredLocalTrustAnchors) { - net::SSLConfig expected_net_config; + net::CertVerifier::Config expected_net_config; // Use the opposite of the default value. - expected_net_config.rev_checking_required_local_anchors = - !expected_net_config.rev_checking_required_local_anchors; + expected_net_config.require_rev_checking_local_anchors = + !expected_net_config.require_rev_checking_local_anchors; mojom::SSLConfigPtr mojo_config = mojom::SSLConfig::New(); mojo_config->rev_checking_required_local_anchors = - expected_net_config.rev_checking_required_local_anchors; + expected_net_config.require_rev_checking_local_anchors; - RunConversionTests(*mojo_config, expected_net_config); + RunCertConversionTests(*mojo_config, expected_net_config); } TEST_F(NetworkServiceSSLConfigServiceTest, Sha1LocalAnchorsEnabled) { - net::SSLConfig expected_net_config; + net::CertVerifier::Config expected_net_config; // Use the opposite of the default value. - expected_net_config.sha1_local_anchors_enabled = - !expected_net_config.sha1_local_anchors_enabled; + expected_net_config.enable_sha1_local_anchors = + !expected_net_config.enable_sha1_local_anchors; mojom::SSLConfigPtr mojo_config = mojom::SSLConfig::New(); mojo_config->sha1_local_anchors_enabled = - expected_net_config.sha1_local_anchors_enabled; + expected_net_config.enable_sha1_local_anchors; - RunConversionTests(*mojo_config, expected_net_config); + RunCertConversionTests(*mojo_config, expected_net_config); } TEST_F(NetworkServiceSSLConfigServiceTest, SymantecEnforcementDisabled) { - net::SSLConfig expected_net_config; + net::CertVerifier::Config expected_net_config; // Use the opposite of the default value. - expected_net_config.symantec_enforcement_disabled = - !expected_net_config.symantec_enforcement_disabled; + expected_net_config.disable_symantec_enforcement = + !expected_net_config.disable_symantec_enforcement; mojom::SSLConfigPtr mojo_config = mojom::SSLConfig::New(); mojo_config->symantec_enforcement_disabled = - expected_net_config.symantec_enforcement_disabled; + expected_net_config.disable_symantec_enforcement; - RunConversionTests(*mojo_config, expected_net_config); + RunCertConversionTests(*mojo_config, expected_net_config); } TEST_F(NetworkServiceSSLConfigServiceTest, SSLVersion) {
diff --git a/services/network/ssl_config_type_converter.cc b/services/network/ssl_config_type_converter.cc index 556f22a..3ef67f43 100644 --- a/services/network/ssl_config_type_converter.cc +++ b/services/network/ssl_config_type_converter.cc
@@ -44,15 +44,6 @@ net::SSLConfig net_config; - net_config.rev_checking_enabled = mojo_config->rev_checking_enabled; - net_config.rev_checking_required_local_anchors = - mojo_config->rev_checking_required_local_anchors; - - net_config.sha1_local_anchors_enabled = - mojo_config->sha1_local_anchors_enabled; - net_config.symantec_enforcement_disabled = - mojo_config->symantec_enforcement_disabled; - net_config.version_min = MojoSSLVersionToNetSSLVersion(mojo_config->version_min); net_config.version_max =
diff --git a/services/resource_coordinator/public/cpp/memory_instrumentation/os_metrics_win.cc b/services/resource_coordinator/public/cpp/memory_instrumentation/os_metrics_win.cc index 56df46d..a936ec3 100644 --- a/services/resource_coordinator/public/cpp/memory_instrumentation/os_metrics_win.cc +++ b/services/resource_coordinator/public/cpp/memory_instrumentation/os_metrics_win.cc
@@ -81,10 +81,12 @@ GUID module_guid; DWORD module_age; - LPCSTR pdb_file; - if (pe_image.GetDebugId(&module_guid, &module_age, &pdb_file)) { + const char* pdb_file = nullptr; + size_t pdb_file_length = 0; + if (pe_image.GetDebugId(&module_guid, &module_age, &pdb_file, + &pdb_file_length)) { region->module_debugid = MakeDebugID(module_guid, module_age); - region->module_debug_path = pdb_file; + region->module_debug_path.assign(pdb_file, pdb_file_length); } maps.push_back(std::move(region));
diff --git a/services/service_manager/public/mojom/connector.mojom b/services/service_manager/public/mojom/connector.mojom index 6acdae586..e0f8b7b 100644 --- a/services/service_manager/public/mojom/connector.mojom +++ b/services/service_manager/public/mojom/connector.mojom
@@ -58,7 +58,7 @@ // Implemented by an object in the service manager associated with a specific // instance. Tells the service manager the PID for a process launched by the -// client. See |ClientProcessConnection|. +// client. interface PIDReceiver { SetPID(uint32 pid); };
diff --git a/services/service_manager/tests/connect/connect_test.mojom b/services/service_manager/tests/connect/connect_test.mojom index f1579a69..24fa8b80 100644 --- a/services/service_manager/tests/connect/connect_test.mojom +++ b/services/service_manager/tests/connect/connect_test.mojom
@@ -40,15 +40,6 @@ (int32 connection_result, service_manager.mojom.Identity target); }; -interface ClientProcessTest { - // Attempts to launch a bare exe and connect to it using the - // ClientProcessConnection param to Connector::Connect(). The callback takes - // the result of the connection, and the identity of the app that the caller - // can use to connect to this app as well. - LaunchAndConnectToProcess() => - (int32 connection_result, service_manager.mojom.Identity target); -}; - struct ConnectionState { string connection_remote_name; string connection_remote_userid;
diff --git a/storage/browser/BUILD.gn b/storage/browser/BUILD.gn index 2205922..4e5f9628 100644 --- a/storage/browser/BUILD.gn +++ b/storage/browser/BUILD.gn
@@ -112,6 +112,8 @@ "fileapi/file_system_usage_cache.h", "fileapi/file_writer_delegate.cc", "fileapi/file_writer_delegate.h", + "fileapi/file_writer_impl.cc", + "fileapi/file_writer_impl.h", "fileapi/isolated_context.cc", "fileapi/isolated_context.h", "fileapi/isolated_file_system_backend.cc", @@ -275,6 +277,7 @@ "fileapi/file_system_url_unittest.cc", "fileapi/file_system_usage_cache_unittest.cc", "fileapi/file_writer_delegate_unittest.cc", + "fileapi/file_writer_impl_unittest.cc", "fileapi/isolated_context_unittest.cc", "fileapi/local_file_stream_reader_unittest.cc", "fileapi/local_file_stream_writer_unittest.cc",
diff --git a/storage/browser/blob/blob_storage_context.cc b/storage/browser/blob/blob_storage_context.cc index 40819ab..0564dcb5 100644 --- a/storage/browser/blob/blob_storage_context.cc +++ b/storage/browser/blob/blob_storage_context.cc
@@ -25,6 +25,7 @@ #include "base/threading/thread_task_runner_handle.h" #include "base/trace_event/memory_dump_manager.h" #include "base/trace_event/trace_event.h" +#include "mojo/public/cpp/bindings/callback_helpers.h" #include "storage/browser/blob/blob_data_builder.h" #include "storage/browser/blob/blob_data_item.h" #include "storage/browser/blob/blob_data_snapshot.h" @@ -75,6 +76,26 @@ return CreateHandle(uuid, entry); } +void BlobStorageContext::GetBlobDataFromBlobPtr( + blink::mojom::BlobPtr blob, + base::OnceCallback<void(std::unique_ptr<BlobDataHandle>)> callback) { + DCHECK(blob); + blink::mojom::Blob* raw_blob = blob.get(); + raw_blob->GetInternalUUID(mojo::WrapCallbackWithDefaultInvokeIfNotRun( + base::BindOnce( + [](blink::mojom::BlobPtr, base::WeakPtr<BlobStorageContext> context, + base::OnceCallback<void(std::unique_ptr<BlobDataHandle>)> callback, + const std::string& uuid) { + if (!context || uuid.empty()) { + std::move(callback).Run(nullptr); + return; + } + std::move(callback).Run(context->GetBlobDataFromUUID(uuid)); + }, + std::move(blob), AsWeakPtr(), std::move(callback)), + "")); +} + std::unique_ptr<BlobDataHandle> BlobStorageContext::AddFinishedBlob( std::unique_ptr<BlobDataBuilder> external_builder) { TRACE_EVENT0("Blob", "Context::AddFinishedBlob");
diff --git a/storage/browser/blob/blob_storage_context.h b/storage/browser/blob/blob_storage_context.h index 86a4556..e0bb90a 100644 --- a/storage/browser/blob/blob_storage_context.h +++ b/storage/browser/blob/blob_storage_context.h
@@ -25,6 +25,7 @@ #include "storage/browser/blob/blob_storage_registry.h" #include "storage/browser/storage_browser_export.h" #include "storage/common/blob_storage/blob_storage_constants.h" +#include "third_party/blink/public/mojom/blob/blob.mojom.h" class GURL; @@ -57,8 +58,15 @@ scoped_refptr<base::TaskRunner> file_runner); ~BlobStorageContext() override; + // The following three methods all lookup a BlobDataHandle based on some + // input. If no blob matching the input exists these methods return null. std::unique_ptr<BlobDataHandle> GetBlobDataFromUUID(const std::string& uuid); std::unique_ptr<BlobDataHandle> GetBlobDataFromPublicURL(const GURL& url); + // If this BlobStorageContext is deleted before this method finishes, the + // callback will still be called with null. + void GetBlobDataFromBlobPtr( + blink::mojom::BlobPtr blob, + base::OnceCallback<void(std::unique_ptr<BlobDataHandle>)> callback); // Always returns a handle to a blob. Use BlobStatus::GetBlobStatus() and // BlobStatus::RunOnConstructionComplete(callback) to determine construction
diff --git a/storage/browser/blob/mojo_blob_reader.cc b/storage/browser/blob/mojo_blob_reader.cc index 2e0cd6ba..480f1de0 100644 --- a/storage/browser/blob/mojo_blob_reader.cc +++ b/storage/browser/blob/mojo_blob_reader.cc
@@ -39,11 +39,14 @@ } MojoBlobReader::~MojoBlobReader() { + DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_); TRACE_EVENT_ASYNC_END1("Blob", "BlobReader", this, "bytes_written", total_written_bytes_); } void MojoBlobReader::Start() { + DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_); + if (blob_reader_->net_error()) { NotifyCompletedAndDeleteIfNeeded(blob_reader_->net_error()); return; @@ -69,6 +72,8 @@ } void MojoBlobReader::NotifyCompletedAndDeleteIfNeeded(int result) { + DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_); + blob_reader_ = nullptr; if (!notified_completed_) { delegate_->OnComplete(static_cast<net::Error>(result), @@ -82,6 +87,8 @@ } void MojoBlobReader::DidCalculateSize(int result) { + DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_); + if (result != net::OK) { TRACE_EVENT_ASYNC_END1("Blob", "BlobReader::CountSize", this, "result", "error"); @@ -126,6 +133,8 @@ } void MojoBlobReader::DidReadSideData(BlobReader::Status status) { + DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_); + if (status != BlobReader::Status::DONE) { NotifyCompletedAndDeleteIfNeeded(blob_reader_->net_error()); return; @@ -135,6 +144,8 @@ } void MojoBlobReader::StartReading() { + DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_); + response_body_stream_ = delegate_->PassDataPipe(); peer_closed_handle_watcher_.Watch( response_body_stream_.get(), MOJO_HANDLE_SIGNAL_PEER_CLOSED, @@ -152,6 +163,7 @@ } void MojoBlobReader::ReadMore() { + DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_); DCHECK(!pending_write_.get()); uint32_t num_bytes; @@ -192,6 +204,8 @@ } void MojoBlobReader::DidRead(bool completed_synchronously, int num_bytes) { + DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_); + if (num_bytes < 0) { TRACE_EVENT_ASYNC_END2("Blob", "BlobReader::ReadMore", this, "result", "error", "net_error", num_bytes); @@ -223,12 +237,16 @@ } void MojoBlobReader::OnResponseBodyStreamClosed(MojoResult result) { + DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_); + response_body_stream_.reset(); pending_write_ = nullptr; NotifyCompletedAndDeleteIfNeeded(net::ERR_ABORTED); } void MojoBlobReader::OnResponseBodyStreamReady(MojoResult result) { + DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_); + if (result == MOJO_RESULT_FAILED_PRECONDITION) { OnResponseBodyStreamClosed(MOJO_RESULT_OK); return;
diff --git a/storage/browser/blob/mojo_blob_reader.h b/storage/browser/blob/mojo_blob_reader.h index ced13b0..3ac46630 100644 --- a/storage/browser/blob/mojo_blob_reader.h +++ b/storage/browser/blob/mojo_blob_reader.h
@@ -7,6 +7,7 @@ #include <memory> #include "base/memory/ref_counted.h" +#include "base/sequence_checker.h" #include "mojo/public/cpp/system/data_pipe.h" #include "mojo/public/cpp/system/simple_watcher.h" #include "net/base/net_errors.h" @@ -38,7 +39,7 @@ public: enum RequestSideData { REQUEST_SIDE_DATA, DONT_REQUEST_SIDE_DATA }; - virtual ~Delegate() {} + virtual ~Delegate() = default; // Called when the blob being read has been fully constructed and its size // is known. |total_size| is the total size of the blob, while @@ -99,7 +100,7 @@ void OnResponseBodyStreamClosed(MojoResult result); void OnResponseBodyStreamReady(MojoResult result); - std::unique_ptr<Delegate> delegate_; + const std::unique_ptr<Delegate> delegate_; // The range of the blob that should be read. Could be unbounded if the entire // blob is being read. @@ -130,6 +131,8 @@ // sure OnComplete isn't called more than once. bool notified_completed_ = false; + SEQUENCE_CHECKER(sequence_checker_); + base::WeakPtrFactory<MojoBlobReader> weak_factory_; DISALLOW_COPY_AND_ASSIGN(MojoBlobReader);
diff --git a/storage/browser/fileapi/file_writer_impl.cc b/storage/browser/fileapi/file_writer_impl.cc new file mode 100644 index 0000000..4f62f86a --- /dev/null +++ b/storage/browser/fileapi/file_writer_impl.cc
@@ -0,0 +1,98 @@ +// 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 "storage/browser/fileapi/file_writer_impl.h" + +#include "base/callback_helpers.h" +#include "storage/browser/blob/blob_data_handle.h" +#include "storage/browser/blob/blob_storage_context.h" + +namespace storage { + +FileWriterImpl::FileWriterImpl( + FileSystemURL url, + std::unique_ptr<FileSystemOperationRunner> operation_runner, + base::WeakPtr<BlobStorageContext> blob_context) + : operation_runner_(std::move(operation_runner)), + blob_context_(std::move(blob_context)), + url_(std::move(url)) { + DCHECK(url_.is_valid()); +} + +FileWriterImpl::~FileWriterImpl() = default; + +void FileWriterImpl::Write(uint64_t position, + blink::mojom::BlobPtr blob, + WriteCallback callback) { + blob_context_->GetBlobDataFromBlobPtr( + std::move(blob), + base::BindOnce(&FileWriterImpl::DoWrite, base::Unretained(this), + std::move(callback), position)); +} + +void FileWriterImpl::Truncate(uint64_t length, TruncateCallback callback) { + operation_runner_->Truncate( + url_, length, + base::BindRepeating( + &FileWriterImpl::DidTruncate, base::Unretained(this), + base::AdaptCallbackForRepeating(std::move(callback)))); +} + +void FileWriterImpl::DoWrite(WriteCallback callback, + uint64_t position, + std::unique_ptr<BlobDataHandle> blob) { + if (!blob) { + std::move(callback).Run(base::File::FILE_ERROR_FAILED, 0); + return; + } + + // FileSystemOperationRunner assumes that positions passed to Write are always + // valid, and will NOTREACHED() if that is not the case, so first check the + // size of the file to make sure the position passed in from the renderer is + // in fact valid. + // Of course the file could still change between checking its size and the + // write operation being started, but this is at least a lot better than the + // old implementation where the renderer only checks against how big it thinks + // the file currently is. + operation_runner_->GetMetadata( + url_, FileSystemOperation::GET_METADATA_FIELD_SIZE, + base::BindRepeating(&FileWriterImpl::DoWriteWithFileInfo, + base::Unretained(this), + base::AdaptCallbackForRepeating(std::move(callback)), + position, base::Passed(std::move(blob)))); +} + +void FileWriterImpl::DoWriteWithFileInfo(WriteCallback callback, + uint64_t position, + std::unique_ptr<BlobDataHandle> blob, + base::File::Error result, + const base::File::Info& file_info) { + if (file_info.size < 0 || position > static_cast<uint64_t>(file_info.size)) { + std::move(callback).Run(base::File::FILE_ERROR_FAILED, 0); + return; + } + operation_runner_->Write( + url_, std::move(blob), position, + base::BindRepeating(&FileWriterImpl::DidWrite, base::Unretained(this), + base::AdaptCallbackForRepeating(std::move(callback)), + base::Owned(new WriteState()))); +} + +void FileWriterImpl::DidWrite(WriteCallback callback, + WriteState* state, + base::File::Error result, + int64_t bytes, + bool complete) { + DCHECK(state); + state->bytes_written += bytes; + if (complete) + std::move(callback).Run(result, state->bytes_written); +} + +void FileWriterImpl::DidTruncate(TruncateCallback callback, + base::File::Error result) { + std::move(callback).Run(result); +} + +} // namespace storage
diff --git a/storage/browser/fileapi/file_writer_impl.h b/storage/browser/fileapi/file_writer_impl.h new file mode 100644 index 0000000..5198134 --- /dev/null +++ b/storage/browser/fileapi/file_writer_impl.h
@@ -0,0 +1,58 @@ +// 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 STORAGE_BROWSER_FILEAPI_FILE_WRITER_IMPL_H_ +#define STORAGE_BROWSER_FILEAPI_FILE_WRITER_IMPL_H_ + +#include "storage/browser/fileapi/file_system_operation_runner.h" +#include "storage/browser/fileapi/file_system_url.h" +#include "storage/browser/storage_browser_export.h" +#include "third_party/blink/public/mojom/filesystem/file_writer.mojom.h" + +namespace storage { + +// This class itself is stateless, but it uses the passed in +// FileSystemOperationRunner and BlobStorageContext so all methods should be +// called on the sequence those instances live on. In chromium that means all +// usage has to be on the IO thread. +class STORAGE_EXPORT FileWriterImpl : public blink::mojom::FileWriter { + public: + FileWriterImpl(FileSystemURL url, + std::unique_ptr<FileSystemOperationRunner> operation_runner, + base::WeakPtr<BlobStorageContext> blob_context); + ~FileWriterImpl() override; + + void Write(uint64_t position, + blink::mojom::BlobPtr blob, + WriteCallback callback) override; + void Truncate(uint64_t length, TruncateCallback callback) override; + + private: + void DoWrite(WriteCallback callback, + uint64_t position, + std::unique_ptr<BlobDataHandle> blob); + void DoWriteWithFileInfo(WriteCallback callback, + uint64_t position, + std::unique_ptr<BlobDataHandle> blob, + base::File::Error result, + const base::File::Info& file_info); + + struct WriteState { + uint64_t bytes_written = 0; + }; + void DidWrite(WriteCallback callback, + WriteState* state, + base::File::Error result, + int64_t bytes, + bool complete); + void DidTruncate(TruncateCallback callback, base::File::Error result); + + const std::unique_ptr<FileSystemOperationRunner> operation_runner_; + const base::WeakPtr<BlobStorageContext> blob_context_; + const FileSystemURL url_; +}; + +} // namespace storage + +#endif // STORAGE_BROWSER_FILEAPI_FILE_WRITER_IMPL_H_
diff --git a/storage/browser/fileapi/file_writer_impl_unittest.cc b/storage/browser/fileapi/file_writer_impl_unittest.cc new file mode 100644 index 0000000..1593c0b --- /dev/null +++ b/storage/browser/fileapi/file_writer_impl_unittest.cc
@@ -0,0 +1,208 @@ +// 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 "storage/browser/fileapi/file_writer_impl.h" + +#include <limits> +#include "base/files/scoped_temp_dir.h" +#include "base/guid.h" +#include "base/test/bind_test_util.h" +#include "base/test/scoped_task_environment.h" +#include "net/base/io_buffer.h" +#include "net/base/net_errors.h" +#include "net/base/test_completion_callback.h" +#include "storage/browser/blob/blob_data_builder.h" +#include "storage/browser/blob/blob_impl.h" +#include "storage/browser/blob/blob_storage_context.h" +#include "storage/browser/fileapi/file_stream_reader.h" +#include "storage/browser/test/async_file_test_helper.h" +#include "storage/browser/test/test_file_system_context.h" +#include "testing/gtest/include/gtest/gtest.h" + +using content::AsyncFileTestHelper; +using content::CreateFileSystemContextForTesting; + +namespace storage { + +class FileWriterImplTest : public testing::Test { + public: + FileWriterImplTest() + : scoped_task_environment_( + base::test::ScopedTaskEnvironment::MainThreadType::IO) {} + + void SetUp() override { + ASSERT_TRUE(dir_.CreateUniqueTempDir()); + file_system_context_ = CreateFileSystemContextForTesting( + /*quota_manager_proxy=*/nullptr, dir_.GetPath()); + + test_url_ = file_system_context_->CreateCrackedFileSystemURL( + GURL("http://example.com"), kFileSystemTypeTest, + base::FilePath::FromUTF8Unsafe("test")); + + ASSERT_EQ(base::File::FILE_OK, AsyncFileTestHelper::CreateFile( + file_system_context_.get(), test_url_)); + + blob_context_ = std::make_unique<BlobStorageContext>(); + + writer_ = std::make_unique<FileWriterImpl>( + test_url_, file_system_context_->CreateFileSystemOperationRunner(), + blob_context_->AsWeakPtr()); + } + + blink::mojom::BlobPtr CreateBlob(const std::string& contents) { + auto builder = + std::make_unique<storage::BlobDataBuilder>(base::GenerateGUID()); + builder->AppendData(contents); + auto handle = blob_context_->AddFinishedBlob(std::move(builder)); + blink::mojom::BlobPtr result; + BlobImpl::Create(std::move(handle), MakeRequest(&result)); + return result; + } + + std::string ReadFile(const FileSystemURL& url) { + std::unique_ptr<FileStreamReader> reader = + file_system_context_->CreateFileStreamReader( + url, 0, std::numeric_limits<int64_t>::max(), base::Time()); + net::TestCompletionCallback callback; + std::string result; + while (true) { + auto buf = base::MakeRefCounted<net::IOBufferWithSize>(4096); + int rv = reader->Read(buf.get(), buf->size(), callback.callback()); + if (rv == net::ERR_IO_PENDING) + rv = callback.WaitForResult(); + EXPECT_GE(rv, 0); + if (rv < 0) + return "(read failure)"; + if (rv == 0) + return result; + result.append(buf->data(), rv); + } + } + + base::File::Error WriteSync(uint64_t position, + blink::mojom::BlobPtr blob, + uint64_t* bytes_written_out) { + base::RunLoop loop; + base::File::Error result_out; + writer_->Write(position, std::move(blob), + base::BindLambdaForTesting( + [&](base::File::Error result, uint64_t bytes_written) { + result_out = result; + *bytes_written_out = bytes_written; + loop.Quit(); + })); + loop.Run(); + return result_out; + } + + base::File::Error TruncateSync(uint64_t length) { + base::RunLoop loop; + base::File::Error result_out; + writer_->Truncate(length, + base::BindLambdaForTesting([&](base::File::Error result) { + result_out = result; + loop.Quit(); + })); + loop.Run(); + return result_out; + } + + protected: + base::test::ScopedTaskEnvironment scoped_task_environment_; + + base::ScopedTempDir dir_; + scoped_refptr<FileSystemContext> file_system_context_; + std::unique_ptr<BlobStorageContext> blob_context_; + + FileSystemURL test_url_; + + std::unique_ptr<FileWriterImpl> writer_; +}; + +TEST_F(FileWriterImplTest, WriteInvalidBlob) { + blink::mojom::BlobPtr blob; + MakeRequest(&blob); + + uint64_t bytes_written; + base::File::Error result = WriteSync(0, std::move(blob), &bytes_written); + EXPECT_EQ(result, base::File::FILE_ERROR_FAILED); + EXPECT_EQ(bytes_written, 0u); + + EXPECT_EQ("", ReadFile(test_url_)); +} + +TEST_F(FileWriterImplTest, WriteValidEmptyBlob) { + uint64_t bytes_written; + base::File::Error result = WriteSync(0, CreateBlob(""), &bytes_written); + EXPECT_EQ(result, base::File::FILE_OK); + EXPECT_EQ(bytes_written, 0u); + + EXPECT_EQ("", ReadFile(test_url_)); +} + +TEST_F(FileWriterImplTest, WriteValidBlob) { + uint64_t bytes_written; + base::File::Error result = + WriteSync(0, CreateBlob("1234567890"), &bytes_written); + EXPECT_EQ(result, base::File::FILE_OK); + EXPECT_EQ(bytes_written, 10u); + + EXPECT_EQ("1234567890", ReadFile(test_url_)); +} + +TEST_F(FileWriterImplTest, WriteWithOffsetInFile) { + uint64_t bytes_written; + base::File::Error result; + + result = WriteSync(0, CreateBlob("1234567890"), &bytes_written); + EXPECT_EQ(result, base::File::FILE_OK); + EXPECT_EQ(bytes_written, 10u); + + result = WriteSync(4, CreateBlob("abc"), &bytes_written); + EXPECT_EQ(result, base::File::FILE_OK); + EXPECT_EQ(bytes_written, 3u); + + EXPECT_EQ("1234abc890", ReadFile(test_url_)); +} + +TEST_F(FileWriterImplTest, WriteWithOffsetPastFile) { + uint64_t bytes_written; + base::File::Error result = WriteSync(4, CreateBlob("abc"), &bytes_written); + EXPECT_EQ(result, base::File::FILE_ERROR_FAILED); + EXPECT_EQ(bytes_written, 0u); + + EXPECT_EQ("", ReadFile(test_url_)); +} + +TEST_F(FileWriterImplTest, TruncateShrink) { + uint64_t bytes_written; + base::File::Error result; + + result = WriteSync(0, CreateBlob("1234567890"), &bytes_written); + EXPECT_EQ(result, base::File::FILE_OK); + EXPECT_EQ(bytes_written, 10u); + + result = TruncateSync(5); + EXPECT_EQ(result, base::File::FILE_OK); + + EXPECT_EQ("12345", ReadFile(test_url_)); +} + +TEST_F(FileWriterImplTest, TruncateGrow) { + uint64_t bytes_written; + base::File::Error result; + + result = WriteSync(0, CreateBlob("abc"), &bytes_written); + EXPECT_EQ(result, base::File::FILE_OK); + EXPECT_EQ(bytes_written, 3u); + + result = TruncateSync(5); + EXPECT_EQ(result, base::File::FILE_OK); + + EXPECT_EQ(std::string("abc\0\0", 5), ReadFile(test_url_)); +} + +// TODO(mek): More tests, particularly for error conditions. + +} // namespace storage
diff --git a/testing/android/driver/java/AndroidManifest.xml b/testing/android/driver/java/AndroidManifest.xml index 16c70e20..97f2d658 100644 --- a/testing/android/driver/java/AndroidManifest.xml +++ b/testing/android/driver/java/AndroidManifest.xml
@@ -17,6 +17,7 @@ <instrumentation android:name="org.chromium.test.driver.OnDeviceInstrumentationDriver" android:targetPackage="org.chromium.test.driver" - android:label="OnDeviceInstrumentationDriver"/> + android:label="OnDeviceInstrumentationDriver" + chromium-junit3="true"/> </manifest>
diff --git a/testing/android/native_test/java/AndroidManifest.xml.jinja2 b/testing/android/native_test/java/AndroidManifest.xml.jinja2 index dd600400..2895d08a 100644 --- a/testing/android/native_test/java/AndroidManifest.xml.jinja2 +++ b/testing/android/native_test/java/AndroidManifest.xml.jinja2
@@ -65,6 +65,7 @@ <instrumentation android:name="org.chromium.native_test.NativeTestInstrumentationTestRunner" android:targetPackage="org.chromium.native_test" - android:label="Instrumentation entry point for org.chromium.native_test"/> + android:label="Instrumentation entry point for org.chromium.native_test" + chromium-junit3="true"/> </manifest>
diff --git a/testing/buildbot/chromium.mac.json b/testing/buildbot/chromium.mac.json index 1eab7c7..9781dd1 100644 --- a/testing/buildbot/chromium.mac.json +++ b/testing/buildbot/chromium.mac.json
@@ -2995,12 +2995,6 @@ } }, { - "alternate_swarming_dimensions": [ - { - "gpu": "8086:0a2e", - "os": "Mac-10.12.6" - } - ], "isolate_name": "webkit_layout_tests_exparchive", "merge": { "args": [ @@ -3014,12 +3008,12 @@ "can_use_on_swarming_builders": true, "dimension_sets": [ { - "os": "Mac-10.13" + "gpu": "8086:0a2e", + "os": "Mac-10.12.6" } ], "shards": 12 - }, - "use_multi_dimension_trigger_script": true + } }, { "isolate_name": "webkit_python_tests",
diff --git a/testing/buildbot/test_suite_exceptions.pyl b/testing/buildbot/test_suite_exceptions.pyl index 1571c1c..96f78ea 100644 --- a/testing/buildbot/test_suite_exceptions.pyl +++ b/testing/buildbot/test_suite_exceptions.pyl
@@ -1622,18 +1622,13 @@ }, 'Mac10.13 Tests': { # TODO(crbug.com/853356): Switch this to 10.13. - 'use_multi_dimension_trigger_script': True, - 'alternate_swarming_dimensions': [{ - 'gpu': '8086:0a2e', - 'os': 'Mac-10.12.6', - }], - # TODO(kbr): if the Swarming dimensions were explicitly specified for # all jobs then this wouldn't be needed. 'swarming': { 'dimension_sets': [ { - 'os': 'Mac-10.13', + 'gpu': '8086:0a2e', + 'os': 'Mac-10.12.6', }, ], 'shards': 12,
diff --git a/testing/variations/fieldtrial_testing_config.json b/testing/variations/fieldtrial_testing_config.json index 608451f..adadb92 100644 --- a/testing/variations/fieldtrial_testing_config.json +++ b/testing/variations/fieldtrial_testing_config.json
@@ -2026,6 +2026,24 @@ ] } ], + "InfiniteSessionRestore": [ + { + "platforms": [ + "chromeos", + "linux", + "mac", + "windows" + ], + "experiments": [ + { + "name": "Enabled", + "enable_features": [ + "InfiniteSessionRestore" + ] + } + ] + } + ], "InspectDownloadedRarFiles": [ { "platforms": [
diff --git a/third_party/WebKit/LayoutTests/FlagExpectations/enable-blink-gen-property-trees b/third_party/WebKit/LayoutTests/FlagExpectations/enable-blink-gen-property-trees index 1925422..164ad31 100644 --- a/third_party/WebKit/LayoutTests/FlagExpectations/enable-blink-gen-property-trees +++ b/third_party/WebKit/LayoutTests/FlagExpectations/enable-blink-gen-property-trees
@@ -355,12 +355,3 @@ crbug.com/854192 fast/multicol/composited-layer-nested.html [ Failure ] crbug.com/854192 fast/multicol/vertical-rl/composited-relpos-overlapping-will-change.html [ Failure ] crbug.com/854192 paint/pagination/composited-paginated-outlined-box.html [ Failure ] - -# Paint invalidation test failures. Needs investigation. -crbug.com/854196 paint/invalidation/compositing/clipping-should-not-repaint-composited-descendants.html [ Failure ] -crbug.com/854196 paint/invalidation/compositing/overlap-test-with-filter.html [ Failure ] -crbug.com/854196 paint/invalidation/compositing/repaint-overflow-scrolled-squashed-content.html [ Failure ] -crbug.com/854196 paint/invalidation/compositing/should-not-repaint-composited-descendants-on-overflow-change.html [ Failure ] -crbug.com/854196 paint/invalidation/compositing/should-not-repaint-composited-descendants.html [ Failure ] -crbug.com/854196 paint/invalidation/scroll/overflow-scroll-composited-non-stacking-child.html [ Failure ] -crbug.com/854196 paint/invalidation/scroll/repaint-composited-child-in-scrolled-container.html [ Failure ]
diff --git a/third_party/WebKit/LayoutTests/TestExpectations b/third_party/WebKit/LayoutTests/TestExpectations index 315f82a..b05bf42f 100644 --- a/third_party/WebKit/LayoutTests/TestExpectations +++ b/third_party/WebKit/LayoutTests/TestExpectations
@@ -4947,3 +4947,7 @@ crbug.com/874737 [ Android ] animations/stability/empty-keyframes.html [ Crash ] crbug.com/874737 [ Android ] animations/svg-attribute-composition/svg-bias-composition.html [ Crash ] crbug.com/874737 [ Android ] animations/svg-attribute-interpolation/svg-numOctaves-interpolation.html [ Crash ] + +# Test frequently times out on Mac CQ bots. +crbug.com/874703 [ Mac ] http/tests/devtools/extensions/extensions-panel.js [ Timeout Pass ] +
diff --git a/third_party/WebKit/LayoutTests/VirtualTestSuites b/third_party/WebKit/LayoutTests/VirtualTestSuites index 8d8d27d..1cdf40e8 100644 --- a/third_party/WebKit/LayoutTests/VirtualTestSuites +++ b/third_party/WebKit/LayoutTests/VirtualTestSuites
@@ -140,8 +140,7 @@ { "prefix": "feature-policy-permissions", "base": "external/wpt/mediacapture-streams", - "args": ["--enable-features=UseFeaturePolicyForPermissions", - "--use-fake-device-for-media-stream", + "args": ["--use-fake-device-for-media-stream", "--use-fake-ui-for-media-stream"] }, {
diff --git a/third_party/WebKit/LayoutTests/external/wpt/css/css-grid/alignment/grid-content-alignment-second-pass-002-expected.txt b/third_party/WebKit/LayoutTests/external/wpt/css/css-grid/alignment/grid-content-alignment-second-pass-002-expected.txt deleted file mode 100644 index e359c5eb..0000000 --- a/third_party/WebKit/LayoutTests/external/wpt/css/css-grid/alignment/grid-content-alignment-second-pass-002-expected.txt +++ /dev/null
@@ -1,16 +0,0 @@ -This is a testharness.js-based test. -PASS .grid 1 -PASS .grid 2 -PASS .grid 3 -PASS .grid 4 -PASS .grid 5 -PASS .grid 6 -PASS .grid 7 -FAIL .grid 8 assert_equals: -<div class="grid contentSpaceAround" style="grid-template-rows: 25%;" data-expected-width="100" data-expected-height="80"> - <div class="firstRowFirstColumn" data-offset-x="15" data-offset-y="5" data-expected-width="70" data-expected-height="20">XXX X</div> - <div class="secondRowFirstColumn" data-offset-x="15" data-offset-y="35" data-expected-width="70" data-expected-height="40">X<br>X</div> -</div> -height expected 80 but got 60 -Harness: the test ran to completion. -
diff --git a/third_party/WebKit/LayoutTests/external/wpt/css/css-grid/layout-algorithm/grid-content-distribution-must-account-for-track-sizing-003.html b/third_party/WebKit/LayoutTests/external/wpt/css/css-grid/layout-algorithm/grid-content-distribution-must-account-for-track-sizing-003.html new file mode 100644 index 0000000..2ba9671 --- /dev/null +++ b/third_party/WebKit/LayoutTests/external/wpt/css/css-grid/layout-algorithm/grid-content-distribution-must-account-for-track-sizing-003.html
@@ -0,0 +1,39 @@ +<!DOCTYPE html> +<meta charset="utf-8"> +<title>CSS Grid Layout Test: Content Distribution and the track sizing algorithm</title> +<link rel="author" title="Javier Fernandez Garcia-Boente" href="mailto:jfernandez@igalia.com"> +<link rel="help" href="https://drafts.csswg.org/css-grid/#grid-align"> +<link rel="help" href="https://drafts.csswg.org/css-align/#content-distribution"> +<link rel="help" href="https://drafts.csswg.org/css-align/#valdef-align-content-space-around"> +<link rel="stylesheet" href="../../support/alignment.css"> +<meta name="flags" content="ahem"> +<meta name="assert" content="Content Distribution offset doesn't account for tracks with non-spanning items."> +<style> +.grid { + display: inline-grid; + background: grey; + grid-template-columns: 100px; + font: 20px/1 Ahem; + width: 200px; +} +.item1 { + background: green; + grid-column: 1; + grid-row: 1; +} +.item2 { + background: blue; + grid-column: 1; + grid-row: 2; +} +</style> +<script src="/resources/testharness.js"></script> +<script src="/resources/testharnessreport.js"></script> +<script src="/resources/check-layout-th.js"></script> + +<body onload="checkLayout('.grid')"> + <div class="grid justifyContentSpaceAround" data-expected-width="200" data-expected-height="60"> + <div class="item1" data-expected-width="100" data-expected-height="40">XXXX XXX</div> + <div class="item2" data-expected-width="100" data-expected-height="20">XXX</div> + </div> +</body>
diff --git a/third_party/WebKit/LayoutTests/external/wpt/css/css-grid/layout-algorithm/grid-content-distribution-must-account-for-track-sizing-004.html b/third_party/WebKit/LayoutTests/external/wpt/css/css-grid/layout-algorithm/grid-content-distribution-must-account-for-track-sizing-004.html new file mode 100644 index 0000000..e6de473 --- /dev/null +++ b/third_party/WebKit/LayoutTests/external/wpt/css/css-grid/layout-algorithm/grid-content-distribution-must-account-for-track-sizing-004.html
@@ -0,0 +1,39 @@ +<!DOCTYPE html> +<meta charset="utf-8"> +<title>CSS Grid Layout Test: Content Distribution and the track sizing algorithm</title> +<link rel="author" title="Javier Fernandez Garcia-Boente" href="mailto:jfernandez@igalia.com"> +<link rel="help" href="https://drafts.csswg.org/css-grid/#grid-align"> +<link rel="help" href="https://drafts.csswg.org/css-align/#content-distribution"> +<link rel="help" href="https://drafts.csswg.org/css-align/#valdef-align-content-space-between"> +<link rel="stylesheet" href="../../support/alignment.css"> +<meta name="flags" content="ahem"> +<meta name="assert" content="Content Distribution offset doesn't account for relative sized tracks with non-spanning items."> +<style> +.grid { + display: inline-grid; + background: grey; + grid-template-columns: 50%; + font: 20px/1 Ahem; +} + +.item1 { + background: green; + grid-column: 1; + grid-row: 1; +} +.item2 { + background: blue; + grid-column: 2; + grid-row: 1; +} +</style> +<script src="/resources/testharness.js"></script> +<script src="/resources/testharnessreport.js"></script> +<script src="/resources/check-layout-th.js"></script> + +<body onload="checkLayout('.grid')"> + <div class="grid justifyContentSpaceBetween" data-expected-width="220" data-expected-height="40"> + <div class="item1" data-expected-width="110" data-expected-height="40">XXXX XXX</div> + <div class="item2" data-expected-width="60" data-expected-height="40">XXX</div> + </div> +</body>
diff --git a/third_party/WebKit/LayoutTests/external/wpt/html/browsers/browsing-the-web/unloading-documents/003-expected.txt b/third_party/WebKit/LayoutTests/external/wpt/html/browsers/browsing-the-web/unloading-documents/003-expected.txt deleted file mode 100644 index 19d7f918..0000000 --- a/third_party/WebKit/LayoutTests/external/wpt/html/browsers/browsing-the-web/unloading-documents/003-expected.txt +++ /dev/null
@@ -1,4 +0,0 @@ -This is a testharness.js-based test. -FAIL document.open in beforeunload with link assert_equals: expected "0123456789" but got "01892B4" -Harness: the test ran to completion. -
diff --git a/third_party/WebKit/LayoutTests/external/wpt/html/browsers/browsing-the-web/unloading-documents/005-expected.txt b/third_party/WebKit/LayoutTests/external/wpt/html/browsers/browsing-the-web/unloading-documents/005-expected.txt deleted file mode 100644 index 9fd03331..0000000 --- a/third_party/WebKit/LayoutTests/external/wpt/html/browsers/browsing-the-web/unloading-documents/005-expected.txt +++ /dev/null
@@ -1,4 +0,0 @@ -This is a testharness.js-based test. -FAIL document.open in pagehide in iframe Cannot read property 'document' of null -Harness: the test ran to completion. -
diff --git a/third_party/WebKit/LayoutTests/external/wpt/html/webappapis/dynamic-markup-insertion/opening-the-input-stream/bailout-side-effects-ignore-opens-during-unload.window-expected.txt b/third_party/WebKit/LayoutTests/external/wpt/html/webappapis/dynamic-markup-insertion/opening-the-input-stream/bailout-side-effects-ignore-opens-during-unload.window-expected.txt deleted file mode 100644 index 0195cc99..0000000 --- a/third_party/WebKit/LayoutTests/external/wpt/html/webappapis/dynamic-markup-insertion/opening-the-input-stream/bailout-side-effects-ignore-opens-during-unload.window-expected.txt +++ /dev/null
@@ -1,6 +0,0 @@ -This is a testharness.js-based test. -FAIL document.open bailout should not have any side effects (ignore-opens-during-unload is greater than 0 during unload event) assert_not_equals: document nodes should not be cleared (ignore-opens-during-unload counter is greater than 0 during unload event) got disallowed value 0 -FAIL document.open bailout should not have any side effects (ignore-opens-during-unload is greater than 0 during beforeunload event) assert_not_equals: document nodes should not be cleared (ignore-opens-during-unload counter is greater than 0 during beforeunload event) got disallowed value 0 -FAIL document.open bailout should not have any side effects (ignore-opens-during-unload is greater than 0 during pagehide event) assert_not_equals: document nodes should not be cleared (ignore-opens-during-unload counter is greater than 0 during pagehide event) got disallowed value 0 -Harness: the test ran to completion. -
diff --git a/third_party/WebKit/LayoutTests/external/wpt/html/webappapis/dynamic-markup-insertion/opening-the-input-stream/ignore-opens-during-unload.window-expected.txt b/third_party/WebKit/LayoutTests/external/wpt/html/webappapis/dynamic-markup-insertion/opening-the-input-stream/ignore-opens-during-unload.window-expected.txt deleted file mode 100644 index c3b002d94..0000000 --- a/third_party/WebKit/LayoutTests/external/wpt/html/webappapis/dynamic-markup-insertion/opening-the-input-stream/ignore-opens-during-unload.window-expected.txt +++ /dev/null
@@ -1,6 +0,0 @@ -This is a testharness.js-based test. -FAIL document.open should bail out when ignore-opens-during-unload is greater than 0 during unload event assert_not_equals: got disallowed value 0 -FAIL document.open should bail out when ignore-opens-during-unload is greater than 0 during beforeunload event assert_not_equals: got disallowed value 0 -FAIL document.open should bail out when ignore-opens-during-unload is greater than 0 during pagehide event assert_not_equals: got disallowed value 0 -Harness: the test ran to completion. -
diff --git a/third_party/WebKit/LayoutTests/external/wpt/html/webappapis/dynamic-markup-insertion/opening-the-input-stream/ignore-opens-during-unload.window.js b/third_party/WebKit/LayoutTests/external/wpt/html/webappapis/dynamic-markup-insertion/opening-the-input-stream/ignore-opens-during-unload.window.js index 5de4b14..43506a2 100644 --- a/third_party/WebKit/LayoutTests/external/wpt/html/webappapis/dynamic-markup-insertion/opening-the-input-stream/ignore-opens-during-unload.window.js +++ b/third_party/WebKit/LayoutTests/external/wpt/html/webappapis/dynamic-markup-insertion/opening-the-input-stream/ignore-opens-during-unload.window.js
@@ -1,15 +1,60 @@ -for (const ev of ["unload", "beforeunload", "pagehide"]) { +for (const [ev, target] of [ + ["beforeunload", iframe => iframe.contentWindow], + ["pagehide", iframe => iframe.contentWindow], + ["unload", iframe => iframe.contentWindow], + ["visibilitychange", iframe => iframe.contentDocument], +]) { async_test(t => { const iframe = document.body.appendChild(document.createElement("iframe")); t.add_cleanup(() => iframe.remove()); iframe.src = "/common/blank.html"; iframe.onload = t.step_func(() => { - iframe.contentWindow.addEventListener(ev, t.step_func_done(() => { + target(iframe).addEventListener(ev, t.step_func_done(() => { assert_not_equals(iframe.contentDocument.childNodes.length, 0); assert_equals(iframe.contentDocument.open(), iframe.contentDocument); assert_not_equals(iframe.contentDocument.childNodes.length, 0); })); iframe.src = "about:blank"; }); - }, `document.open should bail out when ignore-opens-during-unload is greater than 0 during ${ev} event`); + }, `document.open should bail out when ignore-opens-during-unload is greater than 0 during ${ev} event (in top-level browsing context)`); + + async_test(t => { + const iframe = document.body.appendChild(document.createElement("iframe")); + t.add_cleanup(() => iframe.remove()); + iframe.src = "/common/blank.html?1"; + iframe.onload = t.step_func(() => { + const doc = iframe.contentDocument; + const innerIframe = doc.body.appendChild(doc.createElement("iframe")); + innerIframe.src = "/common/blank.html?2"; + innerIframe.onload = t.step_func(() => { + // Navigate the parent, listen on the child, and open() the parent. + target(innerIframe).addEventListener(ev, t.step_func_done(() => { + assert_not_equals(iframe.contentDocument.childNodes.length, 0); + iframe.contentDocument.open(); + assert_not_equals(iframe.contentDocument.childNodes.length, 0); + })); + iframe.src = "about:blank"; + }); + }); + }, `document.open should bail out when ignore-opens-during-unload is greater than 0 during ${ev} event (open(parent) while unloading parent and child)`); + + async_test(t => { + const iframe = document.body.appendChild(document.createElement("iframe")); + t.add_cleanup(() => iframe.remove()); + iframe.src = "/common/blank.html?1"; + iframe.onload = t.step_func(() => { + const doc = iframe.contentDocument; + const innerIframe = doc.body.appendChild(doc.createElement("iframe")); + innerIframe.src = "/common/blank.html?2"; + innerIframe.onload = t.step_func(() => { + // Navigate the child, listen on the child, and open() the parent. + target(innerIframe).addEventListener(ev, t.step_func_done(() => { + assert_not_equals(iframe.contentDocument.childNodes.length, 0); + iframe.contentDocument.open(); + assert_equals(iframe.contentDocument.childNodes.length, 0); + })); + innerIframe.src = "about:blank"; + }); + }); + }, `document.open should bail out when ignore-opens-during-unload is greater than 0 during ${ev} event (open(parent) while unloading child only)`); }
diff --git a/third_party/WebKit/LayoutTests/external/wpt/service-workers/cache-storage/resources/vary.py b/third_party/WebKit/LayoutTests/external/wpt/service-workers/cache-storage/resources/vary.py deleted file mode 100644 index 59e39bc..0000000 --- a/third_party/WebKit/LayoutTests/external/wpt/service-workers/cache-storage/resources/vary.py +++ /dev/null
@@ -1,25 +0,0 @@ -def main(request, response): - if "clear-vary-value-override-cookie" in request.GET: - response.unset_cookie("vary-value-override") - return "vary cookie cleared" - - set_cookie_vary = request.GET.first("set-vary-value-override-cookie", - default="") - if set_cookie_vary: - response.set_cookie("vary-value-override", set_cookie_vary) - return "vary cookie set" - - # If there is a vary-value-override cookie set, then use its value - # for the VARY header no matter what the query string is set to. This - # override is necessary to test the case when two URLs are identical - # (including query), but differ by VARY header. - cookie_vary = request.cookies.get("vary-value-override"); - if cookie_vary: - response.headers.set("vary", cookie_vary) - else: - # If there is no cookie, then use the query string value, if present. - query_vary = request.GET.first("vary", default="") - if query_vary: - response.headers.set("vary", query_vary) - - return "vary response"
diff --git a/third_party/WebKit/LayoutTests/external/wpt/service-workers/cache-storage/script-tests/cache-add.js b/third_party/WebKit/LayoutTests/external/wpt/service-workers/cache-storage/script-tests/cache-add.js index a482c42e..c03faeb 100644 --- a/third_party/WebKit/LayoutTests/external/wpt/service-workers/cache-storage/script-tests/cache-add.js +++ b/third_party/WebKit/LayoutTests/external/wpt/service-workers/cache-storage/script-tests/cache-add.js
@@ -267,84 +267,4 @@ 'twice.'); }, 'Cache.addAll called with the same Request object specified twice'); -cache_test(async function(cache, test) { - const url = '../resources/vary.py?vary=x-shape'; - let requests = [ - new Request(url, { headers: { 'x-shape': 'circle' }}), - new Request(url, { headers: { 'x-shape': 'square' }}), - ]; - let result = await cache.addAll(requests); - assert_equals(result, undefined, 'Cache.addAll() should succeed'); - }, 'Cache.addAll should succeed when entries differ by vary header'); - -cache_test(async function(cache, test) { - const url = '../resources/vary.py?vary=x-shape'; - let requests = [ - new Request(url, { headers: { 'x-shape': 'circle' }}), - new Request(url, { headers: { 'x-shape': 'circle' }}), - ]; - await promise_rejects( - test, - 'InvalidStateError', - cache.addAll(requests), - 'Cache.addAll() should reject when entries are duplicate by vary header'); - }, 'Cache.addAll should reject when entries are duplicate by vary header'); - -// VARY header matching is asymmetric. Determining if two entries are duplicate -// depends on which entry's response is used in the comparison. The target -// response's VARY header determines what request headers are examined. This -// test verifies that Cache.addAll() duplicate checking handles this asymmetric -// behavior correctly. -cache_test(async function(cache, test) { - const base_url = '../resources/vary.py'; - - // Define a request URL that sets a VARY header in the - // query string to be echoed back by the server. - const url = base_url + '?vary=x-size'; - - // Set a cookie to override the VARY header of the response - // when the request is made with credentials. This will - // take precedence over the query string vary param. This - // is a bit confusing, but it's necessary to construct a test - // where the URL is the same, but the VARY headers differ. - // - // Note, the test could also pass this information in additional - // request headers. If the cookie approach becomes too unwieldy - // this test could be rewritten to use that technique. - await fetch(base_url + '?set-vary-value-override-cookie=x-shape'); - test.add_cleanup(_ => fetch(base_url + '?clear-vary-value-override-cookie')); - - let requests = [ - // This request will result in a Response with a "Vary: x-shape" - // header. This *will not* result in a duplicate match with the - // other entry. - new Request(url, { headers: { 'x-shape': 'circle', - 'x-size': 'big' }, - credentials: 'same-origin' }), - - // This request will result in a Response with a "Vary: x-size" - // header. This *will* result in a duplicate match with the other - // entry. - new Request(url, { headers: { 'x-shape': 'square', - 'x-size': 'big' }, - credentials: 'omit' }), - ]; - await promise_rejects( - test, - 'InvalidStateError', - cache.addAll(requests), - 'Cache.addAll() should reject when one entry has a vary header ' + - 'matching an earlier entry.'); - - // Test the reverse order now. - await promise_rejects( - test, - 'InvalidStateError', - cache.addAll(requests.reverse()), - 'Cache.addAll() should reject when one entry has a vary header ' + - 'matching a later entry.'); - - }, 'Cache.addAll should reject when one entry has a vary header ' + - 'matching another entry'); - done();
diff --git a/third_party/WebKit/LayoutTests/external/wpt/service-workers/cache-storage/serviceworker/cache-add.https-expected.txt b/third_party/WebKit/LayoutTests/external/wpt/service-workers/cache-storage/serviceworker/cache-add.https-expected.txt new file mode 100644 index 0000000..a1555dcb8 --- /dev/null +++ b/third_party/WebKit/LayoutTests/external/wpt/service-workers/cache-storage/serviceworker/cache-add.https-expected.txt
@@ -0,0 +1,22 @@ +This is a testharness.js-based test. +PASS Cache.add and Cache.addAll +PASS Cache.add called with no arguments +PASS Cache.add called with relative URL specified as a string +PASS Cache.add called with non-HTTP/HTTPS URL +PASS Cache.add called with Request object +PASS Cache.add called with POST request +PASS Cache.add called twice with the same Request object +PASS Cache.add with request with null body (not consumed) +PASS Cache.add with 206 response +PASS Cache.addAll with 206 response +PASS Cache.add with request that results in a status of 404 +PASS Cache.add with request that results in a status of 500 +PASS Cache.addAll with no arguments +PASS Cache.addAll with a mix of valid and undefined arguments +PASS Cache.addAll with an empty array +PASS Cache.addAll with string URL arguments +PASS Cache.addAll with Request arguments +PASS Cache.addAll with a mix of succeeding and failing requests +FAIL Cache.addAll called with the same Request object specified twice assert_unreached: Should have rejected: Cache.addAll should throw InvalidStateError if the same request is added twice. Reached unreachable code +Harness: the test ran to completion. +
diff --git a/third_party/WebKit/LayoutTests/external/wpt/service-workers/cache-storage/window/cache-add.https-expected.txt b/third_party/WebKit/LayoutTests/external/wpt/service-workers/cache-storage/window/cache-add.https-expected.txt new file mode 100644 index 0000000..3f3f278 --- /dev/null +++ b/third_party/WebKit/LayoutTests/external/wpt/service-workers/cache-storage/window/cache-add.https-expected.txt
@@ -0,0 +1,21 @@ +This is a testharness.js-based test. +PASS Cache.add called with no arguments +PASS Cache.add called with relative URL specified as a string +PASS Cache.add called with non-HTTP/HTTPS URL +PASS Cache.add called with Request object +PASS Cache.add called with POST request +PASS Cache.add called twice with the same Request object +PASS Cache.add with request with null body (not consumed) +PASS Cache.add with 206 response +PASS Cache.addAll with 206 response +PASS Cache.add with request that results in a status of 404 +PASS Cache.add with request that results in a status of 500 +PASS Cache.addAll with no arguments +PASS Cache.addAll with a mix of valid and undefined arguments +PASS Cache.addAll with an empty array +PASS Cache.addAll with string URL arguments +PASS Cache.addAll with Request arguments +PASS Cache.addAll with a mix of succeeding and failing requests +FAIL Cache.addAll called with the same Request object specified twice assert_unreached: Should have rejected: Cache.addAll should throw InvalidStateError if the same request is added twice. Reached unreachable code +Harness: the test ran to completion. +
diff --git a/third_party/WebKit/LayoutTests/external/wpt/service-workers/cache-storage/worker/cache-add.https-expected.txt b/third_party/WebKit/LayoutTests/external/wpt/service-workers/cache-storage/worker/cache-add.https-expected.txt new file mode 100644 index 0000000..3f3f278 --- /dev/null +++ b/third_party/WebKit/LayoutTests/external/wpt/service-workers/cache-storage/worker/cache-add.https-expected.txt
@@ -0,0 +1,21 @@ +This is a testharness.js-based test. +PASS Cache.add called with no arguments +PASS Cache.add called with relative URL specified as a string +PASS Cache.add called with non-HTTP/HTTPS URL +PASS Cache.add called with Request object +PASS Cache.add called with POST request +PASS Cache.add called twice with the same Request object +PASS Cache.add with request with null body (not consumed) +PASS Cache.add with 206 response +PASS Cache.addAll with 206 response +PASS Cache.add with request that results in a status of 404 +PASS Cache.add with request that results in a status of 500 +PASS Cache.addAll with no arguments +PASS Cache.addAll with a mix of valid and undefined arguments +PASS Cache.addAll with an empty array +PASS Cache.addAll with string URL arguments +PASS Cache.addAll with Request arguments +PASS Cache.addAll with a mix of succeeding and failing requests +FAIL Cache.addAll called with the same Request object specified twice assert_unreached: Should have rejected: Cache.addAll should throw InvalidStateError if the same request is added twice. Reached unreachable code +Harness: the test ran to completion. +
diff --git a/third_party/WebKit/LayoutTests/fast/canvas-api/canvas-textMetrics-advances.html b/third_party/WebKit/LayoutTests/fast/canvas-api/canvas-textMetrics-advances.html index 695969e..c1820eda 100644 --- a/third_party/WebKit/LayoutTests/fast/canvas-api/canvas-textMetrics-advances.html +++ b/third_party/WebKit/LayoutTests/fast/canvas-api/canvas-textMetrics-advances.html
@@ -22,11 +22,11 @@ { text: "ليس في اسمنا", rtl: true }, { text: "\u202EHello", rtl: true }, { text: "\u202EHello World", rtl: true }, - // TODO(davidqu): Fix the following edge cases: - //{ text: "الله", rtl: true }, // Special ligatures. - //{ text: "🏁", rtl: false }, // One glyph with two "characters". - //{ text: "एक आम भाषा", rtl: false }, // Special post-modifying characters. - //{ text: "a\u0301", rtl: true }, // Combining diacritical marks + { text: "الله", rtl: true }, // Special ligatures. + { text: "اين المكتبة؟", rtl: true }, // Special ligatures. + { text: "🏁🎶🏁", rtl: false }, // One glyph with two "characters". + { text: "एक आम भाषा", rtl: false }, // Special post-modifying characters. + { text: "a\u0301", rtl: false }, // Combining diacritical marks ] function forEachExample(fn) { @@ -75,7 +75,7 @@ }); } -function testNonIncreasing(ctx) { +function testNonIncreasingForRtl(ctx) { forEachExample((ex, align) => { if (ex.rtl) { const tm = getTextMetrics(ctx, ex.text, align, ex.rtl ? "rtl" : "ltr"); @@ -85,9 +85,9 @@ }); } -function testNonDecreasing(ctx) { +function testNonDecreasingForLtr(ctx) { forEachExample((ex, align) => { - if (ex.ltr) { + if (! ex.rtl) { const tm = getTextMetrics(ctx, ex.text, align, ex.rtl ? "rtl" : "ltr"); assert_true(isNonDecreasing(tm.advances), "LTR advances must be non-decreasing (" + ex.text + ")"); @@ -106,7 +106,8 @@ function testAdvances(ctx) { testEmptyStringReturnsEmptyAdvances(ctx); testAllPositive(ctx); - testNonDecreasing(ctx); + testNonIncreasingForRtl(ctx); + testNonDecreasingForLtr(ctx); testLastAdvanceLessThanWith(ctx); }
diff --git a/third_party/WebKit/LayoutTests/fast/events/alert-in-beforeunload-document-write-expected.txt b/third_party/WebKit/LayoutTests/fast/events/alert-in-beforeunload-document-write-expected.txt index 29d28aa..56084445 100644 --- a/third_party/WebKit/LayoutTests/fast/events/alert-in-beforeunload-document-write-expected.txt +++ b/third_party/WebKit/LayoutTests/fast/events/alert-in-beforeunload-document-write-expected.txt
@@ -1,2 +1 @@ -CONSOLE ERROR: Blocked alert('hello world!') during beforeunload. Test that alert() inside a document.write() during a beforeunload handler does not confuse the modal dialog blocker. This test passes if no alert() dialogs are seen.
diff --git a/third_party/WebKit/LayoutTests/fast/loader/document-destruction-within-unload-expected.txt b/third_party/WebKit/LayoutTests/fast/loader/document-destruction-within-unload-expected.txt deleted file mode 100644 index b6077a5b..0000000 --- a/third_party/WebKit/LayoutTests/fast/loader/document-destruction-within-unload-expected.txt +++ /dev/null
@@ -1,2 +0,0 @@ - -For the test to pass there should be no crash.
diff --git a/third_party/WebKit/LayoutTests/fast/loader/document-destruction-within-unload.html b/third_party/WebKit/LayoutTests/fast/loader/document-destruction-within-unload.html deleted file mode 100644 index e1a6cd8..0000000 --- a/third_party/WebKit/LayoutTests/fast/loader/document-destruction-within-unload.html +++ /dev/null
@@ -1,17 +0,0 @@ -<html> -<body> -<script> -if (window.testRunner) { - testRunner.dumpAsText(); - testRunner.waitUntilDone(); -} - -function done() { - if (window.testRunner) - testRunner.notifyDone(); -} -</script> -<iframe src="resources/document-destruction-within-unload-iframe.html"></iframe> -<p>For the test to pass there should be no crash.</p> -</body> -</html>
diff --git a/third_party/WebKit/LayoutTests/fast/loader/resources/document-destruction-within-unload-iframe.html b/third_party/WebKit/LayoutTests/fast/loader/resources/document-destruction-within-unload-iframe.html deleted file mode 100644 index b3378f2..0000000 --- a/third_party/WebKit/LayoutTests/fast/loader/resources/document-destruction-within-unload-iframe.html +++ /dev/null
@@ -1,19 +0,0 @@ -<html> -<body> -<script> -function runTest() { - var test = document.getElementById('root').contentDocument; - test.firstChild.setAttribute('onunload', "parent.clearUs();"); - location.reload(); -} - -function clearUs() { - document.write(); - parent.done(); - document.close(); -} -</script> -<object data="does_not_exist"></object> -<object data="document-destruction-within-unload.svg" id="root" onload="runTest();"></object> -</body> -</html>
diff --git a/third_party/WebKit/LayoutTests/fast/loader/resources/document-destruction-within-unload.svg b/third_party/WebKit/LayoutTests/fast/loader/resources/document-destruction-within-unload.svg deleted file mode 100644 index e0af766..0000000 --- a/third_party/WebKit/LayoutTests/fast/loader/resources/document-destruction-within-unload.svg +++ /dev/null
@@ -1,2 +0,0 @@ -<svg xmlns="http://www.w3.org/2000/svg"> -</svg>
diff --git a/third_party/WebKit/LayoutTests/flag-specific/enable-blink-gen-property-trees/paint/invalidation/compositing/clipping-should-not-repaint-composited-descendants-expected.txt b/third_party/WebKit/LayoutTests/flag-specific/enable-blink-gen-property-trees/paint/invalidation/compositing/clipping-should-not-repaint-composited-descendants-expected.txt new file mode 100644 index 0000000..78d6b28 --- /dev/null +++ b/third_party/WebKit/LayoutTests/flag-specific/enable-blink-gen-property-trees/paint/invalidation/compositing/clipping-should-not-repaint-composited-descendants-expected.txt
@@ -0,0 +1,88 @@ +{ + "layers": [ + { + "name": "LayoutView #document", + "bounds": [800, 600], + "drawsContent": false, + "backgroundColor": "#FFFFFF" + }, + { + "name": "Scrolling Layer", + "bounds": [785, 600], + "drawsContent": false + }, + { + "name": "Scrolling Contents Layer", + "bounds": [785, 616], + "contentsOpaque": true, + "backgroundColor": "#FFFFFF" + }, + { + "name": "LayoutBlockFlow (positioned) DIV class='clipping-container'", + "bounds": [100, 100], + "drawsContent": false, + "transform": 1 + }, + { + "name": "LayoutBlockFlow DIV class='clipped-composited-child'", + "bounds": [252, 252], + "contentsOpaque": true, + "backgroundColor": "#FFFF00", + "transform": 2 + }, + { + "name": "LayoutBlockFlow (positioned) DIV class='clipping-container with-initial-clipping'", + "bounds": [100, 100], + "drawsContent": false, + "transform": 3 + }, + { + "name": "LayoutBlockFlow DIV class='clipped-composited-child'", + "bounds": [252, 252], + "contentsOpaque": true, + "backgroundColor": "#FFFF00", + "transform": 4 + } + ], + "transforms": [ + { + "id": 1, + "transform": [ + [1, 0, 0, 0], + [0, 1, 0, 0], + [0, 0, 1, 0], + [108, 108, 0, 1] + ] + }, + { + "id": 2, + "parent": 1, + "transform": [ + [1, 0, 0, 0], + [0, 1, 0, 0], + [0, 0, 1, 0], + [-100, -100, 0, 1] + ] + }, + { + "id": 3, + "transform": [ + [1, 0, 0, 0], + [0, 1, 0, 0], + [0, 0, 1, 0], + [108, 408, 0, 1] + ] + }, + { + "id": 4, + "parent": 3, + "transform": [ + [1, 0, 0, 0], + [0, 1, 0, 0], + [0, 0, 1, 0], + [-100, -100, 0, 1] + ] + } + ] +} +
diff --git a/third_party/WebKit/LayoutTests/flag-specific/enable-blink-gen-property-trees/paint/invalidation/compositing/overlap-test-with-filter-expected.txt b/third_party/WebKit/LayoutTests/flag-specific/enable-blink-gen-property-trees/paint/invalidation/compositing/overlap-test-with-filter-expected.txt new file mode 100644 index 0000000..d4917843 --- /dev/null +++ b/third_party/WebKit/LayoutTests/flag-specific/enable-blink-gen-property-trees/paint/invalidation/compositing/overlap-test-with-filter-expected.txt
@@ -0,0 +1,64 @@ +{ + "layers": [ + { + "name": "LayoutView #document", + "bounds": [800, 600], + "drawsContent": false, + "backgroundColor": "#FFFFFF" + }, + { + "name": "Scrolling Layer", + "bounds": [800, 600], + "drawsContent": false + }, + { + "name": "Scrolling Contents Layer", + "bounds": [800, 600], + "contentsOpaque": true, + "backgroundColor": "#FFFFFF" + }, + { + "name": "LayoutIFrame IFRAME", + "bounds": [300, 100] + }, + { + "name": "LayoutView #document", + "bounds": [300, 100], + "backgroundColor": "#FFFF00" + }, + { + "name": "LayoutBlockFlow BODY", + "bounds": [284, 84], + "backgroundColor": "#FFFF00", + "transform": 1 + }, + { + "name": "LayoutBlockFlow (positioned) DIV", + "bounds": [300, 100], + "contentsOpaque": true, + "backgroundColor": "#D3D3D3", + "transform": 2 + } + ], + "transforms": [ + { + "id": 1, + "transform": [ + [1, 0, 0, 0], + [0, 1, 0, 0], + [0, 0, 1, 0], + [8, 8, 0, 1] + ] + }, + { + "id": 2, + "transform": [ + [1, 0, 0, 0], + [0, 1, 0, 0], + [0, 0, 1, 0], + [151, 0, 0, 1] + ] + } + ] +} +
diff --git a/third_party/WebKit/LayoutTests/flag-specific/enable-blink-gen-property-trees/paint/invalidation/compositing/repaint-overflow-scrolled-squashed-content-expected.txt b/third_party/WebKit/LayoutTests/flag-specific/enable-blink-gen-property-trees/paint/invalidation/compositing/repaint-overflow-scrolled-squashed-content-expected.txt new file mode 100644 index 0000000..c5d3da8 --- /dev/null +++ b/third_party/WebKit/LayoutTests/flag-specific/enable-blink-gen-property-trees/paint/invalidation/compositing/repaint-overflow-scrolled-squashed-content-expected.txt
@@ -0,0 +1,57 @@ +{ + "layers": [ + { + "name": "LayoutView #document", + "bounds": [800, 600], + "drawsContent": false, + "backgroundColor": "#FFFFFF" + }, + { + "name": "Scrolling Layer", + "bounds": [800, 600], + "drawsContent": false + }, + { + "name": "Scrolling Contents Layer", + "bounds": [800, 600], + "contentsOpaque": true, + "backgroundColor": "#FFFFFF" + }, + { + "name": "Squashing Containment Layer", + "drawsContent": false + }, + { + "name": "LayoutBlockFlow DIV id='foo2'", + "bounds": [150, 1000], + "contentsOpaque": true, + "backgroundColor": "#ADD8E6", + "transform": 1 + }, + { + "name": "Squashing Layer (first squashed layer: LayoutBlockFlow (positioned) DIV id='foo')", + "position": [8, 8], + "bounds": [100, 1000], + "paintInvalidations": [ + { + "object": "LayoutBlockFlow (positioned) DIV id='foo'", + "rect": [0, 0, 100, 1000], + "reason": "style change" + } + ] + } + ], + "transforms": [ + { + "id": 1, + "transform": [ + [1, 0, 0, 0], + [0, 1, 0, 0], + [0, 0, 1, 0], + [8, 8, 0, 1] + ], + "flattenInheritedTransform": false + } + ] +} +
diff --git a/third_party/WebKit/LayoutTests/flag-specific/enable-blink-gen-property-trees/paint/invalidation/compositing/should-not-repaint-composited-descendants-expected.txt b/third_party/WebKit/LayoutTests/flag-specific/enable-blink-gen-property-trees/paint/invalidation/compositing/should-not-repaint-composited-descendants-expected.txt new file mode 100644 index 0000000..ec7710c --- /dev/null +++ b/third_party/WebKit/LayoutTests/flag-specific/enable-blink-gen-property-trees/paint/invalidation/compositing/should-not-repaint-composited-descendants-expected.txt
@@ -0,0 +1,50 @@ +{ + "layers": [ + { + "name": "LayoutView #document", + "bounds": [800, 600], + "drawsContent": false, + "backgroundColor": "#FFFFFF" + }, + { + "name": "Scrolling Layer", + "bounds": [800, 600], + "drawsContent": false + }, + { + "name": "Scrolling Contents Layer", + "bounds": [800, 600], + "contentsOpaque": true, + "backgroundColor": "#FFFFFF" + }, + { + "name": "LayoutBlockFlow (positioned) DIV id='composited-box'", + "position": [38, 38], + "bounds": [20, 70], + "contentsOpaque": true, + "backfaceVisibility": "hidden", + "backgroundColor": "#008000", + "paintInvalidations": [ + { + "object": "LayoutBlockFlow (positioned) DIV id='composited-box'", + "rect": [0, 0, 20, 70], + "reason": "full layer" + }, + { + "object": "LayoutBlockFlow (positioned) DIV id='composited-box'", + "rect": [0, 0, 10, 60], + "reason": "full layer" + } + ] + }, + { + "name": "LayoutBlockFlow DIV class='composited child'", + "position": [8, 58], + "bounds": [50, 50], + "contentsOpaque": true, + "backfaceVisibility": "hidden", + "backgroundColor": "#008000" + } + ] +} +
diff --git a/third_party/WebKit/LayoutTests/flag-specific/enable-blink-gen-property-trees/paint/invalidation/compositing/should-not-repaint-composited-descendants-on-overflow-change-expected.txt b/third_party/WebKit/LayoutTests/flag-specific/enable-blink-gen-property-trees/paint/invalidation/compositing/should-not-repaint-composited-descendants-on-overflow-change-expected.txt new file mode 100644 index 0000000..1e0b2bb --- /dev/null +++ b/third_party/WebKit/LayoutTests/flag-specific/enable-blink-gen-property-trees/paint/invalidation/compositing/should-not-repaint-composited-descendants-on-overflow-change-expected.txt
@@ -0,0 +1,53 @@ +{ + "layers": [ + { + "name": "LayoutView #document", + "bounds": [800, 600], + "drawsContent": false, + "backgroundColor": "#FFFFFF" + }, + { + "name": "Scrolling Layer", + "bounds": [800, 600], + "drawsContent": false + }, + { + "name": "Scrolling Contents Layer", + "bounds": [800, 600], + "contentsOpaque": true, + "backgroundColor": "#FFFFFF" + }, + { + "name": "LayoutBlockFlow DIV class='composited-child'", + "bounds": [100, 100], + "contentsOpaque": true, + "backfaceVisibility": "hidden", + "backgroundColor": "#008000" + }, + { + "name": "LayoutBlockFlow DIV class='composited-child'", + "position": [0, 200], + "bounds": [100, 100], + "contentsOpaque": true, + "backfaceVisibility": "hidden", + "backgroundColor": "#008000" + }, + { + "name": "LayoutBlockFlow (relative positioned) DIV class='composited-child overflow-child'", + "position": [150, 150], + "bounds": [100, 100], + "contentsOpaque": true, + "backfaceVisibility": "hidden", + "backgroundColor": "#008000" + }, + { + "name": "LayoutBlockFlow (relative positioned) DIV class='composited-child overflow-child'", + "position": [150, 350], + "bounds": [100, 100], + "contentsOpaque": true, + "backfaceVisibility": "hidden", + "backgroundColor": "#008000" + } + ] +} +
diff --git a/third_party/WebKit/LayoutTests/flag-specific/enable-blink-gen-property-trees/paint/invalidation/scroll/overflow-scroll-composited-non-stacking-child-expected.txt b/third_party/WebKit/LayoutTests/flag-specific/enable-blink-gen-property-trees/paint/invalidation/scroll/overflow-scroll-composited-non-stacking-child-expected.txt new file mode 100644 index 0000000..bc911667 --- /dev/null +++ b/third_party/WebKit/LayoutTests/flag-specific/enable-blink-gen-property-trees/paint/invalidation/scroll/overflow-scroll-composited-non-stacking-child-expected.txt
@@ -0,0 +1,72 @@ +{ + "layers": [ + { + "name": "LayoutView #document", + "bounds": [800, 600], + "drawsContent": false, + "backgroundColor": "#FFFFFF" + }, + { + "name": "Scrolling Layer", + "bounds": [800, 600], + "drawsContent": false + }, + { + "name": "Scrolling Contents Layer", + "bounds": [800, 600], + "contentsOpaque": true, + "backgroundColor": "#FFFFFF", + "paintInvalidations": [ + { + "object": "LayoutBlockFlow (positioned) DIV class='back'", + "rect": [93, 125, 180, 100], + "reason": "paint property change" + }, + { + "object": "LayoutBlockFlow (positioned) DIV class='back'", + "rect": [93, 75, 180, 100], + "reason": "paint property change" + }, + { + "object": "VerticalScrollbar", + "rect": [308, 65, 15, 175], + "reason": "scroll control" + } + ] + }, + { + "name": "LayoutBlockFlow (positioned) DIV class='icon'", + "bounds": [40, 40], + "contentsOpaque": true, + "backgroundColor": "#FFDDBB", + "transform": 1 + }, + { + "name": "Squashing Containment Layer", + "drawsContent": false + }, + { + "name": "LayoutBlockFlow (relative positioned) DIV class='list'", + "position": [43, 35], + "bounds": [180, 250], + "drawsContent": false + }, + { + "name": "Squashing Layer (first squashed layer: LayoutBlockFlow (relative positioned) DIV class='commit')", + "position": [43, 35], + "bounds": [180, 250] + } + ], + "transforms": [ + { + "id": 1, + "transform": [ + [1, 0, 0, 0], + [0, 1, 0, 0], + [0, 0, 1, 0], + [200, 10, 0, 1] + ] + } + ] +} +
diff --git a/third_party/WebKit/LayoutTests/flag-specific/enable-blink-gen-property-trees/paint/invalidation/scroll/repaint-composited-child-in-scrolled-container-expected.txt b/third_party/WebKit/LayoutTests/flag-specific/enable-blink-gen-property-trees/paint/invalidation/scroll/repaint-composited-child-in-scrolled-container-expected.txt new file mode 100644 index 0000000..18abbef --- /dev/null +++ b/third_party/WebKit/LayoutTests/flag-specific/enable-blink-gen-property-trees/paint/invalidation/scroll/repaint-composited-child-in-scrolled-container-expected.txt
@@ -0,0 +1,54 @@ +{ + "layers": [ + { + "name": "LayoutView #document", + "bounds": [800, 600], + "drawsContent": false, + "backgroundColor": "#FFFFFF" + }, + { + "name": "Scrolling Layer", + "bounds": [800, 600], + "drawsContent": false + }, + { + "name": "Scrolling Contents Layer", + "bounds": [800, 600], + "contentsOpaque": true, + "backgroundColor": "#FFFFFF", + "paintInvalidations": [ + { + "object": "HorizontalScrollbar", + "rect": [8, 293, 285, 15], + "reason": "scroll control" + } + ] + }, + { + "name": "LayoutBlockFlow (positioned) DIV id='container'", + "bounds": [600, 600], + "contentsOpaque": true, + "backgroundColor": "#FF0000", + "paintInvalidations": [ + { + "object": "LayoutBlockFlow DIV id='inner'", + "rect": [0, 0, 600, 600], + "reason": "appeared" + } + ], + "transform": 1 + } + ], + "transforms": [ + { + "id": 1, + "transform": [ + [1, 0, 0, 0], + [0, 1, 0, 0], + [0, 0, 1, 0], + [-307, 8, 0, 1] + ] + } + ] +} +
diff --git a/third_party/blink/public/platform/modules/cache_storage/cache_storage.mojom b/third_party/blink/public/platform/modules/cache_storage/cache_storage.mojom index a4f092e..67c1693 100644 --- a/third_party/blink/public/platform/modules/cache_storage/cache_storage.mojom +++ b/third_party/blink/public/platform/modules/cache_storage/cache_storage.mojom
@@ -21,7 +21,6 @@ kErrorQueryTooLarge = 6, // TODO(cmumford): kErrorNotImplemented is deprecated. Remove use in code. kErrorNotImplemented = 7, - kErrorDuplicateOperation = 8, // Add new values here. };
diff --git a/third_party/blink/public/platform/modules/locks/lock_manager.mojom b/third_party/blink/public/platform/modules/locks/lock_manager.mojom index e0eae77..fa4fa2c 100644 --- a/third_party/blink/public/platform/modules/locks/lock_manager.mojom +++ b/third_party/blink/public/platform/modules/locks/lock_manager.mojom
@@ -46,7 +46,7 @@ // availablility and options. Once granted, the lock will be held until // explicitly released or the holding context is terminated. // -// Proposal: https://github.com/inexorabletash/web-locks +// Proposal: https://wicg.github.io/web-locks interface LockManager { // PREEMPT corresponds to the |steal| option in the API; if used then
diff --git a/third_party/blink/public/web/web_local_frame.h b/third_party/blink/public/web/web_local_frame.h index 33322a5..fdd0176f 100644 --- a/third_party/blink/public/web/web_local_frame.h +++ b/third_party/blink/public/web/web_local_frame.h
@@ -679,30 +679,6 @@ // default behavior will be restored. virtual void SetTickmarks(const WebVector<WebRect>&) = 0; - // Notifies how many matches have been found in this frame so far, for a - // given identifier. |final_update| specifies whether this is the last - // update for this frame. - // TODO(rakina): Make WebPluginContainer call FindInPage directly and remove - // this. - virtual void ReportFindInPageMatchCount(int identifier, - int count, - bool final_update) = 0; - - // Notifies what tick-mark rect is currently selected. The given - // identifier lets the client know which request this message belongs - // to, so that it can choose to ignore the message if it has moved on - // to other things. The selection rect is expected to have coordinates - // relative to the top left corner of the web page area and represent - // where on the screen the selection rect is currently located. - // |final_update| specifies whether this is the last update for this - // frame. - // TODO(rakina): Make WebPluginContainer call FindInPage directly and remove - // this. - virtual void ReportFindInPageSelection(int identifier, - int active_match_ordinal, - const WebRect& selection, - bool final_update) = 0; - // Context menu ----------------------------------------------------------- // Returns the node that the context menu opened over.
diff --git a/third_party/blink/public/web/web_plugin_container.h b/third_party/blink/public/web/web_plugin_container.h index b85272a..2060c5a 100644 --- a/third_party/blink/public/web/web_plugin_container.h +++ b/third_party/blink/public/web/web_plugin_container.h
@@ -138,6 +138,11 @@ // Sets |this| as find handler for the associated frame. virtual void UsePluginAsFindHandler() = 0; + virtual void ReportFindInPageMatchCount(int identifier, + int total, + bool final_update) = 0; + virtual void ReportFindInPageSelection(int identifier, int index) = 0; + virtual float DeviceScaleFactor() = 0; virtual float PageScaleFactor() = 0; virtual float PageZoomFactor() = 0;
diff --git a/third_party/blink/renderer/core/dom/BUILD.gn b/third_party/blink/renderer/core/dom/BUILD.gn index 97a5327..fa23d84 100644 --- a/third_party/blink/renderer/core/dom/BUILD.gn +++ b/third_party/blink/renderer/core/dom/BUILD.gn
@@ -151,6 +151,7 @@ "id_target_observer_registry.h", "idle_deadline.cc", "idle_deadline.h", + "ignore_opens_during_unload_count_incrementer.h", "increment_load_event_delay_count.cc", "increment_load_event_delay_count.h", "iterator.h",
diff --git a/third_party/blink/renderer/core/dom/document.cc b/third_party/blink/renderer/core/dom/document.cc index 7bdf3e3..3a0745f 100644 --- a/third_party/blink/renderer/core/dom/document.cc +++ b/third_party/blink/renderer/core/dom/document.cc
@@ -635,6 +635,7 @@ contains_plugins_(false), ignore_destructive_write_count_(0), throw_on_dynamic_markup_insertion_count_(0), + ignore_opens_during_unload_count_(0), markers_(new DocumentMarkerController(*this)), update_focus_appearance_timer_( GetTaskRunner(TaskType::kInternalUserInteraction), @@ -3051,11 +3052,11 @@ open(); } +// https://html.spec.whatwg.org/C/dynamic-markup-insertion.html#document-open-steps void Document::open() { DCHECK(!ImportLoader()); if (frame_) { - // https://html.spec.whatwg.org/C/dynamic-markup-insertion.html#document-open-steps // If |document| has an active parser whose script nesting level is greater // than 0, then return |document|. if (ScriptableDocumentParser* parser = GetScriptableDocumentParser()) { @@ -3063,6 +3064,11 @@ return; } + // Similarly, if |document|'s ignore-opens-during-unload counter is greater + // than 0, then return |document|. + if (ignore_opens_during_unload_count_) + return; + if (frame_->Loader().HasProvisionalNavigation()) { frame_->Loader().StopAllLoaders(); // Navigations handled by the client should also be cancelled. @@ -3776,19 +3782,22 @@ bool has_insertion_point = parser_ && parser_->HasInsertionPoint(); - if (!has_insertion_point && ignore_destructive_write_count_) { - AddConsoleMessage( - ConsoleMessage::Create(kJSMessageSource, kWarningMessageLevel, - ExceptionMessages::FailedToExecute( - "write", "Document", - "It isn't possible to write into a document " - "from an asynchronously-loaded external " - "script unless it is explicitly opened."))); - return; - } + if (!has_insertion_point) { + if (ignore_destructive_write_count_) { + AddConsoleMessage(ConsoleMessage::Create( + kJSMessageSource, kWarningMessageLevel, + ExceptionMessages::FailedToExecute( + "write", "Document", + "It isn't possible to write into a document " + "from an asynchronously-loaded external " + "script unless it is explicitly opened."))); + return; + } + if (ignore_opens_during_unload_count_) + return; - if (!has_insertion_point) open(entered_document, ASSERT_NO_EXCEPTION); + } DCHECK(parser_); PerformanceMonitor::ReportGenericViolation(
diff --git a/third_party/blink/renderer/core/dom/document.h b/third_party/blink/renderer/core/dom/document.h index 6a72583..54af198 100644 --- a/third_party/blink/renderer/core/dom/document.h +++ b/third_party/blink/renderer/core/dom/document.h
@@ -1483,6 +1483,7 @@ private: friend class IgnoreDestructiveWriteCountIncrementer; friend class ThrowOnDynamicMarkupInsertionCountIncrementer; + friend class IgnoreOpensDuringUnloadCountIncrementer; friend class NthIndexCache; FRIEND_TEST_ALL_PREFIXES(FrameFetchContextSubresourceFilterTest, DuringOnFreeze); @@ -1708,10 +1709,12 @@ bool contains_validity_style_rules_; bool contains_plugins_; - // http://www.whatwg.org/specs/web-apps/current-work/#ignore-destructive-writes-counter + // https://html.spec.whatwg.org/C/dynamic-markup-insertion.html#ignore-destructive-writes-counter unsigned ignore_destructive_write_count_; - // https://html.spec.whatwg.org/#throw-on-dynamic-markup-insertion-counter + // https://html.spec.whatwg.org/C/dynamic-markup-insertion.html#throw-on-dynamic-markup-insertion-counter unsigned throw_on_dynamic_markup_insertion_count_; + // https://html.spec.whatwg.org/C/dynamic-markup-insertion.html#ignore-opens-during-unload-counter + unsigned ignore_opens_during_unload_count_; String title_; String raw_title_;
diff --git a/third_party/blink/renderer/core/dom/ignore_opens_during_unload_count_incrementer.h b/third_party/blink/renderer/core/dom/ignore_opens_during_unload_count_incrementer.h new file mode 100644 index 0000000..0863a13 --- /dev/null +++ b/third_party/blink/renderer/core/dom/ignore_opens_during_unload_count_incrementer.h
@@ -0,0 +1,39 @@ +// Copyright 2018 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#ifndef THIRD_PARTY_BLINK_RENDERER_CORE_DOM_IGNORE_OPENS_DURING_UNLOAD_COUNT_INCREMENTER_H_ +#define THIRD_PARTY_BLINK_RENDERER_CORE_DOM_IGNORE_OPENS_DURING_UNLOAD_COUNT_INCREMENTER_H_ + +#include "base/macros.h" +#include "third_party/blink/renderer/core/dom/document.h" +#include "third_party/blink/renderer/platform/wtf/allocator.h" + +namespace blink { + +class IgnoreOpensDuringUnloadCountIncrementer { + STACK_ALLOCATED(); + + public: + explicit IgnoreOpensDuringUnloadCountIncrementer(Document* document) + : count_(document ? &document->ignore_opens_during_unload_count_ + : nullptr) { + if (!count_) + return; + ++(*count_); + } + + ~IgnoreOpensDuringUnloadCountIncrementer() { + if (!count_) + return; + --(*count_); + } + + private: + unsigned* count_; + DISALLOW_COPY_AND_ASSIGN(IgnoreOpensDuringUnloadCountIncrementer); +}; + +} // namespace blink + +#endif
diff --git a/third_party/blink/renderer/core/editing/finder/text_finder.cc b/third_party/blink/renderer/core/editing/finder/text_finder.cc index ae1fb5a..cbd2346 100644 --- a/third_party/blink/renderer/core/editing/finder/text_finder.cc +++ b/third_party/blink/renderer/core/editing/finder/text_finder.cc
@@ -51,6 +51,7 @@ #include "third_party/blink/renderer/core/editing/selection_template.h" #include "third_party/blink/renderer/core/editing/visible_selection.h" #include "third_party/blink/renderer/core/exported/web_view_impl.h" +#include "third_party/blink/renderer/core/frame/find_in_page.h" #include "third_party/blink/renderer/core/frame/local_frame_view.h" #include "third_party/blink/renderer/core/frame/settings.h" #include "third_party/blink/renderer/core/frame/web_local_frame_impl.h" @@ -597,7 +598,7 @@ total_match_count_ += count; // Update the UI with the latest findings. - OwnerFrame().ReportFindInPageMatchCount( + OwnerFrame().GetFindInPage()->ReportFindInPageMatchCount( identifier, total_match_count_, !frame_scoping_ || !total_match_count_); } @@ -605,9 +606,9 @@ int active_match_ordinal, int identifier) { // Update the UI with the latest selection rect. - OwnerFrame().ReportFindInPageSelection(identifier, active_match_ordinal, - selection_rect, - false /* final_update */); + OwnerFrame().GetFindInPage()->ReportFindInPageSelection( + identifier, active_match_ordinal, selection_rect, + false /* final_update */); // Update accessibility too, so if the user commits to this query // we can move accessibility focus to this result. ReportFindInPageResultToAccessibility(identifier);
diff --git a/third_party/blink/renderer/core/exported/web_plugin_container_impl.cc b/third_party/blink/renderer/core/exported/web_plugin_container_impl.cc index 384e8a913..adfa7f62 100644 --- a/third_party/blink/renderer/core/exported/web_plugin_container_impl.cc +++ b/third_party/blink/renderer/core/exported/web_plugin_container_impl.cc
@@ -310,8 +310,30 @@ void WebPluginContainerImpl::UsePluginAsFindHandler() { WebLocalFrameImpl* frame = WebLocalFrameImpl::FromFrame(element_->GetDocument().GetFrame()); - if (frame) - frame->GetFindInPage()->SetPluginFindHandler(this); + if (!frame) + return; + frame->GetFindInPage()->SetPluginFindHandler(this); +} + +void WebPluginContainerImpl::ReportFindInPageMatchCount(int identifier, + int total, + bool final_update) { + WebLocalFrameImpl* frame = + WebLocalFrameImpl::FromFrame(element_->GetDocument().GetFrame()); + if (!frame) + return; + frame->GetFindInPage()->ReportFindInPageMatchCount(identifier, total, + final_update); +} + +void WebPluginContainerImpl::ReportFindInPageSelection(int identifier, + int index) { + WebLocalFrameImpl* frame = + WebLocalFrameImpl::FromFrame(element_->GetDocument().GetFrame()); + if (!frame) + return; + frame->GetFindInPage()->ReportFindInPageSelection( + identifier, index, blink::WebRect(), false /* final_update */); } float WebPluginContainerImpl::DeviceScaleFactor() {
diff --git a/third_party/blink/renderer/core/exported/web_plugin_container_impl.h b/third_party/blink/renderer/core/exported/web_plugin_container_impl.h index d6a40e4..73929ab8 100644 --- a/third_party/blink/renderer/core/exported/web_plugin_container_impl.h +++ b/third_party/blink/renderer/core/exported/web_plugin_container_impl.h
@@ -148,6 +148,10 @@ void SetPlugin(WebPlugin*) override; void UsePluginAsFindHandler() override; + void ReportFindInPageMatchCount(int identifier, + int total, + bool final_update) override; + void ReportFindInPageSelection(int identifier, int index) override; float DeviceScaleFactor() override; float PageScaleFactor() override;
diff --git a/third_party/blink/renderer/core/frame/find_in_page.cc b/third_party/blink/renderer/core/frame/find_in_page.cc index e9c698a..68c7330 100644 --- a/third_party/blink/renderer/core/frame/find_in_page.cc +++ b/third_party/blink/renderer/core/frame/find_in_page.cc
@@ -321,12 +321,6 @@ binding_.Close(); } -void WebLocalFrameImpl::ReportFindInPageMatchCount(int request_id, - int count, - bool final_update) { - find_in_page_->ReportFindInPageMatchCount(request_id, count, final_update); -} - void FindInPage::ReportFindInPageMatchCount(int request_id, int count, bool final_update) { @@ -339,15 +333,6 @@ : mojom::blink::FindMatchUpdateType::kMoreUpdatesComing); } -void WebLocalFrameImpl::ReportFindInPageSelection( - int request_id, - int active_match_ordinal, - const blink::WebRect& selection_rect, - bool final_update) { - find_in_page_->ReportFindInPageSelection(request_id, active_match_ordinal, - selection_rect, final_update); -} - void FindInPage::ReportFindInPageSelection(int request_id, int active_match_ordinal, const blink::WebRect& selection_rect,
diff --git a/third_party/blink/renderer/core/frame/local_frame.cc b/third_party/blink/renderer/core/frame/local_frame.cc index ef81bd1f..2ba8a65 100644 --- a/third_party/blink/renderer/core/frame/local_frame.cc +++ b/third_party/blink/renderer/core/frame/local_frame.cc
@@ -50,6 +50,7 @@ #include "third_party/blink/renderer/core/dom/document_parser.h" #include "third_party/blink/renderer/core/dom/document_type.h" #include "third_party/blink/renderer/core/dom/events/event.h" +#include "third_party/blink/renderer/core/dom/ignore_opens_during_unload_count_incrementer.h" #include "third_party/blink/renderer/core/editing/editing_utilities.h" #include "third_party/blink/renderer/core/editing/editor.h" #include "third_party/blink/renderer/core/editing/frame_selection.h" @@ -309,6 +310,11 @@ // child frame during or after detaching children results in an attached // frame on a detached DOM tree, which is bad. SubframeLoadingDisabler disabler(*GetDocument()); + // https://html.spec.whatwg.org/C/browsing-the-web.html#unload-a-document + // The ignore-opens-during-unload counter of a Document must be incremented + // both when unloading itself and when unloading its descendants. + IgnoreOpensDuringUnloadCountIncrementer ignore_opens_during_unload( + GetDocument()); loader_.DispatchUnloadEvent(); DetachChildren();
diff --git a/third_party/blink/renderer/core/frame/web_local_frame_impl.cc b/third_party/blink/renderer/core/frame/web_local_frame_impl.cc index 4a3dbc8..3956d7a504 100644 --- a/third_party/blink/renderer/core/frame/web_local_frame_impl.cc +++ b/third_party/blink/renderer/core/frame/web_local_frame_impl.cc
@@ -139,6 +139,7 @@ #include "third_party/blink/renderer/core/clipboard/clipboard_utilities.h" #include "third_party/blink/renderer/core/dom/document.h" #include "third_party/blink/renderer/core/dom/icon_url.h" +#include "third_party/blink/renderer/core/dom/ignore_opens_during_unload_count_incrementer.h" #include "third_party/blink/renderer/core/dom/node.h" #include "third_party/blink/renderer/core/dom/node_traversal.h" #include "third_party/blink/renderer/core/dom/shadow_root.h" @@ -662,6 +663,11 @@ if (!GetFrame()) return; SubframeLoadingDisabler disabler(GetFrame()->GetDocument()); + // https://html.spec.whatwg.org/C/browsing-the-web.html#unload-a-document + // The ignore-opens-during-unload counter of a Document must be incremented + // when unloading itself. + IgnoreOpensDuringUnloadCountIncrementer ignore_opens_during_unload( + GetFrame()->GetDocument()); GetFrame()->Loader().DispatchUnloadEvent(); }
diff --git a/third_party/blink/renderer/core/frame/web_local_frame_impl.h b/third_party/blink/renderer/core/frame/web_local_frame_impl.h index d17f81f..0ade4f5 100644 --- a/third_party/blink/renderer/core/frame/web_local_frame_impl.h +++ b/third_party/blink/renderer/core/frame/web_local_frame_impl.h
@@ -312,13 +312,6 @@ bool* active_now = nullptr) override; void StopFindingForTesting(mojom::StopFindAction) override; void SetTickmarks(const WebVector<WebRect>&) override; - void ReportFindInPageMatchCount(int identifier, - int count, - bool final_update) override; - void ReportFindInPageSelection(int identifier, - int active_match_ordinal, - const WebRect& selection, - bool final_update) override; WebNode ContextMenuNode() const override; WebFrameWidget* FrameWidget() const override; void CopyImageAt(const WebPoint&) override;
diff --git a/third_party/blink/renderer/core/html/canvas/text_metrics.cc b/third_party/blink/renderer/core/html/canvas/text_metrics.cc index 1a821be2..8f090c98 100644 --- a/third_party/blink/renderer/core/html/canvas/text_metrics.cc +++ b/third_party/blink/renderer/core/html/canvas/text_metrics.cc
@@ -66,11 +66,7 @@ FloatRect bbox = font.BoundingBox(text_run); const FontMetrics& font_metrics = font_data->GetFontMetrics(); - Vector<CharacterRange> ranges = font.IndividualCharacterRanges(text_run); - advances_.resize(ranges.size()); - for (unsigned i = 0; i < ranges.size(); i++) { - advances_[i] = ranges[i].start; - } + advances_ = font.IndividualCharacterAdvances(text_run); // x direction width_ = bbox.Width();
diff --git a/third_party/blink/renderer/core/html/html_attribute_names.json5 b/third_party/blink/renderer/core/html/html_attribute_names.json5 index 4d10558..653ec60 100644 --- a/third_party/blink/renderer/core/html/html_attribute_names.json5 +++ b/third_party/blink/renderer/core/html/html_attribute_names.json5
@@ -109,6 +109,7 @@ "label", "lang", "language", + "lazyload", "leftmargin", "link", "list",
diff --git a/third_party/blink/renderer/core/html/html_frame_owner_element.cc b/third_party/blink/renderer/core/html/html_frame_owner_element.cc index 3bec9322..4b94aea2 100644 --- a/third_party/blink/renderer/core/html/html_frame_owner_element.cc +++ b/third_party/blink/renderer/core/html/html_frame_owner_element.cc
@@ -30,6 +30,7 @@ #include "third_party/blink/renderer/core/frame/local_frame_view.h" #include "third_party/blink/renderer/core/frame/remote_frame_view.h" #include "third_party/blink/renderer/core/html/lazy_load_frame_observer.h" +#include "third_party/blink/renderer/core/html_names.h" #include "third_party/blink/renderer/core/layout/layout_embedded_content.h" #include "third_party/blink/renderer/core/loader/document_loader.h" #include "third_party/blink/renderer/core/loader/frame_load_request.h" @@ -337,6 +338,16 @@ const KURL& url, const AtomicString& frame_name, bool replace_current_item) { + // Update the |should_lazy_load_children_| value according to the "lazyload" + // attribute immediately, so that it still gets respected even if the "src" + // attribute gets parsed in ParseAttribute() before the "lazyload" attribute + // does. + if (should_lazy_load_children_ && + EqualIgnoringASCIICase(FastGetAttribute(HTMLNames::lazyloadAttr), + "off")) { + should_lazy_load_children_ = false; + } + UpdateContainerPolicy(); if (ContentFrame()) { @@ -380,25 +391,27 @@ if ((RuntimeEnabledFeatures::LazyFrameLoadingEnabled() || RuntimeEnabledFeatures::LazyFrameVisibleLoadTimeMetricsEnabled()) && - should_lazy_load_children_ && + !lazy_load_frame_observer_ && // Only http:// or https:// URLs are eligible for lazy loading, excluding // URLs like invalid or empty URLs, "about:blank", local file URLs, etc. // that it doesn't make sense to lazily load. url.ProtocolIsInHTTPFamily() && - // Disallow lazy loading if javascript in the embedding document would be - // able to access the contents of the frame, since in those cases - // deferring the frame could break the page. Note that this check does not - // take any possible redirects of |url| into account. - !GetDocument().GetSecurityOrigin()->CanAccess( - SecurityOrigin::Create(url).get())) { - // Don't lazy load subresources inside a lazily loaded frame. This will make - // it possible for subresources in hidden frames to load that will - // never be visible, as well as make it so that deferred frames that have - // multiple layers of iframes inside them can load faster once they're near - // the viewport or visible. + (EqualIgnoringASCIICase(FastGetAttribute(HTMLNames::lazyloadAttr), + "on") || + (should_lazy_load_children_ && + // Disallow lazy loading by default if javascript in the embedding + // document would be able to access the contents of the frame, since in + // those cases deferring the frame could break the page. Note that this + // check does not take any possible redirects of |url| into account. + !GetDocument().GetSecurityOrigin()->CanAccess( + SecurityOrigin::Create(url).get())))) { + // By default, avoid deferring subresources inside a lazily loaded frame. + // This will make it possible for subresources in hidden frames to load that + // will never be visible, as well as make it so that deferred frames that + // have multiple layers of iframes inside them can load faster once they're + // near the viewport or visible. should_lazy_load_children_ = false; - DCHECK(!lazy_load_frame_observer_); lazy_load_frame_observer_ = new LazyLoadFrameObserver(*this); if (RuntimeEnabledFeatures::LazyFrameVisibleLoadTimeMetricsEnabled()) @@ -427,6 +440,21 @@ return should_lazy_load_children_; } +void HTMLFrameOwnerElement::ParseAttribute( + const AttributeModificationParams& params) { + if (params.name == HTMLNames::lazyloadAttr) { + if (EqualIgnoringASCIICase(params.new_value, "off")) { + should_lazy_load_children_ = false; + if (lazy_load_frame_observer_ && + lazy_load_frame_observer_->IsLazyLoadPending()) { + lazy_load_frame_observer_->LoadImmediately(); + } + } + } else { + HTMLElement::ParseAttribute(params); + } +} + void HTMLFrameOwnerElement::Trace(blink::Visitor* visitor) { visitor->Trace(content_frame_); visitor->Trace(embedded_content_view_);
diff --git a/third_party/blink/renderer/core/html/html_frame_owner_element.h b/third_party/blink/renderer/core/html/html_frame_owner_element.h index 5e62e5ad..f8fe9ff 100644 --- a/third_party/blink/renderer/core/html/html_frame_owner_element.h +++ b/third_party/blink/renderer/core/html/html_frame_owner_element.h
@@ -118,6 +118,8 @@ void CancelPendingLazyLoad(); + void ParseAttribute(const AttributeModificationParams&) override; + void Trace(blink::Visitor*) override; protected:
diff --git a/third_party/blink/renderer/core/html/lazy_load_frame_observer.cc b/third_party/blink/renderer/core/html/lazy_load_frame_observer.cc index 4c4f9b2a..f4baf2e 100644 --- a/third_party/blink/renderer/core/html/lazy_load_frame_observer.cc +++ b/third_party/blink/renderer/core/html/lazy_load_frame_observer.cc
@@ -77,13 +77,28 @@ } // namespace +struct LazyLoadFrameObserver::LazyLoadRequestInfo { + LazyLoadRequestInfo(const ResourceRequest& resource_request, + WebFrameLoadType frame_load_type) + : resource_request(resource_request), frame_load_type(frame_load_type) {} + + const ResourceRequest resource_request; + const WebFrameLoadType frame_load_type; +}; + LazyLoadFrameObserver::LazyLoadFrameObserver(HTMLFrameOwnerElement& element) : element_(&element) {} +LazyLoadFrameObserver::~LazyLoadFrameObserver() = default; + void LazyLoadFrameObserver::DeferLoadUntilNearViewport( const ResourceRequest& resource_request, WebFrameLoadType frame_load_type) { DCHECK(!lazy_load_intersection_observer_); + DCHECK(!lazy_load_request_info_); + lazy_load_request_info_ = + std::make_unique<LazyLoadRequestInfo>(resource_request, frame_load_type); + was_recorded_as_deferred_ = false; lazy_load_intersection_observer_ = IntersectionObserver::Create( @@ -92,13 +107,14 @@ kFixed)}, {std::numeric_limits<float>::min()}, &element_->GetDocument(), WTF::BindRepeating(&LazyLoadFrameObserver::LoadIfHiddenOrNearViewport, - WrapWeakPersistent(this), resource_request, - frame_load_type)); + WrapWeakPersistent(this))); lazy_load_intersection_observer_->observe(element_); } void LazyLoadFrameObserver::CancelPendingLazyLoad() { + lazy_load_request_info_.reset(); + if (!lazy_load_intersection_observer_) return; lazy_load_intersection_observer_->disconnect(); @@ -106,8 +122,6 @@ } void LazyLoadFrameObserver::LoadIfHiddenOrNearViewport( - const ResourceRequest& resource_request, - WebFrameLoadType frame_load_type, const HeapVector<Member<IntersectionObserverEntry>>& entries) { DCHECK(!entries.IsEmpty()); DCHECK_EQ(element_, entries.back()->target()); @@ -122,6 +136,13 @@ return; } + LoadImmediately(); +} + +void LazyLoadFrameObserver::LoadImmediately() { + DCHECK(IsLazyLoadPending()); + DCHECK(lazy_load_request_info_); + if (was_recorded_as_deferred_) { DCHECK(element_->GetDocument().GetFrame()); DCHECK(element_->GetDocument().GetFrame()->Client()); @@ -134,18 +155,23 @@ ->GetEffectiveConnectionType()); } + std::unique_ptr<LazyLoadRequestInfo> scoped_request_info = + std::move(lazy_load_request_info_); + // The content frame of the element should not have changed, since any // pending lazy load should have been already been cancelled in // DisconnectContentFrame() if the content frame changes. DCHECK(element_->ContentFrame()); - // Note that calling FrameLoader::Load() causes the - // |lazy_load_intersection_observer| to be disconnected. + // Note that calling FrameLoader::StartNavigation() causes the + // |lazy_load_intersection_observer_| to be disconnected. ToLocalFrame(element_->ContentFrame()) ->Loader() - .StartNavigation( - FrameLoadRequest(&element_->GetDocument(), resource_request), - frame_load_type); + .StartNavigation(FrameLoadRequest(&element_->GetDocument(), + scoped_request_info->resource_request), + scoped_request_info->frame_load_type); + + DCHECK(!IsLazyLoadPending()); } void LazyLoadFrameObserver::StartTrackingVisibilityMetrics() {
diff --git a/third_party/blink/renderer/core/html/lazy_load_frame_observer.h b/third_party/blink/renderer/core/html/lazy_load_frame_observer.h index 248e38f..5864e31a 100644 --- a/third_party/blink/renderer/core/html/lazy_load_frame_observer.h +++ b/third_party/blink/renderer/core/html/lazy_load_frame_observer.h
@@ -5,6 +5,8 @@ #ifndef THIRD_PARTY_BLINK_RENDERER_CORE_HTML_LAZY_LOAD_FRAME_OBSERVER_H_ #define THIRD_PARTY_BLINK_RENDERER_CORE_HTML_LAZY_LOAD_FRAME_OBSERVER_H_ +#include <memory> + #include "third_party/blink/public/web/web_frame_load_type.h" #include "third_party/blink/renderer/platform/heap/garbage_collected.h" #include "third_party/blink/renderer/platform/heap/heap_allocator.h" @@ -19,7 +21,8 @@ class ResourceRequest; class Visitor; -class LazyLoadFrameObserver : public GarbageCollected<LazyLoadFrameObserver> { +class LazyLoadFrameObserver + : public GarbageCollectedFinalized<LazyLoadFrameObserver> { public: // This enum is logged to histograms, so values should not be reordered or // reused, and it must match the corresponding enum @@ -40,6 +43,7 @@ }; explicit LazyLoadFrameObserver(HTMLFrameOwnerElement&); + ~LazyLoadFrameObserver(); void DeferLoadUntilNearViewport(const ResourceRequest&, WebFrameLoadType); bool IsLazyLoadPending() const { return lazy_load_intersection_observer_; } @@ -48,12 +52,14 @@ void StartTrackingVisibilityMetrics(); void RecordMetricsOnLoadFinished(); + void LoadImmediately(); + void Trace(blink::Visitor*); private: + struct LazyLoadRequestInfo; + void LoadIfHiddenOrNearViewport( - const ResourceRequest&, - WebFrameLoadType, const HeapVector<Member<IntersectionObserverEntry>>&); void RecordMetricsOnVisibilityChanged( @@ -68,6 +74,10 @@ // the viewport. Member<IntersectionObserver> lazy_load_intersection_observer_; + // Keeps track of the resource request and other info needed to load in the + // deferred frame. This is only non-null if there's a lazy load pending. + std::unique_ptr<LazyLoadRequestInfo> lazy_load_request_info_; + // Used to record visibility-related metrics related to lazy load. This is an // IntersectionObserver instead of just an ElementVisibilityObserver so that // hidden frames can be detected in order to avoid recording metrics for them.
diff --git a/third_party/blink/renderer/core/html/lazy_load_frame_observer_test.cc b/third_party/blink/renderer/core/html/lazy_load_frame_observer_test.cc index f987c93..33d2cd2 100644 --- a/third_party/blink/renderer/core/html/lazy_load_frame_observer_test.cc +++ b/third_party/blink/renderer/core/html/lazy_load_frame_observer_test.cc
@@ -8,10 +8,13 @@ #include <memory> #include <tuple> +#include "base/optional.h" #include "third_party/blink/public/platform/web_effective_connection_type.h" +#include "third_party/blink/renderer/core/dom/element.h" #include "third_party/blink/renderer/core/exported/web_view_impl.h" #include "third_party/blink/renderer/core/frame/local_frame_view.h" #include "third_party/blink/renderer/core/frame/settings.h" +#include "third_party/blink/renderer/core/html_names.h" #include "third_party/blink/renderer/core/paint/paint_layer_scrollable_area.h" #include "third_party/blink/renderer/core/testing/sim/sim_compositor.h" #include "third_party/blink/renderer/core/testing/sim/sim_request.h" @@ -719,6 +722,353 @@ "Blink.LazyLoad.CrossOriginFrames.VisibleAfterBeingDeferred", 0); } +TEST_P(LazyLoadFramesTest, CrossOriginFrameFarFromViewportWithLazyLoadAttrOff) { + SimRequest main_resource("https://example.com/", "text/html"); + SimRequest child_frame_resource("https://crossorigin.com/subframe.html", + "text/html"); + + LoadURL("https://example.com/"); + + main_resource.Complete(String::Format( + R"HTML( + <body onload='console.log("main body onload");'> + <div style='height: %dpx;'></div> + <iframe src='https://crossorigin.com/subframe.html' + style='width: 200px; height: 200px;' lazyload='off' + onload='console.log("child frame element onload");'></iframe> + </body>)HTML", + kViewportHeight + GetLoadingDistanceThreshold() + 100)); + + Compositor().BeginFrame(); + test::RunPendingTasks(); + + child_frame_resource.Complete(""); + + Compositor().BeginFrame(); + test::RunPendingTasks(); + + EXPECT_TRUE(ConsoleMessages().Contains("main body onload")); + EXPECT_TRUE(ConsoleMessages().Contains("child frame element onload")); + + ExpectVisibleLoadTimeHistogramSamplesIfApplicable(0, 0); + histogram_tester()->ExpectTotalCount( + "Blink.VisibleBeforeLoaded.LazyLoadEligibleFrames.BelowTheFold", 0); + + for (const auto& pair : kInitialDeferralActionHistogramNames) + histogram_tester()->ExpectTotalCount(pair.second, 0); + histogram_tester()->ExpectTotalCount( + "Blink.LazyLoad.CrossOriginFrames.LoadStartedAfterBeingDeferred", 0); + histogram_tester()->ExpectTotalCount( + "Blink.LazyLoad.CrossOriginFrames.VisibleAfterBeingDeferred", 0); +} + +TEST_P(LazyLoadFramesTest, + LoadSameOriginFrameFarFromViewportWithLazyLoadAttributeOn) { + SimRequest main_resource("https://example.com/", "text/html"); + base::Optional<SimRequest> child_frame_resource; + + if (!RuntimeEnabledFeatures::LazyFrameLoadingEnabled()) { + // This SimRequest needs to be created now if the frame won't actually be + // lazily loaded. Otherwise, it'll be defined later to ensure that the + // subframe resource isn't requested until the page is scrolled down. + child_frame_resource.emplace("https://example.com/subframe.html", + "text/html"); + } + + LoadURL("https://example.com/"); + + main_resource.Complete(String::Format( + R"HTML( + <body onload='console.log("main body onload");'> + <div style='height: %dpx;'></div> + <iframe src='https://example.com/subframe.html' + style='width: 400px; height: 400px;' lazyload='on' + onload='console.log("child frame element onload");'></iframe> + </body>)HTML", + kViewportHeight + GetLoadingDistanceThreshold() + 100)); + + Compositor().BeginFrame(); + test::RunPendingTasks(); + + // If the child frame is being lazy loaded, then the body's load event + // should have already fired. + EXPECT_EQ(RuntimeEnabledFeatures::LazyFrameLoadingEnabled(), + ConsoleMessages().Contains("main body onload")); + EXPECT_FALSE(ConsoleMessages().Contains("child frame element onload")); + + ExpectVisibleLoadTimeHistogramSamplesIfApplicable(0, 0); + + ExpectInitialDeferralActionHistogramSamplesIfApplicable( + LazyLoadFrameObserver::FrameInitialDeferralAction::kDeferred, 1); + histogram_tester()->ExpectTotalCount( + "Blink.LazyLoad.CrossOriginFrames.LoadStartedAfterBeingDeferred", 0); + histogram_tester()->ExpectTotalCount( + "Blink.LazyLoad.CrossOriginFrames.VisibleAfterBeingDeferred", 0); + + if (!child_frame_resource) { + child_frame_resource.emplace("https://example.com/subframe.html", + "text/html"); + } + + if (RuntimeEnabledFeatures::LazyFrameLoadingEnabled()) { + // If LazyFrameLoading is enabled, then scroll down near the child frame to + // cause the child frame to start loading. + GetDocument().View()->LayoutViewport()->SetScrollOffset( + ScrollOffset(0, 150), kProgrammaticScroll); + + Compositor().BeginFrame(); + test::RunPendingTasks(); + } + + EXPECT_FALSE(ConsoleMessages().Contains("child frame element onload")); + ExpectVisibleLoadTimeHistogramSamplesIfApplicable(0, 0); + + ExpectInitialDeferralActionHistogramSamplesIfApplicable( + LazyLoadFrameObserver::FrameInitialDeferralAction::kDeferred, 1); + ExpectLoadStartedAfterDeferredSamplesIfApplicable(1); + histogram_tester()->ExpectTotalCount( + "Blink.LazyLoad.CrossOriginFrames.VisibleAfterBeingDeferred", 0); + + child_frame_resource->Complete(""); + + Compositor().BeginFrame(); + test::RunPendingTasks(); + + EXPECT_TRUE(ConsoleMessages().Contains("main body onload")); + EXPECT_TRUE(ConsoleMessages().Contains("child frame element onload")); + ExpectVisibleLoadTimeHistogramSamplesIfApplicable(0, 0); + + // Scroll down so that the child frame is visible. + GetDocument().View()->LayoutViewport()->SetScrollOffset( + ScrollOffset(0, GetLoadingDistanceThreshold() + 150), + kProgrammaticScroll); + + Compositor().BeginFrame(); + test::RunPendingTasks(); + + EXPECT_TRUE(ConsoleMessages().Contains("main body onload")); + EXPECT_TRUE(ConsoleMessages().Contains("child frame element onload")); + ExpectVisibleLoadTimeHistogramSamplesIfApplicable(0, 1); + + histogram_tester()->ExpectTotalCount( + "Blink.VisibleBeforeLoaded.LazyLoadEligibleFrames.BelowTheFold", 0); + + ExpectInitialDeferralActionHistogramSamplesIfApplicable( + LazyLoadFrameObserver::FrameInitialDeferralAction::kDeferred, 1); + ExpectLoadStartedAfterDeferredSamplesIfApplicable(1); + ExpectVisibleAfterDeferredSamplesIfApplicable(1); +} + +TEST_P(LazyLoadFramesTest, + LoadCrossOriginFrameFarFromViewportThenSetLazyLoadAttributeOff) { + SimRequest main_resource("https://example.com/", "text/html"); + base::Optional<SimRequest> child_frame_resource; + + if (!RuntimeEnabledFeatures::LazyFrameLoadingEnabled()) { + // This SimRequest needs to be created now if the frame won't actually be + // lazily loaded. Otherwise, it'll be defined later to ensure that the + // subframe resource isn't requested until the page is scrolled down. + child_frame_resource.emplace("https://crossorigin.com/subframe.html", + "text/html"); + } + + LoadURL("https://example.com/"); + + main_resource.Complete(String::Format( + R"HTML( + <body onload='console.log("main body onload");'> + <div style='height: %dpx;'></div> + <iframe id='child_frame' src='https://crossorigin.com/subframe.html' + style='width: 400px; height: 400px;' + onload='console.log("child frame element onload");'></iframe> + </body>)HTML", + kViewportHeight + GetLoadingDistanceThreshold() + 100)); + + Compositor().BeginFrame(); + test::RunPendingTasks(); + + // If the child frame is being lazy loaded, then the body's load event + // should have already fired. + EXPECT_EQ(RuntimeEnabledFeatures::LazyFrameLoadingEnabled(), + ConsoleMessages().Contains("main body onload")); + EXPECT_FALSE(ConsoleMessages().Contains("child frame element onload")); + + if (!child_frame_resource) { + child_frame_resource.emplace("https://crossorigin.com/subframe.html", + "text/html"); + } + + Element* child_frame_element = GetDocument().getElementById("child_frame"); + ASSERT_TRUE(child_frame_element); + child_frame_element->setAttribute(HTMLNames::lazyloadAttr, "off"); + + ExpectInitialDeferralActionHistogramSamplesIfApplicable( + LazyLoadFrameObserver::FrameInitialDeferralAction::kDeferred, 1); + ExpectLoadStartedAfterDeferredSamplesIfApplicable(1); + histogram_tester()->ExpectTotalCount( + "Blink.LazyLoad.CrossOriginFrames.VisibleAfterBeingDeferred", 0); + + child_frame_resource->Complete(""); + + Compositor().BeginFrame(); + test::RunPendingTasks(); + + EXPECT_TRUE(ConsoleMessages().Contains("main body onload")); + EXPECT_TRUE(ConsoleMessages().Contains("child frame element onload")); + + ExpectVisibleLoadTimeHistogramSamplesIfApplicable(0, 0); + + histogram_tester()->ExpectTotalCount( + "Blink.VisibleBeforeLoaded.LazyLoadEligibleFrames.BelowTheFold", 0); + + ExpectInitialDeferralActionHistogramSamplesIfApplicable( + LazyLoadFrameObserver::FrameInitialDeferralAction::kDeferred, 1); + ExpectLoadStartedAfterDeferredSamplesIfApplicable(1); + histogram_tester()->ExpectTotalCount( + "Blink.LazyLoad.CrossOriginFrames.VisibleAfterBeingDeferred", 0); +} + +TEST_P(LazyLoadFramesTest, + NestedFrameWithLazyLoadAttributeOnInFrameWithNoLazyLoadAttribute) { + std::unique_ptr<SimRequest> child_frame_resource = + LoadPageWithCrossOriginFrameFarFromViewport(); + + if (RuntimeEnabledFeatures::LazyFrameLoadingEnabled()) { + // If LazyFrameLoading is enabled, then scroll down near the child frame to + // cause the child frame to start loading. + GetDocument().View()->LayoutViewport()->SetScrollOffset( + ScrollOffset(0, 150), kProgrammaticScroll); + + Compositor().BeginFrame(); + test::RunPendingTasks(); + } + + // There's another nested cross origin iframe inside the first child frame, + // even further down such that it's not near the viewport. If LazyLoad is + // enabled, it should be deferred even though it's nested inside a frame that + // was previously deferred, because it has the attribute lazyload=on. + base::Optional<SimRequest> nested_frame_resource; + if (!RuntimeEnabledFeatures::LazyFrameLoadingEnabled()) + nested_frame_resource.emplace("https://test.com/", "text/html"); + + child_frame_resource->Complete( + String::Format("<div style='height: %dpx;'></div>" + "<iframe src='https://test.com/' lazyload='on'" + " style='width: 200px; height: 200px;'>" + "</iframe>", + kViewportHeight + GetLoadingDistanceThreshold() + 100)); + + Compositor().BeginFrame(); + test::RunPendingTasks(); + + if (!RuntimeEnabledFeatures::LazyFrameLoadingEnabled()) { + nested_frame_resource->Complete(""); + + Compositor().BeginFrame(); + test::RunPendingTasks(); + } + + EXPECT_TRUE(ConsoleMessages().Contains("main body onload")); + EXPECT_TRUE(ConsoleMessages().Contains("child frame element onload")); +} + +TEST_P(LazyLoadFramesTest, + NestedFrameWithLazyLoadAttributeOnInFrameWithLazyLoadAttributeOff) { + SimRequest main_resource("https://example.com/", "text/html"); + SimRequest child_frame_resource("https://crossorigin.com/subframe.html", + "text/html"); + + LoadURL("https://example.com/"); + + main_resource.Complete(String::Format( + R"HTML( + <body onload='console.log("main body onload");'> + <div style='height: %dpx;'></div> + <iframe src='https://crossorigin.com/subframe.html' + style='width: 200px; height: 200px;' lazyload='off' + onload='console.log("child frame element onload");'></iframe> + </body>)HTML", + kViewportHeight + GetLoadingDistanceThreshold() + 100)); + + Compositor().BeginFrame(); + test::RunPendingTasks(); + + // There's another nested cross origin iframe inside the first child frame, + // even further down such that it's not near the viewport. If LazyLoad is + // enabled, it should be deferred because it has the attribute lazyload=on, + // even though it's nested inside a frame that has the attribute lazyload=off. + base::Optional<SimRequest> nested_frame_resource; + if (!RuntimeEnabledFeatures::LazyFrameLoadingEnabled()) + nested_frame_resource.emplace("https://test.com/", "text/html"); + + child_frame_resource.Complete( + String::Format("<div style='height: %dpx;'></div>" + "<iframe src='https://test.com/' lazyload='on'" + " style='width: 200px; height: 200px;'>" + "</iframe>", + kViewportHeight + GetLoadingDistanceThreshold() + 100)); + + Compositor().BeginFrame(); + test::RunPendingTasks(); + + if (!RuntimeEnabledFeatures::LazyFrameLoadingEnabled()) { + nested_frame_resource->Complete(""); + + Compositor().BeginFrame(); + test::RunPendingTasks(); + } + + EXPECT_TRUE(ConsoleMessages().Contains("main body onload")); + EXPECT_TRUE(ConsoleMessages().Contains("child frame element onload")); +} + +TEST_P(LazyLoadFramesTest, + NestedFrameWithLazyLoadAttributeOffInFrameWithLazyLoadAttributeOff) { + SimRequest main_resource("https://example.com/", "text/html"); + SimRequest child_frame_resource("https://crossorigin.com/subframe.html", + "text/html"); + + LoadURL("https://example.com/"); + + main_resource.Complete(String::Format( + R"HTML( + <body onload='console.log("main body onload");'> + <div style='height: %dpx;'></div> + <iframe src='https://crossorigin.com/subframe.html' + style='width: 200px; height: 200px;' lazyload='off' + onload='console.log("child frame element onload");'></iframe> + </body>)HTML", + kViewportHeight + GetLoadingDistanceThreshold() + 100)); + + Compositor().BeginFrame(); + test::RunPendingTasks(); + + // There's another nested cross origin iframe inside the first child frame, + // even further down such that it's not near the viewport. Since it has the + // attribute lazyload=off, it shouldn't be deferred. Note that this also + // matches the default behavior that would happen if the lazyload attribute + // was omitted on the nested iframe entirely. + SimRequest nested_frame_resource("https://test.com/", "text/html"); + + child_frame_resource.Complete( + String::Format("<div style='height: %dpx;'></div>" + "<iframe src='https://test.com/' lazyload='off'" + " style='width: 200px; height: 200px;'>" + "</iframe>", + kViewportHeight + GetLoadingDistanceThreshold() + 100)); + + Compositor().BeginFrame(); + test::RunPendingTasks(); + + nested_frame_resource.Complete(""); + + Compositor().BeginFrame(); + test::RunPendingTasks(); + + EXPECT_TRUE(ConsoleMessages().Contains("main body onload")); + EXPECT_TRUE(ConsoleMessages().Contains("child frame element onload")); +} + INSTANTIATE_TEST_CASE_P( LazyFrameLoading, LazyLoadFramesTest,
diff --git a/third_party/blink/renderer/core/layout/grid_track_sizing_algorithm.cc b/third_party/blink/renderer/core/layout/grid_track_sizing_algorithm.cc index 2f11e326..ebb1cd0 100644 --- a/third_party/blink/renderer/core/layout/grid_track_sizing_algorithm.cc +++ b/third_party/blink/renderer/core/layout/grid_track_sizing_algorithm.cc
@@ -227,10 +227,12 @@ const Vector<GridTrack>& all_tracks = Tracks(direction); const GridSpan& span = grid_.GridItemSpan(child, direction); LayoutUnit grid_area_breadth; - for (const auto& track_position : span) { + for (const auto& track_position : span) grid_area_breadth += all_tracks[track_position].BaseSize(); - if (add_content_alignment_offset) - grid_area_breadth += layout_grid_->GridItemOffset(direction); + + if (add_content_alignment_offset) { + grid_area_breadth += + (span.IntegerSpan() - 1) * layout_grid_->GridItemOffset(direction); } grid_area_breadth +=
diff --git a/third_party/blink/renderer/core/layout/ng/inline/ng_offset_mapping_test.cc b/third_party/blink/renderer/core/layout/ng/inline/ng_offset_mapping_test.cc index 1036a00..6c865cc 100644 --- a/third_party/blink/renderer/core/layout/ng/inline/ng_offset_mapping_test.cc +++ b/third_party/blink/renderer/core/layout/ng/inline/ng_offset_mapping_test.cc
@@ -88,16 +88,6 @@ FontCachePurgePreventer purge_preventer_; }; -// TODO(layout-dev): Remove this unused parameterization. -class ParameterizedNGOffsetMappingTest - : public testing::WithParamInterface<bool>, - public NGOffsetMappingTest { - public: - ParameterizedNGOffsetMappingTest() {} -}; - -INSTANTIATE_TEST_CASE_P(All, ParameterizedNGOffsetMappingTest, testing::Bool()); - #define TEST_UNIT(unit, type, owner, dom_start, dom_end, text_content_start, \ text_content_end) \ EXPECT_EQ(type, unit.GetType()); \ @@ -112,14 +102,14 @@ EXPECT_EQ(start, ranges.at(owner).first); \ EXPECT_EQ(end, ranges.at(owner).second) -TEST_P(ParameterizedNGOffsetMappingTest, StoredResult) { +TEST_F(NGOffsetMappingTest, StoredResult) { SetupHtml("t", "<div id=t>foo</div>"); EXPECT_FALSE(IsOffsetMappingStored()); GetOffsetMapping(); EXPECT_TRUE(IsOffsetMappingStored()); } -TEST_P(ParameterizedNGOffsetMappingTest, NGInlineFormattingContextOf) { +TEST_F(NGOffsetMappingTest, NGInlineFormattingContextOf) { SetBodyInnerHTML( "<div id=container>" " foo" @@ -156,7 +146,7 @@ NGInlineFormattingContextOf(Position(blah, 0))); } -TEST_P(ParameterizedNGOffsetMappingTest, OneTextNode) { +TEST_F(NGOffsetMappingTest, OneTextNode) { SetupHtml("t", "<div id=t>foo</div>"); const Node* foo_node = layout_object_->GetNode(); const NGOffsetMapping& result = GetOffsetMapping(); @@ -219,7 +209,7 @@ EXPECT_TRUE(IsAfterNonCollapsedContent(Position(foo_node, 3))); } -TEST_P(ParameterizedNGOffsetMappingTest, TwoTextNodes) { +TEST_F(NGOffsetMappingTest, TwoTextNodes) { SetupHtml("t", "<div id=t>foo<span id=s>bar</span></div>"); const LayoutText* foo = ToLayoutText(layout_object_); const LayoutText* bar = GetLayoutTextUnder("s"); @@ -287,7 +277,7 @@ EXPECT_TRUE(IsAfterNonCollapsedContent(Position(bar_node, 3))); } -TEST_P(ParameterizedNGOffsetMappingTest, BRBetweenTextNodes) { +TEST_F(NGOffsetMappingTest, BRBetweenTextNodes) { SetupHtml("t", u"<div id=t>foo<br>bar</div>"); const LayoutText* foo = ToLayoutText(layout_object_); const LayoutText* br = ToLayoutText(foo->NextSibling()); @@ -342,7 +332,7 @@ EXPECT_EQ(Position(bar_node, 0), GetLastPosition(4)); } -TEST_P(ParameterizedNGOffsetMappingTest, OneTextNodeWithCollapsedSpace) { +TEST_F(NGOffsetMappingTest, OneTextNodeWithCollapsedSpace) { SetupHtml("t", "<div id=t>foo bar</div>"); const Node* node = layout_object_->GetNode(); const NGOffsetMapping& result = GetOffsetMapping(); @@ -415,7 +405,7 @@ EXPECT_TRUE(IsAfterNonCollapsedContent(Position(node, 8))); } -TEST_P(ParameterizedNGOffsetMappingTest, FullyCollapsedWhiteSpaceNode) { +TEST_F(NGOffsetMappingTest, FullyCollapsedWhiteSpaceNode) { SetupHtml("t", "<div id=t>" "<span id=s1>foo </span>" @@ -481,7 +471,7 @@ StartOfNextNonCollapsedContent(Position(space_node, 0u)).IsNull()); } -TEST_P(ParameterizedNGOffsetMappingTest, ReplacedElement) { +TEST_F(NGOffsetMappingTest, ReplacedElement) { SetupHtml("t", "<div id=t>foo <img> bar</div>"); const LayoutText* foo = ToLayoutText(layout_object_); const LayoutObject* img = foo->NextSibling(); @@ -538,7 +528,7 @@ EXPECT_EQ(Position(bar_node, 0), GetLastPosition(5)); } -TEST_P(ParameterizedNGOffsetMappingTest, FirstLetter) { +TEST_F(NGOffsetMappingTest, FirstLetter) { SetupHtml("t", "<style>div:first-letter{color:red}</style>" "<div id=t>foo</div>"); @@ -568,7 +558,7 @@ EXPECT_EQ(Position(foo_node, 1), GetLastPosition(1)); } -TEST_P(ParameterizedNGOffsetMappingTest, FirstLetterWithLeadingSpace) { +TEST_F(NGOffsetMappingTest, FirstLetterWithLeadingSpace) { SetupHtml("t", "<style>div:first-letter{color:red}</style>" "<div id=t> foo</div>"); @@ -604,7 +594,7 @@ EXPECT_EQ(Position(foo_node, 2), GetLastPosition(0)); } -TEST_P(ParameterizedNGOffsetMappingTest, FirstLetterWithoutRemainingText) { +TEST_F(NGOffsetMappingTest, FirstLetterWithoutRemainingText) { SetupHtml("t", "<style>div:first-letter{color:red}</style>" "<div id=t> f</div>"); @@ -635,7 +625,7 @@ EXPECT_EQ(Position(text_node, 2), GetLastPosition(0)); } -TEST_P(ParameterizedNGOffsetMappingTest, FirstLetterInDifferentBlock) { +TEST_F(NGOffsetMappingTest, FirstLetterInDifferentBlock) { SetupHtml("t", "<style>:first-letter{float:right}</style><div id=t>foo</div>"); Element* div = GetDocument().getElementById("t"); @@ -699,7 +689,7 @@ EXPECT_EQ(Position(text_node, 1), remaining_text_result.GetLastPosition(1)); } -TEST_P(ParameterizedNGOffsetMappingTest, WhiteSpaceTextNodeWithoutLayoutText) { +TEST_F(NGOffsetMappingTest, WhiteSpaceTextNodeWithoutLayoutText) { SetupHtml("t", "<div id=t> <span>foo</span></div>"); Element* div = GetDocument().getElementById("t"); const Node* text_node = div->firstChild(); @@ -708,8 +698,7 @@ EXPECT_TRUE(StartOfNextNonCollapsedContent(Position(text_node, 0u)).IsNull()); } -TEST_P(ParameterizedNGOffsetMappingTest, - OneContainerWithLeadingAndTrailingSpaces) { +TEST_F(NGOffsetMappingTest, OneContainerWithLeadingAndTrailingSpaces) { SetupHtml("t", "<div id=t><span id=s> foo </span></div>"); const Node* span = GetElementById("s"); const Node* text = span->firstChild(); @@ -733,7 +722,7 @@ EXPECT_EQ(3u, *GetTextContentOffset(Position::AfterNode(*span))); } -TEST_P(ParameterizedNGOffsetMappingTest, ContainerWithGeneratedContent) { +TEST_F(NGOffsetMappingTest, ContainerWithGeneratedContent) { SetupHtml("t", "<style>#s::before{content:'bar'} #s::after{content:'baz'}</style>" "<div id=t><span id=s>foo</span></div>"); @@ -755,7 +744,7 @@ EXPECT_EQ(6u, *GetTextContentOffset(Position::AfterNode(*span))); } -TEST_P(ParameterizedNGOffsetMappingTest, Table) { +TEST_F(NGOffsetMappingTest, Table) { SetupHtml("t", "<table><tr><td id=t> foo </td></tr></table>"); const Node* foo_node = layout_object_->GetNode(); @@ -775,7 +764,7 @@ TEST_RANGE(result.GetRanges(), foo_node, 0u, 3u); } -TEST_P(ParameterizedNGOffsetMappingTest, GetMappingForInlineBlock) { +TEST_F(NGOffsetMappingTest, GetMappingForInlineBlock) { SetupHtml("t", "<div id=t>foo" "<span style='display: inline-block' id=span> bar </span>" @@ -803,7 +792,7 @@ EXPECT_NE(span_mapping, span_after_mapping); } -TEST_P(ParameterizedNGOffsetMappingTest, NoWrapSpaceAndCollapsibleSpace) { +TEST_F(NGOffsetMappingTest, NoWrapSpaceAndCollapsibleSpace) { SetupHtml("t", "<div id=t>" "<span style='white-space: nowrap' id=span>foo </span>" @@ -828,7 +817,7 @@ 4u, 5u, 8u); } -TEST_P(ParameterizedNGOffsetMappingTest, BiDiAroundForcedBreakInPreLine) { +TEST_F(NGOffsetMappingTest, BiDiAroundForcedBreakInPreLine) { SetupHtml("t", "<div id=t style='white-space: pre-line'>" "<bdo dir=rtl id=bdo>foo\nbar</bdo></div>"); @@ -852,7 +841,7 @@ TEST_RANGE(mapping.GetRanges(), text, 0u, 3u); } -TEST_P(ParameterizedNGOffsetMappingTest, BiDiAroundForcedBreakInPreWrap) { +TEST_F(NGOffsetMappingTest, BiDiAroundForcedBreakInPreWrap) { SetupHtml("t", "<div id=t style='white-space: pre-wrap'>" "<bdo dir=rtl id=bdo>foo\nbar</bdo></div>"); @@ -876,7 +865,7 @@ TEST_RANGE(mapping.GetRanges(), text, 0u, 3u); } -TEST_P(ParameterizedNGOffsetMappingTest, BiDiAroundForcedBreakInPre) { +TEST_F(NGOffsetMappingTest, BiDiAroundForcedBreakInPre) { SetupHtml("t", "<div id=t style='white-space: pre'>" "<bdo dir=rtl id=bdo>foo\nbar</bdo></div>"); @@ -900,7 +889,7 @@ TEST_RANGE(mapping.GetRanges(), text, 0u, 3u); } -TEST_P(ParameterizedNGOffsetMappingTest, SoftHyphen) { +TEST_F(NGOffsetMappingTest, SoftHyphen) { LoadAhem(); SetupHtml( "t", @@ -916,7 +905,7 @@ TEST_RANGE(mapping.GetRanges(), text, 0u, 1u); } -TEST_P(ParameterizedNGOffsetMappingTest, TextOverflowEllipsis) { +TEST_F(NGOffsetMappingTest, TextOverflowEllipsis) { LoadAhem(); SetupHtml("t", "<div id=t style='font: 10px/10px Ahem; width: 30px; overflow: "
diff --git a/third_party/blink/renderer/core/loader/frame_loader.cc b/third_party/blink/renderer/core/loader/frame_loader.cc index a0495b86..d68247b2 100644 --- a/third_party/blink/renderer/core/loader/frame_loader.cc +++ b/third_party/blink/renderer/core/loader/frame_loader.cc
@@ -49,6 +49,7 @@ #include "third_party/blink/renderer/bindings/core/v8/serialization/serialized_script_value.h" #include "third_party/blink/renderer/core/dom/document.h" #include "third_party/blink/renderer/core/dom/element.h" +#include "third_party/blink/renderer/core/dom/ignore_opens_during_unload_count_incrementer.h" #include "third_party/blink/renderer/core/events/page_transition_event.h" #include "third_party/blink/renderer/core/frame/content_settings_client.h" #include "third_party/blink/renderer/core/frame/csp/content_security_policy.h" @@ -382,6 +383,10 @@ // child frame during or after detaching children results in an attached // frame on a detached DOM tree, which is bad. SubframeLoadingDisabler disabler(document); + // https://html.spec.whatwg.org/C/browsing-the-web.html#unload-a-document + // The ignore-opens-during-unload counter of the parent Document must be + // incremented when unloading its descendants. + IgnoreOpensDuringUnloadCountIncrementer ignore_opens_during_unload(document); frame_->DetachChildren(); // detachChildren() potentially detaches or navigates this frame. The load @@ -1163,6 +1168,11 @@ // child frame during or after detaching children results in an attached frame // on a detached DOM tree, which is bad. SubframeLoadingDisabler disabler(frame_->GetDocument()); + // https://html.spec.whatwg.org/C/browsing-the-web.html#unload-a-document + // The ignore-opens-during-unload counter of a Document must be incremented + // both when unloading itself and when unloading its descendants. + IgnoreOpensDuringUnloadCountIncrementer ignore_opens_during_unload( + frame_->GetDocument()); if (document_loader_) { Client()->DispatchWillCommitProvisionalLoad(); DispatchUnloadEvent(); @@ -1445,37 +1455,52 @@ if (!page || !page->GetChromeClient().CanOpenBeforeUnloadConfirmPanel()) return true; - // Store all references to each subframe in advance since beforeunload's event - // handler may modify frame - HeapVector<Member<LocalFrame>> target_frames; - target_frames.push_back(frame_); + HeapVector<Member<LocalFrame>> descendant_frames; for (Frame* child = frame_->Tree().FirstChild(); child; child = child->Tree().TraverseNext(frame_)) { // FIXME: There is not yet any way to dispatch events to out-of-process // frames. if (child->IsLocalFrame()) - target_frames.push_back(ToLocalFrame(child)); + descendant_frames.push_back(ToLocalFrame(child)); } - bool should_close = false; { NavigationDisablerForBeforeUnload navigation_disabler; - size_t i; - bool did_allow_navigation = false; - for (i = 0; i < target_frames.size(); i++) { - if (!target_frames[i]->Tree().IsDescendantOf(frame_)) - continue; - if (!target_frames[i]->GetDocument()->DispatchBeforeUnloadEvent( - page->GetChromeClient(), is_reload, did_allow_navigation)) - break; - } - if (i == target_frames.size()) - should_close = true; + // https://html.spec.whatwg.org/C/browsing-the-web.html#prompt-to-unload-a-document + + // First deal with this frame. + IgnoreOpensDuringUnloadCountIncrementer ignore_opens_during_unload( + frame_->GetDocument()); + if (!frame_->GetDocument()->DispatchBeforeUnloadEvent( + page->GetChromeClient(), is_reload, did_allow_navigation)) + return false; + + // Then deal with descendent frames. + for (Member<LocalFrame>& descendant_frame : descendant_frames) { + if (!descendant_frame->Tree().IsDescendantOf(frame_)) + continue; + + // There is some confusion in the spec around what counters should be + // incremented for a descendant browsing context: + // https://github.com/whatwg/html/issues/3899 + // + // Here for implementation ease, we use the current spec behavior, which + // is to increment only the counter of the Document on which this is + // called, and that of the Document we are firing the beforeunload event + // on -- not any intermediate Documents that may be the parent of the + // frame being unloaded but is not root Document. + IgnoreOpensDuringUnloadCountIncrementer + ignore_opens_during_unload_descendant( + descendant_frame->GetDocument()); + if (!descendant_frame->GetDocument()->DispatchBeforeUnloadEvent( + page->GetChromeClient(), is_reload, did_allow_navigation)) + return false; + } } - return should_close; + return true; } void FrameLoader::ClientDroppedNavigation() {
diff --git a/third_party/blink/renderer/devtools/front_end/audits2_worker/lighthouse/lighthouse-background.js b/third_party/blink/renderer/devtools/front_end/audits2_worker/lighthouse/lighthouse-background.js index 8f2d45c..ff346f1 100644 --- a/third_party/blink/renderer/devtools/front_end/audits2_worker/lighthouse/lighthouse-background.js +++ b/third_party/blink/renderer/devtools/front_end/audits2_worker/lighthouse/lighthouse-background.js
@@ -1,4 +1,4 @@ -// lighthouse, browserified. 3.0.3 (d1cae24fda4182406e02d3f4df6309d48878fc50) +// lighthouse, browserified. 3.0.3.1 (bf652a9fd8c04f445d820203960a905d6461277b) require=function(){function r(e,n,t){function o(i,f){if(!n[i]){if(!e[i]){var c="function"==typeof require&&require;if(!f&&c)return c(i,!0);if(u)return u(i,!0);var a=new Error("Cannot find module '"+i+"'");throw a.code="MODULE_NOT_FOUND",a;}var p=n[i]={exports:{}};e[i][0].call(p.exports,function(r){var n=e[i][1][r];return o(n||r);},p,p.exports,r,e,n,t);}return n[i].exports;}for(var u="function"==typeof require&&require,i=0;i<t.length;i++)o(t[i]);return o;}return r;}()({"../audits/accessibility/accesskeys":[function(require,module,exports){ @@ -23694,8 +23694,12 @@ const BASE_RESPONSE_LATENCY=16; + const SCHEDULABLE_TASK_TITLE='TaskQueueManager::ProcessTaskFromWorkQueue'; -const SCHEDULABLE_TASK_TITLE_ALT='ThreadControllerImpl::DoWork'; + +const SCHEDULABLE_TASK_TITLE_ALT1='ThreadControllerImpl::DoWork'; + +const SCHEDULABLE_TASK_TITLE_ALT2='ThreadControllerImpl::RunTask'; const LHError=require('../errors'); class TraceProcessor{ @@ -23908,7 +23912,9 @@ static isScheduleableTask(evt){ -return evt.name===SCHEDULABLE_TASK_TITLE||evt.name===SCHEDULABLE_TASK_TITLE_ALT; +return evt.name===SCHEDULABLE_TASK_TITLE|| +evt.name===SCHEDULABLE_TASK_TITLE_ALT1|| +evt.name===SCHEDULABLE_TASK_TITLE_ALT2; }}
diff --git a/third_party/blink/renderer/devtools/front_end/perf_ui/FlameChart.js b/third_party/blink/renderer/devtools/front_end/perf_ui/FlameChart.js index d45866b..5e3f5ee 100644 --- a/third_party/blink/renderer/devtools/front_end/perf_ui/FlameChart.js +++ b/third_party/blink/renderer/devtools/front_end/perf_ui/FlameChart.js
@@ -940,6 +940,8 @@ // 2 triangles x 3 points x 4 color values (RGBA) = 24. const colorArray = new Uint8Array(entryTotalTimes.length * 24); let vertex = 0; + /** @type {!Map<string, !Array<number>>} */ + const parsedColorCache = new Map(); for (let i = 0; i < entryTotalTimes.length; ++i) { const level = entryLevels[i]; if (!this._visibleLevels[level]) @@ -947,11 +949,19 @@ const color = this._dataProvider.entryColor(i); if (!color) continue; - const rgba = Common.Color.parse(color).canonicalRGBA(); - rgba[3] = Math.round(rgba[3] * 255); + let rgba = parsedColorCache.get(color); + if (!rgba) { + rgba = Common.Color.parse(color).canonicalRGBA(); + rgba[3] = Math.round(rgba[3] * 255); + parsedColorCache.set(color, rgba); + } const cpos = vertex * 4; - for (let j = 0; j < 6; ++j) // All of the bar vertices have the same color. - colorArray.set(rgba, cpos + j * 4); + for (let j = 0; j < 6; ++j) { // All of the bar vertices have the same color. + colorArray[cpos + j * 4 + 0] = rgba[0]; + colorArray[cpos + j * 4 + 1] = rgba[1]; + colorArray[cpos + j * 4 + 2] = rgba[2]; + colorArray[cpos + j * 4 + 3] = rgba[3]; + } const vpos = vertex * 2; const x0 = entryStartTimes[i] - this._minimumBoundary; @@ -989,40 +999,35 @@ const aVertexColor = gl.getAttribLocation(this._shaderProgram, 'aVertexColor'); gl.enableVertexAttribArray(aVertexColor); gl.vertexAttribPointer(aVertexColor, /* colorComponents*/ 4, gl.UNSIGNED_BYTE, true, 0, 0); + + this._uScalingFactor = gl.getUniformLocation(this._shaderProgram, 'uScalingFactor'); + this._uShiftVector = gl.getUniformLocation(this._shaderProgram, 'uShiftVector'); } _drawGL() { const gl = /** @type {?WebGLRenderingContext} */ (this._canvasGL.getContext('webgl')); if (!gl) return; - const timelineData = this._timelineData(); if (!timelineData) return; - const width = this._canvasGL.width; - const height = this._canvasGL.height; - if (!this._prevTimelineData || timelineData.entryTotalTimes !== this._prevTimelineData.entryTotalTimes) { this._prevTimelineData = timelineData; this._setupGLGeometry(); } - const viewportScale = [2.0 / this.boundarySpan(), -2.0 * window.devicePixelRatio / height]; - const viewportShift = [this.minimumBoundary() - this.zeroTime(), this._chartViewport.scrollOffset()]; - - gl.viewport(0, 0, width, height); + gl.viewport(0, 0, this._canvasGL.width, this._canvasGL.height); gl.clearColor(1.0, 1.0, 1.0, 1.0); gl.clear(gl.COLOR_BUFFER_BIT); if (!this._vertexCount) return; - const uScalingFactor = gl.getUniformLocation(this._shaderProgram, 'uScalingFactor'); - const uShiftVector = gl.getUniformLocation(this._shaderProgram, 'uShiftVector'); - - gl.uniform2fv(uScalingFactor, viewportScale); - gl.uniform2fv(uShiftVector, viewportShift); + const viewportScale = [2.0 / this.boundarySpan(), -2.0 * window.devicePixelRatio / this._canvasGL.height]; + const viewportShift = [this.minimumBoundary() - this.zeroTime(), this._chartViewport.scrollOffset()]; + gl.uniform2fv(this._uScalingFactor, viewportScale); + gl.uniform2fv(this._uShiftVector, viewportShift); gl.drawArrays(gl.TRIANGLES, 0, this._vertexCount); }
diff --git a/third_party/blink/renderer/modules/background_fetch/background_fetch_manager.cc b/third_party/blink/renderer/modules/background_fetch/background_fetch_manager.cc index 9099e3dc9..de043b1 100644 --- a/third_party/blink/renderer/modules/background_fetch/background_fetch_manager.cc +++ b/third_party/blink/renderer/modules/background_fetch/background_fetch_manager.cc
@@ -90,22 +90,8 @@ const KURL& request_url) { // TODO(crbug.com/757441): Using MixedContentChecker::ShouldBlockFetch would // log better metrics. - if (MixedContentChecker::IsMixedContent( - execution_context->GetSecurityOrigin(), request_url)) { - return true; - } - - // Normally requests from e.g. http://127.0.0.1 aren't subject to Mixed - // Content checks even though that is a secure context. Since this is a new - // API only exposed on secure contexts, be strict pending the discussion in - // https://groups.google.com/a/chromium.org/d/topic/security-dev/29Ftfgn-w0I/discussion - // https://w3c.github.io/webappsec-mixed-content/#a-priori-authenticated-url - if (!SecurityOrigin::Create(request_url)->IsPotentiallyTrustworthy() && - !request_url.ProtocolIsData()) { - return true; - } - - return false; + return MixedContentChecker::IsMixedContent( + execution_context->GetSecurityOrigin(), request_url); } bool ShouldBlockDanglingMarkup(const KURL& request_url) {
diff --git a/third_party/blink/renderer/modules/cache_storage/cache_storage_error.cc b/third_party/blink/renderer/modules/cache_storage/cache_storage_error.cc index 60254c1..0cb2707 100644 --- a/third_party/blink/renderer/modules/cache_storage/cache_storage_error.cc +++ b/third_party/blink/renderer/modules/cache_storage/cache_storage_error.cc
@@ -34,9 +34,6 @@ case mojom::CacheStorageError::kErrorStorage: return DOMException::Create(DOMExceptionCode::kUnknownError, "Unexpected internal error."); - case mojom::CacheStorageError::kErrorDuplicateOperation: - return DOMException::Create(DOMExceptionCode::kInvalidStateError, - "Duplicate operation."); case mojom::CacheStorageError::kSuccess: // This function should only be called with an error. break;
diff --git a/third_party/blink/renderer/modules/cache_storage/inspector_cache_storage_agent.cc b/third_party/blink/renderer/modules/cache_storage/inspector_cache_storage_agent.cc index d3faa56..7152bec 100644 --- a/third_party/blink/renderer/modules/cache_storage/inspector_cache_storage_agent.cc +++ b/third_party/blink/renderer/modules/cache_storage/inspector_cache_storage_agent.cc
@@ -161,8 +161,6 @@ return CString("operation too large."); case mojom::blink::CacheStorageError::kErrorStorage: return CString("storage failure."); - case mojom::blink::CacheStorageError::kErrorDuplicateOperation: - return CString("duplicate operation."); case mojom::blink::CacheStorageError::kSuccess: // This function should only be called upon error. break;
diff --git a/third_party/blink/renderer/platform/fonts/font.cc b/third_party/blink/renderer/platform/fonts/font.cc index a67e4393..2df09085 100644 --- a/third_party/blink/renderer/platform/fonts/font.cc +++ b/third_party/blink/renderer/platform/fonts/font.cc
@@ -505,6 +505,12 @@ return ranges; } +Vector<double> Font::IndividualCharacterAdvances(const TextRun& run) const { + FontCachePurgePreventer purge_preventer; + CachingWordShaper shaper(*this); + return shaper.IndividualCharacterAdvances(run); +} + void Font::ExpandRangeToIncludePartialGlyphs(const TextRun& text_run, int* from, int* to) const {
diff --git a/third_party/blink/renderer/platform/fonts/font.h b/third_party/blink/renderer/platform/fonts/font.h index de3a27c..a661792 100644 --- a/third_party/blink/renderer/platform/fonts/font.h +++ b/third_party/blink/renderer/platform/fonts/font.h
@@ -156,6 +156,11 @@ unsigned to) const; Vector<CharacterRange> IndividualCharacterRanges(const TextRun&) const; + // Returns a vector of same size as TextRun.length() with advances measured + // in pixels from the left bounding box of the full TextRun to the left bound + // of the glyph rendered by each character. Values should always be positive. + Vector<double> IndividualCharacterAdvances(const TextRun&) const; + void ExpandRangeToIncludePartialGlyphs(const TextRun&, int* from, int* to) const;
diff --git a/third_party/blink/renderer/platform/fonts/shaping/caching_word_shaper.cc b/third_party/blink/renderer/platform/fonts/shaping/caching_word_shaper.cc index d574c54a..a04cefd7 100644 --- a/third_party/blink/renderer/platform/fonts/shaping/caching_word_shaper.cc +++ b/third_party/blink/renderer/platform/fonts/shaping/caching_word_shaper.cc
@@ -111,7 +111,6 @@ const TextRun& run) { ShapeResultBuffer buffer; float total_width = ShapeResultsForRun(GetShapeCache(), &font_, run, &buffer); - auto ranges = buffer.IndividualCharacterRanges(run.Direction(), total_width); // The shaper can fail to return glyph metrics for all characters (see // crbug.com/613915 and crbug.com/615661) so add empty ranges to ensure all @@ -121,6 +120,14 @@ return ranges; } +Vector<double> CachingWordShaper::IndividualCharacterAdvances( + const TextRun& run) { + ShapeResultBuffer buffer; + float total_width = ShapeResultsForRun(GetShapeCache(), &font_, run, &buffer); + return buffer.IndividualCharacterAdvances(run.ToStringView(), run.Direction(), + total_width); +} + Vector<ShapeResult::RunFontData> CachingWordShaper::GetRunFontData( const TextRun& run) const { ShapeResultBuffer buffer;
diff --git a/third_party/blink/renderer/platform/fonts/shaping/caching_word_shaper.h b/third_party/blink/renderer/platform/fonts/shaping/caching_word_shaper.h index 1adfe22..7565968 100644 --- a/third_party/blink/renderer/platform/fonts/shaping/caching_word_shaper.h +++ b/third_party/blink/renderer/platform/fonts/shaping/caching_word_shaper.h
@@ -61,6 +61,7 @@ void FillResultBuffer(const TextRunPaintInfo&, ShapeResultBuffer*); CharacterRange GetCharacterRange(const TextRun&, unsigned from, unsigned to); Vector<CharacterRange> IndividualCharacterRanges(const TextRun&); + Vector<double> IndividualCharacterAdvances(const TextRun&); Vector<ShapeResult::RunFontData> GetRunFontData(const TextRun&) const;
diff --git a/third_party/blink/renderer/platform/fonts/shaping/shape_result_buffer.cc b/third_party/blink/renderer/platform/fonts/shaping/shape_result_buffer.cc index b42e01c..a959740 100644 --- a/third_party/blink/renderer/platform/fonts/shaping/shape_result_buffer.cc +++ b/third_party/blink/renderer/platform/fonts/shaping/shape_result_buffer.cc
@@ -199,6 +199,86 @@ return ranges; } +void ShapeResultBuffer::AddRunInfoAdvances(const ShapeResult::RunInfo& run_info, + float offset, + Vector<double>& advances) { + const unsigned num_glyphs = run_info.glyph_data_.size(); + const unsigned num_chars = run_info.num_characters_; + + if (run_info.Rtl()) + offset += run_info.width_; + + double current_width = 0; + for (unsigned glyph_id = 0; glyph_id < num_glyphs; glyph_id++) { + unsigned gid = run_info.Rtl() ? num_glyphs - glyph_id - 1 : glyph_id; + unsigned next_gid = + run_info.Rtl() ? num_glyphs - glyph_id - 2 : glyph_id + 1; + const HarfBuzzRunGlyphData& glyph = run_info.glyph_data_[gid]; + + unsigned char_id = glyph.character_index; + unsigned next_char_id = + (glyph_id + 1 == num_glyphs) + ? num_chars + : run_info.glyph_data_[next_gid].character_index; + + current_width += glyph.advance; + + if (char_id == next_char_id) + continue; + + unsigned num_graphemes = run_info.NumGraphemes(char_id, next_char_id); + + for (unsigned i = char_id; i < next_char_id; i++) { + if (run_info.Rtl()) { + advances.push_back(offset - (current_width / num_graphemes)); + } else { + advances.push_back(offset); + } + + if (num_graphemes == next_char_id - char_id) { + offset += (current_width / num_graphemes) * (run_info.Rtl() ? -1 : 1); + } + } + + if (num_graphemes != next_char_id - char_id) { + offset += current_width * (run_info.Rtl() ? -1 : 1); + } + + current_width = 0; + } +} + +Vector<double> ShapeResultBuffer::IndividualCharacterAdvances( + const StringView& text, + TextDirection direction, + float total_width) const { + unsigned character_offset = 0; + Vector<double> advances; + float current_x = direction == TextDirection::kRtl ? total_width : 0; + + for (const scoped_refptr<const ShapeResult> result : results_) { + unsigned run_count = result->runs_.size(); + + result->EnsureGraphemes( + StringView(text, character_offset, result->NumCharacters())); + + if (result->Rtl()) { + for (int index = run_count - 1; index >= 0; index--) { + current_x -= result->runs_[index]->width_; + AddRunInfoAdvances(*result->runs_[index], current_x, advances); + } + } else { + for (unsigned index = 0; index < run_count; index++) { + AddRunInfoAdvances(*result->runs_[index], current_x, advances); + current_x += result->runs_[index]->width_; + } + } + + character_offset += result->NumCharacters(); + } + return advances; +} + int ShapeResultBuffer::OffsetForPosition( const TextRun& run, float target_x,
diff --git a/third_party/blink/renderer/platform/fonts/shaping/shape_result_buffer.h b/third_party/blink/renderer/platform/fonts/shaping/shape_result_buffer.h index d4b73fd5..fb601df7 100644 --- a/third_party/blink/renderer/platform/fonts/shaping/shape_result_buffer.h +++ b/third_party/blink/renderer/platform/fonts/shaping/shape_result_buffer.h
@@ -44,6 +44,9 @@ unsigned to) const; Vector<CharacterRange> IndividualCharacterRanges(TextDirection, float total_width) const; + Vector<double> IndividualCharacterAdvances(const StringView&, + TextDirection, + float total_width) const; static CharacterRange GetCharacterRange(scoped_refptr<const ShapeResult>, const StringView& text, @@ -68,6 +71,9 @@ unsigned from, unsigned to); + static void AddRunInfoAdvances(const ShapeResult::RunInfo& run_info, + float offset, + Vector<double>& advances); static void AddRunInfoRanges(const ShapeResult::RunInfo&, float offset, Vector<CharacterRange>&);
diff --git a/third_party/flatbuffers/BUILD.gn b/third_party/flatbuffers/BUILD.gn index fe61f77..f02db1d0 100644 --- a/third_party/flatbuffers/BUILD.gn +++ b/third_party/flatbuffers/BUILD.gn
@@ -35,24 +35,35 @@ "src/grpc/src/compiler/cpp_generator.h", "src/grpc/src/compiler/go_generator.cc", "src/grpc/src/compiler/go_generator.h", + "src/grpc/src/compiler/java_generator.cc", + "src/grpc/src/compiler/java_generator.h", "src/grpc/src/compiler/schema_interface.h", + "src/include/flatbuffers/base.h", "src/include/flatbuffers/code_generators.h", + "src/include/flatbuffers/flatbuffers.h", "src/include/flatbuffers/flatc.h", "src/include/flatbuffers/flexbuffers.h", "src/include/flatbuffers/grpc.h", "src/include/flatbuffers/hash.h", "src/include/flatbuffers/idl.h", + "src/include/flatbuffers/minireflect.h", "src/include/flatbuffers/reflection.h", "src/include/flatbuffers/reflection_generated.h", + "src/include/flatbuffers/registry.h", + "src/include/flatbuffers/stl_emulation.h", "src/include/flatbuffers/util.h", "src/src/code_generators.cpp", "src/src/flatc.cpp", "src/src/idl_gen_cpp.cpp", + "src/src/idl_gen_dart.cpp", "src/src/idl_gen_fbs.cpp", "src/src/idl_gen_general.cpp", "src/src/idl_gen_go.cpp", "src/src/idl_gen_grpc.cpp", "src/src/idl_gen_js.cpp", + "src/src/idl_gen_json_schema.cpp", + "src/src/idl_gen_lobster.cpp", + "src/src/idl_gen_lua.cpp", "src/src/idl_gen_php.cpp", "src/src/idl_gen_python.cpp", "src/src/idl_gen_text.cpp",
diff --git a/third_party/flatbuffers/README.chromium b/third_party/flatbuffers/README.chromium index 1400e04f..1e7f3309 100644 --- a/third_party/flatbuffers/README.chromium +++ b/third_party/flatbuffers/README.chromium
@@ -1,8 +1,8 @@ Name: FlatBuffers Short Name: flatbuffers URL: https://github.com/google/flatbuffers -Version: 01c50d57a67a52ee3cddd81b54d4647e9123a290 -Date: 2017-06-05 +Version: 5d3648b88a91e8a5d67db83df2d08bb9e8702ae8 +Date: 2018-07-24 License: Apache 2.0 License File: LICENSE Security Critical: yes
diff --git a/third_party/fuchsia-sdk/BUILD.gn b/third_party/fuchsia-sdk/BUILD.gn index ef4d58a..669ecaeb 100644 --- a/third_party/fuchsia-sdk/BUILD.gn +++ b/third_party/fuchsia-sdk/BUILD.gn
@@ -219,6 +219,7 @@ sources = [ "audio.fidl", + "audio_device_enumerator.fidl", "audio_in.fidl", "audio_out.fidl", "audio_renderer.fidl",
diff --git a/third_party/libvpx/README.chromium b/third_party/libvpx/README.chromium index 55aa33fa..90bdcb4e 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: Saturday August 11 2018 +Date: Thursday August 16 2018 Branch: master -Commit: b8642738c9851232c9bb1e1a22474953d3d367cf +Commit: 6c62530c666fc0bcf4385a35a7c49e44c9f38cf5 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 fa1a818..d8f4d31 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 7 #define VERSION_PATCH 0 -#define VERSION_EXTRA "815-gb8642738c" +#define VERSION_EXTRA "834-g6c62530c6" #define VERSION_PACKED ((VERSION_MAJOR<<16)|(VERSION_MINOR<<8)|(VERSION_PATCH)) -#define VERSION_STRING_NOSP "v1.7.0-815-gb8642738c" -#define VERSION_STRING " v1.7.0-815-gb8642738c" +#define VERSION_STRING_NOSP "v1.7.0-834-g6c62530c6" +#define VERSION_STRING " v1.7.0-834-g6c62530c6"
diff --git a/third_party/metrics_proto/README.chromium b/third_party/metrics_proto/README.chromium index 51bd9c7..917c2bf 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: 205000821 -Date: 2018/07/18 UTC +Version: 209012138 +Date: 2018/08/16 UTC License: BSD Security Critical: Yes
diff --git a/third_party/metrics_proto/call_stack_profile.proto b/third_party/metrics_proto/call_stack_profile.proto index 052e600..73d693e5 100644 --- a/third_party/metrics_proto/call_stack_profile.proto +++ b/third_party/metrics_proto/call_stack_profile.proto
@@ -16,33 +16,6 @@ // Call stack sample data for a given profiling session. // Next tag: 5 message CallStackProfile { - // Describes an entry in the callstack. - message Entry { - // Instruction pointer subtracted by module base. - optional uint64 address = 1; - - // Index to the module identifier in |module_ids| of CallStackProfile. - optional int32 module_id_index = 2; - } - - // A sample consisting of one or more callstacks with the same stack frames - // and instruction pointers. - message Sample { - // The callstack. Sample.entries[0] represents the call on the top of the - // stack. - repeated Entry entry = 1; - - // Number of times this stack signature occurs. - optional int64 count = 2; - - // This repeating field indicates the current phase of the system such as - // whether it is in startup, general operation, or shutdown. The first - // Sample of a CallStackProfile will list all phases that have been reached; - // later samples will list only the new phases that occurred since the - // previous one. - repeated ProcessPhase process_phase = 3; - } - // Uniquely identifies a module. message ModuleIdentifier { // A hash that uniquely identifies a particular program version with high @@ -58,6 +31,33 @@ optional fixed64 name_md5_prefix = 2; } + // Describes a location within executable code. + message Location { + // Instruction pointer subtracted by module base. + optional uint64 address = 1; + + // Index to the module identifier in |module_ids| of CallStackProfile. + optional int32 module_id_index = 2; + } + + // A sample consisting of one or more callstacks with the same stack frames + // and instruction pointers. + message Sample { + // The callstack. Sample.frame[0] represents the call on the top of the + // stack. + repeated Location frame = 1; + + // Number of times this stack signature occurs. + optional int64 count = 2; + + // This repeating field indicates the current phase of the system such as + // whether it is in startup, general operation, or shutdown. The first + // Sample of a CallStackProfile will list all phases that have been reached; + // later samples will list only the new phases that occurred since the + // previous one. + repeated ProcessPhase process_phase = 3; + } + // The callstack and counts. repeated Sample sample = 1;
diff --git a/third_party/metrics_proto/cast_logs.proto b/third_party/metrics_proto/cast_logs.proto index 8a38b87..dd46b0b9 100644 --- a/third_party/metrics_proto/cast_logs.proto +++ b/third_party/metrics_proto/cast_logs.proto
@@ -145,7 +145,7 @@ repeated CastConnectionInfo cast_connection_info = 2; // Stores Cast-enabled device specific events with a various context data. - // Next tag: 17 + // Next tag: 18 message CastEventProto { // The name of the action, hashed by same logic used to hash user action // event and histogram. @@ -198,6 +198,9 @@ // Optional values associated with the event. repeated float feature_vector = 15; + + // Optional value associated with timezone update event. + optional string timezone_id = 17; } repeated CastEventProto cast_event = 3; @@ -206,7 +209,7 @@ optional fixed32 virtual_release_track = 4; // Cast specific device information which is expected to change over time. - // Next tag: 7 + // Next tag: 8 message CastDeviceMutableInfo { // This is the last type of reboot the device encountered // Next tag: 9 @@ -246,6 +249,9 @@ // True if the system which cast_shell is running on, supports ip dual stack // sockets. optional bool ip_dual_stack_supported = 6; + + // Current timezone which the device is using. + optional string timezone_id = 7; } // The device sends this information at least once per day. optional CastDeviceMutableInfo cast_device_mutable_info = 5;
diff --git a/third_party/metrics_proto/ukm/source.proto b/third_party/metrics_proto/ukm/source.proto index e05866df..ea6616c 100644 --- a/third_party/metrics_proto/ukm/source.proto +++ b/third_party/metrics_proto/ukm/source.proto
@@ -20,6 +20,7 @@ ABOUT = 4; CHROME = 5; CHROME_EXTENSION = 6; + APP = 7; }; // An identifier for the source. This should be unique within a session.
diff --git a/tools/fuchsia/comparative_tester/README.md b/tools/fuchsia/comparative_tester/README.md new file mode 100644 index 0000000..fddad48 --- /dev/null +++ b/tools/fuchsia/comparative_tester/README.md
@@ -0,0 +1,77 @@ +# Comparative Testing Scripts for Fuchsia + +The collection of python scripts inside of `//tools/fuchsia/comparative_tester` +exist to facilitate the automated building, deployment, and execution of tests +on Linux and Fuchsia devices on the same LAN as the hosting PC which will run +the scripts, as well as generating comparisons and valuable statistical data and +displaying it in an easily viewed form. + +## Test Support +The automated test building and launching should currently work for any test +target within the base `chromium/src` directory. Work is also underway to +support executing Catapult tests automatically, with the same stats collection +capabilities. + +## Usage +The general usage pattern for these scripts is as follows: +1. Check `target_spec.py`. Make sure that the output directories are where you + want them, and that you are running the chromium test targets that you're + interested in collecting results from. Also check to make sure that the + specifications for the Linux and Fuchsia devices are appropriate for your + specific network and OS configuration. +2. Execute `comparative_tester.py`, with any flags necessary to collect the data + of interest. +3. Run `generate_perf_report.py`. This should require no extra configuration on + your part. +4. View your results by loading `display_perf_results.html` in any web browser + and giving it the result JSONs in the output directory you specified. + +### test_results.py +(_Non-Invokable_) + +This file is used internally to parse test output and return objects that can be +manipulated easily by the rest of the code. + +### target_spec.py +(_Non-Invokable_) + +This file contains constant definitions used by other files in this folder to +represent what tests to run, where the output will live, where the test binaries +live, and so on. To add more tests for automatic building and deploying, they +should be added here. + +### comparative_tester.py +_Invocation_: `comparative_tester.py --do-config --do-build --is-debug --num-repetitions=1` + +This is where tests are actually executed. It has four flags of note: + * `--do-config`: makes the test script to generate an args.gn file for + the output directory, and over-writes any existing `args.gn` file. This + option is off by default, and no files will be generated or changed. + * `--is-debug`: requires the do_config flag to be set as well. Makes + the args.gn files that the script will generate have the + `is_debug = true` line. This option is off by default, and will + cause the line `is_debug = false` to appear in the `args.gn` file + * `--do-build`: makes the test script build the targets specified inside of + `target_spec.py`. By default, this is off, and the targets will not be + rebuilt for the test cases. + * `--num-repetitions`: tells the script how many times to run each test in the + battery of tests specified in `target_spec.py`. By default, this is one, + so tests will only be executed one time each. +More complex configuration options are present in `target_spec.py.` + +### generate_perf_report.py +_Invocation_: `generate_perf_report.py` +This script takes no command line flags, but works off of many of the same +fields inside of `target_spec.py` that `comparative_tester.py` does, namely +fields instructing it where the raw data lives, and where to place the generated +statistics when it's finished generating them. It generates the mean, standard +deviation, and coefficient of variance for each target, test, and individual +line scraped from the test output, and writes them to appropriately named JSONs. + +### display_perf_results.html and .js +The HTML file is just a thin shim around `display_perf_results.js` that can be +opened in any web browser to view the data. Due to the isolation between +javascript interpreters and the host's filesystem, the web page must be manually +given the final JSON files that you want to display, at which point it will draw +a table full of the data, and in a more human readable format. It accepts +multiple files at a time. \ No newline at end of file
diff --git a/tools/fuchsia/comparative_tester/comparative_tester.py b/tools/fuchsia/comparative_tester/comparative_tester.py index 09bd203c..a36463e 100755 --- a/tools/fuchsia/comparative_tester/comparative_tester.py +++ b/tools/fuchsia/comparative_tester/comparative_tester.py
@@ -23,7 +23,20 @@ def RunCommand(command: List[str], msg: str) -> str: - "One-shot start and complete command with useful default kwargs" + """Runs a command and returns the standard output. + + Args: + command (List[str]): The list of command chunks to use in subprocess.run. + ex: ['git', 'grep', 'cat'] to find all instances of cat in a repo. + msg (str): An error message in case the subprocess fails for some reason. + + Raises: + subprocess.SubprocessError: Raises this with the command that failed in the + event that the return code of the process is non-zero. + + Returns: + str: the standard output of the subprocess. + """ command = [piece for piece in command if piece != ""] proc = subprocess.run( command, @@ -42,6 +55,16 @@ # TODO(crbug.com/848465): replace with --test-launcher-filter-file directly def ParseFilterFile(filepath: str) -> str: + """Takes a path to a filter file, parses it, and constructs a gtest_filter + string for test execution. + + Args: + filepath (str): The path to the filter file to be parsed into a + --gtest_filter flag. + + Returns: + str: The properly-joined together gtest_filter flag. + """ positive_filters = [] negative_filters = [] with open(filepath, "r") as file: @@ -77,14 +100,36 @@ self._filter_flag = ParseFilterFile(self._filter_file) def ExecFuchsia(self, out_dir: str, run_locally: bool) -> str: + """Execute this test target's test on Fuchsia, either with QEMU or on actual + hardware. + + Args: + out_dir (str): The Fuchsia output directory. + run_locally (bool): Whether to use QEMU(true) or a physical device(false) + + Returns: + str: The standard output of the test process. + """ + runner_name = "{}/bin/run_{}".format(out_dir, self._name) command = [runner_name, self._filter_flag, "--exclude-system-logs"] if not run_locally: command.append("-d") return RunCommand(command, - "Test {} failed on fuchsia!".format(self._target)) + "Test {} failed on Fuchsia!".format(self._target)) def ExecLinux(self, out_dir: str, run_locally: bool) -> str: + """Execute this test target's test on Linux, either with QEMU or on actual + hardware. + + Args: + out_dir (str): The Linux output directory. + run_locally (bool): Whether to use the host machine(true) or a physical + device(false) + + Returns: + str: The standard output of the test process. + """ command = [] # type: List[str] user = target_spec.linux_device_user ip = target_spec.linux_device_ip @@ -102,6 +147,14 @@ return RunCommand(command, "Test {} failed on linux!".format(self._target)) def TransferDependencies(self, out_dir: str, host: str): + """Transfer the dependencies of this target to the machine to execute the + test. + + Args: + out_dir (str): The output directory to find the dependencies in. + host (str): The IP address of the host to receive the dependencies. + """ + gn_desc = ["gn", "desc", out_dir, self._target, "runtime_deps"] out = RunCommand( gn_desc, "Failed to get dependencies of target {}".format(self._target)) @@ -152,6 +205,17 @@ def RunTest(target: TestTarget, run_locally: bool = False) -> None: + """Run the given TestTarget on both Linux and Fuchsia + + Args: + target (TestTarget): The TestTarget to run. + run_locally (bool, optional): Defaults to False. Whether the test should be + run on the host machine, or sent to remote devices for execution. + + Returns: + None: Technically an IO (), as it writes to the results files + """ + linux_out = target.ExecLinux(target_spec.linux_out_dir, run_locally) linux_result = test_results.TargetResultFromStdout(linux_out.splitlines(), target._name) @@ -168,6 +232,19 @@ def RunGnForDirectory(dir_name: str, target_os: str, is_debug: bool) -> None: + """Create the output directory for test builds for an operating system. + + Args: + dir_name (str): The name to use for the output directory. This will be + created if it does not exist. + target_os (str): The operating system to initialize this directory for. + is_debug (bool): Whether or not this is a debug build of the tests in + question. + + Returns: + None: It has a side effect of replacing args.gn + """ + if not os.path.exists(dir_name): os.makedirs(dir_name) @@ -185,6 +262,16 @@ def GenerateTestData(do_config: bool, do_build: bool, num_reps: int, is_debug: bool): + """Initializes directories, builds test targets, and repeatedly executes them + on both operating systems + + Args: + do_config (bool): Whether or not to run GN for the output directories + do_build (bool): Whether or not to run ninja for the test targets. + num_reps (int): How many times to run each test on a given device. + is_debug (bool): Whether or not this should be a debug build of the tests. + """ + DIR_SOURCE_ROOT = os.path.abspath( os.path.join(os.path.dirname(__file__), *([os.pardir] * 3))) os.chdir(DIR_SOURCE_ROOT)
diff --git a/tools/fuchsia/comparative_tester/display_perf_results.js b/tools/fuchsia/comparative_tester/display_perf_results.js index bec01669..3a48169a 100644 --- a/tools/fuchsia/comparative_tester/display_perf_results.js +++ b/tools/fuchsia/comparative_tester/display_perf_results.js
@@ -7,6 +7,7 @@ "F-L Avgs"]; function generateHeader() { + // Generates the header for a table of statistics. let header_row = document.createElement("tr"); for (let i = 0; i < headers.length; i++){ let header = document.createElement("th"); @@ -17,6 +18,8 @@ } function generateTableHtmlFromOutputRows(output_rows) { + // Takes a list of rows of data, and collects them together into a single + // table. let table = document.createElement("table"); table.appendChild(generateHeader()); output_rows.forEach(function(row){ @@ -32,6 +35,7 @@ } function extractStats(line) { + // Deconstructs the JSON file given into a list of the relevant values. return [line.fuchsia_avg, line.fuchsia_dev, line.fuchsia_cv, @@ -42,6 +46,8 @@ } function renderTable(obj_dict) { + // Returns an HTML table object by taking the TargetResults JSON and using it + // to populate a table of statistics. let rows = [] const name = obj_dict['name'] @@ -64,6 +70,8 @@ } function loadTable() { + // Reads the result files, and adds the tables generated to the table_div HTML + // object as they finish loading. let files = document.getElementById('files').files; let table_div = document.getElementById('stats_div'); // Clear the table div of all prior stats tables
diff --git a/tools/fuchsia/comparative_tester/generate_perf_report.py b/tools/fuchsia/comparative_tester/generate_perf_report.py index 8df4878..db4fd978 100755 --- a/tools/fuchsia/comparative_tester/generate_perf_report.py +++ b/tools/fuchsia/comparative_tester/generate_perf_report.py
@@ -24,6 +24,17 @@ def __init__(self, desc: str, unit: str, time_avg: float, time_dev: float, cv: float, samples: int) -> None: + """A corpus of stats about a particular line from a given test's output. + + Args: + desc (str): Descriptive text of the line in question. + unit (str): The units of measure that the line's result is in. + time_avg (float): The average measurement. + time_dev (float): The standard deviation of the measurement. + cv (float): The coefficient of variance of the measure. + samples (int): The number of samples that went into making this object. + """ + self.desc = desc self.time_avg = time_avg self.time_dev = time_dev @@ -32,6 +43,7 @@ self.sample_num = samples def ToString(self) -> str: + """Converts the line to a human-readable string.""" if self.sample_num > 1: return "{}: {:.5f} σ={:.5f} {} with n={} cv={}".format( self.desc, self.time_avg, self.time_dev, self.unit, self.sample_num, @@ -40,7 +52,16 @@ return "{}: {:.5f} with only one sample".format(self.desc, self.time_avg) -def LineFromList(lines: List[ResultLine]) -> Optional[LineStats]: +def LineFromList(lines: List[ResultLine]) -> LineStats: + """Takes a list of ResultLines and generates statistics for them. + + Args: + lines (List[ResultLine]): The list of lines to generate stats for. + + Returns: + LineStats: the representation of statistical data for the lines. + """ + desc = lines[0].desc unit = lines[0].unit times = [line.meas for line in lines] @@ -52,6 +73,17 @@ def __init__(self, name: str, time_avg: float, time_dev: float, cv: float, samples: int, lines: List[LineStats]) -> None: + """Represents a summary of relevant statistics for a list of tests. + + Args: + name (str): The name of the test whose runs are being averaged. + time_avg (float): The average time to execute the test. + time_dev (float): The standard deviation in the mean. + cv (float): The coefficient of variance of the population. + samples (int): The number of samples in the population + lines (List[LineStats]): The averaged list of all the lines of output that + comprises this test. + """ self.name = name self.time_avg = time_avg self.time_dev = time_dev @@ -60,6 +92,13 @@ self.lines = lines def ToLines(self) -> List[str]: + """The stats of this test, as well as its constituent LineStats, in a human- + readable format. + + Returns: + List[str]: The human-readable list of lines. + """ + lines = [] if self.sample_num > 1: lines.append("{}: {:.5f} σ={:.5f}ms with n={} cv={}".format( @@ -73,6 +112,15 @@ def TestFromList(tests: List[TestResult]) -> TestStats: + """Coalesces a list of TestResults into a single TestStats object. + + Args: + tests (List[TestResult]): The input sample of the tests. + + Returns: + TestStats: A representation of the statistics of the tests. + """ + name = tests[0].name avg, dev, cv = GenStats([test.time for test in tests]) lines = {} # type: Dict[str, List[ResultLine]] @@ -94,11 +142,25 @@ class TargetStats(object): def __init__(self, name: str, samples: int, tests: List[TestStats]) -> None: + """A representation of the actual target that was built and run on the + platforms multiple times to generate statistical data. + + Args: + name (str): The name of the target that was built and run. + samples (int): The number of times the tests were run. + tests (List[TestStats]): The statistics of tests included in the target. + """ + self.name = name self.sample_num = samples self.tests = tests def ToLines(self) -> List[str]: + """Converts the entire target into a list of lines in human-readable format. + + Returns: + List[str]: The human-readable test lines. + """ lines = [] if self.sample_num > 1: lines.append("{}: ".format(self.name)) @@ -114,6 +176,16 @@ def TargetFromList(results: List[TargetResult]) -> TargetStats: + """Coalesces a list of TargetResults into a single collection of stats. + + Args: + results (List[TargetResult]): The sampling of target executions to generate + stats for. + + Returns: + TargetStats: The body of stats for the sample given. + """ + name = results[0].name sample_num = len(results) tests = {} # type: Dict[str, List[TestResult]] @@ -131,6 +203,15 @@ def GenStats(corpus: List[float]) -> Tuple[float, float, float]: + """Generates statistics from a list of values + + Args: + corpus (List[float]): The set of data to generate statistics for. + + Returns: + Tuple[float, float, float]: The mean, standard deviation, and coefficient of + variation for the given sample data. + """ avg = sum(corpus) / len(corpus) adjusted_sum = 0.0 for item in corpus: @@ -143,6 +224,17 @@ def DirectoryStats(directory: str) -> List[TargetStats]: + """Takes a path to directory, and uses JSON files in that directory to compile + a list of statistical objects for each independent test target it can detect + in the directory. + + Args: + directory (str): The directory to scan for relevant JSONs + + Returns: + List[TargetStats]: Each element in this list is one target, averaged up over + all of its executions. + """ resultMap = {} # type: Dict[str, List[TargetResult]] for file in os.listdir(directory): results = ReadTargetFromJson("{}/{}".format(directory, file)) @@ -179,6 +271,7 @@ def CompareTests(linux: TestStats, fuchsia: TestStats) -> Dict[str, Any]: + """As CompareTargets, but at the test level""" if not linux and not fuchsia: logging.error("Two null TestStats objects were passed to CompareTests.") return {} @@ -255,10 +348,8 @@ pred: Callable[[T], R]) -> Dict[R, Tuple[T, T]]: """This function takes two lists, and a predicate. The predicate is applied to the values in both lists to obtain a keying value from them. Each item is then - inserted into the returned dictionary using the obtained key. Finally, after - all items have been added to the dict, any items that do not have a pair are - discarded after warning the user, and the new dictionary is returned. The - predicate should not map multiple values from one list to the same key. + inserted into the returned dictionary using the obtained key. The predicate + should not map multiple values from one list to the same key. """ paired_items = {} # type: Dict [R, Tuple[T, T]] for item in left:
diff --git a/tools/fuchsia/comparative_tester/test_results.py b/tools/fuchsia/comparative_tester/test_results.py index 6bd5dc9..4db630e 100644 --- a/tools/fuchsia/comparative_tester/test_results.py +++ b/tools/fuchsia/comparative_tester/test_results.py
@@ -10,6 +10,15 @@ def UnitStringIsValid(unit: str) -> bool: + """Checks to make sure that a given string is in fact a recognized unit used + by the chromium perftests to report results. + + Args: + unit (str): The unit string to be checked. + + Returns: + bool: Whether or not it is a unit. + """ accepted_units = [ "us/hop", "us/task", "ns/sample", "ms", "s", "count", "KB", "MB/s", "us" ] @@ -18,7 +27,7 @@ class ResultLine(object): """ResultLine objects are each an individual line of output, complete with a - unit, measurement, and descriptive component + unit, measurement, and descriptive component. """ def __init__(self, desc: str, measure: float, unit: str) -> None: @@ -27,6 +36,13 @@ self.unit = unit def ToJsonDict(self) -> Dict[str, Any]: + """Converts a ResultLine into a JSON-serializable dictionary object. + + Returns: + Dict[str, Any]: A mapping of strings that will appear in the output JSON + object to their respective values. + """ + return { "description": self.desc, "measurement": self.meas, @@ -34,13 +50,36 @@ } -def ReadResultLineFromJson(dct: Dict[str, Any]): +def ReadResultLineFromJson(dct: Dict[str, Any]) -> ResultLine: + """Converts a JSON dictionary object into a ResultLine. + + Args: + dct (Dict[str, Any]): The JSON object to be parsed as a ResultLine. MUST + contain the strings 'description', 'measurement', and 'unit'. + + Raises: + KeyError: If the passed in dictionary does not contain the three required + strings that a serialized ResultLine must contain. + + Returns: + ResultLine: A ResultLine object reconstituted from the JSON dictionary. + """ return ResultLine(dct["description"], float(dct["measurement"]), dct["unit"]) def ResultLineFromStdout(line: str) -> Optional[ResultLine]: + """Takes a line of stdout data and attempts to parse it into a ResultLine. + + Args: + line (str): The stdout line to be converted + + Returns: + Optional[ResultLine]: The output is Optional, because the line may be noise, + or in some way incorrectly formatted and unparseable. + """ + if "pkgsvr" in line: - return None + return None # Filters pkgsrv noise from Fuchsia output. chunks = line.split() # There should be 1 chunk for the measure, 1 for the unit, and at least one # for the line description, so at least 3 total @@ -74,6 +113,12 @@ self.lines = lines def ToJsonDict(self) -> Dict[str, Any]: + """Converts a TestResult object to a JSON-serializable dictionary. + + Returns: + Dict[str, Any]: The output dictionary object that can be directly + serialized to JSON. + """ return { "name": self.name, "time_in_ms": self.time, @@ -82,6 +127,15 @@ def ReadTestFromJson(obj_dict: Dict[str, Any]) -> TestResult: + """Reconstitutes a TestResult read from a JSON file back into a TestResult + object. + + Args: + obj_dict (Dict[str, Any]): The JSON object as read from an output JSON file. + + Returns: + TestResult: The reconstituted TestResult object. + """ name = obj_dict["name"] time = obj_dict["time_in_ms"] lines = [ReadResultLineFromJson(line) for line in obj_dict["lines"]] @@ -89,6 +143,24 @@ def ExtractTestInfo(line: str) -> Tuple[str, float]: + """Deconstructs a line starting with OK, stating that the test finished + successfully, and isolates the timing measurement as well as a descriptive + string for the test + + Args: + line (str): The line of output to attempt to destructure into name and time. + + Raises: + Exception: In the event that it couldn't split on '(', because then it + find the necessary timing measurement. + Exception: in the event that it cannot find the ')' character in the output, + because then it isn't capable of isolating the timing measurement. + + Returns: + Tuple[str, float]: A tuple of the test name, and the amount of time it took + to run. + """ + # Trim off the [ OK ] part of the line trimmed = line.lstrip("[ OK ]").strip() try: @@ -107,6 +179,17 @@ def TaggedTestFromLines(lines: List[str]) -> TestResult: + """Takes a chunk of lines gathered together from the stdout of a test process + and collects it all into a single test result, including the set of + ResultLines inside of the TestResult. + + Args: + lines (List[str]): The stdout lines to be parsed into a single test result + + Returns: + TestResult: The final parsed TestResult from the input + """ + test_name, time = ExtractTestInfo(lines[-1]) res_lines = [] for line in lines[:-1]: @@ -130,17 +213,39 @@ self.tests = tests def ToJsonDict(self) -> Dict[str, Any]: + """Converts a TargetResult to a JSON-serializable dict. + + Returns: + Dict[str, Any]: The TargetResult in JSON-serializable form. + """ return { "name": self.name, "tests": [test.ToJsonDict() for test in self.tests] } def WriteToJson(self, path: str) -> None: + """Writes this TargetResult object as a JSON file at the given file path. + + Args: + path (str): The location to place the serialized version of this object. + + Returns: + None: It'd return IO (), but this Python. + """ with open(path, "w") as outfile: json.dump(self.ToJsonDict(), outfile, indent=2) -def ReadTargetFromJson(path: str): +def ReadTargetFromJson(path: str) -> Optional[TargetResult]: + """Takes a file path and attempts to parse a TargetResult from it. + + Args: + path (str): The location of the JSON-serialized TargetResult to read. + + Returns: + Optional[TargetResult]: Again, technically should be wrapped in an IO, + but Python. + """ with open(path, "r") as json_file: dct = json.load(json_file) return TargetResult( @@ -160,7 +265,17 @@ Unfortunately, Because the results of output from perftest targets is not necessarily consistent between test targets, this makes a best-effort to parse as much information from them as possible. + + Args: + lines (List[str]): The entire list of lines from the standard output to be + parsed. + name (str): The name of the Target that generated the output. Necessary to + be able to give the TargetResult a meaningful name. + + Returns: + TargetResult: The TargetResult object parsed from the input lines. """ + test_line_lists = [] # type: List[List[str]] test_line_accum = [] # type: List[str] read_lines = False
diff --git a/tools/metrics/histograms/enums.xml b/tools/metrics/histograms/enums.xml index 65c7164..55125bd6 100644 --- a/tools/metrics/histograms/enums.xml +++ b/tools/metrics/histograms/enums.xml
@@ -26053,6 +26053,11 @@ The page displaying the dialog was switched out of its tab (e.g. tab discarding) </int> + <int value="9" label="Dialog closed"> + The UI toolkit forced the dialog to close (at root caused by the user + closing the owning tab but going through a different path due to platform + differences) + </int> </enum> <enum name="JumplisticonsDeleteCategory"> @@ -28873,6 +28878,7 @@ <int value="-77872983" label="BookmarkAppsMac:disabled"/> <int value="-76631048" label="disable-offline-auto-reload-visible-only"/> <int value="-75418012" label="ContextualSuggestionsOptOut:disabled"/> + <int value="-73282711" label="EnableAppListSearchAutocomplete:enabled"/> <int value="-72455054" label="WebVrAutopresent:disabled"/> <int value="-70595606" label="ash-enable-unified-desktop"/> <int value="-69427025" label="OfflinePagesPrefetchingUI:enabled"/> @@ -29112,7 +29118,6 @@ <int value="430959979" label="SyncStandaloneTransport:disabled"/> <int value="431691805" label="MediaDocumentDownloadButton:enabled"/> <int value="434033638" label="PwaPersistentNotification:disabled"/> - <int value="438048339" label="WarnBeforeQuitting:disabled"/> <int value="446316019" label="enable-threaded-compositing"/> <int value="451196246" label="disable-impl-side-painting"/> <int value="452139294" label="VrShellExperimentalRendering:enabled"/> @@ -29155,7 +29160,6 @@ <int value="513356954" label="InstantTethering:disabled"/> <int value="513372959" label="ViewsProfileChooser:enabled"/> <int value="517568645" label="AnimatedAppMenuIcon:disabled"/> - <int value="530158943" label="WarnBeforeQuitting:enabled"/> <int value="535131384" label="OmniboxTailSuggestions:enabled"/> <int value="535976218" label="enable-plugin-power-saver"/> <int value="538468149" label="OfflinePagesCT:enabled"/> @@ -29394,6 +29398,7 @@ <int value="1012942422" label="HorizontalTabSwitcherAndroid:disabled"/> <int value="1015895665" label="drop-sync-credential:enabled"/> <int value="1017364362" label="VrIconInDaydreamHome:enabled"/> + <int value="1018797564" label="EnableAppListSearchAutocomplete:disabled"/> <int value="1018998019" label="memlog"/> <int value="1019623058" label="ash-enable-shelf-model-synchronization"/> <int value="1019857902"
diff --git a/tools/perf/expectations.config b/tools/perf/expectations.config index 468aa9d..d7fa8c66 100644 --- a/tools/perf/expectations.config +++ b/tools/perf/expectations.config
@@ -18,10 +18,6 @@ crbug.com/853738 [ Android_Webview ] blink_perf.canvas/upload-video-to-sub-texture.html [ Skip ] crbug.com/853738 [ Android_Webview ] blink_perf.canvas/upload-video-to-texture.html [ Skip ] -# Benchmark: blink_perf.image_decoder -crbug.com/874810 [ Win ] blink_perf.image_decoder/decode-lossy-webp.html [ Skip ] -crbug.com/874810 [ Win ] blink_perf.image_decoder/decode-png-palette-opaque.html [ Skip ] - # Benchmark: blink_perf.layout crbug.com/551950 [ Android_Svelte ] blink_perf.layout/* [ Skip ] crbug.com/832686 [ Nexus_5 ] blink_perf.layout/subtree-detaching.html [ Skip ]
diff --git a/ui/base/clipboard/clipboard_monitor.cc b/ui/base/clipboard/clipboard_monitor.cc index 984e766..e9e8cbe7 100644 --- a/ui/base/clipboard/clipboard_monitor.cc +++ b/ui/base/clipboard/clipboard_monitor.cc
@@ -12,28 +12,28 @@ ClipboardMonitor::ClipboardMonitor() {} ClipboardMonitor::~ClipboardMonitor() { - DCHECK(CalledOnValidThread()); + DCHECK_CALLED_ON_VALID_THREAD(thread_checker_); } // static ClipboardMonitor* ClipboardMonitor::GetInstance() { - return base::Singleton<ClipboardMonitor, - base::LeakySingletonTraits<ClipboardMonitor>>::get(); + static base::NoDestructor<ClipboardMonitor> monitor; + return monitor.get(); } void ClipboardMonitor::NotifyClipboardDataChanged() { - DCHECK(CalledOnValidThread()); + DCHECK_CALLED_ON_VALID_THREAD(thread_checker_); for (ClipboardObserver& observer : observers_) observer.OnClipboardDataChanged(); } void ClipboardMonitor::AddObserver(ClipboardObserver* observer) { - DCHECK(CalledOnValidThread()); + DCHECK_CALLED_ON_VALID_THREAD(thread_checker_); observers_.AddObserver(observer); } void ClipboardMonitor::RemoveObserver(ClipboardObserver* observer) { - DCHECK(CalledOnValidThread()); + DCHECK_CALLED_ON_VALID_THREAD(thread_checker_); observers_.RemoveObserver(observer); }
diff --git a/ui/base/clipboard/clipboard_monitor.h b/ui/base/clipboard/clipboard_monitor.h index 1330aaf..a18eca44 100644 --- a/ui/base/clipboard/clipboard_monitor.h +++ b/ui/base/clipboard/clipboard_monitor.h
@@ -6,7 +6,7 @@ #define UI_BASE_CLIPBOARD_CLIPBOARD_MONITOR_H_ #include "base/macros.h" -#include "base/memory/singleton.h" +#include "base/no_destructor.h" #include "base/observer_list.h" #include "base/threading/thread_checker.h" #include "ui/base/ui_base_export.h" @@ -17,7 +17,7 @@ // A singleton instance to monitor and notify ClipboardObservers for clipboard // changes. -class UI_BASE_EXPORT ClipboardMonitor : public base::ThreadChecker { +class UI_BASE_EXPORT ClipboardMonitor { public: static ClipboardMonitor* GetInstance(); @@ -31,15 +31,18 @@ virtual void NotifyClipboardDataChanged(); private: - friend struct base::DefaultSingletonTraits<ClipboardMonitor>; + friend class base::NoDestructor<ClipboardMonitor>; + ClipboardMonitor(); virtual ~ClipboardMonitor(); base::ObserverList<ClipboardObserver> observers_; + THREAD_CHECKER(thread_checker_); + DISALLOW_COPY_AND_ASSIGN(ClipboardMonitor); }; } // namespace ui -#endif /* UI_BASE_CLIPBOARD_CLIPBOARD_MONITOR_H_ */ +#endif // UI_BASE_CLIPBOARD_CLIPBOARD_MONITOR_H_
diff --git a/ui/ozone/common/linux/gbm_wrapper.cc b/ui/ozone/common/linux/gbm_wrapper.cc index 3c15127..99eed07 100644 --- a/ui/ozone/common/linux/gbm_wrapper.cc +++ b/ui/ozone/common/linux/gbm_wrapper.cc
@@ -167,6 +167,8 @@ const gfx::Size& size, uint32_t flags, const std::vector<uint64_t>& modifiers) override { + if (modifiers.empty()) + return CreateBuffer(format, size, flags); struct gbm_bo* bo = gbm_bo_create_with_modifiers( device_, size.width(), size.height(), format, modifiers.data(), modifiers.size());
diff --git a/ui/ozone/platform/drm/BUILD.gn b/ui/ozone/platform/drm/BUILD.gn index 3c2d50c..192df8e 100644 --- a/ui/ozone/platform/drm/BUILD.gn +++ b/ui/ozone/platform/drm/BUILD.gn
@@ -60,10 +60,10 @@ "gpu/drm_window.h", "gpu/drm_window_proxy.cc", "gpu/drm_window_proxy.h", - "gpu/gbm_pixmap.cc", - "gpu/gbm_pixmap.h", "gpu/gbm_overlay_surface.cc", "gpu/gbm_overlay_surface.h", + "gpu/gbm_pixmap.cc", + "gpu/gbm_pixmap.h", "gpu/gbm_surface.cc", "gpu/gbm_surface.h", "gpu/gbm_surface_factory.cc", @@ -90,8 +90,6 @@ "gpu/page_flip_request.h", "gpu/proxy_helpers.cc", "gpu/proxy_helpers.h", - "gpu/drm_framebuffer.h", - "gpu/drm_framebuffer_generator.h", "gpu/screen_manager.cc", "gpu/screen_manager.h", "host/drm_cursor.cc", @@ -184,10 +182,8 @@ "gpu/hardware_display_plane_manager_unittest.cc", "gpu/mock_drm_device.cc", "gpu/mock_drm_device.h", - "gpu/mock_dumb_buffer_generator.cc", - "gpu/mock_dumb_buffer_generator.h", - "gpu/mock_drm_framebuffer_generator.cc", - "gpu/mock_drm_framebuffer_generator.h", + "gpu/mock_gbm_device.cc", + "gpu/mock_gbm_device.h", "gpu/proxy_helpers_unittest.cc", "gpu/screen_manager_unittest.cc", ]
diff --git a/ui/ozone/platform/drm/gpu/drm_framebuffer.cc b/ui/ozone/platform/drm/gpu/drm_framebuffer.cc index 0109b28..b632257 100644 --- a/ui/ozone/platform/drm/gpu/drm_framebuffer.cc +++ b/ui/ozone/platform/drm/gpu/drm_framebuffer.cc
@@ -5,6 +5,7 @@ #include "ui/ozone/platform/drm/gpu/drm_framebuffer.h" #include "ui/ozone/common/linux/drm_util_linux.h" +#include "ui/ozone/common/linux/gbm_buffer.h" #include "ui/ozone/platform/drm/common/drm_util.h" #include "ui/ozone/platform/drm/gpu/drm_device.h" @@ -48,6 +49,35 @@ gfx::Size(params.width, params.height)); } +// static +scoped_refptr<DrmFramebuffer> DrmFramebuffer::AddFramebuffer( + scoped_refptr<DrmDevice> drm, + const GbmBuffer* buffer) { + gfx::Size size = buffer->GetSize(); + AddFramebufferParams params; + params.format = buffer->GetFormat(); + params.modifier = buffer->GetFormatModifier(); + params.width = size.width(); + params.height = size.height(); + params.num_planes = buffer->GetNumPlanes(); + for (size_t i = 0; i < params.num_planes; ++i) { + params.handles[i] = buffer->GetPlaneHandle(i); + params.strides[i] = buffer->GetPlaneStride(i); + params.offsets[i] = buffer->GetPlaneOffset(i); + } + + // AddFramebuffer2 only considers the modifiers if addfb_flags has + // DRM_MODE_FB_MODIFIERS set. We only set that when we've created + // a bo with modifiers, otherwise, we rely on the "no modifiers" + // behavior doing the right thing. + params.flags = 0; + if (drm->allow_addfb2_modifiers() && + params.modifier != DRM_FORMAT_MOD_INVALID) + params.flags |= DRM_MODE_FB_MODIFIERS; + + return AddFramebuffer(std::move(drm), params); +} + DrmFramebuffer::DrmFramebuffer(scoped_refptr<DrmDevice> drm_device, uint32_t framebuffer_id, uint32_t framebuffer_pixel_format,
diff --git a/ui/ozone/platform/drm/gpu/drm_framebuffer.h b/ui/ozone/platform/drm/gpu/drm_framebuffer.h index c089cb3..bb5e6e3 100644 --- a/ui/ozone/platform/drm/gpu/drm_framebuffer.h +++ b/ui/ozone/platform/drm/gpu/drm_framebuffer.h
@@ -15,6 +15,7 @@ namespace ui { class DrmDevice; +class GbmBuffer; // Abstraction for a DRM buffer that can be scanned-out of. class DrmFramebuffer : public base::RefCountedThreadSafe<DrmFramebuffer> { @@ -35,6 +36,10 @@ scoped_refptr<DrmDevice> drm_device, AddFramebufferParams params); + static scoped_refptr<DrmFramebuffer> AddFramebuffer( + scoped_refptr<DrmDevice> drm_device, + const GbmBuffer* buffer); + DrmFramebuffer(scoped_refptr<DrmDevice> drm_device, uint32_t framebuffer_id, uint32_t framebuffer_pixel_format,
diff --git a/ui/ozone/platform/drm/gpu/drm_framebuffer_generator.h b/ui/ozone/platform/drm/gpu/drm_framebuffer_generator.h deleted file mode 100644 index 04d8847..0000000 --- a/ui/ozone/platform/drm/gpu/drm_framebuffer_generator.h +++ /dev/null
@@ -1,31 +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 UI_OZONE_PLATFORM_DRM_GPU_SCANOUT_BUFFER_GENERATOR_H_ -#define UI_OZONE_PLATFORM_DRM_GPU_SCANOUT_BUFFER_GENERATOR_H_ - -#include <vector> - -#include "base/memory/scoped_refptr.h" -#include "ui/gfx/geometry/size.h" - -namespace ui { - -class DrmDevice; -class DrmFramebuffer; - -class DrmFramebufferGenerator { - public: - virtual ~DrmFramebufferGenerator() {} - - virtual scoped_refptr<DrmFramebuffer> Create( - const scoped_refptr<DrmDevice>& drm, - uint32_t format, - const std::vector<uint64_t>& modifiers, - const gfx::Size& size) = 0; -}; - -} // namespace ui - -#endif // UI_OZONE_PLATFORM_DRM_GPU_SCANOUT_BUFFER_GENERATOR_H_
diff --git a/ui/ozone/platform/drm/gpu/drm_overlay_plane.cc b/ui/ozone/platform/drm/gpu/drm_overlay_plane.cc index 558c9b30..87fa16d 100644 --- a/ui/ozone/platform/drm/gpu/drm_overlay_plane.cc +++ b/ui/ozone/platform/drm/gpu/drm_overlay_plane.cc
@@ -53,6 +53,13 @@ DrmOverlayPlane::~DrmOverlayPlane() {} +// static +DrmOverlayPlane DrmOverlayPlane::Error() { + return DrmOverlayPlane(nullptr, 0, gfx::OVERLAY_TRANSFORM_INVALID, + gfx::Rect(), gfx::RectF(), /* enable_blend */ true, + /* gpu_fence */ nullptr); +} + bool DrmOverlayPlane::operator<(const DrmOverlayPlane& plane) const { return std::tie(z_order, display_bounds, crop_rect, plane_transform) < std::tie(plane.z_order, plane.display_bounds, plane.crop_rect,
diff --git a/ui/ozone/platform/drm/gpu/drm_overlay_plane.h b/ui/ozone/platform/drm/gpu/drm_overlay_plane.h index 41824c9..e0dcf10 100644 --- a/ui/ozone/platform/drm/gpu/drm_overlay_plane.h +++ b/ui/ozone/platform/drm/gpu/drm_overlay_plane.h
@@ -39,6 +39,9 @@ DrmOverlayPlane(DrmOverlayPlane&& other); DrmOverlayPlane& operator=(DrmOverlayPlane&& other); + // Returns DrmOverlayPlane will null |buffer| for use as error. + static DrmOverlayPlane Error(); + bool operator<(const DrmOverlayPlane& plane) const; ~DrmOverlayPlane();
diff --git a/ui/ozone/platform/drm/gpu/drm_overlay_validator.cc b/ui/ozone/platform/drm/gpu/drm_overlay_validator.cc index 300aabe..ea0947a 100644 --- a/ui/ozone/platform/drm/gpu/drm_overlay_validator.cc +++ b/ui/ozone/platform/drm/gpu/drm_overlay_validator.cc
@@ -10,10 +10,10 @@ #include "ui/gfx/geometry/size_conversions.h" #include "ui/gfx/gpu_fence.h" #include "ui/ozone/common/linux/drm_util_linux.h" +#include "ui/ozone/common/linux/gbm_buffer.h" #include "ui/ozone/platform/drm/common/drm_util.h" #include "ui/ozone/platform/drm/gpu/drm_device.h" #include "ui/ozone/platform/drm/gpu/drm_framebuffer.h" -#include "ui/ozone/platform/drm/gpu/drm_framebuffer_generator.h" #include "ui/ozone/platform/drm/gpu/drm_window.h" #include "ui/ozone/platform/drm/gpu/hardware_display_controller.h" @@ -25,7 +25,6 @@ const scoped_refptr<DrmDevice>& drm_device, const gfx::Size& size, uint32_t format, - DrmFramebufferGenerator* buffer_generator, std::vector<scoped_refptr<DrmFramebuffer>>* reusable_buffers) { // Check if we can re-use existing buffers. for (const auto& buffer : *reusable_buffers) { @@ -35,22 +34,24 @@ } } - const std::vector<uint64_t> - modifiers; // TODO(dcastagna): use the right modifiers. - scoped_refptr<DrmFramebuffer> drm_framebuffer = - buffer_generator->Create(drm_device, format, modifiers, size); - if (drm_framebuffer) - reusable_buffers->push_back(drm_framebuffer); + // TODO(dcastagna): use the right modifiers. + std::unique_ptr<GbmBuffer> buffer = + drm_device->gbm_device()->CreateBuffer(format, size, GBM_BO_USE_SCANOUT); + if (!buffer) + return nullptr; + scoped_refptr<DrmFramebuffer> drm_framebuffer = + DrmFramebuffer::AddFramebuffer(drm_device, buffer.get()); + if (!drm_framebuffer) + return nullptr; + + reusable_buffers->push_back(drm_framebuffer); return drm_framebuffer; } } // namespace -DrmOverlayValidator::DrmOverlayValidator( - DrmWindow* window, - DrmFramebufferGenerator* buffer_generator) - : window_(window), buffer_generator_(buffer_generator) {} +DrmOverlayValidator::DrmOverlayValidator(DrmWindow* window) : window_(window) {} DrmOverlayValidator::~DrmOverlayValidator() {} @@ -82,8 +83,7 @@ scoped_refptr<DrmFramebuffer> buffer = GetBufferForPageFlipTest( drm, params[i].buffer_size, - GetFourCCFormatFromBufferFormat(params[i].format), buffer_generator_, - &reusable_buffers); + GetFourCCFormatFromBufferFormat(params[i].format), &reusable_buffers); DrmOverlayPlane plane(buffer, params[i].plane_z_order, params[i].transform, params[i].display_rect, params[i].crop_rect,
diff --git a/ui/ozone/platform/drm/gpu/drm_overlay_validator.h b/ui/ozone/platform/drm/gpu/drm_overlay_validator.h index 1304559..5030650 100644 --- a/ui/ozone/platform/drm/gpu/drm_overlay_validator.h +++ b/ui/ozone/platform/drm/gpu/drm_overlay_validator.h
@@ -11,14 +11,12 @@ namespace ui { class DrmWindow; -class DrmFramebufferGenerator; struct OverlayCheck_Params; struct OverlayCheckReturn_Params; class DrmOverlayValidator { public: - DrmOverlayValidator(DrmWindow* window, - DrmFramebufferGenerator* buffer_generator); + DrmOverlayValidator(DrmWindow* window); ~DrmOverlayValidator(); // Tests if configurations |params| are compatible with |window_| and finds @@ -30,7 +28,6 @@ private: DrmWindow* window_; // Not owned. - DrmFramebufferGenerator* buffer_generator_; // Not owned. DISALLOW_COPY_AND_ASSIGN(DrmOverlayValidator); };
diff --git a/ui/ozone/platform/drm/gpu/drm_overlay_validator_unittest.cc b/ui/ozone/platform/drm/gpu/drm_overlay_validator_unittest.cc index 977207d..c2a99d7 100644 --- a/ui/ozone/platform/drm/gpu/drm_overlay_validator_unittest.cc +++ b/ui/ozone/platform/drm/gpu/drm_overlay_validator_unittest.cc
@@ -15,14 +15,16 @@ #include "ui/gfx/gpu_fence.h" #include "ui/ozone/common/gpu/ozone_gpu_message_params.h" #include "ui/ozone/common/linux/drm_util_linux.h" +#include "ui/ozone/common/linux/gbm_buffer.h" #include "ui/ozone/platform/drm/common/drm_util.h" #include "ui/ozone/platform/drm/gpu/crtc_controller.h" #include "ui/ozone/platform/drm/gpu/drm_device_generator.h" #include "ui/ozone/platform/drm/gpu/drm_device_manager.h" +#include "ui/ozone/platform/drm/gpu/drm_framebuffer.h" #include "ui/ozone/platform/drm/gpu/drm_window.h" #include "ui/ozone/platform/drm/gpu/hardware_display_controller.h" #include "ui/ozone/platform/drm/gpu/mock_drm_device.h" -#include "ui/ozone/platform/drm/gpu/mock_drm_framebuffer_generator.h" +#include "ui/ozone/platform/drm/gpu/mock_gbm_device.h" #include "ui/ozone/platform/drm/gpu/screen_manager.h" namespace { @@ -62,8 +64,16 @@ void AddPlane(const ui::OverlayCheck_Params& params); scoped_refptr<ui::DrmFramebuffer> CreateBuffer() { - return buffer_generator_->CreateWithModifier( - drm_, DRM_FORMAT_XRGB8888, DRM_FORMAT_MOD_NONE, primary_rect_.size()); + auto gbm_buffer = drm_->gbm_device()->CreateBuffer( + DRM_FORMAT_XRGB8888, primary_rect_.size(), GBM_BO_USE_SCANOUT); + return ui::DrmFramebuffer::AddFramebuffer(drm_, gbm_buffer.get()); + } + + scoped_refptr<ui::DrmFramebuffer> CreateOverlayBuffer(uint32_t format, + const gfx::Size& size) { + auto gbm_buffer = + drm_->gbm_device()->CreateBuffer(format, size, GBM_BO_USE_SCANOUT); + return ui::DrmFramebuffer::AddFramebuffer(drm_, gbm_buffer.get()); } protected: @@ -79,7 +89,7 @@ std::unique_ptr<base::MessageLoop> message_loop_; scoped_refptr<ui::MockDrmDevice> drm_; - std::unique_ptr<ui::MockDrmFramebufferGenerator> buffer_generator_; + ui::MockGbmDevice* gbm_ = nullptr; std::unique_ptr<ui::ScreenManager> screen_manager_; std::unique_ptr<ui::DrmDeviceManager> drm_device_manager_; ui::DrmWindow* window_; @@ -101,15 +111,16 @@ last_swap_buffers_result_ = gfx::SwapResult::SWAP_FAILED; message_loop_.reset(new base::MessageLoopForUI); - drm_ = new ui::MockDrmDevice; + auto gbm = std::make_unique<ui::MockGbmDevice>(); + gbm_ = gbm.get(); + drm_ = new ui::MockDrmDevice(std::move(gbm)); CrtcState crtc_state = {.planes = { {.formats = {DRM_FORMAT_XRGB8888}}, }}; InitializeDrmState({crtc_state}); - buffer_generator_.reset(new ui::MockDrmFramebufferGenerator()); - screen_manager_.reset(new ui::ScreenManager(buffer_generator_.get())); + screen_manager_.reset(new ui::ScreenManager()); screen_manager_->AddDisplayController(drm_, kCrtcIdBase, kConnectorIdBase); screen_manager_->ConfigureDisplayController( drm_, kCrtcIdBase, kConnectorIdBase, gfx::Point(), kDefaultMode); @@ -118,13 +129,12 @@ std::unique_ptr<ui::DrmWindow> window(new ui::DrmWindow( kDefaultWidgetHandle, drm_device_manager_.get(), screen_manager_.get())); - window->Initialize(buffer_generator_.get()); + window->Initialize(); window->SetBounds( gfx::Rect(gfx::Size(kDefaultMode.hdisplay, kDefaultMode.vdisplay))); screen_manager_->AddWindow(kDefaultWidgetHandle, std::move(window)); window_ = screen_manager_->GetWindow(kDefaultWidgetHandle); - overlay_validator_.reset( - new ui::DrmOverlayValidator(window_, buffer_generator_.get())); + overlay_validator_.reset(new ui::DrmOverlayValidator(window_)); overlay_rect_ = gfx::Rect(0, 0, kDefaultMode.hdisplay / 2, kDefaultMode.vdisplay / 2); @@ -210,9 +220,9 @@ void DrmOverlayValidatorTest::AddPlane(const ui::OverlayCheck_Params& params) { scoped_refptr<ui::DrmDevice> drm = window_->GetController()->GetDrmDevice(); - scoped_refptr<ui::DrmFramebuffer> drm_framebuffer = buffer_generator_->Create( - drm, ui::GetFourCCFormatFromBufferFormat(params.format), {}, - params.buffer_size); + + scoped_refptr<ui::DrmFramebuffer> drm_framebuffer = CreateOverlayBuffer( + ui::GetFourCCFormatFromBufferFormat(params.format), params.buffer_size); plane_list_.push_back(ui::DrmOverlayPlane( std::move(drm_framebuffer), params.plane_z_order, params.transform, params.display_rect, params.crop_rect, true, nullptr)); @@ -469,7 +479,7 @@ TEST_F(DrmOverlayValidatorTest, RejectBufferAllocationFail) { // Buffer allocation for scanout might fail. // In that case we should reject the overlay candidate. - buffer_generator_->set_allocation_failure(true); + gbm_->set_allocation_failure(true); std::vector<ui::OverlayCheckReturn_Params> returns = overlay_validator_->TestPageFlip(overlay_params_,
diff --git a/ui/ozone/platform/drm/gpu/drm_thread.cc b/ui/ozone/platform/drm/gpu/drm_thread.cc index 62567655..a16aa818 100644 --- a/ui/ozone/platform/drm/gpu/drm_thread.cc +++ b/ui/ozone/platform/drm/gpu/drm_thread.cc
@@ -22,7 +22,6 @@ #include "ui/ozone/platform/drm/gpu/drm_buffer.h" #include "ui/ozone/platform/drm/gpu/drm_device_generator.h" #include "ui/ozone/platform/drm/gpu/drm_device_manager.h" -#include "ui/ozone/platform/drm/gpu/drm_framebuffer_generator.h" #include "ui/ozone/platform/drm/gpu/drm_gpu_display_manager.h" #include "ui/ozone/platform/drm/gpu/drm_window.h" #include "ui/ozone/platform/drm/gpu/drm_window_proxy.h" @@ -36,34 +35,6 @@ namespace { -scoped_refptr<DrmFramebuffer> AddFramebuffersForBuffer( - const scoped_refptr<DrmDevice>& drm, - GbmBuffer* buffer) { - gfx::Size size = buffer->GetSize(); - DrmFramebuffer::AddFramebufferParams params; - params.format = buffer->GetFormat(); - params.modifier = buffer->GetFormatModifier(); - params.width = size.width(); - params.height = size.height(); - params.num_planes = buffer->GetNumPlanes(); - for (size_t i = 0; i < params.num_planes; ++i) { - params.handles[i] = buffer->GetPlaneHandle(i); - params.strides[i] = buffer->GetPlaneStride(i); - params.offsets[i] = buffer->GetPlaneOffset(i); - } - - // AddFramebuffer2 only considers the modifiers if addfb_flags has - // DRM_MODE_FB_MODIFIERS set. We only set that when we've created - // a bo with modifiers, otherwise, we rely on the "no modifiers" - // behavior doing the right thing. - params.flags = 0; - if (drm->allow_addfb2_modifiers() && - params.modifier != DRM_FORMAT_MOD_INVALID) - params.flags |= DRM_MODE_FB_MODIFIERS; - - return DrmFramebuffer::AddFramebuffer(drm, params); -} - uint32_t BufferUsageToGbmFlags(gfx::BufferUsage usage) { switch (usage) { case gfx::BufferUsage::GPU_READ: @@ -95,18 +66,15 @@ const std::vector<uint64_t>& modifiers, std::unique_ptr<GbmBuffer>* out_buffer, scoped_refptr<DrmFramebuffer>* out_framebuffer) { - std::unique_ptr<GbmBuffer> buffer; - if (modifiers.empty()) - buffer = drm->gbm_device()->CreateBuffer(fourcc_format, size, flags); - else - buffer = drm->gbm_device()->CreateBufferWithModifiers(fourcc_format, size, - flags, modifiers); + std::unique_ptr<GbmBuffer> buffer = + drm->gbm_device()->CreateBufferWithModifiers(fourcc_format, size, flags, + modifiers); if (!buffer) return; scoped_refptr<DrmFramebuffer> framebuffer; if (flags & GBM_BO_USE_SCANOUT) { - framebuffer = AddFramebuffersForBuffer(drm, buffer.get()); + framebuffer = DrmFramebuffer::AddFramebuffer(drm, buffer.get()); if (!framebuffer) return; } @@ -115,36 +83,6 @@ *out_framebuffer = std::move(framebuffer); } -class GbmBufferGenerator : public DrmFramebufferGenerator { - public: - GbmBufferGenerator() {} - ~GbmBufferGenerator() override {} - - // DrmFramebufferGenerator: - scoped_refptr<DrmFramebuffer> Create(const scoped_refptr<DrmDevice>& drm, - uint32_t format, - const std::vector<uint64_t>& modifiers, - const gfx::Size& size) override { - std::unique_ptr<GbmBuffer> buffer; - - if (modifiers.size() > 0) { - buffer = drm->gbm_device()->CreateBufferWithModifiers( - format, size, GBM_BO_USE_SCANOUT, modifiers); - } else { - buffer = - drm->gbm_device()->CreateBuffer(format, size, GBM_BO_USE_SCANOUT); - } - - if (!buffer) - return nullptr; - - return AddFramebuffersForBuffer(drm, buffer.get()); - } - - protected: - DISALLOW_COPY_AND_ASSIGN(GbmBufferGenerator); -}; - class GbmDeviceGenerator : public DrmDeviceGenerator { public: GbmDeviceGenerator() {} @@ -193,8 +131,7 @@ void DrmThread::Init() { device_manager_.reset( new DrmDeviceManager(std::make_unique<GbmDeviceGenerator>())); - buffer_generator_.reset(new GbmBufferGenerator()); - screen_manager_.reset(new ScreenManager(buffer_generator_.get())); + screen_manager_.reset(new ScreenManager()); display_manager_.reset( new DrmGpuDisplayManager(screen_manager_.get(), device_manager_.get())); @@ -264,7 +201,7 @@ if (buffer->GetFlags() & GBM_BO_USE_SCANOUT) { // NB: This is not required to succeed; framebuffers are added for // imported buffers on a best effort basis. - framebuffer = AddFramebuffersForBuffer(drm, buffer.get()); + framebuffer = DrmFramebuffer::AddFramebuffer(drm, buffer.get()); } *out_buffer = std::move(buffer); @@ -328,7 +265,7 @@ void DrmThread::CreateWindow(gfx::AcceleratedWidget widget) { std::unique_ptr<DrmWindow> window( new DrmWindow(widget, device_manager_.get(), screen_manager_.get())); - window->Initialize(buffer_generator_.get()); + window->Initialize(); screen_manager_->AddWindow(widget, std::move(window)); }
diff --git a/ui/ozone/platform/drm/gpu/drm_thread.h b/ui/ozone/platform/drm/gpu/drm_thread.h index b1c954eb..79685b1 100644 --- a/ui/ozone/platform/drm/gpu/drm_thread.h +++ b/ui/ozone/platform/drm/gpu/drm_thread.h
@@ -44,7 +44,6 @@ class DrmFramebuffer; class DrmGpuDisplayManager; class GbmBuffer; -class DrmFramebufferGenerator; class ScreenManager; struct DrmOverlayPlane; @@ -155,7 +154,6 @@ std::vector<DrmOverlayPlane> planes); std::unique_ptr<DrmDeviceManager> device_manager_; - std::unique_ptr<DrmFramebufferGenerator> buffer_generator_; std::unique_ptr<ScreenManager> screen_manager_; std::unique_ptr<DrmGpuDisplayManager> display_manager_;
diff --git a/ui/ozone/platform/drm/gpu/drm_window.cc b/ui/ozone/platform/drm/gpu/drm_window.cc index 1c0dc3dc..04f31690 100644 --- a/ui/ozone/platform/drm/gpu/drm_window.cc +++ b/ui/ozone/platform/drm/gpu/drm_window.cc
@@ -37,12 +37,11 @@ DrmWindow::~DrmWindow() { } -void DrmWindow::Initialize(DrmFramebufferGenerator* buffer_generator) { +void DrmWindow::Initialize() { TRACE_EVENT1("drm", "DrmWindow::Initialize", "widget", widget_); device_manager_->UpdateDrmDevice(widget_, nullptr); - overlay_validator_ = - std::make_unique<DrmOverlayValidator>(this, buffer_generator); + overlay_validator_ = std::make_unique<DrmOverlayValidator>(this); } void DrmWindow::Shutdown() {
diff --git a/ui/ozone/platform/drm/gpu/drm_window.h b/ui/ozone/platform/drm/gpu/drm_window.h index 236eefa0..b44d416 100644 --- a/ui/ozone/platform/drm/gpu/drm_window.h +++ b/ui/ozone/platform/drm/gpu/drm_window.h
@@ -33,7 +33,6 @@ class HardwareDisplayController; struct OverlayCheck_Params; struct OverlayCheckReturn_Params; -class DrmFramebufferGenerator; class ScreenManager; // The GPU object representing a window. @@ -55,7 +54,7 @@ gfx::Rect bounds() const { return bounds_; } - void Initialize(DrmFramebufferGenerator* buffer_generator); + void Initialize(); void Shutdown();
diff --git a/ui/ozone/platform/drm/gpu/drm_window_unittest.cc b/ui/ozone/platform/drm/gpu/drm_window_unittest.cc index fd5d379c..fdd4af7 100644 --- a/ui/ozone/platform/drm/gpu/drm_window_unittest.cc +++ b/ui/ozone/platform/drm/gpu/drm_window_unittest.cc
@@ -21,12 +21,13 @@ #include "third_party/skia/include/core/SkSurface.h" #include "ui/gfx/gpu_fence.h" #include "ui/gfx/presentation_feedback.h" +#include "ui/ozone/common/linux/gbm_buffer.h" #include "ui/ozone/platform/drm/gpu/drm_device_generator.h" #include "ui/ozone/platform/drm/gpu/drm_device_manager.h" #include "ui/ozone/platform/drm/gpu/drm_framebuffer.h" #include "ui/ozone/platform/drm/gpu/hardware_display_controller.h" #include "ui/ozone/platform/drm/gpu/mock_drm_device.h" -#include "ui/ozone/platform/drm/gpu/mock_dumb_buffer_generator.h" +#include "ui/ozone/platform/drm/gpu/mock_gbm_device.h" #include "ui/ozone/platform/drm/gpu/screen_manager.h" #include "ui/ozone/public/surface_ozone_canvas.h" @@ -85,7 +86,6 @@ protected: std::unique_ptr<base::MessageLoop> message_loop_; scoped_refptr<ui::MockDrmDevice> drm_; - std::unique_ptr<ui::MockDumbBufferGenerator> buffer_generator_; std::unique_ptr<ui::ScreenManager> screen_manager_; std::unique_ptr<ui::DrmDeviceManager> drm_device_manager_; @@ -102,9 +102,9 @@ last_swap_buffers_result_ = gfx::SwapResult::SWAP_FAILED; message_loop_.reset(new base::MessageLoopForUI); - drm_ = new ui::MockDrmDevice; - buffer_generator_.reset(new ui::MockDumbBufferGenerator()); - screen_manager_.reset(new ui::ScreenManager(buffer_generator_.get())); + auto gbm_device = std::make_unique<ui::MockGbmDevice>(); + drm_ = new ui::MockDrmDevice(std::move(gbm_device)); + screen_manager_.reset(new ui::ScreenManager()); screen_manager_->AddDisplayController(drm_, kDefaultCrtc, kDefaultConnector); screen_manager_->ConfigureDisplayController( drm_, kDefaultCrtc, kDefaultConnector, gfx::Point(), kDefaultMode); @@ -113,7 +113,7 @@ std::unique_ptr<ui::DrmWindow> window(new ui::DrmWindow( kDefaultWidgetHandle, drm_device_manager_.get(), screen_manager_.get())); - window->Initialize(buffer_generator_.get()); + window->Initialize(); window->SetBounds( gfx::Rect(gfx::Size(kDefaultMode.hdisplay, kDefaultMode.vdisplay))); screen_manager_->AddWindow(kDefaultWidgetHandle, std::move(window)); @@ -159,7 +159,9 @@ gfx::Point(4, 2), 0); // Add another device. - scoped_refptr<ui::MockDrmDevice> drm = new ui::MockDrmDevice; + auto gbm_device = std::make_unique<ui::MockGbmDevice>(); + scoped_refptr<ui::MockDrmDevice> drm = + new ui::MockDrmDevice(std::move(gbm_device)); screen_manager_->AddDisplayController(drm, kDefaultCrtc, kDefaultConnector); screen_manager_->ConfigureDisplayController( drm, kDefaultCrtc, kDefaultConnector, @@ -177,11 +179,13 @@ TEST_F(DrmWindowTest, CheckDeathOnFailedSwap) { const gfx::Size window_size(6, 4); - ui::MockDumbBufferGenerator buffer_generator; ui::DrmWindow* window = screen_manager_->GetWindow(kDefaultWidgetHandle); - ui::DrmOverlayPlane plane( - buffer_generator.Create(drm_, DRM_FORMAT_XRGB8888, {}, window_size), - nullptr); + + std::unique_ptr<ui::GbmBuffer> buffer = drm_->gbm_device()->CreateBuffer( + DRM_FORMAT_XRGB8888, window_size, GBM_BO_USE_SCANOUT); + scoped_refptr<ui::DrmFramebuffer> framebuffer = + ui::DrmFramebuffer::AddFramebuffer(drm_, buffer.get()); + ui::DrmOverlayPlane plane(framebuffer, nullptr); drm_->set_page_flip_expectation(false);
diff --git a/ui/ozone/platform/drm/gpu/hardware_display_controller_unittest.cc b/ui/ozone/platform/drm/gpu/hardware_display_controller_unittest.cc index 0a4c75cb..662d7232 100644 --- a/ui/ozone/platform/drm/gpu/hardware_display_controller_unittest.cc +++ b/ui/ozone/platform/drm/gpu/hardware_display_controller_unittest.cc
@@ -13,12 +13,14 @@ #include "ui/gfx/gpu_fence.h" #include "ui/gfx/native_pixmap.h" #include "ui/gfx/presentation_feedback.h" +#include "ui/ozone/common/linux/gbm_buffer.h" #include "ui/ozone/platform/drm/gpu/crtc_controller.h" +#include "ui/ozone/platform/drm/gpu/drm_framebuffer.h" #include "ui/ozone/platform/drm/gpu/drm_gpu_util.h" #include "ui/ozone/platform/drm/gpu/hardware_display_controller.h" #include "ui/ozone/platform/drm/gpu/hardware_display_plane.h" #include "ui/ozone/platform/drm/gpu/mock_drm_device.h" -#include "ui/ozone/platform/drm/gpu/mock_drm_framebuffer_generator.h" +#include "ui/ozone/platform/drm/gpu/mock_gbm_device.h" namespace { @@ -57,17 +59,18 @@ const std::string& property_name); scoped_refptr<ui::DrmFramebuffer> CreateBuffer() { - return buffer_generator_->CreateWithModifier( - drm_, DRM_FORMAT_XRGB8888, DRM_FORMAT_MOD_NONE, kDefaultModeSize); + std::unique_ptr<ui::GbmBuffer> buffer = drm_->gbm_device()->CreateBuffer( + DRM_FORMAT_XRGB8888, kDefaultModeSize, GBM_BO_USE_SCANOUT); + return ui::DrmFramebuffer::AddFramebuffer(drm_, buffer.get()); } scoped_refptr<ui::DrmFramebuffer> CreateOverlayBuffer() { - return buffer_generator_->CreateWithModifier( - drm_, DRM_FORMAT_XRGB8888, DRM_FORMAT_MOD_NONE, kOverlaySize); + std::unique_ptr<ui::GbmBuffer> buffer = drm_->gbm_device()->CreateBuffer( + DRM_FORMAT_XRGB8888, kOverlaySize, GBM_BO_USE_SCANOUT); + return ui::DrmFramebuffer::AddFramebuffer(drm_, buffer.get()); } protected: - std::unique_ptr<ui::MockDrmFramebufferGenerator> buffer_generator_; std::unique_ptr<ui::HardwareDisplayController> controller_; scoped_refptr<ui::MockDrmDevice> drm_; @@ -83,10 +86,10 @@ page_flips_ = 0; last_swap_result_ = gfx::SwapResult::SWAP_FAILED; - drm_ = new ui::MockDrmDevice; + auto gbm_device = std::make_unique<ui::MockGbmDevice>(); + drm_ = new ui::MockDrmDevice(std::move(gbm_device)); InitializeDrmDevice(/* use_atomic= */ true); - buffer_generator_.reset(new ui::MockDrmFramebufferGenerator()); controller_.reset(new ui::HardwareDisplayController( std::unique_ptr<ui::CrtcController>( new ui::CrtcController(drm_.get(), kPrimaryCrtc, kPrimaryConnector)),
diff --git a/ui/ozone/platform/drm/gpu/hardware_display_plane_manager_unittest.cc b/ui/ozone/platform/drm/gpu/hardware_display_plane_manager_unittest.cc index 7944c60..177a262 100644 --- a/ui/ozone/platform/drm/gpu/hardware_display_plane_manager_unittest.cc +++ b/ui/ozone/platform/drm/gpu/hardware_display_plane_manager_unittest.cc
@@ -17,13 +17,15 @@ #include "ui/display/types/gamma_ramp_rgb_entry.h" #include "ui/gfx/gpu_fence.h" #include "ui/gfx/gpu_fence_handle.h" +#include "ui/ozone/common/linux/gbm_buffer.h" #include "ui/ozone/platform/drm/gpu/crtc_controller.h" +#include "ui/ozone/platform/drm/gpu/drm_framebuffer.h" #include "ui/ozone/platform/drm/gpu/drm_gpu_util.h" #include "ui/ozone/platform/drm/gpu/hardware_display_plane_atomic.h" #include "ui/ozone/platform/drm/gpu/hardware_display_plane_manager_atomic.h" #include "ui/ozone/platform/drm/gpu/hardware_display_plane_manager_legacy.h" #include "ui/ozone/platform/drm/gpu/mock_drm_device.h" -#include "ui/ozone/platform/drm/gpu/mock_drm_framebuffer_generator.h" +#include "ui/ozone/platform/drm/gpu/mock_gbm_device.h" namespace { @@ -62,21 +64,20 @@ void SetUp() override; scoped_refptr<ui::DrmFramebuffer> CreateBuffer(const gfx::Size& size) { - return buffer_generator_->CreateWithModifier(fake_drm_, DRM_FORMAT_XRGB8888, - DRM_FORMAT_MOD_NONE, size); + return CreateBufferWithFormat(size, DRM_FORMAT_XRGB8888); } scoped_refptr<ui::DrmFramebuffer> CreateBufferWithFormat( const gfx::Size& size, uint32_t format) { - return buffer_generator_->CreateWithModifier(fake_drm_, format, - DRM_FORMAT_MOD_NONE, size); + std::unique_ptr<ui::GbmBuffer> buffer = + fake_drm_->gbm_device()->CreateBuffer(format, size, GBM_BO_USE_SCANOUT); + return ui::DrmFramebuffer::AddFramebuffer(fake_drm_, buffer.get()); } protected: ui::HardwareDisplayPlaneList state_; scoped_refptr<ui::DrmFramebuffer> fake_buffer_; - std::unique_ptr<ui::MockDrmFramebufferGenerator> buffer_generator_; scoped_refptr<ui::MockDrmDevice> fake_drm_; std::vector<ui::MockDrmDevice::CrtcProperties> crtc_properties_; @@ -91,9 +92,9 @@ void HardwareDisplayPlaneManagerTest::SetUp() { use_atomic_ = GetParam(); - buffer_generator_.reset(new ui::MockDrmFramebufferGenerator()); - fake_drm_ = new ui::MockDrmDevice; + auto gbm_device = std::make_unique<ui::MockGbmDevice>(); + fake_drm_ = new ui::MockDrmDevice(std::move(gbm_device)); fake_drm_->SetPropertyBlob(ui::MockDrmDevice::AllocateInFormatsBlob( kInFormatsBlobPropId, {DRM_FORMAT_XRGB8888}, {})); @@ -298,7 +299,7 @@ TEST_P(HardwareDisplayPlaneManagerLegacyTest, CheckFramebufferFormatMatch) { ui::DrmOverlayPlaneList assigns; scoped_refptr<ui::DrmFramebuffer> buffer = - CreateBufferWithFormat(kDefaultBufferSize, DRM_FORMAT_NV12); + CreateBufferWithFormat(kDefaultBufferSize, DRM_FORMAT_UYVY); assigns.push_back(ui::DrmOverlayPlane(buffer, nullptr)); InitializeDrmState(/*crtc_count=*/2, /*planes_per_crtc=*/1); @@ -782,8 +783,8 @@ HardwareDisplayPlaneManagerPlanesReadyTest() {} void SetUp() override { - fake_drm_ = new ui::MockDrmDevice; - buffer_generator_.reset(new ui::MockDrmFramebufferGenerator()); + auto gbm_device = std::make_unique<ui::MockGbmDevice>(); + fake_drm_ = new ui::MockDrmDevice(std::move(gbm_device)); drm_framebuffer_ = CreateBuffer(kDefaultBufferSize); planes_without_fences_ = CreatePlanesWithoutFences(); planes_with_fences_ = CreatePlanesWithFences(); @@ -794,8 +795,10 @@ void RequestPlanesReady(ui::DrmOverlayPlaneList planes); scoped_refptr<ui::DrmFramebuffer> CreateBuffer(const gfx::Size& size) { - return buffer_generator_->CreateWithModifier(fake_drm_, DRM_FORMAT_XRGB8888, - DRM_FORMAT_MOD_NONE, size); + std::unique_ptr<ui::GbmBuffer> buffer = + fake_drm_->gbm_device()->CreateBuffer(DRM_FORMAT_XRGB8888, size, + GBM_BO_USE_SCANOUT); + return ui::DrmFramebuffer::AddFramebuffer(fake_drm_, buffer.get()); } ui::DrmOverlayPlaneList CreatePlanesWithoutFences() { @@ -817,7 +820,6 @@ } scoped_refptr<ui::MockDrmDevice> fake_drm_; - std::unique_ptr<ui::MockDrmFramebufferGenerator> buffer_generator_; std::unique_ptr<ui::HardwareDisplayPlaneManager> plane_manager_; bool callback_called = false; base::test::ScopedTaskEnvironment task_env_{ @@ -926,24 +928,26 @@ TEST(HardwareDisplayPlaneManagerAtomic, EnableBlend) { auto plane_manager = std::make_unique<ui::HardwareDisplayPlaneManagerAtomic>(); - auto drm_device = base::MakeRefCounted<ui::MockDrmDevice>(); - auto buffer_generator = std::make_unique<ui::MockDrmFramebufferGenerator>(); + auto gbm_device = std::make_unique<ui::MockGbmDevice>(); + auto drm_device = + base::MakeRefCounted<ui::MockDrmDevice>(std::move(gbm_device)); ui::HardwareDisplayPlaneList plane_list; HardwareDisplayPlaneAtomicMock hw_plane; - scoped_refptr<ui::DrmFramebuffer> buffer = - buffer_generator->CreateWithModifier( - drm_device.get(), DRM_FORMAT_XRGB8888, DRM_FORMAT_MOD_NONE, - kDefaultBufferSize); - ui::DrmOverlayPlane overlay(buffer, nullptr); + std::unique_ptr<ui::GbmBuffer> buffer = + drm_device->gbm_device()->CreateBuffer( + DRM_FORMAT_XRGB8888, kDefaultBufferSize, GBM_BO_USE_SCANOUT); + scoped_refptr<ui::DrmFramebuffer> framebuffer = + ui::DrmFramebuffer::AddFramebuffer(drm_device, buffer.get()); + ui::DrmOverlayPlane overlay(framebuffer, nullptr); overlay.enable_blend = true; plane_manager->SetPlaneData(&plane_list, &hw_plane, overlay, 1, gfx::Rect(), nullptr); - EXPECT_EQ(hw_plane.framebuffer(), buffer->framebuffer_id()); + EXPECT_EQ(hw_plane.framebuffer(), framebuffer->framebuffer_id()); overlay.enable_blend = false; plane_manager->SetPlaneData(&plane_list, &hw_plane, overlay, 1, gfx::Rect(), nullptr); - EXPECT_EQ(hw_plane.framebuffer(), buffer->opaque_framebuffer_id()); + EXPECT_EQ(hw_plane.framebuffer(), framebuffer->opaque_framebuffer_id()); } } // namespace
diff --git a/ui/ozone/platform/drm/gpu/mock_drm_device.cc b/ui/ozone/platform/drm/gpu/mock_drm_device.cc index abdc7adc..4b7f5a46 100644 --- a/ui/ozone/platform/drm/gpu/mock_drm_device.cc +++ b/ui/ozone/platform/drm/gpu/mock_drm_device.cc
@@ -73,11 +73,11 @@ default; MockDrmDevice::PlaneProperties::~PlaneProperties() = default; -MockDrmDevice::MockDrmDevice() +MockDrmDevice::MockDrmDevice(std::unique_ptr<GbmDevice> gbm_device) : DrmDevice(base::FilePath(), base::File(), true /* is_primary_device */, - nullptr), + std::move(gbm_device)), get_crtc_call_count_(0), set_crtc_call_count_(0), restore_crtc_call_count_(0),
diff --git a/ui/ozone/platform/drm/gpu/mock_drm_device.h b/ui/ozone/platform/drm/gpu/mock_drm_device.h index 95ad0398..2e705d0 100644 --- a/ui/ozone/platform/drm/gpu/mock_drm_device.h +++ b/ui/ozone/platform/drm/gpu/mock_drm_device.h
@@ -44,7 +44,7 @@ std::vector<DrmDevice::Property> properties; }; - MockDrmDevice(); + MockDrmDevice(std::unique_ptr<GbmDevice> gbm_device); static ScopedDrmPropertyBlobPtr AllocateInFormatsBlob( uint32_t id,
diff --git a/ui/ozone/platform/drm/gpu/mock_drm_framebuffer_generator.cc b/ui/ozone/platform/drm/gpu/mock_drm_framebuffer_generator.cc deleted file mode 100644 index 41fb7ba..0000000 --- a/ui/ozone/platform/drm/gpu/mock_drm_framebuffer_generator.cc +++ /dev/null
@@ -1,53 +0,0 @@ -// Copyright 2015 The Chromium Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -#include "ui/ozone/platform/drm/gpu/mock_drm_framebuffer_generator.h" - -#include <drm_fourcc.h> - -#include "ui/ozone/platform/drm/common/drm_util.h" -#include "ui/ozone/platform/drm/gpu/drm_device.h" - -namespace ui { - -namespace { - -uint32_t g_current_mock_buffer_handle = 0x1111; - -} // namespace - -MockDrmFramebufferGenerator::MockDrmFramebufferGenerator() {} - -MockDrmFramebufferGenerator::~MockDrmFramebufferGenerator() {} - -scoped_refptr<DrmFramebuffer> MockDrmFramebufferGenerator::Create( - const scoped_refptr<DrmDevice>& drm, - uint32_t format, - const std::vector<uint64_t>& modifiers, - const gfx::Size& size) { - return CreateWithModifier( - drm, format, modifiers.empty() ? DRM_FORMAT_MOD_NONE : modifiers.front(), - size); -} - -scoped_refptr<DrmFramebuffer> MockDrmFramebufferGenerator::CreateWithModifier( - const scoped_refptr<DrmDevice>& drm, - uint32_t format, - uint64_t modifier, - const gfx::Size& size) { - if (allocation_failure_) - return nullptr; - - DrmFramebuffer::AddFramebufferParams params; - params.format = format; - params.modifier = modifier; - params.width = size.width(); - params.height = size.height(); - params.num_planes = 1; - params.handles[0] = g_current_mock_buffer_handle++; - - return DrmFramebuffer::AddFramebuffer(drm, params); -} - -} // namespace ui
diff --git a/ui/ozone/platform/drm/gpu/mock_drm_framebuffer_generator.h b/ui/ozone/platform/drm/gpu/mock_drm_framebuffer_generator.h deleted file mode 100644 index 4b3e8cb..0000000 --- a/ui/ozone/platform/drm/gpu/mock_drm_framebuffer_generator.h +++ /dev/null
@@ -1,44 +0,0 @@ -// Copyright 2015 The Chromium Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -#ifndef UI_OZONE_PLATFORM_DRM_GPU_MOCK_SCANOUT_BUFFER_GENERATOR_H_ -#define UI_OZONE_PLATFORM_DRM_GPU_MOCK_SCANOUT_BUFFER_GENERATOR_H_ - -#include "base/macros.h" - -#include "ui/ozone/platform/drm/gpu/drm_framebuffer.h" -#include "ui/ozone/platform/drm/gpu/drm_framebuffer_generator.h" - -namespace ui { - -class MockDrmFramebufferGenerator : public DrmFramebufferGenerator { - public: - MockDrmFramebufferGenerator(); - ~MockDrmFramebufferGenerator() override; - - // DrmFramebufferGenerator: - scoped_refptr<DrmFramebuffer> Create(const scoped_refptr<DrmDevice>& drm, - uint32_t format, - const std::vector<uint64_t>& modifiers, - const gfx::Size& size) override; - - scoped_refptr<DrmFramebuffer> CreateWithModifier( - const scoped_refptr<DrmDevice>& drm, - uint32_t format, - uint64_t modifier, - const gfx::Size& size); - - void set_allocation_failure(bool allocation_failure) { - allocation_failure_ = allocation_failure; - } - - private: - DISALLOW_COPY_AND_ASSIGN(MockDrmFramebufferGenerator); - - bool allocation_failure_ = false; -}; - -} // namespace ui - -#endif // UI_OZONE_PLATFORM_DRM_GPU_MOCK_SCANOUT_BUFFER_GENERATOR_H_
diff --git a/ui/ozone/platform/drm/gpu/mock_dumb_buffer_generator.cc b/ui/ozone/platform/drm/gpu/mock_dumb_buffer_generator.cc deleted file mode 100644 index 2934559..0000000 --- a/ui/ozone/platform/drm/gpu/mock_dumb_buffer_generator.cc +++ /dev/null
@@ -1,69 +0,0 @@ -// Copyright 2015 The Chromium Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -#include "ui/ozone/platform/drm/gpu/mock_dumb_buffer_generator.h" - -#include "third_party/skia/include/core/SkImageInfo.h" -#include "ui/ozone/platform/drm/gpu/drm_buffer.h" -#include "ui/ozone/platform/drm/gpu/drm_device.h" - -namespace ui { - -namespace { - -uint32_t GetFourCCCodeForSkColorType(SkColorType type) { - switch (type) { - case kUnknown_SkColorType: - case kAlpha_8_SkColorType: - return 0; - case kRGB_565_SkColorType: - return DRM_FORMAT_RGB565; - case kARGB_4444_SkColorType: - return DRM_FORMAT_ARGB4444; - case kN32_SkColorType: - return DRM_FORMAT_ARGB8888; - default: - NOTREACHED(); - return 0; - } -} - -scoped_refptr<DrmFramebuffer> AddFramebufferForDumbBuffer( - const scoped_refptr<DrmDevice>& drm, - uint32_t handle, - uint32_t stride, - const SkImageInfo& info) { - DrmFramebuffer::AddFramebufferParams params; - params.flags = 0; - params.format = GetFourCCCodeForSkColorType(info.colorType()); - params.modifier = DRM_FORMAT_MOD_INVALID; - params.width = info.width(); - params.height = info.height(); - params.num_planes = 1; - params.handles[0] = handle; - params.strides[0] = stride; - return DrmFramebuffer::AddFramebuffer(drm, params); -} - -} // namespace - -MockDumbBufferGenerator::MockDumbBufferGenerator() {} - -MockDumbBufferGenerator::~MockDumbBufferGenerator() {} - -scoped_refptr<DrmFramebuffer> MockDumbBufferGenerator::Create( - const scoped_refptr<DrmDevice>& drm, - uint32_t format, - const std::vector<uint64_t>& modifiers, - const gfx::Size& size) { - std::unique_ptr<DrmBuffer> buffer(new DrmBuffer(drm)); - SkImageInfo info = SkImageInfo::MakeN32Premul(size.width(), size.height()); - if (!buffer->Initialize(info)) - return NULL; - - return AddFramebufferForDumbBuffer(drm, buffer->GetHandle(), buffer->stride(), - info); -} - -} // namespace ui
diff --git a/ui/ozone/platform/drm/gpu/mock_dumb_buffer_generator.h b/ui/ozone/platform/drm/gpu/mock_dumb_buffer_generator.h deleted file mode 100644 index 9fe8f4d..0000000 --- a/ui/ozone/platform/drm/gpu/mock_dumb_buffer_generator.h +++ /dev/null
@@ -1,34 +0,0 @@ -// Copyright 2015 The Chromium Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -#ifndef UI_OZONE_PLATFORM_DRM_GPU_MOCK_DUMB_BUFFER_GENERATOR_H_ -#define UI_OZONE_PLATFORM_DRM_GPU_MOCK_DUMB_BUFFER_GENERATOR_H_ - -#include "base/macros.h" - -#include "ui/ozone/platform/drm/gpu/drm_framebuffer.h" -#include "ui/ozone/platform/drm/gpu/drm_framebuffer_generator.h" - -namespace ui { - -class DrmFramebuffer; - -class MockDumbBufferGenerator : public DrmFramebufferGenerator { - public: - MockDumbBufferGenerator(); - ~MockDumbBufferGenerator() override; - - // DrmFramebufferGenerator: - scoped_refptr<DrmFramebuffer> Create(const scoped_refptr<DrmDevice>& drm, - uint32_t format, - const std::vector<uint64_t>& modifiers, - const gfx::Size& size) override; - - private: - DISALLOW_COPY_AND_ASSIGN(MockDumbBufferGenerator); -}; - -} // namespace ui - -#endif // UI_OZONE_PLATFORM_DRM_GPU_MOCK_DUMB_BUFFER_GENERATOR_H_
diff --git a/ui/ozone/platform/drm/gpu/mock_gbm_device.cc b/ui/ozone/platform/drm/gpu/mock_gbm_device.cc new file mode 100644 index 0000000..d7b298f --- /dev/null +++ b/ui/ozone/platform/drm/gpu/mock_gbm_device.cc
@@ -0,0 +1,161 @@ +// 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 "ui/ozone/platform/drm/gpu/mock_gbm_device.h" + +#include <drm_fourcc.h> +#include <xf86drm.h> + +#include "base/logging.h" +#include "base/numerics/safe_math.h" +#include "testing/gtest/include/gtest/gtest.h" +#include "ui/ozone/common/linux/drm_util_linux.h" +#include "ui/ozone/common/linux/gbm_buffer.h" + +namespace ui { +namespace { + +class MockGbmBuffer final : public ui::GbmBuffer { + public: + MockGbmBuffer(uint32_t format, + uint32_t flags, + uint64_t modifier, + const gfx::Size& size, + std::vector<gfx::NativePixmapPlane> planes, + std::vector<uint32_t> handles) + : format_(format), + format_modifier_(modifier), + flags_(flags), + size_(size), + planes_(std::move(planes)), + handles_(std::move(handles)) {} + + ~MockGbmBuffer() override {} + + uint32_t GetFormat() const override { return format_; } + uint64_t GetFormatModifier() const override { return format_modifier_; } + uint32_t GetFlags() const override { return flags_; } + size_t GetFdCount() const override { return 0; } + gfx::Size GetSize() const override { return size_; } + gfx::BufferFormat GetBufferFormat() const override { + return ui::GetBufferFormatFromFourCCFormat(format_); + } + bool AreFdsValid() const override { return false; } + size_t GetNumPlanes() const override { return planes_.size(); } + int GetPlaneFd(size_t plane) const override { + NOTREACHED(); + return -1; + } + int GetPlaneStride(size_t plane) const override { + DCHECK_LT(plane, planes_.size()); + return planes_[plane].stride; + } + int GetPlaneOffset(size_t plane) const override { + DCHECK_LT(plane, planes_.size()); + return planes_[plane].offset; + } + size_t GetPlaneSize(size_t plane) const override { + DCHECK_LT(plane, planes_.size()); + return planes_[plane].size; + } + uint32_t GetPlaneHandle(size_t plane) const override { + DCHECK_LT(plane, planes_.size()); + return handles_[plane]; + } + uint32_t GetHandle() const override { return GetPlaneHandle(0); } + gfx::NativePixmapHandle ExportHandle() const override { + NOTIMPLEMENTED(); + return gfx::NativePixmapHandle(); + } + + private: + uint32_t format_ = 0; + uint64_t format_modifier_ = 0; + uint32_t flags_ = 0; + std::vector<base::ScopedFD> fds_; + gfx::Size size_; + std::vector<gfx::NativePixmapPlane> planes_; + std::vector<uint32_t> handles_; + + DISALLOW_COPY_AND_ASSIGN(MockGbmBuffer); +}; + +} // namespace + +MockGbmDevice::MockGbmDevice() {} + +MockGbmDevice::~MockGbmDevice() {} + +void MockGbmDevice::set_allocation_failure(bool should_fail_allocations) { + should_fail_allocations_ = should_fail_allocations; +} + +std::unique_ptr<GbmBuffer> MockGbmDevice::CreateBuffer(uint32_t format, + const gfx::Size& size, + uint32_t flags) { + if (should_fail_allocations_) + return nullptr; + + return CreateBufferWithModifiers(format, size, flags, {}); +} + +std::unique_ptr<GbmBuffer> MockGbmDevice::CreateBufferWithModifiers( + uint32_t format, + const gfx::Size& size, + uint32_t flags, + const std::vector<uint64_t>& modifiers) { + uint32_t bytes_per_pixel; + switch (format) { + case DRM_FORMAT_XRGB8888: + case DRM_FORMAT_ARGB8888: + bytes_per_pixel = 4; + break; + case DRM_FORMAT_UYVY: + bytes_per_pixel = 2; + break; + default: + NOTREACHED() << "Unsupported format: " << format; + return nullptr; + } + + if (modifiers.size() > 1) + return nullptr; + + uint64_t format_modifier = + modifiers.size() ? modifiers[0] : DRM_FORMAT_MOD_NONE; + switch (format_modifier) { + case DRM_FORMAT_MOD_NONE: + case I915_FORMAT_MOD_X_TILED: + break; + default: + NOTREACHED() << "Unsupported format modifier: " << format_modifier; + return nullptr; + } + + uint32_t width = base::checked_cast<uint32_t>(size.width()); + uint32_t height = base::checked_cast<uint32_t>(size.height()); + uint32_t plane_stride = base::CheckMul(bytes_per_pixel, width).ValueOrDie(); + uint32_t plane_size = base::CheckMul(plane_stride, height).ValueOrDie(); + uint32_t plane_offset = 0; + + std::vector<gfx::NativePixmapPlane> planes; + planes.push_back(gfx::NativePixmapPlane(plane_stride, plane_offset, + plane_size, format_modifier)); + std::vector<uint32_t> handles; + handles.push_back(next_handle_++); + + return std::make_unique<MockGbmBuffer>(format, flags, format_modifier, size, + std::move(planes), std::move(handles)); +} + +std::unique_ptr<GbmBuffer> MockGbmDevice::CreateBufferFromFds( + uint32_t format, + const gfx::Size& size, + std::vector<base::ScopedFD> fds, + const std::vector<gfx::NativePixmapPlane>& planes) { + NOTREACHED(); + return nullptr; +} + +} // namespace ui
diff --git a/ui/ozone/platform/drm/gpu/mock_gbm_device.h b/ui/ozone/platform/drm/gpu/mock_gbm_device.h new file mode 100644 index 0000000..b07c63e51 --- /dev/null +++ b/ui/ozone/platform/drm/gpu/mock_gbm_device.h
@@ -0,0 +1,44 @@ +// 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 UI_OZONE_PLATFORM_DRM_GPU_MOCK_GBM_DEVICE_H_ +#define UI_OZONE_PLATFORM_DRM_GPU_MOCK_GBM_DEVICE_H_ + +#include "ui/ozone/common/linux/gbm_device.h" + +namespace ui { + +// The real DrmDevice makes actual DRM calls which we can't use in unit tests. +class MockGbmDevice : public GbmDevice { + public: + MockGbmDevice(); + ~MockGbmDevice() override; + + void set_allocation_failure(bool should_fail_allocations); + + // GbmDevice: + std::unique_ptr<GbmBuffer> CreateBuffer(uint32_t format, + const gfx::Size& size, + uint32_t flags) override; + std::unique_ptr<GbmBuffer> CreateBufferWithModifiers( + uint32_t format, + const gfx::Size& size, + uint32_t flags, + const std::vector<uint64_t>& modifiers) override; + std::unique_ptr<GbmBuffer> CreateBufferFromFds( + uint32_t format, + const gfx::Size& size, + std::vector<base::ScopedFD> fds, + const std::vector<gfx::NativePixmapPlane>& planes) override; + + private: + uint32_t next_handle_ = 0; + bool should_fail_allocations_ = false; + + DISALLOW_COPY_AND_ASSIGN(MockGbmDevice); +}; + +} // namespace ui + +#endif // UI_OZONE_PLATFORM_DRM_GPU_MOCK_GBM_DEVICE_H_
diff --git a/ui/ozone/platform/drm/gpu/screen_manager.cc b/ui/ozone/platform/drm/gpu/screen_manager.cc index 3cd0ad0..17a2d1b 100644 --- a/ui/ozone/platform/drm/gpu/screen_manager.cc +++ b/ui/ozone/platform/drm/gpu/screen_manager.cc
@@ -15,12 +15,12 @@ #include "ui/gfx/geometry/rect.h" #include "ui/gfx/geometry/size.h" #include "ui/gfx/gpu_fence.h" +#include "ui/ozone/common/linux/gbm_buffer.h" #include "ui/ozone/platform/drm/common/drm_util.h" #include "ui/ozone/platform/drm/gpu/crtc_controller.h" #include "ui/ozone/platform/drm/gpu/drm_console_buffer.h" #include "ui/ozone/platform/drm/gpu/drm_device.h" #include "ui/ozone/platform/drm/gpu/drm_framebuffer.h" -#include "ui/ozone/platform/drm/gpu/drm_framebuffer_generator.h" #include "ui/ozone/platform/drm/gpu/drm_window.h" #include "ui/ozone/platform/drm/gpu/hardware_display_controller.h" @@ -96,8 +96,7 @@ } // namespace -ScreenManager::ScreenManager(DrmFramebufferGenerator* buffer_generator) - : buffer_generator_(buffer_generator) {} +ScreenManager::ScreenManager() {} ScreenManager::~ScreenManager() { DCHECK(window_map_.empty()); @@ -387,17 +386,22 @@ } scoped_refptr<DrmDevice> drm = controller->GetDrmDevice(); - scoped_refptr<DrmFramebuffer> buffer = - buffer_generator_->Create(drm, fourcc_format, modifiers, bounds.size()); + std::unique_ptr<GbmBuffer> buffer = + drm->gbm_device()->CreateBufferWithModifiers( + fourcc_format, bounds.size(), GBM_BO_USE_SCANOUT, modifiers); if (!buffer) { LOG(ERROR) << "Failed to create scanout buffer"; - return DrmOverlayPlane(nullptr, 0, gfx::OVERLAY_TRANSFORM_INVALID, - gfx::Rect(), gfx::RectF(), /* enable_blend */ true, - /* gpu_fence */ nullptr); + return DrmOverlayPlane::Error(); } - FillModesetBuffer(drm, controller, buffer.get()); - return DrmOverlayPlane(buffer, nullptr); + scoped_refptr<DrmFramebuffer> framebuffer = + DrmFramebuffer::AddFramebuffer(drm, buffer.get()); + if (!framebuffer) { + LOG(ERROR) << "Failed to add framebuffer for scanout buffer"; + return DrmOverlayPlane::Error(); + } + FillModesetBuffer(drm, controller, framebuffer.get()); + return DrmOverlayPlane(framebuffer, nullptr); } bool ScreenManager::EnableController(HardwareDisplayController* controller) {
diff --git a/ui/ozone/platform/drm/gpu/screen_manager.h b/ui/ozone/platform/drm/gpu/screen_manager.h index c21dbde..e5c2760d 100644 --- a/ui/ozone/platform/drm/gpu/screen_manager.h +++ b/ui/ozone/platform/drm/gpu/screen_manager.h
@@ -25,12 +25,11 @@ class DrmDevice; class DrmWindow; -class DrmFramebufferGenerator; // Responsible for keeping track of active displays and configuring them. class ScreenManager { public: - ScreenManager(DrmFramebufferGenerator* surface_generator); + ScreenManager(); virtual ~ScreenManager(); // Register a display controller. This must be called before trying to @@ -131,7 +130,6 @@ DrmWindow* FindWindowAt(const gfx::Rect& bounds) const; - DrmFramebufferGenerator* buffer_generator_; // Not owned. // List of display controllers (active and disabled). HardwareDisplayControllers controllers_;
diff --git a/ui/ozone/platform/drm/gpu/screen_manager_unittest.cc b/ui/ozone/platform/drm/gpu/screen_manager_unittest.cc index d88806e..1d05b1d9 100644 --- a/ui/ozone/platform/drm/gpu/screen_manager_unittest.cc +++ b/ui/ozone/platform/drm/gpu/screen_manager_unittest.cc
@@ -12,6 +12,7 @@ #include "base/macros.h" #include "testing/gtest/include/gtest/gtest.h" #include "ui/gfx/gpu_fence.h" +#include "ui/ozone/common/linux/gbm_buffer.h" #include "ui/ozone/platform/drm/gpu/crtc_controller.h" #include "ui/ozone/platform/drm/gpu/drm_device_generator.h" #include "ui/ozone/platform/drm/gpu/drm_device_manager.h" @@ -19,7 +20,7 @@ #include "ui/ozone/platform/drm/gpu/drm_window.h" #include "ui/ozone/platform/drm/gpu/hardware_display_controller.h" #include "ui/ozone/platform/drm/gpu/mock_drm_device.h" -#include "ui/ozone/platform/drm/gpu/mock_drm_framebuffer_generator.h" +#include "ui/ozone/platform/drm/gpu/mock_gbm_device.h" #include "ui/ozone/platform/drm/gpu/screen_manager.h" namespace ui { @@ -56,20 +57,36 @@ } void SetUp() override { - drm_ = new ui::MockDrmDevice; + auto gbm = std::make_unique<ui::MockGbmDevice>(); + drm_ = new ui::MockDrmDevice(std::move(gbm)); device_manager_.reset(new ui::DrmDeviceManager(nullptr)); - buffer_generator_.reset(new ui::MockDrmFramebufferGenerator()); - screen_manager_.reset(new ui::ScreenManager(buffer_generator_.get())); + screen_manager_.reset(new ui::ScreenManager()); } void TearDown() override { screen_manager_.reset(); drm_ = nullptr; } + scoped_refptr<DrmFramebuffer> CreateBuffer(uint32_t format, + const gfx::Size& size) { + return CreateBufferWithModifier(format, DRM_FORMAT_MOD_NONE, size); + } + + scoped_refptr<DrmFramebuffer> CreateBufferWithModifier( + uint32_t format, + uint64_t format_modifier, + const gfx::Size& size) { + std::vector<uint64_t> modifiers; + if (format_modifier != DRM_FORMAT_MOD_NONE) + modifiers.push_back(format_modifier); + auto buffer = drm_->gbm_device()->CreateBufferWithModifiers( + format, size, GBM_BO_USE_SCANOUT, modifiers); + return DrmFramebuffer::AddFramebuffer(drm_, buffer.get()); + } + protected: scoped_refptr<ui::MockDrmDevice> drm_; std::unique_ptr<ui::DrmDeviceManager> device_manager_; - std::unique_ptr<ui::MockDrmFramebufferGenerator> buffer_generator_; std::unique_ptr<ui::ScreenManager> screen_manager_; private: @@ -360,7 +377,9 @@ TEST_F(ScreenManagerTest, CheckProperConfigurationWithDifferentDeviceAndSameCrtc) { - scoped_refptr<ui::MockDrmDevice> drm2 = new ui::MockDrmDevice; + auto gbm_device = std::make_unique<ui::MockGbmDevice>(); + scoped_refptr<ui::MockDrmDevice> drm2 = + new ui::MockDrmDevice(std::move(gbm_device)); screen_manager_->AddDisplayController(drm_, kPrimaryCrtc, kPrimaryConnector); screen_manager_->AddDisplayController(drm2, kPrimaryCrtc, kPrimaryConnector); @@ -385,7 +404,7 @@ TEST_F(ScreenManagerTest, CheckControllerToWindowMappingWithSameBounds) { std::unique_ptr<ui::DrmWindow> window( new ui::DrmWindow(1, device_manager_.get(), screen_manager_.get())); - window->Initialize(buffer_generator_.get()); + window->Initialize(); window->SetBounds(GetPrimaryBounds()); screen_manager_->AddWindow(1, std::move(window)); @@ -403,7 +422,7 @@ TEST_F(ScreenManagerTest, CheckControllerToWindowMappingWithDifferentBounds) { std::unique_ptr<ui::DrmWindow> window( new ui::DrmWindow(1, device_manager_.get(), screen_manager_.get())); - window->Initialize(buffer_generator_.get()); + window->Initialize(); gfx::Rect new_bounds = GetPrimaryBounds(); new_bounds.Inset(0, 0, 1, 1); window->SetBounds(new_bounds); @@ -426,7 +445,7 @@ for (size_t i = 1; i < kWindowCount + 1; ++i) { std::unique_ptr<ui::DrmWindow> window( new ui::DrmWindow(i, device_manager_.get(), screen_manager_.get())); - window->Initialize(buffer_generator_.get()); + window->Initialize(); window->SetBounds(GetPrimaryBounds()); screen_manager_->AddWindow(i, std::move(window)); } @@ -451,7 +470,7 @@ gfx::AcceleratedWidget window_id = 1; std::unique_ptr<ui::DrmWindow> window(new ui::DrmWindow( window_id, device_manager_.get(), screen_manager_.get())); - window->Initialize(buffer_generator_.get()); + window->Initialize(); window->SetBounds(GetPrimaryBounds()); screen_manager_->AddWindow(window_id, std::move(window)); @@ -473,7 +492,7 @@ TEST_F(ScreenManagerTest, EnableControllerWhenWindowHasNoBuffer) { std::unique_ptr<ui::DrmWindow> window( new ui::DrmWindow(1, device_manager_.get(), screen_manager_.get())); - window->Initialize(buffer_generator_.get()); + window->Initialize(); window->SetBounds(GetPrimaryBounds()); screen_manager_->AddWindow(1, std::move(window)); @@ -502,11 +521,10 @@ TEST_F(ScreenManagerTest, EnableControllerWhenWindowHasBuffer) { std::unique_ptr<ui::DrmWindow> window( new ui::DrmWindow(1, device_manager_.get(), screen_manager_.get())); - window->Initialize(buffer_generator_.get()); + window->Initialize(); window->SetBounds(GetPrimaryBounds()); - - scoped_refptr<ui::DrmFramebuffer> buffer = buffer_generator_->Create( - drm_, DRM_FORMAT_XRGB8888, {}, GetPrimaryBounds().size()); + scoped_refptr<DrmFramebuffer> buffer = + CreateBuffer(DRM_FORMAT_XRGB8888, GetPrimaryBounds().size()); ui::DrmOverlayPlaneList planes; planes.push_back(ui::DrmOverlayPlane(buffer, nullptr)); window->SchedulePageFlip(std::move(planes), base::DoNothing(), @@ -528,13 +546,10 @@ TEST_F(ScreenManagerTest, DISABLED_RejectBufferWithIncompatibleModifiers) { std::unique_ptr<ui::DrmWindow> window( new ui::DrmWindow(1, device_manager_.get(), screen_manager_.get())); - window->Initialize(buffer_generator_.get()); + window->Initialize(); window->SetBounds(GetPrimaryBounds()); - scoped_refptr<ui::DrmFramebuffer> buffer = - buffer_generator_->CreateWithModifier(drm_, DRM_FORMAT_XRGB8888, - I915_FORMAT_MOD_X_TILED, - GetPrimaryBounds().size()); - + auto buffer = CreateBufferWithModifier( + DRM_FORMAT_XRGB8888, I915_FORMAT_MOD_X_TILED, GetPrimaryBounds().size()); ui::DrmOverlayPlaneList planes; planes.push_back(ui::DrmOverlayPlane(buffer, nullptr)); window->SchedulePageFlip(std::move(planes), base::DoNothing(), @@ -558,11 +573,14 @@ } TEST(ScreenManagerTest2, ShouldNotHardwareMirrorDifferentDrmDevices) { - auto drm_device1 = base::MakeRefCounted<MockDrmDevice>(); - auto drm_device2 = base::MakeRefCounted<MockDrmDevice>(); + auto gbm_device1 = std::make_unique<MockGbmDevice>(); + auto drm_device1 = + base::MakeRefCounted<MockDrmDevice>(std::move(gbm_device1)); + auto gbm_device2 = std::make_unique<MockGbmDevice>(); + auto drm_device2 = + base::MakeRefCounted<MockDrmDevice>(std::move(gbm_device2)); DrmDeviceManager drm_device_manager(nullptr); - MockDrmFramebufferGenerator buffer_generator; - ScreenManager screen_manager(&buffer_generator); + ScreenManager screen_manager; constexpr uint32_t kCrtc19 = 19; constexpr uint32_t kConnector28 = 28; @@ -581,7 +599,7 @@ { auto window1 = std::make_unique<DrmWindow>(1, &drm_device_manager, &screen_manager); - window1->Initialize(&buffer_generator); + window1->Initialize(); screen_manager.AddWindow(1, std::move(window1)); screen_manager.GetWindow(1)->SetBounds(gfx::Rect(0, 0, 1920, 1080)); screen_manager.AddDisplayController(drm_device1, kCrtc19, kConnector28); @@ -593,7 +611,7 @@ Mode(1920, 1080)); auto window2 = std::make_unique<DrmWindow>(2, &drm_device_manager, &screen_manager); - window2->Initialize(&buffer_generator); + window2->Initialize(); screen_manager.AddWindow(2, std::move(window2)); screen_manager.GetWindow(2)->SetBounds(gfx::Rect(0, 1140, 1920, 1080)); } @@ -639,7 +657,7 @@ Mode(1920, 1080)); auto window3 = std::make_unique<DrmWindow>(3, &drm_device_manager, &screen_manager); - window3->Initialize(&buffer_generator); + window3->Initialize(); screen_manager.AddWindow(3, std::move(window3)); screen_manager.GetWindow(3)->SetBounds(gfx::Rect(0, 0, 1920, 1080)); screen_manager.GetWindow(1)->SetBounds(gfx::Rect(0, 1140, 1920, 1080));
diff --git a/ui/strings/ui_strings.grd b/ui/strings/ui_strings.grd index 5269edc..35bd5f0 100644 --- a/ui/strings/ui_strings.grd +++ b/ui/strings/ui_strings.grd
@@ -598,6 +598,9 @@ <message name="IDS_APP_MEDIA_STOP_KEY" desc="Media stop key"> Media Stop </message> + <message name="IDS_APP_ALT_KEY" desc="Alt key"> + Alt + </message> <message name="IDS_APP_CTRL_KEY" desc="Ctrl key"> Ctrl </message>