summaryrefslogtreecommitdiffstats
path: root/chromium/chrome/browser/extensions/api
diff options
context:
space:
mode:
authorAllan Sandfeld Jensen <allan.jensen@qt.io>2018-10-24 11:30:15 +0200
committerAllan Sandfeld Jensen <allan.jensen@qt.io>2018-10-30 12:56:19 +0000
commit6036726eb981b6c4b42047513b9d3f4ac865daac (patch)
tree673593e70678e7789766d1f732eb51f613a2703b /chromium/chrome/browser/extensions/api
parent466052c4e7c052268fd931888cd58961da94c586 (diff)
BASELINE: Update Chromium to 70.0.3538.78
Change-Id: Ie634710bf039e26c1957f4ae45e101bd4c434ae7 Reviewed-by: Michael BrĂ¼ning <michael.bruning@qt.io>
Diffstat (limited to 'chromium/chrome/browser/extensions/api')
-rw-r--r--chromium/chrome/browser/extensions/api/BUILD.gn8
-rw-r--r--chromium/chrome/browser/extensions/api/DEPS5
-rw-r--r--chromium/chrome/browser/extensions/api/autofill_private/autofill_private_api.cc55
-rw-r--r--chromium/chrome/browser/extensions/api/autofill_private/autofill_private_api.h19
-rw-r--r--chromium/chrome/browser/extensions/api/autofill_private/autofill_util.cc10
-rw-r--r--chromium/chrome/browser/extensions/api/automation_internal/automation_event_router.cc8
-rw-r--r--chromium/chrome/browser/extensions/api/automation_internal/automation_event_router.h5
-rw-r--r--chromium/chrome/browser/extensions/api/automation_internal/automation_internal_api.cc2
-rw-r--r--chromium/chrome/browser/extensions/api/autotest_private/DEPS3
-rw-r--r--chromium/chrome/browser/extensions/api/autotest_private/autotest_private_api.cc44
-rw-r--r--chromium/chrome/browser/extensions/api/autotest_private/autotest_private_api.h23
-rw-r--r--chromium/chrome/browser/extensions/api/bookmark_manager_private/bookmark_manager_private_api.cc3
-rw-r--r--chromium/chrome/browser/extensions/api/bookmarks/bookmarks_api.cc2
-rw-r--r--chromium/chrome/browser/extensions/api/braille_display_private/braille_controller.h2
-rw-r--r--chromium/chrome/browser/extensions/api/braille_display_private/braille_controller_brlapi.cc22
-rw-r--r--chromium/chrome/browser/extensions/api/braille_display_private/braille_controller_brlapi.h4
-rw-r--r--chromium/chrome/browser/extensions/api/braille_display_private/stub_braille_controller.cc2
-rw-r--r--chromium/chrome/browser/extensions/api/braille_display_private/stub_braille_controller.h2
-rw-r--r--chromium/chrome/browser/extensions/api/browsing_data/browsing_data_api.cc39
-rw-r--r--chromium/chrome/browser/extensions/api/browsing_data/browsing_data_api.h12
-rw-r--r--chromium/chrome/browser/extensions/api/browsing_data/browsing_data_test.cc142
-rw-r--r--chromium/chrome/browser/extensions/api/certificate_provider/certificate_provider_api.cc6
-rw-r--r--chromium/chrome/browser/extensions/api/cloud_print_private/cloud_print_private_api.cc5
-rw-r--r--chromium/chrome/browser/extensions/api/commands/command_service.h2
-rw-r--r--chromium/chrome/browser/extensions/api/content_settings/content_settings_api.cc33
-rw-r--r--chromium/chrome/browser/extensions/api/content_settings/content_settings_apitest.cc50
-rw-r--r--chromium/chrome/browser/extensions/api/content_settings/content_settings_service.cc1
-rw-r--r--chromium/chrome/browser/extensions/api/content_settings/content_settings_service.h1
-rw-r--r--chromium/chrome/browser/extensions/api/content_settings/content_settings_store.h2
-rw-r--r--chromium/chrome/browser/extensions/api/context_menus/context_menu_apitest.cc20
-rw-r--r--chromium/chrome/browser/extensions/api/cryptotoken_private/cryptotoken_private_api.cc9
-rw-r--r--chromium/chrome/browser/extensions/api/debugger/debugger_api.cc9
-rw-r--r--chromium/chrome/browser/extensions/api/declarative/declarative_apitest.cc13
-rw-r--r--chromium/chrome/browser/extensions/api/declarative_content/declarative_content_apitest.cc16
-rw-r--r--chromium/chrome/browser/extensions/api/declarative_content/set_icon_apitest.cc4
-rw-r--r--chromium/chrome/browser/extensions/api/declarative_net_request/declarative_net_request_browsertest.cc114
-rw-r--r--chromium/chrome/browser/extensions/api/declarative_net_request/ruleset_matcher_unittest.cc16
-rw-r--r--chromium/chrome/browser/extensions/api/desktop_capture/OWNERS4
-rw-r--r--chromium/chrome/browser/extensions/api/desktop_capture/desktop_capture_apitest.cc119
-rw-r--r--chromium/chrome/browser/extensions/api/desktop_capture/desktop_capture_base.cc116
-rw-r--r--chromium/chrome/browser/extensions/api/desktop_capture/desktop_capture_base.h20
-rw-r--r--chromium/chrome/browser/extensions/api/developer_private/DEPS4
-rw-r--r--chromium/chrome/browser/extensions/api/developer_private/developer_private_api.cc111
-rw-r--r--chromium/chrome/browser/extensions/api/developer_private/developer_private_api.h18
-rw-r--r--chromium/chrome/browser/extensions/api/developer_private/developer_private_api_unittest.cc252
-rw-r--r--chromium/chrome/browser/extensions/api/developer_private/extension_info_generator.cc35
-rw-r--r--chromium/chrome/browser/extensions/api/developer_private/extension_info_generator_unittest.cc49
-rw-r--r--chromium/chrome/browser/extensions/api/downloads/downloads_api.cc7
-rw-r--r--chromium/chrome/browser/extensions/api/downloads/downloads_api_browsertest.cc13
-rw-r--r--chromium/chrome/browser/extensions/api/easy_unlock_private/easy_unlock_private_api.cc3
-rw-r--r--chromium/chrome/browser/extensions/api/easy_unlock_private/easy_unlock_private_connection.h8
-rw-r--r--chromium/chrome/browser/extensions/api/easy_unlock_private/easy_unlock_private_connection_manager.cc4
-rw-r--r--chromium/chrome/browser/extensions/api/enterprise_device_attributes/enterprise_device_attributes_apitest.cc70
-rw-r--r--chromium/chrome/browser/extensions/api/enterprise_hardware_platform/OWNERS1
-rw-r--r--chromium/chrome/browser/extensions/api/enterprise_hardware_platform/enterprise_hardware_platform_api.cc38
-rw-r--r--chromium/chrome/browser/extensions/api/enterprise_hardware_platform/enterprise_hardware_platform_api.h37
-rw-r--r--chromium/chrome/browser/extensions/api/enterprise_hardware_platform/enterprise_hardware_platform_api_unittest.cc84
-rw-r--r--chromium/chrome/browser/extensions/api/enterprise_platform_keys/enterprise_platform_keys_api.cc18
-rw-r--r--chromium/chrome/browser/extensions/api/enterprise_platform_keys/enterprise_platform_keys_api_unittest.cc11
-rw-r--r--chromium/chrome/browser/extensions/api/enterprise_platform_keys_private/enterprise_platform_keys_private_api.cc3
-rw-r--r--chromium/chrome/browser/extensions/api/enterprise_platform_keys_private/enterprise_platform_keys_private_api_unittest.cc4
-rw-r--r--chromium/chrome/browser/extensions/api/enterprise_reporting_private/chrome_desktop_report_request_helper.cc122
-rw-r--r--chromium/chrome/browser/extensions/api/enterprise_reporting_private/chrome_desktop_report_request_helper_unittest.cc78
-rw-r--r--chromium/chrome/browser/extensions/api/enterprise_reporting_private/enterprise_reporting_policy_migrator.cc40
-rw-r--r--chromium/chrome/browser/extensions/api/enterprise_reporting_private/enterprise_reporting_policy_migrator.h25
-rw-r--r--chromium/chrome/browser/extensions/api/enterprise_reporting_private/enterprise_reporting_policy_migrator_unittest.cc72
-rw-r--r--chromium/chrome/browser/extensions/api/enterprise_reporting_private/enterprise_reporting_private_api.cc3
-rw-r--r--chromium/chrome/browser/extensions/api/enterprise_reporting_private/enterprise_reporting_private_unittest.cc8
-rw-r--r--chromium/chrome/browser/extensions/api/enterprise_reporting_private/prefs.cc29
-rw-r--r--chromium/chrome/browser/extensions/api/enterprise_reporting_private/prefs.h32
-rw-r--r--chromium/chrome/browser/extensions/api/extension_action/browser_action_apitest.cc100
-rw-r--r--chromium/chrome/browser/extensions/api/extension_action/extension_action_api.cc21
-rw-r--r--chromium/chrome/browser/extensions/api/extension_action/extension_action_api.h5
-rw-r--r--chromium/chrome/browser/extensions/api/extension_action/extension_action_apitest.cc38
-rw-r--r--chromium/chrome/browser/extensions/api/extension_action/test_extension_action_api_observer.cc32
-rw-r--r--chromium/chrome/browser/extensions/api/extension_action/test_extension_action_api_observer.h55
-rw-r--r--chromium/chrome/browser/extensions/api/file_system/DEPS6
-rw-r--r--chromium/chrome/browser/extensions/api/identity/gaia_web_auth_flow.cc9
-rw-r--r--chromium/chrome/browser/extensions/api/identity/identity_apitest.cc49
-rw-r--r--chromium/chrome/browser/extensions/api/identity/identity_constants.cc1
-rw-r--r--chromium/chrome/browser/extensions/api/identity/identity_constants.h1
-rw-r--r--chromium/chrome/browser/extensions/api/identity/identity_get_auth_token_function.cc28
-rw-r--r--chromium/chrome/browser/extensions/api/identity/identity_get_auth_token_function.h6
-rw-r--r--chromium/chrome/browser/extensions/api/image_writer_private/destroy_partitions_operation.cc2
-rw-r--r--chromium/chrome/browser/extensions/api/image_writer_private/image_writer_utility_client_browsertest.cc2
-rw-r--r--chromium/chrome/browser/extensions/api/image_writer_private/operation.cc16
-rw-r--r--chromium/chrome/browser/extensions/api/image_writer_private/operation.h11
-rw-r--r--chromium/chrome/browser/extensions/api/image_writer_private/operation_chromeos.cc7
-rw-r--r--chromium/chrome/browser/extensions/api/image_writer_private/operation_manager.cc10
-rw-r--r--chromium/chrome/browser/extensions/api/image_writer_private/removable_storage_provider.cc2
-rw-r--r--chromium/chrome/browser/extensions/api/image_writer_private/removable_storage_provider_chromeos.cc5
-rw-r--r--chromium/chrome/browser/extensions/api/image_writer_private/test_utils.cc10
-rw-r--r--chromium/chrome/browser/extensions/api/image_writer_private/test_utils.h2
-rw-r--r--chromium/chrome/browser/extensions/api/image_writer_private/unzip_helper.cc2
-rw-r--r--chromium/chrome/browser/extensions/api/image_writer_private/write_from_url_operation.cc66
-rw-r--r--chromium/chrome/browser/extensions/api/image_writer_private/write_from_url_operation.h39
-rw-r--r--chromium/chrome/browser/extensions/api/image_writer_private/write_from_url_operation_unittest.cc31
-rw-r--r--chromium/chrome/browser/extensions/api/input_ime/input_ime_api.cc5
-rw-r--r--chromium/chrome/browser/extensions/api/input_ime/input_ime_api.h4
-rw-r--r--chromium/chrome/browser/extensions/api/input_ime/input_ime_api_chromeos.cc4
-rw-r--r--chromium/chrome/browser/extensions/api/language_settings_private/language_settings_private_api.cc6
-rw-r--r--chromium/chrome/browser/extensions/api/language_settings_private/language_settings_private_delegate.cc86
-rw-r--r--chromium/chrome/browser/extensions/api/language_settings_private/language_settings_private_delegate.h26
-rw-r--r--chromium/chrome/browser/extensions/api/management/management_browsertest.cc151
-rw-r--r--chromium/chrome/browser/extensions/api/mdns/mdns_api.cc2
-rw-r--r--chromium/chrome/browser/extensions/api/mdns/mdns_apitest.cc2
-rw-r--r--chromium/chrome/browser/extensions/api/messaging/DEPS8
-rw-r--r--chromium/chrome/browser/extensions/api/messaging/native_message_host_chromeos.cc65
-rw-r--r--chromium/chrome/browser/extensions/api/messaging/native_message_process_host.cc11
-rw-r--r--chromium/chrome/browser/extensions/api/messaging/native_process_launcher.cc2
-rw-r--r--chromium/chrome/browser/extensions/api/music_manager_private/device_id.h2
-rw-r--r--chromium/chrome/browser/extensions/api/music_manager_private/device_id_linux.cc2
-rw-r--r--chromium/chrome/browser/extensions/api/music_manager_private/device_id_mac.cc2
-rw-r--r--chromium/chrome/browser/extensions/api/music_manager_private/device_id_win.cc2
-rw-r--r--chromium/chrome/browser/extensions/api/networking_cast_private/chrome_networking_cast_private_delegate.cc2
-rw-r--r--chromium/chrome/browser/extensions/api/networking_private/DEPS2
-rw-r--r--chromium/chrome/browser/extensions/api/networking_private/networking_private_chromeos_apitest.cc15
-rw-r--r--chromium/chrome/browser/extensions/api/networking_private/networking_private_credentials_getter_browsertest.cc4
-rw-r--r--chromium/chrome/browser/extensions/api/notifications/notifications_api.cc10
-rw-r--r--chromium/chrome/browser/extensions/api/notifications/notifications_apitest.cc1
-rw-r--r--chromium/chrome/browser/extensions/api/page_capture/page_capture_api.cc4
-rw-r--r--chromium/chrome/browser/extensions/api/platform_keys/platform_keys_api.cc18
-rw-r--r--chromium/chrome/browser/extensions/api/platform_keys/platform_keys_test_base.cc30
-rw-r--r--chromium/chrome/browser/extensions/api/platform_keys/verify_trust_api.cc10
-rw-r--r--chromium/chrome/browser/extensions/api/preference/preference_api.cc29
-rw-r--r--chromium/chrome/browser/extensions/api/preference/preference_apitest.cc16
-rw-r--r--chromium/chrome/browser/extensions/api/processes/processes_api.cc2
-rw-r--r--chromium/chrome/browser/extensions/api/proxy/proxy_api.cc6
-rw-r--r--chromium/chrome/browser/extensions/api/proxy/proxy_api_helpers.cc37
-rw-r--r--chromium/chrome/browser/extensions/api/proxy/proxy_api_helpers.h5
-rw-r--r--chromium/chrome/browser/extensions/api/proxy/proxy_api_helpers_unittest.cc63
-rw-r--r--chromium/chrome/browser/extensions/api/proxy/proxy_apitest.cc28
-rw-r--r--chromium/chrome/browser/extensions/api/sessions/sessions_apitest.cc2
-rw-r--r--chromium/chrome/browser/extensions/api/settings_private/generated_pref.h2
-rw-r--r--chromium/chrome/browser/extensions/api/settings_private/prefs_util.cc26
-rw-r--r--chromium/chrome/browser/extensions/api/socket/combined_socket_unittest.cc145
-rw-r--r--chromium/chrome/browser/extensions/api/socket/mock_tcp_client_socket.h82
-rw-r--r--chromium/chrome/browser/extensions/api/socket/socket_apitest.cc30
-rw-r--r--chromium/chrome/browser/extensions/api/socket/tcp_socket_unittest.cc859
-rw-r--r--chromium/chrome/browser/extensions/api/socket/tls_socket_unittest.cc750
-rw-r--r--chromium/chrome/browser/extensions/api/sync_file_system/DEPS5
-rw-r--r--chromium/chrome/browser/extensions/api/sync_file_system/OWNERS1
-rw-r--r--chromium/chrome/browser/extensions/api/sync_file_system/sync_file_system_browsertest.cc4
-rw-r--r--chromium/chrome/browser/extensions/api/system_private/system_private_api.cc2
-rw-r--r--chromium/chrome/browser/extensions/api/tab_capture/offscreen_tab.cc422
-rw-r--r--chromium/chrome/browser/extensions/api/tab_capture/offscreen_tab.h236
-rw-r--r--chromium/chrome/browser/extensions/api/tab_capture/offscreen_tabs_owner.cc114
-rw-r--r--chromium/chrome/browser/extensions/api/tab_capture/offscreen_tabs_owner.h75
-rw-r--r--chromium/chrome/browser/extensions/api/tab_capture/tab_capture_api.cc94
-rw-r--r--chromium/chrome/browser/extensions/api/tab_capture/tab_capture_registry.cc92
-rw-r--r--chromium/chrome/browser/extensions/api/tab_capture/tab_capture_registry.h38
-rw-r--r--chromium/chrome/browser/extensions/api/tabs/tabs_api.cc6
-rw-r--r--chromium/chrome/browser/extensions/api/tabs/tabs_event_router.cc404
-rw-r--r--chromium/chrome/browser/extensions/api/tabs/tabs_event_router.h61
-rw-r--r--chromium/chrome/browser/extensions/api/terminal/terminal_private_api.cc2
-rw-r--r--chromium/chrome/browser/extensions/api/web_navigation/web_navigation_api.cc53
-rw-r--r--chromium/chrome/browser/extensions/api/web_navigation/web_navigation_api.h8
-rw-r--r--chromium/chrome/browser/extensions/api/web_navigation/web_navigation_apitest.cc33
-rw-r--r--chromium/chrome/browser/extensions/api/web_request/chrome_extension_web_request_event_router_delegate.cc15
-rw-r--r--chromium/chrome/browser/extensions/api/web_request/web_request_api_unittest.cc245
-rw-r--r--chromium/chrome/browser/extensions/api/web_request/web_request_apitest.cc405
-rw-r--r--chromium/chrome/browser/extensions/api/webrtc_logging_private/webrtc_logging_private_api.cc2
-rw-r--r--chromium/chrome/browser/extensions/api/webrtc_logging_private/webrtc_logging_private_apitest.cc300
-rw-r--r--chromium/chrome/browser/extensions/api/webrtc_logging_private/webrtc_logging_private_browsertest.cc6
-rw-r--r--chromium/chrome/browser/extensions/api/webstore_private/webstore_private_apitest.cc76
165 files changed, 4984 insertions, 2980 deletions
diff --git a/chromium/chrome/browser/extensions/api/BUILD.gn b/chromium/chrome/browser/extensions/api/BUILD.gn
index ee871a22d98..d6ca561c0b3 100644
--- a/chromium/chrome/browser/extensions/api/BUILD.gn
+++ b/chromium/chrome/browser/extensions/api/BUILD.gn
@@ -10,17 +10,15 @@ import("//tools/json_schema_compiler/json_schema_api.gni")
assert(enable_extensions,
"Cannot depend on extensions because enable_extensions=false.")
-json_schema_api("api_registration") {
- sources = chrome_extensions_api_schema_sources
+function_registration("api_registration") {
+ sources = chrome_extensions_api_schema_sources +
+ chrome_extensions_api_uncompiled_sources
impl_dir = "//chrome/browser/extensions/api"
- bundle_registration = true
configs = [ "//build/config:precompiled_headers" ]
bundle_name = "Chrome"
root_namespace = chrome_extensions_api_root_namespace
schema_include_rules = chrome_extensions_api_schema_include_rules
- uncompiled_sources = chrome_extensions_api_uncompiled_sources
-
deps = [
# Different APIs include headers from these targets.
"//content/public/browser",
diff --git a/chromium/chrome/browser/extensions/api/DEPS b/chromium/chrome/browser/extensions/api/DEPS
index d7be18a52d9..5dc13a559c9 100644
--- a/chromium/chrome/browser/extensions/api/DEPS
+++ b/chromium/chrome/browser/extensions/api/DEPS
@@ -1,10 +1,7 @@
include_rules = [
"+apps",
- "+chrome/browser/apps",
- "+components/about_handler",
- "+components/guest_view/common",
- "+components/language/core/browser",
"+services/device/public",
+
# Enable remote assistance on Chrome OS
"+remoting/base",
"+remoting/host",
diff --git a/chromium/chrome/browser/extensions/api/autofill_private/autofill_private_api.cc b/chromium/chrome/browser/extensions/api/autofill_private/autofill_private_api.cc
index 76fa90e5d6f..6de7439ca22 100644
--- a/chromium/chrome/browser/extensions/api/autofill_private/autofill_private_api.cc
+++ b/chromium/chrome/browser/extensions/api/autofill_private/autofill_private_api.cc
@@ -14,8 +14,13 @@
#include "chrome/browser/browser_process.h"
#include "chrome/browser/extensions/api/autofill_private/autofill_util.h"
#include "chrome/common/extensions/api/autofill_private.h"
+#include "components/autofill/content/browser/content_autofill_driver.h"
+#include "components/autofill/content/browser/content_autofill_driver_factory.h"
+#include "components/autofill/core/browser/autofill_manager.h"
#include "components/autofill/core/browser/autofill_profile.h"
+#include "components/autofill/core/browser/local_card_migration_manager.h"
#include "components/autofill/core/browser/personal_data_manager.h"
+#include "content/public/browser/web_contents.h"
#include "extensions/browser/extension_function.h"
#include "extensions/browser/extension_function_registry.h"
#include "third_party/libaddressinput/src/cpp/include/libaddressinput/address_ui.h"
@@ -531,4 +536,54 @@ AutofillPrivateGetCreditCardListFunction::Run() {
credit_card_list)));
}
+////////////////////////////////////////////////////////////////////////////////
+// AutofillPrivateMigrateCreditCardsFunction
+
+AutofillPrivateMigrateCreditCardsFunction::
+ AutofillPrivateMigrateCreditCardsFunction()
+ : chrome_details_(this) {}
+
+AutofillPrivateMigrateCreditCardsFunction::
+ ~AutofillPrivateMigrateCreditCardsFunction() {}
+
+ExtensionFunction::ResponseAction
+AutofillPrivateMigrateCreditCardsFunction::Run() {
+ autofill::PersonalDataManager* personal_data =
+ autofill::PersonalDataManagerFactory::GetForProfile(
+ chrome_details_.GetProfile());
+ // Get the web contents to get autofill manager.
+ content::WebContents* web_contents = GetSenderWebContents();
+ if (!personal_data || !personal_data->IsDataLoaded() || !web_contents)
+ return RespondNow(Error(kErrorDataUnavailable));
+
+ // Get the autofill manager from the web contains. Autofill manager owns an
+ // unique_ptr of form data importer.
+ autofill::AutofillManager* autofill_manager =
+ autofill::ContentAutofillDriverFactory::FromWebContents(web_contents)
+ ->DriverForFrame(web_contents->GetMainFrame())
+ ->autofill_manager();
+ if (!autofill_manager)
+ return RespondNow(Error(kErrorDataUnavailable));
+
+ // Get the form data importer from autofill manager. Form data importer owns
+ // an unique_ptr of local card migration manager.
+ autofill::FormDataImporter* form_data_importer =
+ autofill_manager->form_data_importer();
+ if (!form_data_importer)
+ return RespondNow(Error(kErrorDataUnavailable));
+
+ // Get local card migration manager from form data importer.
+ autofill::LocalCardMigrationManager* local_card_migration_manager =
+ form_data_importer->local_card_migration_manager();
+ if (!local_card_migration_manager)
+ return RespondNow(Error(kErrorDataUnavailable));
+
+ // Since we already check the migration requirements on the settings page, we
+ // don't check the migration requirements again.
+ local_card_migration_manager->GetMigratableCreditCards();
+ local_card_migration_manager->AttemptToOfferLocalCardMigration(
+ /*is_from_settings_page=*/true);
+ return RespondNow(NoArguments());
+}
+
} // namespace extensions
diff --git a/chromium/chrome/browser/extensions/api/autofill_private/autofill_private_api.h b/chromium/chrome/browser/extensions/api/autofill_private/autofill_private_api.h
index db7e98cfc25..a1b14bed656 100644
--- a/chromium/chrome/browser/extensions/api/autofill_private/autofill_private_api.h
+++ b/chromium/chrome/browser/extensions/api/autofill_private/autofill_private_api.h
@@ -174,6 +174,25 @@ class AutofillPrivateGetCreditCardListFunction
DISALLOW_COPY_AND_ASSIGN(AutofillPrivateGetCreditCardListFunction);
};
+class AutofillPrivateMigrateCreditCardsFunction
+ : public UIThreadExtensionFunction {
+ public:
+ AutofillPrivateMigrateCreditCardsFunction();
+ DECLARE_EXTENSION_FUNCTION("autofillPrivate.migrateCreditCards",
+ AUTOFILLPRIVATE_MIGRATECREDITCARDS);
+
+ protected:
+ ~AutofillPrivateMigrateCreditCardsFunction() override;
+
+ // ExtensionFunction overrides.
+ ResponseAction Run() override;
+
+ private:
+ ChromeExtensionFunctionDetails chrome_details_;
+
+ DISALLOW_COPY_AND_ASSIGN(AutofillPrivateMigrateCreditCardsFunction);
+};
+
} // namespace extensions
#endif // CHROME_BROWSER_EXTENSIONS_API_AUTOFILL_PRIVATE_AUTOFILL_PRIVATE_API_H_
diff --git a/chromium/chrome/browser/extensions/api/autofill_private/autofill_util.cc b/chromium/chrome/browser/extensions/api/autofill_private/autofill_util.cc
index 2f3640b72fa..157f6c089b9 100644
--- a/chromium/chrome/browser/extensions/api/autofill_private/autofill_util.cc
+++ b/chromium/chrome/browser/extensions/api/autofill_private/autofill_util.cc
@@ -132,7 +132,8 @@ autofill_private::CountryEntry CountryToCountryEntry(
}
autofill_private::CreditCardEntry CreditCardToCreditCardEntry(
- const autofill::CreditCard& credit_card) {
+ const autofill::CreditCard& credit_card,
+ const autofill::PersonalDataManager& personal_data) {
autofill_private::CreditCardEntry card;
// Add all credit card fields to the entry.
@@ -158,6 +159,11 @@ autofill_private::CreditCardEntry CreditCardToCreditCardEntry(
credit_card.record_type() == autofill::CreditCard::LOCAL_CARD));
metadata->is_cached.reset(new bool(
credit_card.record_type() == autofill::CreditCard::FULL_SERVER_CARD));
+ // IsValid() checks if both card number and expiration date are valid.
+ // IsServerCard() checks whether there is a duplicated server card in
+ // |personal_data|.
+ metadata->is_migratable.reset(new bool(
+ credit_card.IsValid() && !personal_data.IsServerCard(&credit_card)));
card.metadata = std::move(metadata);
return card;
@@ -210,7 +216,7 @@ CreditCardEntryList GenerateCreditCardList(
CreditCardEntryList list;
for (const autofill::CreditCard* card : cards)
- list.push_back(CreditCardToCreditCardEntry(*card));
+ list.push_back(CreditCardToCreditCardEntry(*card, personal_data));
return list;
}
diff --git a/chromium/chrome/browser/extensions/api/automation_internal/automation_event_router.cc b/chromium/chrome/browser/extensions/api/automation_internal/automation_event_router.cc
index b9eeb7c6b1e..ec98e3dff27 100644
--- a/chromium/chrome/browser/extensions/api/automation_internal/automation_event_router.cc
+++ b/chromium/chrome/browser/extensions/api/automation_internal/automation_event_router.cc
@@ -115,6 +115,9 @@ void AutomationEventRouter::DispatchTreeDestroyedEvent(
api::automation_internal::OnAccessibilityTreeDestroyed::kEventName,
std::move(args), browser_context);
EventRouter::Get(browser_context)->BroadcastEvent(std::move(event));
+
+ if (tree_destroyed_callback_for_test_)
+ tree_destroyed_callback_for_test_.Run(tree_id);
}
void AutomationEventRouter::DispatchActionResult(const ui::AXActionData& data,
@@ -135,6 +138,11 @@ void AutomationEventRouter::DispatchActionResult(const ui::AXActionData& data,
->DispatchEventToExtension(data.source_extension_id, std::move(event));
}
+void AutomationEventRouter::SetTreeDestroyedCallbackForTest(
+ base::RepeatingCallback<void(int)> cb) {
+ tree_destroyed_callback_for_test_ = cb;
+}
+
AutomationEventRouter::AutomationListener::AutomationListener() {
}
diff --git a/chromium/chrome/browser/extensions/api/automation_internal/automation_event_router.h b/chromium/chrome/browser/extensions/api/automation_internal/automation_event_router.h
index 4994b1462a6..51dfc3f55d1 100644
--- a/chromium/chrome/browser/extensions/api/automation_internal/automation_event_router.h
+++ b/chromium/chrome/browser/extensions/api/automation_internal/automation_event_router.h
@@ -8,6 +8,7 @@
#include <set>
#include <vector>
+#include "base/callback_forward.h"
#include "base/macros.h"
#include "base/memory/singleton.h"
#include "chrome/common/extensions/api/automation_internal.h"
@@ -65,6 +66,8 @@ class AutomationEventRouter : public content::NotificationObserver {
// Notify the source extension of the action of an action result.
void DispatchActionResult(const ui::AXActionData& data, bool result);
+ void SetTreeDestroyedCallbackForTest(base::RepeatingCallback<void(int)> cb);
+
private:
struct AutomationListener {
AutomationListener();
@@ -109,6 +112,8 @@ class AutomationEventRouter : public content::NotificationObserver {
Profile* active_profile_;
+ base::RepeatingCallback<void(int)> tree_destroyed_callback_for_test_;
+
friend struct base::DefaultSingletonTraits<AutomationEventRouter>;
DISALLOW_COPY_AND_ASSIGN(AutomationEventRouter);
diff --git a/chromium/chrome/browser/extensions/api/automation_internal/automation_internal_api.cc b/chromium/chrome/browser/extensions/api/automation_internal/automation_internal_api.cc
index 86fd2e7fe18..c2caa575b25 100644
--- a/chromium/chrome/browser/extensions/api/automation_internal/automation_internal_api.cc
+++ b/chromium/chrome/browser/extensions/api/automation_internal/automation_internal_api.cc
@@ -52,8 +52,6 @@ namespace extensions {
class AutomationWebContentsObserver;
} // namespace extensions
-DEFINE_WEB_CONTENTS_USER_DATA_KEY(extensions::AutomationWebContentsObserver);
-
namespace extensions {
namespace {
diff --git a/chromium/chrome/browser/extensions/api/autotest_private/DEPS b/chromium/chrome/browser/extensions/api/autotest_private/DEPS
new file mode 100644
index 00000000000..53fd62a1517
--- /dev/null
+++ b/chromium/chrome/browser/extensions/api/autotest_private/DEPS
@@ -0,0 +1,3 @@
+include_rules = [
+ "+chrome/browser/ui/views/crostini",
+]
diff --git a/chromium/chrome/browser/extensions/api/autotest_private/autotest_private_api.cc b/chromium/chrome/browser/extensions/api/autotest_private/autotest_private_api.cc
index 49f4f3272c4..44c72495440 100644
--- a/chromium/chrome/browser/extensions/api/autotest_private/autotest_private_api.cc
+++ b/chromium/chrome/browser/extensions/api/autotest_private/autotest_private_api.cc
@@ -31,15 +31,19 @@
#include "ash/public/interfaces/constants.mojom.h"
#include "base/feature_list.h"
#include "chrome/browser/chromeos/arc/arc_util.h"
+#include "chrome/browser/chromeos/crostini/crostini_manager.h"
+#include "chrome/browser/chromeos/crostini/crostini_util.h"
#include "chrome/browser/chromeos/login/lock/screen_locker.h"
#include "chrome/browser/chromeos/printing/cups_printers_manager.h"
#include "chrome/browser/chromeos/system/input_device_settings.h"
#include "chrome/browser/profiles/profile_manager.h"
#include "chrome/browser/ui/ash/login_screen_client.h"
+#include "chrome/browser/ui/views/crostini/crostini_installer_view.h"
#include "chrome/common/chrome_features.h"
#include "chromeos/dbus/dbus_thread_manager.h"
#include "chromeos/dbus/session_manager_client.h"
#include "chromeos/printing/printer_configuration.h"
+#include "components/arc/arc_prefs.h"
#include "components/user_manager/user_manager.h"
#include "content/public/common/service_manager_connection.h"
#include "mojo/public/cpp/bindings/associated_binding.h"
@@ -573,6 +577,8 @@ AutotestPrivateSetPlayStoreEnabledFunction::Run() {
return RespondNow(
Error("ARC enabled state cannot be changed for the current user"));
}
+ profile->GetPrefs()->SetBoolean(arc::prefs::kArcLocationServiceEnabled,
+ true);
return RespondNow(NoArguments());
} else {
return RespondNow(Error("ARC is not available for the current user"));
@@ -581,6 +587,44 @@ AutotestPrivateSetPlayStoreEnabledFunction::Run() {
return RespondNow(Error("ARC is not available for the current platform"));
}
+ExtensionFunction::ResponseAction
+AutotestPrivateRunCrostiniInstallerFunction::Run() {
+ DVLOG(1) << "AutotestPrivateInstallCrostiniFunction";
+#if defined(OS_CHROMEOS)
+ if (!IsCrostiniUIAllowedForProfile(ProfileManager::GetActiveUserProfile())) {
+ return RespondNow(Error("Crostini is not available for the current user"));
+ }
+ // Run GUI installer which will install crostini vm / container and
+ // start terminal app on completion. After starting the installer,
+ // we call RestartCrostini and we will be put in the pending restarters
+ // queue and be notified on success/otherwise of installation.
+ Profile* profile = Profile::FromBrowserContext(browser_context());
+ CrostiniInstallerView::Show(profile);
+ CrostiniInstallerView::GetActiveViewForTesting()->Accept();
+ crostini::CrostiniManager::GetInstance()->RestartCrostini(
+ profile, kCrostiniDefaultVmName, kCrostiniDefaultContainerName,
+ base::BindOnce(
+ &AutotestPrivateRunCrostiniInstallerFunction::CrostiniRestarted,
+ this));
+
+ return RespondLater();
+#else
+ return RespondNow(
+ Error("Crostini is not available for the current platform"));
+#endif
+}
+
+#if defined(OS_CHROMEOS)
+void AutotestPrivateRunCrostiniInstallerFunction::CrostiniRestarted(
+ crostini::ConciergeClientResult result) {
+ if (result == crostini::ConciergeClientResult::SUCCESS) {
+ Respond(NoArguments());
+ } else {
+ Respond(Error("Error installing crostini"));
+ }
+}
+#endif
+
static base::LazyInstance<BrowserContextKeyedAPIFactory<AutotestPrivateAPI>>::
DestructorAtExit g_autotest_private_api_factory = LAZY_INSTANCE_INITIALIZER;
diff --git a/chromium/chrome/browser/extensions/api/autotest_private/autotest_private_api.h b/chromium/chrome/browser/extensions/api/autotest_private/autotest_private_api.h
index 4575604fc44..b0623a31be7 100644
--- a/chromium/chrome/browser/extensions/api/autotest_private/autotest_private_api.h
+++ b/chromium/chrome/browser/extensions/api/autotest_private/autotest_private_api.h
@@ -21,6 +21,12 @@ namespace message_center {
class Notification;
}
+#if defined(OS_CHROMEOS)
+namespace crostini {
+enum class ConciergeClientResult;
+}
+#endif
+
namespace extensions {
class AutotestPrivateLogoutFunction : public UIThreadExtensionFunction {
@@ -225,6 +231,23 @@ class AutotestPrivateSetPlayStoreEnabledFunction
ResponseAction Run() override;
};
+class AutotestPrivateRunCrostiniInstallerFunction
+ : public UIThreadExtensionFunction {
+ public:
+ AutotestPrivateRunCrostiniInstallerFunction() = default;
+ DECLARE_EXTENSION_FUNCTION("autotestPrivate.runCrostiniInstaller",
+ AUTOTESTPRIVATE_RUNCROSTINIINSTALLER)
+
+ private:
+ ~AutotestPrivateRunCrostiniInstallerFunction() override = default;
+ ResponseAction Run() override;
+#if defined(OS_CHROMEOS)
+ void CrostiniRestarted(crostini::ConciergeClientResult);
+#endif
+
+ DISALLOW_COPY_AND_ASSIGN(AutotestPrivateRunCrostiniInstallerFunction);
+};
+
class AutotestPrivateGetPrinterListFunction : public UIThreadExtensionFunction {
public:
AutotestPrivateGetPrinterListFunction() = default;
diff --git a/chromium/chrome/browser/extensions/api/bookmark_manager_private/bookmark_manager_private_api.cc b/chromium/chrome/browser/extensions/api/bookmark_manager_private/bookmark_manager_private_api.cc
index bbda385c078..17e44aa888b 100644
--- a/chromium/chrome/browser/extensions/api/bookmark_manager_private/bookmark_manager_private_api.cc
+++ b/chromium/chrome/browser/extensions/api/bookmark_manager_private/bookmark_manager_private_api.cc
@@ -51,9 +51,6 @@ using bookmarks::BookmarkNode;
using bookmarks::BookmarkNodeData;
using content::WebContents;
-DEFINE_WEB_CONTENTS_USER_DATA_KEY(
- extensions::BookmarkManagerPrivateDragEventRouter);
-
namespace extensions {
namespace bookmark_keys = bookmark_api_constants;
diff --git a/chromium/chrome/browser/extensions/api/bookmarks/bookmarks_api.cc b/chromium/chrome/browser/extensions/api/bookmarks/bookmarks_api.cc
index c4d79e3a704..5d6b31d7100 100644
--- a/chromium/chrome/browser/extensions/api/bookmarks/bookmarks_api.cc
+++ b/chromium/chrome/browser/extensions/api/bookmarks/bookmarks_api.cc
@@ -21,7 +21,7 @@
#include "base/strings/string_number_conversions.h"
#include "base/strings/string_util.h"
#include "base/strings/utf_string_conversions.h"
-#include "base/task_scheduler/post_task.h"
+#include "base/task/post_task.h"
#include "base/time/time.h"
#include "build/build_config.h"
#include "chrome/browser/bookmarks/bookmark_html_writer.h"
diff --git a/chromium/chrome/browser/extensions/api/braille_display_private/braille_controller.h b/chromium/chrome/browser/extensions/api/braille_display_private/braille_controller.h
index 5b575d2a32e..528720943d7 100644
--- a/chromium/chrome/browser/extensions/api/braille_display_private/braille_controller.h
+++ b/chromium/chrome/browser/extensions/api/braille_display_private/braille_controller.h
@@ -24,7 +24,7 @@ class BrailleController {
static BrailleController* GetInstance();
virtual std::unique_ptr<DisplayState> GetDisplayState() = 0;
- virtual void WriteDots(const std::vector<char>& cells,
+ virtual void WriteDots(const std::vector<uint8_t>& cells,
unsigned int cols,
unsigned int rows) = 0;
virtual void AddObserver(BrailleObserver* observer) = 0;
diff --git a/chromium/chrome/browser/extensions/api/braille_display_private/braille_controller_brlapi.cc b/chromium/chrome/browser/extensions/api/braille_display_private/braille_controller_brlapi.cc
index a57126facdc..9b506217c61 100644
--- a/chromium/chrome/browser/extensions/api/braille_display_private/braille_controller_brlapi.cc
+++ b/chromium/chrome/browser/extensions/api/braille_display_private/braille_controller_brlapi.cc
@@ -15,7 +15,7 @@
#include "base/bind.h"
#include "base/bind_helpers.h"
#include "base/macros.h"
-#include "base/task_scheduler/post_task.h"
+#include "base/task/post_task.h"
#include "base/time/time.h"
#include "chrome/browser/extensions/api/braille_display_private/brlapi_connection.h"
#include "chrome/browser/extensions/api/braille_display_private/brlapi_keycode_map.h"
@@ -27,12 +27,17 @@ namespace api {
namespace braille_display_private {
namespace {
+
// Delay between detecting a directory update and trying to connect
// to the brlapi.
-const int64_t kConnectionDelayMs = 500;
+constexpr base::TimeDelta kConnectionDelay =
+ base::TimeDelta::FromMilliseconds(500);
+
// How long to periodically retry connecting after a brltty restart.
// Some displays are slow to connect.
-const int64_t kConnectRetryTimeout = 20000;
+constexpr base::TimeDelta kConnectRetryTimeout =
+ base::TimeDelta::FromSeconds(20);
+
} // namespace
BrailleController::BrailleController() {
@@ -100,7 +105,7 @@ std::unique_ptr<DisplayState> BrailleControllerImpl::GetDisplayState() {
return display_state;
}
-void BrailleControllerImpl::WriteDots(const std::vector<char>& cells,
+void BrailleControllerImpl::WriteDots(const std::vector<uint8_t>& cells,
unsigned int cells_cols,
unsigned int cells_rows) {
DCHECK_CURRENTLY_ON(BrowserThread::IO);
@@ -248,19 +253,16 @@ void BrailleControllerImpl::TryToConnect() {
void BrailleControllerImpl::ResetRetryConnectHorizon() {
DCHECK_CURRENTLY_ON(BrowserThread::IO);
- retry_connect_horizon_ =
- base::Time::Now() +
- base::TimeDelta::FromMilliseconds(kConnectRetryTimeout);
+ retry_connect_horizon_ = base::Time::Now() + kConnectRetryTimeout;
}
void BrailleControllerImpl::ScheduleTryToConnect() {
DCHECK_CURRENTLY_ON(BrowserThread::IO);
- base::TimeDelta delay(base::TimeDelta::FromMilliseconds(kConnectionDelayMs));
// Don't reschedule if there's already a connect scheduled or
// the next attempt would fall outside of the retry limit.
if (connect_scheduled_)
return;
- if (base::Time::Now() + delay > retry_connect_horizon_) {
+ if (base::Time::Now() + kConnectionDelay > retry_connect_horizon_) {
VLOG(1) << "Stopping to retry to connect to brlapi";
return;
}
@@ -270,7 +272,7 @@ void BrailleControllerImpl::ScheduleTryToConnect() {
BrowserThread::IO, FROM_HERE,
base::BindOnce(&BrailleControllerImpl::TryToConnect,
base::Unretained(this)),
- delay);
+ kConnectionDelay);
}
void BrailleControllerImpl::Disconnect() {
diff --git a/chromium/chrome/browser/extensions/api/braille_display_private/braille_controller_brlapi.h b/chromium/chrome/browser/extensions/api/braille_display_private/braille_controller_brlapi.h
index 82fe471bf73..fc98d3d832d 100644
--- a/chromium/chrome/browser/extensions/api/braille_display_private/braille_controller_brlapi.h
+++ b/chromium/chrome/browser/extensions/api/braille_display_private/braille_controller_brlapi.h
@@ -25,7 +25,7 @@ class BrailleControllerImpl : public BrailleController {
public:
static BrailleControllerImpl* GetInstance();
std::unique_ptr<DisplayState> GetDisplayState() override;
- void WriteDots(const std::vector<char>& cells,
+ void WriteDots(const std::vector<uint8_t>& cells,
unsigned int cols,
unsigned int rows) override;
void AddObserver(BrailleObserver* observer) override;
@@ -78,7 +78,7 @@ class BrailleControllerImpl : public BrailleController {
scoped_refptr<base::SequencedTaskRunner> sequenced_task_runner_;
// Manipulated on the UI thread.
- base::ObserverList<BrailleObserver> observers_;
+ base::ObserverList<BrailleObserver>::Unchecked observers_;
// Manipulated by the SequencedTaskRunner.
base::FilePathWatcher file_path_watcher_;
diff --git a/chromium/chrome/browser/extensions/api/braille_display_private/stub_braille_controller.cc b/chromium/chrome/browser/extensions/api/braille_display_private/stub_braille_controller.cc
index 5e8a8c5be24..e732981f223 100644
--- a/chromium/chrome/browser/extensions/api/braille_display_private/stub_braille_controller.cc
+++ b/chromium/chrome/browser/extensions/api/braille_display_private/stub_braille_controller.cc
@@ -15,7 +15,7 @@ std::unique_ptr<DisplayState> StubBrailleController::GetDisplayState() {
return std::unique_ptr<DisplayState>(new DisplayState);
}
-void StubBrailleController::WriteDots(const std::vector<char>& cells,
+void StubBrailleController::WriteDots(const std::vector<uint8_t>& cells,
unsigned int cols,
unsigned int rows) {}
diff --git a/chromium/chrome/browser/extensions/api/braille_display_private/stub_braille_controller.h b/chromium/chrome/browser/extensions/api/braille_display_private/stub_braille_controller.h
index cc159125575..44f36ad080b 100644
--- a/chromium/chrome/browser/extensions/api/braille_display_private/stub_braille_controller.h
+++ b/chromium/chrome/browser/extensions/api/braille_display_private/stub_braille_controller.h
@@ -17,7 +17,7 @@ class StubBrailleController : public BrailleController {
public:
StubBrailleController();
std::unique_ptr<DisplayState> GetDisplayState() override;
- void WriteDots(const std::vector<char>& cells,
+ void WriteDots(const std::vector<uint8_t>& cells,
unsigned int cols,
unsigned int rows) override;
void AddObserver(BrailleObserver* observer) override;
diff --git a/chromium/chrome/browser/extensions/api/browsing_data/browsing_data_api.cc b/chromium/chrome/browser/extensions/api/browsing_data/browsing_data_api.cc
index 244be025170..9c960c21cdb 100644
--- a/chromium/chrome/browser/extensions/api/browsing_data/browsing_data_api.cc
+++ b/chromium/chrome/browser/extensions/api/browsing_data/browsing_data_api.cc
@@ -14,11 +14,15 @@
#include "base/values.h"
#include "chrome/browser/browsing_data/browsing_data_helper.h"
-#include "base/task_scheduler/post_task.h"
+#include "base/task/post_task.h"
#include "chrome/browser/browsing_data/chrome_browsing_data_remover_delegate.h"
#include "chrome/browser/plugins/plugin_data_remover_helper.h"
#include "chrome/browser/plugins/plugin_prefs.h"
#include "chrome/browser/profiles/profile.h"
+#include "chrome/browser/signin/account_reconcilor_factory.h"
+#include "chrome/browser/signin/signin_manager_factory.h"
+#include "chrome/browser/sync/profile_sync_service_factory.h"
+#include "chrome/browser/sync/sync_ui_util.h"
#include "chrome/browser/ui/browser.h"
#include "chrome/common/chrome_features.h"
#include "chrome/common/pref_names.h"
@@ -123,6 +127,16 @@ bool IsRemovalPermitted(int removal_mask, PrefService* prefs) {
return true;
}
+// Returns true if Sync is currently running (i.e. enabled and not in error).
+bool IsSyncRunning(Profile* profile) {
+ browser_sync::ProfileSyncService* sync_service =
+ ProfileSyncServiceFactory::GetForProfile(profile);
+ SigninManagerBase* signin_manager =
+ SigninManagerFactory::GetForProfile(profile);
+ sync_ui_util::MessageType sync_status =
+ sync_ui_util::GetStatus(profile, sync_service, *signin_manager);
+ return sync_status == sync_ui_util::SYNCED;
+}
} // namespace
bool BrowsingDataSettingsFunction::isDataTypeSelected(
@@ -253,11 +267,9 @@ BrowsingDataRemoverFunction::BrowsingDataRemoverFunction() : observer_(this) {}
void BrowsingDataRemoverFunction::OnBrowsingDataRemoverDone() {
DCHECK_CURRENTLY_ON(BrowserThread::UI);
-
+ synced_data_deletion_.reset();
observer_.RemoveAll();
-
this->SendResponse(true);
-
Release(); // Balanced in RunAsync.
}
@@ -316,6 +328,10 @@ bool BrowsingDataRemoverFunction::RunAsync() {
BrowsingDataRemoverFunction::~BrowsingDataRemoverFunction() {}
+bool BrowsingDataRemoverFunction::IsPauseSyncAllowed() {
+ return true;
+}
+
void BrowsingDataRemoverFunction::CheckRemovingPluginDataSupported(
scoped_refptr<PluginPrefs> plugin_prefs) {
if (!PluginDataRemoverHelper::IsSupported(plugin_prefs.get()))
@@ -327,11 +343,20 @@ void BrowsingDataRemoverFunction::CheckRemovingPluginDataSupported(
}
void BrowsingDataRemoverFunction::StartRemoving() {
+ Profile* profile = GetProfile();
content::BrowsingDataRemover* remover =
- content::BrowserContext::GetBrowsingDataRemover(GetProfile());
+ content::BrowserContext::GetBrowsingDataRemover(profile);
+
// Add a ref (Balanced in OnBrowsingDataRemoverDone)
AddRef();
+ // Prevent Sync from being paused, if required.
+ DCHECK(!synced_data_deletion_);
+ if (!IsPauseSyncAllowed() && IsSyncRunning(profile)) {
+ synced_data_deletion_ = AccountReconcilorFactory::GetForProfile(profile)
+ ->GetScopedSyncDataDeletion();
+ }
+
// Create a BrowsingDataRemover, set the current object as an observer (so
// that we're notified after removal) and call remove() with the arguments
// we've generated above. We can use a raw pointer here, as the browsing data
@@ -418,6 +443,10 @@ bool BrowsingDataRemoveFunction::GetRemovalMask(int* removal_mask) {
return true;
}
+bool BrowsingDataRemoveFunction::IsPauseSyncAllowed() {
+ return false;
+}
+
bool BrowsingDataRemoveAppcacheFunction::GetRemovalMask(int* removal_mask) {
*removal_mask = content::BrowsingDataRemover::DATA_TYPE_APP_CACHE;
return true;
diff --git a/chromium/chrome/browser/extensions/api/browsing_data/browsing_data_api.h b/chromium/chrome/browser/extensions/api/browsing_data/browsing_data_api.h
index 15db8b7d0ed..d288fc63ee5 100644
--- a/chromium/chrome/browser/extensions/api/browsing_data/browsing_data_api.h
+++ b/chromium/chrome/browser/extensions/api/browsing_data/browsing_data_api.h
@@ -14,6 +14,7 @@
#include "base/scoped_observer.h"
#include "chrome/browser/extensions/chrome_extension_function.h"
#include "components/browsing_data/core/browsing_data_utils.h"
+#include "components/signin/core/browser/account_reconcilor.h"
#include "content/public/browser/browsing_data_remover.h"
class PluginPrefs;
@@ -104,13 +105,19 @@ class BrowsingDataRemoverFunction
protected:
~BrowsingDataRemoverFunction() override;
+ private:
// Children should override this method to provide the proper removal mask
// based on the API call they represent.
// Returns whether or not removal mask retrieval was successful.
// |removal_mask| is populated with the result, if successful.
virtual bool GetRemovalMask(int* removal_mask) = 0;
- private:
+ // Returns true if the data removal is allowed to pause Sync. Returns true by
+ // default. Subclasses can override it to return false and prevent Sync from
+ // being paused. This is important when synced data is being removed, and
+ // pausing Sync would prevent the data from being deleted on the server.
+ virtual bool IsPauseSyncAllowed();
+
// Updates the removal bitmask according to whether removing plugin data is
// supported or not.
void CheckRemovingPluginDataSupported(
@@ -131,6 +138,8 @@ class BrowsingDataRemoverFunction
ScopedObserver<content::BrowsingDataRemover,
content::BrowsingDataRemover::Observer>
observer_;
+ std::unique_ptr<AccountReconcilor::ScopedSyncedDataDeletion>
+ synced_data_deletion_;
};
class BrowsingDataRemoveAppcacheFunction : public BrowsingDataRemoverFunction {
@@ -154,6 +163,7 @@ class BrowsingDataRemoveFunction : public BrowsingDataRemoverFunction {
// BrowsingDataRemoverFunction:
bool GetRemovalMask(int* removal_mask) override;
+ bool IsPauseSyncAllowed() override;
};
class BrowsingDataRemoveCacheFunction : public BrowsingDataRemoverFunction {
diff --git a/chromium/chrome/browser/extensions/api/browsing_data/browsing_data_test.cc b/chromium/chrome/browser/extensions/api/browsing_data/browsing_data_test.cc
index aeea3eef7bb..4208518f151 100644
--- a/chromium/chrome/browser/extensions/api/browsing_data/browsing_data_test.cc
+++ b/chromium/chrome/browser/extensions/api/browsing_data/browsing_data_test.cc
@@ -5,23 +5,42 @@
#include <memory>
#include <string>
+#include "base/callback.h"
#include "base/json/json_string_value_serializer.h"
#include "base/memory/ref_counted.h"
#include "base/strings/pattern.h"
#include "base/strings/string_util.h"
+#include "base/test/bind_test_util.h"
#include "base/values.h"
#include "chrome/browser/browsing_data/browsing_data_helper.h"
#include "chrome/browser/browsing_data/chrome_browsing_data_remover_delegate.h"
#include "chrome/browser/extensions/api/browsing_data/browsing_data_api.h"
#include "chrome/browser/extensions/extension_function_test_utils.h"
#include "chrome/browser/profiles/profile.h"
+#include "chrome/browser/signin/account_reconcilor_factory.h"
+#include "chrome/browser/signin/profile_oauth2_token_service_factory.h"
+#include "chrome/browser/signin/scoped_account_consistency.h"
+#include "chrome/browser/signin/signin_manager_factory.h"
+#include "chrome/browser/sync/profile_sync_service_factory.h"
+#include "chrome/browser/sync/sync_ui_util.h"
#include "chrome/browser/ui/browser.h"
#include "chrome/common/pref_names.h"
#include "chrome/test/base/in_process_browser_test.h"
+#include "components/browser_sync/profile_sync_service.h"
#include "components/browsing_data/core/browsing_data_utils.h"
#include "components/browsing_data/core/pref_names.h"
#include "components/prefs/pref_service.h"
+#include "components/signin/core/browser/account_reconcilor.h"
+#include "components/signin/core/browser/profile_oauth2_token_service.h"
+#include "components/signin/core/browser/signin_buildflags.h"
+#include "components/signin/core/browser/signin_manager.h"
#include "content/public/browser/browsing_data_remover.h"
+#include "content/public/browser/storage_partition.h"
+#include "google_apis/gaia/gaia_urls.h"
+#include "google_apis/gaia/google_service_auth_error.h"
+#include "mojo/public/cpp/bindings/callback_helpers.h"
+#include "net/cookies/canonical_cookie.h"
+#include "url/gurl.h"
using extension_function_test_utils::RunFunctionAndReturnError;
using extension_function_test_utils::RunFunctionAndReturnSingleResult;
@@ -298,6 +317,34 @@ class ExtensionBrowsingDataTest : public InProcessBrowserTest {
content::BrowsingDataRemover* remover_;
};
+#if BUILDFLAG(ENABLE_DICE_SUPPORT)
+// Sets the APISID Gaia cookie, which is monitored by the AccountReconcilor.
+bool SetGaiaCookieForProfile(Profile* profile) {
+ GURL google_url = GaiaUrls::GetInstance()->google_url();
+ net::CanonicalCookie cookie("APISID", std::string(), "." + google_url.host(),
+ "/", base::Time(), base::Time(), base::Time(),
+ false, false, net::CookieSameSite::DEFAULT_MODE,
+ net::COOKIE_PRIORITY_DEFAULT);
+
+ bool success = false;
+ base::RunLoop loop;
+ base::OnceClosure loop_quit = loop.QuitClosure();
+ base::OnceCallback<void(bool)> callback =
+ base::BindLambdaForTesting([&success, &loop_quit](bool s) {
+ success = s;
+ std::move(loop_quit).Run();
+ });
+ network::mojom::CookieManager* cookie_manager =
+ content::BrowserContext::GetDefaultStoragePartition(profile)
+ ->GetCookieManagerForBrowserProcess();
+ cookie_manager->SetCanonicalCookie(
+ cookie, true, true,
+ mojo::WrapCallbackWithDefaultInvokeIfNotRun(std::move(callback), false));
+ loop.Run();
+ return success;
+}
+#endif
+
} // namespace
IN_PROC_BROWSER_TEST_F(ExtensionBrowsingDataTest, RemovalProhibited) {
@@ -358,6 +405,101 @@ IN_PROC_BROWSER_TEST_F(ExtensionBrowsingDataTest, RemoveBrowsingDataAll) {
GetRemovalMask());
}
+#if BUILDFLAG(ENABLE_DICE_SUPPORT)
+// Test that Sync is not paused when browsing data is cleared.
+IN_PROC_BROWSER_TEST_F(ExtensionBrowsingDataTest, Syncing) {
+ Profile* profile = browser()->profile();
+ // Set a Gaia cookie.
+ ASSERT_TRUE(SetGaiaCookieForProfile(profile));
+ // Set a Sync account and a secondary account.
+ const char kPrimaryAccountId[] = "primary_account_id";
+ const char kSecondaryAccountId[] = "secondary_account_id";
+ ProfileOAuth2TokenService* token_service =
+ ProfileOAuth2TokenServiceFactory::GetForProfile(profile);
+ token_service->UpdateCredentials(kPrimaryAccountId, "token");
+ ASSERT_TRUE(token_service->RefreshTokenIsAvailable(kPrimaryAccountId));
+ token_service->UpdateCredentials(kSecondaryAccountId, "token");
+ ASSERT_TRUE(token_service->RefreshTokenIsAvailable(kSecondaryAccountId));
+ SigninManager* signin_manager = SigninManagerFactory::GetForProfile(profile);
+ signin_manager->SetAuthenticatedAccountInfo(kPrimaryAccountId,
+ "user@gmail.com");
+ // Sync is running.
+ browser_sync::ProfileSyncService* sync_service =
+ ProfileSyncServiceFactory::GetForProfile(profile);
+ sync_service->SetFirstSetupComplete();
+ sync_ui_util::MessageType sync_status =
+ sync_ui_util::GetStatus(profile, sync_service, *signin_manager);
+ ASSERT_EQ(sync_ui_util::SYNCED, sync_status);
+ // Clear browsing data.
+ scoped_refptr<BrowsingDataRemoveFunction> function =
+ new BrowsingDataRemoveFunction();
+ EXPECT_EQ(NULL, RunFunctionAndReturnSingleResult(
+ function.get(), kRemoveEverythingArguments, browser()));
+ // Check that the Sync token was not revoked.
+ EXPECT_TRUE(token_service->RefreshTokenIsAvailable(kPrimaryAccountId));
+ EXPECT_FALSE(token_service->RefreshTokenHasError(kPrimaryAccountId));
+ // Check that the secondary token was revoked.
+ EXPECT_FALSE(token_service->RefreshTokenIsAvailable(kSecondaryAccountId));
+}
+
+// Test that Sync is paused when browsing data is cleared if Sync was in
+// authentication error.
+IN_PROC_BROWSER_TEST_F(ExtensionBrowsingDataTest, SyncError) {
+ Profile* profile = browser()->profile();
+ // Set a Gaia cookie.
+ ASSERT_TRUE(SetGaiaCookieForProfile(profile));
+ // Set a Sync account with authentication error.
+ const char kAccountId[] = "account_id";
+ ProfileOAuth2TokenService* token_service =
+ ProfileOAuth2TokenServiceFactory::GetForProfile(profile);
+ token_service->UpdateCredentials(kAccountId, "token");
+ ASSERT_TRUE(token_service->RefreshTokenIsAvailable(kAccountId));
+ SigninManager* signin_manager = SigninManagerFactory::GetForProfile(profile);
+ signin_manager->SetAuthenticatedAccountInfo(kAccountId, "user@gmail.com");
+ token_service->GetDelegate()->UpdateAuthError(
+ kAccountId, GoogleServiceAuthError::FromInvalidGaiaCredentialsReason(
+ GoogleServiceAuthError::InvalidGaiaCredentialsReason::
+ CREDENTIALS_REJECTED_BY_SERVER));
+ // Sync is not running.
+ sync_ui_util::MessageType sync_status = sync_ui_util::GetStatus(
+ profile, ProfileSyncServiceFactory::GetForProfile(profile),
+ *signin_manager);
+ ASSERT_NE(sync_ui_util::SYNCED, sync_status);
+ // Clear browsing data.
+ scoped_refptr<BrowsingDataRemoveFunction> function =
+ new BrowsingDataRemoveFunction();
+ EXPECT_EQ(NULL, RunFunctionAndReturnSingleResult(
+ function.get(), kRemoveEverythingArguments, browser()));
+ // Check that the account was not removed and Sync was paused.
+ EXPECT_TRUE(token_service->RefreshTokenIsAvailable(kAccountId));
+ EXPECT_EQ(GoogleServiceAuthError::InvalidGaiaCredentialsReason::
+ CREDENTIALS_REJECTED_BY_CLIENT,
+ token_service->GetAuthError(kAccountId)
+ .GetInvalidGaiaCredentialsReason());
+}
+
+// Test that the tokens are revoked when browsing data is cleared when there is
+// no primary account.
+IN_PROC_BROWSER_TEST_F(ExtensionBrowsingDataTest, NotSyncing) {
+ Profile* profile = browser()->profile();
+ // Set a Gaia cookie.
+ ASSERT_TRUE(SetGaiaCookieForProfile(profile));
+ // Set a non-Sync account.
+ const char kAccountId[] = "account_id";
+ ProfileOAuth2TokenService* token_service =
+ ProfileOAuth2TokenServiceFactory::GetForProfile(profile);
+ token_service->UpdateCredentials(kAccountId, "token");
+ ASSERT_TRUE(token_service->RefreshTokenIsAvailable(kAccountId));
+ // Clear browsing data.
+ scoped_refptr<BrowsingDataRemoveFunction> function =
+ new BrowsingDataRemoveFunction();
+ EXPECT_EQ(NULL, RunFunctionAndReturnSingleResult(
+ function.get(), kRemoveEverythingArguments, browser()));
+ // Check that the account was removed.
+ EXPECT_FALSE(token_service->RefreshTokenIsAvailable(kAccountId));
+}
+#endif
+
IN_PROC_BROWSER_TEST_F(ExtensionBrowsingDataTest, BrowsingDataOriginTypeMask) {
RunBrowsingDataRemoveFunctionAndCompareOriginTypeMask("{}", 0);
diff --git a/chromium/chrome/browser/extensions/api/certificate_provider/certificate_provider_api.cc b/chromium/chrome/browser/extensions/api/certificate_provider/certificate_provider_api.cc
index 8596f7dd5f0..260ed83d77f 100644
--- a/chromium/chrome/browser/extensions/api/certificate_provider/certificate_provider_api.cc
+++ b/chromium/chrome/browser/extensions/api/certificate_provider/certificate_provider_api.cc
@@ -96,7 +96,7 @@ CertificateProviderInternalReportCertificatesFunction::Run() {
}
chromeos::certificate_provider::CertificateInfoList cert_infos;
- std::vector<std::vector<char>> rejected_certificates;
+ std::vector<std::vector<uint8_t>> rejected_certificates;
for (const api_cp::CertificateInfo& input_cert_info : *params->certificates) {
chromeos::certificate_provider::CertificateInfo parsed_cert_info;
@@ -122,7 +122,7 @@ bool CertificateProviderInternalReportCertificatesFunction::
ParseCertificateInfo(
const api_cp::CertificateInfo& info,
chromeos::certificate_provider::CertificateInfo* out_info) {
- const std::vector<char>& cert_der = info.certificate;
+ const std::vector<uint8_t>& cert_der = info.certificate;
if (cert_der.empty()) {
WriteToConsole(content::CONSOLE_MESSAGE_LEVEL_ERROR,
kCertificateProviderErrorInvalidX509Cert);
@@ -134,7 +134,7 @@ bool CertificateProviderInternalReportCertificatesFunction::
net::X509Certificate::UnsafeCreateOptions options;
options.printable_string_is_utf8 = true;
out_info->certificate = net::X509Certificate::CreateFromBytesUnsafeOptions(
- cert_der.data(), cert_der.size(), options);
+ reinterpret_cast<const char*>(cert_der.data()), cert_der.size(), options);
if (!out_info->certificate) {
WriteToConsole(content::CONSOLE_MESSAGE_LEVEL_ERROR,
kCertificateProviderErrorInvalidX509Cert);
diff --git a/chromium/chrome/browser/extensions/api/cloud_print_private/cloud_print_private_api.cc b/chromium/chrome/browser/extensions/api/cloud_print_private/cloud_print_private_api.cc
index 193801d9a5f..817b5ca8b26 100644
--- a/chromium/chrome/browser/extensions/api/cloud_print_private/cloud_print_private_api.cc
+++ b/chromium/chrome/browser/extensions/api/cloud_print_private/cloud_print_private_api.cc
@@ -6,6 +6,7 @@
#include <memory>
#include <string>
+#include <utility>
#include "chrome/browser/printing/cloud_print/cloud_print_proxy_service.h"
#include "chrome/browser/printing/cloud_print/cloud_print_proxy_service_factory.h"
@@ -109,10 +110,8 @@ ExtensionFunction::ResponseAction CloudPrintPrivateGetPrintersFunction::Run() {
if (!service)
return RespondNow(Error(kErrorIncognito));
- // TODO(https://crbug.com/845250): CloudPrintProxyService::GetPrinters() may
- // not invoke the callback, which means this function may never respond.
service->GetPrinters(
- base::Bind(&CloudPrintPrivateGetPrintersFunction::SendResults, this));
+ base::BindOnce(&CloudPrintPrivateGetPrintersFunction::SendResults, this));
return RespondLater();
}
diff --git a/chromium/chrome/browser/extensions/api/commands/command_service.h b/chromium/chrome/browser/extensions/api/commands/command_service.h
index 378922ae5fe..22d82e817a1 100644
--- a/chromium/chrome/browser/extensions/api/commands/command_service.h
+++ b/chromium/chrome/browser/extensions/api/commands/command_service.h
@@ -265,7 +265,7 @@ class CommandService : public BrowserContextKeyedAPI,
ScopedObserver<ExtensionRegistry, ExtensionRegistryObserver>
extension_registry_observer_;
- base::ObserverList<Observer> observers_;
+ base::ObserverList<Observer>::Unchecked observers_;
DISALLOW_COPY_AND_ASSIGN(CommandService);
};
diff --git a/chromium/chrome/browser/extensions/api/content_settings/content_settings_api.cc b/chromium/chrome/browser/extensions/api/content_settings/content_settings_api.cc
index b361c7babdc..85bbb998db9 100644
--- a/chromium/chrome/browser/extensions/api/content_settings/content_settings_api.cc
+++ b/chromium/chrome/browser/extensions/api/content_settings/content_settings_api.cc
@@ -11,6 +11,8 @@
#include "base/bind.h"
#include "base/command_line.h"
+#include "base/feature_list.h"
+#include "base/metrics/histogram_macros.h"
#include "base/strings/stringprintf.h"
#include "base/values.h"
#include "chrome/browser/content_settings/cookie_settings_factory.h"
@@ -24,6 +26,7 @@
#include "chrome/browser/plugins/plugin_finder.h"
#include "chrome/browser/plugins/plugin_installer.h"
#include "chrome/browser/profiles/profile.h"
+#include "chrome/common/chrome_features.h"
#include "chrome/common/chrome_switches.h"
#include "chrome/common/extensions/api/content_settings.h"
#include "components/content_settings/core/browser/content_settings_info.h"
@@ -31,6 +34,7 @@
#include "components/content_settings/core/browser/content_settings_utils.h"
#include "components/content_settings/core/browser/cookie_settings.h"
#include "components/content_settings/core/browser/host_content_settings_map.h"
+#include "components/content_settings/core/common/content_settings.h"
#include "content/public/browser/browser_thread.h"
#include "content/public/browser/plugin_service.h"
#include "content/public/common/webplugininfo.h"
@@ -214,6 +218,10 @@ ContentSettingsContentSettingSetFunction::Run() {
->Get(content_type)
->IsSettingValid(setting));
+ const content_settings::ContentSettingsInfo* info =
+ content_settings::ContentSettingsRegistry::GetInstance()->Get(
+ content_type);
+
// Some content setting types support the full set of values listed in
// content_settings.json only for exceptions. For the default setting,
// some values might not be supported.
@@ -221,9 +229,7 @@ ContentSettingsContentSettingSetFunction::Run() {
// [ask, block] for the default setting.
if (primary_pattern == ContentSettingsPattern::Wildcard() &&
secondary_pattern == ContentSettingsPattern::Wildcard() &&
- !content_settings::ContentSettingsRegistry::GetInstance()
- ->Get(content_type)
- ->IsDefaultSettingValid(setting)) {
+ !info->IsDefaultSettingValid(setting)) {
static const char kUnsupportedDefaultSettingError[] =
"'%s' is not supported as the default setting of %s.";
@@ -243,6 +249,15 @@ ContentSettingsContentSettingSetFunction::Run() {
readable_type_name.c_str())));
}
+ if (primary_pattern != secondary_pattern &&
+ secondary_pattern != ContentSettingsPattern::Wildcard() &&
+ !info->website_settings_info()->SupportsEmbeddedExceptions() &&
+ base::FeatureList::IsEnabled(::features::kPermissionDelegation)) {
+ static const char kUnsupportedEmbeddedException[] =
+ "Embedded patterns are not supported for this setting.";
+ return RespondNow(Error(kUnsupportedEmbeddedException));
+ }
+
ExtensionPrefsScope scope = kExtensionPrefsScopeRegular;
bool incognito = false;
if (params->details.scope ==
@@ -273,6 +288,18 @@ ContentSettingsContentSettingSetFunction::Run() {
return RespondNow(Error(pref_keys::kIncognitoSessionOnlyErrorMessage));
}
+ size_t num_values = 0;
+ int histogram_value =
+ ContentSettingTypeToHistogramValue(content_type, &num_values);
+ if (primary_pattern != secondary_pattern &&
+ secondary_pattern != ContentSettingsPattern::Wildcard()) {
+ UMA_HISTOGRAM_EXACT_LINEAR("ContentSettings.ExtensionEmbeddedSettingSet",
+ histogram_value, num_values);
+ } else {
+ UMA_HISTOGRAM_EXACT_LINEAR("ContentSettings.ExtensionNonEmbeddedSettingSet",
+ histogram_value, num_values);
+ }
+
scoped_refptr<ContentSettingsStore> store =
ContentSettingsService::Get(browser_context())->content_settings_store();
store->SetExtensionContentSetting(extension_id(), primary_pattern,
diff --git a/chromium/chrome/browser/extensions/api/content_settings/content_settings_apitest.cc b/chromium/chrome/browser/extensions/api/content_settings/content_settings_apitest.cc
index 2699c31961f..155603ec248 100644
--- a/chromium/chrome/browser/extensions/api/content_settings/content_settings_apitest.cc
+++ b/chromium/chrome/browser/extensions/api/content_settings/content_settings_apitest.cc
@@ -8,6 +8,8 @@
#include "base/location.h"
#include "base/single_thread_task_runner.h"
#include "base/strings/utf_string_conversions.h"
+#include "base/test/metrics/histogram_tester.h"
+#include "base/test/scoped_feature_list.h"
#include "base/threading/thread_task_runner_handle.h"
#include "build/build_config.h"
#include "chrome/browser/chrome_notification_types.h"
@@ -17,9 +19,11 @@
#include "chrome/browser/extensions/extension_apitest.h"
#include "chrome/browser/profiles/profile.h"
#include "chrome/browser/ui/browser.h"
+#include "chrome/common/chrome_features.h"
#include "chrome/common/chrome_switches.h"
#include "components/content_settings/core/browser/cookie_settings.h"
#include "components/content_settings/core/browser/host_content_settings_map.h"
+#include "components/content_settings/core/common/content_settings.h"
#include "components/keep_alive_registry/keep_alive_types.h"
#include "components/keep_alive_registry/scoped_keep_alive.h"
#include "components/prefs/pref_service.h"
@@ -359,4 +363,50 @@ IN_PROC_BROWSER_TEST_F(ExtensionContentSettingsApiTest,
<< message_;
}
+IN_PROC_BROWSER_TEST_F(ExtensionContentSettingsApiTest,
+ EmbeddedSettingsMetric) {
+ base::HistogramTester histogram_tester;
+ const char kExtensionPath[] = "content_settings/embeddedsettingsmetric";
+ EXPECT_TRUE(RunExtensionSubtest(kExtensionPath, "test.html")) << message_;
+
+ size_t num_values = 0;
+ int javascript_type = ContentSettingTypeToHistogramValue(
+ CONTENT_SETTINGS_TYPE_IMAGES, &num_values);
+ int geolocation_type = ContentSettingTypeToHistogramValue(
+ CONTENT_SETTINGS_TYPE_GEOLOCATION, &num_values);
+ int cookies_type = ContentSettingTypeToHistogramValue(
+ CONTENT_SETTINGS_TYPE_COOKIES, &num_values);
+
+ histogram_tester.ExpectBucketCount(
+ "ContentSettings.ExtensionEmbeddedSettingSet", javascript_type, 1);
+ histogram_tester.ExpectBucketCount(
+ "ContentSettings.ExtensionEmbeddedSettingSet", geolocation_type, 1);
+ histogram_tester.ExpectTotalCount(
+ "ContentSettings.ExtensionEmbeddedSettingSet", 2);
+
+ histogram_tester.ExpectBucketCount(
+ "ContentSettings.ExtensionNonEmbeddedSettingSet", javascript_type, 1);
+ histogram_tester.ExpectBucketCount(
+ "ContentSettings.ExtensionNonEmbeddedSettingSet", cookies_type, 1);
+ histogram_tester.ExpectTotalCount(
+ "ContentSettings.ExtensionNonEmbeddedSettingSet", 2);
+}
+
+IN_PROC_BROWSER_TEST_F(ExtensionContentSettingsApiTest, EmbeddedSettings) {
+ base::test::ScopedFeatureList scoped_feature_list;
+ scoped_feature_list.InitAndDisableFeature(features::kPermissionDelegation);
+ const char kExtensionPath[] = "content_settings/embeddedsettings";
+ EXPECT_TRUE(RunExtensionSubtest(kExtensionPath, "test.html")) << message_;
+}
+
+IN_PROC_BROWSER_TEST_F(ExtensionContentSettingsApiTest,
+ EmbeddedSettingsPermissionDelegation) {
+ base::test::ScopedFeatureList scoped_feature_list;
+ scoped_feature_list.InitAndEnableFeature(features::kPermissionDelegation);
+ const char kExtensionPath[] = "content_settings/embeddedsettings";
+ EXPECT_TRUE(
+ RunExtensionSubtest(kExtensionPath, "test.html?permission_delegation"))
+ << message_;
+}
+
} // namespace extensions
diff --git a/chromium/chrome/browser/extensions/api/content_settings/content_settings_service.cc b/chromium/chrome/browser/extensions/api/content_settings/content_settings_service.cc
index 83169fca6d7..272f5ee9eb2 100644
--- a/chromium/chrome/browser/extensions/api/content_settings/content_settings_service.cc
+++ b/chromium/chrome/browser/extensions/api/content_settings/content_settings_service.cc
@@ -5,7 +5,6 @@
#include "chrome/browser/extensions/api/content_settings/content_settings_service.h"
#include "base/lazy_instance.h"
-#include "chrome/browser/extensions/api/content_settings/content_settings_store.h"
#include "extensions/browser/extension_prefs.h"
#include "extensions/browser/extension_prefs_scope.h"
#include "extensions/browser/pref_names.h"
diff --git a/chromium/chrome/browser/extensions/api/content_settings/content_settings_service.h b/chromium/chrome/browser/extensions/api/content_settings/content_settings_service.h
index 96fa0e8d102..0b4d70ca25f 100644
--- a/chromium/chrome/browser/extensions/api/content_settings/content_settings_service.h
+++ b/chromium/chrome/browser/extensions/api/content_settings/content_settings_service.h
@@ -7,6 +7,7 @@
#include "base/macros.h"
#include "base/memory/ref_counted.h"
+#include "chrome/browser/extensions/api/content_settings/content_settings_store.h"
#include "extensions/browser/browser_context_keyed_api_factory.h"
#include "extensions/browser/extension_prefs_observer.h"
diff --git a/chromium/chrome/browser/extensions/api/content_settings/content_settings_store.h b/chromium/chrome/browser/extensions/api/content_settings/content_settings_store.h
index 3a9033a4747..ea311c4b725 100644
--- a/chromium/chrome/browser/extensions/api/content_settings/content_settings_store.h
+++ b/chromium/chrome/browser/extensions/api/content_settings/content_settings_store.h
@@ -140,7 +140,7 @@ class ContentSettingsStore
// The entries.
ExtensionEntries entries_;
- base::ObserverList<Observer, false> observers_;
+ base::ObserverList<Observer, false>::Unchecked observers_;
mutable base::Lock lock_;
diff --git a/chromium/chrome/browser/extensions/api/context_menus/context_menu_apitest.cc b/chromium/chrome/browser/extensions/api/context_menus/context_menu_apitest.cc
index 4554ed65ee5..856b74eb55e 100644
--- a/chromium/chrome/browser/extensions/api/context_menus/context_menu_apitest.cc
+++ b/chromium/chrome/browser/extensions/api/context_menus/context_menu_apitest.cc
@@ -273,11 +273,6 @@ IN_PROC_BROWSER_TEST_F(ExtensionContextMenuApiTest,
VerifyMenuItem("parent", top_level_model_, top_level_index(),
ui::MenuModel::TYPE_SUBMENU, true);
- // Since the extension submenu is shown, the previous separator should be in
- // the model.
- EXPECT_EQ(ui::MenuModel::TYPE_SEPARATOR,
- top_level_model_->GetTypeAt(top_level_index() - 1));
-
ui::MenuModel* submodel =
top_level_model_->GetSubmenuModelAt(top_level_index());
ASSERT_TRUE(submodel);
@@ -306,11 +301,6 @@ IN_PROC_BROWSER_TEST_F(ExtensionContextMenuApiTest,
VerifyMenuItem("parent", top_level_model_, top_level_index(),
ui::MenuModel::TYPE_SUBMENU, true);
- // Since the extension submenu is shown, the previous separator should be in
- // the model.
- EXPECT_EQ(ui::MenuModel::TYPE_SEPARATOR,
- top_level_model_->GetTypeAt(top_level_index() - 1));
-
ui::MenuModel* submodel =
top_level_model_->GetSubmenuModelAt(top_level_index());
ASSERT_TRUE(submodel);
@@ -339,11 +329,6 @@ IN_PROC_BROWSER_TEST_F(ExtensionContextMenuApiTest,
VerifyMenuItem(extension()->name(), top_level_model_, top_level_index(),
ui::MenuModel::TYPE_SUBMENU, true);
- // Since the extension submenu is shown, the previous separator should be in
- // the model.
- EXPECT_EQ(ui::MenuModel::TYPE_SEPARATOR,
- top_level_model_->GetTypeAt(top_level_index() - 1));
-
ui::MenuModel* submodel =
top_level_model_->GetSubmenuModelAt(top_level_index());
ASSERT_TRUE(submodel);
@@ -378,11 +363,6 @@ IN_PROC_BROWSER_TEST_F(ExtensionContextMenuApiTest,
VerifyMenuItem(extension()->name(), top_level_model_, top_level_index(),
ui::MenuModel::TYPE_SUBMENU, true);
- // Since the extension submenu is shown, the previous separator should be in
- // the model.
- EXPECT_EQ(ui::MenuModel::TYPE_SEPARATOR,
- top_level_model_->GetTypeAt(top_level_index() - 1));
-
ui::MenuModel* submodel =
top_level_model_->GetSubmenuModelAt(top_level_index());
ASSERT_TRUE(submodel);
diff --git a/chromium/chrome/browser/extensions/api/cryptotoken_private/cryptotoken_private_api.cc b/chromium/chrome/browser/extensions/api/cryptotoken_private/cryptotoken_private_api.cc
index 44223d6702c..a36c6245c28 100644
--- a/chromium/chrome/browser/extensions/api/cryptotoken_private/cryptotoken_private_api.cc
+++ b/chromium/chrome/browser/extensions/api/cryptotoken_private/cryptotoken_private_api.cc
@@ -32,7 +32,7 @@ constexpr const char* kGoogleGstaticAppIds[] = {
// ContainsAppIdByHash returns true iff the SHA-256 hash of one of the
// elements of |list| equals |hash|.
bool ContainsAppIdByHash(const base::ListValue& list,
- const std::vector<char>& hash) {
+ const std::vector<uint8_t>& hash) {
if (hash.size() != crypto::kSHA256Length) {
return false;
}
@@ -44,9 +44,10 @@ bool ContainsAppIdByHash(const base::ListValue& list,
continue;
}
- if (crypto::SHA256HashString(s).compare(0, crypto::kSHA256Length,
- hash.data(),
- crypto::kSHA256Length) == 0) {
+ if (crypto::SHA256HashString(s).compare(
+ 0, crypto::kSHA256Length,
+ reinterpret_cast<const char*>(hash.data()),
+ crypto::kSHA256Length) == 0) {
return true;
}
}
diff --git a/chromium/chrome/browser/extensions/api/debugger/debugger_api.cc b/chromium/chrome/browser/extensions/api/debugger/debugger_api.cc
index c3ce2dda86d..70600589c31 100644
--- a/chromium/chrome/browser/extensions/api/debugger/debugger_api.cc
+++ b/chromium/chrome/browser/extensions/api/debugger/debugger_api.cc
@@ -44,6 +44,7 @@
#include "content/public/browser/render_widget_host.h"
#include "content/public/browser/web_contents.h"
#include "content/public/common/content_client.h"
+#include "content/public/common/url_constants.h"
#include "content/public/common/url_utils.h"
#include "extensions/browser/event_router.h"
#include "extensions/browser/extension_host.h"
@@ -90,6 +91,9 @@ bool ExtensionCanAttachToURL(const Extension& extension,
const GURL& url,
Profile* profile,
std::string* error) {
+ if (url == content::kUnreachableWebDataURL)
+ return true;
+
// NOTE: The `debugger` permission implies all URLs access (and indicates
// such to the user), so we don't check explicit page access. However, we
// still need to check if it's an otherwise-restricted URL.
@@ -361,9 +365,8 @@ bool ExtensionDevToolsClientHost::MayAttachToRenderer(
const GURL& site_instance_url =
render_frame_host->GetSiteInstance()->GetSiteURL();
- if (site_instance_url.is_empty()) {
- // |site_instance_url| is empty for about:blank. Allow the extension to
- // attach.
+ if (site_instance_url.is_empty() || site_instance_url == "about:") {
+ // Allow the extension to attach to about:blank.
return true;
}
diff --git a/chromium/chrome/browser/extensions/api/declarative/declarative_apitest.cc b/chromium/chrome/browser/extensions/api/declarative/declarative_apitest.cc
index bf1db39d6bf..449b6e1bf25 100644
--- a/chromium/chrome/browser/extensions/api/declarative/declarative_apitest.cc
+++ b/chromium/chrome/browser/extensions/api/declarative/declarative_apitest.cc
@@ -17,6 +17,7 @@
#include "chrome/browser/ui/tabs/tab_strip_model.h"
#include "chrome/test/base/ui_test_utils.h"
#include "content/public/browser/browser_thread.h"
+#include "content/public/browser/storage_partition.h"
#include "extensions/browser/api/declarative/rules_registry_service.h"
#include "extensions/browser/api/declarative_webrequest/webrequest_constants.h"
#include "extensions/browser/api/declarative_webrequest/webrequest_rules_registry.h"
@@ -151,6 +152,9 @@ IN_PROC_BROWSER_TEST_F(DeclarativeApiTest, PRE_PersistRules) {
}
IN_PROC_BROWSER_TEST_F(DeclarativeApiTest, PersistRules) {
+ // Wait for declarative rules to be set up from PRE test.
+ content::BrowserContext::GetDefaultStoragePartition(profile())
+ ->FlushNetworkInterfaceForTesting();
ui_test_utils::NavigateToURL(browser(), GURL(kArbitraryUrl));
EXPECT_EQ(kTestTitle, GetTitle());
}
@@ -180,6 +184,9 @@ IN_PROC_BROWSER_TEST_F(DeclarativeApiTest,
const Extension* extension = InstallExtensionWithUIAutoConfirm(
ext_dir.Pack(), 1 /*+1 installed extension*/, browser());
ASSERT_TRUE(extension);
+ // Wait for declarative rules to be set up.
+ content::BrowserContext::GetDefaultStoragePartition(profile())
+ ->FlushNetworkInterfaceForTesting();
std::string extension_id(extension->id());
ASSERT_TRUE(ready.WaitUntilSatisfied());
ui_test_utils::NavigateToURL(browser(), GURL(kArbitraryUrl));
@@ -254,6 +261,9 @@ IN_PROC_BROWSER_TEST_F(DeclarativeApiTest, MAYBE_NoTracesAfterUninstalling) {
const Extension* extension = InstallExtensionWithUIAutoConfirm(
ext_dir.Pack(), 1 /*+1 installed extension*/, browser());
ASSERT_TRUE(extension);
+ // Wait for declarative rules to be set up.
+ content::BrowserContext::GetDefaultStoragePartition(profile())
+ ->FlushNetworkInterfaceForTesting();
std::string extension_id(extension->id());
ASSERT_TRUE(ready.WaitUntilSatisfied());
ui_test_utils::NavigateToURL(browser(), GURL(kArbitraryUrl));
@@ -264,6 +274,9 @@ IN_PROC_BROWSER_TEST_F(DeclarativeApiTest, MAYBE_NoTracesAfterUninstalling) {
// 2. Uninstall the extension. Rules are gone and preferences should be empty.
UninstallExtension(extension_id);
+ // Wait for declarative rules to be removed.
+ content::BrowserContext::GetDefaultStoragePartition(profile())
+ ->FlushNetworkInterfaceForTesting();
ui_test_utils::NavigateToURL(browser(), GURL(kArbitraryUrl));
EXPECT_NE(kTestTitle, GetTitle());
EXPECT_EQ(0u, NumberOfRegisteredRules(extension_id));
diff --git a/chromium/chrome/browser/extensions/api/declarative_content/declarative_content_apitest.cc b/chromium/chrome/browser/extensions/api/declarative_content/declarative_content_apitest.cc
index df8b818e031..792970cdbab 100644
--- a/chromium/chrome/browser/extensions/api/declarative_content/declarative_content_apitest.cc
+++ b/chromium/chrome/browser/extensions/api/declarative_content/declarative_content_apitest.cc
@@ -20,6 +20,7 @@
#include "chrome/browser/ui/browser_window.h"
#include "chrome/browser/ui/tabs/tab_strip_model.h"
#include "components/bookmarks/browser/bookmark_model.h"
+#include "content/public/browser/storage_partition.h"
#include "content/public/test/browser_test_utils.h"
#include "extensions/browser/extension_registry.h"
#include "extensions/browser/extension_system.h"
@@ -361,6 +362,9 @@ IN_PROC_BROWSER_TEST_F(DeclarativeContentApiTest, ReusedActionInstance) {
ExtensionTestMessageListener ready("ready", false);
const Extension* extension = LoadExtension(ext_dir_.UnpackedPath());
ASSERT_TRUE(extension);
+ // Wait for declarative rules to be set up.
+ content::BrowserContext::GetDefaultStoragePartition(profile())
+ ->FlushNetworkInterfaceForTesting();
const ExtensionAction* page_action =
ExtensionActionManager::Get(browser()->profile())
->GetPageAction(*extension);
@@ -605,6 +609,9 @@ IN_PROC_BROWSER_TEST_F(DeclarativeContentApiTest,
ext_dir_.WriteFile(FILE_PATH_LITERAL("background.js"), kBackgroundHelpers);
const Extension* extension = LoadExtension(ext_dir_.UnpackedPath());
ASSERT_TRUE(extension);
+ // Wait for declarative rules to be set up.
+ content::BrowserContext::GetDefaultStoragePartition(profile())
+ ->FlushNetworkInterfaceForTesting();
const std::string extension_id = extension->id();
const ExtensionAction* page_action = ExtensionActionManager::Get(
browser()->profile())->GetPageAction(*extension);
@@ -631,6 +638,9 @@ IN_PROC_BROWSER_TEST_F(DeclarativeContentApiTest,
EXPECT_EQ(1u, extension_action_test_util::GetTotalPageActionCount(tab));
ReloadExtension(extension_id); // Invalidates page_action and extension.
+ // Wait for declarative rules to be removed.
+ content::BrowserContext::GetDefaultStoragePartition(profile())
+ ->FlushNetworkInterfaceForTesting();
EXPECT_EQ("test_rule",
ExecuteScriptInBackgroundPage(extension_id, kTestRule));
// TODO(jyasskin): Apply new rules to existing tabs, without waiting for a
@@ -641,6 +651,9 @@ IN_PROC_BROWSER_TEST_F(DeclarativeContentApiTest,
EXPECT_EQ(1u, extension_action_test_util::GetTotalPageActionCount(tab));
UnloadExtension(extension_id);
+ // Wait for declarative rules to be removed.
+ content::BrowserContext::GetDefaultStoragePartition(profile())
+ ->FlushNetworkInterfaceForTesting();
NavigateInRenderer(tab, GURL("http://test/"));
EXPECT_TRUE(WaitForPageActionVisibilityChangeTo(0));
EXPECT_EQ(0u, extension_action_test_util::GetVisiblePageActionCount(tab));
@@ -722,6 +735,9 @@ IN_PROC_BROWSER_TEST_P(ShowPageActionWithoutPageActionTest, Test) {
scoped_refptr<const Extension> extension =
loader.LoadExtension(ext_dir_.UnpackedPath());
ASSERT_TRUE(extension);
+ // Wait for declarative rules to be set up.
+ content::BrowserContext::GetDefaultStoragePartition(profile())
+ ->FlushNetworkInterfaceForTesting();
const char kScript[] =
"setRules([{\n"
diff --git a/chromium/chrome/browser/extensions/api/declarative_content/set_icon_apitest.cc b/chromium/chrome/browser/extensions/api/declarative_content/set_icon_apitest.cc
index 72a79c3313d..b06f9309bf5 100644
--- a/chromium/chrome/browser/extensions/api/declarative_content/set_icon_apitest.cc
+++ b/chromium/chrome/browser/extensions/api/declarative_content/set_icon_apitest.cc
@@ -7,6 +7,7 @@
#include "chrome/browser/extensions/extension_tab_util.h"
#include "chrome/browser/ui/tabs/tab_strip_model.h"
#include "components/version_info/version_info.h"
+#include "content/public/browser/storage_partition.h"
#include "extensions/common/features/feature_channel.h"
#include "extensions/test/extension_test_message_listener.h"
#include "extensions/test/test_extension_dir.h"
@@ -74,6 +75,9 @@ IN_PROC_BROWSER_TEST_F(SetIconAPITest, Overview) {
ExtensionTestMessageListener ready("ready", false);
const Extension* extension = LoadExtension(ext_dir_.UnpackedPath());
ASSERT_TRUE(extension);
+ // Wait for declarative rules to be set up.
+ content::BrowserContext::GetDefaultStoragePartition(profile())
+ ->FlushNetworkInterfaceForTesting();
const ExtensionAction* page_action =
ExtensionActionManager::Get(browser()->profile())->
GetPageAction(*extension);
diff --git a/chromium/chrome/browser/extensions/api/declarative_net_request/declarative_net_request_browsertest.cc b/chromium/chrome/browser/extensions/api/declarative_net_request/declarative_net_request_browsertest.cc
index 43c0ea8cd18..5f086a51ea0 100644
--- a/chromium/chrome/browser/extensions/api/declarative_net_request/declarative_net_request_browsertest.cc
+++ b/chromium/chrome/browser/extensions/api/declarative_net_request/declarative_net_request_browsertest.cc
@@ -19,6 +19,7 @@
#include "base/path_service.h"
#include "base/rand_util.h"
#include "base/run_loop.h"
+#include "base/strings/utf_string_conversions.h"
#include "base/synchronization/lock.h"
#include "base/test/metrics/histogram_tester.h"
#include "base/threading/thread_restrictions.h"
@@ -52,6 +53,7 @@
#include "extensions/browser/api/declarative_net_request/ruleset_manager.h"
#include "extensions/browser/api/declarative_net_request/ruleset_matcher.h"
#include "extensions/browser/api/declarative_net_request/test_utils.h"
+#include "extensions/browser/api/declarative_net_request/utils.h"
#include "extensions/browser/api/web_request/web_request_info.h"
#include "extensions/browser/extension_prefs.h"
#include "extensions/browser/extension_registry.h"
@@ -338,18 +340,10 @@ class DeclarativeNetRequestBrowserTest
}
ASSERT_TRUE(extension);
- EXPECT_TRUE(HasValidIndexedRuleset(*extension, profile()));
// Ensure the ruleset is also loaded on the IO thread.
content::RunAllTasksUntilIdle();
- // Wait for the background page to load if needed.
- if (has_background_script_)
- WaitForBackgroundScriptToLoad(extension->id());
-
- // Ensure no load errors were reported.
- EXPECT_TRUE(LoadErrorReporter::GetInstance()->GetErrors()->empty());
-
tester.ExpectTotalCount(kIndexRulesTimeHistogram, 1);
tester.ExpectTotalCount(kIndexAndPersistRulesTimeHistogram, 1);
tester.ExpectUniqueSample(kManifestRulesCountHistogram,
@@ -359,6 +353,15 @@ class DeclarativeNetRequestBrowserTest
tester.ExpectUniqueSample(
"Extensions.DeclarativeNetRequest.LoadRulesetResult",
RulesetMatcher::kLoadSuccess /*sample*/, 1 /*count*/);
+
+ EXPECT_TRUE(HasValidIndexedRuleset(*extension, profile()));
+
+ // Wait for the background page to load if needed.
+ if (has_background_script_)
+ WaitForBackgroundScriptToLoad(extension->id());
+
+ // Ensure no load errors were reported.
+ EXPECT_TRUE(LoadErrorReporter::GetInstance()->GetErrors()->empty());
}
void LoadExtensionWithRules(const std::vector<TestRule>& rules) {
@@ -480,7 +483,10 @@ IN_PROC_BROWSER_TEST_P(DeclarativeNetRequestBrowserTest,
{"|http://*.us", 3},
{"pages_with_script/page2.html|", 4},
{"|http://msn*/pages_with_script/page.html|", 5},
- {"%20", 6}, // Block any urls with space.
+ {"%20", 6}, // Block any urls with space.
+ {"%C3%A9", 7}, // Percent-encoded non-ascii character Ă©.
+ // Internationalized domain "â±´ase.com" in punycode.
+ {"|http://xn--ase-7z0b.com", 8},
};
// Rule |i| is the rule with id |i|.
@@ -504,6 +510,12 @@ IN_PROC_BROWSER_TEST_P(DeclarativeNetRequestBrowserTest,
{"abc.com", "/pages_with_script/page.html?q=hi bye", false}, // Rule 6
{"abc.com", "/pages_with_script/page.html?q=hi%20bye", false}, // Rule 6
{"abc.com", "/pages_with_script/page.html?q=hibye", true},
+ {"abc.com",
+ "/pages_with_script/page.html?q=" + base::WideToUTF8(L"\u00E9"),
+ false}, // Rule 7
+ {base::WideToUTF8(L"\x2c74"
+ L"ase.com"),
+ "/pages_with_script/page.html", false}, // Rule 8
};
// Load the extension.
@@ -653,7 +665,10 @@ IN_PROC_BROWSER_TEST_P(DeclarativeNetRequestBrowserTest,
size_t id;
std::vector<std::string> domains;
std::vector<std::string> excluded_domains;
- } rules_data[] = {{"child_frame.html?frame=1", 1, {"x.com"}, {"a.x.com"}},
+ } rules_data[] = {{"child_frame.html?frame=1",
+ 1,
+ {"x.com", "xn--36c-tfa.com" /* punycode for 36°c.com */},
+ {"a.x.com"}},
{"child_frame.html?frame=2", 2, {}, {"a.y.com"}}};
std::vector<TestRule> rules;
@@ -679,6 +694,9 @@ IN_PROC_BROWSER_TEST_P(DeclarativeNetRequestBrowserTest,
bool expect_frame_2_loaded;
} test_cases[] = {
{"x.com", false /* Rule 1 */, false /* Rule 2 */},
+ {base::WideToUTF8(L"36\x00b0"
+ L"c.com" /* 36°c.com */),
+ false /*Rule 1*/, false /*Rule 2*/},
{"b.x.com", false /* Rule 1 */, false /* Rule 2 */},
{"a.x.com", true, false /* Rule 2 */},
{"b.a.x.com", true, false /* Rule 2 */},
@@ -1307,7 +1325,7 @@ IN_PROC_BROWSER_TEST_P(DeclarativeNetRequestBrowserTest,
// affecting requests.
PrefService* pref_service = browser()->profile()->GetPrefs();
pref_service->Set(proxy_config::prefs::kProxy,
- *ProxyConfigDictionary::CreatePacScript(
+ ProxyConfigDictionary::CreatePacScript(
embedded_test_server()->GetURL("/self.pac").spec(),
true /* pac_mandatory */));
// Flush the proxy configuration change over the Mojo pipe to avoid any races.
@@ -1632,15 +1650,6 @@ IN_PROC_BROWSER_TEST_P(DeclarativeNetRequestBrowserTest,
request->resource_type = content::ResourceType::RESOURCE_TYPE_SCRIPT;
request->render_frame_id = MSG_ROUTING_NONE;
- // TODO(https://crbug.com/857577): remove this hack. When an unrelated
- // browser issued request (typically from GaiaAuthFetcher) has run, it causes
- // the StoragePartitionImpl to create and cache a URLLoaderFactory without the
- // web request proxying. This resets it so one with the web request proxying
- // is created the next time a request is made.
- base::RunLoop().RunUntilIdle();
- content::BrowserContext::GetDefaultStoragePartition(profile())
- ->ResetURLLoaderFactoryForBrowserProcessForTesting();
-
auto loader = network::SimpleURLLoader::Create(std::move(request),
TRAFFIC_ANNOTATION_FOR_TESTS);
content::SimpleURLLoaderTestHelper loader_helper;
@@ -1816,10 +1825,11 @@ IN_PROC_BROWSER_TEST_P(DeclarativeNetRequestBrowserTest_Packed,
verify_page_load(false);
}
- // Overwrite the indexed ruleset file with arbitrary data to mimic corruption.
+ // Overwrite the indexed ruleset file with arbitrary data to mimic corruption,
+ // while maintaining the correct version header.
{
base::ScopedAllowBlockingForTesting scoped_allow_blocking;
- std::string corrupted_data = "data";
+ std::string corrupted_data = GetVersionHeaderForTesting() + "data";
ASSERT_EQ(static_cast<int>(corrupted_data.size()),
base::WriteFile(file_util::GetIndexedRulesetPath(extension_path),
corrupted_data.c_str(), corrupted_data.size()));
@@ -1844,7 +1854,7 @@ IN_PROC_BROWSER_TEST_P(DeclarativeNetRequestBrowserTest_Packed,
EXPECT_EQ(1, tester.GetBucketCount(
"Extensions.DeclarativeNetRequest.LoadRulesetResult",
RulesetMatcher::LoadRulesetResult::
- kLoadErrorRulesetVerification /*sample*/));
+ kLoadErrorChecksumMismatch /*sample*/));
EXPECT_EQ(1,
tester.GetBucketCount(
"Extensions.DeclarativeNetRequest.LoadRulesetResult",
@@ -1877,7 +1887,7 @@ IN_PROC_BROWSER_TEST_P(DeclarativeNetRequestBrowserTest,
// Mimic extension prefs corruption by overwriting the indexed ruleset
// checksum.
const int kInvalidRulesetChecksum = -1;
- ExtensionPrefs::Get(profile())->SetDNRRulesetChecksumForTesting(
+ ExtensionPrefs::Get(profile())->SetDNRRulesetChecksum(
extension_id, kInvalidRulesetChecksum);
TestExtensionRegistryObserver registry_observer(
@@ -1904,7 +1914,7 @@ IN_PROC_BROWSER_TEST_P(DeclarativeNetRequestBrowserTest,
EXPECT_EQ(1, tester.GetBucketCount(
"Extensions.DeclarativeNetRequest.LoadRulesetResult",
RulesetMatcher::LoadRulesetResult::
- kLoadErrorRulesetVerification /*sample*/));
+ kLoadErrorChecksumMismatch /*sample*/));
// Verify that re-indexing the ruleset failed.
tester.ExpectUniqueSample(
@@ -1912,6 +1922,60 @@ IN_PROC_BROWSER_TEST_P(DeclarativeNetRequestBrowserTest,
false /*sample*/, 1 /*count*/);
}
+// Tests that we reindex the extension ruleset in case its ruleset format
+// version is not the same as one used by Chrome.
+IN_PROC_BROWSER_TEST_P(DeclarativeNetRequestBrowserTest_Packed,
+ ReindexOnRulesetVersionMismatch) {
+ // Set up an observer for RulesetMatcher to monitor the number of extension
+ // rulesets.
+ RulesetCountWaiter ruleset_count_waiter;
+ ScopedRulesetManagerTestObserver scoped_observer(
+ &ruleset_count_waiter,
+ base::WrapRefCounted(ExtensionSystem::Get(profile())->info_map()));
+
+ TestRule rule = CreateGenericRule();
+ rule.condition->url_filter = std::string("*");
+ ASSERT_NO_FATAL_FAILURE(LoadExtensionWithRules({rule}));
+ ruleset_count_waiter.WaitForRulesetCount(1);
+
+ const ExtensionId extension_id = last_loaded_extension_id();
+ const auto* rules_monitor_service = BrowserContextKeyedAPIFactory<
+ declarative_net_request::RulesMonitorService>::Get(profile());
+ EXPECT_TRUE(rules_monitor_service->HasRegisteredRuleset(extension_id));
+
+ DisableExtension(extension_id);
+ ruleset_count_waiter.WaitForRulesetCount(0);
+ EXPECT_FALSE(rules_monitor_service->HasRegisteredRuleset(extension_id));
+
+ // Now change the current indexed ruleset format version. This should cause a
+ // version mismatch when the extension is loaded again, but reindexing should
+ // still succeed.
+ const int kIndexedRulesetFormatVersion = 100;
+ std::string old_version_header = GetVersionHeaderForTesting();
+ SetIndexedRulesetFormatVersionForTesting(kIndexedRulesetFormatVersion);
+ ASSERT_NE(old_version_header, GetVersionHeaderForTesting());
+
+ base::HistogramTester tester;
+ EnableExtension(extension_id);
+ ruleset_count_waiter.WaitForRulesetCount(1);
+ EXPECT_TRUE(rules_monitor_service->HasRegisteredRuleset(extension_id));
+
+ // Verify that loading the ruleset would have failed initially due to
+ // version header mismatch and later succeeded.
+ EXPECT_EQ(1, tester.GetBucketCount(
+ "Extensions.DeclarativeNetRequest.LoadRulesetResult",
+ RulesetMatcher::LoadRulesetResult::
+ kLoadErrorVersionMismatch /*sample*/));
+ EXPECT_EQ(1, tester.GetBucketCount(
+ "Extensions.DeclarativeNetRequest.LoadRulesetResult",
+ RulesetMatcher::LoadRulesetResult::kLoadSuccess /*sample*/));
+
+ // Verify that reindexing succeeded.
+ tester.ExpectUniqueSample(
+ "Extensions.DeclarativeNetRequest.RulesetReindexSuccessful",
+ true /*sample*/, 1 /*count*/);
+}
+
// Test fixture to verify that host permissions for the request url and the
// request initiator are properly checked. Loads an example.com url with four
// sub-frames named frame_[1..4] from hosts frame_[1..4].com. The initiator for
diff --git a/chromium/chrome/browser/extensions/api/declarative_net_request/ruleset_matcher_unittest.cc b/chromium/chrome/browser/extensions/api/declarative_net_request/ruleset_matcher_unittest.cc
index 90209860ec6..2948dde85c1 100644
--- a/chromium/chrome/browser/extensions/api/declarative_net_request/ruleset_matcher_unittest.cc
+++ b/chromium/chrome/browser/extensions/api/declarative_net_request/ruleset_matcher_unittest.cc
@@ -14,6 +14,7 @@
#include "chrome/browser/profiles/profile.h"
#include "components/url_pattern_index/flat/url_pattern_index_generated.h"
#include "extensions/browser/api/declarative_net_request/test_utils.h"
+#include "extensions/browser/api/declarative_net_request/utils.h"
#include "extensions/browser/extension_prefs.h"
#include "extensions/common/api/declarative_net_request/constants.h"
#include "extensions/common/api/declarative_net_request/test_utils.h"
@@ -123,7 +124,8 @@ TEST_P(RulesetMatcherTest, FailedVerification) {
base::FilePath indexed_ruleset_path =
file_util::GetIndexedRulesetPath(extension()->path());
- // Persist invalid data to the ruleset file.
+ // Persist invalid data to the ruleset file and ensure that a version mismatch
+ // occurs.
std::string data = "invalid data";
ASSERT_EQ(static_cast<int>(data.size()),
base::WriteFile(indexed_ruleset_path, data.c_str(), data.size()));
@@ -134,7 +136,17 @@ TEST_P(RulesetMatcherTest, FailedVerification) {
->GetDNRRulesetChecksum(extension()->id(), &expected_checksum));
std::unique_ptr<RulesetMatcher> matcher;
- EXPECT_EQ(RulesetMatcher::kLoadErrorRulesetVerification,
+ EXPECT_EQ(RulesetMatcher::kLoadErrorVersionMismatch,
+ RulesetMatcher::CreateVerifiedMatcher(indexed_ruleset_path,
+ expected_checksum, &matcher));
+
+ // Now, persist invalid data to the ruleset file, while maintaining the
+ // correct version header. Ensure that it fails verification due to checksum
+ // mismatch.
+ data = GetVersionHeaderForTesting() + "invalid data";
+ ASSERT_EQ(static_cast<int>(data.size()),
+ base::WriteFile(indexed_ruleset_path, data.c_str(), data.size()));
+ EXPECT_EQ(RulesetMatcher::kLoadErrorChecksumMismatch,
RulesetMatcher::CreateVerifiedMatcher(indexed_ruleset_path,
expected_checksum, &matcher));
}
diff --git a/chromium/chrome/browser/extensions/api/desktop_capture/OWNERS b/chromium/chrome/browser/extensions/api/desktop_capture/OWNERS
index c43cfad6ede..62e34f14d33 100644
--- a/chromium/chrome/browser/extensions/api/desktop_capture/OWNERS
+++ b/chromium/chrome/browser/extensions/api/desktop_capture/OWNERS
@@ -1,7 +1,7 @@
-# Please send the changes to zijiehe@chromium.org first.
+# Please send the changes to braveyao@chromium.org first.
sergeyu@chromium.org
wez@chromium.org
-zijiehe@chromium.org
+braveyao@chromium.org
# TEAM: media-capture-and-streams@grotations.appspotmail.com
# COMPONENT: Blink>GetUserMedia>Desktop
diff --git a/chromium/chrome/browser/extensions/api/desktop_capture/desktop_capture_apitest.cc b/chromium/chrome/browser/extensions/api/desktop_capture/desktop_capture_apitest.cc
index 66e3efd2644..4345409664f 100644
--- a/chromium/chrome/browser/extensions/api/desktop_capture/desktop_capture_apitest.cc
+++ b/chromium/chrome/browser/extensions/api/desktop_capture/desktop_capture_apitest.cc
@@ -8,11 +8,10 @@
#include "base/macros.h"
#include "base/path_service.h"
#include "base/strings/string_number_conversions.h"
-#include "base/threading/thread_task_runner_handle.h"
#include "build/build_config.h"
#include "chrome/browser/extensions/api/desktop_capture/desktop_capture_api.h"
#include "chrome/browser/extensions/extension_apitest.h"
-#include "chrome/browser/media/webrtc/fake_desktop_media_list.h"
+#include "chrome/browser/media/webrtc/fake_desktop_media_picker_factory.h"
#include "chrome/browser/ui/tabs/tab_strip_model.h"
#include "chrome/common/chrome_paths.h"
#include "chrome/common/chrome_switches.h"
@@ -30,20 +29,6 @@ namespace extensions {
namespace {
-struct TestFlags {
- bool expect_screens;
- bool expect_windows;
- bool expect_tabs;
- bool expect_audio;
- DesktopMediaID selected_source;
- bool cancelled;
-
- // Following flags are set by FakeDesktopMediaPicker when it's created and
- // deleted.
- bool picker_created;
- bool picker_deleted;
-};
-
// TODO(crbug.com/805145): Uncomment this when test is re-enabled.
#if 0
DesktopMediaID MakeFakeWebContentsMediaId(bool audio_share) {
@@ -56,104 +41,6 @@ DesktopMediaID MakeFakeWebContentsMediaId(bool audio_share) {
}
#endif
-class FakeDesktopMediaPicker : public DesktopMediaPicker {
- public:
- explicit FakeDesktopMediaPicker(TestFlags* expectation)
- : expectation_(expectation),
- weak_factory_(this) {
- expectation_->picker_created = true;
- }
- ~FakeDesktopMediaPicker() override { expectation_->picker_deleted = true; }
-
- // DesktopMediaPicker interface.
- void Show(const DesktopMediaPicker::Params& params,
- std::vector<std::unique_ptr<DesktopMediaList>> source_lists,
- const DoneCallback& done_callback) override {
- bool show_screens = false;
- bool show_windows = false;
- bool show_tabs = false;
-
- for (auto& source_list : source_lists) {
- switch (source_list->GetMediaListType()) {
- case DesktopMediaID::TYPE_NONE:
- break;
- case DesktopMediaID::TYPE_SCREEN:
- show_screens = true;
- break;
- case DesktopMediaID::TYPE_WINDOW:
- show_windows = true;
- break;
- case DesktopMediaID::TYPE_WEB_CONTENTS:
- show_tabs = true;
- break;
- }
- }
- EXPECT_EQ(expectation_->expect_screens, show_screens);
- EXPECT_EQ(expectation_->expect_windows, show_windows);
- EXPECT_EQ(expectation_->expect_tabs, show_tabs);
- EXPECT_EQ(expectation_->expect_audio, params.request_audio);
- EXPECT_EQ(params.modality, ui::ModalType::MODAL_TYPE_CHILD);
-
- if (!expectation_->cancelled) {
- // Post a task to call the callback asynchronously.
- base::ThreadTaskRunnerHandle::Get()->PostTask(
- FROM_HERE, base::BindOnce(&FakeDesktopMediaPicker::CallCallback,
- weak_factory_.GetWeakPtr(), done_callback));
- } else {
- // If we expect the dialog to be cancelled then store the callback to
- // retain reference to the callback handler.
- done_callback_ = done_callback;
- }
- }
-
- private:
- void CallCallback(DoneCallback done_callback) {
- done_callback.Run(expectation_->selected_source);
- }
-
- TestFlags* expectation_;
- DoneCallback done_callback_;
-
- base::WeakPtrFactory<FakeDesktopMediaPicker> weak_factory_;
-
- DISALLOW_COPY_AND_ASSIGN(FakeDesktopMediaPicker);
-};
-
-class FakeDesktopMediaPickerFactory :
- public DesktopCaptureChooseDesktopMediaFunction::PickerFactory {
- public:
- FakeDesktopMediaPickerFactory() {}
- ~FakeDesktopMediaPickerFactory() override {}
-
- void SetTestFlags(TestFlags* test_flags, int tests_count) {
- test_flags_ = test_flags;
- tests_count_ = tests_count;
- current_test_ = 0;
- }
-
- std::unique_ptr<DesktopMediaPicker> CreatePicker() override {
- EXPECT_LE(current_test_, tests_count_);
- if (current_test_ >= tests_count_)
- return std::unique_ptr<DesktopMediaPicker>();
- ++current_test_;
- return std::unique_ptr<DesktopMediaPicker>(
- new FakeDesktopMediaPicker(test_flags_ + current_test_ - 1));
- }
-
- std::unique_ptr<DesktopMediaList> CreateMediaList(
- DesktopMediaID::Type type) override {
- EXPECT_LE(current_test_, tests_count_);
- return std::unique_ptr<DesktopMediaList>(new FakeDesktopMediaList(type));
- }
-
- private:
- TestFlags* test_flags_;
- int tests_count_;
- int current_test_;
-
- DISALLOW_COPY_AND_ASSIGN(FakeDesktopMediaPickerFactory);
-};
-
class DesktopCaptureApiTest : public ExtensionApiTest {
public:
DesktopCaptureApiTest() {
@@ -195,7 +82,7 @@ class DesktopCaptureApiTest : public ExtensionApiTest {
IN_PROC_BROWSER_TEST_F(DesktopCaptureApiTest, MAYBE_ChooseDesktopMedia) {
// Each element in the following array corresponds to one test in
// chrome/test/data/extensions/api_test/desktop_capture/test.js .
- TestFlags test_flags[] = {
+ FakeDesktopMediaPickerFactory::TestFlags test_flags[] = {
// pickerUiCanceled()
{true, true, false, false, DesktopMediaID()},
// chooseMedia()
@@ -269,7 +156,7 @@ IN_PROC_BROWSER_TEST_F(DesktopCaptureApiTest, DISABLED_Delegation) {
ui_test_utils::NavigateToURL(
browser(), GetURLForPath("example.com", "/example.com.html"));
- TestFlags test_flags[] = {
+ FakeDesktopMediaPickerFactory::TestFlags test_flags[] = {
{true, true, false, false,
DesktopMediaID(DesktopMediaID::TYPE_SCREEN, DesktopMediaID::kNullId)},
{true, true, false, false,
diff --git a/chromium/chrome/browser/extensions/api/desktop_capture/desktop_capture_base.cc b/chromium/chrome/browser/extensions/api/desktop_capture/desktop_capture_base.cc
index 4e8b6cc9ffa..29040b29d65 100644
--- a/chromium/chrome/browser/extensions/api/desktop_capture/desktop_capture_base.cc
+++ b/chromium/chrome/browser/extensions/api/desktop_capture/desktop_capture_base.cc
@@ -13,7 +13,7 @@
#include "build/build_config.h"
#include "chrome/browser/extensions/extension_tab_util.h"
#include "chrome/browser/media/webrtc/desktop_media_list_ash.h"
-#include "chrome/browser/media/webrtc/desktop_streams_registry.h"
+#include "chrome/browser/media/webrtc/desktop_media_picker_factory_impl.h"
#include "chrome/browser/media/webrtc/media_capture_devices_dispatcher.h"
#include "chrome/browser/media/webrtc/native_desktop_media_list.h"
#include "chrome/browser/media/webrtc/tab_desktop_media_list.h"
@@ -21,6 +21,7 @@
#include "chrome/browser/ui/browser_window.h"
#include "chrome/grit/chromium_strings.h"
#include "content/public/browser/desktop_capture.h"
+#include "content/public/browser/desktop_streams_registry.h"
#include "content/public/browser/render_frame_host.h"
#include "content/public/browser/render_process_host.h"
#include "content/public/browser/web_contents.h"
@@ -39,20 +40,18 @@ const char kInvalidSourceNameError[] = "Invalid source type specified.";
const char kEmptySourcesListError[] =
"At least one source type must be specified.";
-DesktopCaptureChooseDesktopMediaFunctionBase::PickerFactory* g_picker_factory =
- NULL;
+DesktopMediaPickerFactory* g_picker_factory = nullptr;
} // namespace
// static
void DesktopCaptureChooseDesktopMediaFunctionBase::SetPickerFactoryForTests(
- PickerFactory* factory) {
+ DesktopMediaPickerFactory* factory) {
g_picker_factory = factory;
}
DesktopCaptureChooseDesktopMediaFunctionBase::
- DesktopCaptureChooseDesktopMediaFunctionBase() {
-}
+ DesktopCaptureChooseDesktopMediaFunctionBase() = default;
DesktopCaptureChooseDesktopMediaFunctionBase::
~DesktopCaptureChooseDesktopMediaFunctionBase() {
@@ -94,12 +93,8 @@ bool DesktopCaptureChooseDesktopMediaFunctionBase::Execute(
parent_window = target_browser->window()->GetNativeWindow();
}
- // Keep same order as the input |sources| and avoid duplicates.
- std::vector<std::unique_ptr<DesktopMediaList>> source_lists;
- bool have_screen_list = false;
- bool have_window_list = false;
- bool have_tab_list = false;
bool request_audio = false;
+ std::vector<content::DesktopMediaID::Type> media_types;
for (auto source_type : sources) {
switch (source_type) {
case api::desktop_capture::DESKTOP_CAPTURE_SOURCE_TYPE_NONE: {
@@ -107,98 +102,45 @@ bool DesktopCaptureChooseDesktopMediaFunctionBase::Execute(
return false;
}
case api::desktop_capture::DESKTOP_CAPTURE_SOURCE_TYPE_SCREEN: {
- if (have_screen_list) {
- continue;
- }
- std::unique_ptr<DesktopMediaList> screen_list;
- if (g_picker_factory) {
- screen_list =
- g_picker_factory->CreateMediaList(DesktopMediaID::TYPE_SCREEN);
- } else {
-#if defined(OS_CHROMEOS)
- screen_list = std::make_unique<DesktopMediaListAsh>(
- DesktopMediaID::TYPE_SCREEN);
-#else // !defined(OS_CHROMEOS)
- screen_list = std::make_unique<NativeDesktopMediaList>(
- content::DesktopMediaID::TYPE_SCREEN,
- content::desktop_capture::CreateScreenCapturer());
-#endif // !defined(OS_CHROMEOS)
- }
- have_screen_list = true;
- source_lists.push_back(std::move(screen_list));
+ media_types.push_back(content::DesktopMediaID::TYPE_SCREEN);
break;
}
case api::desktop_capture::DESKTOP_CAPTURE_SOURCE_TYPE_WINDOW: {
- if (have_window_list) {
- continue;
- }
- std::unique_ptr<DesktopMediaList> window_list;
- if (g_picker_factory) {
- window_list =
- g_picker_factory->CreateMediaList(DesktopMediaID::TYPE_WINDOW);
- } else {
-#if defined(OS_CHROMEOS)
- window_list = std::make_unique<DesktopMediaListAsh>(
- DesktopMediaID::TYPE_WINDOW);
-#else // !defined(OS_CHROMEOS)
- // NativeDesktopMediaList calls the capturers on a background thread.
- // This means that the two DesktopCapturer instances (for screens and
- // windows) created here cannot share the same DesktopCaptureOptions
- // instance. DesktopCaptureOptions owns X connection, which cannot be
- // used on multiple threads concurrently.
- window_list = std::make_unique<NativeDesktopMediaList>(
- content::DesktopMediaID::TYPE_WINDOW,
- content::desktop_capture::CreateWindowCapturer());
-#endif // !defined(OS_CHROMEOS)
- }
- have_window_list = true;
- source_lists.push_back(std::move(window_list));
+ media_types.push_back(content::DesktopMediaID::TYPE_WINDOW);
break;
}
case api::desktop_capture::DESKTOP_CAPTURE_SOURCE_TYPE_TAB: {
if (base::CommandLine::ForCurrentProcess()->HasSwitch(
- extensions::switches::kDisableTabForDesktopShare) ||
- have_tab_list) {
+ extensions::switches::kDisableTabForDesktopShare)) {
continue;
}
- std::unique_ptr<DesktopMediaList> tab_list;
- if (g_picker_factory) {
- tab_list = g_picker_factory->CreateMediaList(
- DesktopMediaID::TYPE_WEB_CONTENTS);
- } else {
- tab_list = std::make_unique<TabDesktopMediaList>();
- }
- have_tab_list = true;
- source_lists.push_back(std::move(tab_list));
+ media_types.push_back(content::DesktopMediaID::TYPE_WEB_CONTENTS);
break;
}
case api::desktop_capture::DESKTOP_CAPTURE_SOURCE_TYPE_AUDIO: {
- bool audio_capture_disabled =
- base::CommandLine::ForCurrentProcess()->HasSwitch(
- extensions::switches::kDisableDesktopCaptureAudio);
- if (!audio_capture_disabled) {
+ if (!base::CommandLine::ForCurrentProcess()->HasSwitch(
+ extensions::switches::kDisableDesktopCaptureAudio)) {
request_audio = true;
}
break;
}
}
}
+
+ DesktopMediaPickerFactory* picker_factory =
+ g_picker_factory ? g_picker_factory
+ : DesktopMediaPickerFactoryImpl::GetInstance();
+ // Keep same order as the input |sources| and avoid duplicates.
+ std::vector<std::unique_ptr<DesktopMediaList>> source_lists =
+ picker_factory->CreateMediaList(media_types);
if (source_lists.empty()) {
error_ = kEmptySourcesListError;
return false;
}
-
- if (g_picker_factory) {
- picker_ = g_picker_factory->CreatePicker();
- } else {
- // DesktopMediaPicker is implemented only for Windows, OSX and
- // Aura Linux builds.
-#if defined(TOOLKIT_VIEWS) || defined(OS_MACOSX)
- picker_ = DesktopMediaPicker::Create();
-#else
+ picker_ = picker_factory->CreatePicker();
+ if (!picker_) {
error_ = "Desktop Capture API is not yet implemented for this platform.";
return false;
-#endif
}
DesktopMediaPicker::DoneCallback callback = base::Bind(
@@ -234,20 +176,15 @@ void DesktopCaptureChooseDesktopMediaFunctionBase::OnPickerDialogResults(
DesktopMediaID source) {
std::string result;
if (source.type != DesktopMediaID::TYPE_NONE && web_contents()) {
- DesktopStreamsRegistry* registry =
- MediaCaptureDevicesDispatcher::GetInstance()->
- GetDesktopStreamsRegistry();
// TODO(miu): Once render_frame_host() is being set, we should register the
// exact RenderFrame requesting the stream, not the main RenderFrame. With
// that change, also update
// MediaCaptureDevicesDispatcher::ProcessDesktopCaptureAccessRequest().
// http://crbug.com/304341
content::RenderFrameHost* const main_frame = web_contents()->GetMainFrame();
- result = registry->RegisterStream(main_frame->GetProcess()->GetID(),
- main_frame->GetRoutingID(),
- origin_,
- source,
- extension()->name());
+ result = content::DesktopStreamsRegistry::GetInstance()->RegisterStream(
+ main_frame->GetProcess()->GetID(), main_frame->GetRoutingID(), origin_,
+ source, extension()->name(), content::kRegistryStreamTypeDesktop);
}
Options options;
@@ -258,9 +195,7 @@ void DesktopCaptureChooseDesktopMediaFunctionBase::OnPickerDialogResults(
DesktopCaptureRequestsRegistry::RequestId::RequestId(int process_id,
int request_id)
- : process_id(process_id),
- request_id(request_id) {
-}
+ : process_id(process_id), request_id(request_id) {}
bool DesktopCaptureRequestsRegistry::RequestId::operator<(
const RequestId& other) const {
@@ -312,5 +247,4 @@ void DesktopCaptureRequestsRegistry::CancelRequest(int process_id,
it->second->Cancel();
}
-
} // namespace extensions
diff --git a/chromium/chrome/browser/extensions/api/desktop_capture/desktop_capture_base.h b/chromium/chrome/browser/extensions/api/desktop_capture/desktop_capture_base.h
index a56432871db..595a331a6a2 100644
--- a/chromium/chrome/browser/extensions/api/desktop_capture/desktop_capture_base.h
+++ b/chromium/chrome/browser/extensions/api/desktop_capture/desktop_capture_base.h
@@ -14,6 +14,7 @@
#include "chrome/browser/extensions/chrome_extension_function.h"
#include "chrome/browser/media/webrtc/desktop_media_list.h"
#include "chrome/browser/media/webrtc/desktop_media_picker.h"
+#include "chrome/browser/media/webrtc/desktop_media_picker_factory.h"
#include "chrome/common/extensions/api/desktop_capture.h"
#include "content/public/browser/web_contents_observer.h"
#include "url/gurl.h"
@@ -24,26 +25,10 @@ class DesktopCaptureChooseDesktopMediaFunctionBase
: public ChromeAsyncExtensionFunction,
public content::WebContentsObserver {
public:
- // Factory creating DesktopMediaList and DesktopMediaPicker instances.
- // Used for tests to supply fake picker.
- class PickerFactory {
- public:
- virtual std::unique_ptr<DesktopMediaPicker> CreatePicker() = 0;
- virtual std::unique_ptr<DesktopMediaList> CreateMediaList(
- content::DesktopMediaID::Type type) = 0;
-
- protected:
- PickerFactory() = default;
- virtual ~PickerFactory() {}
-
- private:
- DISALLOW_COPY_AND_ASSIGN(PickerFactory);
- };
-
// Used to set PickerFactory used to create mock DesktopMediaPicker instances
// for tests. Calling tests keep ownership of the factory. Can be called with
// |factory| set to NULL at the end of the test.
- static void SetPickerFactoryForTests(PickerFactory* factory);
+ static void SetPickerFactoryForTests(DesktopMediaPickerFactory* factory);
DesktopCaptureChooseDesktopMediaFunctionBase();
@@ -77,6 +62,7 @@ class DesktopCaptureChooseDesktopMediaFunctionBase
// URL of page that desktop capture was requested for.
GURL origin_;
+ std::unique_ptr<DesktopMediaPickerFactory> picker_factory_;
std::unique_ptr<DesktopMediaPicker> picker_;
};
diff --git a/chromium/chrome/browser/extensions/api/developer_private/DEPS b/chromium/chrome/browser/extensions/api/developer_private/DEPS
index 5ad83b64961..5b9436cd654 100644
--- a/chromium/chrome/browser/extensions/api/developer_private/DEPS
+++ b/chromium/chrome/browser/extensions/api/developer_private/DEPS
@@ -1,4 +1,8 @@
specific_include_rules = {
+ "show_permissions_dialog_helper.cc": [
+ #TODO(https://crbug.com/873872): Remove this.
+ "+chrome/browser/apps/platform_apps/app_load_service.h",
+ ],
"developer_private_api_unittest.cc": [
# Allow the unittest to create a data_decoder service.
"+services/data_decoder"
diff --git a/chromium/chrome/browser/extensions/api/developer_private/developer_private_api.cc b/chromium/chrome/browser/extensions/api/developer_private/developer_private_api.cc
index 27e3b46092f..52d4edb8c3e 100644
--- a/chromium/chrome/browser/extensions/api/developer_private/developer_private_api.cc
+++ b/chromium/chrome/browser/extensions/api/developer_private/developer_private_api.cc
@@ -18,7 +18,7 @@
#include "base/strings/string_number_conversions.h"
#include "base/strings/stringprintf.h"
#include "base/strings/utf_string_conversions.h"
-#include "base/task_scheduler/post_task.h"
+#include "base/task/post_task.h"
#include "chrome/browser/devtools/devtools_window.h"
#include "chrome/browser/extensions/api/developer_private/developer_private_mangle.h"
#include "chrome/browser/extensions/api/developer_private/entry_picker.h"
@@ -27,12 +27,14 @@
#include "chrome/browser/extensions/chrome_zipfile_installer.h"
#include "chrome/browser/extensions/crx_installer.h"
#include "chrome/browser/extensions/devtools_util.h"
+#include "chrome/browser/extensions/error_console/error_console_factory.h"
#include "chrome/browser/extensions/extension_commands_global_registry.h"
#include "chrome/browser/extensions/extension_service.h"
#include "chrome/browser/extensions/extension_tab_util.h"
#include "chrome/browser/extensions/extension_ui_util.h"
#include "chrome/browser/extensions/extension_util.h"
#include "chrome/browser/extensions/install_verifier.h"
+#include "chrome/browser/extensions/permissions_updater.h"
#include "chrome/browser/extensions/scripting_permissions_modifier.h"
#include "chrome/browser/extensions/shared_module_service.h"
#include "chrome/browser/extensions/unpacked_installer.h"
@@ -52,7 +54,9 @@
#include "chrome/common/url_constants.h"
#include "chrome/grit/generated_resources.h"
#include "content/public/browser/browser_thread.h"
+#include "content/public/browser/notification_details.h"
#include "content/public/browser/notification_service.h"
+#include "content/public/browser/notification_source.h"
#include "content/public/browser/render_frame_host.h"
#include "content/public/browser/render_process_host.h"
#include "content/public/browser/site_instance.h"
@@ -66,15 +70,20 @@
#include "extensions/browser/content_verifier.h"
#include "extensions/browser/disable_reason.h"
#include "extensions/browser/error_map.h"
+#include "extensions/browser/event_router_factory.h"
#include "extensions/browser/extension_error.h"
#include "extensions/browser/extension_prefs.h"
+#include "extensions/browser/extension_prefs_factory.h"
#include "extensions/browser/extension_registry.h"
+#include "extensions/browser/extension_registry_factory.h"
#include "extensions/browser/extension_system.h"
#include "extensions/browser/file_highlighter.h"
#include "extensions/browser/management_policy.h"
#include "extensions/browser/notification_types.h"
#include "extensions/browser/path_util.h"
+#include "extensions/browser/process_manager_factory.h"
#include "extensions/browser/warning_service.h"
+#include "extensions/browser/warning_service_factory.h"
#include "extensions/browser/zipfile_installer.h"
#include "extensions/common/extension_set.h"
#include "extensions/common/feature_switch.h"
@@ -259,6 +268,25 @@ developer::LoadError CreateLoadError(
return response;
}
+base::Optional<URLPattern> ParseRuntimePermissionsPattern(
+ const std::string& pattern_str) {
+ constexpr int kValidRuntimePermissionSchemes = URLPattern::SCHEME_HTTP |
+ URLPattern::SCHEME_HTTPS |
+ URLPattern::SCHEME_FILE;
+
+ URLPattern pattern(kValidRuntimePermissionSchemes);
+ if (pattern.Parse(pattern_str) != URLPattern::PARSE_SUCCESS)
+ return base::nullopt;
+
+ // We don't allow adding paths for permissions, because they aren't meaningful
+ // in terms of origin access. The frontend should validate this, but there's
+ // a chance something can slip through, so we should fail gracefully.
+ if (pattern.path() != "/*")
+ return base::nullopt;
+
+ return pattern;
+}
+
} // namespace
namespace ChoosePath = api::developer_private::ChoosePath;
@@ -302,6 +330,20 @@ DeveloperPrivateAPI::GetFactoryInstance() {
return g_developer_private_api_factory.Pointer();
}
+template <>
+void BrowserContextKeyedAPIFactory<
+ DeveloperPrivateAPI>::DeclareFactoryDependencies() {
+ DependsOn(ExtensionRegistryFactory::GetInstance());
+ DependsOn(ErrorConsoleFactory::GetInstance());
+ DependsOn(ProcessManagerFactory::GetInstance());
+ DependsOn(AppWindowRegistry::Factory::GetInstance());
+ DependsOn(WarningServiceFactory::GetInstance());
+ DependsOn(ExtensionPrefsFactory::GetInstance());
+ DependsOn(ExtensionManagementFactory::GetInstance());
+ DependsOn(CommandService::GetFactoryInstance());
+ DependsOn(EventRouterFactory::GetInstance());
+}
+
// static
DeveloperPrivateAPI* DeveloperPrivateAPI::Get(
content::BrowserContext* context) {
@@ -341,6 +383,9 @@ DeveloperPrivateEventRouter::DeveloperPrivateEventRouter(Profile* profile)
prefs::kExtensionsUIDeveloperMode,
base::Bind(&DeveloperPrivateEventRouter::OnProfilePrefChanged,
base::Unretained(this)));
+ notification_registrar_.Add(
+ this, extensions::NOTIFICATION_EXTENSION_PERMISSIONS_UPDATED,
+ content::Source<Profile>(profile_));
}
DeveloperPrivateEventRouter::~DeveloperPrivateEventRouter() {
@@ -448,6 +493,12 @@ void DeveloperPrivateEventRouter::OnExtensionDisableReasonsChanged(
BroadcastItemStateChanged(developer::EVENT_TYPE_PREFS_CHANGED, extension_id);
}
+void DeveloperPrivateEventRouter::OnExtensionRuntimePermissionsChanged(
+ const std::string& extension_id) {
+ BroadcastItemStateChanged(developer::EVENT_TYPE_PERMISSIONS_CHANGED,
+ extension_id);
+}
+
void DeveloperPrivateEventRouter::OnExtensionManagementSettingsChanged() {
std::unique_ptr<base::ListValue> args(new base::ListValue());
args->Append(CreateProfileInfo(profile_)->ToValue());
@@ -463,6 +514,18 @@ void DeveloperPrivateEventRouter::ExtensionWarningsChanged(
BroadcastItemStateChanged(developer::EVENT_TYPE_WARNINGS_CHANGED, id);
}
+void DeveloperPrivateEventRouter::Observe(
+ int type,
+ const content::NotificationSource& source,
+ const content::NotificationDetails& details) {
+ DCHECK_EQ(NOTIFICATION_EXTENSION_PERMISSIONS_UPDATED, type);
+
+ UpdatedExtensionPermissionsInfo* info =
+ content::Details<UpdatedExtensionPermissionsInfo>(details).ptr();
+ BroadcastItemStateChanged(developer::EVENT_TYPE_PERMISSIONS_CHANGED,
+ info->extension->id());
+}
+
void DeveloperPrivateEventRouter::OnProfilePrefChanged() {
std::unique_ptr<base::ListValue> args(new base::ListValue());
args->Append(CreateProfileInfo(profile_)->ToValue());
@@ -1932,30 +1995,27 @@ DeveloperPrivateAddHostPermissionFunction::Run() {
developer::AddHostPermission::Params::Create(*args_));
EXTENSION_FUNCTION_VALIDATE(params);
- GURL host(params->host);
- if (!host.is_valid() || host.path_piece().length() > 1 || host.has_query() ||
- host.has_ref()) {
+ base::Optional<URLPattern> pattern =
+ ParseRuntimePermissionsPattern(params->host);
+ if (!pattern)
return RespondNow(Error(kInvalidHost));
- }
const Extension* extension = GetExtensionById(params->extension_id);
if (!extension)
return RespondNow(Error(kNoSuchExtensionError));
- ScriptingPermissionsModifier scripting_modifier(browser_context(), extension);
- if (!scripting_modifier.CanAffectExtension())
+ if (!ScriptingPermissionsModifier(browser_context(), extension)
+ .CanAffectExtension()) {
return RespondNow(Error(kCannotChangeHostPermissions));
-
- // Only grant withheld permissions. This also ensures that we won't grant
- // any permission for a host that shouldn't be accessible to the extension,
- // like chrome:-scheme urls.
- if (!extension->permissions_data()
- ->withheld_permissions()
- .HasEffectiveAccessToURL(host)) {
- return RespondNow(Error("Cannot grant a permission that wasn't withheld."));
}
- scripting_modifier.GrantHostPermission(host);
+ URLPatternSet new_host_permissions({*pattern});
+ PermissionsUpdater(browser_context())
+ .GrantRuntimePermissions(
+ *extension,
+ PermissionSet(APIPermissionSet(), ManifestPermissionSet(),
+ new_host_permissions, new_host_permissions));
+
return RespondNow(NoArguments());
}
@@ -1970,11 +2030,10 @@ DeveloperPrivateRemoveHostPermissionFunction::Run() {
developer::RemoveHostPermission::Params::Create(*args_));
EXTENSION_FUNCTION_VALIDATE(params);
- GURL host(params->host);
- if (!host.is_valid() || host.path_piece().length() > 1 || host.has_query() ||
- host.has_ref()) {
+ base::Optional<URLPattern> pattern =
+ ParseRuntimePermissionsPattern(params->host);
+ if (!pattern)
return RespondNow(Error(kInvalidHost));
- }
const Extension* extension = GetExtensionById(params->extension_id);
if (!extension)
@@ -1984,10 +2043,18 @@ DeveloperPrivateRemoveHostPermissionFunction::Run() {
if (!scripting_modifier.CanAffectExtension())
return RespondNow(Error(kCannotChangeHostPermissions));
- if (!scripting_modifier.HasGrantedHostPermission(host))
+ URLPatternSet host_permissions_to_remove({*pattern});
+ std::unique_ptr<const PermissionSet> permissions_to_remove =
+ PermissionSet::CreateIntersection(
+ PermissionSet(APIPermissionSet(), ManifestPermissionSet(),
+ host_permissions_to_remove, host_permissions_to_remove),
+ *scripting_modifier.GetRevokablePermissions(),
+ URLPatternSet::IntersectionBehavior::kDetailed);
+ if (permissions_to_remove->IsEmpty())
return RespondNow(Error("Cannot remove a host that hasn't been granted."));
- scripting_modifier.RemoveGrantedHostPermission(host);
+ PermissionsUpdater(browser_context())
+ .RevokeRuntimePermissions(*extension, *permissions_to_remove);
return RespondNow(NoArguments());
}
diff --git a/chromium/chrome/browser/extensions/api/developer_private/developer_private_api.h b/chromium/chrome/browser/extensions/api/developer_private/developer_private_api.h
index 1d59e38c25a..373a4300e99 100644
--- a/chromium/chrome/browser/extensions/api/developer_private/developer_private_api.h
+++ b/chromium/chrome/browser/extensions/api/developer_private/developer_private_api.h
@@ -23,6 +23,8 @@
#include "chrome/common/extensions/api/developer_private.h"
#include "chrome/common/extensions/webstore_install_result.h"
#include "components/prefs/pref_change_registrar.h"
+#include "content/public/browser/notification_observer.h"
+#include "content/public/browser/notification_registrar.h"
#include "extensions/browser/api/file_system/file_system_api.h"
#include "extensions/browser/app_window/app_window_registry.h"
#include "extensions/browser/browser_context_keyed_api_factory.h"
@@ -59,7 +61,8 @@ class DeveloperPrivateEventRouter : public ExtensionRegistryObserver,
public CommandService::Observer,
public ExtensionPrefsObserver,
public ExtensionManagement::Observer,
- public WarningService::Observer {
+ public WarningService::Observer,
+ public content::NotificationObserver {
public:
explicit DeveloperPrivateEventRouter(Profile* profile);
~DeveloperPrivateEventRouter() override;
@@ -107,6 +110,8 @@ class DeveloperPrivateEventRouter : public ExtensionRegistryObserver,
// ExtensionPrefsObserver:
void OnExtensionDisableReasonsChanged(const std::string& extension_id,
int disable_reasons) override;
+ void OnExtensionRuntimePermissionsChanged(
+ const std::string& extension_id) override;
// ExtensionManagement::Observer:
void OnExtensionManagementSettingsChanged() override;
@@ -115,6 +120,11 @@ class DeveloperPrivateEventRouter : public ExtensionRegistryObserver,
void ExtensionWarningsChanged(
const ExtensionIdSet& affected_extensions) override;
+ // content::NotificationObserver:
+ void Observe(int notification_type,
+ const content::NotificationSource& source,
+ const content::NotificationDetails& details) override;
+
// Handles a profile preferance change.
void OnProfilePrefChanged();
@@ -157,6 +167,8 @@ class DeveloperPrivateEventRouter : public ExtensionRegistryObserver,
PrefChangeRegistrar pref_change_registrar_;
+ content::NotificationRegistrar notification_registrar_;
+
base::WeakPtrFactory<DeveloperPrivateEventRouter> weak_factory_;
DISALLOW_COPY_AND_ASSIGN(DeveloperPrivateEventRouter);
@@ -267,6 +279,10 @@ class DeveloperPrivateAPI : public BrowserContextKeyedAPI,
DISALLOW_COPY_AND_ASSIGN(DeveloperPrivateAPI);
};
+template <>
+void BrowserContextKeyedAPIFactory<
+ DeveloperPrivateAPI>::DeclareFactoryDependencies();
+
namespace api {
class DeveloperPrivateAPIFunction : public UIThreadExtensionFunction {
diff --git a/chromium/chrome/browser/extensions/api/developer_private/developer_private_api_unittest.cc b/chromium/chrome/browser/extensions/api/developer_private/developer_private_api_unittest.cc
index e5c2c3880ee..a4579c439a6 100644
--- a/chromium/chrome/browser/extensions/api/developer_private/developer_private_api_unittest.cc
+++ b/chromium/chrome/browser/extensions/api/developer_private/developer_private_api_unittest.cc
@@ -10,6 +10,7 @@
#include "base/files/file_util.h"
#include "base/macros.h"
#include "base/scoped_observer.h"
+#include "base/stl_util.h"
#include "base/strings/utf_string_conversions.h"
#include "base/test/scoped_feature_list.h"
#include "chrome/browser/chrome_notification_types.h"
@@ -21,6 +22,7 @@
#include "chrome/browser/extensions/extension_service.h"
#include "chrome/browser/extensions/extension_service_test_with_install.h"
#include "chrome/browser/extensions/extension_util.h"
+#include "chrome/browser/extensions/permissions_updater.h"
#include "chrome/browser/extensions/scripting_permissions_modifier.h"
#include "chrome/browser/extensions/test_extension_system.h"
#include "chrome/browser/extensions/unpacked_installer.h"
@@ -41,6 +43,7 @@
#include "content/public/browser/notification_service.h"
#include "content/public/test/web_contents_tester.h"
#include "extensions/browser/api_test_utils.h"
+#include "extensions/browser/event_router.h"
#include "extensions/browser/event_router_factory.h"
#include "extensions/browser/extension_dialog_auto_confirm.h"
#include "extensions/browser/extension_error_test_util.h"
@@ -51,12 +54,15 @@
#include "extensions/browser/extension_util.h"
#include "extensions/browser/install/extension_install_ui.h"
#include "extensions/browser/mock_external_provider.h"
+#include "extensions/browser/test_event_router_observer.h"
#include "extensions/browser/test_extension_registry_observer.h"
#include "extensions/common/extension.h"
#include "extensions/common/extension_builder.h"
#include "extensions/common/extension_features.h"
#include "extensions/common/extension_set.h"
#include "extensions/common/manifest_constants.h"
+#include "extensions/common/permissions/permission_set.h"
+#include "extensions/common/permissions/permissions_data.h"
#include "extensions/common/value_builder.h"
#include "extensions/test/test_extension_dir.h"
#include "services/data_decoder/data_decoder_service.h"
@@ -90,6 +96,34 @@ bool HasPrefsPermission(bool (*has_pref)(const std::string&,
return has_pref(id, context);
}
+bool WasPermissionsUpdatedEventDispatched(
+ const TestEventRouterObserver& observer,
+ const ExtensionId& extension_id) {
+ const std::string kEventName =
+ api::developer_private::OnItemStateChanged::kEventName;
+ const auto& event_map = observer.events();
+ auto iter = event_map.find(kEventName);
+ if (iter == event_map.end())
+ return false;
+
+ const Event& event = *iter->second;
+ CHECK(event.event_args);
+ CHECK_GE(1u, event.event_args->GetList().size());
+ std::unique_ptr<api::developer_private::EventData> event_data =
+ api::developer_private::EventData::FromValue(
+ event.event_args->GetList()[0]);
+ if (!event_data)
+ return false;
+
+ if (event_data->item_id != extension_id ||
+ event_data->event_type !=
+ api::developer_private::EVENT_TYPE_PERMISSIONS_CHANGED) {
+ return false;
+ }
+
+ return true;
+}
+
} // namespace
class DeveloperPrivateApiUnitTest : public ExtensionServiceTestWithInstall {
@@ -1341,19 +1375,33 @@ TEST_F(DeveloperPrivateApiUnitTest, GrantHostPermission) {
}
};
- GURL host("https://example.com");
- EXPECT_FALSE(modifier.HasGrantedHostPermission(host));
- run_add_host_permission(host.spec(), true, nullptr);
+ const GURL kExampleCom("https://example.com/");
+ EXPECT_FALSE(modifier.HasGrantedHostPermission(kExampleCom));
+ run_add_host_permission("https://example.com/*", true, nullptr);
+ EXPECT_TRUE(modifier.HasGrantedHostPermission(kExampleCom));
+
+ const GURL kGoogleCom("https://google.com");
+ const GURL kMapsGoogleCom("https://maps.google.com/");
+ EXPECT_FALSE(modifier.HasGrantedHostPermission(kGoogleCom));
+ EXPECT_FALSE(modifier.HasGrantedHostPermission(kMapsGoogleCom));
+ run_add_host_permission("https://*.google.com/*", true, nullptr);
+ EXPECT_TRUE(modifier.HasGrantedHostPermission(kGoogleCom));
+ EXPECT_TRUE(modifier.HasGrantedHostPermission(kMapsGoogleCom));
run_add_host_permission(kInvalidHost, false, kInvalidHostError);
+ // Path of the pattern must exactly match "/*".
+ run_add_host_permission("https://example.com/", false, kInvalidHostError);
run_add_host_permission("https://example.com/foobar", false,
kInvalidHostError);
run_add_host_permission("https://example.com/#foobar", false,
kInvalidHostError);
+ run_add_host_permission("https://example.com/*foobar", false,
+ kInvalidHostError);
+
+ // Cannot grant chrome:-scheme URLs.
+ GURL chrome_host("chrome://settings/*");
+ run_add_host_permission(chrome_host.spec(), false, kInvalidHostError);
- GURL chrome_host("chrome://settings");
- run_add_host_permission(chrome_host.spec(), false,
- "Cannot grant a permission that wasn't withheld.");
EXPECT_FALSE(modifier.HasGrantedHostPermission(chrome_host));
}
@@ -1386,22 +1434,41 @@ TEST_F(DeveloperPrivateApiUnitTest, RemoveHostPermission) {
}
};
- GURL host("https://example.com");
- run_remove_host_permission(host.spec(), false,
+ run_remove_host_permission("https://example.com/*", false,
"Cannot remove a host that hasn't been granted.");
- modifier.GrantHostPermission(host);
- EXPECT_TRUE(modifier.HasGrantedHostPermission(host));
+ const GURL kExampleCom("https://example.com");
+ modifier.GrantHostPermission(kExampleCom);
+ EXPECT_TRUE(modifier.HasGrantedHostPermission(kExampleCom));
+ // Path of the pattern must exactly match "/*".
+ run_remove_host_permission("https://example.com/", false, kInvalidHostError);
run_remove_host_permission("https://example.com/foobar", false,
kInvalidHostError);
run_remove_host_permission("https://example.com/#foobar", false,
kInvalidHostError);
+ run_remove_host_permission("https://example.com/*foobar", false,
+ kInvalidHostError);
run_remove_host_permission(kInvalidHost, false, kInvalidHostError);
- EXPECT_TRUE(modifier.HasGrantedHostPermission(host));
+ EXPECT_TRUE(modifier.HasGrantedHostPermission(kExampleCom));
+
+ run_remove_host_permission("https://example.com/*", true, nullptr);
+ EXPECT_FALSE(modifier.HasGrantedHostPermission(kExampleCom));
+
+ URLPattern new_pattern(Extension::kValidHostPermissionSchemes,
+ "https://*.google.com/*");
+ PermissionsUpdater(profile()).GrantRuntimePermissions(
+ *extension, PermissionSet(APIPermissionSet(), ManifestPermissionSet(),
+ URLPatternSet({new_pattern}), URLPatternSet()));
+
+ const GURL kGoogleCom("https://google.com/");
+ const GURL kMapsGoogleCom("https://maps.google.com/");
+ EXPECT_TRUE(modifier.HasGrantedHostPermission(kGoogleCom));
+ EXPECT_TRUE(modifier.HasGrantedHostPermission(kMapsGoogleCom));
- run_remove_host_permission(host.spec(), true, nullptr);
- EXPECT_FALSE(modifier.HasGrantedHostPermission(host));
+ run_remove_host_permission("https://*.google.com/*", true, nullptr);
+ EXPECT_FALSE(modifier.HasGrantedHostPermission(kGoogleCom));
+ EXPECT_FALSE(modifier.HasGrantedHostPermission(kMapsGoogleCom));
}
TEST_F(DeveloperPrivateApiUnitTest, UpdateHostAccess) {
@@ -1494,6 +1561,165 @@ TEST_F(DeveloperPrivateApiUnitTest,
EXPECT_FALSE(modifier.HasGrantedHostPermission(example_com));
}
+TEST_F(DeveloperPrivateApiUnitTest,
+ UpdateHostAccess_GrantScopeGreaterThanRequestedScope) {
+ base::test::ScopedFeatureList feature_list;
+ feature_list.InitAndEnableFeature(features::kRuntimeHostPermissions);
+
+ scoped_refptr<const Extension> extension =
+ ExtensionBuilder("test").AddPermission("http://*/*").Build();
+ service()->AddExtension(extension.get());
+ ScriptingPermissionsModifier modifier(profile(), extension.get());
+ modifier.SetWithholdHostPermissions(true);
+
+ ExtensionPrefs* extension_prefs = ExtensionPrefs::Get(profile());
+ EXPECT_EQ(PermissionSet(),
+ extension->permissions_data()->active_permissions());
+ EXPECT_EQ(PermissionSet(),
+ *extension_prefs->GetRuntimeGrantedPermissions(extension->id()));
+
+ {
+ scoped_refptr<UIThreadExtensionFunction> function =
+ base::MakeRefCounted<api::DeveloperPrivateAddHostPermissionFunction>();
+ std::string args = base::StringPrintf(
+ R"(["%s", "%s"])", extension->id().c_str(), "*://chromium.org/*");
+ EXPECT_TRUE(api_test_utils::RunFunction(function.get(), args, profile()))
+ << function->GetError();
+ }
+
+ // The active permissions (which are given to the extension process) should
+ // only include the intersection of what was requested by the extension and
+ // the runtime granted permissions - which is http://chromium.org/*.
+ URLPattern http_chromium(Extension::kValidHostPermissionSchemes,
+ "http://chromium.org/*");
+ const PermissionSet http_chromium_set(
+ APIPermissionSet(), ManifestPermissionSet(),
+ URLPatternSet({http_chromium}), URLPatternSet());
+ EXPECT_EQ(http_chromium_set,
+ extension->permissions_data()->active_permissions());
+
+ // The runtime granted permissions should include all of what was approved by
+ // the user, which is *://chromium.org/*, and should be present in both the
+ // scriptable and explicit hosts.
+ URLPattern all_chromium(Extension::kValidHostPermissionSchemes,
+ "*://chromium.org/*");
+ const PermissionSet all_chromium_set(
+ APIPermissionSet(), ManifestPermissionSet(),
+ URLPatternSet({all_chromium}), URLPatternSet({all_chromium}));
+ EXPECT_EQ(all_chromium_set,
+ *extension_prefs->GetRuntimeGrantedPermissions(extension->id()));
+
+ {
+ scoped_refptr<UIThreadExtensionFunction> function = base::MakeRefCounted<
+ api::DeveloperPrivateRemoveHostPermissionFunction>();
+ std::string args = base::StringPrintf(
+ R"(["%s", "%s"])", extension->id().c_str(), "*://chromium.org/*");
+ EXPECT_TRUE(api_test_utils::RunFunction(function.get(), args, profile()))
+ << function->GetError();
+ }
+
+ // Removing the granted permission should remove it entirely from both
+ // the active and the stored permissions.
+ EXPECT_EQ(PermissionSet(),
+ extension->permissions_data()->active_permissions());
+ EXPECT_EQ(PermissionSet(),
+ *extension_prefs->GetRuntimeGrantedPermissions(extension->id()));
+}
+
+TEST_F(DeveloperPrivateApiUnitTest,
+ UpdateHostAccess_UnrequestedHostsDispatchUpdateEvents) {
+ base::test::ScopedFeatureList feature_list;
+ feature_list.InitAndEnableFeature(features::kRuntimeHostPermissions);
+
+ scoped_refptr<const Extension> extension =
+ ExtensionBuilder("test").AddPermission("http://google.com/*").Build();
+ service()->AddExtension(extension.get());
+ ScriptingPermissionsModifier modifier(profile(), extension.get());
+ modifier.SetWithholdHostPermissions(true);
+
+ // We need to call DeveloperPrivateAPI::Get() in order to instantiate the
+ // keyed service, since it's not created by default in unit tests.
+ DeveloperPrivateAPI::Get(profile());
+ const ExtensionId listener_id = crx_file::id_util::GenerateId("listener");
+ EventRouter* event_router = EventRouter::Get(profile());
+
+ // The DeveloperPrivateEventRouter will only dispatch events if there's at
+ // least one listener to dispatch to. Create one.
+ content::RenderProcessHost* process = nullptr;
+ const char* kEventName =
+ api::developer_private::OnItemStateChanged::kEventName;
+ event_router->AddEventListener(kEventName, process, listener_id);
+
+ TestEventRouterObserver test_observer(event_router);
+ EXPECT_FALSE(
+ WasPermissionsUpdatedEventDispatched(test_observer, extension->id()));
+
+ URLPatternSet hosts({URLPattern(Extension::kValidHostPermissionSchemes,
+ "https://example.com/*")});
+ PermissionSet permissions(APIPermissionSet(), ManifestPermissionSet(), hosts,
+ hosts);
+ PermissionsUpdater(profile()).GrantRuntimePermissions(*extension,
+ permissions);
+ // The event router fetches icons from a blocking thread when sending the
+ // update event; allow it to finish before verifying the event was dispatched.
+ base::RunLoop().RunUntilIdle();
+ EXPECT_TRUE(
+ WasPermissionsUpdatedEventDispatched(test_observer, extension->id()));
+
+ test_observer.ClearEvents();
+
+ PermissionsUpdater(profile()).RevokeRuntimePermissions(*extension,
+ permissions);
+ base::RunLoop().RunUntilIdle();
+ EXPECT_TRUE(
+ WasPermissionsUpdatedEventDispatched(test_observer, extension->id()));
+}
+
+TEST_F(DeveloperPrivateApiUnitTest, ExtensionUpdatedEventOnPermissionsChange) {
+ // We need to call DeveloperPrivateAPI::Get() in order to instantiate the
+ // keyed service, since it's not created by default in unit tests.
+ DeveloperPrivateAPI::Get(profile());
+ const ExtensionId listener_id = crx_file::id_util::GenerateId("listener");
+ EventRouter* event_router = EventRouter::Get(profile());
+
+ // The DeveloperPrivateEventRouter will only dispatch events if there's at
+ // least one listener to dispatch to. Create one.
+ content::RenderProcessHost* process = nullptr;
+ const char* kEventName =
+ api::developer_private::OnItemStateChanged::kEventName;
+ event_router->AddEventListener(kEventName, process, listener_id);
+
+ scoped_refptr<const Extension> dummy_extension =
+ ExtensionBuilder("dummy")
+ .SetManifestKey("optional_permissions",
+ ListBuilder().Append("tabs").Build())
+ .Build();
+
+ TestEventRouterObserver test_observer(event_router);
+ EXPECT_FALSE(WasPermissionsUpdatedEventDispatched(test_observer,
+ dummy_extension->id()));
+
+ APIPermissionSet apis;
+ apis.insert(APIPermission::kTab);
+ PermissionSet permissions(apis, ManifestPermissionSet(), URLPatternSet(),
+ URLPatternSet());
+ PermissionsUpdater(profile()).GrantOptionalPermissions(*dummy_extension,
+ permissions);
+ // The event router fetches icons from a blocking thread when sending the
+ // update event; allow it to finish before verifying the event was dispatched.
+ base::RunLoop().RunUntilIdle();
+ EXPECT_TRUE(WasPermissionsUpdatedEventDispatched(test_observer,
+ dummy_extension->id()));
+
+ test_observer.ClearEvents();
+
+ PermissionsUpdater(profile()).RevokeOptionalPermissions(
+ *dummy_extension, permissions, PermissionsUpdater::REMOVE_HARD);
+ base::RunLoop().RunUntilIdle();
+ EXPECT_TRUE(WasPermissionsUpdatedEventDispatched(test_observer,
+ dummy_extension->id()));
+}
+
class DeveloperPrivateZipInstallerUnitTest
: public DeveloperPrivateApiUnitTest {
public:
diff --git a/chromium/chrome/browser/extensions/api/developer_private/extension_info_generator.cc b/chromium/chrome/browser/extensions/api/developer_private/extension_info_generator.cc
index 98edfbd90b7..d17531186eb 100644
--- a/chromium/chrome/browser/extensions/api/developer_private/extension_info_generator.cc
+++ b/chromium/chrome/browser/extensions/api/developer_private/extension_info_generator.cc
@@ -273,24 +273,33 @@ void AddPermissionsInfo(content::BrowserContext* browser_context,
if (!permissions_modifier.HasWithheldHostPermissions()) {
permissions->host_access = developer::HOST_ACCESS_ON_ALL_SITES;
} else {
- constexpr bool include_rcd = true;
- constexpr bool exclude_file_scheme = true;
- std::set<std::string> distinct_hosts =
- permission_message_util::GetDistinctHosts(
- active_permissions.effective_hosts(), include_rcd,
- exclude_file_scheme);
- // TODO(devlin): This isn't quite right - it's possible the user just
- // selected "on specific sites" from the dropdown, and hasn't yet added
- // any sites. We'll need to handle this.
- // https://crbug.com/844128.
- if (!distinct_hosts.empty()) {
+ ExtensionPrefs* extension_prefs = ExtensionPrefs::Get(browser_context);
+ std::unique_ptr<const PermissionSet> runtime_granted_permissions =
+ extension_prefs->GetRuntimeGrantedPermissions(extension.id());
+ if (runtime_granted_permissions->effective_hosts().is_empty()) {
+ // TODO(devlin): This isn't quite right - it's possible the user just
+ // selected "on specific sites" from the dropdown, and hasn't yet added
+ // any sites. We'll need to handle this.
+ // https://crbug.com/844128.
+ permissions->host_access = developer::HOST_ACCESS_ON_CLICK;
+ } else {
permissions->host_access = developer::HOST_ACCESS_ON_SPECIFIC_SITES;
+ std::set<std::string> distinct_hosts;
+ for (auto pattern : runtime_granted_permissions->effective_hosts()) {
+ // We only allow addition/removal of full hosts (since from a
+ // permissions point of view, path is irrelevant). We always make the
+ // path wildcard when adding through this UI, but the optional
+ // permissions API may allow adding permissions with paths.
+ // TODO(devlin): Investigate, and possibly change the optional
+ // permissions API.
+ pattern.SetPath("/*");
+ distinct_hosts.insert(pattern.GetAsString());
+ }
+
permissions->runtime_host_permissions =
std::make_unique<std::vector<std::string>>(
std::make_move_iterator(distinct_hosts.begin()),
std::make_move_iterator(distinct_hosts.end()));
- } else {
- permissions->host_access = developer::HOST_ACCESS_ON_CLICK;
}
}
}
diff --git a/chromium/chrome/browser/extensions/api/developer_private/extension_info_generator_unittest.cc b/chromium/chrome/browser/extensions/api/developer_private/extension_info_generator_unittest.cc
index a8184d3e998..9d8496fb56c 100644
--- a/chromium/chrome/browser/extensions/api/developer_private/extension_info_generator_unittest.cc
+++ b/chromium/chrome/browser/extensions/api/developer_private/extension_info_generator_unittest.cc
@@ -36,7 +36,10 @@
#include "extensions/common/extension_features.h"
#include "extensions/common/feature_switch.h"
#include "extensions/common/permissions/permission_message.h"
+#include "extensions/common/permissions/permission_set.h"
#include "extensions/common/permissions/permissions_data.h"
+#include "extensions/common/url_pattern.h"
+#include "extensions/common/url_pattern_set.h"
#include "extensions/common/value_builder.h"
#include "testing/gmock/include/gmock/gmock.h"
#include "testing/gtest/include/gtest/gtest.h"
@@ -430,7 +433,7 @@ TEST_F(ExtensionInfoGeneratorUnitTest, RuntimeHostPermissions) {
info->permissions.host_access);
ASSERT_TRUE(info->permissions.runtime_host_permissions);
EXPECT_THAT(*info->permissions.runtime_host_permissions,
- testing::UnorderedElementsAre("example.com"));
+ testing::UnorderedElementsAre("https://example.com/*"));
EXPECT_THAT(info->permissions.simple_permissions, testing::IsEmpty());
// An extension that doesn't request any host permissions should not have
@@ -457,6 +460,50 @@ TEST_F(ExtensionInfoGeneratorUnitTest, RuntimeHostPermissionsWithoutFeature) {
info->permissions.simple_permissions[0].message);
}
+// Tests that runtime_host_permissions is correctly populated when permissions
+// are granted by the user beyond what the extension originally requested in the
+// manifest.
+TEST_F(ExtensionInfoGeneratorUnitTest,
+ RuntimeHostPermissionsBeyondRequestedScope) {
+ base::test::ScopedFeatureList feature_list;
+ feature_list.InitAndEnableFeature(features::kRuntimeHostPermissions);
+
+ scoped_refptr<const Extension> extension =
+ CreateExtension("extension", ListBuilder().Append("http://*/*").Build(),
+ Manifest::INTERNAL);
+
+ std::unique_ptr<developer::ExtensionInfo> info =
+ GenerateExtensionInfo(extension->id());
+
+ // Withhold permissions, and grant *://chromium.org/*.
+ ScriptingPermissionsModifier permissions_modifier(profile(), extension);
+ permissions_modifier.SetWithholdHostPermissions(true);
+ URLPattern all_chromium(Extension::kValidHostPermissionSchemes,
+ "*://chromium.org/*");
+ PermissionSet all_chromium_set(APIPermissionSet(), ManifestPermissionSet(),
+ URLPatternSet({all_chromium}),
+ URLPatternSet({all_chromium}));
+ PermissionsUpdater(profile()).GrantRuntimePermissions(*extension,
+ all_chromium_set);
+
+ // The extension should only be granted http://chromium.org/* (since that's
+ // the intersection with what it requested).
+ URLPattern http_chromium(Extension::kValidHostPermissionSchemes,
+ "http://chromium.org/*");
+ EXPECT_EQ(PermissionSet(APIPermissionSet(), ManifestPermissionSet(),
+ URLPatternSet({http_chromium}), URLPatternSet()),
+ extension->permissions_data()->active_permissions());
+
+ // The generated info should use the entirety of the granted permission,
+ // which is *://chromium.org/*.
+ info = GenerateExtensionInfo(extension->id());
+ EXPECT_EQ(developer::HOST_ACCESS_ON_SPECIFIC_SITES,
+ info->permissions.host_access);
+ ASSERT_TRUE(info->permissions.runtime_host_permissions);
+ EXPECT_THAT(*info->permissions.runtime_host_permissions,
+ testing::UnorderedElementsAre("*://chromium.org/*"));
+}
+
// Test that file:// access checkbox does not show up when the user can't
// modify an extension's settings. https://crbug.com/173640.
TEST_F(ExtensionInfoGeneratorUnitTest, ExtensionInfoLockedAllUrls) {
diff --git a/chromium/chrome/browser/extensions/api/downloads/downloads_api.cc b/chromium/chrome/browser/extensions/api/downloads/downloads_api.cc
index 1205f08f044..9ad91ec7fcf 100644
--- a/chromium/chrome/browser/extensions/api/downloads/downloads_api.cc
+++ b/chromium/chrome/browser/extensions/api/downloads/downloads_api.cc
@@ -642,12 +642,7 @@ class ExtensionDownloadsEventRouterData : public base::SupportsUserData::Data {
download_item->SetUserData(kKey, base::WrapUnique(this));
}
- ~ExtensionDownloadsEventRouterData() override {
- if (updated_ > 0) {
- UMA_HISTOGRAM_PERCENTAGE("Download.OnChanged",
- (changed_fired_ * 100 / updated_));
- }
- }
+ ~ExtensionDownloadsEventRouterData() override = default;
void set_is_download_completed(bool is_download_completed) {
is_download_completed_ = is_download_completed;
diff --git a/chromium/chrome/browser/extensions/api/downloads/downloads_api_browsertest.cc b/chromium/chrome/browser/extensions/api/downloads/downloads_api_browsertest.cc
index a6529fc0fdb..e0fbac65374 100644
--- a/chromium/chrome/browser/extensions/api/downloads/downloads_api_browsertest.cc
+++ b/chromium/chrome/browser/extensions/api/downloads/downloads_api_browsertest.cc
@@ -1496,12 +1496,21 @@ IN_PROC_BROWSER_TEST_F(DownloadExtensionTest,
ASSERT_EQ(items[2]->GetTargetFilePath().value(), item_name);
}
+// https://crbug.com/874946, flaky on Win.
+#if defined(OS_WIN)
+#define MAYBE_DownloadExtensionTest_SearchPauseResumeCancelGetFileIconIncognito \
+ DISABLED_DownloadExtensionTest_SearchPauseResumeCancelGetFileIconIncognito
+#else
+#define MAYBE_DownloadExtensionTest_SearchPauseResumeCancelGetFileIconIncognito \
+ DownloadExtensionTest_SearchPauseResumeCancelGetFileIconIncognito
+#endif
// Test that incognito downloads are only visible in incognito contexts, and
// test that on-record downloads are visible in both incognito and on-record
// contexts, for DownloadsSearchFunction, DownloadsPauseFunction,
// DownloadsResumeFunction, and DownloadsCancelFunction.
-IN_PROC_BROWSER_TEST_F(DownloadExtensionTest,
- DownloadExtensionTest_SearchPauseResumeCancelGetFileIconIncognito) {
+IN_PROC_BROWSER_TEST_F(
+ DownloadExtensionTest,
+ MAYBE_DownloadExtensionTest_SearchPauseResumeCancelGetFileIconIncognito) {
std::unique_ptr<base::Value> result_value;
base::ListValue* result_list = NULL;
base::DictionaryValue* result_dict = NULL;
diff --git a/chromium/chrome/browser/extensions/api/easy_unlock_private/easy_unlock_private_api.cc b/chromium/chrome/browser/extensions/api/easy_unlock_private/easy_unlock_private_api.cc
index d29ba90273d..72e1f6400f1 100644
--- a/chromium/chrome/browser/extensions/api/easy_unlock_private/easy_unlock_private_api.cc
+++ b/chromium/chrome/browser/extensions/api/easy_unlock_private/easy_unlock_private_api.cc
@@ -13,7 +13,7 @@
#include "base/lazy_instance.h"
#include "base/numerics/safe_conversions.h"
#include "base/strings/utf_string_conversions.h"
-#include "base/task_scheduler/post_task.h"
+#include "base/task/post_task.h"
#include "base/threading/thread_task_runner_handle.h"
#include "base/time/default_tick_clock.h"
#include "base/time/time.h"
@@ -26,6 +26,7 @@
#include "chrome/browser/chromeos/login/easy_unlock/easy_unlock_service_regular.h"
#include "chrome/browser/chromeos/login/easy_unlock/easy_unlock_tpm_key_manager.h"
#include "chrome/browser/chromeos/login/easy_unlock/easy_unlock_tpm_key_manager_factory.h"
+#include "chrome/browser/extensions/api/easy_unlock_private/easy_unlock_private_connection.h"
#include "chrome/browser/extensions/api/easy_unlock_private/easy_unlock_private_connection_manager.h"
#include "chrome/browser/profiles/profile.h"
#include "chrome/browser/ui/proximity_auth/proximity_auth_error_bubble.h"
diff --git a/chromium/chrome/browser/extensions/api/easy_unlock_private/easy_unlock_private_connection.h b/chromium/chrome/browser/extensions/api/easy_unlock_private/easy_unlock_private_connection.h
index 90b1b9080e2..987e88500e4 100644
--- a/chromium/chrome/browser/extensions/api/easy_unlock_private/easy_unlock_private_connection.h
+++ b/chromium/chrome/browser/extensions/api/easy_unlock_private/easy_unlock_private_connection.h
@@ -11,12 +11,20 @@
#include "content/public/browser/browser_thread.h"
#include "extensions/browser/api/api_resource.h"
#include "extensions/browser/api/api_resource_manager.h"
+#include "extensions/browser/browser_context_keyed_api_factory.h"
namespace cryptauth {
class Connection;
} // namespace cryptauth
namespace extensions {
+
+class EasyUnlockPrivateConnection;
+
+template <>
+BrowserContextKeyedAPIFactory<ApiResourceManager<EasyUnlockPrivateConnection>>*
+ApiResourceManager<EasyUnlockPrivateConnection>::GetFactoryInstance();
+
// An ApiResource wrapper for a cryptauth::Connection.
class EasyUnlockPrivateConnection : public ApiResource {
public:
diff --git a/chromium/chrome/browser/extensions/api/easy_unlock_private/easy_unlock_private_connection_manager.cc b/chromium/chrome/browser/extensions/api/easy_unlock_private/easy_unlock_private_connection_manager.cc
index 3d694cbfe8d..58ec3c09ffa 100644
--- a/chromium/chrome/browser/extensions/api/easy_unlock_private/easy_unlock_private_connection_manager.cc
+++ b/chromium/chrome/browser/extensions/api/easy_unlock_private/easy_unlock_private_connection_manager.cc
@@ -136,7 +136,7 @@ void EasyUnlockPrivateConnectionManager::OnMessageReceived(
std::string event_name = api::easy_unlock_private::OnDataReceived::kEventName;
events::HistogramValue histogram_value =
events::EASY_UNLOCK_PRIVATE_ON_DATA_RECEIVED;
- std::vector<char> data(message.body().begin(), message.body().end());
+ std::vector<uint8_t> data(message.body().begin(), message.body().end());
std::unique_ptr<base::ListValue> args =
api::easy_unlock_private::OnDataReceived::Create(0, data);
DispatchConnectionEvent(event_name, histogram_value, &connection,
@@ -156,7 +156,7 @@ void EasyUnlockPrivateConnectionManager::OnSendCompleted(
api::easy_unlock_private::OnSendCompleted::kEventName;
events::HistogramValue histogram_value =
events::EASY_UNLOCK_PRIVATE_ON_SEND_COMPLETED;
- std::vector<char> data(message.payload().begin(), message.payload().end());
+ std::vector<uint8_t> data(message.payload().begin(), message.payload().end());
std::unique_ptr<base::ListValue> args =
api::easy_unlock_private::OnSendCompleted::Create(0, data, success);
DispatchConnectionEvent(event_name, histogram_value, &connection,
diff --git a/chromium/chrome/browser/extensions/api/enterprise_device_attributes/enterprise_device_attributes_apitest.cc b/chromium/chrome/browser/extensions/api/enterprise_device_attributes/enterprise_device_attributes_apitest.cc
index c923b2d663b..07767f021ca 100644
--- a/chromium/chrome/browser/extensions/api/enterprise_device_attributes/enterprise_device_attributes_apitest.cc
+++ b/chromium/chrome/browser/extensions/api/enterprise_device_attributes/enterprise_device_attributes_apitest.cc
@@ -55,10 +55,17 @@ constexpr char kAnotherAffiliationID[] = "another-affiliation-id";
constexpr char kTestExtensionID[] = "nbiliclbejdndfpchgkbmfoppjplbdok";
struct Params {
- explicit Params(bool affiliated) : affiliated_(affiliated) {}
- bool affiliated_;
+ explicit Params(bool affiliated) : affiliated(affiliated) {}
+ bool affiliated;
};
+// Must be a valid test name (no spaces etc.). Makes the test show up as e.g.
+// AffiliationCheck/U.A.B.T.Affiliated/NotAffiliated_NotActiveDirectory
+std::string PrintParam(testing::TestParamInfo<Params> param_info) {
+ return base::StringPrintf("%sAffiliated",
+ param_info.param.affiliated ? "" : "Not");
+}
+
base::Value BuildCustomArg(const std::string& expected_directory_device_id,
const std::string& expected_serial_number,
const std::string& expected_asset_id,
@@ -78,9 +85,9 @@ base::Value BuildCustomArg(const std::string& expected_directory_device_id,
namespace extensions {
-class EnterpriseDeviceAttributesTest :
- public ExtensionApiTest,
- public ::testing::WithParamInterface<Params> {
+class EnterpriseDeviceAttributesTest
+ : public ExtensionApiTest,
+ public ::testing::WithParamInterface<Params> {
public:
EnterpriseDeviceAttributesTest() {
fake_statistics_provider_.SetMachineStatistic(
@@ -93,8 +100,8 @@ class EnterpriseDeviceAttributesTest :
// ExtensionApiTest
void SetUpCommandLine(base::CommandLine* command_line) override {
ExtensionApiTest::SetUpCommandLine(command_line);
- policy::affiliation_test_helper::
- AppendCommandLineSwitchesForLoginManager(command_line);
+ policy::AffiliationTestHelper::AppendCommandLineSwitchesForLoginManager(
+ command_line);
}
void SetUpInProcessBrowserTestFixture() override {
@@ -106,29 +113,24 @@ class EnterpriseDeviceAttributesTest :
std::unique_ptr<chromeos::SessionManagerClient>(
fake_session_manager_client));
+ policy::AffiliationTestHelper affiliation_helper =
+ policy::AffiliationTestHelper::CreateForCloud(
+ fake_session_manager_client);
+
std::set<std::string> device_affiliation_ids;
device_affiliation_ids.insert(kAffiliationID);
- policy::affiliation_test_helper::SetDeviceAffiliationID(
- &test_helper_, fake_session_manager_client, device_affiliation_ids);
+ ASSERT_NO_FATAL_FAILURE(affiliation_helper.SetDeviceAffiliationIDs(
+ &test_helper_, device_affiliation_ids));
std::set<std::string> user_affiliation_ids;
- if (GetParam().affiliated_) {
+ if (GetParam().affiliated) {
user_affiliation_ids.insert(kAffiliationID);
} else {
user_affiliation_ids.insert(kAnotherAffiliationID);
}
policy::UserPolicyBuilder user_policy;
- policy::affiliation_test_helper::SetUserAffiliationIDs(
- &user_policy, fake_session_manager_client, affiliated_account_id_,
- user_affiliation_ids);
-
- // Set up fake install attributes.
- std::unique_ptr<chromeos::StubInstallAttributes> attributes =
- std::make_unique<chromeos::StubInstallAttributes>();
-
- attributes->SetCloudManaged("fake-domain", "fake-id");
- policy::BrowserPolicyConnectorChromeOS::SetInstallAttributesForTesting(
- attributes.release());
+ ASSERT_NO_FATAL_FAILURE(affiliation_helper.SetUserAffiliationIDs(
+ &user_policy, affiliated_account_id_, user_affiliation_ids));
test_helper_.InstallOwnerKey();
// Init the device policy.
@@ -157,7 +159,7 @@ class EnterpriseDeviceAttributesTest :
const base::ListValue* users =
g_browser_process->local_state()->GetList("LoggedInUsers");
if (!users->empty())
- policy::affiliation_test_helper::LoginUser(affiliated_account_id_);
+ policy::AffiliationTestHelper::LoginUser(affiliated_account_id_);
ExtensionApiTest::SetUpOnMainThread();
}
@@ -221,13 +223,16 @@ class EnterpriseDeviceAttributesTest :
kAffiliatedUserGaiaId);
private:
+ chromeos::ScopedStubInstallAttributes test_install_attributes_{
+ chromeos::StubInstallAttributes::CreateCloudManaged("fake-domain",
+ "fake-id")};
policy::MockConfigurationPolicyProvider policy_provider_;
policy::DevicePolicyCrosTestHelper test_helper_;
chromeos::system::ScopedFakeStatisticsProvider fake_statistics_provider_;
};
IN_PROC_BROWSER_TEST_P(EnterpriseDeviceAttributesTest, PRE_Success) {
- policy::affiliation_test_helper::PreLoginUser(affiliated_account_id_);
+ policy::AffiliationTestHelper::PreLoginUser(affiliated_account_id_);
}
IN_PROC_BROWSER_TEST_P(EnterpriseDeviceAttributesTest, Success) {
@@ -237,17 +242,18 @@ IN_PROC_BROWSER_TEST_P(EnterpriseDeviceAttributesTest, Success) {
SetPolicy();
- EXPECT_EQ(GetParam().affiliated_, user_manager::UserManager::Get()->
- FindUser(affiliated_account_id_)->IsAffiliated());
+ EXPECT_EQ(GetParam().affiliated, user_manager::UserManager::Get()
+ ->FindUser(affiliated_account_id_)
+ ->IsAffiliated());
// Device attributes are available only for affiliated user.
std::string expected_directory_device_id =
- GetParam().affiliated_ ? kDeviceId : "";
+ GetParam().affiliated ? kDeviceId : "";
std::string expected_serial_number =
- GetParam().affiliated_ ? kSerialNumber : "";
- std::string expected_asset_id = GetParam().affiliated_ ? kAssetId : "";
+ GetParam().affiliated ? kSerialNumber : "";
+ std::string expected_asset_id = GetParam().affiliated ? kAssetId : "";
std::string expected_annotated_location =
- GetParam().affiliated_ ? kAnnotatedLocation : "";
+ GetParam().affiliated ? kAnnotatedLocation : "";
// Pass the expected value (device_id) to test.
ASSERT_TRUE(TestExtension(
@@ -284,6 +290,8 @@ IN_PROC_BROWSER_TEST_F(
// Both cases of affiliated and non-affiliated on the device user are tested.
INSTANTIATE_TEST_CASE_P(AffiliationCheck,
- EnterpriseDeviceAttributesTest,
- ::testing::Values(Params(true), Params(false)));
+ EnterpriseDeviceAttributesTest,
+ ::testing::Values(Params(true /* affiliated */),
+ Params(false /* affiliated */)),
+ PrintParam);
} // namespace extensions
diff --git a/chromium/chrome/browser/extensions/api/enterprise_hardware_platform/OWNERS b/chromium/chrome/browser/extensions/api/enterprise_hardware_platform/OWNERS
new file mode 100644
index 00000000000..05cb9bd3c02
--- /dev/null
+++ b/chromium/chrome/browser/extensions/api/enterprise_hardware_platform/OWNERS
@@ -0,0 +1 @@
+guidou@chromium.org
diff --git a/chromium/chrome/browser/extensions/api/enterprise_hardware_platform/enterprise_hardware_platform_api.cc b/chromium/chrome/browser/extensions/api/enterprise_hardware_platform/enterprise_hardware_platform_api.cc
new file mode 100644
index 00000000000..3a75d928dd4
--- /dev/null
+++ b/chromium/chrome/browser/extensions/api/enterprise_hardware_platform/enterprise_hardware_platform_api.cc
@@ -0,0 +1,38 @@
+// 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/extensions/api/enterprise_hardware_platform/enterprise_hardware_platform_api.h"
+
+#include <utility>
+
+#include "base/bind.h"
+#include "chrome/common/extensions/api/enterprise_hardware_platform.h"
+
+namespace extensions {
+
+EnterpriseHardwarePlatformGetHardwarePlatformInfoFunction::
+ EnterpriseHardwarePlatformGetHardwarePlatformInfoFunction() = default;
+
+EnterpriseHardwarePlatformGetHardwarePlatformInfoFunction::
+ ~EnterpriseHardwarePlatformGetHardwarePlatformInfoFunction() = default;
+
+ExtensionFunction::ResponseAction
+EnterpriseHardwarePlatformGetHardwarePlatformInfoFunction::Run() {
+ base::SysInfo::GetHardwareInfo(base::BindOnce(
+ &EnterpriseHardwarePlatformGetHardwarePlatformInfoFunction::
+ OnHardwarePlatformInfo,
+ this));
+ return RespondLater();
+}
+
+void EnterpriseHardwarePlatformGetHardwarePlatformInfoFunction::
+ OnHardwarePlatformInfo(base::SysInfo::HardwareInfo info) {
+ api::enterprise_hardware_platform::HardwarePlatformInfo result;
+ result.manufacturer = std::move(info.manufacturer);
+ result.model = std::move(info.model);
+ Respond(ArgumentList(api::enterprise_hardware_platform::
+ GetHardwarePlatformInfo::Results::Create(result)));
+}
+
+} // namespace extensions
diff --git a/chromium/chrome/browser/extensions/api/enterprise_hardware_platform/enterprise_hardware_platform_api.h b/chromium/chrome/browser/extensions/api/enterprise_hardware_platform/enterprise_hardware_platform_api.h
new file mode 100644
index 00000000000..70726063ac1
--- /dev/null
+++ b/chromium/chrome/browser/extensions/api/enterprise_hardware_platform/enterprise_hardware_platform_api.h
@@ -0,0 +1,37 @@
+// 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_EXTENSIONS_API_ENTERPRISE_HARDWARE_PLATFORM_ENTERPRISE_HARDWARE_PLATFORM_API_H_
+#define CHROME_BROWSER_EXTENSIONS_API_ENTERPRISE_HARDWARE_PLATFORM_ENTERPRISE_HARDWARE_PLATFORM_API_H_
+
+#include "base/macros.h"
+#include "base/sys_info.h"
+#include "extensions/browser/extension_function.h"
+
+namespace extensions {
+
+class EnterpriseHardwarePlatformGetHardwarePlatformInfoFunction
+ : public UIThreadExtensionFunction {
+ public:
+ EnterpriseHardwarePlatformGetHardwarePlatformInfoFunction();
+
+ protected:
+ ~EnterpriseHardwarePlatformGetHardwarePlatformInfoFunction() override;
+
+ ResponseAction Run() override;
+
+ private:
+ DECLARE_EXTENSION_FUNCTION(
+ "enterprise.hardwarePlatform.getHardwarePlatformInfo",
+ ENTERPRISE_HARDWAREPLATFORM_GETHARDWAREPLATFORMINFO);
+
+ void OnHardwarePlatformInfo(base::SysInfo::HardwareInfo info);
+
+ DISALLOW_COPY_AND_ASSIGN(
+ EnterpriseHardwarePlatformGetHardwarePlatformInfoFunction);
+};
+
+} // namespace extensions
+
+#endif // CHROME_BROWSER_EXTENSIONS_API_ENTERPRISE_HARDWARE_PLATFORM_ENTERPRISE_HARDWARE_PLATFORM_API_H_
diff --git a/chromium/chrome/browser/extensions/api/enterprise_hardware_platform/enterprise_hardware_platform_api_unittest.cc b/chromium/chrome/browser/extensions/api/enterprise_hardware_platform/enterprise_hardware_platform_api_unittest.cc
new file mode 100644
index 00000000000..285c63683a1
--- /dev/null
+++ b/chromium/chrome/browser/extensions/api/enterprise_hardware_platform/enterprise_hardware_platform_api_unittest.cc
@@ -0,0 +1,84 @@
+// 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/extensions/api/enterprise_hardware_platform/enterprise_hardware_platform_api.h"
+
+#include <memory>
+#include <string>
+
+#include "base/json/json_writer.h"
+#include "chrome/browser/extensions/extension_api_unittest.h"
+#include "chrome/browser/extensions/extension_function_test_utils.h"
+#include "chrome/browser/extensions/extension_service.h"
+#include "chrome/browser/extensions/extension_service_test_with_install.h"
+#include "components/crx_file/id_util.h"
+#include "extensions/common/extension_builder.h"
+#include "testing/gtest/include/gtest/gtest.h"
+
+namespace extensions {
+
+class EnterpriseHardwarePlatformAPITest
+ : public ExtensionServiceTestWithInstall {
+ public:
+ EnterpriseHardwarePlatformAPITest() = default;
+ ~EnterpriseHardwarePlatformAPITest() override = default;
+ Browser* browser() { return browser_.get(); }
+
+ private:
+ void SetUp() override {
+ ExtensionServiceTestWithInstall::SetUp();
+ InitializeEmptyExtensionService();
+ browser_window_ = std::make_unique<TestBrowserWindow>();
+ Browser::CreateParams params(profile(), true);
+ params.type = Browser::TYPE_TABBED;
+ params.window = browser_window_.get();
+ browser_ = std::make_unique<Browser>(params);
+ }
+
+ void TearDown() override {
+ browser_.reset();
+ browser_window_.reset();
+ ExtensionServiceTestWithInstall::TearDown();
+ }
+
+ std::unique_ptr<TestBrowserWindow> browser_window_;
+ std::unique_ptr<Browser> browser_;
+
+ DISALLOW_COPY_AND_ASSIGN(EnterpriseHardwarePlatformAPITest);
+};
+
+TEST_F(EnterpriseHardwarePlatformAPITest, GetHardwarePlatformInfo) {
+ scoped_refptr<const Extension> extension = ExtensionBuilder("Test").Build();
+ scoped_refptr<EnterpriseHardwarePlatformGetHardwarePlatformInfoFunction>
+ function =
+ new EnterpriseHardwarePlatformGetHardwarePlatformInfoFunction();
+ function->set_extension(extension.get());
+ function->set_has_callback(true);
+
+ std::string args;
+ base::JSONWriter::Write(base::ListValue(), &args);
+
+ std::unique_ptr<base::Value> result(
+ extension_function_test_utils::RunFunctionAndReturnSingleResult(
+ function.get(), args, browser()));
+ base::RunLoop().RunUntilIdle();
+
+ ASSERT_TRUE(result);
+ ASSERT_TRUE(result->is_dict());
+ ASSERT_EQ(result->DictSize(), 2u);
+
+ const base::Value* val =
+ result->FindKeyOfType("manufacturer", base::Value::Type::STRING);
+ ASSERT_TRUE(val);
+ const std::string& manufacturer = val->GetString();
+
+ val = result->FindKeyOfType("model", base::Value::Type::STRING);
+ ASSERT_TRUE(val);
+ const std::string& model = val->GetString();
+
+ EXPECT_FALSE(manufacturer.empty());
+ EXPECT_FALSE(model.empty());
+}
+
+} // namespace extensions
diff --git a/chromium/chrome/browser/extensions/api/enterprise_platform_keys/enterprise_platform_keys_api.cc b/chromium/chrome/browser/extensions/api/enterprise_platform_keys/enterprise_platform_keys_api.cc
index 20f62befb7d..7136b037ebe 100644
--- a/chromium/chrome/browser/extensions/api/enterprise_platform_keys/enterprise_platform_keys_api.cc
+++ b/chromium/chrome/browser/extensions/api/enterprise_platform_keys/enterprise_platform_keys_api.cc
@@ -32,11 +32,11 @@ const char kEnterprisePlatformErrorInternal[] = "Internal Error.";
const char kEnterprisePlatformErrorInvalidX509Cert[] =
"Certificate is not a valid X.509 certificate.";
-std::vector<char> VectorFromString(const std::string& s) {
- return std::vector<char>(s.begin(), s.end());
+std::vector<uint8_t> VectorFromString(const std::string& s) {
+ return std::vector<uint8_t>(s.begin(), s.end());
}
-std::string StringFromVector(const std::vector<char>& v) {
+std::string StringFromVector(const std::vector<uint8_t>& v) {
return std::string(v.begin(), v.end());
}
@@ -77,7 +77,7 @@ void EnterprisePlatformKeysInternalGenerateKeyFunction::OnGeneratedKey(
DCHECK_CURRENTLY_ON(content::BrowserThread::UI);
if (error_message.empty()) {
Respond(ArgumentList(api_epki::GenerateKey::Results::Create(
- std::vector<char>(public_key_der.begin(), public_key_der.end()))));
+ std::vector<uint8_t>(public_key_der.begin(), public_key_der.end()))));
} else {
Respond(Error(error_message));
}
@@ -142,14 +142,15 @@ EnterprisePlatformKeysImportCertificateFunction::Run() {
if (!platform_keys::ValidateToken(params->token_id, &platform_keys_token_id))
return RespondNow(Error(platform_keys::kErrorInvalidToken));
- const std::vector<char>& cert_der = params->certificate;
+ const std::vector<uint8_t>& cert_der = params->certificate;
// Allow UTF-8 inside PrintableStrings in client certificates. See
// crbug.com/770323 and crbug.com/788655.
net::X509Certificate::UnsafeCreateOptions options;
options.printable_string_is_utf8 = true;
scoped_refptr<net::X509Certificate> cert_x509 =
net::X509Certificate::CreateFromBytesUnsafeOptions(
- cert_der.data(), cert_der.size(), options);
+ reinterpret_cast<const char*>(cert_der.data()), cert_der.size(),
+ options);
if (!cert_x509.get())
return RespondNow(Error(kEnterprisePlatformErrorInvalidX509Cert));
@@ -185,14 +186,15 @@ EnterprisePlatformKeysRemoveCertificateFunction::Run() {
if (!platform_keys::ValidateToken(params->token_id, &platform_keys_token_id))
return RespondNow(Error(platform_keys::kErrorInvalidToken));
- const std::vector<char>& cert_der = params->certificate;
+ const std::vector<uint8_t>& cert_der = params->certificate;
// Allow UTF-8 inside PrintableStrings in client certificates. See
// crbug.com/770323 and crbug.com/788655.
net::X509Certificate::UnsafeCreateOptions options;
options.printable_string_is_utf8 = true;
scoped_refptr<net::X509Certificate> cert_x509 =
net::X509Certificate::CreateFromBytesUnsafeOptions(
- cert_der.data(), cert_der.size(), options);
+ reinterpret_cast<const char*>(cert_der.data()), cert_der.size(),
+ options);
if (!cert_x509.get())
return RespondNow(Error(kEnterprisePlatformErrorInvalidX509Cert));
diff --git a/chromium/chrome/browser/extensions/api/enterprise_platform_keys/enterprise_platform_keys_api_unittest.cc b/chromium/chrome/browser/extensions/api/enterprise_platform_keys/enterprise_platform_keys_api_unittest.cc
index d6cdb2102e3..30be624ce38 100644
--- a/chromium/chrome/browser/extensions/api/enterprise_platform_keys/enterprise_platform_keys_api_unittest.cc
+++ b/chromium/chrome/browser/extensions/api/enterprise_platform_keys/enterprise_platform_keys_api_unittest.cc
@@ -13,6 +13,7 @@
#include "base/threading/thread_task_runner_handle.h"
#include "base/values.h"
#include "chrome/browser/chromeos/login/users/fake_chrome_user_manager.h"
+#include "chrome/browser/chromeos/settings/cros_settings.h"
#include "chrome/browser/chromeos/settings/scoped_cros_settings_test_helper.h"
#include "chrome/browser/chromeos/settings/stub_install_attributes.h"
#include "chrome/browser/extensions/extension_function_test_utils.h"
@@ -24,6 +25,7 @@
#include "chrome/test/base/testing_profile_manager.h"
#include "chromeos/attestation/mock_attestation_flow.h"
#include "chromeos/cryptohome/async_method_caller.h"
+#include "chromeos/cryptohome/cryptohome_parameters.h"
#include "chromeos/cryptohome/mock_async_method_caller.h"
#include "chromeos/dbus/attestation_constants.h"
#include "chromeos/dbus/dbus_method_call_status.h"
@@ -366,7 +368,7 @@ TEST_F(EPKChallengeMachineKeyTest, Success) {
ASSERT_TRUE(value->is_blob());
EXPECT_EQ("response",
- std::string(value->GetBlob().data(), value->GetBlob().size()));
+ std::string(value->GetBlob().begin(), value->GetBlob().end()));
}
TEST_F(EPKChallengeMachineKeyTest, KeyRegisteredSuccess) {
@@ -395,7 +397,7 @@ TEST_F(EPKChallengeMachineKeyTest, KeyRegisteredSuccess) {
ASSERT_TRUE(value->is_blob());
EXPECT_EQ("response",
- std::string(value->GetBlob().data(), value->GetBlob().size()));
+ std::string(value->GetBlob().begin(), value->GetBlob().end()));
}
TEST_F(EPKChallengeMachineKeyTest, AttestationNotPrepared) {
@@ -511,7 +513,8 @@ TEST_F(EPKChallengeUserKeyTest, KeyRegistrationFailed) {
TEST_F(EPKChallengeUserKeyTest, KeyExists) {
cryptohome_client_.SetTpmAttestationUserCertificate(
- cryptohome::Identification(AccountId::FromUserEmail(kUserEmail)),
+ cryptohome::CreateAccountIdentifierFromAccountId(
+ AccountId::FromUserEmail(kUserEmail)),
"attest-ent-user", std::string());
// GetCertificate must not be called if the key exists.
EXPECT_CALL(mock_attestation_flow_, GetCertificate(_, _, _, _, _)).Times(0);
@@ -563,7 +566,7 @@ TEST_F(EPKChallengeUserKeyTest, Success) {
ASSERT_TRUE(value->is_blob());
EXPECT_EQ("response",
- std::string(value->GetBlob().data(), value->GetBlob().size()));
+ std::string(value->GetBlob().begin(), value->GetBlob().end()));
}
TEST_F(EPKChallengeUserKeyTest, AttestationNotPrepared) {
diff --git a/chromium/chrome/browser/extensions/api/enterprise_platform_keys_private/enterprise_platform_keys_private_api.cc b/chromium/chrome/browser/extensions/api/enterprise_platform_keys_private/enterprise_platform_keys_private_api.cc
index 8435980e7af..ba1f6042883 100644
--- a/chromium/chrome/browser/extensions/api/enterprise_platform_keys_private/enterprise_platform_keys_private_api.cc
+++ b/chromium/chrome/browser/extensions/api/enterprise_platform_keys_private/enterprise_platform_keys_private_api.cc
@@ -224,7 +224,8 @@ void EPKPChallengeKeyBase::IsAttestationPreparedCallback(
}
// Attestation is available, see if the key we need already exists.
cryptohome_client_->TpmAttestationDoesKeyExist(
- context.key_type, cryptohome::Identification(context.account_id),
+ context.key_type,
+ cryptohome::CreateAccountIdentifierFromAccountId(context.account_id),
context.key_name,
base::BindOnce(&EPKPChallengeKeyBase::DoesKeyExistCallback,
base::Unretained(this), context));
diff --git a/chromium/chrome/browser/extensions/api/enterprise_platform_keys_private/enterprise_platform_keys_private_api_unittest.cc b/chromium/chrome/browser/extensions/api/enterprise_platform_keys_private/enterprise_platform_keys_private_api_unittest.cc
index fb7241aa4fa..62671ff64c8 100644
--- a/chromium/chrome/browser/extensions/api/enterprise_platform_keys_private/enterprise_platform_keys_private_api_unittest.cc
+++ b/chromium/chrome/browser/extensions/api/enterprise_platform_keys_private/enterprise_platform_keys_private_api_unittest.cc
@@ -14,6 +14,7 @@
#include "base/values.h"
#include "chrome/browser/chromeos/login/users/fake_chrome_user_manager.h"
#include "chrome/browser/chromeos/profiles/profile_helper.h"
+#include "chrome/browser/chromeos/settings/cros_settings.h"
#include "chrome/browser/chromeos/settings/scoped_cros_settings_test_helper.h"
#include "chrome/browser/chromeos/settings/stub_install_attributes.h"
#include "chrome/browser/extensions/extension_function_test_utils.h"
@@ -485,7 +486,8 @@ TEST_F(EPKPChallengeUserKeyTest, KeyRegistrationFailed) {
TEST_F(EPKPChallengeUserKeyTest, KeyExists) {
cryptohome_client_.SetTpmAttestationUserCertificate(
- cryptohome::Identification(AccountId::FromUserEmail(kUserEmail)),
+ cryptohome::CreateAccountIdentifierFromAccountId(
+ AccountId::FromUserEmail(kUserEmail)),
"attest-ent-user", std::string());
// GetCertificate must not be called if the key exists.
EXPECT_CALL(mock_attestation_flow_, GetCertificate(_, _, _, _, _))
diff --git a/chromium/chrome/browser/extensions/api/enterprise_reporting_private/chrome_desktop_report_request_helper.cc b/chromium/chrome/browser/extensions/api/enterprise_reporting_private/chrome_desktop_report_request_helper.cc
index a9177d0b6db..b31517c9a8c 100644
--- a/chromium/chrome/browser/extensions/api/enterprise_reporting_private/chrome_desktop_report_request_helper.cc
+++ b/chromium/chrome/browser/extensions/api/enterprise_reporting_private/chrome_desktop_report_request_helper.cc
@@ -12,6 +12,7 @@
#include "base/strings/utf_string_conversions.h"
#include "base/values.h"
#include "chrome/browser/browser_process.h"
+#include "chrome/browser/extensions/api/enterprise_reporting_private/prefs.h"
#include "chrome/browser/policy/chrome_browser_policy_connector.h"
#include "chrome/browser/policy/machine_level_user_cloud_policy_controller.h"
#include "chrome/browser/policy/policy_conversions.h"
@@ -77,42 +78,53 @@ int64_t GetMachineLevelUserCloudPolicyFetchTimestamp() {
void AppendAdditionalBrowserInformation(em::ChromeDesktopReportRequest* request,
Profile* profile) {
- // Set Chrome version number
- request->mutable_browser_report()->set_browser_version(
- version_info::GetVersionNumber());
- // Set Chrome channel
- request->mutable_browser_report()->set_channel(
- static_cast<em::BrowserReport_Channel>(chrome::GetChannel()));
- // Set Chrome executable path
- request->mutable_browser_report()->set_executable_path(GetChromePath());
+ const PrefService* prefs = profile->GetPrefs();
+
+ if (prefs->GetBoolean(enterprise_reporting::kReportVersionData)) {
+ // Set Chrome version number
+ request->mutable_browser_report()->set_browser_version(
+ version_info::GetVersionNumber());
+ // Set Chrome channel
+ request->mutable_browser_report()->set_channel(
+ policy::ConvertToProtoChannel(chrome::GetChannel()));
+ }
// Add a new profile report if extension doesn't report any profile.
if (request->browser_report().chrome_user_profile_reports_size() == 0)
request->mutable_browser_report()->add_chrome_user_profile_reports();
DCHECK_EQ(1, request->browser_report().chrome_user_profile_reports_size());
- // Set profile ID for the first profile.
- request->mutable_browser_report()
- ->mutable_chrome_user_profile_reports(0)
- ->set_id(GetProfileId(profile));
-
- // Set policy data of the first profile. Extension will report this data in
- // the future.
- request->mutable_browser_report()
- ->mutable_chrome_user_profile_reports(0)
- ->set_policy_data(policy::GetAllPolicyValuesAsJSON(profile, true, false));
-
- int64_t timestamp = GetMachineLevelUserCloudPolicyFetchTimestamp();
- if (timestamp > 0) {
+
+ if (prefs->GetBoolean(enterprise_reporting::kReportUserIDData)) {
+ // Set Chrome executable path
+ request->mutable_browser_report()->set_executable_path(GetChromePath());
+
+ // Set profile ID for the first profile.
+ request->mutable_browser_report()
+ ->mutable_chrome_user_profile_reports(0)
+ ->set_id(GetProfileId(profile));
+
+ // Set the profile name
request->mutable_browser_report()
->mutable_chrome_user_profile_reports(0)
- ->set_policy_fetched_timestamp(timestamp);
+ ->set_name(prefs->GetString(prefs::kProfileName));
}
- // Set the profile name
- request->mutable_browser_report()
- ->mutable_chrome_user_profile_reports(0)
- ->set_name(profile->GetPrefs()->GetString(prefs::kProfileName));
+ if (prefs->GetBoolean(enterprise_reporting::kReportPolicyData)) {
+ // Set policy data of the first profile. Extension will report this data in
+ // the future.
+ request->mutable_browser_report()
+ ->mutable_chrome_user_profile_reports(0)
+ ->set_policy_data(
+ policy::GetAllPolicyValuesAsJSON(profile, true, false));
+
+ int64_t timestamp = GetMachineLevelUserCloudPolicyFetchTimestamp();
+ if (timestamp > 0) {
+ request->mutable_browser_report()
+ ->mutable_chrome_user_profile_reports(0)
+ ->set_policy_fetched_timestamp(timestamp);
+ }
+ }
}
bool UpdateJSONEncodedStringEntry(const base::Value& dict_value,
@@ -135,37 +147,49 @@ bool UpdateJSONEncodedStringEntry(const base::Value& dict_value,
return true;
}
-void AppendPlatformInformation(em::ChromeDesktopReportRequest* request) {
- const char kComputerName[] = "computername";
- const char kUsername[] = "username";
-
- base::Value os_info = base::Value(base::Value::Type::DICTIONARY);
- os_info.SetKey(kOS, base::Value(policy::GetOSPlatform()));
- os_info.SetKey(kOSVersion, base::Value(policy::GetOSVersion()));
- os_info.SetKey(kOSArch, base::Value(policy::GetOSArchitecture()));
- base::JSONWriter::Write(os_info, request->mutable_os_info());
+void AppendPlatformInformation(em::ChromeDesktopReportRequest* request,
+ const PrefService* prefs) {
+ if (prefs->GetBoolean(enterprise_reporting::kReportVersionData)) {
+ base::Value os_info = base::Value(base::Value::Type::DICTIONARY);
+ os_info.SetKey(kOS, base::Value(policy::GetOSPlatform()));
+ os_info.SetKey(kOSVersion, base::Value(policy::GetOSVersion()));
+ os_info.SetKey(kOSArch, base::Value(policy::GetOSArchitecture()));
+ base::JSONWriter::Write(os_info, request->mutable_os_info());
+ }
- base::Value machine_name = base::Value(base::Value::Type::DICTIONARY);
- machine_name.SetKey(kComputerName, base::Value(policy::GetMachineName()));
- base::JSONWriter::Write(machine_name, request->mutable_machine_name());
+ if (prefs->GetBoolean(enterprise_reporting::kReportMachineIDData)) {
+ const char kComputerName[] = "computername";
+ base::Value machine_name = base::Value(base::Value::Type::DICTIONARY);
+ machine_name.SetKey(kComputerName, base::Value(policy::GetMachineName()));
+ base::JSONWriter::Write(machine_name, request->mutable_machine_name());
+ }
- base::Value os_user = base::Value(base::Value::Type::DICTIONARY);
- os_user.SetKey(kUsername, base::Value(policy::GetOSUsername()));
- base::JSONWriter::Write(os_user, request->mutable_os_user());
+ if (prefs->GetBoolean(enterprise_reporting::kReportUserIDData)) {
+ const char kUsername[] = "username";
+ base::Value os_user = base::Value(base::Value::Type::DICTIONARY);
+ os_user.SetKey(kUsername, base::Value(policy::GetOSUsername()));
+ base::JSONWriter::Write(os_user, request->mutable_os_user());
+ }
}
std::unique_ptr<em::ChromeUserProfileReport>
-GenerateChromeUserProfileReportRequest(const base::Value& profile_report) {
+GenerateChromeUserProfileReportRequest(const base::Value& profile_report,
+ const PrefService* prefs) {
if (!profile_report.is_dict())
return nullptr;
std::unique_ptr<em::ChromeUserProfileReport> request =
std::make_unique<em::ChromeUserProfileReport>();
- if (!UpdateJSONEncodedStringEntry(profile_report, kChromeSignInUser,
- request->mutable_chrome_signed_in_user(),
- DICTIONARY) ||
- !UpdateJSONEncodedStringEntry(profile_report, kExtensionData,
+ if (prefs->GetBoolean(enterprise_reporting::kReportUserIDData)) {
+ if (!UpdateJSONEncodedStringEntry(profile_report, kChromeSignInUser,
+ request->mutable_chrome_signed_in_user(),
+ DICTIONARY)) {
+ return nullptr;
+ }
+ }
+
+ if (!UpdateJSONEncodedStringEntry(profile_report, kExtensionData,
request->mutable_extension_data(), LIST) ||
!UpdateJSONEncodedStringEntry(profile_report, kPlugins,
request->mutable_plugins(), LIST)) {
@@ -197,7 +221,9 @@ GenerateChromeDesktopReportRequest(const base::DictionaryValue& report,
std::unique_ptr<em::ChromeDesktopReportRequest> request =
std::make_unique<em::ChromeDesktopReportRequest>();
- AppendPlatformInformation(request.get());
+ const PrefService* prefs = profile->GetPrefs();
+
+ AppendPlatformInformation(request.get(), prefs);
if (const base::Value* browser_report =
report.FindKeyOfType(kBrowserReport, base::Value::Type::DICTIONARY)) {
@@ -208,7 +234,7 @@ GenerateChromeDesktopReportRequest(const base::DictionaryValue& report,
// Currently, profile send their browser reports individually.
std::unique_ptr<em::ChromeUserProfileReport> profile_report_request =
GenerateChromeUserProfileReportRequest(
- profile_reports->GetList()[0]);
+ profile_reports->GetList()[0], prefs);
if (!profile_report_request)
return nullptr;
request->mutable_browser_report()
diff --git a/chromium/chrome/browser/extensions/api/enterprise_reporting_private/chrome_desktop_report_request_helper_unittest.cc b/chromium/chrome/browser/extensions/api/enterprise_reporting_private/chrome_desktop_report_request_helper_unittest.cc
index 97d58f1c3ac..2c669521c57 100644
--- a/chromium/chrome/browser/extensions/api/enterprise_reporting_private/chrome_desktop_report_request_helper_unittest.cc
+++ b/chromium/chrome/browser/extensions/api/enterprise_reporting_private/chrome_desktop_report_request_helper_unittest.cc
@@ -7,6 +7,7 @@
#include "base/json/json_reader.h"
#include "base/json/string_escape.h"
#include "base/values.h"
+#include "chrome/browser/extensions/api/enterprise_reporting_private/prefs.h"
#include "chrome/common/pref_names.h"
#include "chrome/test/base/testing_profile.h"
#include "components/policy/core/common/cloud/cloud_policy_util.h"
@@ -19,6 +20,20 @@ namespace em = enterprise_management;
namespace extensions {
+namespace {
+
+base::DictionaryValue CreateReport(base::Value profile_report) {
+ base::Value profile_reports(base::Value::Type::LIST);
+ profile_reports.GetList().push_back(std::move(profile_report));
+
+ base::DictionaryValue report;
+ report.SetPath({"browserReport", "chromeUserProfileReport"},
+ std::move(profile_reports));
+ return report;
+}
+
+} // namespace
+
class ChromeDesktopReportRequestGeneratorTest : public ::testing::Test {
protected:
content::TestBrowserThreadBundle test_browser_thread_bundle_;
@@ -183,4 +198,67 @@ TEST_F(ChromeDesktopReportRequestGeneratorTest, SafeBrowsing) {
.safe_browsing_warnings_click_through());
}
+TEST_F(ChromeDesktopReportRequestGeneratorTest, DontReportVersionData) {
+ PrefService* prefs = profile_.GetPrefs();
+ prefs->SetBoolean(enterprise_reporting::kReportVersionData, false);
+
+ std::unique_ptr<em::ChromeDesktopReportRequest> request;
+
+ request =
+ GenerateChromeDesktopReportRequest(base::DictionaryValue(), &profile_);
+
+ ASSERT_TRUE(request);
+ EXPECT_FALSE(request->has_os_info());
+ EXPECT_FALSE(request->browser_report().has_browser_version());
+ EXPECT_FALSE(request->browser_report().has_channel());
+}
+
+TEST_F(ChromeDesktopReportRequestGeneratorTest, DontReportPolicyData) {
+ PrefService* prefs = profile_.GetPrefs();
+ prefs->SetBoolean(enterprise_reporting::kReportPolicyData, false);
+
+ std::unique_ptr<em::ChromeDesktopReportRequest> request =
+ GenerateChromeDesktopReportRequest(base::DictionaryValue(), &profile_);
+
+ ASSERT_TRUE(request);
+ const em::ChromeUserProfileReport& profile =
+ request->browser_report().chrome_user_profile_reports(0);
+ EXPECT_FALSE(profile.has_policy_data());
+ EXPECT_FALSE(profile.has_policy_fetched_timestamp());
+}
+
+TEST_F(ChromeDesktopReportRequestGeneratorTest, DontReportMachineIDData) {
+ PrefService* prefs = profile_.GetPrefs();
+ prefs->SetBoolean(enterprise_reporting::kReportMachineIDData, false);
+
+ std::unique_ptr<em::ChromeDesktopReportRequest> request =
+ GenerateChromeDesktopReportRequest(base::DictionaryValue(), &profile_);
+
+ ASSERT_TRUE(request);
+ EXPECT_FALSE(request->has_machine_name());
+}
+
+TEST_F(ChromeDesktopReportRequestGeneratorTest, DontReportUserIDData) {
+ PrefService* prefs = profile_.GetPrefs();
+ prefs->SetBoolean(enterprise_reporting::kReportUserIDData, false);
+
+ base::Value profile_report(base::Value::Type::DICTIONARY);
+ profile_report.SetPath({"chromeSignInUser", "email"},
+ base::Value("john_doe@gmail.com"));
+ profile_report.SetPath({"chromeSignInUser", "id"}, base::Value("123456789"));
+
+ std::unique_ptr<em::ChromeDesktopReportRequest> request =
+ GenerateChromeDesktopReportRequest(
+ CreateReport(std::move(profile_report)), &profile_);
+
+ ASSERT_TRUE(request);
+ EXPECT_FALSE(request->has_os_user());
+ EXPECT_FALSE(request->browser_report().has_executable_path());
+ const em::ChromeUserProfileReport& profile =
+ request->browser_report().chrome_user_profile_reports(0);
+ EXPECT_FALSE(profile.has_id());
+ EXPECT_FALSE(profile.has_name());
+ EXPECT_FALSE(profile.has_chrome_signed_in_user());
+}
+
} // namespace extensions
diff --git a/chromium/chrome/browser/extensions/api/enterprise_reporting_private/enterprise_reporting_policy_migrator.cc b/chromium/chrome/browser/extensions/api/enterprise_reporting_private/enterprise_reporting_policy_migrator.cc
new file mode 100644
index 00000000000..50cf0293da0
--- /dev/null
+++ b/chromium/chrome/browser/extensions/api/enterprise_reporting_private/enterprise_reporting_policy_migrator.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 "chrome/browser/extensions/api/enterprise_reporting_private/enterprise_reporting_policy_migrator.h"
+
+#include "components/policy/policy_constants.h"
+
+namespace extensions {
+namespace enterprise_reporting {
+
+namespace {
+
+// Extension ID for the Chrome Reporting Extension.
+// https://chrome.google.com/webstore/detail/chrome-reporting-extensio/emahakmocgideepebncgnmlmliepgpgb
+const char kStableExtensionId[] = "emahakmocgideepebncgnmlmliepgpgb";
+
+// Beta extension ID.
+const char kBetaExtensionId[] = "kigjhoekjcpdfjpimbdjegmgecmlicaf";
+
+const policy::ExtensionPolicyMigrator::Migration kMigrations[] = {
+ {"report_version_data", policy::key::kReportVersionData},
+ {"report_policy_data", policy::key::kReportPolicyData},
+ {"report_machine_id_data", policy::key::kReportMachineIDData},
+ {"report_user_id_data", policy::key::kReportUserIDData},
+};
+
+} // namespace
+
+EnterpriseReportingPolicyMigrator::EnterpriseReportingPolicyMigrator() {}
+
+EnterpriseReportingPolicyMigrator::~EnterpriseReportingPolicyMigrator() {}
+
+void EnterpriseReportingPolicyMigrator::Migrate(policy::PolicyBundle* bundle) {
+ CopyPoliciesIfUnset(bundle, kStableExtensionId, kMigrations);
+ CopyPoliciesIfUnset(bundle, kBetaExtensionId, kMigrations);
+}
+
+} // namespace enterprise_reporting
+} // namespace extensions
diff --git a/chromium/chrome/browser/extensions/api/enterprise_reporting_private/enterprise_reporting_policy_migrator.h b/chromium/chrome/browser/extensions/api/enterprise_reporting_private/enterprise_reporting_policy_migrator.h
new file mode 100644
index 00000000000..f08a41a3944
--- /dev/null
+++ b/chromium/chrome/browser/extensions/api/enterprise_reporting_private/enterprise_reporting_policy_migrator.h
@@ -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.
+
+#ifndef CHROME_BROWSER_EXTENSIONS_API_ENTERPRISE_REPORTING_PRIVATE_ENTERPRISE_REPORTING_POLICY_MIGRATOR_H_
+#define CHROME_BROWSER_EXTENSIONS_API_ENTERPRISE_REPORTING_PRIVATE_ENTERPRISE_REPORTING_POLICY_MIGRATOR_H_
+
+#include "components/policy/core/common/extension_policy_migrator.h"
+
+namespace extensions {
+namespace enterprise_reporting {
+
+class EnterpriseReportingPolicyMigrator
+ : public policy::ExtensionPolicyMigrator {
+ public:
+ EnterpriseReportingPolicyMigrator();
+ ~EnterpriseReportingPolicyMigrator() override;
+
+ void Migrate(policy::PolicyBundle* bundle) override;
+};
+
+} // namespace enterprise_reporting
+} // namespace extensions
+
+#endif // CHROME_BROWSER_EXTENSIONS_API_ENTERPRISE_REPORTING_PRIVATE_ENTERPRISE_REPORTING_POLICY_MIGRATOR_H_
diff --git a/chromium/chrome/browser/extensions/api/enterprise_reporting_private/enterprise_reporting_policy_migrator_unittest.cc b/chromium/chrome/browser/extensions/api/enterprise_reporting_private/enterprise_reporting_policy_migrator_unittest.cc
new file mode 100644
index 00000000000..2b40d89276d
--- /dev/null
+++ b/chromium/chrome/browser/extensions/api/enterprise_reporting_private/enterprise_reporting_policy_migrator_unittest.cc
@@ -0,0 +1,72 @@
+// 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/extensions/api/enterprise_reporting_private/enterprise_reporting_policy_migrator.h"
+
+#include "base/bind.h"
+#include "base/callback.h"
+#include "base/strings/utf_string_conversions.h"
+#include "base/values.h"
+#include "components/policy/policy_constants.h"
+#include "testing/gtest/include/gtest/gtest.h"
+
+namespace extensions {
+namespace enterprise_reporting {
+
+namespace {
+
+const char kStableExtensionId[] = "emahakmocgideepebncgnmlmliepgpgb";
+const char kBetaExtensionId[] = "kigjhoekjcpdfjpimbdjegmgecmlicaf";
+
+const policy::ExtensionPolicyMigrator::Migration kMigrations[] = {
+ {"report_version_data", policy::key::kReportVersionData},
+ {"report_policy_data", policy::key::kReportPolicyData},
+ {"report_machine_id_data", policy::key::kReportMachineIDData},
+ {"report_user_id_data", policy::key::kReportUserIDData},
+};
+
+void SetPolicy(policy::PolicyMap* policy,
+ const char* policy_name,
+ std::unique_ptr<base::Value> value) {
+ policy->Set(policy_name, policy::POLICY_LEVEL_MANDATORY,
+ policy::POLICY_SCOPE_USER, policy::POLICY_SOURCE_CLOUD,
+ std::move(value), nullptr);
+}
+
+} // namespace
+
+TEST(EnterpriseReportingPolicyMigratorTest, Migrate) {
+ policy::PolicyBundle bundle;
+
+ policy::PolicyMap& stable_extension_map = bundle.Get(policy::PolicyNamespace(
+ policy::POLICY_DOMAIN_EXTENSIONS, kStableExtensionId));
+ SetPolicy(&stable_extension_map, kMigrations[0].old_name,
+ std::make_unique<base::Value>(false));
+ SetPolicy(&stable_extension_map, kMigrations[1].old_name,
+ std::make_unique<base::Value>(false));
+ SetPolicy(&stable_extension_map, kMigrations[2].old_name,
+ std::make_unique<base::Value>(false));
+
+ policy::PolicyMap& beta_extension_map = bundle.Get(policy::PolicyNamespace(
+ policy::POLICY_DOMAIN_EXTENSIONS, kBetaExtensionId));
+ SetPolicy(&beta_extension_map, kMigrations[2].old_name,
+ std::make_unique<base::Value>(true));
+ SetPolicy(&beta_extension_map, kMigrations[3].old_name,
+ std::make_unique<base::Value>(true));
+
+ EnterpriseReportingPolicyMigrator().Migrate(&bundle);
+
+ policy::PolicyMap& chrome_map = bundle.Get(policy::PolicyNamespace(
+ policy::POLICY_DOMAIN_CHROME, /* component_id */ std::string()));
+
+ EXPECT_EQ(4u, chrome_map.size());
+ EXPECT_EQ(base::Value(false), *chrome_map.GetValue(kMigrations[0].new_name));
+ EXPECT_EQ(base::Value(false), *chrome_map.GetValue(kMigrations[1].new_name));
+ // Stable takes priority over Beta, when the policy is set.
+ EXPECT_EQ(base::Value(false), *chrome_map.GetValue(kMigrations[2].new_name));
+ EXPECT_EQ(base::Value(true), *chrome_map.GetValue(kMigrations[3].new_name));
+}
+
+} // namespace enterprise_reporting
+} // namespace extensions
diff --git a/chromium/chrome/browser/extensions/api/enterprise_reporting_private/enterprise_reporting_private_api.cc b/chromium/chrome/browser/extensions/api/enterprise_reporting_private/enterprise_reporting_private_api.cc
index 4d3ed0a610f..b7ac4535e8d 100644
--- a/chromium/chrome/browser/extensions/api/enterprise_reporting_private/enterprise_reporting_private_api.cc
+++ b/chromium/chrome/browser/extensions/api/enterprise_reporting_private/enterprise_reporting_private_api.cc
@@ -19,7 +19,6 @@
#include "components/policy/core/common/cloud/cloud_policy_client.h"
#include "components/policy/core/common/cloud/device_management_service.h"
#include "components/policy/proto/device_management_backend.pb.h"
-#include "net/url_request/url_request_context_getter.h"
#include "services/network/public/cpp/shared_url_loader_factory.h"
namespace em = enterprise_management;
@@ -60,7 +59,7 @@ EnterpriseReportingPrivateUploadChromeDesktopReportFunction::
cloud_policy_client_ = std::make_unique<policy::CloudPolicyClient>(
std::string() /* machine_id */, std::string() /* machine_model */,
std::string() /* brand_code */, device_management_service,
- g_browser_process->system_request_context(), url_loader_factory, nullptr,
+ std::move(url_loader_factory), nullptr,
policy::CloudPolicyClient::DeviceDMTokenCallback());
dm_token_ = policy::BrowserDMTokenStorage::Get()->RetrieveDMToken();
client_id_ = policy::BrowserDMTokenStorage::Get()->RetrieveClientId();
diff --git a/chromium/chrome/browser/extensions/api/enterprise_reporting_private/enterprise_reporting_private_unittest.cc b/chromium/chrome/browser/extensions/api/enterprise_reporting_private/enterprise_reporting_private_unittest.cc
index 6cd8da022ff..58dfc380424 100644
--- a/chromium/chrome/browser/extensions/api/enterprise_reporting_private/enterprise_reporting_private_unittest.cc
+++ b/chromium/chrome/browser/extensions/api/enterprise_reporting_private/enterprise_reporting_private_unittest.cc
@@ -27,7 +27,9 @@ const char kFakeMachineNameReport[] = "{\"computername\":\"name\"}";
class MockCloudPolicyClient : public policy::MockCloudPolicyClient {
public:
- MockCloudPolicyClient() = default;
+ explicit MockCloudPolicyClient(
+ scoped_refptr<network::SharedURLLoaderFactory> url_loader_factory)
+ : policy::MockCloudPolicyClient(std::move(url_loader_factory)) {}
void UploadChromeDesktopReport(
std::unique_ptr<enterprise_management::ChromeDesktopReportRequest>
@@ -69,8 +71,8 @@ class EnterpriseReportingPrivateTest : public ExtensionApiUnittest {
EnterpriseReportingPrivateUploadChromeDesktopReportFunction* function =
EnterpriseReportingPrivateUploadChromeDesktopReportFunction::
CreateForTesting(test_shared_loader_factory_);
- std::unique_ptr<MockCloudPolicyClient> client =
- std::make_unique<MockCloudPolicyClient>();
+ auto client =
+ std::make_unique<MockCloudPolicyClient>(test_shared_loader_factory_);
client_ = client.get();
function->SetCloudPolicyClientForTesting(std::move(client));
function->SetRegistrationInfoForTesting(dm_token, kFakeClientId);
diff --git a/chromium/chrome/browser/extensions/api/enterprise_reporting_private/prefs.cc b/chromium/chrome/browser/extensions/api/enterprise_reporting_private/prefs.cc
new file mode 100644
index 00000000000..09239d5b5d5
--- /dev/null
+++ b/chromium/chrome/browser/extensions/api/enterprise_reporting_private/prefs.cc
@@ -0,0 +1,29 @@
+// 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/extensions/api/enterprise_reporting_private/prefs.h"
+
+#include "components/pref_registry/pref_registry_syncable.h"
+
+namespace extensions {
+namespace enterprise_reporting {
+
+const char kReportVersionData[] = "enterprise_reporting.report_version_data";
+
+const char kReportPolicyData[] = "enterprise_reporting.report_policy_data";
+
+const char kReportMachineIDData[] =
+ "enterprise_reporting.report_machine_id_data";
+
+const char kReportUserIDData[] = "enterprise_reporting.report_user_id_data";
+
+void RegisterProfilePrefs(user_prefs::PrefRegistrySyncable* registry) {
+ registry->RegisterBooleanPref(kReportVersionData, true);
+ registry->RegisterBooleanPref(kReportPolicyData, true);
+ registry->RegisterBooleanPref(kReportMachineIDData, true);
+ registry->RegisterBooleanPref(kReportUserIDData, true);
+}
+
+} // namespace enterprise_reporting
+} // namespace extensions
diff --git a/chromium/chrome/browser/extensions/api/enterprise_reporting_private/prefs.h b/chromium/chrome/browser/extensions/api/enterprise_reporting_private/prefs.h
new file mode 100644
index 00000000000..8471671b8a4
--- /dev/null
+++ b/chromium/chrome/browser/extensions/api/enterprise_reporting_private/prefs.h
@@ -0,0 +1,32 @@
+// 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_EXTENSIONS_API_ENTERPRISE_REPORTING_PRIVATE_PREFS_H_
+#define CHROME_BROWSER_EXTENSIONS_API_ENTERPRISE_REPORTING_PRIVATE_PREFS_H_
+
+namespace user_prefs {
+class PrefRegistrySyncable;
+} // namespace user_prefs
+
+namespace extensions {
+namespace enterprise_reporting {
+
+// Controls reporting of OS/Chrome version information.
+extern const char kReportVersionData[];
+
+// Controls reporting of Chrome policy data and policy fetch timestamps.
+extern const char kReportPolicyData[];
+
+// Controls reporting of information that can identify machines.
+extern const char kReportMachineIDData[];
+
+// Controls reporting of information that can identify users.
+extern const char kReportUserIDData[];
+
+void RegisterProfilePrefs(user_prefs::PrefRegistrySyncable* registry);
+
+} // namespace enterprise_reporting
+} // namespace extensions
+
+#endif // CHROME_BROWSER_EXTENSIONS_API_ENTERPRISE_REPORTING_PRIVATE_PREFS_H_
diff --git a/chromium/chrome/browser/extensions/api/extension_action/browser_action_apitest.cc b/chromium/chrome/browser/extensions/api/extension_action/browser_action_apitest.cc
index d7bd3505ef5..cac23b180ec 100644
--- a/chromium/chrome/browser/extensions/api/extension_action/browser_action_apitest.cc
+++ b/chromium/chrome/browser/extensions/api/extension_action/browser_action_apitest.cc
@@ -9,6 +9,8 @@
#include "base/files/scoped_temp_dir.h"
#include "base/macros.h"
#include "base/run_loop.h"
+#include "base/strings/stringprintf.h"
+#include "base/test/metrics/histogram_tester.h"
#include "base/threading/thread_restrictions.h"
#include "build/build_config.h"
#include "chrome/browser/download/download_prefs.h"
@@ -34,6 +36,7 @@
#include "components/prefs/pref_service.h"
#include "content/public/browser/browser_context.h"
#include "content/public/browser/notification_service.h"
+#include "content/public/browser/picture_in_picture_window_controller.h"
#include "content/public/browser/render_frame_host.h"
#include "content/public/browser/web_contents.h"
#include "content/public/test/browser_test_utils.h"
@@ -368,6 +371,60 @@ IN_PROC_BROWSER_TEST_F(BrowserActionApiTest, DynamicBrowserAction) {
EXPECT_EQ(kEmptyPathError, catcher.message());
}
+IN_PROC_BROWSER_TEST_F(BrowserActionApiTest, InvisibleIconBrowserAction) {
+ // Turn this on so errors are reported.
+ ExtensionActionSetIconFunction::SetReportErrorForInvisibleIconForTesting(
+ true);
+ ASSERT_TRUE(RunExtensionTest("browser_action/invisible_icon")) << message_;
+ const Extension* extension = GetSingleLoadedExtension();
+ ASSERT_TRUE(extension) << message_;
+
+ // Test there is a browser action in the toolbar.
+ ASSERT_EQ(1, GetBrowserActionsBar()->NumberOfBrowserActions());
+ EXPECT_TRUE(GetBrowserActionsBar()->HasIcon(0));
+ gfx::Image initial_bar_icon = GetBrowserActionsBar()->GetIcon(0);
+
+ ExtensionHost* background_page =
+ ProcessManager::Get(profile())->GetBackgroundHostForExtension(
+ extension->id());
+ ASSERT_TRUE(background_page);
+
+ static constexpr char kScript[] =
+ "setIcon(%s).then(function(arg) {"
+ " domAutomationController.send(arg);"
+ "});";
+
+ const std::string histogram_name =
+ "Extensions.DynamicExtensionActionIconWasVisible";
+ {
+ base::HistogramTester histogram_tester;
+ std::string result;
+ EXPECT_TRUE(ExecuteScriptAndExtractString(
+ background_page->host_contents(),
+ base::StringPrintf(kScript, "invisible"), &result));
+ EXPECT_EQ("Icon not sufficiently visible.", result);
+ // The icon should not have changed.
+ EXPECT_TRUE(gfx::test::AreImagesEqual(initial_bar_icon,
+ GetBrowserActionsBar()->GetIcon(0)));
+ EXPECT_THAT(histogram_tester.GetAllSamples(histogram_name),
+ testing::ElementsAre(base::Bucket(0, 1)));
+ }
+
+ {
+ base::HistogramTester histogram_tester;
+ std::string result;
+ EXPECT_TRUE(ExecuteScriptAndExtractString(
+ background_page->host_contents(),
+ base::StringPrintf(kScript, "visible"), &result));
+ EXPECT_EQ("", result);
+ // The icon should have changed.
+ EXPECT_FALSE(gfx::test::AreImagesEqual(initial_bar_icon,
+ GetBrowserActionsBar()->GetIcon(0)));
+ EXPECT_THAT(histogram_tester.GetAllSamples(histogram_name),
+ testing::ElementsAre(base::Bucket(1, 1)));
+ }
+}
+
IN_PROC_BROWSER_TEST_F(BrowserActionApiTest, TabSpecificBrowserActionState) {
ASSERT_TRUE(RunExtensionTest("browser_action/tab_specific_state")) <<
message_;
@@ -1059,5 +1116,48 @@ IN_PROC_BROWSER_TEST_F(NavigatingExtensionPopupBrowserTest, DownloadViaPost) {
#endif
}
+// Verify video can enter and exit Picture-in_Picture when browser action icon
+// is clicked.
+IN_PROC_BROWSER_TEST_F(BrowserActionApiTest,
+ TestPictureInPictureOnBrowserActionIconClick) {
+ ASSERT_TRUE(StartEmbeddedTestServer());
+
+ ASSERT_TRUE(
+ RunExtensionTest("trigger_actions/browser_action_picture_in_picture"))
+ << message_;
+ const Extension* extension = GetSingleLoadedExtension();
+ ASSERT_TRUE(extension) << message_;
+
+ // Test that there is a browser action in the toolbar.
+ ASSERT_EQ(1, GetBrowserActionsBar()->NumberOfBrowserActions());
+
+ ExtensionAction* browser_action = GetBrowserAction(*extension);
+ EXPECT_TRUE(browser_action);
+
+ // Find the background page.
+ ProcessManager* process_manager =
+ extensions::ProcessManager::Get(browser()->profile());
+ content::WebContents* web_contents =
+ process_manager->GetBackgroundHostForExtension(extension->id())
+ ->web_contents();
+ ASSERT_TRUE(web_contents);
+ content::PictureInPictureWindowController* window_controller =
+ content::PictureInPictureWindowController::GetOrCreateForWebContents(
+ web_contents);
+ ASSERT_TRUE(window_controller->GetWindowForTesting());
+ EXPECT_FALSE(window_controller->GetWindowForTesting()->IsVisible());
+
+ // Click on the browser action icon to enter Picture-in-Picture.
+ ResultCatcher catcher;
+ GetBrowserActionsBar()->Press(0);
+ EXPECT_TRUE(catcher.GetNextResult());
+ EXPECT_TRUE(window_controller->GetWindowForTesting()->IsVisible());
+
+ // Click on the browser action icon to exit Picture-in-Picture.
+ GetBrowserActionsBar()->Press(0);
+ EXPECT_TRUE(catcher.GetNextResult());
+ EXPECT_FALSE(window_controller->GetWindowForTesting()->IsVisible());
+}
+
} // namespace
} // namespace extensions
diff --git a/chromium/chrome/browser/extensions/api/extension_action/extension_action_api.cc b/chromium/chrome/browser/extensions/api/extension_action/extension_action_api.cc
index 9e4a41060ab..a12b3d54afa 100644
--- a/chromium/chrome/browser/extensions/api/extension_action/extension_action_api.cc
+++ b/chromium/chrome/browser/extensions/api/extension_action/extension_action_api.cc
@@ -11,6 +11,7 @@
#include "base/lazy_instance.h"
#include "base/location.h"
#include "base/macros.h"
+#include "base/metrics/histogram_macros.h"
#include "base/single_thread_task_runner.h"
#include "base/strings/string_number_conversions.h"
#include "base/threading/thread_task_runner_handle.h"
@@ -59,6 +60,8 @@ const char kOpenPopupError[] =
const char kInvalidColorError[] =
"The color specification could not be parsed.";
+bool g_report_error_for_invisible_icon = false;
+
} // namespace
//
@@ -421,6 +424,12 @@ ExtensionActionHideFunction::RunExtensionAction() {
return RespondNow(NoArguments());
}
+// static
+void ExtensionActionSetIconFunction::SetReportErrorForInvisibleIconForTesting(
+ bool value) {
+ g_report_error_for_invisible_icon = value;
+}
+
ExtensionFunction::ResponseAction
ExtensionActionSetIconFunction::RunExtensionAction() {
EXTENSION_FUNCTION_VALIDATE(details_);
@@ -438,7 +447,17 @@ ExtensionActionSetIconFunction::RunExtensionAction() {
if (icon.isNull())
return RespondNow(Error("Icon invalid."));
- extension_action_->SetIcon(tab_id_, gfx::Image(icon));
+ gfx::Image icon_image(icon);
+
+ const bool is_visible =
+ image_util::IsIconSufficientlyVisible(icon_image.AsBitmap());
+ UMA_HISTOGRAM_BOOLEAN("Extensions.DynamicExtensionActionIconWasVisible",
+ is_visible);
+
+ if (!is_visible && g_report_error_for_invisible_icon)
+ return RespondNow(Error("Icon not sufficiently visible."));
+
+ extension_action_->SetIcon(tab_id_, icon_image);
} else if (details_->GetInteger("iconIndex", &icon_index)) {
// Obsolete argument: ignore it.
return RespondNow(NoArguments());
diff --git a/chromium/chrome/browser/extensions/api/extension_action/extension_action_api.h b/chromium/chrome/browser/extensions/api/extension_action/extension_action_api.h
index 051518beed5..a9c08ccb71e 100644
--- a/chromium/chrome/browser/extensions/api/extension_action/extension_action_api.h
+++ b/chromium/chrome/browser/extensions/api/extension_action/extension_action_api.h
@@ -128,7 +128,7 @@ class ExtensionActionAPI : public BrowserContextKeyedAPI {
static const char* service_name() { return "ExtensionActionAPI"; }
static const bool kServiceRedirectedInIncognito = true;
- base::ObserverList<Observer> observers_;
+ base::ObserverList<Observer>::Unchecked observers_;
content::BrowserContext* browser_context_;
@@ -197,6 +197,9 @@ class ExtensionActionHideFunction : public ExtensionActionFunction {
// setIcon
class ExtensionActionSetIconFunction : public ExtensionActionFunction {
+ public:
+ static void SetReportErrorForInvisibleIconForTesting(bool value);
+
protected:
~ExtensionActionSetIconFunction() override {}
ResponseAction RunExtensionAction() override;
diff --git a/chromium/chrome/browser/extensions/api/extension_action/extension_action_apitest.cc b/chromium/chrome/browser/extensions/api/extension_action/extension_action_apitest.cc
index f12831ad5e7..c4229c5e970 100644
--- a/chromium/chrome/browser/extensions/api/extension_action/extension_action_apitest.cc
+++ b/chromium/chrome/browser/extensions/api/extension_action/extension_action_apitest.cc
@@ -6,9 +6,9 @@
#include <string>
#include "base/macros.h"
-#include "base/run_loop.h"
#include "base/scoped_observer.h"
#include "base/strings/stringprintf.h"
+#include "chrome/browser/extensions/api/extension_action/test_extension_action_api_observer.h"
#include "chrome/browser/extensions/extension_action.h"
#include "chrome/browser/extensions/extension_action_manager.h"
#include "chrome/browser/extensions/extension_apitest.h"
@@ -57,42 +57,6 @@ class TestStateStoreObserver : public StateStore::TestObserver {
DISALLOW_COPY_AND_ASSIGN(TestStateStoreObserver);
};
-// A helper class to observe ExtensionActionAPI changes.
-class TestExtensionActionAPIObserver : public ExtensionActionAPI::Observer {
- public:
- TestExtensionActionAPIObserver(content::BrowserContext* context,
- const std::string& extension_id)
- : extension_id_(extension_id), scoped_observer_(this) {
- scoped_observer_.Add(ExtensionActionAPI::Get(context));
- }
- ~TestExtensionActionAPIObserver() override {}
-
- void OnExtensionActionUpdated(
- ExtensionAction* extension_action,
- content::WebContents* web_contents,
- content::BrowserContext* browser_context) override {
- if (extension_action->extension_id() == extension_id_) {
- last_web_contents_ = web_contents;
- run_loop_.QuitWhenIdle();
- }
- }
-
- const content::WebContents* last_web_contents() const {
- return last_web_contents_;
- }
-
- void Wait() { run_loop_.Run(); }
-
- private:
- content::WebContents* last_web_contents_ = nullptr;
- std::string extension_id_;
- base::RunLoop run_loop_;
- ScopedObserver<ExtensionActionAPI, ExtensionActionAPI::Observer>
- scoped_observer_;
-
- DISALLOW_COPY_AND_ASSIGN(TestExtensionActionAPIObserver);
-};
-
} // namespace
using ExtensionActionAPITest = ExtensionApiTest;
diff --git a/chromium/chrome/browser/extensions/api/extension_action/test_extension_action_api_observer.cc b/chromium/chrome/browser/extensions/api/extension_action/test_extension_action_api_observer.cc
new file mode 100644
index 00000000000..2083a406aa9
--- /dev/null
+++ b/chromium/chrome/browser/extensions/api/extension_action/test_extension_action_api_observer.cc
@@ -0,0 +1,32 @@
+// 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/extensions/api/extension_action/test_extension_action_api_observer.h"
+
+namespace extensions {
+
+TestExtensionActionAPIObserver::TestExtensionActionAPIObserver(
+ content::BrowserContext* context,
+ const ExtensionId& extension_id)
+ : extension_id_(extension_id), scoped_observer_(this) {
+ scoped_observer_.Add(ExtensionActionAPI::Get(context));
+}
+
+TestExtensionActionAPIObserver::~TestExtensionActionAPIObserver() = default;
+
+void TestExtensionActionAPIObserver::Wait() {
+ run_loop_.Run();
+}
+
+void TestExtensionActionAPIObserver::OnExtensionActionUpdated(
+ ExtensionAction* extension_action,
+ content::WebContents* web_contents,
+ content::BrowserContext* browser_context) {
+ if (extension_action->extension_id() == extension_id_) {
+ last_web_contents_ = web_contents;
+ run_loop_.QuitWhenIdle();
+ }
+}
+
+} // namespace extensions
diff --git a/chromium/chrome/browser/extensions/api/extension_action/test_extension_action_api_observer.h b/chromium/chrome/browser/extensions/api/extension_action/test_extension_action_api_observer.h
new file mode 100644
index 00000000000..11b35f5b279
--- /dev/null
+++ b/chromium/chrome/browser/extensions/api/extension_action/test_extension_action_api_observer.h
@@ -0,0 +1,55 @@
+// Copyright 2018 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#ifndef CHROME_BROWSER_EXTENSIONS_API_EXTENSION_ACTION_TEST_EXTENSION_ACTION_API_OBSERVER_H_
+#define CHROME_BROWSER_EXTENSIONS_API_EXTENSION_ACTION_TEST_EXTENSION_ACTION_API_OBSERVER_H_
+
+#include "base/macros.h"
+#include "base/run_loop.h"
+#include "base/scoped_observer.h"
+#include "chrome/browser/extensions/api/extension_action/extension_action_api.h"
+#include "extensions/common/extension_id.h"
+
+namespace content {
+class BrowserContext;
+class WebContents;
+} // namespace content
+
+namespace extensions {
+
+// A helper class to observe ExtensionActionAPI changes.
+class TestExtensionActionAPIObserver : public ExtensionActionAPI::Observer {
+ public:
+ TestExtensionActionAPIObserver(content::BrowserContext* context,
+ const ExtensionId& extension_id);
+ ~TestExtensionActionAPIObserver() override;
+
+ // Waits till the extension action is updated.
+ void Wait();
+
+ // Returns the web contents for which the extension action was updated. Must
+ // be called after calling Wait().
+ const content::WebContents* last_web_contents() const {
+ return last_web_contents_;
+ }
+
+ private:
+ // ExtensionActionAPI::Observer override:
+ void OnExtensionActionUpdated(
+ ExtensionAction* extension_action,
+ content::WebContents* web_contents,
+ content::BrowserContext* browser_context) override;
+
+ content::WebContents* last_web_contents_ = nullptr;
+ ExtensionId extension_id_;
+ base::RunLoop run_loop_;
+ ScopedObserver<ExtensionActionAPI, ExtensionActionAPI::Observer>
+ scoped_observer_;
+
+ DISALLOW_COPY_AND_ASSIGN(TestExtensionActionAPIObserver);
+};
+
+} // namespace extensions
+
+#endif // CHROME_BROWSER_EXTENSIONS_API_EXTENSION_ACTION_TEST_EXTENSION_ACTION_API_OBSERVER_H_
diff --git a/chromium/chrome/browser/extensions/api/file_system/DEPS b/chromium/chrome/browser/extensions/api/file_system/DEPS
index b9a9cec2c20..9bf73e30601 100644
--- a/chromium/chrome/browser/extensions/api/file_system/DEPS
+++ b/chromium/chrome/browser/extensions/api/file_system/DEPS
@@ -1,9 +1,3 @@
include_rules = [
"+chrome/browser/ui/views/extensions",
]
-
-specific_include_rules = {
- "file_system_apitest_chromeos\.cc": [
- "+components/drive"
- ],
-}
diff --git a/chromium/chrome/browser/extensions/api/identity/gaia_web_auth_flow.cc b/chromium/chrome/browser/extensions/api/identity/gaia_web_auth_flow.cc
index 1657c78bb85..3c640ff82b5 100644
--- a/chromium/chrome/browser/extensions/api/identity/gaia_web_auth_flow.cc
+++ b/chromium/chrome/browser/extensions/api/identity/gaia_web_auth_flow.cc
@@ -11,7 +11,7 @@
#include "base/strings/stringprintf.h"
#include "base/trace_event/trace_event.h"
#include "chrome/browser/profiles/profile.h"
-#include "chrome/browser/signin/chrome_signin_client_factory.h"
+#include "chrome/browser/signin/chrome_device_id_helper.h"
#include "chrome/browser/signin/profile_oauth2_token_service_factory.h"
#include "chrome/browser/signin/signin_manager_factory.h"
#include "components/signin/core/browser/profile_oauth2_token_service.h"
@@ -58,11 +58,8 @@ GaiaWebAuthFlow::GaiaWebAuthFlow(Delegate* delegate,
std::reverse(client_id_parts.begin(), client_id_parts.end());
redirect_scheme_ = base::JoinString(client_id_parts, ".");
std::string signin_scoped_device_id;
- // profile_ can be nullptr in unittests.
- SigninClient* signin_client =
- profile_ ? ChromeSigninClientFactory::GetForProfile(profile_) : nullptr;
- if (signin_client)
- signin_scoped_device_id = signin_client->GetSigninScopedDeviceId();
+ if (profile_)
+ signin_scoped_device_id = GetSigninScopedDeviceIdForProfile(profile_);
redirect_path_prefix_ = base::StringPrintf(kOAuth2RedirectPathFormat,
token_key->extension_id.c_str());
diff --git a/chromium/chrome/browser/extensions/api/identity/identity_apitest.cc b/chromium/chrome/browser/extensions/api/identity/identity_apitest.cc
index 574f1a83551..be2c71148f1 100644
--- a/chromium/chrome/browser/extensions/api/identity/identity_apitest.cc
+++ b/chromium/chrome/browser/extensions/api/identity/identity_apitest.cc
@@ -65,6 +65,7 @@
#include "net/test/embedded_test_server/embedded_test_server.h"
#include "services/identity/public/cpp/identity_manager.h"
#include "services/identity/public/cpp/identity_test_utils.h"
+#include "services/network/public/cpp/shared_url_loader_factory.h"
#include "testing/gmock/include/gmock/gmock.h"
#include "testing/gtest/include/gtest/gtest.h"
#include "url/gurl.h"
@@ -169,7 +170,7 @@ class TestHangOAuth2MintTokenFlow : public OAuth2MintTokenFlow {
TestHangOAuth2MintTokenFlow()
: OAuth2MintTokenFlow(NULL, OAuth2MintTokenFlow::Parameters()) {}
- void Start(net::URLRequestContextGetter* context,
+ void Start(scoped_refptr<network::SharedURLLoaderFactory> url_loader_factory,
const std::string& access_token) override {
// Do nothing, simulating a hanging network call.
}
@@ -191,7 +192,7 @@ class TestOAuth2MintTokenFlow : public OAuth2MintTokenFlow {
result_(result),
delegate_(delegate) {}
- void Start(net::URLRequestContextGetter* context,
+ void Start(scoped_refptr<network::SharedURLLoaderFactory> url_loader_factory,
const std::string& access_token) override {
switch (result_) {
case ISSUE_ADVICE_SUCCESS: {
@@ -465,9 +466,6 @@ class IdentityTestWithSignin : public AsyncExtensionBrowserTest {
ProfileOAuth2TokenServiceFactory::GetInstance()->GetForProfile(
profile()));
ASSERT_TRUE(token_service_);
- GaiaCookieManagerServiceFactory::GetInstance()
- ->GetForProfile(profile())
- ->Init();
#if defined(OS_CHROMEOS)
// On ChromeOS, ProfileOAuth2TokenService does not fire
@@ -862,6 +860,19 @@ IN_PROC_BROWSER_TEST_F(GetAuthTokenFunctionTest,
EXPECT_TRUE(func->login_ui_shown());
EXPECT_FALSE(func->scope_ui_shown());
}
+
+IN_PROC_BROWSER_TEST_F(GetAuthTokenFunctionTest,
+ InteractiveNotSignedAndSigninNotAllowed) {
+ browser()->profile()->GetPrefs()->SetBoolean(prefs::kSigninAllowed, false);
+ scoped_refptr<FakeGetAuthTokenFunction> func(new FakeGetAuthTokenFunction());
+ func->set_extension(CreateExtension(CLIENT_ID | SCOPES));
+ func->set_login_ui_result(false);
+ std::string error = utils::RunFunctionAndReturnError(
+ func.get(), "[{\"interactive\": true}]", browser());
+ EXPECT_EQ(std::string(errors::kBrowserSigninNotAllowed), error);
+ EXPECT_FALSE(func->login_ui_shown());
+ EXPECT_FALSE(func->scope_ui_shown());
+}
#endif
IN_PROC_BROWSER_TEST_F(GetAuthTokenFunctionTest,
@@ -1936,21 +1947,13 @@ class GetAuthTokenFunctionPublicSessionTest : public GetAuthTokenFunctionTest {
protected:
void SetUpInProcessBrowserTestFixture() override {
- GetAuthTokenFunctionTest::SetUpInProcessBrowserTestFixture();
-
- // Set up the user manager to fake a public session.
- EXPECT_CALL(*user_manager_, IsLoggedInAsKioskApp())
- .WillRepeatedly(Return(false));
- EXPECT_CALL(*user_manager_, IsLoggedInAsPublicAccount())
- .WillRepeatedly(Return(true));
-
- // Set up fake install attributes to make the device appeared as
- // enterprise-managed.
- std::unique_ptr<chromeos::StubInstallAttributes> attributes =
- std::make_unique<chromeos::StubInstallAttributes>();
- attributes->SetCloudManaged("example.com", "fake-id");
- policy::BrowserPolicyConnectorChromeOS::SetInstallAttributesForTesting(
- attributes.release());
+ GetAuthTokenFunctionTest::SetUpInProcessBrowserTestFixture();
+
+ // Set up the user manager to fake a public session.
+ EXPECT_CALL(*user_manager_, IsLoggedInAsKioskApp())
+ .WillRepeatedly(Return(false));
+ EXPECT_CALL(*user_manager_, IsLoggedInAsPublicAccount())
+ .WillRepeatedly(Return(true));
}
scoped_refptr<Extension> CreateTestExtension(const std::string& id) {
@@ -1964,6 +1967,12 @@ class GetAuthTokenFunctionPublicSessionTest : public GetAuthTokenFunctionTest {
.Build();
}
+ // Set up fake install attributes to make the device appeared as
+ // enterprise-managed.
+ chromeos::ScopedStubInstallAttributes test_install_attributes_{
+ chromeos::StubInstallAttributes::CreateCloudManaged("example.com",
+ "fake-id")};
+
// Owned by |user_manager_enabler|.
chromeos::MockUserManager* user_manager_;
};
diff --git a/chromium/chrome/browser/extensions/api/identity/identity_constants.cc b/chromium/chrome/browser/extensions/api/identity/identity_constants.cc
index 8676090894f..fefac477308 100644
--- a/chromium/chrome/browser/extensions/api/identity/identity_constants.cc
+++ b/chromium/chrome/browser/extensions/api/identity/identity_constants.cc
@@ -13,6 +13,7 @@ const char kAuthFailure[] = "OAuth2 request failed: ";
const char kNoGrant[] = "OAuth2 not granted or revoked.";
const char kUserRejected[] = "The user did not approve access.";
const char kUserNotSignedIn[] = "The user is not signed in.";
+const char kBrowserSigninNotAllowed[] = "The user turned off browser signin";
const char kInteractionRequired[] = "User interaction required.";
const char kInvalidRedirect[] = "Did not redirect to the right URL.";
const char kOffTheRecord[] = "Identity API is disabled in incognito windows.";
diff --git a/chromium/chrome/browser/extensions/api/identity/identity_constants.h b/chromium/chrome/browser/extensions/api/identity/identity_constants.h
index 8fc01ff187d..e849ccd2222 100644
--- a/chromium/chrome/browser/extensions/api/identity/identity_constants.h
+++ b/chromium/chrome/browser/extensions/api/identity/identity_constants.h
@@ -14,6 +14,7 @@ extern const char kAuthFailure[];
extern const char kNoGrant[];
extern const char kUserRejected[];
extern const char kUserNotSignedIn[];
+extern const char kBrowserSigninNotAllowed[];
extern const char kInteractionRequired[];
extern const char kInvalidRedirect[];
extern const char kOffTheRecord[];
diff --git a/chromium/chrome/browser/extensions/api/identity/identity_get_auth_token_function.cc b/chromium/chrome/browser/extensions/api/identity/identity_get_auth_token_function.cc
index 2549540f7f9..41b2cc15afb 100644
--- a/chromium/chrome/browser/extensions/api/identity/identity_get_auth_token_function.cc
+++ b/chromium/chrome/browser/extensions/api/identity/identity_get_auth_token_function.cc
@@ -16,14 +16,16 @@
#include "chrome/browser/extensions/api/identity/identity_constants.h"
#include "chrome/browser/profiles/profile.h"
#include "chrome/browser/signin/account_tracker_service_factory.h"
-#include "chrome/browser/signin/chrome_signin_client_factory.h"
+#include "chrome/browser/signin/chrome_device_id_helper.h"
#include "chrome/browser/signin/profile_oauth2_token_service_factory.h"
#include "chrome/browser/ui/webui/signin/login_ui_service.h"
#include "chrome/browser/ui/webui/signin/login_ui_service_factory.h"
#include "chrome/common/extensions/api/identity.h"
+#include "components/prefs/pref_service.h"
#include "components/signin/core/browser/account_tracker_service.h"
#include "components/signin/core/browser/profile_management_switches.h"
#include "components/signin/core/browser/profile_oauth2_token_service.h"
+#include "components/signin/core/browser/signin_pref_names.h"
#include "content/public/common/service_manager_connection.h"
#include "extensions/common/extension_l10n_util.h"
#include "google_apis/gaia/gaia_urls.h"
@@ -56,6 +58,10 @@ const char* const kPublicSessionAllowedOrigins[] = {
"chrome-extension://gbchcmhmhahfdphkhkmpfmihenigjmpp/"};
#endif
+bool IsBrowserSigninAllowed(Profile* profile) {
+ return profile->GetPrefs()->GetBoolean(prefs::kSigninAllowed);
+}
+
} // namespace
IdentityGetAuthTokenFunction::IdentityGetAuthTokenFunction()
@@ -92,7 +98,8 @@ bool IdentityGetAuthTokenFunction::RunAsync() {
*params->details->interactive;
should_prompt_for_scopes_ = interactive_;
- should_prompt_for_signin_ = interactive_;
+ should_prompt_for_signin_ =
+ interactive_ && IsBrowserSigninAllowed(GetProfile());
const OAuth2Info& oauth2_info = OAuth2Info::GetOAuth2Info(extension());
@@ -203,7 +210,10 @@ void IdentityGetAuthTokenFunction::OnReceivedExtensionAccountInfo(
if (!account_state.has_refresh_token) {
if (!ShouldStartSigninFlow()) {
- CompleteFunctionWithError(identity_constants::kUserNotSignedIn);
+ CompleteFunctionWithError(
+ IsBrowserSigninAllowed(GetProfile())
+ ? identity_constants::kUserNotSignedIn
+ : identity_constants::kBrowserSigninNotAllowed);
return;
}
// Display a login prompt.
@@ -593,10 +603,10 @@ void IdentityGetAuthTokenFunction::OnGetAccessTokenComplete(
#if defined(OS_CHROMEOS)
void IdentityGetAuthTokenFunction::OnGetTokenSuccess(
const OAuth2TokenService::Request* request,
- const std::string& access_token,
- const base::Time& expiration_time) {
+ const OAuth2AccessTokenConsumer::TokenResponse& token_response) {
login_token_request_.reset();
- OnGetAccessTokenComplete(access_token, expiration_time,
+ OnGetAccessTokenComplete(token_response.access_token,
+ token_response.expiration_time,
GoogleServiceAuthError::AuthErrorNone());
}
@@ -684,7 +694,7 @@ void IdentityGetAuthTokenFunction::StartGaiaRequest(
const std::string& login_access_token) {
DCHECK(!login_access_token.empty());
mint_token_flow_.reset(CreateMintTokenFlow());
- mint_token_flow_->Start(GetProfile()->GetRequestContext(),
+ mint_token_flow_->Start(GetProfile()->GetURLLoaderFactory(),
login_access_token);
}
@@ -704,10 +714,8 @@ void IdentityGetAuthTokenFunction::ShowOAuthApprovalDialog(
}
OAuth2MintTokenFlow* IdentityGetAuthTokenFunction::CreateMintTokenFlow() {
- SigninClient* signin_client =
- ChromeSigninClientFactory::GetForProfile(GetProfile());
std::string signin_scoped_device_id =
- signin_client->GetSigninScopedDeviceId();
+ GetSigninScopedDeviceIdForProfile(GetProfile());
OAuth2MintTokenFlow* mint_token_flow = new OAuth2MintTokenFlow(
this,
OAuth2MintTokenFlow::Parameters(
diff --git a/chromium/chrome/browser/extensions/api/identity/identity_get_auth_token_function.h b/chromium/chrome/browser/extensions/api/identity/identity_get_auth_token_function.h
index ed99f975a37..ace71040bff 100644
--- a/chromium/chrome/browser/extensions/api/identity/identity_get_auth_token_function.h
+++ b/chromium/chrome/browser/extensions/api/identity/identity_get_auth_token_function.h
@@ -73,9 +73,9 @@ class IdentityGetAuthTokenFunction : public ChromeAsyncExtensionFunction,
// OAuth2TokenService::Consumer.
#if defined(OS_CHROMEOS)
// OAuth2TokenService::Consumer implementation:
- void OnGetTokenSuccess(const OAuth2TokenService::Request* request,
- const std::string& access_token,
- const base::Time& expiration_time) override;
+ void OnGetTokenSuccess(
+ const OAuth2TokenService::Request* request,
+ const OAuth2AccessTokenConsumer::TokenResponse& token_response) override;
void OnGetTokenFailure(const OAuth2TokenService::Request* request,
const GoogleServiceAuthError& error) override;
#endif
diff --git a/chromium/chrome/browser/extensions/api/image_writer_private/destroy_partitions_operation.cc b/chromium/chrome/browser/extensions/api/image_writer_private/destroy_partitions_operation.cc
index 793a0a5d6b2..6779605e610 100644
--- a/chromium/chrome/browser/extensions/api/image_writer_private/destroy_partitions_operation.cc
+++ b/chromium/chrome/browser/extensions/api/image_writer_private/destroy_partitions_operation.cc
@@ -34,7 +34,7 @@ DestroyPartitionsOperation::~DestroyPartitionsOperation() {}
void DestroyPartitionsOperation::StartImpl() {
DCHECK(IsRunningInCorrectSequence());
- if (!base::CreateTemporaryFileInDir(temp_dir_.GetPath(), &image_path_)) {
+ if (!base::CreateTemporaryFileInDir(temp_dir_->GetPath(), &image_path_)) {
Error(error::kTempFileError);
return;
}
diff --git a/chromium/chrome/browser/extensions/api/image_writer_private/image_writer_utility_client_browsertest.cc b/chromium/chrome/browser/extensions/api/image_writer_private/image_writer_utility_client_browsertest.cc
index ab1999a5135..22830d6a2af 100644
--- a/chromium/chrome/browser/extensions/api/image_writer_private/image_writer_utility_client_browsertest.cc
+++ b/chromium/chrome/browser/extensions/api/image_writer_private/image_writer_utility_client_browsertest.cc
@@ -12,7 +12,7 @@
#include "base/macros.h"
#include "base/run_loop.h"
#include "base/sequenced_task_runner.h"
-#include "base/task_scheduler/post_task.h"
+#include "base/task/post_task.h"
#include "base/threading/thread_restrictions.h"
#include "chrome/browser/extensions/api/image_writer_private/operation.h"
#include "chrome/services/removable_storage_writer/public/mojom/removable_storage_writer.mojom.h"
diff --git a/chromium/chrome/browser/extensions/api/image_writer_private/operation.cc b/chromium/chrome/browser/extensions/api/image_writer_private/operation.cc
index 58739bb2437..125db2b83a5 100644
--- a/chromium/chrome/browser/extensions/api/image_writer_private/operation.cc
+++ b/chromium/chrome/browser/extensions/api/image_writer_private/operation.cc
@@ -8,7 +8,7 @@
#include "base/files/file_enumerator.h"
#include "base/files/file_util.h"
-#include "base/task_scheduler/post_task.h"
+#include "base/task/post_task.h"
#include "build/build_config.h"
#include "chrome/browser/extensions/api/image_writer_private/error_messages.h"
#include "chrome/browser/extensions/api/image_writer_private/operation_manager.h"
@@ -39,6 +39,7 @@ Operation::Operation(base::WeakPtr<OperationManager> manager,
#else
device_path_(device_path),
#endif
+ temp_dir_(std::make_unique<base::ScopedTempDir>()),
connector_(std::move(connector)),
stage_(image_writer_api::STAGE_UNKNOWN),
progress_(0),
@@ -50,6 +51,11 @@ Operation::Operation(base::WeakPtr<OperationManager> manager,
Operation::~Operation() {
// The connector_ is bound to the |task_runner_| and must be deleted there.
task_runner_->DeleteSoon(FROM_HERE, std::move(connector_));
+
+ // base::ScopedTempDir must be destroyed on a thread that allows blocking IO
+ // because it will try delete the directory if a call to Delete() hasn't been
+ // made or was unsuccessful.
+ task_runner_->DeleteSoon(FROM_HERE, std::move(temp_dir_));
}
void Operation::Cancel() {
@@ -81,9 +87,9 @@ void Operation::Start() {
DCHECK(IsRunningInCorrectSequence());
#if defined(OS_CHROMEOS)
if (download_folder_.empty() ||
- !temp_dir_.CreateUniqueTempDirUnderPath(download_folder_)) {
+ !temp_dir_->CreateUniqueTempDirUnderPath(download_folder_)) {
#else
- if (!temp_dir_.CreateUniqueTempDir()) {
+ if (!temp_dir_->CreateUniqueTempDir()) {
#endif
Error(error::kTempDirError);
return;
@@ -91,7 +97,7 @@ void Operation::Start() {
AddCleanUpFunction(
base::BindOnce(base::IgnoreResult(&base::ScopedTempDir::Delete),
- base::Unretained(&temp_dir_)));
+ base::Unretained(temp_dir_.get())));
StartImpl();
}
@@ -119,7 +125,7 @@ void Operation::Unzip(const base::Closure& continuation) {
base::Bind(&Operation::CompleteAndContinue, this, continuation),
base::Bind(&Operation::OnUnzipFailure, this),
base::Bind(&Operation::OnUnzipProgress, this));
- unzip_helper->Unzip(image_path_, temp_dir_.GetPath());
+ unzip_helper->Unzip(image_path_, temp_dir_->GetPath());
}
void Operation::Finish() {
diff --git a/chromium/chrome/browser/extensions/api/image_writer_private/operation.h b/chromium/chrome/browser/extensions/api/image_writer_private/operation.h
index f629f58d7e4..ba12212379a 100644
--- a/chromium/chrome/browser/extensions/api/image_writer_private/operation.h
+++ b/chromium/chrome/browser/extensions/api/image_writer_private/operation.h
@@ -16,12 +16,16 @@
#include "base/memory/ref_counted_memory.h"
#include "base/memory/weak_ptr.h"
#include "base/sequenced_task_runner.h"
-#include "base/task_scheduler/task_traits.h"
+#include "base/task/task_traits.h"
#include "build/build_config.h"
#include "chrome/browser/extensions/api/image_writer_private/image_writer_utility_client.h"
#include "chrome/common/extensions/api/image_writer_private.h"
#include "extensions/common/extension_id.h"
+#if defined(OS_CHROMEOS)
+#include "chromeos/disks/disk_mount_manager.h"
+#endif
+
namespace image_writer_api = extensions::api::image_writer_private;
namespace base {
@@ -155,7 +159,7 @@ class Operation : public base::RefCountedThreadSafe<Operation> {
base::FilePath device_path_;
// Temporary directory to store files as we go.
- base::ScopedTempDir temp_dir_;
+ std::unique_ptr<base::ScopedTempDir> temp_dir_;
private:
friend class base::RefCountedThreadSafe<Operation>;
@@ -183,7 +187,8 @@ class Operation : public base::RefCountedThreadSafe<Operation> {
// Unmounts all volumes on |device_path_|.
void UnmountVolumes(const base::Closure& continuation);
// Starts the write after unmounting.
- void UnmountVolumesCallback(const base::Closure& continuation, bool success);
+ void UnmountVolumesCallback(const base::Closure& continuation,
+ chromeos::MountError error_code);
// Starts the ImageBurner write. Note that target_path is the file path of
// the device where device_path has been a system device path.
void StartWriteOnUIThread(const std::string& target_path,
diff --git a/chromium/chrome/browser/extensions/api/image_writer_private/operation_chromeos.cc b/chromium/chrome/browser/extensions/api/image_writer_private/operation_chromeos.cc
index 56b833274df..6817c9db7f2 100644
--- a/chromium/chrome/browser/extensions/api/image_writer_private/operation_chromeos.cc
+++ b/chromium/chrome/browser/extensions/api/image_writer_private/operation_chromeos.cc
@@ -8,6 +8,7 @@
#include "chrome/browser/extensions/api/image_writer_private/operation.h"
#include "chromeos/dbus/dbus_thread_manager.h"
#include "chromeos/dbus/image_burner_client.h"
+#include "chromeos/disks/disk.h"
#include "chromeos/disks/disk_mount_manager.h"
#include "content/public/browser/browser_thread.h"
@@ -61,11 +62,11 @@ void Operation::UnmountVolumes(const base::Closure& continuation) {
}
void Operation::UnmountVolumesCallback(const base::Closure& continuation,
- bool success) {
+ chromeos::MountError error_code) {
DCHECK_CURRENTLY_ON(BrowserThread::UI);
- if (!success) {
- LOG(ERROR) << "Volume unmounting failed.";
+ if (error_code != chromeos::MOUNT_ERROR_NONE) {
+ LOG(ERROR) << "Volume unmounting failed with error code " << error_code;
PostTask(base::Bind(&Operation::Error, this, error::kUnmountVolumesError));
return;
}
diff --git a/chromium/chrome/browser/extensions/api/image_writer_private/operation_manager.cc b/chromium/chrome/browser/extensions/api/image_writer_private/operation_manager.cc
index f923cc582c0..037e29ae338 100644
--- a/chromium/chrome/browser/extensions/api/image_writer_private/operation_manager.cc
+++ b/chromium/chrome/browser/extensions/api/image_writer_private/operation_manager.cc
@@ -86,11 +86,15 @@ void OperationManager::StartWriteFromUrl(
return;
}
+ network::mojom::URLLoaderFactoryPtrInfo url_loader_factory_info;
+ content::BrowserContext::GetDefaultStoragePartition(browser_context_)
+ ->GetURLLoaderFactoryForBrowserProcess()
+ ->Clone(mojo::MakeRequest(&url_loader_factory_info));
+
scoped_refptr<Operation> operation(new WriteFromUrlOperation(
weak_factory_.GetWeakPtr(), CreateConnector(), extension_id,
- content::BrowserContext::GetDefaultStoragePartition(browser_context_)
- ->GetURLRequestContext(),
- url, hash, device_path, GetAssociatedDownloadFolder()));
+ std::move(url_loader_factory_info), url, hash, device_path,
+ GetAssociatedDownloadFolder()));
operations_[extension_id] = operation;
operation->PostTask(base::BindOnce(&Operation::Start, operation));
diff --git a/chromium/chrome/browser/extensions/api/image_writer_private/removable_storage_provider.cc b/chromium/chrome/browser/extensions/api/image_writer_private/removable_storage_provider.cc
index c16b847be5a..a0f60c4059b 100644
--- a/chromium/chrome/browser/extensions/api/image_writer_private/removable_storage_provider.cc
+++ b/chromium/chrome/browser/extensions/api/image_writer_private/removable_storage_provider.cc
@@ -5,7 +5,7 @@
#include "chrome/browser/extensions/api/image_writer_private/removable_storage_provider.h"
#include "base/lazy_instance.h"
-#include "base/task_scheduler/post_task.h"
+#include "base/task/post_task.h"
#include "base/threading/thread_task_runner_handle.h"
#include "content/public/browser/browser_thread.h"
diff --git a/chromium/chrome/browser/extensions/api/image_writer_private/removable_storage_provider_chromeos.cc b/chromium/chrome/browser/extensions/api/image_writer_private/removable_storage_provider_chromeos.cc
index c3599770427..525557ccce8 100644
--- a/chromium/chrome/browser/extensions/api/image_writer_private/removable_storage_provider_chromeos.cc
+++ b/chromium/chrome/browser/extensions/api/image_writer_private/removable_storage_provider_chromeos.cc
@@ -3,6 +3,8 @@
// found in the LICENSE file.
#include "chrome/browser/extensions/api/image_writer_private/removable_storage_provider.h"
+
+#include "chromeos/disks/disk.h"
#include "chromeos/disks/disk_mount_manager.h"
namespace extensions {
@@ -10,6 +12,7 @@ namespace extensions {
const char kUnknownSDDiskModel[] = "SD Card";
const char kUnknownUSBDiskModel[] = "USB Drive";
+using chromeos::disks::Disk;
using chromeos::disks::DiskMountManager;
// The Chrome OS implementation takes advantage of the Chrome OS
@@ -26,7 +29,7 @@ RemovableStorageProvider::PopulateDeviceList() {
for (DiskMountManager::DiskMap::const_iterator iter = disks.begin();
iter != disks.end();
++iter) {
- const DiskMountManager::Disk& disk = *iter->second;
+ const Disk& disk = *iter->second;
if (disk.is_parent() && !disk.on_boot_device() && disk.has_media() &&
(disk.device_type() == chromeos::DEVICE_TYPE_USB ||
disk.device_type() == chromeos::DEVICE_TYPE_SD)) {
diff --git a/chromium/chrome/browser/extensions/api/image_writer_private/test_utils.cc b/chromium/chrome/browser/extensions/api/image_writer_private/test_utils.cc
index d8204d5ad57..f6d4020a22b 100644
--- a/chromium/chrome/browser/extensions/api/image_writer_private/test_utils.cc
+++ b/chromium/chrome/browser/extensions/api/image_writer_private/test_utils.cc
@@ -9,7 +9,7 @@
#include "base/location.h"
#include "base/single_thread_task_runner.h"
-#include "base/task_scheduler/post_task.h"
+#include "base/task/post_task.h"
#include "base/threading/thread_task_runner_handle.h"
#include "build/build_config.h"
#include "chrome/browser/extensions/api/image_writer_private/error_messages.h"
@@ -18,6 +18,7 @@
#if defined(OS_CHROMEOS)
#include "chromeos/dbus/dbus_thread_manager.h"
#include "chromeos/dbus/fake_image_burner_client.h"
+#include "chromeos/disks/disk.h"
#endif
namespace extensions {
@@ -73,9 +74,10 @@ FakeDiskMountManager::~FakeDiskMountManager() {}
void FakeDiskMountManager::UnmountDeviceRecursively(
const std::string& device_path,
- const UnmountDeviceRecursivelyCallbackType& callback) {
- base::ThreadTaskRunnerHandle::Get()->PostTask(FROM_HERE,
- base::BindOnce(callback, true));
+ UnmountDeviceRecursivelyCallbackType callback) {
+ base::ThreadTaskRunnerHandle::Get()->PostTask(
+ FROM_HERE,
+ base::BindOnce(std::move(callback), chromeos::MOUNT_ERROR_NONE));
}
#endif
diff --git a/chromium/chrome/browser/extensions/api/image_writer_private/test_utils.h b/chromium/chrome/browser/extensions/api/image_writer_private/test_utils.h
index 1031b57f7fa..aa0397989d1 100644
--- a/chromium/chrome/browser/extensions/api/image_writer_private/test_utils.h
+++ b/chromium/chrome/browser/extensions/api/image_writer_private/test_utils.h
@@ -70,7 +70,7 @@ class FakeDiskMountManager : public chromeos::disks::MockDiskMountManager {
void UnmountDeviceRecursively(
const std::string& device_path,
- const UnmountDeviceRecursivelyCallbackType& callback) override;
+ UnmountDeviceRecursivelyCallbackType callback) override;
private:
DiskMap disks_;
diff --git a/chromium/chrome/browser/extensions/api/image_writer_private/unzip_helper.cc b/chromium/chrome/browser/extensions/api/image_writer_private/unzip_helper.cc
index dbca44a3e9d..41f1ecce153 100644
--- a/chromium/chrome/browser/extensions/api/image_writer_private/unzip_helper.cc
+++ b/chromium/chrome/browser/extensions/api/image_writer_private/unzip_helper.cc
@@ -8,7 +8,7 @@
#include "base/files/file_util.h"
#include "base/single_thread_task_runner.h"
-#include "base/task_scheduler/post_task.h"
+#include "base/task/post_task.h"
#include "chrome/browser/extensions/api/image_writer_private/error_messages.h"
#include "third_party/zlib/google/zip_reader.h"
diff --git a/chromium/chrome/browser/extensions/api/image_writer_private/write_from_url_operation.cc b/chromium/chrome/browser/extensions/api/image_writer_private/write_from_url_operation.cc
index cedfb9b5446..1a9629190e7 100644
--- a/chromium/chrome/browser/extensions/api/image_writer_private/write_from_url_operation.cc
+++ b/chromium/chrome/browser/extensions/api/image_writer_private/write_from_url_operation.cc
@@ -9,6 +9,8 @@
#include "content/public/browser/browser_thread.h"
#include "net/traffic_annotation/network_traffic_annotation.h"
#include "net/url_request/url_fetcher.h"
+#include "services/network/public/cpp/resource_response.h"
+#include "services/network/public/cpp/simple_url_loader.h"
#include "services/service_manager/public/cpp/connector.h"
namespace extensions {
@@ -20,7 +22,7 @@ WriteFromUrlOperation::WriteFromUrlOperation(
base::WeakPtr<OperationManager> manager,
std::unique_ptr<service_manager::Connector> connector,
const ExtensionId& extension_id,
- net::URLRequestContextGetter* request_context,
+ network::mojom::URLLoaderFactoryPtrInfo factory_info,
GURL url,
const std::string& hash,
const std::string& device_path,
@@ -30,7 +32,7 @@ WriteFromUrlOperation::WriteFromUrlOperation(
extension_id,
device_path,
download_folder),
- request_context_(request_context),
+ url_loader_factory_ptr_info_(std::move(factory_info)),
url_(url),
hash_(hash),
download_continuation_() {}
@@ -59,14 +61,14 @@ void WriteFromUrlOperation::GetDownloadTarget(base::OnceClosure continuation) {
}
if (url_.ExtractFileName().empty()) {
- if (!base::CreateTemporaryFileInDir(temp_dir_.GetPath(), &image_path_)) {
+ if (!base::CreateTemporaryFileInDir(temp_dir_->GetPath(), &image_path_)) {
Error(error::kTempFileError);
return;
}
} else {
base::FilePath file_name =
base::FilePath::FromUTF8Unsafe(url_.ExtractFileName());
- image_path_ = temp_dir_.GetPath().Append(file_name);
+ image_path_ = temp_dir_->GetPath().Append(file_name);
}
PostTask(std::move(continuation));
@@ -110,49 +112,53 @@ void WriteFromUrlOperation::Download(base::OnceClosure continuation) {
"Not implemented, considered not useful."
})");
- // Store the URL fetcher on this object so that it is destroyed before this
- // object is.
- url_fetcher_ = net::URLFetcher::Create(url_, net::URLFetcher::GET, this,
- traffic_annotation);
+ auto request = std::make_unique<network::ResourceRequest>();
+ request->url = GURL(url_);
+ simple_url_loader_ =
+ network::SimpleURLLoader::Create(std::move(request), traffic_annotation);
- url_fetcher_->SetRequestContext(request_context_);
- url_fetcher_->SaveResponseToFileAtPath(image_path_, task_runner());
+ simple_url_loader_->SetOnDownloadProgressCallback(base::BindRepeating(
+ &WriteFromUrlOperation::OnDataDownloaded, base::Unretained(this)));
+ simple_url_loader_->SetOnResponseStartedCallback(base::BindOnce(
+ &WriteFromUrlOperation::OnResponseStarted, base::Unretained(this)));
AddCleanUpFunction(
- base::BindOnce(&WriteFromUrlOperation::DestroyUrlFetcher, this));
+ base::BindOnce(&WriteFromUrlOperation::DestroySimpleURLLoader, this));
- url_fetcher_->Start();
+ network::mojom::URLLoaderFactoryPtr url_loader_factory_ptr;
+ url_loader_factory_ptr.Bind(std::move(url_loader_factory_ptr_info_));
+
+ simple_url_loader_->DownloadToFile(
+ url_loader_factory_ptr.get(),
+ base::BindOnce(&WriteFromUrlOperation::OnSimpleLoaderComplete,
+ base::Unretained(this)),
+ image_path_);
}
-void WriteFromUrlOperation::DestroyUrlFetcher() { url_fetcher_.reset(); }
+void WriteFromUrlOperation::DestroySimpleURLLoader() {
+ simple_url_loader_.reset();
+}
-void WriteFromUrlOperation::OnURLFetchUploadProgress(
- const net::URLFetcher* source,
- int64_t current,
- int64_t total) {
- // No-op
+void WriteFromUrlOperation::OnResponseStarted(
+ const GURL& final_url,
+ const network::ResourceResponseHead& response_head) {
+ total_response_bytes_ = response_head.content_length;
}
-void WriteFromUrlOperation::OnURLFetchDownloadProgress(
- const net::URLFetcher* source,
- int64_t current,
- int64_t total,
- int64_t current_network_bytes) {
+void WriteFromUrlOperation::OnDataDownloaded(uint64_t current) {
DCHECK(IsRunningInCorrectSequence());
- if (IsCancelled()) {
- url_fetcher_.reset(NULL);
- }
+ if (IsCancelled())
+ DestroySimpleURLLoader();
- int progress = (kProgressComplete * current) / total;
+ int progress = (kProgressComplete * current) / total_response_bytes_;
SetProgress(progress);
}
-void WriteFromUrlOperation::OnURLFetchComplete(const net::URLFetcher* source) {
+void WriteFromUrlOperation::OnSimpleLoaderComplete(base::FilePath file_path) {
DCHECK(IsRunningInCorrectSequence());
-
- if (source->GetStatus().is_success() && source->GetResponseCode() == 200) {
+ if (!file_path.empty()) {
SetProgress(kProgressComplete);
std::move(download_continuation_).Run();
diff --git a/chromium/chrome/browser/extensions/api/image_writer_private/write_from_url_operation.h b/chromium/chrome/browser/extensions/api/image_writer_private/write_from_url_operation.h
index b2c5a9cfa9b..757fc07ffb9 100644
--- a/chromium/chrome/browser/extensions/api/image_writer_private/write_from_url_operation.h
+++ b/chromium/chrome/browser/extensions/api/image_writer_private/write_from_url_operation.h
@@ -8,13 +8,13 @@
#include <stdint.h>
#include "chrome/browser/extensions/api/image_writer_private/operation.h"
-#include "net/url_request/url_fetcher_delegate.h"
+#include "services/network/public/mojom/url_loader_factory.mojom.h"
#include "url/gurl.h"
-namespace net {
-class URLFetcher;
-class URLRequestContextGetter;
-} // namespace net
+namespace network {
+struct ResourceResponseHead;
+class SimpleURLLoader;
+} // namespace network
namespace extensions {
namespace image_writer {
@@ -22,12 +22,12 @@ namespace image_writer {
class OperationManager;
// Encapsulates a write of an image accessed via URL.
-class WriteFromUrlOperation : public Operation, public net::URLFetcherDelegate {
+class WriteFromUrlOperation : public Operation {
public:
WriteFromUrlOperation(base::WeakPtr<OperationManager> manager,
std::unique_ptr<service_manager::Connector> connector,
const ExtensionId& extension_id,
- net::URLRequestContextGetter* request_context,
+ network::mojom::URLLoaderFactoryPtrInfo factory_info,
GURL url,
const std::string& hash,
const std::string& storage_unit_id,
@@ -52,33 +52,24 @@ class WriteFromUrlOperation : public Operation, public net::URLFetcherDelegate {
void VerifyDownload(base::OnceClosure continuation);
private:
- // Destroys the URLFetcher. The URLFetcher needs to be destroyed on the same
- // thread it was created on. The Operation may be deleted on the UI thread
- // and so we must first delete the URLFetcher on the FILE thread.
- void DestroyUrlFetcher();
-
- // URLFetcherDelegate implementation.
- void OnURLFetchComplete(const net::URLFetcher* source) override;
- void OnURLFetchDownloadProgress(const net::URLFetcher* source,
- int64_t current,
- int64_t total,
- int64_t current_network_bytes) override;
- void OnURLFetchUploadProgress(const net::URLFetcher* source,
- int64_t current,
- int64_t total) override;
-
+ void DestroySimpleURLLoader();
+ void OnResponseStarted(const GURL& final_url,
+ const network::ResourceResponseHead& response_head);
+ void OnDataDownloaded(uint64_t current);
+ void OnSimpleLoaderComplete(base::FilePath file_path);
void VerifyDownloadCompare(base::OnceClosure continuation,
const std::string& download_hash);
void VerifyDownloadComplete(base::OnceClosure continuation);
// Arguments
- net::URLRequestContextGetter* request_context_;
+ network::mojom::URLLoaderFactoryPtrInfo url_loader_factory_ptr_info_;
GURL url_;
const std::string hash_;
// Local state
- std::unique_ptr<net::URLFetcher> url_fetcher_;
+ std::unique_ptr<network::SimpleURLLoader> simple_url_loader_;
base::OnceClosure download_continuation_;
+ int total_response_bytes_ = -1;
};
} // namespace image_writer
diff --git a/chromium/chrome/browser/extensions/api/image_writer_private/write_from_url_operation_unittest.cc b/chromium/chrome/browser/extensions/api/image_writer_private/write_from_url_operation_unittest.cc
index c79d6998b8f..20f3c870603 100644
--- a/chromium/chrome/browser/extensions/api/image_writer_private/write_from_url_operation_unittest.cc
+++ b/chromium/chrome/browser/extensions/api/image_writer_private/write_from_url_operation_unittest.cc
@@ -5,11 +5,12 @@
#include "chrome/browser/extensions/api/image_writer_private/write_from_url_operation.h"
#include "base/run_loop.h"
-#include "base/task_scheduler/post_task.h"
+#include "base/task/post_task.h"
#include "chrome/browser/extensions/api/image_writer_private/error_messages.h"
#include "chrome/browser/extensions/api/image_writer_private/test_utils.h"
#include "chrome/test/base/testing_profile.h"
#include "content/public/browser/browser_thread.h"
+#include "content/public/browser/storage_partition.h"
#include "net/url_request/test_url_request_interceptor.h"
#include "services/service_manager/public/cpp/connector.h"
@@ -35,16 +36,17 @@ typedef net::LocalHostTestURLRequestInterceptor GetInterceptor;
// the current path to the image file.
class WriteFromUrlOperationForTest : public WriteFromUrlOperation {
public:
- WriteFromUrlOperationForTest(base::WeakPtr<OperationManager> manager,
- const ExtensionId& extension_id,
- net::URLRequestContextGetter* request_context,
- GURL url,
- const std::string& hash,
- const std::string& storage_unit_id)
+ WriteFromUrlOperationForTest(
+ base::WeakPtr<OperationManager> manager,
+ const ExtensionId& extension_id,
+ network::mojom::URLLoaderFactoryPtrInfo factory_info,
+ GURL url,
+ const std::string& hash,
+ const std::string& storage_unit_id)
: WriteFromUrlOperation(manager,
/*connector=*/nullptr,
extension_id,
- request_context,
+ std::move(factory_info),
url,
hash,
storage_unit_id,
@@ -99,7 +101,7 @@ class ImageWriterWriteFromUrlOperationTest : public ImageWriterUnitTestBase {
get_interceptor_.reset(new GetInterceptor(
BrowserThread::GetTaskRunnerForThread(BrowserThread::IO),
base::CreateTaskRunnerWithTraits(
- {base::MayBlock(), base::TaskPriority::BACKGROUND,
+ {base::MayBlock(), base::TaskPriority::BEST_EFFORT,
base::TaskShutdownBehavior::SKIP_ON_SHUTDOWN})));
get_interceptor_->SetResponse(GURL(kTestImageUrl),
test_utils_.GetImagePath());
@@ -112,10 +114,15 @@ class ImageWriterWriteFromUrlOperationTest : public ImageWriterUnitTestBase {
scoped_refptr<WriteFromUrlOperationForTest> CreateOperation(
const GURL& url,
const std::string& hash) {
+ network::mojom::URLLoaderFactoryPtrInfo url_loader_factory_ptr_info;
+ content::BrowserContext::GetDefaultStoragePartition(&test_profile_)
+ ->GetURLLoaderFactoryForBrowserProcess()
+ ->Clone(mojo::MakeRequest(&url_loader_factory_ptr_info));
+
scoped_refptr<WriteFromUrlOperationForTest> operation(
new WriteFromUrlOperationForTest(
manager_.AsWeakPtr(), kDummyExtensionId,
- test_profile_.GetRequestContext(), url, hash,
+ std::move(url_loader_factory_ptr_info), url, hash,
test_utils_.GetDevicePath().AsUTF8Unsafe()));
operation->Start();
return operation;
@@ -182,10 +189,6 @@ TEST_F(ImageWriterWriteFromUrlOperationTest, DownloadFile) {
EXPECT_CALL(
manager_,
- OnProgress(kDummyExtensionId, image_writer_api::STAGE_DOWNLOAD, _))
- .Times(AtLeast(1));
- EXPECT_CALL(
- manager_,
OnProgress(kDummyExtensionId, image_writer_api::STAGE_DOWNLOAD, 0))
.Times(AnyNumber());
EXPECT_CALL(
diff --git a/chromium/chrome/browser/extensions/api/input_ime/input_ime_api.cc b/chromium/chrome/browser/extensions/api/input_ime/input_ime_api.cc
index f4aedc8c0fa..c5f26972ffb 100644
--- a/chromium/chrome/browser/extensions/api/input_ime/input_ime_api.cc
+++ b/chromium/chrome/browser/extensions/api/input_ime/input_ime_api.cc
@@ -197,6 +197,11 @@ bool ImeObserver::HasListener(const std::string& event_name) const {
return extensions::EventRouter::Get(profile_)->HasEventListener(event_name);
}
+bool ImeObserver::ExtensionHasListener(const std::string& event_name) const {
+ return extensions::EventRouter::Get(profile_)->ExtensionHasEventListener(
+ extension_id_, event_name);
+}
+
std::string ImeObserver::ConvertInputContextType(
ui::IMEEngineHandlerInterface::InputContext input_context) {
std::string input_context_type = "text";
diff --git a/chromium/chrome/browser/extensions/api/input_ime/input_ime_api.h b/chromium/chrome/browser/extensions/api/input_ime/input_ime_api.h
index ca9b9522dd9..78e9fce74fd 100644
--- a/chromium/chrome/browser/extensions/api/input_ime/input_ime_api.h
+++ b/chromium/chrome/browser/extensions/api/input_ime/input_ime_api.h
@@ -81,8 +81,12 @@ class ImeObserver : public input_method::InputMethodEngineBase::Observer {
bool ShouldForwardKeyEvent() const;
// Returns true if there are any listeners on the given event.
+ // TODO(https://crbug.com/835699): Merge this with |ExtensionHasListener|.
bool HasListener(const std::string& event_name) const;
+ // Returns true if the extension has any listeners on the given event.
+ bool ExtensionHasListener(const std::string& event_name) const;
+
// Functions used to convert InputContext struct to string
std::string ConvertInputContextType(
IMEEngineHandlerInterface::InputContext input_context);
diff --git a/chromium/chrome/browser/extensions/api/input_ime/input_ime_api_chromeos.cc b/chromium/chrome/browser/extensions/api/input_ime/input_ime_api_chromeos.cc
index 7f26164f67f..b437fc65997 100644
--- a/chromium/chrome/browser/extensions/api/input_ime/input_ime_api_chromeos.cc
+++ b/chromium/chrome/browser/extensions/api/input_ime/input_ime_api_chromeos.cc
@@ -202,7 +202,7 @@ class ImeObserverChromeOS : public ui::ImeObserver {
// There is both a public and private OnFocus event. The private OnFocus
// event is only for ChromeOS and contains additional information about pen
// inputs. We ensure that we only trigger one OnFocus event.
- if (HasListener(input_method_private::OnFocus::kEventName) &&
+ if (ExtensionHasListener(input_method_private::OnFocus::kEventName) &&
keyboard::IsStylusVirtualKeyboardEnabled()) {
input_method_private::InputContext input_context;
input_context.context_id = context.id;
@@ -210,6 +210,8 @@ class ImeObserverChromeOS : public ui::ImeObserver {
ConvertInputContextType(context));
input_context.auto_correct = ConvertInputContextAutoCorrect(context);
input_context.auto_complete = ConvertInputContextAutoComplete(context);
+ input_context.auto_capitalize = (input_method_private::AutoCapitalizeType)
+ ConvertInputContextAutoCapitalize(context);
input_context.spell_check = ConvertInputContextSpellCheck(context);
input_context.should_do_learning = context.should_do_learning;
input_context.focus_reason = input_method_private::ParseFocusReason(
diff --git a/chromium/chrome/browser/extensions/api/language_settings_private/language_settings_private_api.cc b/chromium/chrome/browser/extensions/api/language_settings_private/language_settings_private_api.cc
index 0a2368e6f81..19df4358af6 100644
--- a/chromium/chrome/browser/extensions/api/language_settings_private/language_settings_private_api.cc
+++ b/chromium/chrome/browser/extensions/api/language_settings_private/language_settings_private_api.cc
@@ -532,7 +532,7 @@ LanguageSettingsPrivateGetTranslateTargetLanguageFunction::Run() {
Profile* profile = chrome_details_.GetProfile();
language::LanguageModel* language_model =
LanguageModelManagerFactory::GetForBrowserContext(profile)
- ->GetDefaultModel();
+ ->GetPrimaryModel();
return RespondNow(OneArgument(
std::make_unique<base::Value>(TranslateService::GetTargetLanguage(
profile->GetPrefs(), language_model))));
@@ -562,7 +562,9 @@ void PopulateInputMethodListFromDescriptors(
input_method.enabled.reset(new bool(true));
if (descriptor.options_page_url().is_valid())
input_method.has_options_page.reset(new bool(true));
- if (!allowed_ids.empty() && util->IsKeyboardLayout(input_method.id) &&
+ if (!allowed_ids.empty() &&
+ (util->IsKeyboardLayout(input_method.id) ||
+ chromeos::extension_ime_util::IsArcIME(input_method.id)) &&
allowed_ids.count(input_method.id) == 0) {
input_method.is_prohibited_by_policy.reset(new bool(true));
}
diff --git a/chromium/chrome/browser/extensions/api/language_settings_private/language_settings_private_delegate.cc b/chromium/chrome/browser/extensions/api/language_settings_private/language_settings_private_delegate.cc
index f1057324374..634e75751ea 100644
--- a/chromium/chrome/browser/extensions/api/language_settings_private/language_settings_private_delegate.cc
+++ b/chromium/chrome/browser/extensions/api/language_settings_private/language_settings_private_delegate.cc
@@ -32,6 +32,7 @@ LanguageSettingsPrivateDelegate::LanguageSettingsPrivateDelegate(
: custom_dictionary_(nullptr),
context_(context),
listening_spellcheck_(false),
+ listening_input_method_(false),
profile_added_(false) {
// Register with the event router so we know when renderers are listening to
// our events. We first check and see if there *is* an event router, because
@@ -45,6 +46,10 @@ LanguageSettingsPrivateDelegate::LanguageSettingsPrivateDelegate(
language_settings_private::OnSpellcheckDictionariesChanged::kEventName);
event_router->RegisterObserver(this,
language_settings_private::OnCustomDictionaryChanged::kEventName);
+ event_router->RegisterObserver(
+ this, language_settings_private::OnInputMethodAdded::kEventName);
+ event_router->RegisterObserver(
+ this, language_settings_private::OnInputMethodRemoved::kEventName);
// SpellcheckService cannot be created until Profile::DoFinalInit() has been
// called. http://crbug.com/171406
@@ -56,10 +61,14 @@ LanguageSettingsPrivateDelegate::LanguageSettingsPrivateDelegate(
GetPrefs());
StartOrStopListeningForSpellcheckChanges();
+#if defined(OS_CHROMEOS)
+ StartOrStopListeningForInputMethodChanges();
+#endif // defined(OS_CHROMEOS)
}
LanguageSettingsPrivateDelegate::~LanguageSettingsPrivateDelegate() {
DCHECK(!listening_spellcheck_);
+ DCHECK(!listening_input_method_);
pref_change_registrar_.RemoveAll();
notification_registrar_.RemoveAll();
}
@@ -101,6 +110,16 @@ void LanguageSettingsPrivateDelegate::Shutdown() {
RemoveDictionaryObservers();
listening_spellcheck_ = false;
}
+
+#if defined(OS_CHROMEOS)
+ if (listening_input_method_) {
+ auto* input_method_manager =
+ chromeos::input_method::InputMethodManager::Get();
+ if (input_method_manager)
+ input_method_manager->RemoveObserver(this);
+ listening_input_method_ = false;
+ }
+#endif // defined(OS_CHROMEOS)
}
void LanguageSettingsPrivateDelegate::OnListenerAdded(
@@ -111,13 +130,26 @@ void LanguageSettingsPrivateDelegate::OnListenerAdded(
details.event_name ==
language_settings_private::OnCustomDictionaryChanged::kEventName) {
StartOrStopListeningForSpellcheckChanges();
+ return;
+ }
+#if defined(OS_CHROMEOS)
+ if (details.event_name ==
+ language_settings_private::OnInputMethodAdded::kEventName ||
+ details.event_name ==
+ language_settings_private::OnInputMethodRemoved::kEventName) {
+ StartOrStopListeningForInputMethodChanges();
+ return;
}
+#endif // defined(OS_CHROMEOS)
}
void LanguageSettingsPrivateDelegate::OnListenerRemoved(
const EventListenerInfo& details) {
// Stop listening to events if there are no more listeners.
StartOrStopListeningForSpellcheckChanges();
+#if defined(OS_CHROMEOS)
+ StartOrStopListeningForInputMethodChanges();
+#endif // defined(OS_CHROMEOS)
}
void LanguageSettingsPrivateDelegate::Observe(
@@ -128,6 +160,37 @@ void LanguageSettingsPrivateDelegate::Observe(
StartOrStopListeningForSpellcheckChanges();
}
+#if defined(OS_CHROMEOS)
+void LanguageSettingsPrivateDelegate::InputMethodChanged(
+ chromeos::input_method::InputMethodManager* manager,
+ Profile* profile,
+ bool show_message) {
+ // Nothing to do.
+}
+
+void LanguageSettingsPrivateDelegate::OnInputMethodExtensionAdded(
+ const std::string& extension_id) {
+ std::unique_ptr<base::ListValue> args(
+ language_settings_private::OnInputMethodAdded::Create(extension_id));
+ std::unique_ptr<extensions::Event> extension_event(new extensions::Event(
+ events::LANGUAGE_SETTINGS_PRIVATE_ON_INPUT_METHOD_ADDED,
+ language_settings_private::OnInputMethodAdded::kEventName,
+ std::move(args)));
+ EventRouter::Get(context_)->BroadcastEvent(std::move(extension_event));
+}
+
+void LanguageSettingsPrivateDelegate::OnInputMethodExtensionRemoved(
+ const std::string& extension_id) {
+ std::unique_ptr<base::ListValue> args(
+ language_settings_private::OnInputMethodRemoved::Create(extension_id));
+ std::unique_ptr<extensions::Event> extension_event(new extensions::Event(
+ events::LANGUAGE_SETTINGS_PRIVATE_ON_INPUT_METHOD_REMOVED,
+ language_settings_private::OnInputMethodRemoved::kEventName,
+ std::move(args)));
+ EventRouter::Get(context_)->BroadcastEvent(std::move(extension_event));
+}
+#endif // defined(OS_CHROMEOS)
+
void LanguageSettingsPrivateDelegate::OnHunspellDictionaryInitialized(
const std::string& language) {
BroadcastDictionariesChangedEvent();
@@ -229,6 +292,29 @@ void LanguageSettingsPrivateDelegate::
listening_spellcheck_ = should_listen;
}
+#if defined(OS_CHROMEOS)
+void LanguageSettingsPrivateDelegate::
+ StartOrStopListeningForInputMethodChanges() {
+ EventRouter* event_router = EventRouter::Get(context_);
+ bool should_listen =
+ event_router->HasEventListener(
+ language_settings_private::OnInputMethodAdded::kEventName) ||
+ event_router->HasEventListener(
+ language_settings_private::OnInputMethodRemoved::kEventName);
+
+ auto* input_method_manager =
+ chromeos::input_method::InputMethodManager::Get();
+ if (input_method_manager) {
+ if (should_listen && !listening_input_method_)
+ input_method_manager->AddObserver(this);
+ else if (!should_listen && listening_input_method_)
+ input_method_manager->RemoveObserver(this);
+ }
+
+ listening_input_method_ = should_listen;
+}
+#endif // defined(OS_CHROMEOS)
+
void LanguageSettingsPrivateDelegate::RetryDownloadHunspellDictionary(
const std::string& language) {
for (const base::WeakPtr<SpellcheckHunspellDictionary> dictionary :
diff --git a/chromium/chrome/browser/extensions/api/language_settings_private/language_settings_private_delegate.h b/chromium/chrome/browser/extensions/api/language_settings_private/language_settings_private_delegate.h
index 873dec91a69..17098f43ce8 100644
--- a/chromium/chrome/browser/extensions/api/language_settings_private/language_settings_private_delegate.h
+++ b/chromium/chrome/browser/extensions/api/language_settings_private/language_settings_private_delegate.h
@@ -5,6 +5,7 @@
#ifndef CHROME_BROWSER_EXTENSIONS_API_LANGUAGE_SETTINGS_PRIVATE_LANGUAGE_SETTINGS_PRIVATE_DELEGATE_H_
#define CHROME_BROWSER_EXTENSIONS_API_LANGUAGE_SETTINGS_PRIVATE_LANGUAGE_SETTINGS_PRIVATE_DELEGATE_H_
+#include <string>
#include <vector>
#include "base/macros.h"
@@ -18,6 +19,10 @@
#include "content/public/browser/notification_registrar.h"
#include "extensions/browser/event_router.h"
+#if defined(OS_CHROMEOS)
+#include "ui/base/ime/chromeos/input_method_manager.h"
+#endif
+
namespace content {
class BrowserContext;
}
@@ -30,6 +35,9 @@ class LanguageSettingsPrivateDelegate
: public KeyedService,
public EventRouter::Observer,
public content::NotificationObserver,
+#if defined(OS_CHROMEOS)
+ public chromeos::input_method::InputMethodManager::Observer,
+#endif // defined(OS_CHROMEOS)
public SpellcheckHunspellDictionary::Observer,
public SpellcheckCustomDictionary::Observer {
public:
@@ -60,6 +68,15 @@ class LanguageSettingsPrivateDelegate
void OnListenerAdded(const EventListenerInfo& details) override;
void OnListenerRemoved(const EventListenerInfo& details) override;
+#if defined(OS_CHROMEOS)
+ // chromeos::input_method::InputMethodManager::Observer implementation.
+ void InputMethodChanged(chromeos::input_method::InputMethodManager* manager,
+ Profile* profile,
+ bool show_message) override;
+ void OnInputMethodExtensionAdded(const std::string& extension_id) override;
+ void OnInputMethodExtensionRemoved(const std::string& extension_id) override;
+#endif // defined(OS_CHROMEOS)
+
// SpellcheckHunspellDictionary::Observer implementation.
void OnHunspellDictionaryInitialized(const std::string& language) override;
void OnHunspellDictionaryDownloadBegin(const std::string& language) override;
@@ -88,6 +105,13 @@ class LanguageSettingsPrivateDelegate
// any observers.
void StartOrStopListeningForSpellcheckChanges();
+#if defined(OS_CHROMEOS)
+ // If there are any JavaScript listeners registered for input method events,
+ // ensures we are registered for change notifications. Otherwise, unregisters
+ // any observers.
+ void StartOrStopListeningForInputMethodChanges();
+#endif // defined(OS_CHROMEOS)
+
// Handles the preference for which languages should be used for spellcheck
// by resetting the dictionaries and broadcasting an event.
void OnSpellcheckDictionariesChanged();
@@ -110,6 +134,8 @@ class LanguageSettingsPrivateDelegate
// True if there are observers listening for spellcheck events.
bool listening_spellcheck_;
+ // True if there are observers listening for input method events.
+ bool listening_input_method_;
// True if the profile has finished initializing.
bool profile_added_;
diff --git a/chromium/chrome/browser/extensions/api/management/management_browsertest.cc b/chromium/chrome/browser/extensions/api/management/management_browsertest.cc
index 870c2eb71cb..24da4131ac6 100644
--- a/chromium/chrome/browser/extensions/api/management/management_browsertest.cc
+++ b/chromium/chrome/browser/extensions/api/management/management_browsertest.cc
@@ -11,7 +11,8 @@
#include "base/run_loop.h"
#include "base/stl_util.h"
#include "base/strings/stringprintf.h"
-#include "base/task_scheduler/post_task.h"
+#include "base/task/post_task.h"
+#include "base/test/bind_test_util.h"
#include "build/build_config.h"
#include "chrome/browser/extensions/extension_browsertest.h"
#include "chrome/browser/extensions/extension_management.h"
@@ -31,6 +32,7 @@
#include "content/public/browser/notification_service.h"
#include "content/public/browser/render_view_host.h"
#include "content/public/test/browser_test_utils.h"
+#include "content/public/test/url_loader_interceptor.h"
#include "extensions/browser/extension_host.h"
#include "extensions/browser/extension_prefs.h"
#include "extensions/browser/extension_registry.h"
@@ -343,18 +345,32 @@ IN_PROC_BROWSER_TEST_F(ExtensionManagementTest, MAYBE_AutoUpdate) {
basedir.AppendASCII("v2"), temp_dir.GetPath().AppendASCII("v2.crx"),
pem_path, base::FilePath());
- // Note: This interceptor gets requests on the IO thread.
- net::LocalHostTestURLRequestInterceptor interceptor(
- BrowserThread::GetTaskRunnerForThread(BrowserThread::IO),
- base::CreateTaskRunnerWithTraits(
- {base::MayBlock(), base::TaskPriority::BACKGROUND,
- base::TaskShutdownBehavior::SKIP_ON_SHUTDOWN}));
-
- interceptor.SetResponseIgnoreQuery(
- GURL("http://localhost/autoupdate/manifest"),
- basedir.AppendASCII("manifest_v2.xml"));
- interceptor.SetResponseIgnoreQuery(GURL("http://localhost/autoupdate/v2.crx"),
- v2_path);
+ content::URLLoaderInterceptor interceptor(base::BindLambdaForTesting(
+ [&](content::URLLoaderInterceptor::RequestParams* params) -> bool {
+ if (params->url_request.url.path() == "/autoupdate/v2.crx") {
+ content::URLLoaderInterceptor::WriteResponse(v2_path,
+ params->client.get());
+ return true;
+ }
+ if (params->url_request.url.path() == "/autoupdate/v3.crx") {
+ content::URLLoaderInterceptor::WriteResponse(
+ basedir.AppendASCII("v3.crx"), params->client.get());
+ return true;
+ }
+ if (params->url_request.url.path() == "/autoupdate/manifest") {
+ static bool first = true;
+ if (first) {
+ content::URLLoaderInterceptor::WriteResponse(
+ basedir.AppendASCII("manifest_v2.xml"), params->client.get());
+ first = false;
+ } else {
+ content::URLLoaderInterceptor::WriteResponse(
+ basedir.AppendASCII("manifest_v3.xml"), params->client.get());
+ }
+ return true;
+ }
+ return false;
+ }));
// Install version 1 of the extension.
ExtensionTestMessageListener listener1("v1 installed", false);
@@ -394,11 +410,6 @@ IN_PROC_BROWSER_TEST_F(ExtensionManagementTest, MAYBE_AutoUpdate) {
// Now try doing an update to version 3, which has been incorrectly
// signed. This should fail.
- interceptor.SetResponseIgnoreQuery(
- GURL("http://localhost/autoupdate/manifest"),
- basedir.AppendASCII("manifest_v3.xml"));
- interceptor.SetResponseIgnoreQuery(GURL("http://localhost/autoupdate/v3.crx"),
- basedir.AppendASCII("v3.crx"));
extensions::ExtensionUpdater::CheckParams params2;
params2.callback = base::BindOnce(&NotificationListener::OnFinished,
@@ -447,18 +458,20 @@ IN_PROC_BROWSER_TEST_F(ExtensionManagementTest,
basedir.AppendASCII("v2"), temp_dir.GetPath().AppendASCII("v2.crx"),
pem_path, base::FilePath());
- // Note: This interceptor gets requests on the IO thread.
- net::LocalHostTestURLRequestInterceptor interceptor(
- BrowserThread::GetTaskRunnerForThread(BrowserThread::IO),
- base::CreateTaskRunnerWithTraits(
- {base::MayBlock(), base::TaskPriority::BACKGROUND,
- base::TaskShutdownBehavior::SKIP_ON_SHUTDOWN}));
-
- interceptor.SetResponseIgnoreQuery(
- GURL("http://localhost/autoupdate/manifest"),
- basedir.AppendASCII("manifest_v2.xml"));
- interceptor.SetResponseIgnoreQuery(GURL("http://localhost/autoupdate/v2.crx"),
- v2_path);
+ content::URLLoaderInterceptor interceptor(base::BindLambdaForTesting(
+ [&](content::URLLoaderInterceptor::RequestParams* params) -> bool {
+ if (params->url_request.url.path() == "/autoupdate/manifest") {
+ content::URLLoaderInterceptor::WriteResponse(
+ basedir.AppendASCII("manifest_v2.xml"), params->client.get());
+ return true;
+ }
+ if (params->url_request.url.path() == "/autoupdate/v2.crx") {
+ content::URLLoaderInterceptor::WriteResponse(v2_path,
+ params->client.get());
+ return true;
+ }
+ return false;
+ }));
// Install version 1 of the extension.
ExtensionTestMessageListener listener1("v1 installed", false);
@@ -523,18 +536,20 @@ IN_PROC_BROWSER_TEST_F(ExtensionManagementTest, ExternalUrlUpdate) {
basedir.AppendASCII("v2"), temp_dir.GetPath().AppendASCII("v2.crx"),
pem_path, base::FilePath());
- // Note: This interceptor gets requests on the IO thread.
- net::LocalHostTestURLRequestInterceptor interceptor(
- BrowserThread::GetTaskRunnerForThread(BrowserThread::IO),
- base::CreateTaskRunnerWithTraits(
- {base::MayBlock(), base::TaskPriority::BACKGROUND,
- base::TaskShutdownBehavior::SKIP_ON_SHUTDOWN}));
-
- interceptor.SetResponseIgnoreQuery(
- GURL("http://localhost/autoupdate/manifest"),
- basedir.AppendASCII("manifest_v2.xml"));
- interceptor.SetResponseIgnoreQuery(GURL("http://localhost/autoupdate/v2.crx"),
- v2_path);
+ content::URLLoaderInterceptor interceptor(base::BindLambdaForTesting(
+ [&](content::URLLoaderInterceptor::RequestParams* params) -> bool {
+ if (params->url_request.url.path() == "/autoupdate/manifest") {
+ content::URLLoaderInterceptor::WriteResponse(
+ basedir.AppendASCII("manifest_v2.xml"), params->client.get());
+ return true;
+ }
+ if (params->url_request.url.path() == "/autoupdate/v2.crx") {
+ content::URLLoaderInterceptor::WriteResponse(v2_path,
+ params->client.get());
+ return true;
+ }
+ return false;
+ }));
ExtensionRegistry* registry = ExtensionRegistry::Get(browser()->profile());
const size_t size_before = registry->enabled_extensions().size();
@@ -630,18 +645,20 @@ IN_PROC_BROWSER_TEST_F(ExtensionManagementTest, ExternalPolicyRefresh) {
basedir.AppendASCII("v2"), temp_dir.GetPath().AppendASCII("v2.crx"),
pem_path, base::FilePath());
- // Note: This interceptor gets requests on the IO thread.
- net::LocalHostTestURLRequestInterceptor interceptor(
- BrowserThread::GetTaskRunnerForThread(BrowserThread::IO),
- base::CreateTaskRunnerWithTraits(
- {base::MayBlock(), base::TaskPriority::BACKGROUND,
- base::TaskShutdownBehavior::SKIP_ON_SHUTDOWN}));
-
- interceptor.SetResponseIgnoreQuery(
- GURL("http://localhost/autoupdate/manifest"),
- basedir.AppendASCII("manifest_v2.xml"));
- interceptor.SetResponseIgnoreQuery(GURL("http://localhost/autoupdate/v2.crx"),
- v2_path);
+ content::URLLoaderInterceptor interceptor(base::BindLambdaForTesting(
+ [&](content::URLLoaderInterceptor::RequestParams* params) -> bool {
+ if (params->url_request.url.path() == "/autoupdate/manifest") {
+ content::URLLoaderInterceptor::WriteResponse(
+ basedir.AppendASCII("manifest_v2.xml"), params->client.get());
+ return true;
+ }
+ if (params->url_request.url.path() == "/autoupdate/v2.crx") {
+ content::URLLoaderInterceptor::WriteResponse(v2_path,
+ params->client.get());
+ return true;
+ }
+ return false;
+ }));
ExtensionRegistry* registry = ExtensionRegistry::Get(browser()->profile());
const size_t size_before = registry->enabled_extensions().size();
@@ -722,18 +739,20 @@ IN_PROC_BROWSER_TEST_F(ExtensionManagementTest,
basedir.AppendASCII("v2"), temp_dir.GetPath().AppendASCII("v2.crx"),
pem_path, base::FilePath());
- // Note: This interceptor gets requests on the IO thread.
- net::LocalHostTestURLRequestInterceptor interceptor(
- BrowserThread::GetTaskRunnerForThread(BrowserThread::IO),
- base::CreateTaskRunnerWithTraits(
- {base::MayBlock(), base::TaskPriority::BACKGROUND,
- base::TaskShutdownBehavior::SKIP_ON_SHUTDOWN}));
-
- interceptor.SetResponseIgnoreQuery(
- GURL("http://localhost/autoupdate/manifest"),
- basedir.AppendASCII("manifest_v2.xml"));
- interceptor.SetResponseIgnoreQuery(GURL("http://localhost/autoupdate/v2.crx"),
- v2_path);
+ content::URLLoaderInterceptor interceptor(base::BindLambdaForTesting(
+ [&](content::URLLoaderInterceptor::RequestParams* params) -> bool {
+ if (params->url_request.url.path() == "/autoupdate/manifest") {
+ content::URLLoaderInterceptor::WriteResponse(
+ basedir.AppendASCII("manifest_v2.xml"), params->client.get());
+ return true;
+ }
+ if (params->url_request.url.path() == "/autoupdate/v2.crx") {
+ content::URLLoaderInterceptor::WriteResponse(v2_path,
+ params->client.get());
+ return true;
+ }
+ return false;
+ }));
// Check that the policy is initially empty.
ASSERT_TRUE(extensions::ExtensionManagementFactory::GetForBrowserContext(
diff --git a/chromium/chrome/browser/extensions/api/mdns/mdns_api.cc b/chromium/chrome/browser/extensions/api/mdns/mdns_api.cc
index 2bf04ff08ba..e27d9f13054 100644
--- a/chromium/chrome/browser/extensions/api/mdns/mdns_api.cc
+++ b/chromium/chrome/browser/extensions/api/mdns/mdns_api.cc
@@ -74,7 +74,7 @@ void MDnsAPI::SetDnsSdRegistryForTesting(DnsSdRegistry* dns_sd_registry) {
void MDnsAPI::ForceDiscovery() {
DCHECK(thread_checker_.CalledOnValidThread());
DnsSdRegistry* registry = dns_sd_registry();
- return registry->ForceDiscovery();
+ return registry->ResetAndDiscover();
}
DnsSdRegistry* MDnsAPI::dns_sd_registry() {
diff --git a/chromium/chrome/browser/extensions/api/mdns/mdns_apitest.cc b/chromium/chrome/browser/extensions/api/mdns/mdns_apitest.cc
index 7751cefc276..495366644a2 100644
--- a/chromium/chrome/browser/extensions/api/mdns/mdns_apitest.cc
+++ b/chromium/chrome/browser/extensions/api/mdns/mdns_apitest.cc
@@ -100,7 +100,7 @@ IN_PROC_BROWSER_TEST_F(MDnsAPITest, MAYBE_ForceDiscovery) {
EXPECT_CALL(*dns_sd_registry_, RegisterDnsSdListener(service_type)).Times(1);
EXPECT_CALL(*dns_sd_registry_, UnregisterDnsSdListener(service_type))
.Times(1);
- EXPECT_CALL(*dns_sd_registry_, ForceDiscovery()).Times(1);
+ EXPECT_CALL(*dns_sd_registry_, ResetAndDiscover()).Times(1);
EXPECT_CALL(*dns_sd_registry_,
RemoveObserver(A<DnsSdRegistry::DnsSdObserver*>()))
.Times(1);
diff --git a/chromium/chrome/browser/extensions/api/messaging/DEPS b/chromium/chrome/browser/extensions/api/messaging/DEPS
deleted file mode 100644
index 06590ef7e73..00000000000
--- a/chromium/chrome/browser/extensions/api/messaging/DEPS
+++ /dev/null
@@ -1,8 +0,0 @@
-specific_include_rules = {
- "native_message_host_chromeos.cc": [
- # TODO(erg): This allows us to switch between mus and classic ash/ozone as
- # targets. It should be removed when support for classic ash is removed;
- # which means that remoting never touches ozone.
- "+ui/ozone/public/ozone_platform.h",
- ]
-}
diff --git a/chromium/chrome/browser/extensions/api/messaging/native_message_host_chromeos.cc b/chromium/chrome/browser/extensions/api/messaging/native_message_host_chromeos.cc
index 3c9932703ad..fcc93f51bfa 100644
--- a/chromium/chrome/browser/extensions/api/messaging/native_message_host_chromeos.cc
+++ b/chromium/chrome/browser/extensions/api/messaging/native_message_host_chromeos.cc
@@ -12,12 +12,9 @@
#include "base/bind_helpers.h"
#include "base/json/json_reader.h"
#include "base/json/json_writer.h"
-#include "base/lazy_instance.h"
#include "base/location.h"
#include "base/macros.h"
#include "base/single_thread_task_runner.h"
-#include "base/task_scheduler/post_task.h"
-#include "base/task_scheduler/task_traits.h"
#include "base/threading/thread_task_runner_handle.h"
#include "base/values.h"
#include "chrome/browser/browser_process.h"
@@ -26,18 +23,10 @@
#include "extensions/common/constants.h"
#include "extensions/common/url_pattern.h"
#include "net/url_request/url_request_context_getter.h"
-#include "remoting/base/auto_thread_task_runner.h"
-#include "remoting/host/chromoting_host_context.h"
-#include "remoting/host/it2me/it2me_native_messaging_host.h"
-#include "remoting/host/policy_watcher.h"
-#include "ui/events/system_input_injector.h"
+#include "remoting/host/it2me/it2me_native_messaging_host_chromeos.h"
#include "ui/gfx/native_widget_types.h"
#include "url/gurl.h"
-#if defined(USE_OZONE)
-#include "ui/ozone/public/ozone_platform.h"
-#endif
-
namespace extensions {
namespace {
@@ -102,52 +91,14 @@ struct BuiltInHost {
std::unique_ptr<NativeMessageHost> (*create_function)();
};
-#if defined(USE_OZONE)
-class OzoneSystemInputInjectorAdaptor : public ui::SystemInputInjectorFactory {
- public:
- std::unique_ptr<ui::SystemInputInjector> CreateSystemInputInjector()
- override {
- return ui::OzonePlatform::GetInstance()->CreateSystemInputInjector();
- }
-};
-
-base::LazyInstance<OzoneSystemInputInjectorAdaptor>::Leaky
- g_ozone_system_input_injector_adaptor = LAZY_INSTANCE_INITIALIZER;
-#endif
-
-ui::SystemInputInjectorFactory* GetInputInjector() {
- ui::SystemInputInjectorFactory* system = ui::GetSystemInputInjectorFactory();
- if (system)
- return system;
-
-#if defined(USE_OZONE)
- return g_ozone_system_input_injector_adaptor.Pointer();
-#endif
-
- return nullptr;
-}
-
std::unique_ptr<NativeMessageHost> CreateIt2MeHost() {
- std::unique_ptr<remoting::It2MeHostFactory> host_factory(
- new remoting::It2MeHostFactory());
- std::unique_ptr<remoting::ChromotingHostContext> context =
- remoting::ChromotingHostContext::CreateForChromeOS(
- base::WrapRefCounted(g_browser_process->system_request_context()),
- content::BrowserThread::GetTaskRunnerForThread(
- content::BrowserThread::IO),
- content::BrowserThread::GetTaskRunnerForThread(
- content::BrowserThread::UI),
- base::CreateSingleThreadTaskRunnerWithTraits(
- {base::MayBlock(), base::TaskPriority::BACKGROUND}),
- GetInputInjector());
- std::unique_ptr<remoting::PolicyWatcher> policy_watcher =
- remoting::PolicyWatcher::CreateWithPolicyService(
- g_browser_process->policy_service());
- std::unique_ptr<NativeMessageHost> host(
- new remoting::It2MeNativeMessagingHost(
- /*needs_elevation=*/false, std::move(policy_watcher),
- std::move(context), std::move(host_factory)));
- return host;
+ return remoting::CreateIt2MeNativeMessagingHostForChromeOS(
+ g_browser_process->system_request_context(),
+ content::BrowserThread::GetTaskRunnerForThread(
+ content::BrowserThread::IO),
+ content::BrowserThread::GetTaskRunnerForThread(
+ content::BrowserThread::UI),
+ g_browser_process->policy_service());
}
// If you modify the list of allowed_origins, don't forget to update
diff --git a/chromium/chrome/browser/extensions/api/messaging/native_message_process_host.cc b/chromium/chrome/browser/extensions/api/messaging/native_message_process_host.cc
index 9b8591d4d4e..274257d18bf 100644
--- a/chromium/chrome/browser/extensions/api/messaging/native_message_process_host.cc
+++ b/chromium/chrome/browser/extensions/api/messaging/native_message_process_host.cc
@@ -12,7 +12,7 @@
#include "base/files/file_path.h"
#include "base/logging.h"
#include "base/process/kill.h"
-#include "base/task_scheduler/post_task.h"
+#include "base/task/post_task.h"
#include "build/build_config.h"
#include "chrome/browser/extensions/api/messaging/native_messaging_host_manifest.h"
#include "chrome/browser/extensions/api/messaging/native_process_launcher.h"
@@ -71,7 +71,7 @@ NativeMessageProcessHost::~NativeMessageProcessHost() {
// block, so we have to post a task on the blocking pool.
#if defined(OS_MACOSX)
base::PostTaskWithTraits(
- FROM_HERE, {base::MayBlock(), base::TaskPriority::BACKGROUND},
+ FROM_HERE, {base::MayBlock(), base::TaskPriority::BEST_EFFORT},
base::BindOnce(&base::EnsureProcessTerminated, Passed(&process_)));
#else
base::EnsureProcessTerminated(std::move(process_));
@@ -298,8 +298,11 @@ void NativeMessageProcessHost::DoWrite() {
!current_write_buffer_->BytesRemaining()) {
if (write_queue_.empty())
return;
- current_write_buffer_ = new net::DrainableIOBuffer(
- write_queue_.front().get(), write_queue_.front()->size());
+ scoped_refptr<net::IOBufferWithSize> buffer =
+ std::move(write_queue_.front());
+ int buffer_size = buffer->size();
+ current_write_buffer_ = base::MakeRefCounted<net::DrainableIOBuffer>(
+ std::move(buffer), buffer_size);
write_queue_.pop();
}
diff --git a/chromium/chrome/browser/extensions/api/messaging/native_process_launcher.cc b/chromium/chrome/browser/extensions/api/messaging/native_process_launcher.cc
index 0d36259d062..eda727af052 100644
--- a/chromium/chrome/browser/extensions/api/messaging/native_process_launcher.cc
+++ b/chromium/chrome/browser/extensions/api/messaging/native_process_launcher.cc
@@ -15,7 +15,7 @@
#include "base/macros.h"
#include "base/memory/ref_counted.h"
#include "base/strings/stringprintf.h"
-#include "base/task_scheduler/post_task.h"
+#include "base/task/post_task.h"
#include "build/build_config.h"
#include "chrome/browser/extensions/api/messaging/native_messaging_host_manifest.h"
#include "chrome/common/chrome_paths.h"
diff --git a/chromium/chrome/browser/extensions/api/music_manager_private/device_id.h b/chromium/chrome/browser/extensions/api/music_manager_private/device_id.h
index 7a1cf5dafef..623a00b6d4b 100644
--- a/chromium/chrome/browser/extensions/api/music_manager_private/device_id.h
+++ b/chromium/chrome/browser/extensions/api/music_manager_private/device_id.h
@@ -10,7 +10,7 @@
#include <string>
#include "base/bind.h"
-#include "base/task_scheduler/task_traits.h"
+#include "base/task/task_traits.h"
namespace extensions {
namespace api {
diff --git a/chromium/chrome/browser/extensions/api/music_manager_private/device_id_linux.cc b/chromium/chrome/browser/extensions/api/music_manager_private/device_id_linux.cc
index ddc0c9a1214..a31cba28ced 100644
--- a/chromium/chrome/browser/extensions/api/music_manager_private/device_id_linux.cc
+++ b/chromium/chrome/browser/extensions/api/music_manager_private/device_id_linux.cc
@@ -20,7 +20,7 @@
#include "base/macros.h"
#include "base/strings/string_number_conversions.h"
#include "base/strings/string_util.h"
-#include "base/task_scheduler/post_task.h"
+#include "base/task/post_task.h"
#include "base/threading/thread_restrictions.h"
#include "content/public/browser/browser_thread.h"
diff --git a/chromium/chrome/browser/extensions/api/music_manager_private/device_id_mac.cc b/chromium/chrome/browser/extensions/api/music_manager_private/device_id_mac.cc
index 300e1bb2134..2081b232621 100644
--- a/chromium/chrome/browser/extensions/api/music_manager_private/device_id_mac.cc
+++ b/chromium/chrome/browser/extensions/api/music_manager_private/device_id_mac.cc
@@ -21,7 +21,7 @@
#include "base/strings/string_number_conversions.h"
#include "base/strings/string_util.h"
#include "base/strings/sys_string_conversions.h"
-#include "base/task_scheduler/post_task.h"
+#include "base/task/post_task.h"
#include "base/threading/thread_restrictions.h"
#include "content/public/browser/browser_thread.h"
diff --git a/chromium/chrome/browser/extensions/api/music_manager_private/device_id_win.cc b/chromium/chrome/browser/extensions/api/music_manager_private/device_id_win.cc
index 2b49d9a9f79..151fa8fdf22 100644
--- a/chromium/chrome/browser/extensions/api/music_manager_private/device_id_win.cc
+++ b/chromium/chrome/browser/extensions/api/music_manager_private/device_id_win.cc
@@ -22,7 +22,7 @@
#include "base/scoped_native_library.h"
#include "base/strings/string_number_conversions.h"
#include "base/strings/string_util.h"
-#include "base/task_scheduler/post_task.h"
+#include "base/task/post_task.h"
#include "base/threading/thread_restrictions.h"
#include "base/win/windows_version.h"
#include "content/public/browser/browser_thread.h"
diff --git a/chromium/chrome/browser/extensions/api/networking_cast_private/chrome_networking_cast_private_delegate.cc b/chromium/chrome/browser/extensions/api/networking_cast_private/chrome_networking_cast_private_delegate.cc
index 508de031a40..1c1d786f10c 100644
--- a/chromium/chrome/browser/extensions/api/networking_cast_private/chrome_networking_cast_private_delegate.cc
+++ b/chromium/chrome/browser/extensions/api/networking_cast_private/chrome_networking_cast_private_delegate.cc
@@ -13,7 +13,7 @@
#include "base/sequenced_task_runner.h"
#include "base/strings/string_number_conversions.h"
#include "base/strings/string_util.h"
-#include "base/task_scheduler/post_task.h"
+#include "base/task/post_task.h"
#include "base/threading/thread_task_runner_handle.h"
#include "chrome/browser/extensions/api/networking_private/networking_private_credentials_getter.h"
#include "chrome/browser/extensions/api/networking_private/networking_private_crypto.h"
diff --git a/chromium/chrome/browser/extensions/api/networking_private/DEPS b/chromium/chrome/browser/extensions/api/networking_private/DEPS
index a070d53ba99..d6abddad069 100644
--- a/chromium/chrome/browser/extensions/api/networking_private/DEPS
+++ b/chromium/chrome/browser/extensions/api/networking_private/DEPS
@@ -1,5 +1,3 @@
include_rules = [
- "+components/onc",
- "+components/wifi",
"+dbus",
]
diff --git a/chromium/chrome/browser/extensions/api/networking_private/networking_private_chromeos_apitest.cc b/chromium/chrome/browser/extensions/api/networking_private/networking_private_chromeos_apitest.cc
index 475010dec10..83532ae924b 100644
--- a/chromium/chrome/browser/extensions/api/networking_private/networking_private_chromeos_apitest.cc
+++ b/chromium/chrome/browser/extensions/api/networking_private/networking_private_chromeos_apitest.cc
@@ -220,10 +220,9 @@ class NetworkingPrivateChromeOSApiTest : public extensions::ExtensionApiTest {
// TODO(pneubeck): Remove the following hack, once the NetworkingPrivateAPI
// uses the ProfileHelper to obtain the userhash crbug/238623.
- const cryptohome::Identification login_user =
- cryptohome::Identification::FromString(
- user_manager::CanonicalizeUserID(command_line->GetSwitchValueNative(
- chromeos::switches::kLoginUser)));
+ cryptohome::AccountIdentifier login_user;
+ login_user.set_account_id(user_manager::CanonicalizeUserID(
+ command_line->GetSwitchValueNative(chromeos::switches::kLoginUser)));
const std::string sanitized_user =
CryptohomeClient::GetStubSanitizedUsername(login_user);
command_line->AppendSwitchASCII(chromeos::switches::kLoginProfile,
@@ -236,7 +235,7 @@ class NetworkingPrivateChromeOSApiTest : public extensions::ExtensionApiTest {
CHECK(user);
std::string userhash;
DBusThreadManager::Get()->GetCryptohomeClient()->GetSanitizedUsername(
- cryptohome::Identification(user->GetAccountId()),
+ cryptohome::CreateAccountIdentifierFromAccountId(user->GetAccountId()),
base::BindOnce(
[](std::string* out, base::Optional<std::string> result) {
CHECK(result.has_value());
@@ -424,6 +423,9 @@ class NetworkingPrivateChromeOSApiTest : public extensions::ExtensionApiTest {
kWifi1ServicePath, shill::kConnectableProperty, base::Value(true));
service_test_->SetServiceProperty(kWifi1ServicePath, shill::kDeviceProperty,
base::Value(kWifiDevicePath));
+ service_test_->SetServiceProperty(
+ kWifi1ServicePath, shill::kTetheringProperty,
+ base::Value(shill::kTetheringNotDetectedState));
base::DictionaryValue static_ipconfig;
static_ipconfig.SetKey(shill::kAddressProperty, base::Value("1.2.3.4"));
service_test_->SetServiceProperty(
@@ -445,6 +447,9 @@ class NetworkingPrivateChromeOSApiTest : public extensions::ExtensionApiTest {
kWifi2ServicePath, shill::kSignalStrengthProperty, base::Value(80));
service_test_->SetServiceProperty(
kWifi2ServicePath, shill::kConnectableProperty, base::Value(true));
+ service_test_->SetServiceProperty(
+ kWifi2ServicePath, shill::kTetheringProperty,
+ base::Value(shill::kTetheringNotDetectedState));
AddService("stub_wimax", "wimax", shill::kTypeWimax, shill::kStateOnline);
service_test_->SetServiceProperty(
diff --git a/chromium/chrome/browser/extensions/api/networking_private/networking_private_credentials_getter_browsertest.cc b/chromium/chrome/browser/extensions/api/networking_private/networking_private_credentials_getter_browsertest.cc
index 9ab7402b18d..f01292fcec9 100644
--- a/chromium/chrome/browser/extensions/api/networking_private/networking_private_credentials_getter_browsertest.cc
+++ b/chromium/chrome/browser/extensions/api/networking_private/networking_private_credentials_getter_browsertest.cc
@@ -6,7 +6,7 @@
#include "base/callback.h"
#include "base/macros.h"
#include "base/run_loop.h"
-#include "base/task_scheduler/post_task.h"
+#include "base/task/post_task.h"
#include "chrome/browser/extensions/api/networking_private/networking_private_credentials_getter.h"
#include "chrome/services/wifi_util_win/public/mojom/wifi_credentials_getter.mojom.h"
#include "chrome/test/base/in_process_browser_test.h"
@@ -29,7 +29,7 @@ class NetworkingPrivateCredentialsGetterTest : public InProcessBrowserTest {
done_called_ = false;
base::PostTaskWithTraits(
- FROM_HERE, {base::MayBlock(), base::TaskPriority::BACKGROUND},
+ FROM_HERE, {base::MayBlock(), base::TaskPriority::BEST_EFFORT},
base::Bind(&NetworkingPrivateCredentialsGetterTest::GetCredentials,
base::Unretained(this)));
run_loop.Run();
diff --git a/chromium/chrome/browser/extensions/api/notifications/notifications_api.cc b/chromium/chrome/browser/extensions/api/notifications/notifications_api.cc
index e62669225cc..66cfea4b410 100644
--- a/chromium/chrome/browser/extensions/api/notifications/notifications_api.cc
+++ b/chromium/chrome/browser/extensions/api/notifications/notifications_api.cc
@@ -152,7 +152,7 @@ bool NotificationBitmapToGfxImage(
return false;
// Ensure we have rgba data.
- std::vector<char>* rgba_data = notification_bitmap.data.get();
+ std::vector<uint8_t>* rgba_data = notification_bitmap.data.get();
if (!rgba_data)
return false;
@@ -172,7 +172,7 @@ bool NotificationBitmapToGfxImage(
return false;
uint32_t* pixels = bitmap.getAddr32(0, 0);
- const char* c_rgba_data = rgba_data->data();
+ const uint8_t* c_rgba_data = rgba_data->data();
for (size_t t = 0; t < rgba_area; ++t) {
// |c_rgba_data| is RGBA, pixels is ARGB.
@@ -287,6 +287,9 @@ bool NotificationsApiFunction::CreateNotification(
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 @@ bool NotificationsApiFunction::UpdateNotification(
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/chromium/chrome/browser/extensions/api/notifications/notifications_apitest.cc b/chromium/chrome/browser/extensions/api/notifications/notifications_apitest.cc
index 5a4c13177f1..d5974129a30 100644
--- a/chromium/chrome/browser/extensions/api/notifications/notifications_apitest.cc
+++ b/chromium/chrome/browser/extensions/api/notifications/notifications_apitest.cc
@@ -292,6 +292,7 @@ IN_PROC_BROWSER_TEST_F(NotificationsApiTest, TestPartialUpdate) {
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/chromium/chrome/browser/extensions/api/page_capture/page_capture_api.cc b/chromium/chrome/browser/extensions/api/page_capture/page_capture_api.cc
index c64ad578f6d..e328205b19c 100644
--- a/chromium/chrome/browser/extensions/api/page_capture/page_capture_api.cc
+++ b/chromium/chrome/browser/extensions/api/page_capture/page_capture_api.cc
@@ -10,7 +10,7 @@
#include "base/bind.h"
#include "base/bind_helpers.h"
#include "base/files/file_util.h"
-#include "base/task_scheduler/post_task.h"
+#include "base/task/post_task.h"
#include "base/threading/thread_restrictions.h"
#include "chrome/browser/browser_process.h"
#include "chrome/browser/extensions/extension_tab_util.h"
@@ -95,7 +95,7 @@ bool PageCaptureSaveAsMHTMLFunction::RunAsync() {
// time, we show the user a dialog where they can choose whether to allow the
// extension access to the API.
#if defined(OS_CHROMEOS)
- if (profiles::IsPublicSession()) {
+ if (profiles::ArePublicSessionRestrictionsEnabled()) {
WebContents* web_contents = GetWebContents();
if (!web_contents) {
ReturnFailure(kTabClosedError);
diff --git a/chromium/chrome/browser/extensions/api/platform_keys/platform_keys_api.cc b/chromium/chrome/browser/extensions/api/platform_keys/platform_keys_api.cc
index 3cfa9e91a8b..2983149f56b 100644
--- a/chromium/chrome/browser/extensions/api/platform_keys/platform_keys_api.cc
+++ b/chromium/chrome/browser/extensions/api/platform_keys/platform_keys_api.cc
@@ -129,7 +129,7 @@ PlatformKeysInternalGetPublicKeyFunction::Run() {
api_pki::GetPublicKey::Params::Create(*args_));
EXTENSION_FUNCTION_VALIDATE(params);
- const std::vector<char>& cert_der = params->certificate;
+ const std::vector<uint8_t>& cert_der = params->certificate;
if (cert_der.empty())
return RespondNow(Error(platform_keys::kErrorInvalidX509Cert));
// Allow UTF-8 inside PrintableStrings in client certificates. See
@@ -138,7 +138,8 @@ PlatformKeysInternalGetPublicKeyFunction::Run() {
options.printable_string_is_utf8 = true;
scoped_refptr<net::X509Certificate> cert_x509 =
net::X509Certificate::CreateFromBytesUnsafeOptions(
- cert_der.data(), cert_der.size(), options);
+ reinterpret_cast<const char*>(cert_der.data()), cert_der.size(),
+ options);
if (!cert_x509)
return RespondNow(Error(platform_keys::kErrorInvalidX509Cert));
@@ -163,8 +164,8 @@ PlatformKeysInternalGetPublicKeyFunction::Run() {
&algorithm.additional_properties);
return RespondNow(ArgumentList(api_pki::GetPublicKey::Results::Create(
- std::vector<char>(key_info.public_key_spki_der.begin(),
- key_info.public_key_spki_der.end()),
+ std::vector<uint8_t>(key_info.public_key_spki_der.begin(),
+ key_info.public_key_spki_der.end()),
algorithm)));
}
@@ -184,7 +185,7 @@ PlatformKeysInternalSelectClientCertificatesFunction::Run() {
DCHECK(service);
chromeos::platform_keys::ClientCertificateRequest request;
- for (const std::vector<char>& cert_authority :
+ for (const std::vector<uint8_t>& cert_authority :
params->details.request.certificate_authorities) {
request.certificate_authorities.push_back(
std::string(cert_authority.begin(), cert_authority.end()));
@@ -208,7 +209,7 @@ PlatformKeysInternalSelectClientCertificatesFunction::Run() {
std::unique_ptr<net::CertificateList> client_certs;
if (params->details.client_certs) {
client_certs.reset(new net::CertificateList);
- for (const std::vector<char>& client_cert_der :
+ for (const std::vector<uint8_t>& client_cert_der :
*params->details.client_certs) {
if (client_cert_der.empty())
return RespondNow(Error(platform_keys::kErrorInvalidX509Cert));
@@ -218,7 +219,8 @@ PlatformKeysInternalSelectClientCertificatesFunction::Run() {
options.printable_string_is_utf8 = true;
scoped_refptr<net::X509Certificate> client_cert_x509 =
net::X509Certificate::CreateFromBytesUnsafeOptions(
- client_cert_der.data(), client_cert_der.size(), options);
+ reinterpret_cast<const char*>(client_cert_der.data()),
+ client_cert_der.size(), options);
if (!client_cert_x509)
return RespondNow(Error(platform_keys::kErrorInvalidX509Cert));
client_certs->push_back(client_cert_x509);
@@ -344,7 +346,7 @@ void PlatformKeysInternalSignFunction::OnSigned(
if (error_message.empty())
Respond(ArgumentList(api_pki::Sign::Results::Create(
- std::vector<char>(signature.begin(), signature.end()))));
+ std::vector<uint8_t>(signature.begin(), signature.end()))));
else
Respond(Error(error_message));
}
diff --git a/chromium/chrome/browser/extensions/api/platform_keys/platform_keys_test_base.cc b/chromium/chrome/browser/extensions/api/platform_keys/platform_keys_test_base.cc
index 24934f6a747..c64afa4782c 100644
--- a/chromium/chrome/browser/extensions/api/platform_keys/platform_keys_test_base.cc
+++ b/chromium/chrome/browser/extensions/api/platform_keys/platform_keys_test_base.cc
@@ -34,9 +34,6 @@
const char kAffiliationID[] = "some-affiliation-id";
const char kTestUserinfoToken[] = "fake-userinfo-token";
-using policy::affiliation_test_helper::kEnterpriseUserEmail;
-using policy::affiliation_test_helper::kEnterpriseUserGaiaId;
-
PlatformKeysTestBase::PlatformKeysTestBase(
SystemTokenStatus system_token_status,
EnrollmentStatus enrollment_status,
@@ -44,8 +41,9 @@ PlatformKeysTestBase::PlatformKeysTestBase(
: system_token_status_(system_token_status),
enrollment_status_(enrollment_status),
user_status_(user_status),
- account_id_(AccountId::FromUserEmailGaiaId(kEnterpriseUserEmail,
- kEnterpriseUserGaiaId)) {
+ account_id_(AccountId::FromUserEmailGaiaId(
+ policy::AffiliationTestHelper::kEnterpriseUserEmail,
+ policy::AffiliationTestHelper::kEnterpriseUserGaiaId)) {
// Command line should not be tweaked as if user is already logged in.
set_chromeos_user_ = false;
// We log in without running browser.
@@ -78,7 +76,7 @@ void PlatformKeysTestBase::SetUp() {
void PlatformKeysTestBase::SetUpCommandLine(base::CommandLine* command_line) {
extensions::ExtensionApiTest::SetUpCommandLine(command_line);
- policy::affiliation_test_helper::AppendCommandLineSwitchesForLoginManager(
+ policy::AffiliationTestHelper::AppendCommandLineSwitchesForLoginManager(
command_line);
const GURL gaia_url = gaia_https_forwarder_.GetURLForSSLHost(std::string());
@@ -99,21 +97,23 @@ void PlatformKeysTestBase::SetUpInProcessBrowserTestFixture() {
std::unique_ptr<chromeos::SessionManagerClient>(
fake_session_manager_client));
+ policy::AffiliationTestHelper affiliation_helper =
+ policy::AffiliationTestHelper::CreateForCloud(
+ fake_session_manager_client);
+
if (enrollment_status() == EnrollmentStatus::ENROLLED) {
std::set<std::string> device_affiliation_ids;
device_affiliation_ids.insert(kAffiliationID);
- policy::affiliation_test_helper::SetDeviceAffiliationID(
- &device_policy_test_helper_, fake_session_manager_client,
- device_affiliation_ids);
+ ASSERT_NO_FATAL_FAILURE(affiliation_helper.SetDeviceAffiliationIDs(
+ &device_policy_test_helper_, device_affiliation_ids));
}
if (user_status() == UserStatus::MANAGED_AFFILIATED_DOMAIN) {
std::set<std::string> user_affiliation_ids;
user_affiliation_ids.insert(kAffiliationID);
policy::UserPolicyBuilder user_policy;
- policy::affiliation_test_helper::SetUserAffiliationIDs(
- &user_policy, fake_session_manager_client, account_id_,
- user_affiliation_ids);
+ ASSERT_NO_FATAL_FAILURE(affiliation_helper.SetUserAffiliationIDs(
+ &user_policy, account_id_, user_affiliation_ids));
}
EXPECT_CALL(mock_policy_provider_, IsInitializationComplete(testing::_))
@@ -135,7 +135,7 @@ void PlatformKeysTestBase::SetUpOnMainThread() {
token_info.audience = GaiaUrls::GetInstance()->oauth2_chrome_client_id();
token_info.token = kTestUserinfoToken;
token_info.email = account_id_.GetUserEmail();
- fake_gaia_.IssueOAuthToken(policy::affiliation_test_helper::kFakeRefreshToken,
+ fake_gaia_.IssueOAuthToken(policy::AffiliationTestHelper::kFakeRefreshToken,
token_info);
// On PRE_ test stage list of users is empty at this point. Then in the body
@@ -143,7 +143,7 @@ void PlatformKeysTestBase::SetUpOnMainThread() {
// after PRE_ test the list of user contains one kEnterpriseUser user.
// This user logs in.
if (!IsPreTest()) {
- policy::affiliation_test_helper::LoginUser(account_id_);
+ policy::AffiliationTestHelper::LoginUser(account_id_);
if (user_status() != UserStatus::UNMANAGED) {
policy::ProfilePolicyConnector* const connector =
@@ -183,7 +183,7 @@ void PlatformKeysTestBase::PrepareTestSystemSlotOnIO(
crypto::ScopedTestSystemNSSKeySlot* system_slot) {}
void PlatformKeysTestBase::RunPreTest() {
- policy::affiliation_test_helper::PreLoginUser(account_id_);
+ policy::AffiliationTestHelper::PreLoginUser(account_id_);
}
bool PlatformKeysTestBase::TestExtension(const std::string& page_url) {
diff --git a/chromium/chrome/browser/extensions/api/platform_keys/verify_trust_api.cc b/chromium/chrome/browser/extensions/api/platform_keys/verify_trust_api.cc
index e1e4d05bc8e..04e63f93299 100644
--- a/chromium/chrome/browser/extensions/api/platform_keys/verify_trust_api.cc
+++ b/chromium/chrome/browser/extensions/api/platform_keys/verify_trust_api.cc
@@ -18,7 +18,6 @@
#include "net/cert/cert_verify_result.h"
#include "net/cert/x509_certificate.h"
#include "net/log/net_log_with_source.h"
-#include "net/ssl/ssl_config_service.h"
namespace extensions {
@@ -162,7 +161,8 @@ void VerifyTrustAPI::IOPart::Verify(std::unique_ptr<Params> params,
}
std::vector<base::StringPiece> der_cert_chain;
- for (const std::vector<char>& cert_der : details.server_certificate_chain) {
+ for (const std::vector<uint8_t>& cert_der :
+ details.server_certificate_chain) {
if (cert_der.empty()) {
callback.Run(platform_keys::kErrorInvalidX509Cert, 0, 0);
return;
@@ -197,10 +197,8 @@ void VerifyTrustAPI::IOPart::Verify(std::unique_ptr<Params> params,
const int return_value = verifier->Verify(
net::CertVerifier::RequestParams(std::move(cert_chain), details.hostname,
- flags, ocsp_response,
- net::CertificateList()),
- net::SSLConfigService::GetCRLSet().get(), verify_result_ptr,
- bound_callback, &request_state->request, *net_log);
+ flags, ocsp_response),
+ verify_result_ptr, bound_callback, &request_state->request, *net_log);
if (return_value != net::ERR_IO_PENDING) {
bound_callback.Run(return_value);
diff --git a/chromium/chrome/browser/extensions/api/preference/preference_api.cc b/chromium/chrome/browser/extensions/api/preference/preference_api.cc
index 5119a448e46..44cc6d7e252 100644
--- a/chromium/chrome/browser/extensions/api/preference/preference_api.cc
+++ b/chromium/chrome/browser/extensions/api/preference/preference_api.cc
@@ -25,7 +25,7 @@
#include "chrome/browser/net/prediction_options.h"
#include "chrome/browser/profiles/profile.h"
#include "chrome/common/pref_names.h"
-#include "components/autofill/core/common/autofill_pref_names.h"
+#include "components/autofill/core/common/autofill_prefs.h"
#include "components/content_settings/core/common/pref_names.h"
#include "components/data_reduction_proxy/core/common/data_reduction_proxy_pref_names.h"
#include "components/password_manager/core/common/password_manager_pref_names.h"
@@ -94,7 +94,11 @@ const PrefMappingEntry kPrefMapping[] = {
APIPermission::kDataReductionProxy, APIPermission::kDataReductionProxy},
{"alternateErrorPagesEnabled", prefs::kAlternateErrorPagesEnabled,
APIPermission::kPrivacy, APIPermission::kPrivacy},
- {"autofillEnabled", autofill::prefs::kAutofillEnabled,
+ {"autofillEnabled", autofill::prefs::kAutofillEnabledDeprecated,
+ APIPermission::kPrivacy, APIPermission::kPrivacy},
+ {"autofillAddressEnabled", autofill::prefs::kAutofillProfileEnabled,
+ APIPermission::kPrivacy, APIPermission::kPrivacy},
+ {"autofillCreditCardEnabled", autofill::prefs::kAutofillCreditCardEnabled,
APIPermission::kPrivacy, APIPermission::kPrivacy},
{"hyperlinkAuditingEnabled", prefs::kEnableHyperlinkAuditing,
APIPermission::kPrivacy, APIPermission::kPrivacy},
@@ -782,9 +786,24 @@ ExtensionFunction::ResponseAction SetPreferenceFunction::Run() {
transformer->BrowserToExtensionPref(browser_pref_value.get()));
EXTENSION_FUNCTION_VALIDATE(extension_pref_value);
- PreferenceAPI::Get(browser_context())
- ->SetExtensionControlledPref(extension_id(), browser_pref, scope,
- browser_pref_value.release());
+ PreferenceAPI* preference_api = PreferenceAPI::Get(browser_context());
+
+ // Set the new Autofill prefs if the extension sets the deprecated pref in
+ // order to maintain backward compatibility in the extensions preference API.
+ // TODO(crbug.com/870328): Remove this once the deprecated pref is retired.
+ if (autofill::prefs::kAutofillEnabledDeprecated == browser_pref) {
+ // |SetExtensionControlledPref| takes ownership of the base::Value pointer.
+ preference_api->SetExtensionControlledPref(
+ extension_id(), autofill::prefs::kAutofillCreditCardEnabled, scope,
+ new base::Value(browser_pref_value->GetBool()));
+ preference_api->SetExtensionControlledPref(
+ extension_id(), autofill::prefs::kAutofillProfileEnabled, scope,
+ new base::Value(browser_pref_value->GetBool()));
+ }
+
+ preference_api->SetExtensionControlledPref(
+ extension_id(), browser_pref, scope, browser_pref_value.release());
+
return RespondNow(NoArguments());
}
diff --git a/chromium/chrome/browser/extensions/api/preference/preference_apitest.cc b/chromium/chrome/browser/extensions/api/preference/preference_apitest.cc
index 1c25420c612..9f9ea511da8 100644
--- a/chromium/chrome/browser/extensions/api/preference/preference_apitest.cc
+++ b/chromium/chrome/browser/extensions/api/preference/preference_apitest.cc
@@ -19,7 +19,7 @@
#include "chrome/common/chrome_switches.h"
#include "chrome/common/pref_names.h"
#include "chrome/test/base/ui_test_utils.h"
-#include "components/autofill/core/common/autofill_pref_names.h"
+#include "components/autofill/core/common/autofill_prefs.h"
#include "components/content_settings/core/common/pref_names.h"
#include "components/keep_alive_registry/keep_alive_types.h"
#include "components/keep_alive_registry/scoped_keep_alive.h"
@@ -46,7 +46,9 @@ class ExtensionPreferenceApiTest : public extensions::ExtensionApiTest {
ASSERT_TRUE(pref);
EXPECT_TRUE(pref->IsExtensionControlled());
EXPECT_TRUE(prefs->GetBoolean(prefs::kAlternateErrorPagesEnabled));
- EXPECT_TRUE(prefs->GetBoolean(autofill::prefs::kAutofillEnabled));
+ EXPECT_TRUE(prefs->GetBoolean(autofill::prefs::kAutofillEnabledDeprecated));
+ EXPECT_TRUE(prefs->GetBoolean(autofill::prefs::kAutofillCreditCardEnabled));
+ EXPECT_TRUE(prefs->GetBoolean(autofill::prefs::kAutofillProfileEnabled));
EXPECT_FALSE(prefs->GetBoolean(prefs::kBlockThirdPartyCookies));
EXPECT_TRUE(prefs->GetBoolean(prefs::kEnableHyperlinkAuditing));
EXPECT_TRUE(prefs->GetBoolean(prefs::kEnableReferrers));
@@ -66,7 +68,11 @@ class ExtensionPreferenceApiTest : public extensions::ExtensionApiTest {
ASSERT_TRUE(pref);
EXPECT_FALSE(pref->IsExtensionControlled());
EXPECT_FALSE(prefs->GetBoolean(prefs::kAlternateErrorPagesEnabled));
- EXPECT_FALSE(prefs->GetBoolean(autofill::prefs::kAutofillEnabled));
+ EXPECT_FALSE(
+ prefs->GetBoolean(autofill::prefs::kAutofillEnabledDeprecated));
+ EXPECT_FALSE(
+ prefs->GetBoolean(autofill::prefs::kAutofillCreditCardEnabled));
+ EXPECT_FALSE(prefs->GetBoolean(autofill::prefs::kAutofillProfileEnabled));
EXPECT_TRUE(prefs->GetBoolean(prefs::kBlockThirdPartyCookies));
EXPECT_FALSE(prefs->GetBoolean(prefs::kEnableHyperlinkAuditing));
EXPECT_FALSE(prefs->GetBoolean(prefs::kEnableReferrers));
@@ -117,7 +123,9 @@ class ExtensionPreferenceApiTest : public extensions::ExtensionApiTest {
IN_PROC_BROWSER_TEST_F(ExtensionPreferenceApiTest, MAYBE_Standard) {
PrefService* prefs = profile_->GetPrefs();
prefs->SetBoolean(prefs::kAlternateErrorPagesEnabled, false);
- prefs->SetBoolean(autofill::prefs::kAutofillEnabled, false);
+ prefs->SetBoolean(autofill::prefs::kAutofillEnabledDeprecated, false);
+ prefs->SetBoolean(autofill::prefs::kAutofillCreditCardEnabled, false);
+ prefs->SetBoolean(autofill::prefs::kAutofillProfileEnabled, false);
prefs->SetBoolean(prefs::kBlockThirdPartyCookies, true);
prefs->SetBoolean(prefs::kEnableHyperlinkAuditing, false);
prefs->SetBoolean(prefs::kEnableReferrers, false);
diff --git a/chromium/chrome/browser/extensions/api/processes/processes_api.cc b/chromium/chrome/browser/extensions/api/processes/processes_api.cc
index 1de247454bc..517c2595222 100644
--- a/chromium/chrome/browser/extensions/api/processes/processes_api.cc
+++ b/chromium/chrome/browser/extensions/api/processes/processes_api.cc
@@ -520,7 +520,7 @@ base::ProcessHandle ProcessesTerminateFunction::GetProcessHandleOnIO(
auto* host = content::BrowserChildProcessHost::FromID(child_process_host_id);
if (host)
- return host->GetData().handle;
+ return host->GetData().GetHandle();
return base::kNullProcessHandle;
}
diff --git a/chromium/chrome/browser/extensions/api/proxy/proxy_api.cc b/chromium/chrome/browser/extensions/api/proxy/proxy_api.cc
index 1faf2e10fa3..9bb8242b4e7 100644
--- a/chromium/chrome/browser/extensions/api/proxy/proxy_api.cc
+++ b/chromium/chrome/browser/extensions/api/proxy/proxy_api.cc
@@ -111,7 +111,7 @@ std::unique_ptr<base::Value> ProxyPrefTransformer::ExtensionToBrowserPref(
// chrome.proxy.settings.set(). Several of these strings will
// remain blank no respective values have been passed to set().
// If a values has been passed to set but could not be parsed, we bail
- // out and return NULL.
+ // out and return null.
ProxyPrefs::ProxyMode mode_enum;
bool pac_mandatory;
std::string pac_url;
@@ -144,9 +144,7 @@ std::unique_ptr<base::Value> ProxyPrefTransformer::BrowserToExtensionPref(
// This is a dictionary wrapper that exposes the proxy configuration stored in
// the browser preferences.
- ProxyConfigDictionary config(
- static_cast<const base::DictionaryValue*>(browser_pref)
- ->CreateDeepCopy());
+ ProxyConfigDictionary config(browser_pref->Clone());
ProxyPrefs::ProxyMode mode;
if (!config.GetMode(&mode)) {
diff --git a/chromium/chrome/browser/extensions/api/proxy/proxy_api_helpers.cc b/chromium/chrome/browser/extensions/api/proxy/proxy_api_helpers.cc
index c3ad97eb799..153d46d923d 100644
--- a/chromium/chrome/browser/extensions/api/proxy/proxy_api_helpers.cc
+++ b/chromium/chrome/browser/extensions/api/proxy/proxy_api_helpers.cc
@@ -84,8 +84,10 @@ bool GetPacMandatoryFromExtensionPref(const base::DictionaryValue* proxy_config,
const base::DictionaryValue* pac_dict = NULL;
proxy_config->GetDictionary(proxy_api_constants::kProxyConfigPacScript,
&pac_dict);
- if (!pac_dict)
+ if (!pac_dict) {
+ *out = false;
return true;
+ }
bool mandatory_pac = false;
if (pac_dict->HasKey(proxy_api_constants::kProxyConfigPacScriptMandatory) &&
@@ -322,7 +324,7 @@ bool GetBypassListFromExtensionPref(const base::DictionaryValue* proxy_config,
return JoinUrlList(bypass_list, ",", out, error, bad_message);
}
-std::unique_ptr<base::DictionaryValue> CreateProxyConfigDict(
+std::unique_ptr<base::Value> CreateProxyConfigDict(
ProxyPrefs::ProxyMode mode_enum,
bool pac_mandatory,
const std::string& pac_url,
@@ -330,14 +332,13 @@ std::unique_ptr<base::DictionaryValue> CreateProxyConfigDict(
const std::string& proxy_rules_string,
const std::string& bypass_list,
std::string* error) {
- std::unique_ptr<base::DictionaryValue> result_proxy_config;
switch (mode_enum) {
case ProxyPrefs::MODE_DIRECT:
- result_proxy_config = ProxyConfigDictionary::CreateDirect();
- break;
+ return std::make_unique<base::Value>(
+ ProxyConfigDictionary::CreateDirect());
case ProxyPrefs::MODE_AUTO_DETECT:
- result_proxy_config = ProxyConfigDictionary::CreateAutoDetect();
- break;
+ return std::make_unique<base::Value>(
+ ProxyConfigDictionary::CreateAutoDetect());
case ProxyPrefs::MODE_PAC_SCRIPT: {
std::string url;
if (!pac_url.empty()) {
@@ -348,30 +349,30 @@ std::unique_ptr<base::DictionaryValue> CreateProxyConfigDict(
return nullptr;
}
} else {
- *error = "Proxy mode 'pac_script' requires a 'pacScript' field with "
- "either a 'url' field or a 'data' field.";
+ *error =
+ "Proxy mode 'pac_script' requires a 'pacScript' field with "
+ "either a 'url' field or a 'data' field.";
return nullptr;
}
- result_proxy_config =
- ProxyConfigDictionary::CreatePacScript(url, pac_mandatory);
- break;
+ return std::make_unique<base::Value>(
+ ProxyConfigDictionary::CreatePacScript(url, pac_mandatory));
}
case ProxyPrefs::MODE_FIXED_SERVERS: {
if (proxy_rules_string.empty()) {
*error = "Proxy mode 'fixed_servers' requires a 'rules' field.";
return nullptr;
}
- result_proxy_config = ProxyConfigDictionary::CreateFixedServers(
- proxy_rules_string, bypass_list);
- break;
+ return std::make_unique<base::Value>(
+ ProxyConfigDictionary::CreateFixedServers(proxy_rules_string,
+ bypass_list));
}
case ProxyPrefs::MODE_SYSTEM:
- result_proxy_config = ProxyConfigDictionary::CreateSystem();
- break;
+ return std::make_unique<base::Value>(
+ ProxyConfigDictionary::CreateSystem());
case ProxyPrefs::kModeCount:
NOTREACHED();
}
- return result_proxy_config;
+ return nullptr;
}
std::unique_ptr<base::DictionaryValue> CreateProxyRulesDict(
diff --git a/chromium/chrome/browser/extensions/api/proxy/proxy_api_helpers.h b/chromium/chrome/browser/extensions/api/proxy/proxy_api_helpers.h
index 43428988aa6..00da93813d5 100644
--- a/chromium/chrome/browser/extensions/api/proxy/proxy_api_helpers.h
+++ b/chromium/chrome/browser/extensions/api/proxy/proxy_api_helpers.h
@@ -18,6 +18,7 @@ class ProxyConfigDictionary;
namespace base {
class DictionaryValue;
class ListValue;
+class Value;
}
namespace extensions {
@@ -43,6 +44,8 @@ bool CreatePACScriptFromDataURL(
//
// - If there are NO entries for the respective pieces of data, the functions
// return true.
+// The GetPacMandatoryFromExtensionPref() function sets |out| to false in this
+// case.
// - If there ARE entries and they could be parsed, the functions set |out|
// and return true.
// - If there are entries that could not be parsed, the functions set |error|
@@ -79,7 +82,7 @@ bool GetBypassListFromExtensionPref(const base::DictionaryValue* proxy_config,
// Creates and returns a ProxyConfig dictionary (as defined in the extension
// API) from the given parameters. Ownership is passed to the caller.
// Depending on the value of |mode_enum|, several of the strings may be empty.
-std::unique_ptr<base::DictionaryValue> CreateProxyConfigDict(
+std::unique_ptr<base::Value> CreateProxyConfigDict(
ProxyPrefs::ProxyMode mode_enum,
bool pac_mandatory,
const std::string& pac_url,
diff --git a/chromium/chrome/browser/extensions/api/proxy/proxy_api_helpers_unittest.cc b/chromium/chrome/browser/extensions/api/proxy/proxy_api_helpers_unittest.cc
index 85ff80162b4..93eee864b1e 100644
--- a/chromium/chrome/browser/extensions/api/proxy/proxy_api_helpers_unittest.cc
+++ b/chromium/chrome/browser/extensions/api/proxy/proxy_api_helpers_unittest.cc
@@ -225,47 +225,44 @@ TEST(ExtensionProxyApiHelpers, GetBypassListFromExtensionPref) {
TEST(ExtensionProxyApiHelpers, CreateProxyConfigDict) {
std::string error;
- std::unique_ptr<base::DictionaryValue> exp_direct =
- ProxyConfigDictionary::CreateDirect();
- std::unique_ptr<base::DictionaryValue> out_direct(CreateProxyConfigDict(
+ base::Value exp_direct = ProxyConfigDictionary::CreateDirect();
+ std::unique_ptr<base::Value> out_direct(CreateProxyConfigDict(
ProxyPrefs::MODE_DIRECT, false, std::string(), std::string(),
std::string(), std::string(), &error));
- EXPECT_EQ(*exp_direct, *out_direct);
+ EXPECT_EQ(exp_direct, *out_direct);
- std::unique_ptr<base::DictionaryValue> exp_auto =
- ProxyConfigDictionary::CreateAutoDetect();
- std::unique_ptr<base::DictionaryValue> out_auto(CreateProxyConfigDict(
+ base::Value exp_auto = ProxyConfigDictionary::CreateAutoDetect();
+ std::unique_ptr<base::Value> out_auto(CreateProxyConfigDict(
ProxyPrefs::MODE_AUTO_DETECT, false, std::string(), std::string(),
std::string(), std::string(), &error));
- EXPECT_EQ(*exp_auto, *out_auto);
+ EXPECT_EQ(exp_auto, *out_auto);
- std::unique_ptr<base::DictionaryValue> exp_pac_url =
+ base::Value exp_pac_url =
ProxyConfigDictionary::CreatePacScript(kSamplePacScriptUrl, false);
- std::unique_ptr<base::DictionaryValue> out_pac_url(CreateProxyConfigDict(
+ std::unique_ptr<base::Value> out_pac_url(CreateProxyConfigDict(
ProxyPrefs::MODE_PAC_SCRIPT, false, kSamplePacScriptUrl, std::string(),
std::string(), std::string(), &error));
- EXPECT_EQ(*exp_pac_url, *out_pac_url);
+ EXPECT_EQ(exp_pac_url, *out_pac_url);
- std::unique_ptr<base::DictionaryValue> exp_pac_data =
+ base::Value exp_pac_data =
ProxyConfigDictionary::CreatePacScript(kSamplePacScriptAsDataUrl, false);
- std::unique_ptr<base::DictionaryValue> out_pac_data(CreateProxyConfigDict(
+ std::unique_ptr<base::Value> out_pac_data(CreateProxyConfigDict(
ProxyPrefs::MODE_PAC_SCRIPT, false, std::string(), kSamplePacScript,
std::string(), std::string(), &error));
- EXPECT_EQ(*exp_pac_data, *out_pac_data);
+ EXPECT_EQ(exp_pac_data, *out_pac_data);
- std::unique_ptr<base::DictionaryValue> exp_fixed =
+ base::Value exp_fixed =
ProxyConfigDictionary::CreateFixedServers("foo:80", "localhost");
- std::unique_ptr<base::DictionaryValue> out_fixed(CreateProxyConfigDict(
+ std::unique_ptr<base::Value> out_fixed(CreateProxyConfigDict(
ProxyPrefs::MODE_FIXED_SERVERS, false, std::string(), std::string(),
"foo:80", "localhost", &error));
- EXPECT_EQ(*exp_fixed, *out_fixed);
+ EXPECT_EQ(exp_fixed, *out_fixed);
- std::unique_ptr<base::DictionaryValue> exp_system =
- ProxyConfigDictionary::CreateSystem();
- std::unique_ptr<base::DictionaryValue> out_system(CreateProxyConfigDict(
+ base::Value exp_system = ProxyConfigDictionary::CreateSystem();
+ std::unique_ptr<base::Value> out_system(CreateProxyConfigDict(
ProxyPrefs::MODE_SYSTEM, false, std::string(), std::string(),
std::string(), std::string(), &error));
- EXPECT_EQ(*exp_system, *out_system);
+ EXPECT_EQ(exp_system, *out_system);
// Neither of them should have set an error.
EXPECT_EQ(std::string(), error);
@@ -311,11 +308,9 @@ TEST(ExtensionProxyApiHelpers, JoinUrlList) {
// This tests CreateProxyServerDict as well.
TEST(ExtensionProxyApiHelpers, CreateProxyRulesDict) {
- std::unique_ptr<base::DictionaryValue> browser_pref(
- ProxyConfigDictionary::CreateFixedServers(
- "http=proxy1:80;https=proxy2:80;ftp=proxy3:80;socks=proxy4:80",
- "localhost"));
- ProxyConfigDictionary config(std::move(browser_pref));
+ ProxyConfigDictionary config(ProxyConfigDictionary::CreateFixedServers(
+ "http=proxy1:80;https=proxy2:80;ftp=proxy3:80;socks=proxy4:80",
+ "localhost"));
std::unique_ptr<base::DictionaryValue> extension_pref(
CreateProxyRulesDict(config));
ASSERT_TRUE(extension_pref.get());
@@ -338,12 +333,10 @@ TEST(ExtensionProxyApiHelpers, CreateProxyRulesDict) {
// Test multiple proxies per scheme -- expect that only the first is returned.
TEST(ExtensionProxyApiHelpers, CreateProxyRulesDictMultipleProxies) {
- std::unique_ptr<base::DictionaryValue> browser_pref(
- ProxyConfigDictionary::CreateFixedServers(
- "http=proxy1:80,default://;https=proxy2:80,proxy1:80;ftp=proxy3:80,"
- "https://proxy5:443;socks=proxy4:80,proxy1:80",
- "localhost"));
- ProxyConfigDictionary config(std::move(browser_pref));
+ ProxyConfigDictionary config(ProxyConfigDictionary::CreateFixedServers(
+ "http=proxy1:80,default://;https=proxy2:80,proxy1:80;ftp=proxy3:80,"
+ "https://proxy5:443;socks=proxy4:80,proxy1:80",
+ "localhost"));
std::unique_ptr<base::DictionaryValue> extension_pref(
CreateProxyRulesDict(config));
ASSERT_TRUE(extension_pref.get());
@@ -366,9 +359,8 @@ TEST(ExtensionProxyApiHelpers, CreateProxyRulesDictMultipleProxies) {
// Test if a PAC script URL is specified.
TEST(ExtensionProxyApiHelpers, CreatePacScriptDictWithUrl) {
- std::unique_ptr<base::DictionaryValue> browser_pref(
+ ProxyConfigDictionary config(
ProxyConfigDictionary::CreatePacScript(kSamplePacScriptUrl, false));
- ProxyConfigDictionary config(std::move(browser_pref));
std::unique_ptr<base::DictionaryValue> extension_pref(
CreatePacScriptDict(config));
ASSERT_TRUE(extension_pref.get());
@@ -382,9 +374,8 @@ TEST(ExtensionProxyApiHelpers, CreatePacScriptDictWithUrl) {
// Test if a PAC script is encoded in a data URL.
TEST(ExtensionProxyApiHelpers, CreatePacScriptDictWidthData) {
- std::unique_ptr<base::DictionaryValue> browser_pref(
+ ProxyConfigDictionary config(
ProxyConfigDictionary::CreatePacScript(kSamplePacScriptAsDataUrl, false));
- ProxyConfigDictionary config(std::move(browser_pref));
std::unique_ptr<base::DictionaryValue> extension_pref(
CreatePacScriptDict(config));
ASSERT_TRUE(extension_pref.get());
diff --git a/chromium/chrome/browser/extensions/api/proxy/proxy_apitest.cc b/chromium/chrome/browser/extensions/api/proxy/proxy_apitest.cc
index 981c9b2d1b2..2d954803cb0 100644
--- a/chromium/chrome/browser/extensions/api/proxy/proxy_apitest.cc
+++ b/chromium/chrome/browser/extensions/api/proxy/proxy_apitest.cc
@@ -43,8 +43,7 @@ class ProxySettingsApiTest : public ExtensionApiTest {
EXPECT_TRUE(pref->IsExtensionControlled());
ProxyConfigDictionary dict(
- pref_service->GetDictionary(proxy_config::prefs::kProxy)
- ->CreateDeepCopy());
+ pref_service->GetDictionary(proxy_config::prefs::kProxy)->Clone());
ProxyPrefs::ProxyMode mode;
ASSERT_TRUE(dict.GetMode(&mode));
@@ -397,20 +396,10 @@ IN_PROC_BROWSER_TEST_F(ProxySettingsApiTest,
pref_service);
}
-// This test sets proxy to an inavalid host "does.not.exist" and then fetches
-// a page from localhost, expecting an error since host is invalid.
-// On ChromeOS, localhost is by default bypassed, so the page from localhost
-// will be fetched successfully, resulting in no error. Hence this test
-// shouldn't run on ChromeOS.
-#if defined(OS_CHROMEOS)
-#define MAYBE_ProxyEventsInvalidProxy DISABLED_ProxyEventsInvalidProxy
-#else
-#define MAYBE_ProxyEventsInvalidProxy ProxyEventsInvalidProxy
-#endif // defined(OS_CHROMEOS)
-
-// Tests error events: invalid proxy
-IN_PROC_BROWSER_TEST_F(ProxySettingsApiTest, MAYBE_ProxyEventsInvalidProxy) {
- ASSERT_TRUE(StartEmbeddedTestServer());
+// This test sets the HTTP proxy to an unreachable host "does.not.exist" and
+// then attempts to fetch "example.test", expecting the listeners of
+// chrome.proxy.onProxyError to fire with ERR_PROXY_CONNECTION_FAILED.
+IN_PROC_BROWSER_TEST_F(ProxySettingsApiTest, ProxyEventsInvalidProxy) {
ASSERT_TRUE(
RunExtensionSubtest("proxy/events", "invalid_proxy.html")) << message_;
}
@@ -421,4 +410,11 @@ IN_PROC_BROWSER_TEST_F(ProxySettingsApiTest, ProxyEventsParseError) {
RunExtensionSubtest("proxy/events", "parse_error.html")) << message_;
}
+// Tests that chrome.proxy.onProxyError is NOT called in the case of a
+// non-proxy error.
+IN_PROC_BROWSER_TEST_F(ProxySettingsApiTest, ProxyEventsOtherError) {
+ ASSERT_TRUE(RunExtensionSubtest("proxy/events", "other_error.html"))
+ << message_;
+}
+
} // namespace extensions
diff --git a/chromium/chrome/browser/extensions/api/sessions/sessions_apitest.cc b/chromium/chrome/browser/extensions/api/sessions/sessions_apitest.cc
index 6b5dc75cc8a..20644c9da22 100644
--- a/chromium/chrome/browser/extensions/api/sessions/sessions_apitest.cc
+++ b/chromium/chrome/browser/extensions/api/sessions/sessions_apitest.cc
@@ -268,7 +268,7 @@ void ExtensionSessionsTest::CreateSessionModels() {
std::unique_ptr<syncer::DataTypeActivationResponse> activation_response;
base::RunLoop loop;
ProfileSyncServiceFactory::GetForProfile(browser_->profile())
- ->GetSessionSyncControllerDelegateOnUIThread()
+ ->GetSessionSyncControllerDelegate()
->OnSyncStarting(
request, base::BindLambdaForTesting(
[&](std::unique_ptr<syncer::DataTypeActivationResponse>
diff --git a/chromium/chrome/browser/extensions/api/settings_private/generated_pref.h b/chromium/chrome/browser/extensions/api/settings_private/generated_pref.h
index a634903329b..3222055de56 100644
--- a/chromium/chrome/browser/extensions/api/settings_private/generated_pref.h
+++ b/chromium/chrome/browser/extensions/api/settings_private/generated_pref.h
@@ -63,7 +63,7 @@ class GeneratedPref {
void NotifyObservers(const std::string& pref_name);
private:
- base::ObserverList<Observer> observers_;
+ base::ObserverList<Observer>::Unchecked observers_;
DISALLOW_COPY_AND_ASSIGN(GeneratedPref);
};
diff --git a/chromium/chrome/browser/extensions/api/settings_private/prefs_util.cc b/chromium/chrome/browser/extensions/api/settings_private/prefs_util.cc
index a64508aaa09..cda1e3351d1 100644
--- a/chromium/chrome/browser/extensions/api/settings_private/prefs_util.cc
+++ b/chromium/chrome/browser/extensions/api/settings_private/prefs_util.cc
@@ -14,7 +14,7 @@
#include "chrome/browser/profiles/profile.h"
#include "chrome/common/pref_names.h"
#include "chromeos/components/proximity_auth/proximity_auth_pref_names.h"
-#include "components/autofill/core/common/autofill_pref_names.h"
+#include "components/autofill/core/common/autofill_prefs.h"
#include "components/bookmarks/common/bookmark_pref_names.h"
#include "components/browsing_data/core/pref_names.h"
#include "components/component_updater/pref_names.h"
@@ -117,8 +117,6 @@ const PrefsUtil::TypedPrefMap& PrefsUtil::GetWhitelistedKeys() {
// Miscellaneous
(*s_whitelist)[::prefs::kAlternateErrorPagesEnabled] =
settings_api::PrefType::PREF_TYPE_BOOLEAN;
- (*s_whitelist)[autofill::prefs::kAutofillEnabled] =
- settings_api::PrefType::PREF_TYPE_BOOLEAN;
(*s_whitelist)[autofill::prefs::kAutofillProfileEnabled] =
settings_api::PrefType::PREF_TYPE_BOOLEAN;
(*s_whitelist)[autofill::prefs::kAutofillCreditCardEnabled] =
@@ -178,6 +176,10 @@ const PrefsUtil::TypedPrefMap& PrefsUtil::GetWhitelistedKeys() {
settings_api::PrefType::PREF_TYPE_BOOLEAN;
(*s_whitelist)[drive::prefs::kDisableDrive] =
settings_api::PrefType::PREF_TYPE_BOOLEAN;
+#if defined(OS_CHROMEOS)
+ (*s_whitelist)[::prefs::kNetworkFileSharesAllowed] =
+ settings_api::PrefType::PREF_TYPE_BOOLEAN;
+#endif
// Printing settings.
(*s_whitelist)[::prefs::kLocalDiscoveryNotificationsEnabled] =
@@ -197,6 +199,10 @@ const PrefsUtil::TypedPrefMap& PrefsUtil::GetWhitelistedKeys() {
(*s_whitelist)[password_manager::prefs::kCredentialsEnableAutosignin] =
settings_api::PrefType::PREF_TYPE_BOOLEAN;
+ // Privacy page
+ (*s_whitelist)[::prefs::kSigninAllowedOnNextStartup] =
+ settings_api::PrefType::PREF_TYPE_BOOLEAN;
+
// Sync and personalization page.
(*s_whitelist)[::prefs::kSafeBrowsingEnabled] =
settings_api::PrefType::PREF_TYPE_BOOLEAN;
@@ -289,12 +295,12 @@ const PrefsUtil::TypedPrefMap& PrefsUtil::GetWhitelistedKeys() {
// kEnableAutoScreenLock is read-only.
(*s_whitelist)[ash::prefs::kEnableAutoScreenLock] =
settings_api::PrefType::PREF_TYPE_BOOLEAN;
- (*s_whitelist)[::prefs::kEnableQuickUnlockFingerprint] =
- settings_api::PrefType::PREF_TYPE_BOOLEAN;
(*s_whitelist)[proximity_auth::prefs::kEasyUnlockProximityThreshold] =
settings_api::PrefType::PREF_TYPE_NUMBER;
(*s_whitelist)[proximity_auth::prefs::kProximityAuthIsChromeOSLoginEnabled] =
settings_api::PrefType::PREF_TYPE_BOOLEAN;
+ (*s_whitelist)[ash::prefs::kMessageCenterLockScreenMode] =
+ settings_api::PrefType::PREF_TYPE_STRING;
// Accessibility.
(*s_whitelist)[ash::prefs::kAccessibilitySpokenFeedbackEnabled] =
@@ -363,6 +369,8 @@ const PrefsUtil::TypedPrefMap& PrefsUtil::GetWhitelistedKeys() {
settings_api::PrefType::PREF_TYPE_BOOLEAN;
(*s_whitelist)[arc::prefs::kVoiceInteractionHotwordEnabled] =
settings_api::PrefType::PREF_TYPE_BOOLEAN;
+ (*s_whitelist)[arc::prefs::kVoiceInteractionNotificationEnabled] =
+ settings_api::PrefType::PREF_TYPE_BOOLEAN;
// Misc.
(*s_whitelist)[::prefs::kUse24HourClock] =
@@ -461,6 +469,10 @@ const PrefsUtil::TypedPrefMap& PrefsUtil::GetWhitelistedKeys() {
settings_api::PrefType::PREF_TYPE_NUMBER;
(*s_whitelist)[::prefs::kLanguageRemapDiamondKeyTo] =
settings_api::PrefType::PREF_TYPE_NUMBER;
+ (*s_whitelist)[::prefs::kLanguageRemapExternalCommandKeyTo] =
+ settings_api::PrefType::PREF_TYPE_NUMBER;
+ (*s_whitelist)[::prefs::kLanguageRemapExternalMetaKeyTo] =
+ settings_api::PrefType::PREF_TYPE_NUMBER;
(*s_whitelist)[::prefs::kLanguageSendFunctionKeys] =
settings_api::PrefType::PREF_TYPE_BOOLEAN;
(*s_whitelist)[::prefs::kLanguageXkbAutoRepeatEnabled] =
@@ -470,10 +482,6 @@ const PrefsUtil::TypedPrefMap& PrefsUtil::GetWhitelistedKeys() {
(*s_whitelist)[::prefs::kLanguageXkbAutoRepeatInterval] =
settings_api::PrefType::PREF_TYPE_NUMBER;
- // Multidevice settings.
- (*s_whitelist)[arc::prefs::kSmsConnectEnabled] =
- settings_api::PrefType::PREF_TYPE_BOOLEAN;
-
// Native Printing settings.
(*s_whitelist)[::prefs::kUserNativePrintersAllowed] =
settings_api::PrefType::PREF_TYPE_BOOLEAN;
diff --git a/chromium/chrome/browser/extensions/api/socket/combined_socket_unittest.cc b/chromium/chrome/browser/extensions/api/socket/combined_socket_unittest.cc
deleted file mode 100644
index 6feb6fe9361..00000000000
--- a/chromium/chrome/browser/extensions/api/socket/combined_socket_unittest.cc
+++ /dev/null
@@ -1,145 +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 <memory>
-
-#include "chrome/browser/extensions/api/socket/mock_tcp_client_socket.h"
-#include "extensions/browser/api/socket/socket.h"
-#include "extensions/browser/api/socket/tcp_socket.h"
-#include "extensions/browser/api/socket/tls_socket.h"
-#include "net/socket/stream_socket.h"
-#include "testing/gmock/include/gmock/gmock.h"
-#include "testing/gtest/include/gtest/gtest.h"
-
-namespace extensions {
-
-const int kBufferLength = 10;
-
-template <typename T>
-std::unique_ptr<T> CreateTestSocket(
- std::unique_ptr<MockTCPClientSocket> stream);
-
-template <>
-std::unique_ptr<TCPSocket> CreateTestSocket(
- std::unique_ptr<MockTCPClientSocket> stream) {
- return std::make_unique<TCPSocket>(std::move(stream), "fake id",
- true /* is_connected */);
-}
-
-template <>
-std::unique_ptr<TLSSocket> CreateTestSocket(
- std::unique_ptr<MockTCPClientSocket> stream) {
- return std::make_unique<TLSSocket>(std::move(stream), "fake id");
-}
-
-class CombinedSocketTest : public testing::Test {
- public:
- CombinedSocketTest() : count_(0), io_buffer_(nullptr) {}
-
- // Strict test for synchronous (immediate) read behavior
- template <typename T>
- void TestRead() {
- net::IOBuffer* buffer = nullptr;
-
- std::unique_ptr<MockTCPClientSocket> stream(
- new testing::StrictMock<MockTCPClientSocket>());
- EXPECT_CALL(*stream, Read(testing::NotNull(), kBufferLength, testing::_))
- .WillOnce(DoAll(testing::SaveArg<0>(&buffer),
- testing::Return(kBufferLength)));
- EXPECT_CALL(*stream, Disconnect());
-
- std::unique_ptr<T> socket = CreateTestSocket<T>(std::move(stream));
- ReadCompletionCallback read_callback =
- base::Bind(&CombinedSocketTest::OnRead, base::Unretained(this));
- socket->Read(kBufferLength, read_callback);
- EXPECT_EQ(kBufferLength, count_);
- EXPECT_NE(nullptr, buffer);
- EXPECT_EQ(buffer, io_buffer_);
- }
-
- // Strict test for async read behavior (read returns PENDING)
- template <typename T>
- void TestReadPending() {
- net::IOBuffer* buffer = nullptr;
- net::CompletionCallback socket_cb;
-
- std::unique_ptr<MockTCPClientSocket> stream(
- new testing::StrictMock<MockTCPClientSocket>());
- EXPECT_CALL(*stream, Read(testing::NotNull(), kBufferLength, testing::_))
- .WillOnce(DoAll(testing::SaveArg<0>(&buffer),
- testing::SaveArg<2>(&socket_cb),
- testing::Return(net::ERR_IO_PENDING)));
- EXPECT_CALL(*stream, Disconnect());
-
- std::unique_ptr<T> socket = CreateTestSocket<T>(std::move(stream));
- ReadCompletionCallback read_callback =
- base::Bind(&CombinedSocketTest::OnRead, base::Unretained(this));
- socket->Read(kBufferLength, read_callback);
- EXPECT_EQ(0, count_);
- EXPECT_EQ(nullptr, io_buffer_);
- socket_cb.Run(kBufferLength);
- EXPECT_EQ(kBufferLength, count_);
- EXPECT_NE(nullptr, buffer);
- EXPECT_EQ(buffer, io_buffer_);
- }
-
- // Even if the socket is closed, it may still have data left to read.
- template <typename T>
- void TestReadAfterDisconnect() {
- net::IOBuffer* buffer = nullptr;
-
- std::unique_ptr<MockTCPClientSocket> stream(
- new testing::NiceMock<MockTCPClientSocket>());
- EXPECT_CALL(*stream, Read(testing::NotNull(), kBufferLength, testing::_))
- .WillOnce(DoAll(testing::SaveArg<0>(&buffer),
- testing::Return(kBufferLength)));
- ON_CALL(*stream, IsConnected()).WillByDefault(testing::Return(false));
- EXPECT_CALL(*stream, Disconnect());
-
- std::unique_ptr<T> socket = CreateTestSocket<T>(std::move(stream));
- ReadCompletionCallback read_callback =
- base::Bind(&CombinedSocketTest::OnRead, base::Unretained(this));
- socket->Read(kBufferLength, read_callback);
- EXPECT_EQ(kBufferLength, count_);
- EXPECT_NE(nullptr, buffer);
- EXPECT_EQ(buffer, io_buffer_);
- }
-
- void OnRead(int count,
- scoped_refptr<net::IOBuffer> io_buffer,
- bool socket_destroying) {
- count_ = count;
- io_buffer_ = io_buffer.get();
- }
-
- protected:
- int count_;
- net::IOBuffer* io_buffer_;
-};
-
-TEST_F(CombinedSocketTest, TlsRead) {
- TestRead<TLSSocket>();
-}
-
-TEST_F(CombinedSocketTest, TcpRead) {
- TestRead<TCPSocket>();
-}
-
-TEST_F(CombinedSocketTest, TlsReadPending) {
- TestReadPending<TLSSocket>();
-}
-
-TEST_F(CombinedSocketTest, TcpReadPending) {
- TestReadPending<TCPSocket>();
-}
-
-TEST_F(CombinedSocketTest, TlsReadAfterDisconnect) {
- TestReadAfterDisconnect<TLSSocket>();
-}
-
-TEST_F(CombinedSocketTest, TcpReadAfterDisconnect) {
- TestReadAfterDisconnect<TCPSocket>();
-}
-
-} // namespace extensions
diff --git a/chromium/chrome/browser/extensions/api/socket/mock_tcp_client_socket.h b/chromium/chrome/browser/extensions/api/socket/mock_tcp_client_socket.h
deleted file mode 100644
index fddad102ac6..00000000000
--- a/chromium/chrome/browser/extensions/api/socket/mock_tcp_client_socket.h
+++ /dev/null
@@ -1,82 +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 CHROME_BROWSER_EXTENSIONS_API_SOCKET_MOCK_TCP_CLIENT_SOCKET_H_
-#define CHROME_BROWSER_EXTENSIONS_API_SOCKET_MOCK_TCP_CLIENT_SOCKET_H_
-
-#include "base/callback_helpers.h"
-#include "net/log/net_log_source.h"
-#include "net/log/net_log_with_source.h"
-#include "net/socket/tcp_client_socket.h"
-#include "net/traffic_annotation/network_traffic_annotation_test_helper.h"
-#include "testing/gmock/include/gmock/gmock.h"
-
-namespace extensions {
-class MockTCPClientSocket : public net::TCPClientSocket {
- public:
- MockTCPClientSocket();
- ~MockTCPClientSocket() override;
-
- int Read(net::IOBuffer* buffer,
- int bytes,
- net::CompletionOnceCallback callback) override {
- return Read(buffer, bytes,
- base::AdaptCallbackForRepeating(std::move(callback)));
- }
-
- int Write(net::IOBuffer* buffer,
- int bytes,
- net::CompletionOnceCallback callback,
- const net::NetworkTrafficAnnotationTag& tag) override {
- return Write(buffer, bytes,
- base::AdaptCallbackForRepeating(std::move(callback)), tag);
- }
-
- int Connect(net::CompletionOnceCallback callback) override {
- return Connect(base::AdaptCallbackForRepeating(std::move(callback)));
- }
-
- MOCK_METHOD3(Read, int(net::IOBuffer*, int, const net::CompletionCallback&));
- MOCK_METHOD4(Write,
- int(net::IOBuffer*,
- int,
- const net::CompletionCallback&,
- const net::NetworkTrafficAnnotationTag&));
- MOCK_METHOD1(SetReceiveBufferSize, int(int32_t));
- MOCK_METHOD1(SetSendBufferSize, int(int32_t));
- MOCK_METHOD1(Connect, int(const net::CompletionCallback&));
- MOCK_METHOD0(Disconnect, void());
- MOCK_CONST_METHOD0(IsConnected, bool());
- MOCK_CONST_METHOD0(IsConnectedAndIdle, bool());
- MOCK_CONST_METHOD1(GetPeerAddress, int(net::IPEndPoint*));
- MOCK_CONST_METHOD1(GetLocalAddress, int(net::IPEndPoint*));
- MOCK_CONST_METHOD0(NetLog, const net::NetLogWithSource&());
- MOCK_CONST_METHOD0(WasEverUsed, bool());
- MOCK_CONST_METHOD0(UsingTCPFastOpen, bool());
- MOCK_CONST_METHOD0(NumBytesRead, int64_t());
- MOCK_CONST_METHOD0(GetConnectTimeMicros, base::TimeDelta());
- MOCK_CONST_METHOD0(WasAlpnNegotiated, bool());
- MOCK_CONST_METHOD0(GetNegotiatedProtocol, net::NextProto());
- MOCK_METHOD1(GetSSLInfo, bool(net::SSLInfo*));
- MOCK_CONST_METHOD1(GetConnectionAttempts, void(net::ConnectionAttempts*));
- MOCK_METHOD0(ClearConnectionAttempts, void());
- MOCK_METHOD1(AddConnectionAttempts, void(const net::ConnectionAttempts&));
- MOCK_CONST_METHOD0(GetTotalReceivedBytes, int64_t());
-
- // Methods specific to MockTCPClientSocket
- MOCK_METHOD1(Bind, int(const net::IPEndPoint&));
- MOCK_METHOD2(SetKeepAlive, bool(bool, int));
- MOCK_METHOD1(SetNoDelay, bool(bool));
-};
-
-MockTCPClientSocket::MockTCPClientSocket()
- : TCPClientSocket(net::AddressList(),
- nullptr,
- nullptr,
- net::NetLogSource()) {}
-MockTCPClientSocket::~MockTCPClientSocket() {}
-
-} // namespace extensions
-
-#endif // CHROME_BROWSER_EXTENSIONS_API_SOCKET_MOCK_TCP_CLIENT_SOCKET_H_
diff --git a/chromium/chrome/browser/extensions/api/socket/socket_apitest.cc b/chromium/chrome/browser/extensions/api/socket/socket_apitest.cc
index ae11686ed95..ee35b81809e 100644
--- a/chromium/chrome/browser/extensions/api/socket/socket_apitest.cc
+++ b/chromium/chrome/browser/extensions/api/socket/socket_apitest.cc
@@ -9,8 +9,6 @@
#include "chrome/browser/ui/browser.h"
#include "chrome/common/chrome_paths.h"
#include "chrome/test/base/in_process_browser_test.h"
-#include "extensions/browser/api/dns/host_resolver_wrapper.h"
-#include "extensions/browser/api/dns/mock_host_resolver_creator.h"
#include "extensions/browser/api/socket/socket_api.h"
#include "extensions/test/extension_test_message_listener.h"
#include "extensions/test/result_catcher.h"
@@ -22,35 +20,15 @@ using extensions::ResultCatcher;
namespace {
-const char kHostname[] = "127.0.0.1";
+const char kHostname[] = "www.foo.com";
const int kPort = 8888;
class SocketApiTest : public extensions::ExtensionApiTest {
public:
- SocketApiTest()
- : resolver_event_(base::WaitableEvent::ResetPolicy::MANUAL,
- base::WaitableEvent::InitialState::NOT_SIGNALED),
- resolver_creator_(new extensions::MockHostResolverCreator()) {}
-
void SetUpOnMainThread() override {
extensions::ExtensionApiTest::SetUpOnMainThread();
- extensions::HostResolverWrapper::GetInstance()->SetHostResolverForTesting(
- resolver_creator_->CreateMockHostResolver());
- }
-
- void TearDownOnMainThread() override {
- extensions::HostResolverWrapper::GetInstance()->
- SetHostResolverForTesting(NULL);
- resolver_creator_->DeleteMockHostResolver();
+ host_resolver()->AddRule(kHostname, "127.0.0.1");
}
-
- private:
- base::WaitableEvent resolver_event_;
-
- // 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<extensions::MockHostResolverCreator> resolver_creator_;
};
} // namespace
@@ -67,7 +45,7 @@ IN_PROC_BROWSER_TEST_F(SocketApiTest, SocketUDPExtension) {
ASSERT_GT(port, 0);
// Test that sendTo() is properly resolving hostnames.
- host_port_pair.set_host("LOCALhost");
+ host_port_pair.set_host(kHostname);
ResultCatcher catcher;
catcher.RestrictToBrowserContext(browser()->profile());
@@ -115,7 +93,7 @@ IN_PROC_BROWSER_TEST_F(SocketApiTest, SocketTCPServerExtension) {
ExtensionTestMessageListener listener("info_please", true);
ASSERT_TRUE(LoadExtension(test_data_dir_.AppendASCII("socket/api")));
EXPECT_TRUE(listener.WaitUntilSatisfied());
- listener.Reply(base::StringPrintf("tcp_server:%s:%d", kHostname, kPort));
+ listener.Reply(base::StringPrintf("tcp_server:127.0.0.1:%d", kPort));
EXPECT_TRUE(catcher.GetNextResult()) << catcher.message();
}
diff --git a/chromium/chrome/browser/extensions/api/socket/tcp_socket_unittest.cc b/chromium/chrome/browser/extensions/api/socket/tcp_socket_unittest.cc
index 6351e3d6ca2..8fc0c4bfcca 100644
--- a/chromium/chrome/browser/extensions/api/socket/tcp_socket_unittest.cc
+++ b/chromium/chrome/browser/extensions/api/socket/tcp_socket_unittest.cc
@@ -4,274 +4,719 @@
#include <memory>
-#include "base/callback_helpers.h"
#include "base/macros.h"
+#include "base/memory/scoped_refptr.h"
+#include "base/test/bind_test_util.h"
+#include "chrome/browser/extensions/extension_service_test_base.h"
+#include "chrome/test/base/testing_profile.h"
+#include "content/public/browser/browser_context.h"
+#include "content/public/test/test_storage_partition.h"
#include "extensions/browser/api/socket/tcp_socket.h"
#include "net/base/address_list.h"
#include "net/base/completion_callback.h"
#include "net/base/io_buffer.h"
#include "net/base/net_errors.h"
-#include "net/base/rand_callback.h"
-#include "net/log/net_log_source.h"
-#include "net/socket/tcp_client_socket.h"
-#include "net/socket/tcp_server_socket.h"
+#include "net/base/test_completion_callback.h"
+#include "net/socket/socket_test_util.h"
#include "net/traffic_annotation/network_traffic_annotation.h"
-#include "testing/gmock/include/gmock/gmock.h"
-
-using testing::_;
-using testing::DoAll;
-using testing::Return;
-using testing::SaveArg;
+#include "net/url_request/url_request_test_util.h"
+#include "services/network/network_context.h"
+#include "services/network/public/mojom/network_context.mojom.h"
namespace extensions {
-class MockTCPSocket : public net::TCPClientSocket {
+namespace {
+
+const char kTestMsg[] = "abcdefghij";
+const int kTestMsgLength = strlen(kTestMsg);
+
+const char FAKE_ID[] = "abcdefghijklmnopqrst";
+
+class TCPSocketUnitTestBase : public extensions::ExtensionServiceTestBase {
public:
- explicit MockTCPSocket(const net::AddressList& address_list)
- : net::TCPClientSocket(address_list, NULL, NULL, net::NetLogSource()) {}
-
- int Read(net::IOBuffer* buffer,
- int bytes,
- net::CompletionOnceCallback callback) override {
- return Read(buffer, bytes,
- base::AdaptCallbackForRepeating(std::move(callback)));
+ TCPSocketUnitTestBase()
+ : url_request_context_(true /* delay_initialization */) {}
+ ~TCPSocketUnitTestBase() override {}
+
+ std::unique_ptr<TCPSocket> CreateSocket() {
+ auto socket = std::make_unique<TCPSocket>(&profile_, FAKE_ID);
+ socket->SetStoragePartitionForTest(&partition_);
+ return socket;
}
- int Write(net::IOBuffer* buffer,
- int bytes,
- net::CompletionOnceCallback callback,
- const net::NetworkTrafficAnnotationTag& tag) override {
- return Write(buffer, bytes,
- base::AdaptCallbackForRepeating(std::move(callback)), tag);
+ std::unique_ptr<TCPSocket> CreateAndConnectSocketWithAddress(
+ const net::IPEndPoint& ip_end_point) {
+ auto socket = CreateSocket();
+ net::AddressList address(ip_end_point);
+ net::TestCompletionCallback callback;
+ socket->Connect(address, callback.callback());
+ EXPECT_EQ(net::OK, callback.WaitForResult());
+ return socket;
}
- MOCK_METHOD3(Read, int(net::IOBuffer* buf, int buf_len,
- const net::CompletionCallback& callback));
- MOCK_METHOD4(Write,
- int(net::IOBuffer* buf,
- int buf_len,
- const net::CompletionCallback& callback,
- const net::NetworkTrafficAnnotationTag&));
- MOCK_METHOD2(SetKeepAlive, bool(bool enable, int delay));
- MOCK_METHOD1(SetNoDelay, bool(bool no_delay));
- bool IsConnected() const override {
- return true;
+ std::unique_ptr<TCPSocket> CreateAndConnectSocket() {
+ net::IPEndPoint ip_end_point(net::IPAddress::IPv4Localhost(), 1234);
+ return CreateAndConnectSocketWithAddress(ip_end_point);
}
- private:
- DISALLOW_COPY_AND_ASSIGN(MockTCPSocket);
-};
+ // Reads data from |socket| and compares it with |expected_data|.
+ void ReadData(Socket* socket, const std::string& expected_data) {
+ std::string received_data;
+ const int count = 512;
+ while (true) {
+ base::RunLoop run_loop;
+ int net_error = net::ERR_FAILED;
+ socket->Read(count,
+ base::BindLambdaForTesting(
+ [&](int result, scoped_refptr<net::IOBuffer> io_buffer,
+ bool socket_destroying) {
+ net_error = result;
+ EXPECT_FALSE(socket_destroying);
+ if (result > 0)
+ received_data.append(io_buffer->data(), result);
+ run_loop.Quit();
+ }));
+ run_loop.Run();
+ if (net_error <= 0)
+ break;
+ }
+ EXPECT_EQ(expected_data, received_data);
+ }
-class MockTCPServerSocket : public net::TCPServerSocket {
- public:
- MockTCPServerSocket() : net::TCPServerSocket(NULL, net::NetLogSource()) {}
- MOCK_METHOD2(Listen, int(const net::IPEndPoint& address, int backlog));
- MOCK_METHOD2(Accept,
- int(std::unique_ptr<net::StreamSocket>* socket,
- const net::CompletionCallback& callback));
+ protected:
+ // extensions::ExtensionServiceTestBase implementation.
+ void SetUp() override { InitializeEmptyExtensionService(); }
+
+ void Initialize() {
+ url_request_context_.Init();
+ network_context_ = std::make_unique<network::NetworkContext>(
+ nullptr, mojo::MakeRequest(&network_context_ptr_),
+ &url_request_context_);
+ partition_.set_network_context(network_context_ptr_.get());
+ }
+
+ net::TestURLRequestContext url_request_context_;
private:
- DISALLOW_COPY_AND_ASSIGN(MockTCPServerSocket);
+ TestingProfile profile_;
+ content::TestStoragePartition partition_;
+ std::unique_ptr<network::NetworkContext> network_context_;
+ network::mojom::NetworkContextPtr network_context_ptr_;
};
-class CompleteHandler {
+} // namespace
+
+class TCPSocketUnitTest : public TCPSocketUnitTestBase,
+ public ::testing::WithParamInterface<net::IoMode> {
public:
- CompleteHandler() {}
- MOCK_METHOD1(OnComplete, void(int result_code));
- MOCK_METHOD3(OnReadComplete,
- void(int result_code,
- scoped_refptr<net::IOBuffer> io_buffer,
- bool socket_destroying));
-
- // MOCK_METHOD cannot mock a scoped_ptr argument.
- MOCK_METHOD2(OnAcceptMock, void(int, net::TCPClientSocket*));
- void OnAccept(int count, std::unique_ptr<net::TCPClientSocket> socket) {
- OnAcceptMock(count, socket.get());
+ TCPSocketUnitTest() : TCPSocketUnitTestBase() {
+ mock_client_socket_factory_.set_enable_read_if_ready(true);
+ url_request_context_.set_client_socket_factory(
+ &mock_client_socket_factory_);
+ Initialize();
+ }
+ ~TCPSocketUnitTest() override {}
+
+ net::MockClientSocketFactory* mock_client_socket_factory() {
+ return &mock_client_socket_factory_;
}
private:
- DISALLOW_COPY_AND_ASSIGN(CompleteHandler);
+ net::MockClientSocketFactory mock_client_socket_factory_;
};
-const char FAKE_ID[] = "abcdefghijklmnopqrst";
+INSTANTIATE_TEST_CASE_P(/* no prefix */,
+ TCPSocketUnitTest,
+ testing::Values(net::SYNCHRONOUS, net::ASYNC));
+
+TEST_F(TCPSocketUnitTest, SocketConnectError) {
+ net::IPEndPoint ip_end_point(net::IPAddress::IPv4Localhost(), 1234);
+ net::StaticSocketDataProvider data_provider((base::span<net::MockRead>()),
+ base::span<net::MockWrite>());
+ data_provider.set_connect_data(
+ net::MockConnect(net::ASYNC, net::ERR_FAILED, ip_end_point));
+ mock_client_socket_factory()->AddSocketDataProvider(&data_provider);
+ std::unique_ptr<TCPSocket> socket = CreateSocket();
+
+ net::AddressList address(ip_end_point);
+ net::TestCompletionCallback callback;
+ socket->Connect(address, callback.callback());
+ EXPECT_EQ(net::ERR_FAILED, callback.WaitForResult());
+}
+
+TEST_P(TCPSocketUnitTest, SocketConnectAfterDisconnect) {
+ net::IoMode io_mode = GetParam();
+ const net::MockRead kReads[] = {net::MockRead(io_mode, net::OK)};
+ net::StaticSocketDataProvider data_provider1(kReads,
+ base::span<net::MockWrite>());
+ net::StaticSocketDataProvider data_provider2(kReads,
+ base::span<net::MockWrite>());
+ mock_client_socket_factory()->AddSocketDataProvider(&data_provider1);
+ mock_client_socket_factory()->AddSocketDataProvider(&data_provider2);
+ std::unique_ptr<TCPSocket> socket = CreateAndConnectSocket();
+ socket->Disconnect(false /* socket_destroying */);
+ net::TestCompletionCallback callback2;
+ net::IPEndPoint ip_end_point(net::IPAddress::IPv4Localhost(), 1234);
+ net::AddressList address(ip_end_point);
+ socket->Connect(address, callback2.callback());
+ EXPECT_EQ(net::OK, callback2.WaitForResult());
+
+ EXPECT_TRUE(data_provider1.AllReadDataConsumed());
+ EXPECT_TRUE(data_provider1.AllWriteDataConsumed());
+ EXPECT_TRUE(data_provider2.AllReadDataConsumed());
+ EXPECT_TRUE(data_provider2.AllWriteDataConsumed());
+}
+
+TEST_F(TCPSocketUnitTest, DestroyWhileReadPending) {
+ const net::MockRead kReads[] = {
+ net::MockRead(net::SYNCHRONOUS, net::ERR_IO_PENDING)};
+ net::StaticSocketDataProvider data_provider(kReads,
+ base::span<net::MockWrite>());
+ mock_client_socket_factory()->AddSocketDataProvider(&data_provider);
+ std::unique_ptr<TCPSocket> socket = CreateAndConnectSocket();
+
+ int net_result = net::ERR_FAILED;
+ base::RunLoop run_loop;
+ int count = 1;
+ // Read one byte, and it should be pending.
+ socket->Read(count,
+ base::BindLambdaForTesting(
+ [&](int result, scoped_refptr<net::IOBuffer> io_buffer,
+ bool socket_destroying) {
+ net_result = result;
+ // |socket_destroying| should correctly denote that this
+ // read callback is invoked through the destructor of
+ // TCPSocket.
+ EXPECT_TRUE(socket_destroying);
+ run_loop.Quit();
+ }));
+ // Destroy socket.
+ socket = nullptr;
+ // Wait for read callback.
+ run_loop.Run();
+ EXPECT_EQ(net::ERR_CONNECTION_CLOSED, net_result);
+}
-TEST(SocketTest, TestTCPSocketRead) {
- net::AddressList address_list;
- std::unique_ptr<MockTCPSocket> tcp_client_socket(
- new MockTCPSocket(address_list));
- CompleteHandler handler;
+TEST_P(TCPSocketUnitTest, Read) {
+ net::IoMode io_mode = GetParam();
+ const net::MockRead kReads[] = {
+ net::MockRead(io_mode, kTestMsg, kTestMsgLength),
+ net::MockRead(io_mode, net::OK)};
+ net::StaticSocketDataProvider data_provider(kReads,
+ base::span<net::MockWrite>());
- EXPECT_CALL(*tcp_client_socket, Read(_, _, _))
- .Times(1);
- EXPECT_CALL(handler, OnReadComplete(_, _, _)).Times(1);
+ mock_client_socket_factory()->AddSocketDataProvider(&data_provider);
+ std::unique_ptr<TCPSocket> socket = CreateAndConnectSocket();
+
+ ReadData(socket.get(), kTestMsg);
+ EXPECT_TRUE(data_provider.AllReadDataConsumed());
+ EXPECT_TRUE(data_provider.AllWriteDataConsumed());
+}
+
+// Tests the case where a message is split over two separate socket reads.
+TEST_P(TCPSocketUnitTest, SocketMultipleRead) {
+ const char kFirstHalfTestMsg[] = "abcde";
+ const char kSecondHalfTestMsg[] = "fghij";
+ EXPECT_EQ(kTestMsg, std::string(kFirstHalfTestMsg) + kSecondHalfTestMsg);
+ net::IoMode io_mode = GetParam();
+ const net::MockRead kReads[] = {
+ net::MockRead(io_mode, kFirstHalfTestMsg, strlen(kFirstHalfTestMsg)),
+ net::MockRead(io_mode, kSecondHalfTestMsg, strlen(kSecondHalfTestMsg)),
+ net::MockRead(io_mode, net::OK)};
+ net::StaticSocketDataProvider data_provider(kReads,
+ base::span<net::MockWrite>());
+
+ mock_client_socket_factory()->AddSocketDataProvider(&data_provider);
+ std::unique_ptr<TCPSocket> socket = CreateAndConnectSocket();
+
+ ReadData(socket.get(), kTestMsg);
+ EXPECT_TRUE(data_provider.AllReadDataConsumed());
+ EXPECT_TRUE(data_provider.AllWriteDataConsumed());
+}
+
+// Tests the case where read size is smaller than the actual message.
+TEST_P(TCPSocketUnitTest, SocketPartialRead) {
+ net::IoMode io_mode = GetParam();
+ const net::MockRead kReads[] = {
+ net::MockRead(io_mode, kTestMsg, kTestMsgLength),
+ net::MockRead(io_mode, net::OK)};
+ net::StaticSocketDataProvider data_provider(kReads,
+ base::span<net::MockWrite>());
+ mock_client_socket_factory()->AddSocketDataProvider(&data_provider);
+ std::unique_ptr<TCPSocket> socket = CreateAndConnectSocket();
+
+ int count = 1;
+ std::string received_data;
+ while (true) {
+ int net_result = net::ERR_FAILED;
+ base::RunLoop run_loop;
+ socket->Read(count,
+ base::BindLambdaForTesting(
+ [&](int result, scoped_refptr<net::IOBuffer> io_buffer,
+ bool socket_destroying) {
+ net_result = result;
+ EXPECT_FALSE(socket_destroying);
+ if (result > 0)
+ received_data.append(io_buffer->data(), result);
+ run_loop.Quit();
+ }));
+ run_loop.Run();
+ if (net_result <= 0)
+ break;
+ // Double the read size in the next iteration.
+ count *= 2;
+ }
+ EXPECT_EQ(kTestMsg, received_data);
+ EXPECT_TRUE(data_provider.AllReadDataConsumed());
+ EXPECT_TRUE(data_provider.AllWriteDataConsumed());
+}
- std::unique_ptr<TCPSocket> socket(TCPSocket::CreateSocketForTesting(
- std::move(tcp_client_socket), FAKE_ID, true));
+TEST_P(TCPSocketUnitTest, ReadError) {
+ net::IoMode io_mode = GetParam();
+ const net::MockRead kReads[] = {
+ net::MockRead(io_mode, kTestMsg, kTestMsgLength),
+ net::MockRead(io_mode, net::ERR_INSUFFICIENT_RESOURCES)};
+ net::StaticSocketDataProvider data_provider(kReads,
+ base::span<net::MockWrite>());
+ mock_client_socket_factory()->AddSocketDataProvider(&data_provider);
+ std::unique_ptr<TCPSocket> socket = CreateAndConnectSocket();
const int count = 512;
- socket->Read(count, base::Bind(&CompleteHandler::OnReadComplete,
- base::Unretained(&handler)));
+ int net_error = net::OK;
+ while (true) {
+ base::RunLoop run_loop;
+ socket->Read(count,
+ base::BindLambdaForTesting(
+ [&](int result, scoped_refptr<net::IOBuffer> io_buffer,
+ bool socket_destroying) {
+ net_error = result;
+ EXPECT_FALSE(socket_destroying);
+ if (result <= 0) {
+ EXPECT_FALSE(socket->IsConnected());
+ EXPECT_EQ(nullptr, io_buffer);
+ } else {
+ EXPECT_TRUE(socket->IsConnected());
+ }
+ run_loop.Quit();
+ }));
+ run_loop.Run();
+ if (net_error <= 0)
+ break;
+ }
+ // Note that TCPSocket only detects that receive pipe is broken and propagates
+ // it as 0 byte read. It doesn't know the specific net error code. To know the
+ // specific net error code, it needs to register itself as a
+ // network::mojom::SocketObserver. However, that gets tricky because of two
+ // separate mojo pipes.
+ EXPECT_EQ(0, net_error);
+ EXPECT_TRUE(data_provider.AllReadDataConsumed());
+ EXPECT_TRUE(data_provider.AllWriteDataConsumed());
}
-TEST(SocketTest, TestTCPSocketWrite) {
- net::AddressList address_list;
- std::unique_ptr<MockTCPSocket> tcp_client_socket(
- new MockTCPSocket(address_list));
- CompleteHandler handler;
-
- net::CompletionCallback callback;
- EXPECT_CALL(*tcp_client_socket, Write(_, _, _, _))
- .Times(2)
- .WillRepeatedly(testing::DoAll(SaveArg<2>(&callback), Return(128)));
- EXPECT_CALL(handler, OnComplete(_))
- .Times(1);
-
- std::unique_ptr<TCPSocket> socket(TCPSocket::CreateSocketForTesting(
- std::move(tcp_client_socket), FAKE_ID, true));
-
- scoped_refptr<net::IOBufferWithSize> io_buffer(
- new net::IOBufferWithSize(256));
- socket->Write(io_buffer.get(), io_buffer->size(),
- base::Bind(&CompleteHandler::OnComplete, base::Unretained(&handler)));
+TEST_P(TCPSocketUnitTest, Write) {
+ net::IoMode io_mode = GetParam();
+ const net::MockRead kReads[] = {
+ net::MockRead(net::SYNCHRONOUS, net::ERR_IO_PENDING)};
+ const net::MockWrite kWrites[] = {
+ net::MockWrite(io_mode, kTestMsg, kTestMsgLength)};
+
+ net::StaticSocketDataProvider data_provider(kReads, kWrites);
+
+ mock_client_socket_factory()->AddSocketDataProvider(&data_provider);
+ std::unique_ptr<TCPSocket> socket = CreateAndConnectSocket();
+
+ auto io_buffer = base::MakeRefCounted<net::StringIOBuffer>(kTestMsg);
+ net::TestCompletionCallback write_callback;
+ socket->Write(io_buffer.get(), kTestMsgLength, write_callback.callback());
+ EXPECT_EQ(kTestMsgLength, write_callback.WaitForResult());
}
-TEST(SocketTest, TestTCPSocketBlockedWrite) {
- net::AddressList address_list;
- std::unique_ptr<MockTCPSocket> tcp_client_socket(
- new MockTCPSocket(address_list));
- CompleteHandler handler;
-
- net::CompletionCallback callback;
- EXPECT_CALL(*tcp_client_socket, Write(_, _, _, _))
- .Times(2)
- .WillRepeatedly(
- testing::DoAll(SaveArg<2>(&callback), Return(net::ERR_IO_PENDING)));
-
- std::unique_ptr<TCPSocket> socket(TCPSocket::CreateSocketForTesting(
- std::move(tcp_client_socket), FAKE_ID, true));
-
- scoped_refptr<net::IOBufferWithSize> io_buffer(new net::IOBufferWithSize(42));
- socket->Write(io_buffer.get(), io_buffer->size(),
- base::Bind(&CompleteHandler::OnComplete, base::Unretained(&handler)));
-
- // Good. Original call came back unable to complete. Now pretend the socket
- // finished, and confirm that we passed the error back.
- EXPECT_CALL(handler, OnComplete(42))
- .Times(1);
- callback.Run(40);
- callback.Run(2);
+// Tests the case where a message is split over two separate socket writes.
+TEST_P(TCPSocketUnitTest, MultipleWrite) {
+ const char kFirstHalfTestMsg[] = "abcde";
+ const char kSecondHalfTestMsg[] = "fghij";
+ EXPECT_EQ(kTestMsg, std::string(kFirstHalfTestMsg) + kSecondHalfTestMsg);
+ net::IoMode io_mode = GetParam();
+ const net::MockRead kReads[] = {
+ net::MockRead(net::SYNCHRONOUS, net::ERR_IO_PENDING)};
+ const net::MockWrite kWrites[] = {
+ net::MockWrite(io_mode, kFirstHalfTestMsg, strlen(kFirstHalfTestMsg)),
+ net::MockWrite(io_mode, kSecondHalfTestMsg, strlen(kSecondHalfTestMsg))};
+
+ net::StaticSocketDataProvider data_provider(kReads, kWrites);
+ mock_client_socket_factory()->AddSocketDataProvider(&data_provider);
+ std::unique_ptr<TCPSocket> socket = CreateAndConnectSocket();
+
+ int num_bytes_written = 0;
+ auto io_buffer = base::MakeRefCounted<net::StringIOBuffer>(kTestMsg);
+ auto drainable_io_buffer = base::MakeRefCounted<net::DrainableIOBuffer>(
+ io_buffer.get(), kTestMsgLength);
+ while (num_bytes_written < kTestMsgLength) {
+ net::TestCompletionCallback write_callback;
+ socket->Write(drainable_io_buffer.get(), kTestMsgLength - num_bytes_written,
+ write_callback.callback());
+ int result = write_callback.WaitForResult();
+ ASSERT_GT(result, net::OK);
+ drainable_io_buffer->DidConsume(result);
+ num_bytes_written += result;
+ // Flushes the write.
+ base::RunLoop().RunUntilIdle();
+ }
+ EXPECT_TRUE(data_provider.AllReadDataConsumed());
+ EXPECT_TRUE(data_provider.AllWriteDataConsumed());
}
-TEST(SocketTest, TestTCPSocketBlockedWriteReentry) {
- net::AddressList address_list;
- std::unique_ptr<MockTCPSocket> tcp_client_socket(
- new MockTCPSocket(address_list));
- CompleteHandler handlers[5];
-
- net::CompletionCallback callback;
- EXPECT_CALL(*tcp_client_socket, Write(_, _, _, _))
- .Times(5)
- .WillRepeatedly(
- testing::DoAll(SaveArg<2>(&callback), Return(net::ERR_IO_PENDING)));
-
- std::unique_ptr<TCPSocket> socket(TCPSocket::CreateSocketForTesting(
- std::move(tcp_client_socket), FAKE_ID, true));
-
- scoped_refptr<net::IOBufferWithSize> io_buffers[5];
- int i;
- for (i = 0; i < 5; i++) {
- io_buffers[i] = new net::IOBufferWithSize(128 + i * 50);
- scoped_refptr<net::IOBufferWithSize> io_buffer1(
- new net::IOBufferWithSize(42));
- socket->Write(io_buffers[i].get(), io_buffers[i]->size(),
- base::Bind(&CompleteHandler::OnComplete,
- base::Unretained(&handlers[i])));
-
- EXPECT_CALL(handlers[i], OnComplete(io_buffers[i]->size()))
- .Times(1);
+TEST_P(TCPSocketUnitTest, PartialWrite) {
+ net::IoMode io_mode = GetParam();
+ const net::MockRead kReads[] = {
+ net::MockRead(net::SYNCHRONOUS, net::ERR_IO_PENDING)};
+ const net::MockWrite kWrites[] = {
+ net::MockWrite(io_mode, "a", 1), net::MockWrite(io_mode, "bc", 2),
+ net::MockWrite(io_mode, "defg", 4), net::MockWrite(io_mode, "hij", 3)};
+
+ net::StaticSocketDataProvider data_provider(kReads, kWrites);
+
+ mock_client_socket_factory()->AddSocketDataProvider(&data_provider);
+ std::unique_ptr<TCPSocket> socket = CreateAndConnectSocket();
+
+ // Start with writing one byte, and double that in the next iteration.
+ int num_bytes_to_write = 1;
+ int num_bytes_written = 0;
+ auto io_buffer = base::MakeRefCounted<net::StringIOBuffer>(kTestMsg);
+ auto drainable_io_buffer = base::MakeRefCounted<net::DrainableIOBuffer>(
+ io_buffer.get(), kTestMsgLength);
+ while (num_bytes_written < kTestMsgLength) {
+ net::TestCompletionCallback write_callback;
+ socket->Write(
+ drainable_io_buffer.get(),
+ std::max(kTestMsgLength - num_bytes_written, num_bytes_to_write),
+ write_callback.callback());
+ int result = write_callback.WaitForResult();
+ ASSERT_GT(result, net::OK);
+ drainable_io_buffer->DidConsume(result);
+ num_bytes_written += result;
+ num_bytes_to_write *= 2;
+ // Flushes the write.
+ base::RunLoop().RunUntilIdle();
}
+ EXPECT_TRUE(data_provider.AllReadDataConsumed());
+ EXPECT_TRUE(data_provider.AllWriteDataConsumed());
+}
- for (i = 0; i < 5; i++) {
- callback.Run(128 + i * 50);
+TEST_P(TCPSocketUnitTest, WriteError) {
+ net::IoMode io_mode = GetParam();
+ const net::MockRead kReads[] = {
+ net::MockRead(net::SYNCHRONOUS, net::ERR_IO_PENDING)};
+ const net::MockWrite kWrites[] = {
+ net::MockWrite(io_mode, net::ERR_INSUFFICIENT_RESOURCES)};
+
+ net::StaticSocketDataProvider data_provider(kReads, kWrites);
+
+ mock_client_socket_factory()->AddSocketDataProvider(&data_provider);
+ std::unique_ptr<TCPSocket> socket = CreateAndConnectSocket();
+
+ // Mojo data pipe might buffer some write data, so continue writing until the
+ // write error is received.
+ auto io_buffer = base::MakeRefCounted<net::StringIOBuffer>(kTestMsg);
+ int net_error = net::OK;
+ while (true) {
+ base::RunLoop run_loop;
+ socket->Write(io_buffer.get(), kTestMsgLength,
+ base::BindLambdaForTesting([&](int result) {
+ EXPECT_EQ(result > 0, socket->IsConnected());
+ net_error = result;
+ run_loop.Quit();
+ }));
+ run_loop.Run();
+ if (net_error <= 0)
+ break;
}
+ // Note that TCPSocket only detects that send pipe is broken and propagates
+ // it as a net::ERR_FAILED. It doesn't know the specific net error code. To do
+ // that, it needs to register itself as a network::mojom::SocketObserver.
+ EXPECT_EQ(net::ERR_FAILED, net_error);
+ EXPECT_TRUE(data_provider.AllReadDataConsumed());
+ EXPECT_TRUE(data_provider.AllWriteDataConsumed());
}
-TEST(SocketTest, TestTCPSocketSetNoDelay) {
- net::AddressList address_list;
- std::unique_ptr<MockTCPSocket> tcp_client_socket(
- new MockTCPSocket(address_list));
+namespace {
- bool no_delay = false;
- {
- testing::InSequence dummy;
- EXPECT_CALL(*tcp_client_socket, SetNoDelay(_))
- .WillOnce(testing::DoAll(SaveArg<0>(&no_delay), Return(true)));
- EXPECT_CALL(*tcp_client_socket, SetNoDelay(_))
- .WillOnce(testing::DoAll(SaveArg<0>(&no_delay), Return(false)));
+class ExtensionsMockClientSocket : public net::MockTCPClientSocket {
+ public:
+ ExtensionsMockClientSocket(net::SocketDataProvider* provider, bool success)
+ : MockTCPClientSocket(
+ net::AddressList(
+ net::IPEndPoint(net::IPAddress::IPv4Localhost(), 1234)),
+ nullptr /* netlog */,
+ provider),
+ success_(success) {
+ this->set_enable_read_if_ready(true);
}
+ ~ExtensionsMockClientSocket() override {}
- std::unique_ptr<TCPSocket> socket(
- TCPSocket::CreateSocketForTesting(std::move(tcp_client_socket), FAKE_ID));
+ bool SetNoDelay(bool no_delay) override { return success_; }
+ bool SetKeepAlive(bool enable, int delay) override { return success_; }
- EXPECT_FALSE(no_delay);
- int result = socket->SetNoDelay(true);
- EXPECT_TRUE(result);
- EXPECT_TRUE(no_delay);
+ private:
+ // Whether to return success for SetNoDelay() and SetKeepAlive().
+ const bool success_;
- result = socket->SetNoDelay(false);
- EXPECT_FALSE(result);
- EXPECT_FALSE(no_delay);
-}
+ DISALLOW_COPY_AND_ASSIGN(ExtensionsMockClientSocket);
+};
-TEST(SocketTest, TestTCPSocketSetKeepAlive) {
- net::AddressList address_list;
- std::unique_ptr<MockTCPSocket> tcp_client_socket(
- new MockTCPSocket(address_list));
+static const net::MockRead kMockReads[] = {net::MockRead(net::ASYNC, net::OK)};
- bool enable = false;
- int delay = 0;
- {
- testing::InSequence dummy;
- EXPECT_CALL(*tcp_client_socket, SetKeepAlive(_, _))
- .WillOnce(testing::DoAll(SaveArg<0>(&enable), SaveArg<1>(&delay),
- Return(true)));
- EXPECT_CALL(*tcp_client_socket, SetKeepAlive(_, _))
- .WillOnce(testing::DoAll(SaveArg<0>(&enable), SaveArg<1>(&delay),
- Return(false)));
+// A ClientSocketFactory to create sockets that simulate SetNoDelay and
+// SetKeepAlive success and failures.
+class TestSocketFactory : public net::ClientSocketFactory {
+ public:
+ explicit TestSocketFactory(bool success) : success_(success) {}
+ ~TestSocketFactory() override = default;
+
+ std::unique_ptr<net::DatagramClientSocket> CreateDatagramClientSocket(
+ net::DatagramSocket::BindType,
+ net::NetLog*,
+ const net::NetLogSource&) override {
+ NOTIMPLEMENTED();
+ return nullptr;
+ }
+ std::unique_ptr<net::TransportClientSocket> CreateTransportClientSocket(
+ const net::AddressList&,
+ std::unique_ptr<net::SocketPerformanceWatcher>,
+ net::NetLog*,
+ const net::NetLogSource&) override {
+ providers_.push_back(std::make_unique<net::StaticSocketDataProvider>(
+ kMockReads, base::span<net::MockWrite>()));
+ return std::make_unique<ExtensionsMockClientSocket>(providers_.back().get(),
+ success_);
+ }
+ std::unique_ptr<net::SSLClientSocket> CreateSSLClientSocket(
+ std::unique_ptr<net::ClientSocketHandle>,
+ const net::HostPortPair&,
+ const net::SSLConfig&,
+ const net::SSLClientSocketContext&) override {
+ NOTIMPLEMENTED();
+ return std::unique_ptr<net::SSLClientSocket>();
+ }
+ std::unique_ptr<net::ProxyClientSocket> CreateProxyClientSocket(
+ std::unique_ptr<net::ClientSocketHandle> transport_socket,
+ const std::string& user_agent,
+ const net::HostPortPair& endpoint,
+ net::HttpAuthController* http_auth_controller,
+ bool tunnel,
+ bool using_spdy,
+ net::NextProto negotiated_protocol,
+ bool is_https_proxy,
+ const net::NetworkTrafficAnnotationTag& traffic_annotation) override {
+ NOTIMPLEMENTED();
+ return nullptr;
+ }
+ void ClearSSLSessionCache() override { NOTIMPLEMENTED(); }
+
+ private:
+ std::vector<std::unique_ptr<net::StaticSocketDataProvider>> providers_;
+ // Whether to return success for net::TransportClientSocket::SetNoDelay() and
+ // SetKeepAlive().
+ const bool success_;
+
+ DISALLOW_COPY_AND_ASSIGN(TestSocketFactory);
+};
+
+} // namespace
+
+class TCPSocketSettingsTest : public TCPSocketUnitTestBase,
+ public ::testing::WithParamInterface<bool> {
+ public:
+ TCPSocketSettingsTest()
+ : TCPSocketUnitTestBase(), client_socket_factory_(GetParam()) {
+ url_request_context_.set_client_socket_factory(&client_socket_factory_);
+ Initialize();
}
+ ~TCPSocketSettingsTest() override {}
- std::unique_ptr<TCPSocket> socket(
- TCPSocket::CreateSocketForTesting(std::move(tcp_client_socket), FAKE_ID));
+ private:
+ TestSocketFactory client_socket_factory_;
+};
- EXPECT_FALSE(enable);
- int result = socket->SetKeepAlive(true, 4500);
- EXPECT_TRUE(result);
- EXPECT_TRUE(enable);
- EXPECT_EQ(4500, delay);
+INSTANTIATE_TEST_CASE_P(/* no prefix */,
+ TCPSocketSettingsTest,
+ testing::Bool());
- result = socket->SetKeepAlive(false, 0);
- EXPECT_FALSE(result);
- EXPECT_FALSE(enable);
- EXPECT_EQ(0, delay);
+TEST_P(TCPSocketSettingsTest, SetNoDelay) {
+ std::unique_ptr<TCPSocket> socket = CreateAndConnectSocket();
+ bool expected_success = GetParam();
+ {
+ base::RunLoop run_loop;
+ socket->SetNoDelay(true, base::BindLambdaForTesting([&](bool success) {
+ EXPECT_EQ(expected_success, success);
+ run_loop.Quit();
+ }));
+ run_loop.Run();
+ }
+
+ {
+ base::RunLoop run_loop;
+ socket->SetNoDelay(false, base::BindLambdaForTesting([&](bool success) {
+ EXPECT_EQ(expected_success, success);
+ run_loop.Quit();
+ }));
+ run_loop.Run();
+ }
}
-TEST(SocketTest, TestTCPServerSocketListenAccept) {
- std::unique_ptr<MockTCPServerSocket> tcp_server_socket(
- new MockTCPServerSocket());
- CompleteHandler handler;
+TEST_P(TCPSocketSettingsTest, SetKeepAlive) {
+ std::unique_ptr<TCPSocket> socket = CreateAndConnectSocket();
+ bool expected_success = GetParam();
+ {
+ base::RunLoop run_loop;
+ socket->SetKeepAlive(true /* enable */, 123 /* delay */,
+ base::BindLambdaForTesting([&](bool success) {
+ EXPECT_EQ(expected_success, success);
+ run_loop.Quit();
+ }));
+ run_loop.Run();
+ }
- EXPECT_CALL(*tcp_server_socket, Accept(_, _)).Times(1);
- EXPECT_CALL(*tcp_server_socket, Listen(_, _)).Times(1);
+ {
+ base::RunLoop run_loop;
+ socket->SetKeepAlive(false /* enable */, 123 /* delay */,
+ base::BindLambdaForTesting([&](bool success) {
+ EXPECT_EQ(expected_success, success);
+ run_loop.Quit();
+ }));
+ run_loop.Run();
+ }
+}
+
+class TCPSocketServerTest : public TCPSocketUnitTestBase {
+ public:
+ TCPSocketServerTest() : TCPSocketUnitTestBase() { Initialize(); }
+ ~TCPSocketServerTest() override {}
- std::unique_ptr<TCPSocket> socket(TCPSocket::CreateServerSocketForTesting(
- std::move(tcp_server_socket), FAKE_ID));
+ private:
+ net::MockClientSocketFactory mock_client_socket_factory_;
+};
- EXPECT_CALL(handler, OnAcceptMock(_, _));
+TEST_F(TCPSocketServerTest, ListenAccept) {
+ // Create a server socket.
+ std::unique_ptr<TCPSocket> socket = CreateSocket();
+ net::TestCompletionCallback callback;
+ base::RunLoop run_loop;
+ socket->Listen(
+ "127.0.0.1", 0 /* port */, 1 /* backlog */,
+ base::BindLambdaForTesting([&](int result, const std::string& error_msg) {
+ EXPECT_EQ(net::OK, result);
+ run_loop.Quit();
+ }));
+ run_loop.Run();
+ net::IPEndPoint server_addr;
+ EXPECT_TRUE(socket->GetLocalAddress(&server_addr));
+
+ base::RunLoop accept_run_loop;
+ net::IPEndPoint accept_client_addr;
+ socket->Accept(base::BindLambdaForTesting(
+ [&](int result, network::mojom::TCPConnectedSocketPtr accepted_socket,
+ const base::Optional<net::IPEndPoint>& remote_addr,
+ mojo::ScopedDataPipeConsumerHandle receive_handle,
+ mojo::ScopedDataPipeProducerHandle send_handle) {
+ EXPECT_EQ(net::OK, result);
+ accept_client_addr = remote_addr.value();
+ accept_run_loop.Quit();
+ }));
+
+ // Create a client socket to talk to the server socket.
+ auto client_socket = CreateAndConnectSocketWithAddress(server_addr);
+ accept_run_loop.Run();
+
+ net::IPEndPoint peer_addr;
+ EXPECT_TRUE(client_socket->GetPeerAddress(&peer_addr));
+ net::IPEndPoint client_addr;
+ EXPECT_TRUE(client_socket->GetLocalAddress(&client_addr));
+ EXPECT_EQ(server_addr, peer_addr);
+ EXPECT_EQ(client_addr, accept_client_addr);
+}
- std::string err_msg;
- EXPECT_EQ(net::OK, socket->Listen("127.0.0.1", 9999, 10, &err_msg));
- socket->Accept(base::Bind(&CompleteHandler::OnAccept,
- base::Unretained(&handler)));
+TEST_F(TCPSocketServerTest, ReadAndWrite) {
+ // Create a server socket.
+ std::unique_ptr<TCPSocket> socket = CreateSocket();
+ net::TestCompletionCallback callback;
+ base::RunLoop run_loop;
+ socket->Listen(
+ "127.0.0.1", 0 /* port */, 1 /* backlog */,
+ base::BindLambdaForTesting([&](int result, const std::string& error_msg) {
+ EXPECT_EQ(net::OK, result);
+ run_loop.Quit();
+ }));
+ run_loop.Run();
+ net::IPEndPoint server_addr;
+ EXPECT_TRUE(socket->GetLocalAddress(&server_addr));
+
+ base::RunLoop accept_run_loop;
+ std::unique_ptr<TCPSocket> accepted_socket;
+
+ socket->Accept(base::BindLambdaForTesting(
+ [&](int result, network::mojom::TCPConnectedSocketPtr connected_socket,
+ const base::Optional<net::IPEndPoint>& remote_addr,
+ mojo::ScopedDataPipeConsumerHandle receive_handle,
+ mojo::ScopedDataPipeProducerHandle send_handle) {
+ EXPECT_EQ(net::OK, result);
+ accepted_socket = std::make_unique<TCPSocket>(
+ std::move(connected_socket), std::move(receive_handle),
+ std::move(send_handle), remote_addr, FAKE_ID);
+ accept_run_loop.Quit();
+ }));
+
+ // Create a client socket to talk to the server socket.
+ auto client_socket = CreateAndConnectSocketWithAddress(server_addr);
+ net::TestCompletionCallback connect_callback;
+ accept_run_loop.Run();
+
+ // Send data from the client to the server.
+ auto io_buffer = base::MakeRefCounted<net::StringIOBuffer>(kTestMsg);
+ net::TestCompletionCallback write_callback;
+ client_socket->Write(io_buffer.get(), kTestMsgLength,
+ write_callback.callback());
+ EXPECT_EQ(kTestMsgLength, write_callback.WaitForResult());
+
+ std::string received_contents;
+ while (received_contents.size() < kTestMsgLength) {
+ base::RunLoop run_loop;
+ accepted_socket->Read(
+ kTestMsgLength,
+ base::BindLambdaForTesting([&](int result,
+ scoped_refptr<net::IOBuffer> io_buffer,
+ bool socket_destroying) {
+ ASSERT_GT(result, 0);
+ EXPECT_FALSE(socket_destroying);
+ received_contents.append(std::string(io_buffer->data(), result));
+ run_loop.Quit();
+ }));
+ run_loop.Run();
+ }
+ EXPECT_EQ(kTestMsg, received_contents);
+
+ // Send data from the server to the client.
+ net::TestCompletionCallback write_callback2;
+ accepted_socket->Write(io_buffer.get(), kTestMsgLength,
+ write_callback2.callback());
+ EXPECT_EQ(kTestMsgLength, write_callback2.WaitForResult());
+
+ std::string sent_contents;
+ while (sent_contents.size() < kTestMsgLength) {
+ base::RunLoop run_loop;
+ client_socket->Read(
+ kTestMsgLength,
+ base::BindLambdaForTesting([&](int result,
+ scoped_refptr<net::IOBuffer> io_buffer,
+ bool socket_destroying) {
+ ASSERT_GT(result, 0);
+ EXPECT_FALSE(socket_destroying);
+ sent_contents.append(std::string(io_buffer->data(), result));
+ run_loop.Quit();
+ }));
+ run_loop.Run();
+ }
+ EXPECT_EQ(kTestMsg, sent_contents);
}
} // namespace extensions
diff --git a/chromium/chrome/browser/extensions/api/socket/tls_socket_unittest.cc b/chromium/chrome/browser/extensions/api/socket/tls_socket_unittest.cc
index 678b630744e..16fa23874e7 100644
--- a/chromium/chrome/browser/extensions/api/socket/tls_socket_unittest.cc
+++ b/chromium/chrome/browser/extensions/api/socket/tls_socket_unittest.cc
@@ -2,372 +2,488 @@
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
-#include <stddef.h>
-#include <stdint.h>
-
#include <memory>
#include <utility>
-#include "base/callback_helpers.h"
-#include "base/containers/circular_deque.h"
#include "base/macros.h"
-#include "base/strings/string_piece.h"
+#include "base/test/bind_test_util.h"
+#include "chrome/browser/extensions/extension_service_test_base.h"
+#include "chrome/test/base/testing_profile.h"
+#include "content/public/browser/browser_context.h"
+#include "content/public/test/test_storage_partition.h"
#include "extensions/browser/api/socket/tls_socket.h"
#include "net/base/address_list.h"
#include "net/base/completion_callback.h"
#include "net/base/io_buffer.h"
#include "net/base/net_errors.h"
-#include "net/base/rand_callback.h"
-#include "net/log/net_log_source.h"
-#include "net/log/net_log_with_source.h"
-#include "net/socket/next_proto.h"
-#include "net/socket/socket_tag.h"
-#include "net/socket/ssl_client_socket.h"
-#include "net/socket/tcp_client_socket.h"
-#include "net/traffic_annotation/network_traffic_annotation.h"
-#include "testing/gmock/include/gmock/gmock.h"
-
-using testing::_;
-using testing::DoAll;
-using testing::Invoke;
-using testing::Gt;
-using testing::Return;
-using testing::SaveArg;
-using testing::WithArgs;
-using base::StringPiece;
+#include "net/base/test_completion_callback.h"
+#include "net/socket/socket_test_util.h"
+#include "net/url_request/url_request_test_util.h"
+#include "services/network/network_context.h"
+#include "services/network/public/mojom/network_context.mojom.h"
namespace extensions {
-class MockSSLClientSocket : public net::SSLClientSocket {
+namespace {
+
+const char kTestMsg[] = "abcdefghij";
+const int kTestMsgLength = strlen(kTestMsg);
+
+const char FAKE_ID[] = "abcdefghijklmnopqrst";
+
+class TLSSocketTestBase : public extensions::ExtensionServiceTestBase {
public:
- MockSSLClientSocket() {}
- int Read(net::IOBuffer* buffer,
- int bytes,
- net::CompletionOnceCallback callback) override {
- return Read(buffer, bytes,
- base::AdaptCallbackForRepeating(std::move(callback)));
+ TLSSocketTestBase() : url_request_context_(true) {}
+ ~TLSSocketTestBase() override {}
+
+ // Creates a TCP socket.
+ std::unique_ptr<TCPSocket> CreateTCPSocket() {
+ auto socket = std::make_unique<TCPSocket>(&profile_, FAKE_ID);
+ socket->SetStoragePartitionForTest(&partition_);
+ net::TestCompletionCallback connect_callback;
+ net::IPEndPoint ip_end_point(net::IPAddress::IPv4Localhost(), kPort);
+ socket->Connect(net::AddressList(ip_end_point),
+ connect_callback.callback());
+ if (net::OK != connect_callback.WaitForResult()) {
+ return nullptr;
+ }
+ return socket;
}
- int Write(net::IOBuffer* buffer,
- int bytes,
- net::CompletionOnceCallback callback,
- const net::NetworkTrafficAnnotationTag& tag) override {
- return Write(buffer, bytes,
- base::AdaptCallbackForRepeating(std::move(callback)), tag);
+ // Create a TCP socket and upgrade it to TLS.
+ std::unique_ptr<TLSSocket> CreateSocket() {
+ auto socket = CreateTCPSocket();
+ if (!socket)
+ return nullptr;
+ base::RunLoop run_loop;
+ net::HostPortPair host_port_pair("example.com", kPort);
+ net::IPEndPoint local_addr;
+ net::IPEndPoint peer_addr;
+ if (!socket->GetLocalAddress(&local_addr) ||
+ !socket->GetPeerAddress(&peer_addr)) {
+ return nullptr;
+ }
+ std::unique_ptr<TLSSocket> tls_socket;
+ socket->UpgradeToTLS(
+ nullptr /* options */,
+ base::BindLambdaForTesting(
+ [&](int result, network::mojom::TLSClientSocketPtr tls_socket_ptr,
+ const net::IPEndPoint& local_addr,
+ const net::IPEndPoint& peer_addr,
+ mojo::ScopedDataPipeConsumerHandle receive_handle,
+ mojo::ScopedDataPipeProducerHandle send_handle) {
+ if (net::OK == result) {
+ tls_socket = std::make_unique<TLSSocket>(
+ std::move(tls_socket_ptr), local_addr, peer_addr,
+ std::move(receive_handle), std::move(send_handle), FAKE_ID);
+ }
+ run_loop.Quit();
+ }));
+ run_loop.Run();
+ return tls_socket;
}
- int Connect(net::CompletionOnceCallback callback) override {
- return Connect(base::AdaptCallbackForRepeating(std::move(callback)));
+ protected:
+ // extensions::ExtensionServiceTestBase implementation.
+ void SetUp() override { InitializeEmptyExtensionService(); }
+
+ void Initialize() {
+ url_request_context_.Init();
+ network_context_ = std::make_unique<network::NetworkContext>(
+ nullptr, mojo::MakeRequest(&network_context_ptr_),
+ &url_request_context_);
+ partition_.set_network_context(network_context_ptr_.get());
}
- MOCK_METHOD0(Disconnect, void());
- MOCK_METHOD3(Read,
- int(net::IOBuffer* buf,
- int buf_len,
- const net::CompletionCallback& callback));
- MOCK_METHOD4(Write,
- int(net::IOBuffer* buf,
- int buf_len,
- const net::CompletionCallback& callback,
- const net::NetworkTrafficAnnotationTag&));
- MOCK_METHOD1(SetReceiveBufferSize, int(int32_t));
- MOCK_METHOD1(SetSendBufferSize, int(int32_t));
- MOCK_METHOD1(Connect, int(const CompletionCallback&));
- MOCK_CONST_METHOD0(IsConnectedAndIdle, bool());
- MOCK_CONST_METHOD1(GetPeerAddress, int(net::IPEndPoint*));
- MOCK_CONST_METHOD1(GetLocalAddress, int(net::IPEndPoint*));
- MOCK_CONST_METHOD0(NetLog, const net::NetLogWithSource&());
- MOCK_CONST_METHOD0(WasEverUsed, bool());
- MOCK_CONST_METHOD0(UsingTCPFastOpen, bool());
- MOCK_CONST_METHOD0(WasAlpnNegotiated, bool());
- MOCK_CONST_METHOD0(GetNegotiatedProtocol, net::NextProto());
- MOCK_METHOD1(GetSSLInfo, bool(net::SSLInfo*));
- MOCK_CONST_METHOD1(GetConnectionAttempts, void(net::ConnectionAttempts*));
- MOCK_METHOD0(ClearConnectionAttempts, void());
- MOCK_METHOD1(AddConnectionAttempts, void(const net::ConnectionAttempts&));
- MOCK_CONST_METHOD0(GetTotalReceivedBytes, int64_t());
- MOCK_METHOD1(ApplySocketTag, void(const net::SocketTag&));
- MOCK_METHOD5(ExportKeyingMaterial,
- int(const StringPiece&,
- bool,
- const StringPiece&,
- unsigned char*,
- unsigned int));
- MOCK_CONST_METHOD1(GetSSLCertRequestInfo, void(net::SSLCertRequestInfo*));
- MOCK_CONST_METHOD0(GetUnverifiedServerCertificateChain,
- scoped_refptr<net::X509Certificate>());
- MOCK_CONST_METHOD0(GetChannelIDService, net::ChannelIDService*());
- MOCK_METHOD3(GetTokenBindingSignature,
- net::Error(crypto::ECPrivateKey*,
- net::TokenBindingType,
- std::vector<uint8_t>*));
- MOCK_CONST_METHOD0(GetChannelIDKey, crypto::ECPrivateKey*());
- bool IsConnected() const override { return true; }
+ net::TestURLRequestContext url_request_context_;
private:
- DISALLOW_COPY_AND_ASSIGN(MockSSLClientSocket);
+ static const int kPort = 1234;
+ TestingProfile profile_;
+ content::TestStoragePartition partition_;
+ std::unique_ptr<network::NetworkContext> network_context_;
+ network::mojom::NetworkContextPtr network_context_ptr_;
};
-class MockTCPSocket : public net::TCPClientSocket {
+} // namespace
+
+class TLSSocketTest : public TLSSocketTestBase,
+ public ::testing::WithParamInterface<net::IoMode> {
public:
- explicit MockTCPSocket(const net::AddressList& address_list)
- : net::TCPClientSocket(address_list, NULL, NULL, net::NetLogSource()) {}
-
- int Read(net::IOBuffer* buffer,
- int bytes,
- net::CompletionOnceCallback callback) override {
- return Read(buffer, bytes,
- base::AdaptCallbackForRepeating(std::move(callback)));
+ TLSSocketTest() : TLSSocketTestBase() {
+ mock_client_socket_factory_.set_enable_read_if_ready(true);
+ url_request_context_.set_client_socket_factory(
+ &mock_client_socket_factory_);
+ Initialize();
}
+ ~TLSSocketTest() override {}
- int Write(net::IOBuffer* buffer,
- int bytes,
- net::CompletionOnceCallback callback,
- const net::NetworkTrafficAnnotationTag& tag) override {
- return Write(buffer, bytes,
- base::AdaptCallbackForRepeating(std::move(callback)), tag);
+ net::MockClientSocketFactory* mock_client_socket_factory() {
+ return &mock_client_socket_factory_;
}
- MOCK_METHOD3(Read,
- int(net::IOBuffer* buf,
- int buf_len,
- const net::CompletionCallback& callback));
- MOCK_METHOD4(Write,
- int(net::IOBuffer* buf,
- int buf_len,
- const net::CompletionCallback& callback,
- const net::NetworkTrafficAnnotationTag&));
- MOCK_METHOD2(SetKeepAlive, bool(bool enable, int delay));
- MOCK_METHOD1(SetNoDelay, bool(bool no_delay));
-
- bool IsConnected() const override { return true; }
-
private:
- DISALLOW_COPY_AND_ASSIGN(MockTCPSocket);
+ net::MockClientSocketFactory mock_client_socket_factory_;
};
-class CompleteHandler {
- public:
- CompleteHandler() {}
- MOCK_METHOD1(OnComplete, void(int result_code));
- MOCK_METHOD3(OnReadComplete,
- void(int result_code,
- scoped_refptr<net::IOBuffer> io_buffer,
- bool socket_destroying));
- MOCK_METHOD2(OnAccept, void(int, net::TCPClientSocket*));
-
- private:
- DISALLOW_COPY_AND_ASSIGN(CompleteHandler);
-};
-
-class TLSSocketTest : public ::testing::Test {
- public:
- TLSSocketTest() {}
-
- void SetUp() override {
- net::AddressList address_list;
- // |ssl_socket_| is owned by |socket_|. TLSSocketTest keeps a pointer to
- // it to expect invocations from TLSSocket to |ssl_socket_|.
- std::unique_ptr<MockSSLClientSocket> ssl_sock(new MockSSLClientSocket);
- ssl_socket_ = ssl_sock.get();
- socket_.reset(new TLSSocket(std::move(ssl_sock), "test_extension_id"));
- EXPECT_CALL(*ssl_socket_, Disconnect()).Times(1);
- };
-
- void TearDown() override {
- ssl_socket_ = NULL;
- socket_.reset();
- };
-
- protected:
- MockSSLClientSocket* ssl_socket_;
- std::unique_ptr<TLSSocket> socket_;
-};
-
-// Verify that a Read() on TLSSocket will pass through into a Read() on
-// |ssl_socket_| and invoke its completion callback.
-TEST_F(TLSSocketTest, TestTLSSocketRead) {
- CompleteHandler handler;
-
- EXPECT_CALL(*ssl_socket_, Read(_, _, _)).Times(1);
- EXPECT_CALL(handler, OnReadComplete(_, _, _)).Times(1);
-
- const int count = 512;
- socket_->Read(
- count,
- base::Bind(&CompleteHandler::OnReadComplete, base::Unretained(&handler)));
+TEST_F(TLSSocketTest, DestroyWhileReadPending) {
+ const net::MockRead kReads[] = {net::MockRead(net::SYNCHRONOUS, net::OK, 1)};
+ const net::MockWrite kWrites[] = {
+ net::MockWrite(net::ASYNC, kTestMsg, kTestMsgLength, 0)};
+ net::StaticSocketDataProvider data_provider(kReads, kWrites);
+ mock_client_socket_factory()->AddSocketDataProvider(&data_provider);
+ net::SSLSocketDataProvider ssl_socket(net::ASYNC, net::OK);
+ mock_client_socket_factory()->AddSSLSocketDataProvider(&ssl_socket);
+
+ std::unique_ptr<TLSSocket> socket = CreateSocket();
+
+ int net_result = net::ERR_FAILED;
+ base::RunLoop run_loop;
+ int count = 1;
+ // Read one byte, and it should be pending because it is blocked on the mock
+ // write.
+ socket->Read(count,
+ base::BindLambdaForTesting(
+ [&](int result, scoped_refptr<net::IOBuffer> io_buffer,
+ bool socket_destroying) {
+ net_result = result;
+ // |socket_destroying| should correctly denote that this
+ // read callback is invoked through the destructor of
+ // TLSSocket.
+ EXPECT_TRUE(socket_destroying);
+ run_loop.Quit();
+ }));
+ // Destroy socket.
+ socket = nullptr;
+ // Wait for read callback.
+ run_loop.Run();
+ EXPECT_EQ(net::ERR_CONNECTION_CLOSED, net_result);
}
-// Verify that a Write() on a TLSSocket will pass through to Write()
-// invocations on |ssl_socket_|, handling partial writes correctly, and calls
-// the completion callback correctly.
-TEST_F(TLSSocketTest, TestTLSSocketWrite) {
- CompleteHandler handler;
- net::CompletionCallback callback;
-
- EXPECT_CALL(*ssl_socket_, Write(_, _, _, _))
- .Times(2)
- .WillRepeatedly(DoAll(SaveArg<2>(&callback), Return(128)));
- EXPECT_CALL(handler, OnComplete(_)).Times(1);
-
- scoped_refptr<net::IOBufferWithSize> io_buffer(
- new net::IOBufferWithSize(256));
- socket_->Write(
- io_buffer.get(),
- io_buffer->size(),
- base::Bind(&CompleteHandler::OnComplete, base::Unretained(&handler)));
+// UpgradeToTLS() fails when there is a pending read.
+TEST_F(TLSSocketTest, UpgradeToTLSWhilePendingRead) {
+ const net::MockRead kReads[] = {
+ net::MockRead(net::ASYNC, net::ERR_IO_PENDING)};
+ net::StaticSocketDataProvider data_provider(kReads,
+ base::span<net::MockWrite>());
+ mock_client_socket_factory()->AddSocketDataProvider(&data_provider);
+ auto socket = CreateTCPSocket();
+ // This read will be pending when UpgradeToTLS() is called.
+ socket->Read(1 /* count */, base::DoNothing());
+ network::mojom::TLSClientSocketPtr tls_socket_ptr;
+ base::RunLoop run_loop;
+ socket->UpgradeToTLS(
+ nullptr /* options */,
+ base::BindLambdaForTesting(
+ [&](int result, network::mojom::TLSClientSocketPtr tls_socket_ptr,
+ const net::IPEndPoint& local_addr,
+ const net::IPEndPoint& peer_addr,
+ mojo::ScopedDataPipeConsumerHandle receive_handle,
+ mojo::ScopedDataPipeProducerHandle send_handle) {
+ EXPECT_EQ(net::ERR_FAILED, result);
+ run_loop.Quit();
+ }));
+ run_loop.Run();
}
-// Simulate a blocked Write, and verify that, when simulating the Write going
-// through, the callback gets invoked.
-TEST_F(TLSSocketTest, TestTLSSocketBlockedWrite) {
- CompleteHandler handler;
- net::CompletionCallback callback;
-
- // Return ERR_IO_PENDING to say the Write()'s blocked. Save the |callback|
- // Write()'s passed.
- EXPECT_CALL(*ssl_socket_, Write(_, _, _, _))
- .Times(2)
- .WillRepeatedly(
- DoAll(SaveArg<2>(&callback), Return(net::ERR_IO_PENDING)));
-
- scoped_refptr<net::IOBufferWithSize> io_buffer(new net::IOBufferWithSize(42));
- socket_->Write(
- io_buffer.get(),
- io_buffer->size(),
- base::Bind(&CompleteHandler::OnComplete, base::Unretained(&handler)));
-
- // After the simulated asynchronous writes come back (via calls to
- // callback.Run()), hander's OnComplete() should get invoked with the total
- // amount written.
- EXPECT_CALL(handler, OnComplete(42)).Times(1);
- callback.Run(40);
- callback.Run(2);
+TEST_F(TLSSocketTest, UpgradeToTLSWithCustomOptions) {
+ // Mock data are not consumed. These are here so that net::StreamSocket::Read
+ // is always pending and blocked on the write. Otherwise, mock socket data
+ // will complains that there aren't any data to read.
+ const net::MockRead kReads[] = {
+ net::MockRead(net::ASYNC, kTestMsg, kTestMsgLength, 1),
+ net::MockRead(net::ASYNC, net::OK, 2)};
+ const net::MockWrite kWrites[] = {
+ net::MockWrite(net::ASYNC, kTestMsg, kTestMsgLength, 0)};
+ net::SequencedSocketData data_provider(kReads, kWrites);
+ net::SSLSocketDataProvider ssl_socket(net::ASYNC, net::OK);
+ ssl_socket.expected_ssl_version_min = net::SSL_PROTOCOL_VERSION_TLS1_1;
+ ssl_socket.expected_ssl_version_max = net::SSL_PROTOCOL_VERSION_TLS1_2;
+ mock_client_socket_factory()->AddSocketDataProvider(&data_provider);
+ mock_client_socket_factory()->AddSSLSocketDataProvider(&ssl_socket);
+
+ auto socket = CreateTCPSocket();
+ network::mojom::TLSClientSocketPtr tls_socket_ptr;
+ api::socket::SecureOptions options;
+ options.tls_version = std::make_unique<api::socket::TLSVersionConstraints>();
+ options.tls_version->min = std::make_unique<std::string>("tls1.1");
+ options.tls_version->max = std::make_unique<std::string>("tls1.2");
+ int net_error = net::ERR_FAILED;
+ base::RunLoop run_loop;
+ socket->UpgradeToTLS(
+ &options,
+ base::BindLambdaForTesting(
+ [&](int result, network::mojom::TLSClientSocketPtr tls_socket_ptr,
+ const net::IPEndPoint& local_addr,
+ const net::IPEndPoint& peer_addr,
+ mojo::ScopedDataPipeConsumerHandle receive_handle,
+ mojo::ScopedDataPipeProducerHandle send_handle) {
+ net_error = result;
+ run_loop.Quit();
+ }));
+ run_loop.Run();
+ EXPECT_EQ(net::OK, net_error);
+ EXPECT_TRUE(ssl_socket.ConnectDataConsumed());
}
-// Simulate multiple blocked Write()s.
-TEST_F(TLSSocketTest, TestTLSSocketBlockedWriteReentry) {
- const int kNumIOs = 5;
- CompleteHandler handlers[kNumIOs];
- net::CompletionCallback callback;
- scoped_refptr<net::IOBufferWithSize> io_buffers[kNumIOs];
-
- // The implementation of TLSSocket::Write() is inherited from
- // Socket::Write(), which implements an internal write queue that wraps
- // TLSSocket::WriteImpl(). Each call from TLSSocket::WriteImpl() will invoke
- // |ssl_socket_|'s Write() (mocked here). Save the |callback| (assume they
- // will all be equivalent), and return ERR_IO_PENDING, to indicate a blocked
- // request. The mocked SSLClientSocket::Write() will get one request per
- // TLSSocket::Write() request invoked on |socket_| below.
- EXPECT_CALL(*ssl_socket_, Write(_, _, _, _))
- .Times(kNumIOs)
- .WillRepeatedly(
- DoAll(SaveArg<2>(&callback), Return(net::ERR_IO_PENDING)));
-
- // Send out |kNuMIOs| requests, each with a different size.
- for (int i = 0; i < kNumIOs; i++) {
- io_buffers[i] = new net::IOBufferWithSize(128 + i * 50);
- socket_->Write(io_buffers[i].get(),
- io_buffers[i]->size(),
- base::Bind(&CompleteHandler::OnComplete,
- base::Unretained(&handlers[i])));
-
- // Set up expectations on all |kNumIOs| handlers.
- EXPECT_CALL(handlers[i], OnComplete(io_buffers[i]->size())).Times(1);
+INSTANTIATE_TEST_CASE_P(/* no prefix */,
+ TLSSocketTest,
+ testing::Values(net::SYNCHRONOUS, net::ASYNC));
+
+TEST_P(TLSSocketTest, ReadWrite) {
+ net::IoMode io_mode = GetParam();
+ const net::MockRead kReads[] = {
+ net::MockRead(net::ASYNC, kTestMsg, kTestMsgLength, 1),
+ net::MockRead(io_mode, net::OK, 2)};
+ const net::MockWrite kWrites[] = {
+ net::MockWrite(net::SYNCHRONOUS, kTestMsg, kTestMsgLength, 0)};
+ net::SequencedSocketData data_provider(kReads, kWrites);
+ net::SSLSocketDataProvider ssl_socket(io_mode, net::OK);
+
+ mock_client_socket_factory()->AddSocketDataProvider(&data_provider);
+ mock_client_socket_factory()->AddSSLSocketDataProvider(&ssl_socket);
+ std::unique_ptr<TLSSocket> socket = CreateSocket();
+
+ auto io_buffer = base::MakeRefCounted<net::StringIOBuffer>(kTestMsg);
+ net::TestCompletionCallback write_callback;
+ socket->Write(io_buffer.get(), kTestMsgLength, write_callback.callback());
+ EXPECT_EQ(kTestMsgLength, write_callback.WaitForResult());
+
+ std::string received_data;
+ int count = 512;
+ while (true) {
+ base::RunLoop run_loop;
+ int net_error = net::ERR_FAILED;
+ socket->Read(count,
+ base::BindLambdaForTesting(
+ [&](int result, scoped_refptr<net::IOBuffer> io_buffer,
+ bool socket_destroying) {
+ net_error = result;
+ EXPECT_FALSE(socket_destroying);
+ if (result > 0)
+ received_data.append(io_buffer->data(), result);
+ run_loop.Quit();
+ }));
+ run_loop.Run();
+ if (net_error <= 0)
+ break;
}
+ EXPECT_EQ(kTestMsg, received_data);
+ EXPECT_TRUE(data_provider.AllReadDataConsumed());
+ EXPECT_TRUE(data_provider.AllWriteDataConsumed());
+ EXPECT_TRUE(ssl_socket.ConnectDataConsumed());
+}
- // Finish each pending I/O. This should satisfy the expectations on the
- // handlers.
- for (int i = 0; i < kNumIOs; i++) {
- callback.Run(128 + i * 50);
+// Tests the case where read size is smaller than the actual message.
+TEST_P(TLSSocketTest, PartialRead) {
+ net::IoMode io_mode = GetParam();
+ const net::MockRead kReads[] = {
+ net::MockRead(net::ASYNC, kTestMsg, kTestMsgLength, 1),
+ net::MockRead(io_mode, net::OK, 2)};
+ const net::MockWrite kWrites[] = {
+ net::MockWrite(net::SYNCHRONOUS, kTestMsg, kTestMsgLength, 0)};
+ net::SequencedSocketData data_provider(kReads, kWrites);
+ net::SSLSocketDataProvider ssl_socket(io_mode, net::OK);
+ mock_client_socket_factory()->AddSocketDataProvider(&data_provider);
+ mock_client_socket_factory()->AddSSLSocketDataProvider(&ssl_socket);
+ std::unique_ptr<TLSSocket> socket = CreateSocket();
+
+ auto io_buffer = base::MakeRefCounted<net::StringIOBuffer>(kTestMsg);
+ net::TestCompletionCallback write_callback;
+ socket->Write(io_buffer.get(), kTestMsgLength, write_callback.callback());
+ EXPECT_EQ(kTestMsgLength, write_callback.WaitForResult());
+
+ int count = 1;
+ std::string received_data;
+ while (true) {
+ int net_result = net::ERR_FAILED;
+ base::RunLoop run_loop;
+ socket->Read(count,
+ base::BindLambdaForTesting(
+ [&](int result, scoped_refptr<net::IOBuffer> io_buffer,
+ bool socket_destroying) {
+ net_result = result;
+ EXPECT_FALSE(socket_destroying);
+ if (result > 0)
+ received_data.append(io_buffer->data(), result);
+ run_loop.Quit();
+ }));
+ run_loop.Run();
+ if (net_result <= 0)
+ break;
+ // Double the read size in the next iteration.
+ count *= 2;
}
+ EXPECT_EQ(kTestMsg, received_data);
+ EXPECT_TRUE(data_provider.AllReadDataConsumed());
+ EXPECT_TRUE(data_provider.AllWriteDataConsumed());
+ EXPECT_TRUE(ssl_socket.ConnectDataConsumed());
}
-typedef std::pair<net::CompletionCallback, int> PendingCallback;
+TEST_P(TLSSocketTest, ReadError) {
+ net::IoMode io_mode = GetParam();
+ const net::MockRead kReads[] = {
+ net::MockRead(net::ASYNC, net::ERR_INSUFFICIENT_RESOURCES, 1)};
+ const net::MockWrite kWrites[] = {
+ net::MockWrite(net::SYNCHRONOUS, kTestMsg, kTestMsgLength, 0)};
+ net::SequencedSocketData data_provider(kReads, kWrites);
+ net::SSLSocketDataProvider ssl_socket(io_mode, net::OK);
+ mock_client_socket_factory()->AddSocketDataProvider(&data_provider);
+ mock_client_socket_factory()->AddSSLSocketDataProvider(&ssl_socket);
-class CallbackList : public base::circular_deque<PendingCallback> {
- public:
- void append(const net::CompletionCallback& cb, int arg) {
- push_back(std::make_pair(cb, arg));
+ std::unique_ptr<TLSSocket> socket = CreateSocket();
+
+ auto io_buffer = base::MakeRefCounted<net::StringIOBuffer>(kTestMsg);
+ net::TestCompletionCallback write_callback;
+ socket->Write(io_buffer.get(), kTestMsgLength, write_callback.callback());
+ EXPECT_EQ(kTestMsgLength, write_callback.WaitForResult());
+
+ const int count = 512;
+ int net_error = net::OK;
+ while (true) {
+ base::RunLoop run_loop;
+ socket->Read(count,
+ base::BindLambdaForTesting(
+ [&](int result, scoped_refptr<net::IOBuffer> io_buffer,
+ bool socket_destroying) {
+ net_error = result;
+ EXPECT_FALSE(socket_destroying);
+ if (result <= 0) {
+ EXPECT_FALSE(socket->IsConnected());
+ EXPECT_EQ(nullptr, io_buffer);
+ } else {
+ EXPECT_TRUE(socket->IsConnected());
+ }
+ run_loop.Quit();
+ }));
+ run_loop.Run();
+ if (net_error <= 0)
+ break;
}
-};
+ // Note that TLSSocket only detects that receive pipe is broken and propagates
+ // it as 0 byte read. It doesn't know the specific net error code. To know the
+ // specific net error code, it needs to register itself as a
+ // network::mojom::SocketObserver. However, that gets tricky because of two
+ // separate mojo pipes.
+ EXPECT_EQ(0, net_error);
+ EXPECT_TRUE(data_provider.AllReadDataConsumed());
+ EXPECT_TRUE(data_provider.AllWriteDataConsumed());
+ EXPECT_TRUE(ssl_socket.ConnectDataConsumed());
+}
-// Simulate Write()s above and below a SSLClientSocket size limit.
-TEST_F(TLSSocketTest, TestTLSSocketLargeWrites) {
- const int kSizeIncrement = 4096;
- const int kNumIncrements = 10;
- const int kFragmentIncrement = 4;
- const int kSizeLimit = kSizeIncrement * kFragmentIncrement;
- net::CompletionCallback callback;
- CompleteHandler handler;
- scoped_refptr<net::IOBufferWithSize> io_buffers[kNumIncrements];
- CallbackList pending_callbacks;
- size_t total_bytes_requested = 0;
- size_t total_bytes_written = 0;
-
- // Some implementations of SSLClientSocket may have write-size limits (e.g,
- // max 1 TLS record, which is 16k). This test mocks a size limit at
- // |kSizeIncrement| and calls Write() above and below that limit. It
- // simulates SSLClientSocket::Write() behavior in only writing up to the size
- // limit, requiring additional calls for the remaining data to be sent.
- // Socket::Write() (and supporting methods) execute the additional calls as
- // needed. This test verifies that this inherited implementation does
- // properly issue additional calls, and that the total amount returned from
- // all mocked SSLClientSocket::Write() calls is the same as originally
- // requested.
-
- // |ssl_socket_|'s Write() will write at most |kSizeLimit| bytes. The
- // inherited Socket::Write() will repeatedly call |ssl_socket_|'s Write()
- // until the entire original request is sent. Socket::Write() will queue any
- // additional write requests until the current request is complete. A
- // request is complete when the callback passed to Socket::WriteImpl() is
- // invoked with an argument equal to the original number of bytes requested
- // from Socket::Write(). If the callback is invoked with a smaller number,
- // Socket::WriteImpl() will get repeatedly invoked until the sum of the
- // callbacks' arguments is equal to the original requested amount.
- EXPECT_CALL(*ssl_socket_, Write(_, _, _, _))
- .WillRepeatedly(DoAll(
- WithArgs<2, 1>(Invoke(&pending_callbacks, &CallbackList::append)),
- Return(net::ERR_IO_PENDING)));
-
- // Observe what comes back from Socket::Write() here.
- EXPECT_CALL(handler, OnComplete(Gt(0))).Times(kNumIncrements);
-
- // Send out |kNumIncrements| requests, each with a different size. The
- // last request is the same size as the first, and the ones in the middle
- // are monotonically increasing from the first.
- for (int i = 0; i < kNumIncrements; i++) {
- const bool last = i == (kNumIncrements - 1);
- io_buffers[i] = new net::IOBufferWithSize(last ? kSizeIncrement
- : kSizeIncrement * (i + 1));
- total_bytes_requested += io_buffers[i]->size();
-
- // Invoke Socket::Write(). This will invoke |ssl_socket_|'s Write(), which
- // this test mocks out. That mocked Write() is in an asynchronous waiting
- // state until the passed callback (saved in the EXPECT_CALL for
- // |ssl_socket_|'s Write()) is invoked.
- socket_->Write(
- io_buffers[i].get(),
- io_buffers[i]->size(),
- base::Bind(&CompleteHandler::OnComplete, base::Unretained(&handler)));
+// Tests the case where a message is split over two separate socket writes.
+TEST_P(TLSSocketTest, MultipleWrite) {
+ const char kFirstHalfTestMsg[] = "abcde";
+ const char kSecondHalfTestMsg[] = "fghij";
+ EXPECT_EQ(kTestMsg, std::string(kFirstHalfTestMsg) + kSecondHalfTestMsg);
+ net::IoMode io_mode = GetParam();
+ const net::MockRead kReads[] = {net::MockRead(net::ASYNC, net::OK, 2)};
+ const net::MockWrite kWrites[] = {
+ net::MockWrite(io_mode, kFirstHalfTestMsg, strlen(kFirstHalfTestMsg), 0),
+ net::MockWrite(io_mode, kSecondHalfTestMsg, strlen(kSecondHalfTestMsg),
+ 1)};
+ net::SequencedSocketData data_provider(kReads, kWrites);
+ net::SSLSocketDataProvider ssl_socket(io_mode, net::OK);
+ mock_client_socket_factory()->AddSocketDataProvider(&data_provider);
+ mock_client_socket_factory()->AddSSLSocketDataProvider(&ssl_socket);
+ std::unique_ptr<TLSSocket> socket = CreateSocket();
+
+ int num_bytes_written = 0;
+ auto io_buffer = base::MakeRefCounted<net::StringIOBuffer>(kTestMsg);
+ auto drainable_io_buffer = base::MakeRefCounted<net::DrainableIOBuffer>(
+ io_buffer.get(), kTestMsgLength);
+ while (num_bytes_written < kTestMsgLength) {
+ net::TestCompletionCallback write_callback;
+ socket->Write(drainable_io_buffer.get(), kTestMsgLength - num_bytes_written,
+ write_callback.callback());
+ int result = write_callback.WaitForResult();
+ ASSERT_GT(result, net::OK);
+ drainable_io_buffer->DidConsume(result);
+ num_bytes_written += result;
+ // Flushes the write.
+ base::RunLoop().RunUntilIdle();
}
+ EXPECT_TRUE(data_provider.AllReadDataConsumed());
+ EXPECT_TRUE(data_provider.AllWriteDataConsumed());
+ EXPECT_TRUE(ssl_socket.ConnectDataConsumed());
+}
- // Invoke callbacks for pending I/Os. These can synchronously invoke more of
- // |ssl_socket_|'s Write() as needed. The callback checks how much is left
- // in the request, and then starts issuing any queued Socket::Write()
- // invocations.
- while (!pending_callbacks.empty()) {
- PendingCallback cb = pending_callbacks.front();
- pending_callbacks.pop_front();
-
- int amount_written_invocation = std::min(kSizeLimit, cb.second);
- total_bytes_written += amount_written_invocation;
- cb.first.Run(amount_written_invocation);
+TEST_P(TLSSocketTest, PartialWrite) {
+ net::IoMode io_mode = GetParam();
+ const net::MockRead kReads[] = {net::MockRead(net::ASYNC, net::OK, 4)};
+ const net::MockWrite kWrites[] = {net::MockWrite(io_mode, "a", 1, 0),
+ net::MockWrite(io_mode, "bc", 2, 1),
+ net::MockWrite(io_mode, "defg", 4, 2),
+ net::MockWrite(io_mode, "hij", 3, 3)};
+
+ net::SequencedSocketData data_provider(kReads, kWrites);
+ net::SSLSocketDataProvider ssl_socket(io_mode, net::OK);
+
+ mock_client_socket_factory()->AddSocketDataProvider(&data_provider);
+ mock_client_socket_factory()->AddSSLSocketDataProvider(&ssl_socket);
+
+ mock_client_socket_factory()->AddSocketDataProvider(&data_provider);
+ std::unique_ptr<TLSSocket> socket = CreateSocket();
+
+ // Start with writing one byte, and double that in the next iteration.
+ int num_bytes_to_write = 1;
+ int num_bytes_written = 0;
+ auto io_buffer = base::MakeRefCounted<net::StringIOBuffer>(kTestMsg);
+ auto drainable_io_buffer = base::MakeRefCounted<net::DrainableIOBuffer>(
+ io_buffer.get(), kTestMsgLength);
+ while (num_bytes_written < kTestMsgLength) {
+ net::TestCompletionCallback write_callback;
+ socket->Write(
+ drainable_io_buffer.get(),
+ std::max(kTestMsgLength - num_bytes_written, num_bytes_to_write),
+ write_callback.callback());
+ int result = write_callback.WaitForResult();
+ ASSERT_GT(result, net::OK);
+ drainable_io_buffer->DidConsume(result);
+ num_bytes_written += result;
+ num_bytes_to_write *= 2;
+ // Flushes the write.
+ base::RunLoop().RunUntilIdle();
}
+ EXPECT_TRUE(data_provider.AllReadDataConsumed());
+ EXPECT_TRUE(data_provider.AllWriteDataConsumed());
+ EXPECT_TRUE(ssl_socket.ConnectDataConsumed());
+}
- ASSERT_EQ(total_bytes_requested, total_bytes_written)
- << "There should be exactly as many bytes written as originally "
- << "requested to Write().";
+TEST_P(TLSSocketTest, WriteError) {
+ net::IoMode io_mode = GetParam();
+ const net::MockRead kReads[] = {net::MockRead(net::ASYNC, net::OK, 1)};
+ const net::MockWrite kWrites[] = {
+ net::MockWrite(io_mode, net::ERR_INSUFFICIENT_RESOURCES, 0)};
+
+ net::SequencedSocketData data_provider(kReads, kWrites);
+ net::SSLSocketDataProvider ssl_socket(io_mode, net::OK);
+
+ mock_client_socket_factory()->AddSocketDataProvider(&data_provider);
+ mock_client_socket_factory()->AddSSLSocketDataProvider(&ssl_socket);
+ std::unique_ptr<TLSSocket> socket = CreateSocket();
+
+ // Mojo data pipe might buffer some write data, so continue writing until the
+ // write error is received.
+ auto io_buffer = base::MakeRefCounted<net::StringIOBuffer>(kTestMsg);
+ int net_error = net::OK;
+ while (true) {
+ base::RunLoop run_loop;
+ socket->Write(io_buffer.get(), kTestMsgLength,
+ base::BindLambdaForTesting([&](int result) {
+ if (result == net::ERR_FAILED)
+ EXPECT_FALSE(socket->IsConnected());
+ net_error = result;
+ run_loop.Quit();
+ }));
+ run_loop.Run();
+ if (net_error <= 0)
+ break;
+ }
+ // Note that TCPSocket only detects that send pipe is broken and propagates
+ // it as a net::ERR_FAILED. It doesn't know the specific net error code. To do
+ // that, it needs to register itself as a network::mojom::SocketObserver.
+ EXPECT_EQ(net::ERR_FAILED, net_error);
}
} // namespace extensions
diff --git a/chromium/chrome/browser/extensions/api/sync_file_system/DEPS b/chromium/chrome/browser/extensions/api/sync_file_system/DEPS
deleted file mode 100644
index 73bc109ad21..00000000000
--- a/chromium/chrome/browser/extensions/api/sync_file_system/DEPS
+++ /dev/null
@@ -1,5 +0,0 @@
-specific_include_rules = {
- "sync_file_system_browsertest\.cc": [
- "+components/drive"
- ],
-}
diff --git a/chromium/chrome/browser/extensions/api/sync_file_system/OWNERS b/chromium/chrome/browser/extensions/api/sync_file_system/OWNERS
index 9d970c731ce..89ed524015e 100644
--- a/chromium/chrome/browser/extensions/api/sync_file_system/OWNERS
+++ b/chromium/chrome/browser/extensions/api/sync_file_system/OWNERS
@@ -1,4 +1,5 @@
kinuko@chromium.org
+pwnall@chromium.org
tzik@chromium.org
# TEAM: storage-dev@chromium.org
diff --git a/chromium/chrome/browser/extensions/api/sync_file_system/sync_file_system_browsertest.cc b/chromium/chrome/browser/extensions/api/sync_file_system/sync_file_system_browsertest.cc
index 383b5c631be..233bfca0c7b 100644
--- a/chromium/chrome/browser/extensions/api/sync_file_system/sync_file_system_browsertest.cc
+++ b/chromium/chrome/browser/extensions/api/sync_file_system/sync_file_system_browsertest.cc
@@ -9,7 +9,7 @@
#include "base/macros.h"
#include "base/run_loop.h"
#include "base/sequenced_task_runner.h"
-#include "base/task_scheduler/post_task.h"
+#include "base/task/post_task.h"
#include "base/threading/thread_task_runner_handle.h"
#include "base/values.h"
#include "chrome/browser/apps/platform_apps/app_browsertest_util.h"
@@ -106,7 +106,7 @@ class SyncFileSystemTest : public extensions::PlatformAppBrowserTest,
// drive::FakeDriveService::ChangeObserver override.
void OnNewChangeAvailable() override {
- sync_engine()->OnNotificationReceived();
+ sync_engine()->OnNotificationTimerFired();
}
SyncFileSystemService* sync_file_system_service() {
diff --git a/chromium/chrome/browser/extensions/api/system_private/system_private_api.cc b/chromium/chrome/browser/extensions/api/system_private/system_private_api.cc
index 132abe1537a..bc91204ef8c 100644
--- a/chromium/chrome/browser/extensions/api/system_private/system_private_api.cc
+++ b/chromium/chrome/browser/extensions/api/system_private/system_private_api.cc
@@ -22,7 +22,7 @@
#include "chromeos/dbus/dbus_thread_manager.h"
#include "chromeos/dbus/update_engine_client.h"
#else
-#include "chrome/browser/upgrade_detector.h"
+#include "chrome/browser/upgrade_detector/upgrade_detector.h"
#endif
namespace {
diff --git a/chromium/chrome/browser/extensions/api/tab_capture/offscreen_tab.cc b/chromium/chrome/browser/extensions/api/tab_capture/offscreen_tab.cc
deleted file mode 100644
index 6706c0fab95..00000000000
--- a/chromium/chrome/browser/extensions/api/tab_capture/offscreen_tab.cc
+++ /dev/null
@@ -1,422 +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 "chrome/browser/extensions/api/tab_capture/offscreen_tab.h"
-
-#include <algorithm>
-#include <utility>
-#include <vector>
-
-#include "base/bind.h"
-#include "base/macros.h"
-#include "base/stl_util.h"
-#include "chrome/browser/extensions/api/tab_capture/tab_capture_registry.h"
-#include "chrome/browser/media/router/presentation/presentation_navigation_policy.h"
-#include "chrome/browser/media/router/presentation/receiver_presentation_service_delegate_impl.h" // nogncheck
-#include "chrome/browser/profiles/profile.h"
-#include "chrome/browser/ui/web_contents_sizer.h"
-#include "content/public/browser/keyboard_event_processing_result.h"
-#include "content/public/browser/navigation_handle.h"
-#include "content/public/browser/render_widget_host_view.h"
-#include "content/public/browser/web_contents.h"
-#include "extensions/browser/extension_host.h"
-#include "extensions/browser/process_manager.h"
-#include "third_party/blink/public/web/web_presentation_receiver_flags.h"
-
-using content::WebContents;
-
-DEFINE_WEB_CONTENTS_USER_DATA_KEY(extensions::OffscreenTabsOwner);
-
-namespace {
-
-// Upper limit on the number of simultaneous off-screen tabs per extension
-// instance.
-const int kMaxOffscreenTabsPerExtension = 4;
-
-// Time intervals used by the logic that detects when the capture of an
-// offscreen tab has stopped, to automatically tear it down and free resources.
-const int kMaxSecondsToWaitForCapture = 60;
-const int kPollIntervalInSeconds = 1;
-
-} // namespace
-
-namespace extensions {
-
-OffscreenTabsOwner::OffscreenTabsOwner(WebContents* extension_web_contents)
- : extension_web_contents_(extension_web_contents) {
- DCHECK(extension_web_contents_);
-}
-
-OffscreenTabsOwner::~OffscreenTabsOwner() {}
-
-// static
-OffscreenTabsOwner* OffscreenTabsOwner::Get(
- content::WebContents* extension_web_contents) {
- // CreateForWebContents() really means "create if not exists."
- CreateForWebContents(extension_web_contents);
- return FromWebContents(extension_web_contents);
-}
-
-OffscreenTab* OffscreenTabsOwner::OpenNewTab(
- const GURL& start_url,
- const gfx::Size& initial_size,
- const std::string& optional_presentation_id) {
- if (tabs_.size() >= kMaxOffscreenTabsPerExtension)
- return nullptr; // Maximum number of offscreen tabs reached.
-
- // OffscreenTab cannot be created with MakeUnique<OffscreenTab> since the
- // constructor is protected. So create it separately, and then move it to
- // |tabs_| below.
- std::unique_ptr<OffscreenTab> offscreen_tab(new OffscreenTab(this));
- tabs_.push_back(std::move(offscreen_tab));
- tabs_.back()->Start(start_url, initial_size, optional_presentation_id);
- return tabs_.back().get();
-}
-
-void OffscreenTabsOwner::DestroyTab(OffscreenTab* tab) {
- for (std::vector<std::unique_ptr<OffscreenTab>>::iterator iter =
- tabs_.begin();
- iter != tabs_.end(); ++iter) {
- if (iter->get() == tab) {
- tabs_.erase(iter);
- break;
- }
- }
-}
-
-OffscreenTab::OffscreenTab(OffscreenTabsOwner* owner)
- : owner_(owner),
- otr_profile_registration_(
- IndependentOTRProfileManager::GetInstance()
- ->CreateFromOriginalProfile(
- Profile::FromBrowserContext(
- owner->extension_web_contents()->GetBrowserContext()),
- base::BindOnce(&OffscreenTab::DieIfOriginalProfileDestroyed,
- base::Unretained(this)))),
- content_capture_was_detected_(false),
- navigation_policy_(
- std::make_unique<media_router::DefaultNavigationPolicy>()) {
- DCHECK(otr_profile_registration_->profile());
-}
-
-OffscreenTab::~OffscreenTab() {
- DVLOG(1) << "Destroying OffscreenTab for start_url=" << start_url_.spec();
-}
-
-void OffscreenTab::Start(const GURL& start_url,
- const gfx::Size& initial_size,
- const std::string& optional_presentation_id) {
- DCHECK(start_time_.is_null());
- start_url_ = start_url;
- DVLOG(1) << "Starting OffscreenTab with initial size of "
- << initial_size.ToString() << " for start_url=" << start_url_.spec();
-
- // Create the WebContents to contain the off-screen tab's page.
- WebContents::CreateParams params(otr_profile_registration_->profile());
- if (!optional_presentation_id.empty())
- params.starting_sandbox_flags = blink::kPresentationReceiverSandboxFlags;
-
- offscreen_tab_web_contents_ = WebContents::Create(params);
- offscreen_tab_web_contents_->SetDelegate(this);
- WebContentsObserver::Observe(offscreen_tab_web_contents_.get());
-
- // Set initial size, if specified.
- if (!initial_size.IsEmpty())
- ResizeWebContents(offscreen_tab_web_contents_.get(),
- gfx::Rect(initial_size));
-
- // Mute audio output. When tab capture starts, the audio will be
- // automatically unmuted, but will be captured into the MediaStream.
- offscreen_tab_web_contents_->SetAudioMuted(true);
-
- if (!optional_presentation_id.empty()) {
- // This offscreen tab is a presentation created through the Presentation
- // API. https://www.w3.org/TR/presentation-api/
- //
- // Create a ReceiverPresentationServiceDelegateImpl associated with the
- // offscreen tab's WebContents. The new instance will set up the necessary
- // infrastructure to allow controlling pages the ability to connect to the
- // offscreen tab.
- DVLOG(1) << "Register with ReceiverPresentationServiceDelegateImpl, "
- << "presentation_id=" << optional_presentation_id;
- media_router::ReceiverPresentationServiceDelegateImpl::CreateForWebContents(
- offscreen_tab_web_contents_.get(), optional_presentation_id);
-
- // Presentations are not allowed to perform top-level navigations after
- // initial load. This is enforced through sandboxing flags, but we also
- // enforce it here.
- navigation_policy_ =
- std::make_unique<media_router::PresentationNavigationPolicy>();
- }
-
- // Navigate to the initial URL.
- content::NavigationController::LoadURLParams load_params(start_url_);
- load_params.should_replace_current_entry = true;
- load_params.should_clear_history_list = true;
- offscreen_tab_web_contents_->GetController().LoadURLWithParams(load_params);
-
- start_time_ = base::TimeTicks::Now();
- DieIfContentCaptureEnded();
-}
-
-void OffscreenTab::Close() {
- if (offscreen_tab_web_contents_)
- offscreen_tab_web_contents_->ClosePage();
-}
-
-void OffscreenTab::CloseContents(WebContents* source) {
- DCHECK_EQ(offscreen_tab_web_contents_.get(), source);
- // Javascript in the page called window.close().
- DVLOG(1) << "OffscreenTab for start_url=" << start_url_.spec() << " will die";
- owner_->DestroyTab(this);
- // |this| is no longer valid.
-}
-
-bool OffscreenTab::ShouldSuppressDialogs(WebContents* source) {
- DCHECK_EQ(offscreen_tab_web_contents_.get(), source);
- // Suppress all because there is no possible direct user interaction with
- // dialogs.
- // TODO(crbug.com/734191): This does not suppress window.print().
- return true;
-}
-
-bool OffscreenTab::ShouldFocusLocationBarByDefault(WebContents* source) {
- DCHECK_EQ(offscreen_tab_web_contents_.get(), source);
- // Indicate the location bar should be focused instead of the page, even
- // though there is no location bar. This will prevent the page from
- // automatically receiving input focus, which should never occur since there
- // is not supposed to be any direct user interaction.
- return true;
-}
-
-bool OffscreenTab::ShouldFocusPageAfterCrash() {
- // Never focus the page. Not even after a crash.
- return false;
-}
-
-void OffscreenTab::CanDownload(const GURL& url,
- const std::string& request_method,
- const base::Callback<void(bool)>& callback) {
- // Offscreen tab pages are not allowed to download files.
- callback.Run(false);
-}
-
-bool OffscreenTab::HandleContextMenu(const content::ContextMenuParams& params) {
- // Context menus should never be shown. Do nothing, but indicate the context
- // menu was shown so that default implementation in libcontent does not
- // attempt to do so on its own.
- return true;
-}
-
-content::KeyboardEventProcessingResult OffscreenTab::PreHandleKeyboardEvent(
- WebContents* source,
- const content::NativeWebKeyboardEvent& event) {
- DCHECK_EQ(offscreen_tab_web_contents_.get(), source);
- // Intercept and silence all keyboard events before they can be sent to the
- // renderer.
- return content::KeyboardEventProcessingResult::HANDLED;
-}
-
-bool OffscreenTab::PreHandleGestureEvent(WebContents* source,
- const blink::WebGestureEvent& event) {
- DCHECK_EQ(offscreen_tab_web_contents_.get(), source);
- // Intercept and silence all gesture events before they can be sent to the
- // renderer.
- return true;
-}
-
-bool OffscreenTab::CanDragEnter(
- WebContents* source,
- const content::DropData& data,
- blink::WebDragOperationsMask operations_allowed) {
- DCHECK_EQ(offscreen_tab_web_contents_.get(), source);
- // Halt all drag attempts onto the page since there should be no direct user
- // interaction with it.
- return false;
-}
-
-bool OffscreenTab::ShouldCreateWebContents(
- content::WebContents* web_contents,
- content::RenderFrameHost* opener,
- content::SiteInstance* source_site_instance,
- int32_t route_id,
- int32_t main_frame_route_id,
- int32_t main_frame_widget_route_id,
- content::mojom::WindowContainerType window_container_type,
- const GURL& opener_url,
- const std::string& frame_name,
- const GURL& target_url,
- const std::string& partition_id,
- content::SessionStorageNamespace* session_storage_namespace) {
- DCHECK_EQ(offscreen_tab_web_contents_.get(), web_contents);
- // Disallow creating separate WebContentses. The WebContents implementation
- // uses this to spawn new windows/tabs, which is also not allowed for
- // offscreen tabs.
- return false;
-}
-
-bool OffscreenTab::EmbedsFullscreenWidget() const {
- // OffscreenTab will manage fullscreen widgets.
- return true;
-}
-
-void OffscreenTab::EnterFullscreenModeForTab(
- WebContents* contents,
- const GURL& origin,
- const blink::WebFullscreenOptions& options) {
- DCHECK_EQ(offscreen_tab_web_contents_.get(), contents);
-
- if (in_fullscreen_mode())
- return;
-
- non_fullscreen_size_ =
- contents->GetRenderWidgetHostView()->GetViewBounds().size();
- if (contents->IsBeingCaptured() && !contents->GetPreferredSize().IsEmpty())
- ResizeWebContents(contents, gfx::Rect(contents->GetPreferredSize()));
-}
-
-void OffscreenTab::ExitFullscreenModeForTab(WebContents* contents) {
- DCHECK_EQ(offscreen_tab_web_contents_.get(), contents);
-
- if (!in_fullscreen_mode())
- return;
-
- ResizeWebContents(contents, gfx::Rect(non_fullscreen_size_));
- non_fullscreen_size_ = gfx::Size();
-}
-
-bool OffscreenTab::IsFullscreenForTabOrPending(
- const WebContents* contents) const {
- DCHECK_EQ(offscreen_tab_web_contents_.get(), contents);
- return in_fullscreen_mode();
-}
-
-blink::WebDisplayMode OffscreenTab::GetDisplayMode(
- const WebContents* contents) const {
- DCHECK_EQ(offscreen_tab_web_contents_.get(), contents);
- return in_fullscreen_mode() ? blink::kWebDisplayModeFullscreen
- : blink::kWebDisplayModeBrowser;
-}
-
-void OffscreenTab::RequestMediaAccessPermission(
- WebContents* contents,
- const content::MediaStreamRequest& request,
- content::MediaResponseCallback callback) {
- DCHECK_EQ(offscreen_tab_web_contents_.get(), contents);
-
- // This method is being called to check whether an extension is permitted to
- // capture the page. Verify that the request is being made by the extension
- // that spawned this OffscreenTab.
-
- // Find the extension ID associated with the extension background page's
- // WebContents.
- content::BrowserContext* const extension_browser_context =
- owner_->extension_web_contents()->GetBrowserContext();
- const extensions::Extension* const extension =
- ProcessManager::Get(extension_browser_context)->
- GetExtensionForWebContents(owner_->extension_web_contents());
- const std::string extension_id = extension ? extension->id() : "";
- LOG_IF(DFATAL, extension_id.empty())
- << "Extension that started this OffscreenTab was not found.";
-
- // If verified, allow any tab capture audio/video devices that were requested.
- extensions::TabCaptureRegistry* const tab_capture_registry =
- extensions::TabCaptureRegistry::Get(extension_browser_context);
- content::MediaStreamDevices devices;
- if (tab_capture_registry && tab_capture_registry->VerifyRequest(
- request.render_process_id,
- request.render_frame_id,
- extension_id)) {
- if (request.audio_type == content::MEDIA_TAB_AUDIO_CAPTURE) {
- devices.push_back(content::MediaStreamDevice(
- content::MEDIA_TAB_AUDIO_CAPTURE, std::string(), std::string()));
- }
- if (request.video_type == content::MEDIA_TAB_VIDEO_CAPTURE) {
- devices.push_back(content::MediaStreamDevice(
- content::MEDIA_TAB_VIDEO_CAPTURE, std::string(), std::string()));
- }
- }
-
- DVLOG(2) << "Allowing " << devices.size()
- << " capture devices for OffscreenTab content.";
-
- std::move(callback).Run(devices,
- devices.empty() ? content::MEDIA_DEVICE_INVALID_STATE
- : content::MEDIA_DEVICE_OK,
- std::unique_ptr<content::MediaStreamUI>(nullptr));
-}
-
-bool OffscreenTab::CheckMediaAccessPermission(
- content::RenderFrameHost* render_frame_host,
- const GURL& security_origin,
- content::MediaStreamType type) {
- DCHECK_EQ(offscreen_tab_web_contents_.get(),
- content::WebContents::FromRenderFrameHost(render_frame_host));
- return type == content::MEDIA_TAB_AUDIO_CAPTURE ||
- type == content::MEDIA_TAB_VIDEO_CAPTURE;
-}
-
-void OffscreenTab::DidShowFullscreenWidget() {
- if (!offscreen_tab_web_contents_->IsBeingCaptured() ||
- offscreen_tab_web_contents_->GetPreferredSize().IsEmpty())
- return; // Do nothing, since no preferred size is specified.
- content::RenderWidgetHostView* const current_fs_view =
- offscreen_tab_web_contents_->GetFullscreenRenderWidgetHostView();
- if (current_fs_view)
- current_fs_view->SetSize(offscreen_tab_web_contents_->GetPreferredSize());
-}
-
-void OffscreenTab::DidStartNavigation(
- content::NavigationHandle* navigation_handle) {
- DCHECK(offscreen_tab_web_contents_.get());
- if (!navigation_policy_->AllowNavigation(navigation_handle)) {
- DVLOG(2) << "Closing because NavigationPolicy disallowed "
- << "StartNavigation to " << navigation_handle->GetURL().spec();
- Close();
- }
-}
-
-void OffscreenTab::DieIfContentCaptureEnded() {
- DCHECK(offscreen_tab_web_contents_.get());
-
- if (content_capture_was_detected_) {
- if (!offscreen_tab_web_contents_->IsBeingCaptured()) {
- DVLOG(2) << "Capture of OffscreenTab content has stopped for start_url="
- << start_url_.spec();
- owner_->DestroyTab(this);
- return; // |this| is no longer valid.
- } else {
- DVLOG(3) << "Capture of OffscreenTab content continues for start_url="
- << start_url_.spec();
- }
- } else if (offscreen_tab_web_contents_->IsBeingCaptured()) {
- DVLOG(2) << "Capture of OffscreenTab content has started for start_url="
- << start_url_.spec();
- content_capture_was_detected_ = true;
- } else if (base::TimeTicks::Now() - start_time_ >
- base::TimeDelta::FromSeconds(kMaxSecondsToWaitForCapture)) {
- // More than a minute has elapsed since this OffscreenTab was started and
- // content capture still hasn't started. As a safety precaution, assume
- // that content capture is never going to start and die to free up
- // resources.
- LOG(WARNING) << "Capture of OffscreenTab content did not start "
- "within timeout for start_url=" << start_url_.spec();
- owner_->DestroyTab(this);
- return; // |this| is no longer valid.
- }
-
- // Schedule the timer to check again in a second.
- capture_poll_timer_.Start(
- FROM_HERE,
- base::TimeDelta::FromSeconds(kPollIntervalInSeconds),
- base::Bind(&OffscreenTab::DieIfContentCaptureEnded,
- base::Unretained(this)));
-}
-
-void OffscreenTab::DieIfOriginalProfileDestroyed(Profile* profile) {
- DCHECK(profile == otr_profile_registration_->profile());
- owner_->DestroyTab(this);
-}
-
-} // namespace extensions
diff --git a/chromium/chrome/browser/extensions/api/tab_capture/offscreen_tab.h b/chromium/chrome/browser/extensions/api/tab_capture/offscreen_tab.h
deleted file mode 100644
index 93e51b9fc51..00000000000
--- a/chromium/chrome/browser/extensions/api/tab_capture/offscreen_tab.h
+++ /dev/null
@@ -1,236 +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 CHROME_BROWSER_EXTENSIONS_API_TAB_CAPTURE_OFFSCREEN_TAB_H_
-#define CHROME_BROWSER_EXTENSIONS_API_TAB_CAPTURE_OFFSCREEN_TAB_H_
-
-#include <stdint.h>
-
-#include <memory>
-#include <string>
-#include <vector>
-
-#include "base/macros.h"
-#include "base/time/time.h"
-#include "base/timer/timer.h"
-#include "chrome/browser/media/router/presentation/independent_otr_profile_manager.h"
-#include "content/public/browser/web_contents_delegate.h"
-#include "content/public/browser/web_contents_observer.h"
-#include "content/public/browser/web_contents_user_data.h"
-#include "ui/gfx/geometry/size.h"
-
-namespace media_router {
-class NavigationPolicy;
-} // namespace media_router
-
-namespace extensions {
-
-class OffscreenTab; // Forward declaration. See below.
-
-// Creates, owns, and manages all OffscreenTab instances created by the same
-// extension background page. When the extension background page's WebContents
-// is about to be destroyed, its associated OffscreenTabsOwner and all of its
-// OffscreenTab instances are destroyed.
-//
-// Usage:
-//
-// OffscreenTabsOwner::Get(extension_contents)
-// ->OpenNewTab(start_url, size, std::string());
-//
-// This class operates exclusively on the UI thread and so is not thread-safe.
-class OffscreenTabsOwner
- : public content::WebContentsUserData<OffscreenTabsOwner> {
- public:
- ~OffscreenTabsOwner() final;
-
- // Returns the OffscreenTabsOwner instance associated with the given extension
- // background page's WebContents. Never returns nullptr.
- static OffscreenTabsOwner* Get(content::WebContents* extension_web_contents);
-
- // Instantiate a new offscreen tab and navigate it to |start_url|. The new
- // tab's main frame will start out with the given |initial_size| in DIP
- // coordinates. If too many offscreen tabs are already running, nothing
- // happens and nullptr is returned.
- //
- // If |optional_presentation_id| is non-empty, the offscreen tab is registered
- // for use by the Media Router (chrome/browser/media/router/...) as the
- // receiving browsing context for the W3C Presentation API.
- OffscreenTab* OpenNewTab(const GURL& start_url,
- const gfx::Size& initial_size,
- const std::string& optional_presentation_id);
-
- protected:
- friend class OffscreenTab;
-
- // Accessor to the extension background page's WebContents.
- content::WebContents* extension_web_contents() const {
- return extension_web_contents_;
- }
-
- // Shuts down and destroys the |tab|.
- void DestroyTab(OffscreenTab* tab);
-
- private:
- friend class content::WebContentsUserData<OffscreenTabsOwner>;
-
- explicit OffscreenTabsOwner(content::WebContents* extension_web_contents);
-
- content::WebContents* const extension_web_contents_;
- std::vector<std::unique_ptr<OffscreenTab>> tabs_;
-
- DISALLOW_COPY_AND_ASSIGN(OffscreenTabsOwner);
-};
-
-// Owns and controls a sandboxed WebContents instance hosting the rendering
-// engine for an offscreen tab. Since the offscreen tab does not interact with
-// the user in any direct way, the WebContents is not attached to any Browser
-// window/UI, and any input and focusing capabilities are blocked.
-//
-// OffscreenTab is instantiated by OffscreenTabsOwner. An instance is shut down
-// one of three ways:
-//
-// 1. When WebContents::IsBeingCaptured() returns false, indicating there are
-// no more consumers of its captured content (e.g., when all MediaStreams
-// have been closed). OffscreenTab will auto-detect this case and
-// self-destruct.
-// 2. By the renderer, where the WebContents implementation will invoke the
-// WebContentsDelegate::CloseContents() override. This occurs, for
-// example, when a page calls window.close().
-// 3. Automatically, when the extension background page's WebContents is
-// destroyed.
-//
-// This class operates exclusively on the UI thread and so is not thread-safe.
-class OffscreenTab : protected content::WebContentsDelegate,
- protected content::WebContentsObserver {
- public:
- ~OffscreenTab() final;
-
- // The WebContents instance hosting the rendering engine for this
- // OffscreenTab.
- content::WebContents* web_contents() const {
- return offscreen_tab_web_contents_.get();
- }
-
- protected:
- friend class OffscreenTabsOwner;
-
- explicit OffscreenTab(OffscreenTabsOwner* owner);
-
- // Creates the WebContents instance containing the offscreen tab's page,
- // configures it for offscreen rendering at the given |initial_size|, and
- // navigates it to |start_url|. This is invoked once by OffscreenTabsOwner
- // just after construction.
- void Start(const GURL& start_url,
- const gfx::Size& initial_size,
- const std::string& optional_presentation_id);
-
- // Closes the underlying WebContents.
- void Close();
-
- // content::WebContentsDelegate overrides to provide the desired behaviors.
- void CloseContents(content::WebContents* source) final;
- bool ShouldSuppressDialogs(content::WebContents* source) final;
- bool ShouldFocusLocationBarByDefault(content::WebContents* source) final;
- bool ShouldFocusPageAfterCrash() final;
- void CanDownload(const GURL& url,
- const std::string& request_method,
- const base::Callback<void(bool)>& callback) final;
- bool HandleContextMenu(const content::ContextMenuParams& params) final;
- content::KeyboardEventProcessingResult PreHandleKeyboardEvent(
- content::WebContents* source,
- const content::NativeWebKeyboardEvent& event) final;
- bool PreHandleGestureEvent(content::WebContents* source,
- const blink::WebGestureEvent& event) final;
- bool CanDragEnter(content::WebContents* source,
- const content::DropData& data,
- blink::WebDragOperationsMask operations_allowed) final;
- bool ShouldCreateWebContents(
- content::WebContents* web_contents,
- content::RenderFrameHost* opener,
- content::SiteInstance* source_site_instance,
- int32_t route_id,
- int32_t main_frame_route_id,
- int32_t main_frame_widget_route_id,
- content::mojom::WindowContainerType window_container_type,
- const GURL& opener_url,
- const std::string& frame_name,
- const GURL& target_url,
- const std::string& partition_id,
- content::SessionStorageNamespace* session_storage_namespace) final;
- bool EmbedsFullscreenWidget() const final;
- void EnterFullscreenModeForTab(
- content::WebContents* contents,
- const GURL& origin,
- const blink::WebFullscreenOptions& options) final;
- void ExitFullscreenModeForTab(content::WebContents* contents) final;
- bool IsFullscreenForTabOrPending(
- const content::WebContents* contents) const final;
- blink::WebDisplayMode GetDisplayMode(
- const content::WebContents* contents) const final;
- void RequestMediaAccessPermission(
- content::WebContents* contents,
- const content::MediaStreamRequest& request,
- content::MediaResponseCallback callback) final;
- bool CheckMediaAccessPermission(content::RenderFrameHost* render_frame_host,
- const GURL& security_origin,
- content::MediaStreamType type) final;
-
- // content::WebContentsObserver overrides
- void DidShowFullscreenWidget() final;
- void DidStartNavigation(content::NavigationHandle* navigation_handle) final;
-
- private:
- bool in_fullscreen_mode() const { return !non_fullscreen_size_.IsEmpty(); }
-
- // Called by |capture_poll_timer_| to automatically destroy this OffscreenTab
- // when the capturer count returns to zero.
- void DieIfContentCaptureEnded();
-
- // Called if the profile that our OTR profile is based on is being destroyed
- // and |this| therefore needs to be destroyed also.
- void DieIfOriginalProfileDestroyed(Profile* profile);
-
- OffscreenTabsOwner* const owner_;
-
- // The initial navigation URL, which may or may not match the current URL if
- // page-initiated navigations have occurred.
- GURL start_url_;
-
- // A non-shared off-the-record profile based on the profile of the extension
- // background page.
- const std::unique_ptr<IndependentOTRProfileManager::OTRProfileRegistration>
- otr_profile_registration_;
-
- // The WebContents containing the off-screen tab's page.
- std::unique_ptr<content::WebContents> offscreen_tab_web_contents_;
-
- // The time at which Start() finished creating |offscreen_tab_web_contents_|.
- base::TimeTicks start_time_;
-
- // Set to the original size of the renderer just before entering fullscreen
- // mode. When not in fullscreen mode, this is an empty size.
- gfx::Size non_fullscreen_size_;
-
- // Poll timer to monitor the capturer count on |offscreen_tab_web_contents_|.
- // When the capturer count returns to zero, this OffscreenTab is automatically
- // destroyed.
- //
- // TODO(miu): Add a method to WebContentsObserver to report capturer count
- // changes and get rid of this polling-based approach.
- // http://crbug.com/540965
- base::OneShotTimer capture_poll_timer_;
-
- // This is false until after the Start() method is called, and capture of the
- // |offscreen_tab_web_contents_| is first detected.
- bool content_capture_was_detected_;
-
- // Object consulted to determine which offscreen tab navigations are allowed.
- std::unique_ptr<media_router::NavigationPolicy> navigation_policy_;
-
- DISALLOW_COPY_AND_ASSIGN(OffscreenTab);
-};
-
-} // namespace extensions
-
-#endif // CHROME_BROWSER_EXTENSIONS_API_TAB_CAPTURE_OFFSCREEN_TAB_H_
diff --git a/chromium/chrome/browser/extensions/api/tab_capture/offscreen_tabs_owner.cc b/chromium/chrome/browser/extensions/api/tab_capture/offscreen_tabs_owner.cc
new file mode 100644
index 00000000000..202e849c408
--- /dev/null
+++ b/chromium/chrome/browser/extensions/api/tab_capture/offscreen_tabs_owner.cc
@@ -0,0 +1,114 @@
+// 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 "chrome/browser/extensions/api/tab_capture/offscreen_tabs_owner.h"
+
+#include <algorithm>
+#include <utility>
+#include <vector>
+
+#include "base/bind.h"
+#include "base/stl_util.h"
+#include "chrome/browser/extensions/api/tab_capture/tab_capture_registry.h"
+#include "chrome/browser/profiles/profile.h"
+#include "content/public/browser/web_contents.h"
+#include "extensions/browser/extension_host.h"
+#include "extensions/browser/process_manager.h"
+
+using content::WebContents;
+
+namespace {
+
+// Upper limit on the number of simultaneous off-screen tabs per extension
+// instance.
+const int kMaxOffscreenTabsPerExtension = 4;
+
+} // namespace
+
+namespace extensions {
+
+OffscreenTabsOwner::OffscreenTabsOwner(WebContents* extension_web_contents)
+ : extension_web_contents_(extension_web_contents) {
+ DCHECK(extension_web_contents_);
+}
+
+OffscreenTabsOwner::~OffscreenTabsOwner() {}
+
+// static
+OffscreenTabsOwner* OffscreenTabsOwner::Get(
+ content::WebContents* extension_web_contents) {
+ // CreateForWebContents() really means "create if not exists."
+ CreateForWebContents(extension_web_contents);
+ return FromWebContents(extension_web_contents);
+}
+
+OffscreenTab* OffscreenTabsOwner::OpenNewTab(
+ const GURL& start_url,
+ const gfx::Size& initial_size,
+ const std::string& optional_presentation_id) {
+ if (tabs_.size() >= kMaxOffscreenTabsPerExtension)
+ return nullptr; // Maximum number of offscreen tabs reached.
+
+ tabs_.emplace_back(std::make_unique<OffscreenTab>(
+ this, extension_web_contents_->GetBrowserContext()));
+ tabs_.back()->Start(start_url, initial_size, optional_presentation_id);
+ return tabs_.back().get();
+}
+
+void OffscreenTabsOwner::RequestMediaAccessPermission(
+ const content::MediaStreamRequest& request,
+ content::MediaResponseCallback callback) {
+ // This method is being called to check whether an extension is permitted to
+ // capture the page. Verify that the request is being made by the extension
+ // that spawned this OffscreenTab.
+
+ // Find the extension ID associated with the extension background page's
+ // WebContents.
+ content::BrowserContext* const extension_browser_context =
+ extension_web_contents_->GetBrowserContext();
+ const extensions::Extension* const extension =
+ ProcessManager::Get(extension_browser_context)
+ ->GetExtensionForWebContents(extension_web_contents_);
+ const std::string extension_id = extension ? extension->id() : "";
+ LOG_IF(DFATAL, extension_id.empty())
+ << "Extension that started this OffscreenTab was not found.";
+
+ // If verified, allow any tab capture audio/video devices that were requested.
+ extensions::TabCaptureRegistry* const tab_capture_registry =
+ extensions::TabCaptureRegistry::Get(extension_browser_context);
+ content::MediaStreamDevices devices;
+ if (tab_capture_registry &&
+ tab_capture_registry->VerifyRequest(
+ request.render_process_id, request.render_frame_id, extension_id)) {
+ if (request.audio_type == content::MEDIA_GUM_TAB_AUDIO_CAPTURE) {
+ devices.push_back(content::MediaStreamDevice(
+ content::MEDIA_GUM_TAB_AUDIO_CAPTURE, std::string(), std::string()));
+ }
+ if (request.video_type == content::MEDIA_GUM_TAB_VIDEO_CAPTURE) {
+ devices.push_back(content::MediaStreamDevice(
+ content::MEDIA_GUM_TAB_VIDEO_CAPTURE, std::string(), std::string()));
+ }
+ }
+
+ DVLOG(2) << "Allowing " << devices.size()
+ << " capture devices for OffscreenTab content.";
+
+ std::move(callback).Run(devices,
+ devices.empty() ? content::MEDIA_DEVICE_INVALID_STATE
+ : content::MEDIA_DEVICE_OK,
+ nullptr);
+}
+
+void OffscreenTabsOwner::DestroyTab(OffscreenTab* tab) {
+ for (std::vector<std::unique_ptr<OffscreenTab>>::iterator iter =
+ tabs_.begin();
+ iter != tabs_.end(); ++iter) {
+ if (iter->get() == tab) {
+ tabs_.erase(iter);
+ break;
+ }
+ }
+}
+
+} // namespace extensions
diff --git a/chromium/chrome/browser/extensions/api/tab_capture/offscreen_tabs_owner.h b/chromium/chrome/browser/extensions/api/tab_capture/offscreen_tabs_owner.h
new file mode 100644
index 00000000000..badea71d804
--- /dev/null
+++ b/chromium/chrome/browser/extensions/api/tab_capture/offscreen_tabs_owner.h
@@ -0,0 +1,75 @@
+// 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 CHROME_BROWSER_EXTENSIONS_API_TAB_CAPTURE_OFFSCREEN_TABS_OWNER_H_
+#define CHROME_BROWSER_EXTENSIONS_API_TAB_CAPTURE_OFFSCREEN_TABS_OWNER_H_
+
+#include <stdint.h>
+
+#include <memory>
+#include <string>
+#include <vector>
+
+#include "base/macros.h"
+#include "chrome/browser/media/offscreen_tab.h"
+#include "content/public/browser/web_contents_user_data.h"
+#include "ui/gfx/geometry/size.h"
+
+class OffscreenTab;
+
+namespace extensions {
+
+// Creates, owns, and manages all OffscreenTab instances created by the same
+// extension background page. When the extension background page's WebContents
+// is about to be destroyed, its associated OffscreenTabsOwner and all of its
+// OffscreenTab instances are destroyed.
+//
+// Usage:
+//
+// OffscreenTabsOwner::Get(extension_contents)
+// ->OpenNewTab(start_url, size, std::string());
+//
+// This class operates exclusively on the UI thread and so is not thread-safe.
+class OffscreenTabsOwner final
+ : public OffscreenTab::Owner,
+ public content::WebContentsUserData<OffscreenTabsOwner> {
+ public:
+ ~OffscreenTabsOwner() final;
+
+ // Returns the OffscreenTabsOwner instance associated with the given extension
+ // background page's WebContents. Never returns nullptr.
+ static OffscreenTabsOwner* Get(content::WebContents* extension_web_contents);
+
+ // Instantiate a new offscreen tab and navigate it to |start_url|. The new
+ // tab's main frame will start out with the given |initial_size| in DIP
+ // coordinates. If too many offscreen tabs are already running, nothing
+ // happens and nullptr is returned.
+ //
+ // If |optional_presentation_id| is non-empty, the offscreen tab is registered
+ // for use by the Media Router (chrome/browser/media/router/...) as the
+ // receiving browsing context for the W3C Presentation API.
+ OffscreenTab* OpenNewTab(const GURL& start_url,
+ const gfx::Size& initial_size,
+ const std::string& optional_presentation_id);
+
+ private:
+ friend class content::WebContentsUserData<OffscreenTabsOwner>;
+
+ explicit OffscreenTabsOwner(content::WebContents* extension_web_contents);
+
+ // OffscreenTab::Owner implementation.
+ void RequestMediaAccessPermission(
+ const content::MediaStreamRequest& request,
+ content::MediaResponseCallback callback) override;
+ void DestroyTab(OffscreenTab* tab) override;
+
+ content::WebContents* const extension_web_contents_;
+ std::vector<std::unique_ptr<OffscreenTab>> tabs_;
+
+ DISALLOW_COPY_AND_ASSIGN(OffscreenTabsOwner);
+};
+
+} // namespace extensions
+
+#endif // CHROME_BROWSER_EXTENSIONS_API_TAB_CAPTURE_OFFSCREEN_TABS_OWNER_H_
diff --git a/chromium/chrome/browser/extensions/api/tab_capture/tab_capture_api.cc b/chromium/chrome/browser/extensions/api/tab_capture/tab_capture_api.cc
index 529970f3025..7ea18093f69 100644
--- a/chromium/chrome/browser/extensions/api/tab_capture/tab_capture_api.cc
+++ b/chromium/chrome/browser/extensions/api/tab_capture/tab_capture_api.cc
@@ -18,7 +18,7 @@
#include "base/strings/string_util.h"
#include "base/strings/stringprintf.h"
#include "base/values.h"
-#include "chrome/browser/extensions/api/tab_capture/offscreen_tab.h"
+#include "chrome/browser/extensions/api/tab_capture/offscreen_tabs_owner.h"
#include "chrome/browser/extensions/api/tab_capture/tab_capture_registry.h"
#include "chrome/browser/profiles/profile.h"
#include "chrome/browser/sessions/session_tab_helper.h"
@@ -26,6 +26,7 @@
#include "chrome/browser/ui/browser_finder.h"
#include "chrome/browser/ui/tabs/tab_strip_model.h"
#include "chrome/common/chrome_switches.h"
+#include "content/public/browser/desktop_media_id.h"
#include "content/public/browser/render_frame_host.h"
#include "content/public/browser/render_process_host.h"
#include "content/public/browser/web_contents.h"
@@ -35,6 +36,8 @@
#include "extensions/common/permissions/permissions_data.h"
#include "extensions/common/switches.h"
+using content::DesktopMediaID;
+using content::WebContentsMediaCaptureId;
using extensions::api::tab_capture::MediaStreamConstraint;
namespace TabCapture = extensions::api::tab_capture;
@@ -116,21 +119,7 @@ void FilterDeprecatedGoogConstraints(TabCapture::CaptureOptions* options) {
}
}
-// Add Chrome-specific source identifiers to the MediaStreamConstraints objects
-// in |options| to provide references to the |target_contents| to be captured.
-void AddMediaStreamSourceConstraints(content::WebContents* target_contents,
- TabCapture::CaptureOptions* options) {
- DCHECK(options);
- DCHECK(target_contents);
-
- MediaStreamConstraint* constraints_to_modify[2] = { nullptr, nullptr };
-
- if (options->audio && *options->audio) {
- if (!options->audio_constraints)
- options->audio_constraints.reset(new MediaStreamConstraint);
- constraints_to_modify[0] = options->audio_constraints.get();
- }
-
+bool GetAutoThrottlingFromOptions(TabCapture::CaptureOptions* options) {
bool enable_auto_throttling = false;
if (options->video && *options->video) {
if (options->video_constraints) {
@@ -146,21 +135,45 @@ void AddMediaStreamSourceConstraints(content::WebContents* target_contents,
// Remove the key from the properties to avoid an "unrecognized
// constraint" error in the renderer.
props.RemoveWithoutPathExpansion(kEnableAutoThrottlingKey, nullptr);
- } else {
- options->video_constraints.reset(new MediaStreamConstraint);
}
- constraints_to_modify[1] = options->video_constraints.get();
}
- // Format the device ID that references the target tab.
- content::RenderFrameHost* const main_frame = target_contents->GetMainFrame();
- // TODO(miu): We should instead use a "randomly generated device ID" scheme,
- // like that employed by the desktop capture API. http://crbug.com/163100
- const std::string device_id = base::StringPrintf(
- "web-contents-media-stream://%i:%i%s",
- main_frame->GetProcess()->GetID(),
- main_frame->GetRoutingID(),
- enable_auto_throttling ? "?throttling=auto" : "");
+ return enable_auto_throttling;
+}
+
+DesktopMediaID BuildDesktopMediaID(content::WebContents* target_contents,
+ TabCapture::CaptureOptions* options) {
+ content::RenderFrameHost* const target_frame =
+ target_contents->GetMainFrame();
+ DesktopMediaID source(
+ DesktopMediaID::TYPE_WEB_CONTENTS, DesktopMediaID::kNullId,
+ WebContentsMediaCaptureId(target_frame->GetProcess()->GetID(),
+ target_frame->GetRoutingID(),
+ GetAutoThrottlingFromOptions(options), false));
+ return source;
+}
+
+// Add Chrome-specific source identifiers to the MediaStreamConstraints objects
+// in |options| to provide references to the |target_contents| to be captured.
+void AddMediaStreamSourceConstraints(content::WebContents* target_contents,
+ TabCapture::CaptureOptions* options,
+ const std::string& device_id) {
+ DCHECK(options);
+ DCHECK(target_contents);
+
+ MediaStreamConstraint* constraints_to_modify[2] = {nullptr, nullptr};
+
+ if (options->audio && *options->audio) {
+ if (!options->audio_constraints)
+ options->audio_constraints.reset(new MediaStreamConstraint);
+ constraints_to_modify[0] = options->audio_constraints.get();
+ }
+
+ if (options->video && *options->video) {
+ if (!options->video_constraints)
+ options->video_constraints.reset(new MediaStreamConstraint);
+ constraints_to_modify[1] = options->video_constraints.get();
+ }
// Append chrome specific tab constraints.
for (MediaStreamConstraint* msc : constraints_to_modify) {
@@ -217,14 +230,21 @@ ExtensionFunction::ResponseAction TabCaptureCaptureFunction::Run() {
if (!OptionsSpecifyAudioOrVideo(params->options))
return RespondNow(Error(kNoAudioOrVideo));
+ DesktopMediaID source =
+ BuildDesktopMediaID(target_contents, &params->options);
+ content::WebContents* const extension_web_contents = GetSenderWebContents();
+ EXTENSION_FUNCTION_VALIDATE(extension_web_contents);
TabCaptureRegistry* registry = TabCaptureRegistry::Get(browser_context());
- if (!registry->AddRequest(target_contents, extension_id, false)) {
+ std::string device_id = registry->AddRequest(
+ target_contents, extension_id, false, extension()->url(), source,
+ extension()->name(), extension_web_contents);
+ if (device_id.empty()) {
// TODO(miu): Allow multiple consumers of single tab capture.
// http://crbug.com/535336
return RespondNow(Error(kCapturingSameTab));
}
FilterDeprecatedGoogConstraints(&params->options);
- AddMediaStreamSourceConstraints(target_contents, &params->options);
+ AddMediaStreamSourceConstraints(target_contents, &params->options, device_id);
// At this point, everything is set up in the browser process. It's now up to
// the custom JS bindings in the extension's render process to request a
@@ -283,15 +303,21 @@ ExtensionFunction::ResponseAction TabCaptureCaptureOffscreenTabFunction::Run() {
if (!offscreen_tab)
return RespondNow(Error(kTooManyOffscreenTabs));
- if (!TabCaptureRegistry::Get(browser_context())->AddRequest(
- offscreen_tab->web_contents(), extension()->id(), true)) {
+ content::WebContents* target_contents = offscreen_tab->web_contents();
+ const std::string& extension_id = extension()->id();
+ DesktopMediaID source =
+ BuildDesktopMediaID(target_contents, &params->options);
+ TabCaptureRegistry* registry = TabCaptureRegistry::Get(browser_context());
+ std::string device_id = registry->AddRequest(
+ target_contents, extension_id, true, extension()->url(), source,
+ extension()->name(), extension_web_contents);
+ if (device_id.empty()) {
// TODO(miu): Allow multiple consumers of single tab capture.
// http://crbug.com/535336
return RespondNow(Error(kCapturingSameOffscreenTab));
}
FilterDeprecatedGoogConstraints(&params->options);
- AddMediaStreamSourceConstraints(offscreen_tab->web_contents(),
- &params->options);
+ AddMediaStreamSourceConstraints(target_contents, &params->options, device_id);
// At this point, everything is set up in the browser process. It's now up to
// the custom JS bindings in the extension's render process to complete the
diff --git a/chromium/chrome/browser/extensions/api/tab_capture/tab_capture_registry.cc b/chromium/chrome/browser/extensions/api/tab_capture/tab_capture_registry.cc
index c8a4493a740..52b033eb2cb 100644
--- a/chromium/chrome/browser/extensions/api/tab_capture/tab_capture_registry.cc
+++ b/chromium/chrome/browser/extensions/api/tab_capture/tab_capture_registry.cc
@@ -13,7 +13,9 @@
#include "chrome/browser/sessions/session_tab_helper.h"
#include "components/keyed_service/content/browser_context_dependency_manager.h"
#include "content/public/browser/browser_thread.h"
+#include "content/public/browser/desktop_streams_registry.h"
#include "content/public/browser/render_frame_host.h"
+#include "content/public/browser/render_process_host.h"
#include "content/public/browser/web_contents.h"
#include "content/public/browser/web_contents_observer.h"
#include "extensions/browser/event_router.h"
@@ -138,8 +140,9 @@ class TabCaptureRegistry::LiveRequest : public content::WebContentsObserver {
#if defined(USE_AURA)
window_agent_(target_contents->GetNativeView()),
#endif
- render_process_id_(-1),
- render_frame_id_(-1) {
+ render_process_id_(
+ target_contents->GetMainFrame()->GetProcess()->GetID()),
+ render_frame_id_(target_contents->GetMainFrame()->GetRoutingID()) {
DCHECK(web_contents());
DCHECK(registry_);
}
@@ -165,17 +168,8 @@ class TabCaptureRegistry::LiveRequest : public content::WebContentsObserver {
is_verified_ = true;
}
- // TODO(miu): See TODO(miu) in VerifyRequest() below.
- void SetOriginallyTargettedRenderFrameID(int render_process_id,
- int render_frame_id) {
- DCHECK_GT(render_frame_id, 0);
- DCHECK_EQ(render_frame_id_, -1); // Setting ID only once.
- render_process_id_ = render_process_id;
- render_frame_id_ = render_frame_id;
- }
-
- bool WasOriginallyTargettingRenderFrameID(int render_process_id,
- int render_frame_id) const {
+ bool WasTargettingRenderFrameID(int render_process_id,
+ int render_frame_id) const {
return render_process_id_ == render_process_id &&
render_frame_id_ == render_frame_id;
}
@@ -298,16 +292,22 @@ void TabCaptureRegistry::OnExtensionUnloaded(
}
}
-bool TabCaptureRegistry::AddRequest(content::WebContents* target_contents,
- const std::string& extension_id,
- bool is_anonymous) {
+std::string TabCaptureRegistry::AddRequest(
+ content::WebContents* target_contents,
+ const std::string& extension_id,
+ bool is_anonymous,
+ const GURL& origin,
+ content::DesktopMediaID source,
+ const std::string& extension_name,
+ content::WebContents* caller_contents) {
+ std::string device_id;
LiveRequest* const request = FindRequest(target_contents);
// Currently, we do not allow multiple active captures for same tab.
if (request != NULL) {
if (request->capture_state() == tab_capture::TAB_CAPTURE_STATE_PENDING ||
request->capture_state() == tab_capture::TAB_CAPTURE_STATE_ACTIVE) {
- return false;
+ return device_id;
} else {
// Delete the request before creating its replacement (below).
KillRequest(request);
@@ -316,7 +316,15 @@ bool TabCaptureRegistry::AddRequest(content::WebContents* target_contents,
requests_.push_back(std::make_unique<LiveRequest>(
target_contents, extension_id, is_anonymous, this));
- return true;
+
+ content::RenderFrameHost* const main_frame = caller_contents->GetMainFrame();
+ if (main_frame) {
+ device_id = content::DesktopStreamsRegistry::GetInstance()->RegisterStream(
+ main_frame->GetProcess()->GetID(), main_frame->GetRoutingID(), origin,
+ source, extension_name, content::kRegistryStreamTypeTab);
+ }
+
+ return device_id;
}
bool TabCaptureRegistry::VerifyRequest(
@@ -325,56 +333,35 @@ bool TabCaptureRegistry::VerifyRequest(
const std::string& extension_id) {
DCHECK_CURRENTLY_ON(BrowserThread::UI);
- LiveRequest* const request = FindRequest(
- content::WebContents::FromRenderFrameHost(
- content::RenderFrameHost::FromID(
- render_process_id, render_frame_id)));
- if (!request)
+ LiveRequest* const request = FindRequest(render_process_id, render_frame_id);
+ if (!request) {
return false; // Unknown RenderFrameHost ID, or frame has gone away.
+ }
- // TODO(miu): We should probably also verify the origin URL, like the desktop
- // capture API. http://crbug.com/163100
if (request->is_verified() ||
request->extension_id() != extension_id ||
(request->capture_state() != tab_capture::TAB_CAPTURE_STATE_NONE &&
request->capture_state() != tab_capture::TAB_CAPTURE_STATE_PENDING))
return false;
- // TODO(miu): The RenderFrameHost IDs should be set when LiveRequest is
- // constructed, but ExtensionFunction does not yet support use of
- // render_frame_host() to determine the exact RenderFrameHost for the call to
- // AddRequest() above. Fix tab_capture_api.cc, and then fix this ugly hack.
- // http://crbug.com/304341
- request->SetOriginallyTargettedRenderFrameID(
- render_process_id, render_frame_id);
-
request->SetIsVerified();
return true;
}
void TabCaptureRegistry::OnRequestUpdate(
- int original_target_render_process_id,
- int original_target_render_frame_id,
+ int target_render_process_id,
+ int target_render_frame_id,
content::MediaStreamType stream_type,
const content::MediaRequestState new_state) {
DCHECK_CURRENTLY_ON(BrowserThread::UI);
- if (stream_type != content::MEDIA_TAB_VIDEO_CAPTURE &&
- stream_type != content::MEDIA_TAB_AUDIO_CAPTURE) {
+ if (stream_type != content::MEDIA_GUM_TAB_VIDEO_CAPTURE &&
+ stream_type != content::MEDIA_GUM_TAB_AUDIO_CAPTURE) {
return;
}
- LiveRequest* request = FindRequest(original_target_render_process_id,
- original_target_render_frame_id);
+ LiveRequest* request =
+ FindRequest(target_render_process_id, target_render_frame_id);
if (!request) {
- // Fall-back: Search again using WebContents since this method may have been
- // called before VerifyRequest() set the RenderFrameHost ID. If the
- // RenderFrameHost has gone away, that's okay since the upcoming call to
- // VerifyRequest() will fail, and that means the tracking of request updates
- // doesn't matter anymore.
- request = FindRequest(content::WebContents::FromRenderFrameHost(
- content::RenderFrameHost::FromID(original_target_render_process_id,
- original_target_render_frame_id)));
- if (!request)
return; // Stale or invalid request update.
}
@@ -444,12 +431,11 @@ TabCaptureRegistry::LiveRequest* TabCaptureRegistry::FindRequest(
}
TabCaptureRegistry::LiveRequest* TabCaptureRegistry::FindRequest(
- int original_target_render_process_id,
- int original_target_render_frame_id) const {
+ int target_render_process_id,
+ int target_render_frame_id) const {
for (const std::unique_ptr<LiveRequest>& request : requests_) {
- if (request->WasOriginallyTargettingRenderFrameID(
- original_target_render_process_id,
- original_target_render_frame_id)) {
+ if (request->WasTargettingRenderFrameID(target_render_process_id,
+ target_render_frame_id)) {
return request.get();
}
}
diff --git a/chromium/chrome/browser/extensions/api/tab_capture/tab_capture_registry.h b/chromium/chrome/browser/extensions/api/tab_capture/tab_capture_registry.h
index 4d4abd65d1e..80b2b7e361a 100644
--- a/chromium/chrome/browser/extensions/api/tab_capture/tab_capture_registry.h
+++ b/chromium/chrome/browser/extensions/api/tab_capture/tab_capture_registry.h
@@ -13,6 +13,7 @@
#include "base/scoped_observer.h"
#include "chrome/browser/media/webrtc/media_capture_devices_dispatcher.h"
#include "chrome/common/extensions/api/tab_capture.h"
+#include "content/public/browser/desktop_media_id.h"
#include "content/public/browser/media_request_state.h"
#include "extensions/browser/browser_context_keyed_api_factory.h"
#include "extensions/browser/extension_registry_observer.h"
@@ -47,18 +48,23 @@ class TabCaptureRegistry : public BrowserContextKeyedAPI,
base::ListValue* list_of_capture_info) const;
// Add a tab capture request to the registry when a stream is requested
- // through the API. |target_contents| refers to the WebContents associated
- // with the tab to be captured. |extension_id| refers to the Extension
- // initiating the request. |is_anonymous| is true if GetCapturedTabs() should
- // not list the captured tab, and no status change events should be dispatched
- // for it.
- //
- // TODO(miu): This is broken in that it's possible for a later WebContents
- // instance to have the same pointer value as a previously-destroyed one. To
- // be fixed while working on http://crbug.com/163100.
- bool AddRequest(content::WebContents* target_contents,
- const std::string& extension_id,
- bool is_anonymous);
+ // through the API and create a randomly generated device id after user
+ // initiated access to |source| for the |origin|. If capture is already
+ // taking place for the same tab, this operation fails and returns an
+ // empty string.
+ // |target_contents|: the WebContents associated with the tab to be captured.
+ // |extension_id|: the Extension initiating the request.
+ // |is_anonymous| is true if GetCapturedTabs() should not list the captured
+ // tab, and no status change events should be dispatched for it.
+ // |caller_contents|: the WebContents associated with the tab/extension that
+ // starts the capture.
+ std::string AddRequest(content::WebContents* target_contents,
+ const std::string& extension_id,
+ bool is_anonymous,
+ const GURL& origin,
+ content::DesktopMediaID source,
+ const std::string& extension_name,
+ content::WebContents* caller_contents);
// Called by MediaStreamDevicesController to verify the request before
// creating the stream. |render_process_id| and |render_frame_id| are used to
@@ -91,8 +97,8 @@ class TabCaptureRegistry : public BrowserContextKeyedAPI,
UnloadedExtensionReason reason) override;
// MediaCaptureDevicesDispatcher::Observer implementation.
- void OnRequestUpdate(int original_target_render_process_id,
- int original_target_render_frame_id,
+ void OnRequestUpdate(int target_render_process_id,
+ int target_render_frame_id,
content::MediaStreamType stream_type,
const content::MediaRequestState state) override;
@@ -102,8 +108,8 @@ class TabCaptureRegistry : public BrowserContextKeyedAPI,
// Look-up a LiveRequest associated with the given |target_contents| (or
// the originally targetted RenderFrameHost), if any.
LiveRequest* FindRequest(const content::WebContents* target_contents) const;
- LiveRequest* FindRequest(int original_target_render_process_id,
- int original_target_render_frame_id) const;
+ LiveRequest* FindRequest(int target_render_process_id,
+ int target_render_frame_id) const;
// Removes the |request| from |requests_|, thus causing its destruction.
void KillRequest(LiveRequest* request);
diff --git a/chromium/chrome/browser/extensions/api/tabs/tabs_api.cc b/chromium/chrome/browser/extensions/api/tabs/tabs_api.cc
index 6dbd04f2fb0..e5dbcdc147d 100644
--- a/chromium/chrome/browser/extensions/api/tabs/tabs_api.cc
+++ b/chromium/chrome/browser/extensions/api/tabs/tabs_api.cc
@@ -53,7 +53,7 @@
#include "chrome/browser/ui/tabs/tab_strip_model.h"
#include "chrome/browser/ui/tabs/tab_utils.h"
#include "chrome/browser/ui/window_sizer/window_sizer.h"
-#include "chrome/browser/web_applications/extensions/web_app_extension_helpers.h"
+#include "chrome/browser/web_applications/components/web_app_helpers.h"
#include "chrome/common/chrome_switches.h"
#include "chrome/common/extensions/api/tabs.h"
#include "chrome/common/extensions/api/windows.h"
@@ -280,7 +280,7 @@ void SetLockedFullscreenState(Browser* browser, bool locked) {
// Disallow screenshots in locked fullscreen mode.
// TODO(isandrk, 816900): ChromeScreenshotGrabber isn't implemented in Mash
// yet, remove this conditional when it becomes available.
- if (features::IsAshInBrowserProcess())
+ if (!features::IsMultiProcessMash())
ChromeScreenshotGrabber::Get()->set_screenshots_allowed(!locked);
// Reset the clipboard and kill dev tools when entering or exiting locked
@@ -593,7 +593,7 @@ ExtensionFunction::ResponseAction WindowsCreateFunction::Run() {
create_params.initial_bounds = window_bounds;
} else {
create_params = Browser::CreateParams::CreateForApp(
- web_app::GenerateApplicationNameFromExtensionId(extension_id),
+ web_app::GenerateApplicationNameFromAppId(extension_id),
false /* trusted_source */, window_bounds, window_profile,
user_gesture());
}
diff --git a/chromium/chrome/browser/extensions/api/tabs/tabs_event_router.cc b/chromium/chrome/browser/extensions/api/tabs/tabs_event_router.cc
index 43d4ab78ab9..a2c3f3ab41d 100644
--- a/chromium/chrome/browser/extensions/api/tabs/tabs_event_router.cc
+++ b/chromium/chrome/browser/extensions/api/tabs/tabs_event_router.cc
@@ -63,6 +63,23 @@ bool WillDispatchTabUpdatedEvent(
return true;
}
+bool WillDispatchTabCreatedEvent(WebContents* contents,
+ bool active,
+ content::BrowserContext* context,
+ const Extension* extension,
+ Event* event,
+ const base::DictionaryValue* listener_filter) {
+ event->event_args->Clear();
+ std::unique_ptr<base::DictionaryValue> tab_value =
+ ExtensionTabUtil::CreateTabObject(contents, ExtensionTabUtil::kScrubTab,
+ extension)
+ ->ToValue();
+ tab_value->SetBoolean(tabs_constants::kSelectedKey, active);
+ tab_value->SetBoolean(tabs_constants::kActiveKey, active);
+ event->event_args->Append(std::move(tab_value));
+ return true;
+}
+
} // namespace
TabsEventRouter::TabEntry::TabEntry(TabsEventRouter* router,
@@ -155,74 +172,143 @@ bool TabsEventRouter::ShouldTrackBrowser(Browser* browser) {
ExtensionTabUtil::BrowserSupportsTabs(browser);
}
-void TabsEventRouter::RegisterForTabNotifications(WebContents* contents) {
- favicon_scoped_observer_.Add(
- favicon::ContentFaviconDriver::FromWebContents(contents));
+void TabsEventRouter::OnBrowserSetLastActive(Browser* browser) {
+ TabsWindowsAPI* tabs_window_api = TabsWindowsAPI::Get(profile_);
+ if (tabs_window_api) {
+ tabs_window_api->windows_event_router()->OnActiveWindowChanged(
+ browser ? browser->extension_window_controller() : NULL);
+ }
+}
- ZoomController::FromWebContents(contents)->AddObserver(this);
+void TabsEventRouter::OnTabStripModelChanged(
+ TabStripModel* tab_strip_model,
+ const TabStripModelChange& change,
+ const TabStripSelectionChange& selection) {
+ switch (change.type()) {
+ case TabStripModelChange::kInserted: {
+ for (const auto& delta : change.deltas()) {
+ DispatchTabInsertedAt(tab_strip_model, delta.insert.contents,
+ delta.insert.index,
+ selection.new_contents == delta.insert.contents);
+ }
+ break;
+ }
+ case TabStripModelChange::kRemoved: {
+ for (const auto& delta : change.deltas()) {
+ if (delta.remove.will_be_deleted)
+ DispatchTabClosingAt(tab_strip_model, delta.remove.contents,
+ delta.remove.index);
+
+ DispatchTabDetachedAt(delta.remove.contents, delta.remove.index,
+ selection.old_contents == delta.remove.contents);
+ }
+ break;
+ }
+ case TabStripModelChange::kMoved: {
+ for (const auto& delta : change.deltas()) {
+ DispatchTabMoved(delta.move.contents, delta.move.from_index,
+ delta.move.to_index);
+ }
+ break;
+ }
+ case TabStripModelChange::kReplaced: {
+ for (const auto& delta : change.deltas()) {
+ DispatchTabReplacedAt(delta.replace.old_contents,
+ delta.replace.new_contents, delta.replace.index);
+ }
+ break;
+ }
+ case TabStripModelChange::kSelectionOnly:
+ break;
+ }
- int tab_id = ExtensionTabUtil::GetTabId(contents);
- DCHECK(tab_entries_.find(tab_id) == tab_entries_.end());
- tab_entries_[tab_id] = std::make_unique<TabEntry>(this, contents);
+ if (tab_strip_model->empty())
+ return;
+
+ if (selection.active_tab_changed()) {
+ DispatchActiveTabChanged(selection.old_contents, selection.new_contents,
+ selection.new_model.active(), selection.reason);
+ }
+
+ if (selection.selection_changed()) {
+ DispatchTabSelectionChanged(tab_strip_model, selection.old_model);
+ }
}
-void TabsEventRouter::UnregisterForTabNotifications(WebContents* contents) {
- favicon_scoped_observer_.Remove(
- favicon::ContentFaviconDriver::FromWebContents(contents));
+void TabsEventRouter::TabChangedAt(WebContents* contents,
+ int index,
+ TabChangeType change_type) {
+ TabEntry* entry = GetTabEntry(contents);
+ // TabClosingAt() may have already removed the entry for |contents| even
+ // though the tab has not yet been detached.
+ if (entry)
+ TabUpdated(entry, entry->UpdateLoadState());
+}
- ZoomController::FromWebContents(contents)->RemoveObserver(this);
+void TabsEventRouter::TabPinnedStateChanged(TabStripModel* tab_strip_model,
+ WebContents* contents,
+ int index) {
+ std::set<std::string> changed_property_names;
+ changed_property_names.insert(tabs_constants::kPinnedKey);
+ DispatchTabUpdatedEvent(contents, std::move(changed_property_names));
+}
- int tab_id = ExtensionTabUtil::GetTabId(contents);
- int removed_count = tab_entries_.erase(tab_id);
- DCHECK_GT(removed_count, 0);
+void TabsEventRouter::OnZoomChanged(
+ const ZoomController::ZoomChangedEventData& data) {
+ DCHECK(data.web_contents);
+ int tab_id = ExtensionTabUtil::GetTabId(data.web_contents);
+ if (tab_id < 0)
+ return;
+
+ // Prepare the zoom change information.
+ api::tabs::OnZoomChange::ZoomChangeInfo zoom_change_info;
+ zoom_change_info.tab_id = tab_id;
+ zoom_change_info.old_zoom_factor =
+ content::ZoomLevelToZoomFactor(data.old_zoom_level);
+ zoom_change_info.new_zoom_factor =
+ content::ZoomLevelToZoomFactor(data.new_zoom_level);
+ ZoomModeToZoomSettings(data.zoom_mode, &zoom_change_info.zoom_settings);
+
+ // Dispatch the |onZoomChange| event.
+ Profile* profile =
+ Profile::FromBrowserContext(data.web_contents->GetBrowserContext());
+ DispatchEvent(profile, events::TABS_ON_ZOOM_CHANGE,
+ api::tabs::OnZoomChange::kEventName,
+ api::tabs::OnZoomChange::Create(zoom_change_info),
+ EventRouter::USER_GESTURE_UNKNOWN);
}
-void TabsEventRouter::OnBrowserSetLastActive(Browser* browser) {
- TabsWindowsAPI* tabs_window_api = TabsWindowsAPI::Get(profile_);
- if (tabs_window_api) {
- tabs_window_api->windows_event_router()->OnActiveWindowChanged(
- browser ? browser->extension_window_controller() : NULL);
+void TabsEventRouter::OnFaviconUpdated(
+ favicon::FaviconDriver* favicon_driver,
+ NotificationIconType notification_icon_type,
+ const GURL& icon_url,
+ bool icon_url_changed,
+ const gfx::Image& image) {
+ if (notification_icon_type == NON_TOUCH_16_DIP && icon_url_changed) {
+ favicon::ContentFaviconDriver* content_favicon_driver =
+ static_cast<favicon::ContentFaviconDriver*>(favicon_driver);
+ FaviconUrlUpdated(content_favicon_driver->web_contents());
}
}
-static bool WillDispatchTabCreatedEvent(
- WebContents* contents,
- bool active,
- content::BrowserContext* context,
- const Extension* extension,
- Event* event,
- const base::DictionaryValue* listener_filter) {
- event->event_args->Clear();
- std::unique_ptr<base::DictionaryValue> tab_value =
- ExtensionTabUtil::CreateTabObject(contents, ExtensionTabUtil::kScrubTab,
- extension)
- ->ToValue();
- tab_value->SetBoolean(tabs_constants::kSelectedKey, active);
- tab_value->SetBoolean(tabs_constants::kActiveKey, active);
- event->event_args->Append(std::move(tab_value));
- return true;
+void TabsEventRouter::OnDiscardedStateChange(WebContents* contents,
+ bool is_discarded) {
+ std::set<std::string> changed_property_names;
+ changed_property_names.insert(tabs_constants::kDiscardedKey);
+ DispatchTabUpdatedEvent(contents, std::move(changed_property_names));
}
-void TabsEventRouter::TabCreatedAt(WebContents* contents,
- int index,
- bool active) {
- Profile* profile = Profile::FromBrowserContext(contents->GetBrowserContext());
- std::unique_ptr<base::ListValue> args(new base::ListValue);
- auto event = std::make_unique<Event>(events::TABS_ON_CREATED,
- api::tabs::OnCreated::kEventName,
- std::move(args), profile);
- event->user_gesture = EventRouter::USER_GESTURE_NOT_ENABLED;
- event->will_dispatch_callback =
- base::Bind(&WillDispatchTabCreatedEvent, contents, active);
- EventRouter::Get(profile)->BroadcastEvent(std::move(event));
-
- RegisterForTabNotifications(contents);
+void TabsEventRouter::OnAutoDiscardableStateChange(WebContents* contents,
+ bool is_auto_discardable) {
+ std::set<std::string> changed_property_names;
+ changed_property_names.insert(tabs_constants::kAutoDiscardableKey);
+ DispatchTabUpdatedEvent(contents, std::move(changed_property_names));
}
-void TabsEventRouter::TabInsertedAt(TabStripModel* tab_strip_model,
- WebContents* contents,
- int index,
- bool active) {
+void TabsEventRouter::DispatchTabInsertedAt(TabStripModel* tab_strip_model,
+ WebContents* contents,
+ int index,
+ bool active) {
if (!GetTabEntry(contents)) {
// We've never seen this tab, send create event as long as we're not in the
// constructor.
@@ -252,9 +338,33 @@ void TabsEventRouter::TabInsertedAt(TabStripModel* tab_strip_model,
EventRouter::USER_GESTURE_UNKNOWN);
}
-void TabsEventRouter::TabDetachedAt(WebContents* contents,
- int index,
- bool was_active) {
+void TabsEventRouter::DispatchTabClosingAt(TabStripModel* tab_strip_model,
+ WebContents* contents,
+ int index) {
+ int tab_id = ExtensionTabUtil::GetTabId(contents);
+
+ std::unique_ptr<base::ListValue> args(new base::ListValue);
+ args->AppendInteger(tab_id);
+
+ std::unique_ptr<base::DictionaryValue> object_args(
+ new base::DictionaryValue());
+ object_args->SetInteger(tabs_constants::kWindowIdKey,
+ ExtensionTabUtil::GetWindowIdOfTab(contents));
+ object_args->SetBoolean(tabs_constants::kWindowClosing,
+ tab_strip_model->closing_all());
+ args->Append(std::move(object_args));
+
+ Profile* profile = Profile::FromBrowserContext(contents->GetBrowserContext());
+ DispatchEvent(profile, events::TABS_ON_REMOVED,
+ api::tabs::OnRemoved::kEventName, std::move(args),
+ EventRouter::USER_GESTURE_UNKNOWN);
+
+ UnregisterForTabNotifications(contents);
+}
+
+void TabsEventRouter::DispatchTabDetachedAt(WebContents* contents,
+ int index,
+ bool was_active) {
if (!GetTabEntry(contents)) {
// The tab was removed. Don't send detach event.
return;
@@ -278,34 +388,10 @@ void TabsEventRouter::TabDetachedAt(WebContents* contents,
EventRouter::USER_GESTURE_UNKNOWN);
}
-void TabsEventRouter::TabClosingAt(TabStripModel* tab_strip_model,
- WebContents* contents,
- int index) {
- int tab_id = ExtensionTabUtil::GetTabId(contents);
-
- std::unique_ptr<base::ListValue> args(new base::ListValue);
- args->AppendInteger(tab_id);
-
- std::unique_ptr<base::DictionaryValue> object_args(
- new base::DictionaryValue());
- object_args->SetInteger(tabs_constants::kWindowIdKey,
- ExtensionTabUtil::GetWindowIdOfTab(contents));
- object_args->SetBoolean(tabs_constants::kWindowClosing,
- tab_strip_model->closing_all());
- args->Append(std::move(object_args));
-
- Profile* profile = Profile::FromBrowserContext(contents->GetBrowserContext());
- DispatchEvent(profile, events::TABS_ON_REMOVED,
- api::tabs::OnRemoved::kEventName, std::move(args),
- EventRouter::USER_GESTURE_UNKNOWN);
-
- UnregisterForTabNotifications(contents);
-}
-
-void TabsEventRouter::ActiveTabChanged(WebContents* old_contents,
- WebContents* new_contents,
- int index,
- int reason) {
+void TabsEventRouter::DispatchActiveTabChanged(WebContents* old_contents,
+ WebContents* new_contents,
+ int index,
+ int reason) {
auto args = std::make_unique<base::ListValue>();
int tab_id = ExtensionTabUtil::GetTabId(new_contents);
args->AppendInteger(tab_id);
@@ -340,7 +426,7 @@ void TabsEventRouter::ActiveTabChanged(WebContents* old_contents,
std::move(on_activated_args), gesture);
}
-void TabsEventRouter::TabSelectionChanged(
+void TabsEventRouter::DispatchTabSelectionChanged(
TabStripModel* tab_strip_model,
const ui::ListSelectionModel& old_model) {
ui::ListSelectionModel::SelectedIndices new_selection =
@@ -378,9 +464,9 @@ void TabsEventRouter::TabSelectionChanged(
EventRouter::USER_GESTURE_UNKNOWN);
}
-void TabsEventRouter::TabMoved(WebContents* contents,
- int from_index,
- int to_index) {
+void TabsEventRouter::DispatchTabMoved(WebContents* contents,
+ int from_index,
+ int to_index) {
std::unique_ptr<base::ListValue> args(new base::ListValue);
args->AppendInteger(ExtensionTabUtil::GetTabId(contents));
@@ -400,6 +486,43 @@ void TabsEventRouter::TabMoved(WebContents* contents,
std::move(args), EventRouter::USER_GESTURE_UNKNOWN);
}
+void TabsEventRouter::DispatchTabReplacedAt(WebContents* old_contents,
+ WebContents* new_contents,
+ int index) {
+ // Notify listeners that the next tabs closing or being added are due to
+ // WebContents being swapped.
+ const int new_tab_id = ExtensionTabUtil::GetTabId(new_contents);
+ const int old_tab_id = ExtensionTabUtil::GetTabId(old_contents);
+ std::unique_ptr<base::ListValue> args(new base::ListValue);
+ args->AppendInteger(new_tab_id);
+ args->AppendInteger(old_tab_id);
+
+ DispatchEvent(Profile::FromBrowserContext(new_contents->GetBrowserContext()),
+ events::TABS_ON_REPLACED, api::tabs::OnReplaced::kEventName,
+ std::move(args), EventRouter::USER_GESTURE_UNKNOWN);
+
+ UnregisterForTabNotifications(old_contents);
+
+ if (!GetTabEntry(new_contents))
+ RegisterForTabNotifications(new_contents);
+}
+
+void TabsEventRouter::TabCreatedAt(WebContents* contents,
+ int index,
+ bool active) {
+ Profile* profile = Profile::FromBrowserContext(contents->GetBrowserContext());
+ std::unique_ptr<base::ListValue> args(new base::ListValue);
+ auto event = std::make_unique<Event>(events::TABS_ON_CREATED,
+ api::tabs::OnCreated::kEventName,
+ std::move(args), profile);
+ event->user_gesture = EventRouter::USER_GESTURE_NOT_ENABLED;
+ event->will_dispatch_callback =
+ base::Bind(&WillDispatchTabCreatedEvent, contents, active);
+ EventRouter::Get(profile)->BroadcastEvent(std::move(event));
+
+ RegisterForTabNotifications(contents);
+}
+
void TabsEventRouter::TabUpdated(TabEntry* entry,
std::set<std::string> changed_property_names) {
auto* audible_helper =
@@ -476,103 +599,32 @@ void TabsEventRouter::DispatchTabUpdatedEvent(
EventRouter::Get(profile)->BroadcastEvent(std::move(event));
}
-TabsEventRouter::TabEntry* TabsEventRouter::GetTabEntry(WebContents* contents) {
- const auto it = tab_entries_.find(ExtensionTabUtil::GetTabId(contents));
-
- return it == tab_entries_.end() ? nullptr : it->second.get();
-}
-
-void TabsEventRouter::TabChangedAt(WebContents* contents,
- int index,
- TabChangeType change_type) {
- TabEntry* entry = GetTabEntry(contents);
- // TabClosingAt() may have already removed the entry for |contents| even
- // though the tab has not yet been detached.
- if (entry)
- TabUpdated(entry, entry->UpdateLoadState());
-}
-
-void TabsEventRouter::TabReplacedAt(TabStripModel* tab_strip_model,
- WebContents* old_contents,
- WebContents* new_contents,
- int index) {
- // Notify listeners that the next tabs closing or being added are due to
- // WebContents being swapped.
- const int new_tab_id = ExtensionTabUtil::GetTabId(new_contents);
- const int old_tab_id = ExtensionTabUtil::GetTabId(old_contents);
- std::unique_ptr<base::ListValue> args(new base::ListValue);
- args->AppendInteger(new_tab_id);
- args->AppendInteger(old_tab_id);
-
- DispatchEvent(Profile::FromBrowserContext(new_contents->GetBrowserContext()),
- events::TABS_ON_REPLACED, api::tabs::OnReplaced::kEventName,
- std::move(args), EventRouter::USER_GESTURE_UNKNOWN);
-
- UnregisterForTabNotifications(old_contents);
+void TabsEventRouter::RegisterForTabNotifications(WebContents* contents) {
+ favicon_scoped_observer_.Add(
+ favicon::ContentFaviconDriver::FromWebContents(contents));
- if (!GetTabEntry(new_contents))
- RegisterForTabNotifications(new_contents);
-}
+ ZoomController::FromWebContents(contents)->AddObserver(this);
-void TabsEventRouter::TabPinnedStateChanged(TabStripModel* tab_strip_model,
- WebContents* contents,
- int index) {
- std::set<std::string> changed_property_names;
- changed_property_names.insert(tabs_constants::kPinnedKey);
- DispatchTabUpdatedEvent(contents, std::move(changed_property_names));
+ int tab_id = ExtensionTabUtil::GetTabId(contents);
+ DCHECK(tab_entries_.find(tab_id) == tab_entries_.end());
+ tab_entries_[tab_id] = std::make_unique<TabEntry>(this, contents);
}
-void TabsEventRouter::OnZoomChanged(
- const ZoomController::ZoomChangedEventData& data) {
- DCHECK(data.web_contents);
- int tab_id = ExtensionTabUtil::GetTabId(data.web_contents);
- if (tab_id < 0)
- return;
-
- // Prepare the zoom change information.
- api::tabs::OnZoomChange::ZoomChangeInfo zoom_change_info;
- zoom_change_info.tab_id = tab_id;
- zoom_change_info.old_zoom_factor =
- content::ZoomLevelToZoomFactor(data.old_zoom_level);
- zoom_change_info.new_zoom_factor =
- content::ZoomLevelToZoomFactor(data.new_zoom_level);
- ZoomModeToZoomSettings(data.zoom_mode,
- &zoom_change_info.zoom_settings);
+void TabsEventRouter::UnregisterForTabNotifications(WebContents* contents) {
+ favicon_scoped_observer_.Remove(
+ favicon::ContentFaviconDriver::FromWebContents(contents));
- // Dispatch the |onZoomChange| event.
- Profile* profile = Profile::FromBrowserContext(
- data.web_contents->GetBrowserContext());
- DispatchEvent(profile, events::TABS_ON_ZOOM_CHANGE,
- api::tabs::OnZoomChange::kEventName,
- api::tabs::OnZoomChange::Create(zoom_change_info),
- EventRouter::USER_GESTURE_UNKNOWN);
-}
+ ZoomController::FromWebContents(contents)->RemoveObserver(this);
-void TabsEventRouter::OnFaviconUpdated(
- favicon::FaviconDriver* favicon_driver,
- NotificationIconType notification_icon_type,
- const GURL& icon_url,
- bool icon_url_changed,
- const gfx::Image& image) {
- if (notification_icon_type == NON_TOUCH_16_DIP && icon_url_changed) {
- favicon::ContentFaviconDriver* content_favicon_driver =
- static_cast<favicon::ContentFaviconDriver*>(favicon_driver);
- FaviconUrlUpdated(content_favicon_driver->web_contents());
- }
+ int tab_id = ExtensionTabUtil::GetTabId(contents);
+ int removed_count = tab_entries_.erase(tab_id);
+ DCHECK_GT(removed_count, 0);
}
-void TabsEventRouter::OnDiscardedStateChange(WebContents* contents,
- bool is_discarded) {
- std::set<std::string> changed_property_names;
- changed_property_names.insert(tabs_constants::kDiscardedKey);
- DispatchTabUpdatedEvent(contents, std::move(changed_property_names));
-}
+TabsEventRouter::TabEntry* TabsEventRouter::GetTabEntry(WebContents* contents) {
+ const auto it = tab_entries_.find(ExtensionTabUtil::GetTabId(contents));
-void TabsEventRouter::OnAutoDiscardableStateChange(WebContents* contents,
- bool is_auto_discardable) {
- std::set<std::string> changed_property_names;
- changed_property_names.insert(tabs_constants::kAutoDiscardableKey);
- DispatchTabUpdatedEvent(contents, std::move(changed_property_names));
+ return it == tab_entries_.end() ? nullptr : it->second.get();
}
} // namespace extensions
diff --git a/chromium/chrome/browser/extensions/api/tabs/tabs_event_router.h b/chromium/chrome/browser/extensions/api/tabs/tabs_event_router.h
index d0b11d82c81..a7796a93f9d 100644
--- a/chromium/chrome/browser/extensions/api/tabs/tabs_event_router.h
+++ b/chromium/chrome/browser/extensions/api/tabs/tabs_event_router.h
@@ -54,32 +54,14 @@ class TabsEventRouter : public TabStripModelObserver,
void OnBrowserSetLastActive(Browser* browser) override;
// TabStripModelObserver:
- void TabInsertedAt(TabStripModel* tab_strip_model,
- content::WebContents* contents,
- int index,
- bool active) override;
- void TabClosingAt(TabStripModel* tab_strip_model,
- content::WebContents* contents,
- int index) override;
- void TabDetachedAt(content::WebContents* contents,
- int index,
- bool was_active) override;
- void ActiveTabChanged(content::WebContents* old_contents,
- content::WebContents* new_contents,
- int index,
- int reason) override;
- void TabSelectionChanged(TabStripModel* tab_strip_model,
- const ui::ListSelectionModel& old_model) override;
- void TabMoved(content::WebContents* contents,
- int from_index,
- int to_index) override;
+ void OnTabStripModelChanged(
+ TabStripModel* tab_strip_model,
+ const TabStripModelChange& change,
+ const TabStripSelectionChange& selection) override;
+
void TabChangedAt(content::WebContents* contents,
int index,
TabChangeType change_type) override;
- void TabReplacedAt(TabStripModel* tab_strip_model,
- content::WebContents* old_contents,
- content::WebContents* new_contents,
- int index) override;
void TabPinnedStateChanged(TabStripModel* tab_strip_model,
content::WebContents* contents,
int index) override;
@@ -102,7 +84,32 @@ class TabsEventRouter : public TabStripModelObserver,
bool is_auto_discardable) override;
private:
- // "Synthetic" event. Called from TabInsertedAt if new tab is detected.
+ // Methods called from OnTabStripModelChanged.
+ void DispatchTabInsertedAt(TabStripModel* tab_strip_model,
+ content::WebContents* contents,
+ int index,
+ bool active);
+ void DispatchTabClosingAt(TabStripModel* tab_strip_model,
+ content::WebContents* contents,
+ int index);
+ void DispatchTabDetachedAt(content::WebContents* contents,
+ int index,
+ bool was_active);
+ void DispatchActiveTabChanged(content::WebContents* old_contents,
+ content::WebContents* new_contents,
+ int index,
+ int reason);
+ void DispatchTabSelectionChanged(TabStripModel* tab_strip_model,
+ const ui::ListSelectionModel& old_model);
+ void DispatchTabMoved(content::WebContents* contents,
+ int from_index,
+ int to_index);
+ void DispatchTabReplacedAt(content::WebContents* old_contents,
+ content::WebContents* new_contents,
+ int index);
+
+ // "Synthetic" event. Called from DispatchTabInsertedAt if new tab is
+ // detected.
void TabCreatedAt(content::WebContents* contents, int index, bool active);
// Internal processing of tab updated events. Intended to be called when
@@ -123,12 +130,6 @@ class TabsEventRouter : public TabStripModelObserver,
std::unique_ptr<base::ListValue> args,
EventRouter::UserGestureState user_gesture);
- void DispatchEventsAcrossIncognito(
- Profile* profile,
- const std::string& event_name,
- std::unique_ptr<base::ListValue> event_args,
- std::unique_ptr<base::ListValue> cross_incognito_args);
-
// Packages |changed_property_names| as a tab updated event for the tab
// |contents| and dispatches the event to the extension.
void DispatchTabUpdatedEvent(
diff --git a/chromium/chrome/browser/extensions/api/terminal/terminal_private_api.cc b/chromium/chrome/browser/extensions/api/terminal/terminal_private_api.cc
index 6a0a795e8bb..b550c6a0e6e 100644
--- a/chromium/chrome/browser/extensions/api/terminal/terminal_private_api.cc
+++ b/chromium/chrome/browser/extensions/api/terminal/terminal_private_api.cc
@@ -12,7 +12,7 @@
#include "base/command_line.h"
#include "base/json/json_writer.h"
#include "base/sys_info.h"
-#include "base/task_scheduler/post_task.h"
+#include "base/task/post_task.h"
#include "base/values.h"
#include "chrome/browser/extensions/api/terminal/terminal_extension_helper.h"
#include "chrome/browser/extensions/extension_service.h"
diff --git a/chromium/chrome/browser/extensions/api/web_navigation/web_navigation_api.cc b/chromium/chrome/browser/extensions/api/web_navigation/web_navigation_api.cc
index 7c5099fbe81..c546379bcd8 100644
--- a/chromium/chrome/browser/extensions/api/web_navigation/web_navigation_api.cc
+++ b/chromium/chrome/browser/extensions/api/web_navigation/web_navigation_api.cc
@@ -33,8 +33,6 @@
namespace GetFrame = extensions::api::web_navigation::GetFrame;
namespace GetAllFrames = extensions::api::web_navigation::GetAllFrames;
-DEFINE_WEB_CONTENTS_USER_DATA_KEY(extensions::WebNavigationTabObserver);
-
namespace extensions {
namespace web_navigation = api::web_navigation;
@@ -90,25 +88,32 @@ bool WebNavigationEventRouter::ShouldTrackBrowser(Browser* browser) {
return profile_->IsSameProfile(browser->profile());
}
-void WebNavigationEventRouter::TabReplacedAt(
+void WebNavigationEventRouter::OnTabStripModelChanged(
TabStripModel* tab_strip_model,
- content::WebContents* old_contents,
- content::WebContents* new_contents,
- int index) {
- WebNavigationTabObserver* tab_observer =
- WebNavigationTabObserver::Get(old_contents);
- if (!tab_observer) {
- // If you hit this DCHECK(), please add reproduction steps to
- // http://crbug.com/109464.
- DCHECK(GetViewType(old_contents) != VIEW_TYPE_TAB_CONTENTS);
- return;
- }
- if (!FrameNavigationState::IsValidUrl(old_contents->GetURL()) ||
- !FrameNavigationState::IsValidUrl(new_contents->GetURL()))
+ const TabStripModelChange& change,
+ const TabStripSelectionChange& selection) {
+ if (change.type() != TabStripModelChange::kReplaced)
return;
- web_navigation_api_helpers::DispatchOnTabReplaced(old_contents, profile_,
- new_contents);
+ for (const auto& delta : change.deltas()) {
+ content::WebContents* old_contents = delta.replace.old_contents;
+ content::WebContents* new_contents = delta.replace.new_contents;
+
+ WebNavigationTabObserver* tab_observer =
+ WebNavigationTabObserver::Get(old_contents);
+ if (!tab_observer) {
+ // If you hit this DCHECK(), please add reproduction steps to
+ // http://crbug.com/109464.
+ DCHECK(GetViewType(old_contents) != VIEW_TYPE_TAB_CONTENTS);
+ continue;
+ }
+ if (!FrameNavigationState::IsValidUrl(old_contents->GetURL()) ||
+ !FrameNavigationState::IsValidUrl(new_contents->GetURL()))
+ continue;
+
+ web_navigation_api_helpers::DispatchOnTabReplaced(old_contents, profile_,
+ new_contents);
+ }
}
void WebNavigationEventRouter::Observe(
@@ -388,10 +393,14 @@ void WebNavigationTabObserver::DidOpenRequestedURL(
if (!router)
return;
- router->RecordNewWebContents(web_contents(),
- source_render_frame_host->GetProcess()->GetID(),
- source_render_frame_host->GetRoutingID(), url,
- new_contents, renderer_initiated);
+ TabStripModel* ignored_tab_strip_model = nullptr;
+ int ignored_tab_index = -1;
+ bool new_contents_is_present_in_tabstrip = ExtensionTabUtil::GetTabStripModel(
+ new_contents, &ignored_tab_strip_model, &ignored_tab_index);
+ router->RecordNewWebContents(
+ web_contents(), source_render_frame_host->GetProcess()->GetID(),
+ source_render_frame_host->GetRoutingID(), url, new_contents,
+ !new_contents_is_present_in_tabstrip);
}
void WebNavigationTabObserver::WebContentsDestroyed() {
diff --git a/chromium/chrome/browser/extensions/api/web_navigation/web_navigation_api.h b/chromium/chrome/browser/extensions/api/web_navigation/web_navigation_api.h
index 1b4b6645194..30e90fc1077 100644
--- a/chromium/chrome/browser/extensions/api/web_navigation/web_navigation_api.h
+++ b/chromium/chrome/browser/extensions/api/web_navigation/web_navigation_api.h
@@ -148,10 +148,10 @@ class WebNavigationEventRouter : public TabStripModelObserver,
bool ShouldTrackBrowser(Browser* browser) override;
// TabStripModelObserver implementation.
- void TabReplacedAt(TabStripModel* tab_strip_model,
- content::WebContents* old_contents,
- content::WebContents* new_contents,
- int index) override;
+ void OnTabStripModelChanged(
+ TabStripModel* tab_strip_model,
+ const TabStripModelChange& change,
+ const TabStripSelectionChange& selection) override;
// content::NotificationObserver implementation.
void Observe(int type,
diff --git a/chromium/chrome/browser/extensions/api/web_navigation/web_navigation_apitest.cc b/chromium/chrome/browser/extensions/api/web_navigation/web_navigation_apitest.cc
index 45bae3a8d76..06d2a2591bf 100644
--- a/chromium/chrome/browser/extensions/api/web_navigation/web_navigation_apitest.cc
+++ b/chromium/chrome/browser/extensions/api/web_navigation/web_navigation_apitest.cc
@@ -218,9 +218,16 @@ IN_PROC_BROWSER_TEST_F(WebNavigationApiTest, Api) {
ASSERT_TRUE(RunExtensionTest("webnavigation/api")) << message_;
}
-IN_PROC_BROWSER_TEST_F(WebNavigationApiTest, GetFrame) {
+// Flaky on Windows. See http://crbug.com/874782
+#if defined(OS_WIN)
+#define MAYBE_GetFrame DISABLED_GetFrame
+#else
+#define MAYBE_GetFrame GetFrame
+#endif
+IN_PROC_BROWSER_TEST_F(WebNavigationApiTest, MAYBE_GetFrame) {
ASSERT_TRUE(RunExtensionTest("webnavigation/getFrame")) << message_;
}
+#undef MAYBE_GetFrame
IN_PROC_BROWSER_TEST_F(WebNavigationApiTest, ClientRedirect) {
ASSERT_TRUE(RunExtensionTest("webnavigation/clientRedirect"))
@@ -246,9 +253,18 @@ IN_PROC_BROWSER_TEST_F(WebNavigationApiTest, Download) {
}
IN_PROC_BROWSER_TEST_F(WebNavigationApiTest, ServerRedirectSingleProcess) {
- // TODO(lukasza): https://crbug.com/671734: Investigate why this test fails
- // with --site-per-process.
- if (content::AreAllSitesIsolatedForTesting())
+ // TODO(lukasza): https://crbug.com/671734: In the long-term, //chrome-layer
+ // tests should only be run with site-per-process - remove the early return
+ // below when fixing https://crbug.com/870761 and removing the
+ // not_site_per_process_browser_tests step.
+ //
+ // This test has its expectations in
+ // serverRedirectSingleProcess/test_serverRedirectSingleProcess.js. The
+ // expectations include exact |processId| ("exact" meaning that one cannot use
+ // a wildcard - the verification is done via chrome.test.checkDeepEq).
+ // Inclusion of |processId| means that the expectation change in
+ // site-per-process mode.
+ if (!content::AreAllSitesIsolatedForTesting())
return;
ASSERT_TRUE(StartEmbeddedTestServer());
@@ -346,7 +362,16 @@ IN_PROC_BROWSER_TEST_F(WebNavigationApiTest, MAYBE_UserAction) {
GURL url = extension->GetResourceURL(
"a.html?" + base::IntToString(embedded_test_server()->port()));
+ // Register an observer for the navigation in the subframe, so the test
+ // can wait until it is fully complete. Otherwise the context menu
+ // navigation is non-deterministic on which process it will get associated
+ // with, leading to test flakiness.
+ content::TestNavigationManager nav_manager(
+ tab, embedded_test_server()->GetURL(
+ "/extensions/api_test/webnavigation/userAction/subframe.html"));
ui_test_utils::NavigateToURL(browser(), url);
+ nav_manager.WaitForNavigationFinished();
+ EXPECT_TRUE(nav_manager.was_successful());
// This corresponds to "Open link in new tab".
content::ContextMenuParams params;
diff --git a/chromium/chrome/browser/extensions/api/web_request/chrome_extension_web_request_event_router_delegate.cc b/chromium/chrome/browser/extensions/api/web_request/chrome_extension_web_request_event_router_delegate.cc
index 547d704e804..f9b9e4ac4cb 100644
--- a/chromium/chrome/browser/extensions/api/web_request/chrome_extension_web_request_event_router_delegate.cc
+++ b/chromium/chrome/browser/extensions/api/web_request/chrome_extension_web_request_event_router_delegate.cc
@@ -43,6 +43,21 @@ void NotifyWebRequestWithheldOnUI(int render_process_id,
if (!extension)
return;
+ // If the extension doesn't request access to the tab, return. The user
+ // invoking the extension on a site grants access to the tab's origin if
+ // and only if the extension requested it; without requesting the tab,
+ // clicking on the extension won't grant access to the resource.
+ // https://crbug.com/891586.
+ // TODO(https://157736): We can remove this if extensions require host
+ // permissions to the initiator, since then we'll never get into this type
+ // of circumstance (the request would be blocked, rather than withheld).
+ if (!extension->permissions_data()
+ ->withheld_permissions()
+ .explicit_hosts()
+ .MatchesURL(rfh->GetLastCommittedURL())) {
+ return;
+ }
+
runner->OnWebRequestBlocked(extension);
}
diff --git a/chromium/chrome/browser/extensions/api/web_request/web_request_api_unittest.cc b/chromium/chrome/browser/extensions/api/web_request/web_request_api_unittest.cc
index ec0e9ea2710..566f1087400 100644
--- a/chromium/chrome/browser/extensions/api/web_request/web_request_api_unittest.cc
+++ b/chromium/chrome/browser/extensions/api/web_request/web_request_api_unittest.cc
@@ -46,7 +46,6 @@
#include "extensions/browser/api/web_request/web_request_api.h"
#include "extensions/browser/api/web_request/web_request_api_constants.h"
#include "extensions/browser/api/web_request/web_request_api_helpers.h"
-#include "extensions/browser/warning_set.h"
#include "extensions/common/api/web_request.h"
#include "extensions/common/extension_messages.h"
#include "extensions/common/features/feature.h"
@@ -116,12 +115,14 @@ static void EventHandledOnIOThread(
}
// Returns whether |warnings| contains an extension for |extension_id|.
-bool HasWarning(const WarningSet& warnings,
- const std::string& extension_id) {
- for (WarningSet::const_iterator i = warnings.begin();
- i != warnings.end(); ++i) {
- if (i->extension_id() == extension_id)
+bool HasIgnoredAction(const helpers::IgnoredActions& ignored_actions,
+ const std::string& extension_id,
+ web_request::IgnoredActionType action_type) {
+ for (const auto& ignored_action : ignored_actions) {
+ if (ignored_action.extension_id == extension_id &&
+ ignored_action.action_type == action_type) {
return true;
+ }
}
return false;
}
@@ -228,8 +229,6 @@ class ExtensionWebRequestTest : public testing::Test {
protected:
void SetUp() override {
ASSERT_TRUE(profile_manager_.SetUp());
- ChromeNetworkDelegate::InitializePrefsOnUIThread(
- nullptr, nullptr, nullptr, profile_.GetTestingPrefService());
network_delegate_.reset(new ChromeNetworkDelegate(event_router_.get()));
network_delegate_->set_profile(&profile_);
network_delegate_->set_cookie_settings(
@@ -1121,8 +1120,6 @@ class ExtensionWebRequestHeaderModificationTest
protected:
void SetUp() override {
ASSERT_TRUE(profile_manager_.SetUp());
- ChromeNetworkDelegate::InitializePrefsOnUIThread(
- nullptr, nullptr, nullptr, profile_.GetTestingPrefService());
network_delegate_.reset(new ChromeNetworkDelegate(event_router_.get()));
network_delegate_->set_profile(&profile_);
network_delegate_->set_cookie_settings(
@@ -1543,14 +1540,14 @@ TEST(ExtensionWebRequestHelpersTest, TestCalculateOnBeforeSendHeadersDelta) {
const bool cancel = true;
std::string value;
net::HttpRequestHeaders old_headers;
- old_headers.AddHeadersFromString("key1: value1\r\n"
- "key2: value2\r\n");
+ old_headers.SetHeader("key1", "value1");
+ old_headers.SetHeader("key2", "value2");
// Test adding a header.
net::HttpRequestHeaders new_headers_added;
- new_headers_added.AddHeadersFromString("key1: value1\r\n"
- "key3: value3\r\n"
- "key2: value2\r\n");
+ new_headers_added.SetHeader("key1", "value1");
+ new_headers_added.SetHeader("key3", "value3");
+ new_headers_added.SetHeader("key2", "value2");
std::unique_ptr<EventResponseDelta> delta_added(
CalculateOnBeforeSendHeadersDelta("extid", base::Time::Now(), cancel,
&old_headers, &new_headers_added));
@@ -1561,7 +1558,7 @@ TEST(ExtensionWebRequestHelpersTest, TestCalculateOnBeforeSendHeadersDelta) {
// Test deleting a header.
net::HttpRequestHeaders new_headers_deleted;
- new_headers_deleted.AddHeadersFromString("key1: value1\r\n");
+ new_headers_deleted.SetHeader("key1", "value1");
std::unique_ptr<EventResponseDelta> delta_deleted(
CalculateOnBeforeSendHeadersDelta("extid", base::Time::Now(), cancel,
&old_headers, &new_headers_deleted));
@@ -1571,8 +1568,8 @@ TEST(ExtensionWebRequestHelpersTest, TestCalculateOnBeforeSendHeadersDelta) {
// Test modifying a header.
net::HttpRequestHeaders new_headers_modified;
- new_headers_modified.AddHeadersFromString("key1: value1\r\n"
- "key2: value3\r\n");
+ new_headers_modified.SetHeader("key1", "value1");
+ new_headers_modified.SetHeader("key2", "value3");
std::unique_ptr<EventResponseDelta> delta_modified(
CalculateOnBeforeSendHeadersDelta("extid", base::Time::Now(), cancel,
&old_headers, &new_headers_modified));
@@ -1586,9 +1583,9 @@ TEST(ExtensionWebRequestHelpersTest, TestCalculateOnBeforeSendHeadersDelta) {
// value) pair with a key that existed before. This is incorrect
// usage of the API that shall be handled gracefully.
net::HttpRequestHeaders new_headers_modified2;
- new_headers_modified2.AddHeadersFromString("key1: value1\r\n"
- "key2: value2\r\n"
- "key2: value3\r\n");
+ new_headers_modified2.SetHeader("key1", "value1");
+ new_headers_modified2.SetHeader("key2", "value2");
+ new_headers_modified2.SetHeader("key2", "value3");
std::unique_ptr<EventResponseDelta> delta_modified2(
CalculateOnBeforeSendHeadersDelta("extid", base::Time::Now(), cancel,
&old_headers, &new_headers_modified));
@@ -1712,7 +1709,7 @@ TEST(ExtensionWebRequestHelpersTest, TestMergeCancelOfResponses) {
TEST(ExtensionWebRequestHelpersTest, TestMergeOnBeforeRequestResponses) {
EventResponseDeltas deltas;
TestLogger logger;
- WarningSet warning_set;
+ helpers::IgnoredActions ignored_actions;
GURL effective_new_url;
// No redirect
@@ -1720,7 +1717,7 @@ TEST(ExtensionWebRequestHelpersTest, TestMergeOnBeforeRequestResponses) {
new EventResponseDelta("extid0", base::Time::FromInternalValue(0)));
deltas.push_back(d0);
MergeOnBeforeRequestResponses(GURL(kExampleUrl), deltas, &effective_new_url,
- &warning_set, &logger);
+ &ignored_actions, &logger);
EXPECT_TRUE(effective_new_url.is_empty());
// Single redirect.
@@ -1732,9 +1729,9 @@ TEST(ExtensionWebRequestHelpersTest, TestMergeOnBeforeRequestResponses) {
deltas.sort(&InDecreasingExtensionInstallationTimeOrder);
logger.clear();
MergeOnBeforeRequestResponses(GURL(kExampleUrl), deltas, &effective_new_url,
- &warning_set, &logger);
+ &ignored_actions, &logger);
EXPECT_EQ(new_url_1, effective_new_url);
- EXPECT_TRUE(warning_set.empty());
+ EXPECT_TRUE(ignored_actions.empty());
EXPECT_EQ(1u, logger.log_size());
// Ignored redirect (due to precedence).
@@ -1744,13 +1741,14 @@ TEST(ExtensionWebRequestHelpersTest, TestMergeOnBeforeRequestResponses) {
d2->new_url = GURL(new_url_2);
deltas.push_back(d2);
deltas.sort(&InDecreasingExtensionInstallationTimeOrder);
- warning_set.clear();
+ ignored_actions.clear();
logger.clear();
MergeOnBeforeRequestResponses(GURL(kExampleUrl), deltas, &effective_new_url,
- &warning_set, &logger);
+ &ignored_actions, &logger);
EXPECT_EQ(new_url_1, effective_new_url);
- EXPECT_EQ(1u, warning_set.size());
- EXPECT_TRUE(HasWarning(warning_set, "extid2"));
+ EXPECT_EQ(1u, ignored_actions.size());
+ EXPECT_TRUE(HasIgnoredAction(ignored_actions, "extid2",
+ web_request::IGNORED_ACTION_TYPE_REDIRECT));
EXPECT_EQ(2u, logger.log_size());
// Overriding redirect.
@@ -1760,14 +1758,16 @@ TEST(ExtensionWebRequestHelpersTest, TestMergeOnBeforeRequestResponses) {
d3->new_url = GURL(new_url_3);
deltas.push_back(d3);
deltas.sort(&InDecreasingExtensionInstallationTimeOrder);
- warning_set.clear();
+ ignored_actions.clear();
logger.clear();
MergeOnBeforeRequestResponses(GURL(kExampleUrl), deltas, &effective_new_url,
- &warning_set, &logger);
+ &ignored_actions, &logger);
EXPECT_EQ(new_url_3, effective_new_url);
- EXPECT_EQ(2u, warning_set.size());
- EXPECT_TRUE(HasWarning(warning_set, "extid1"));
- EXPECT_TRUE(HasWarning(warning_set, "extid2"));
+ EXPECT_EQ(2u, ignored_actions.size());
+ EXPECT_TRUE(HasIgnoredAction(ignored_actions, "extid1",
+ web_request::IGNORED_ACTION_TYPE_REDIRECT));
+ EXPECT_TRUE(HasIgnoredAction(ignored_actions, "extid2",
+ web_request::IGNORED_ACTION_TYPE_REDIRECT));
EXPECT_EQ(3u, logger.log_size());
// Check that identical redirects don't cause a conflict.
@@ -1776,14 +1776,16 @@ TEST(ExtensionWebRequestHelpersTest, TestMergeOnBeforeRequestResponses) {
d4->new_url = GURL(new_url_3);
deltas.push_back(d4);
deltas.sort(&InDecreasingExtensionInstallationTimeOrder);
- warning_set.clear();
+ ignored_actions.clear();
logger.clear();
MergeOnBeforeRequestResponses(GURL(kExampleUrl), deltas, &effective_new_url,
- &warning_set, &logger);
+ &ignored_actions, &logger);
EXPECT_EQ(new_url_3, effective_new_url);
- EXPECT_EQ(2u, warning_set.size());
- EXPECT_TRUE(HasWarning(warning_set, "extid1"));
- EXPECT_TRUE(HasWarning(warning_set, "extid2"));
+ EXPECT_EQ(2u, ignored_actions.size());
+ EXPECT_TRUE(HasIgnoredAction(ignored_actions, "extid1",
+ web_request::IGNORED_ACTION_TYPE_REDIRECT));
+ EXPECT_TRUE(HasIgnoredAction(ignored_actions, "extid2",
+ web_request::IGNORED_ACTION_TYPE_REDIRECT));
EXPECT_EQ(4u, logger.log_size());
}
@@ -1792,7 +1794,7 @@ TEST(ExtensionWebRequestHelpersTest, TestMergeOnBeforeRequestResponses) {
TEST(ExtensionWebRequestHelpersTest, TestMergeOnBeforeRequestResponses2) {
EventResponseDeltas deltas;
TestLogger logger;
- WarningSet warning_set;
+ helpers::IgnoredActions ignored_actions;
GURL effective_new_url;
// Single redirect.
@@ -1802,7 +1804,7 @@ TEST(ExtensionWebRequestHelpersTest, TestMergeOnBeforeRequestResponses2) {
d0->new_url = GURL(new_url_0);
deltas.push_back(d0);
MergeOnBeforeRequestResponses(GURL(kExampleUrl), deltas, &effective_new_url,
- &warning_set, &logger);
+ &ignored_actions, &logger);
EXPECT_EQ(new_url_0, effective_new_url);
// Cancel request by redirecting to a data:// URL. This shall override
@@ -1813,12 +1815,12 @@ TEST(ExtensionWebRequestHelpersTest, TestMergeOnBeforeRequestResponses2) {
d1->new_url = GURL(new_url_1);
deltas.push_back(d1);
deltas.sort(&InDecreasingExtensionInstallationTimeOrder);
- warning_set.clear();
+ ignored_actions.clear();
logger.clear();
MergeOnBeforeRequestResponses(GURL(kExampleUrl), deltas, &effective_new_url,
- &warning_set, &logger);
+ &ignored_actions, &logger);
EXPECT_EQ(new_url_1, effective_new_url);
- EXPECT_TRUE(warning_set.empty());
+ EXPECT_TRUE(ignored_actions.empty());
EXPECT_EQ(1u, logger.log_size());
// Cancel request by redirecting to the same data:// URL. This shall
@@ -1829,13 +1831,13 @@ TEST(ExtensionWebRequestHelpersTest, TestMergeOnBeforeRequestResponses2) {
d2->new_url = GURL(new_url_2);
deltas.push_back(d2);
deltas.sort(&InDecreasingExtensionInstallationTimeOrder);
- warning_set.clear();
+ ignored_actions.clear();
logger.clear();
MergeOnBeforeRequestResponses(GURL(kExampleUrl), deltas, &effective_new_url,
- &warning_set, &logger);
+ &ignored_actions, &logger);
EXPECT_EQ(new_url_1, effective_new_url);
- EXPECT_TRUE(warning_set.empty());
+ EXPECT_TRUE(ignored_actions.empty());
EXPECT_EQ(2u, logger.log_size());
// Cancel redirect by redirecting to a different data:// URL. This needs
@@ -1846,13 +1848,14 @@ TEST(ExtensionWebRequestHelpersTest, TestMergeOnBeforeRequestResponses2) {
d3->new_url = GURL(new_url_3);
deltas.push_back(d3);
deltas.sort(&InDecreasingExtensionInstallationTimeOrder);
- warning_set.clear();
+ ignored_actions.clear();
logger.clear();
MergeOnBeforeRequestResponses(GURL(kExampleUrl), deltas, &effective_new_url,
- &warning_set, &logger);
+ &ignored_actions, &logger);
EXPECT_EQ(new_url_1, effective_new_url);
- EXPECT_EQ(1u, warning_set.size());
- EXPECT_TRUE(HasWarning(warning_set, "extid3"));
+ EXPECT_EQ(1u, ignored_actions.size());
+ EXPECT_TRUE(HasIgnoredAction(ignored_actions, "extid3",
+ web_request::IGNORED_ACTION_TYPE_REDIRECT));
EXPECT_EQ(3u, logger.log_size());
}
@@ -1861,7 +1864,7 @@ TEST(ExtensionWebRequestHelpersTest, TestMergeOnBeforeRequestResponses2) {
TEST(ExtensionWebRequestHelpersTest, TestMergeOnBeforeRequestResponses3) {
EventResponseDeltas deltas;
TestLogger logger;
- WarningSet warning_set;
+ helpers::IgnoredActions ignored_actions;
GURL effective_new_url;
// Single redirect.
@@ -1871,7 +1874,7 @@ TEST(ExtensionWebRequestHelpersTest, TestMergeOnBeforeRequestResponses3) {
d0->new_url = GURL(new_url_0);
deltas.push_back(d0);
MergeOnBeforeRequestResponses(GURL(kExampleUrl), deltas, &effective_new_url,
- &warning_set, &logger);
+ &ignored_actions, &logger);
EXPECT_EQ(new_url_0, effective_new_url);
// Cancel request by redirecting to about:blank. This shall override
@@ -1882,12 +1885,12 @@ TEST(ExtensionWebRequestHelpersTest, TestMergeOnBeforeRequestResponses3) {
d1->new_url = GURL(new_url_1);
deltas.push_back(d1);
deltas.sort(&InDecreasingExtensionInstallationTimeOrder);
- warning_set.clear();
+ ignored_actions.clear();
logger.clear();
MergeOnBeforeRequestResponses(GURL(kExampleUrl), deltas, &effective_new_url,
- &warning_set, &logger);
+ &ignored_actions, &logger);
EXPECT_EQ(new_url_1, effective_new_url);
- EXPECT_TRUE(warning_set.empty());
+ EXPECT_TRUE(ignored_actions.empty());
EXPECT_EQ(1u, logger.log_size());
}
@@ -1895,7 +1898,7 @@ TEST(ExtensionWebRequestHelpersTest, TestMergeOnBeforeRequestResponses3) {
TEST(ExtensionWebRequestHelpersTest, TestMergeOnBeforeRequestResponses4) {
EventResponseDeltas deltas;
TestLogger logger;
- WarningSet warning_set;
+ helpers::IgnoredActions ignored_actions;
GURL effective_new_url;
// Single redirect.
@@ -1904,7 +1907,7 @@ TEST(ExtensionWebRequestHelpersTest, TestMergeOnBeforeRequestResponses4) {
delta->new_url = GURL("http://foo.com");
deltas.push_back(delta);
MergeOnBeforeRequestResponses(GURL("ws://example.com"), deltas,
- &effective_new_url, &warning_set, &logger);
+ &effective_new_url, &ignored_actions, &logger);
EXPECT_EQ(GURL(), effective_new_url);
}
@@ -1913,7 +1916,7 @@ TEST(ExtensionWebRequestHelpersTest, TestMergeOnBeforeSendHeadersResponses) {
base_headers.SetHeader("key1", "value 1");
base_headers.SetHeader("key2", "value 2");
TestLogger logger;
- WarningSet warning_set;
+ helpers::IgnoredActions ignored_actions;
std::string header_value;
EventResponseDeltas deltas;
@@ -1924,13 +1927,13 @@ TEST(ExtensionWebRequestHelpersTest, TestMergeOnBeforeSendHeadersResponses) {
bool request_headers_modified0;
net::HttpRequestHeaders headers0;
headers0.MergeFrom(base_headers);
- MergeOnBeforeSendHeadersResponses(GURL(), deltas, &headers0, &warning_set,
+ MergeOnBeforeSendHeadersResponses(GURL(), deltas, &headers0, &ignored_actions,
&logger, &request_headers_modified0);
ASSERT_TRUE(headers0.GetHeader("key1", &header_value));
EXPECT_EQ("value 1", header_value);
ASSERT_TRUE(headers0.GetHeader("key2", &header_value));
EXPECT_EQ("value 2", header_value);
- EXPECT_EQ(0u, warning_set.size());
+ EXPECT_EQ(0u, ignored_actions.size());
EXPECT_EQ(0u, logger.log_size());
EXPECT_FALSE(request_headers_modified0);
@@ -1942,19 +1945,19 @@ TEST(ExtensionWebRequestHelpersTest, TestMergeOnBeforeSendHeadersResponses) {
d1->modified_request_headers.SetHeader("key3", "value 3");
deltas.push_back(d1);
deltas.sort(&InDecreasingExtensionInstallationTimeOrder);
- warning_set.clear();
+ ignored_actions.clear();
logger.clear();
bool request_headers_modified1;
net::HttpRequestHeaders headers1;
headers1.MergeFrom(base_headers);
- MergeOnBeforeSendHeadersResponses(GURL(), deltas, &headers1, &warning_set,
+ MergeOnBeforeSendHeadersResponses(GURL(), deltas, &headers1, &ignored_actions,
&logger, &request_headers_modified1);
EXPECT_FALSE(headers1.HasHeader("key1"));
ASSERT_TRUE(headers1.GetHeader("key2", &header_value));
EXPECT_EQ("value 3", header_value);
ASSERT_TRUE(headers1.GetHeader("key3", &header_value));
EXPECT_EQ("value 3", header_value);
- EXPECT_EQ(0u, warning_set.size());
+ EXPECT_EQ(0u, ignored_actions.size());
EXPECT_EQ(1u, logger.log_size());
EXPECT_TRUE(request_headers_modified1);
@@ -1967,12 +1970,12 @@ TEST(ExtensionWebRequestHelpersTest, TestMergeOnBeforeSendHeadersResponses) {
d2->modified_request_headers.SetHeader("key4", "value 4");
deltas.push_back(d2);
deltas.sort(&InDecreasingExtensionInstallationTimeOrder);
- warning_set.clear();
+ ignored_actions.clear();
logger.clear();
bool request_headers_modified2;
net::HttpRequestHeaders headers2;
headers2.MergeFrom(base_headers);
- MergeOnBeforeSendHeadersResponses(GURL(), deltas, &headers2, &warning_set,
+ MergeOnBeforeSendHeadersResponses(GURL(), deltas, &headers2, &ignored_actions,
&logger, &request_headers_modified2);
EXPECT_FALSE(headers2.HasHeader("key1"));
ASSERT_TRUE(headers2.GetHeader("key2", &header_value));
@@ -1980,8 +1983,10 @@ TEST(ExtensionWebRequestHelpersTest, TestMergeOnBeforeSendHeadersResponses) {
ASSERT_TRUE(headers2.GetHeader("key3", &header_value));
EXPECT_EQ("value 3", header_value);
EXPECT_FALSE(headers2.HasHeader("key4"));
- EXPECT_EQ(1u, warning_set.size());
- EXPECT_TRUE(HasWarning(warning_set, "extid2"));
+ EXPECT_EQ(1u, ignored_actions.size());
+ EXPECT_TRUE(
+ HasIgnoredAction(ignored_actions, "extid2",
+ web_request::IGNORED_ACTION_TYPE_REQUEST_HEADERS));
EXPECT_EQ(2u, logger.log_size());
EXPECT_TRUE(request_headers_modified2);
@@ -1994,12 +1999,12 @@ TEST(ExtensionWebRequestHelpersTest, TestMergeOnBeforeSendHeadersResponses) {
d3->modified_request_headers.SetHeader("key5", "value 5");
deltas.push_back(d3);
deltas.sort(&InDecreasingExtensionInstallationTimeOrder);
- warning_set.clear();
+ ignored_actions.clear();
logger.clear();
bool request_headers_modified3;
net::HttpRequestHeaders headers3;
headers3.MergeFrom(base_headers);
- MergeOnBeforeSendHeadersResponses(GURL(), deltas, &headers3, &warning_set,
+ MergeOnBeforeSendHeadersResponses(GURL(), deltas, &headers3, &ignored_actions,
&logger, &request_headers_modified3);
EXPECT_FALSE(headers3.HasHeader("key1"));
ASSERT_TRUE(headers3.GetHeader("key2", &header_value));
@@ -2008,8 +2013,10 @@ TEST(ExtensionWebRequestHelpersTest, TestMergeOnBeforeSendHeadersResponses) {
EXPECT_EQ("value 3", header_value);
ASSERT_TRUE(headers3.GetHeader("key5", &header_value));
EXPECT_EQ("value 5", header_value);
- EXPECT_EQ(1u, warning_set.size());
- EXPECT_TRUE(HasWarning(warning_set, "extid2"));
+ EXPECT_EQ(1u, ignored_actions.size());
+ EXPECT_TRUE(
+ HasIgnoredAction(ignored_actions, "extid2",
+ web_request::IGNORED_ACTION_TYPE_REQUEST_HEADERS));
EXPECT_EQ(3u, logger.log_size());
EXPECT_TRUE(request_headers_modified3);
}
@@ -2017,10 +2024,10 @@ TEST(ExtensionWebRequestHelpersTest, TestMergeOnBeforeSendHeadersResponses) {
TEST(ExtensionWebRequestHelpersTest,
TestMergeOnBeforeSendHeadersResponses_Cookies) {
net::HttpRequestHeaders base_headers;
- base_headers.AddHeaderFromString(
- "Cookie: name=value; name2=value2; name3=\"value3\"");
+ base_headers.SetHeader("Cookie",
+ "name=value; name2=value2; name3=\"value3\"");
TestLogger logger;
- WarningSet warning_set;
+ helpers::IgnoredActions ignored_actions;
std::string header_value;
EventResponseDeltas deltas;
@@ -2066,13 +2073,13 @@ TEST(ExtensionWebRequestHelpersTest,
bool request_headers_modified1;
net::HttpRequestHeaders headers1;
headers1.MergeFrom(base_headers);
- warning_set.clear();
- MergeOnBeforeSendHeadersResponses(GURL(), deltas, &headers1, &warning_set,
+ ignored_actions.clear();
+ MergeOnBeforeSendHeadersResponses(GURL(), deltas, &headers1, &ignored_actions,
&logger, &request_headers_modified1);
EXPECT_TRUE(headers1.HasHeader("Cookie"));
ASSERT_TRUE(headers1.GetHeader("Cookie", &header_value));
EXPECT_EQ("name=new value; name2=new value; name4=\"value 4\"", header_value);
- EXPECT_EQ(0u, warning_set.size());
+ EXPECT_EQ(0u, ignored_actions.size());
EXPECT_EQ(0u, logger.log_size());
EXPECT_FALSE(request_headers_modified1);
}
@@ -2106,7 +2113,6 @@ std::string GetCookieExpirationDate(int delta_secs) {
TEST(ExtensionWebRequestHelpersTest,
TestMergeCookiesInOnHeadersReceivedResponses) {
TestLogger logger;
- WarningSet warning_set;
std::string header_value;
EventResponseDeltas deltas;
@@ -2140,10 +2146,9 @@ TEST(ExtensionWebRequestHelpersTest,
new EventResponseDelta("extid0", base::Time::FromInternalValue(3000)));
deltas.push_back(d0);
scoped_refptr<net::HttpResponseHeaders> new_headers0;
- MergeCookiesInOnHeadersReceivedResponses(
- GURL(), deltas, base_headers.get(), &new_headers0, &warning_set, &logger);
+ MergeCookiesInOnHeadersReceivedResponses(GURL(), deltas, base_headers.get(),
+ &new_headers0, &logger);
EXPECT_FALSE(new_headers0.get());
- EXPECT_EQ(0u, warning_set.size());
EXPECT_EQ(0u, logger.log_size());
linked_ptr<ResponseCookieModification> add_cookie =
@@ -2308,9 +2313,8 @@ TEST(ExtensionWebRequestHelpersTest,
net::HttpUtil::AssembleRawHeaders(
base_headers_string.c_str(), base_headers_string.size())));
scoped_refptr<net::HttpResponseHeaders> new_headers1;
- warning_set.clear();
- MergeCookiesInOnHeadersReceivedResponses(
- GURL(), deltas, headers1.get(), &new_headers1, &warning_set, &logger);
+ MergeCookiesInOnHeadersReceivedResponses(GURL(), deltas, headers1.get(),
+ &new_headers1, &logger);
EXPECT_TRUE(new_headers1->HasHeader("Foo"));
size_t iter = 0;
@@ -2334,13 +2338,12 @@ TEST(ExtensionWebRequestHelpersTest,
while (new_headers1->EnumerateHeader(&iter, "Set-Cookie", &cookie_string))
actual_cookies.insert(cookie_string);
EXPECT_EQ(expected_cookies, actual_cookies);
- EXPECT_EQ(0u, warning_set.size());
EXPECT_EQ(0u, logger.log_size());
}
TEST(ExtensionWebRequestHelpersTest, TestMergeOnHeadersReceivedResponses) {
TestLogger logger;
- WarningSet warning_set;
+ helpers::IgnoredActions ignored_actions;
std::string header_value;
EventResponseDeltas deltas;
@@ -2363,11 +2366,11 @@ TEST(ExtensionWebRequestHelpersTest, TestMergeOnHeadersReceivedResponses) {
GURL allowed_unsafe_redirect_url0;
MergeOnHeadersReceivedResponses(GURL(kExampleUrl), deltas, base_headers.get(),
&new_headers0, &allowed_unsafe_redirect_url0,
- &warning_set, &logger,
+ &ignored_actions, &logger,
&response_headers_modified0);
EXPECT_FALSE(new_headers0.get());
EXPECT_TRUE(allowed_unsafe_redirect_url0.is_empty());
- EXPECT_EQ(0u, warning_set.size());
+ EXPECT_EQ(0u, ignored_actions.size());
EXPECT_EQ(0u, logger.log_size());
EXPECT_FALSE(response_headers_modified0);
@@ -2378,14 +2381,14 @@ TEST(ExtensionWebRequestHelpersTest, TestMergeOnHeadersReceivedResponses) {
d1->added_response_headers.push_back(ResponseHeader("Key2", "Value3"));
deltas.push_back(d1);
deltas.sort(&InDecreasingExtensionInstallationTimeOrder);
- warning_set.clear();
+ ignored_actions.clear();
logger.clear();
bool response_headers_modified1;
scoped_refptr<net::HttpResponseHeaders> new_headers1;
GURL allowed_unsafe_redirect_url1;
MergeOnHeadersReceivedResponses(GURL(kExampleUrl), deltas, base_headers.get(),
&new_headers1, &allowed_unsafe_redirect_url1,
- &warning_set, &logger,
+ &ignored_actions, &logger,
&response_headers_modified1);
ASSERT_TRUE(new_headers1.get());
EXPECT_TRUE(allowed_unsafe_redirect_url1.is_empty());
@@ -2399,7 +2402,7 @@ TEST(ExtensionWebRequestHelpersTest, TestMergeOnHeadersReceivedResponses) {
actual1.insert(std::pair<std::string, std::string>(name, value));
}
EXPECT_EQ(expected1, actual1);
- EXPECT_EQ(0u, warning_set.size());
+ EXPECT_EQ(0u, ignored_actions.size());
EXPECT_EQ(1u, logger.log_size());
EXPECT_TRUE(response_headers_modified1);
@@ -2412,14 +2415,14 @@ TEST(ExtensionWebRequestHelpersTest, TestMergeOnHeadersReceivedResponses) {
d2->added_response_headers.push_back(ResponseHeader("Key2", "Value4"));
deltas.push_back(d2);
deltas.sort(&InDecreasingExtensionInstallationTimeOrder);
- warning_set.clear();
+ ignored_actions.clear();
logger.clear();
bool response_headers_modified2;
scoped_refptr<net::HttpResponseHeaders> new_headers2;
GURL allowed_unsafe_redirect_url2;
MergeOnHeadersReceivedResponses(GURL(kExampleUrl), deltas, base_headers.get(),
&new_headers2, &allowed_unsafe_redirect_url2,
- &warning_set, &logger,
+ &ignored_actions, &logger,
&response_headers_modified2);
ASSERT_TRUE(new_headers2.get());
EXPECT_TRUE(allowed_unsafe_redirect_url2.is_empty());
@@ -2429,8 +2432,10 @@ TEST(ExtensionWebRequestHelpersTest, TestMergeOnHeadersReceivedResponses) {
actual2.insert(std::pair<std::string, std::string>(name, value));
}
EXPECT_EQ(expected1, actual2);
- EXPECT_EQ(1u, warning_set.size());
- EXPECT_TRUE(HasWarning(warning_set, "extid2"));
+ EXPECT_EQ(1u, ignored_actions.size());
+ EXPECT_TRUE(
+ HasIgnoredAction(ignored_actions, "extid2",
+ web_request::IGNORED_ACTION_TYPE_RESPONSE_HEADERS));
EXPECT_EQ(2u, logger.log_size());
EXPECT_TRUE(response_headers_modified2);
}
@@ -2439,7 +2444,7 @@ TEST(ExtensionWebRequestHelpersTest, TestMergeOnHeadersReceivedResponses) {
TEST(ExtensionWebRequestHelpersTest,
TestMergeOnHeadersReceivedResponsesDeletion) {
TestLogger logger;
- WarningSet warning_set;
+ helpers::IgnoredActions ignored_actions;
std::string header_value;
EventResponseDeltas deltas;
@@ -2464,7 +2469,7 @@ TEST(ExtensionWebRequestHelpersTest,
GURL allowed_unsafe_redirect_url1;
MergeOnHeadersReceivedResponses(GURL(kExampleUrl), deltas, base_headers.get(),
&new_headers1, &allowed_unsafe_redirect_url1,
- &warning_set, &logger,
+ &ignored_actions, &logger,
&response_headers_modified1);
ASSERT_TRUE(new_headers1.get());
EXPECT_TRUE(allowed_unsafe_redirect_url1.is_empty());
@@ -2480,7 +2485,7 @@ TEST(ExtensionWebRequestHelpersTest,
actual1.insert(std::pair<std::string, std::string>(name, value));
}
EXPECT_EQ(expected1, actual1);
- EXPECT_EQ(0u, warning_set.size());
+ EXPECT_EQ(0u, ignored_actions.size());
EXPECT_EQ(1u, logger.log_size());
EXPECT_TRUE(response_headers_modified1);
}
@@ -2492,7 +2497,7 @@ TEST(ExtensionWebRequestHelpersTest,
TestMergeOnHeadersReceivedResponsesRedirect) {
EventResponseDeltas deltas;
TestLogger logger;
- WarningSet warning_set;
+ helpers::IgnoredActions ignored_actions;
char base_headers_string[] =
"HTTP/1.0 200 OK\r\n"
@@ -2510,11 +2515,11 @@ TEST(ExtensionWebRequestHelpersTest,
GURL allowed_unsafe_redirect_url0;
MergeOnHeadersReceivedResponses(GURL(kExampleUrl), deltas, base_headers.get(),
&new_headers0, &allowed_unsafe_redirect_url0,
- &warning_set, &logger,
+ &ignored_actions, &logger,
&response_headers_modified0);
EXPECT_FALSE(new_headers0.get());
EXPECT_TRUE(allowed_unsafe_redirect_url0.is_empty());
- EXPECT_EQ(0u, warning_set.size());
+ EXPECT_EQ(0u, ignored_actions.size());
EXPECT_EQ(0u, logger.log_size());
EXPECT_FALSE(response_headers_modified0);
@@ -2532,20 +2537,20 @@ TEST(ExtensionWebRequestHelpersTest,
GURL allowed_unsafe_redirect_url1;
MergeOnHeadersReceivedResponses(GURL(kExampleUrl), deltas, base_headers.get(),
&new_headers1, &allowed_unsafe_redirect_url1,
- &warning_set, &logger,
+ &ignored_actions, &logger,
&response_headers_modified1);
EXPECT_TRUE(new_headers1.get());
EXPECT_TRUE(new_headers1->HasHeaderValue("Location", new_url_1.spec()));
EXPECT_EQ(new_url_1, allowed_unsafe_redirect_url1);
- EXPECT_TRUE(warning_set.empty());
+ EXPECT_TRUE(ignored_actions.empty());
EXPECT_EQ(1u, logger.log_size());
EXPECT_FALSE(response_headers_modified1);
}
TEST(ExtensionWebRequestHelpersTest, TestMergeOnAuthRequiredResponses) {
TestLogger logger;
- WarningSet warning_set;
+ helpers::IgnoredActions ignored_actions;
EventResponseDeltas deltas;
base::string16 username = base::ASCIIToUTF16("foo");
base::string16 password = base::ASCIIToUTF16("bar");
@@ -2557,10 +2562,10 @@ TEST(ExtensionWebRequestHelpersTest, TestMergeOnAuthRequiredResponses) {
deltas.push_back(d0);
net::AuthCredentials auth0;
bool credentials_set =
- MergeOnAuthRequiredResponses(deltas, &auth0, &warning_set, &logger);
+ MergeOnAuthRequiredResponses(deltas, &auth0, &ignored_actions, &logger);
EXPECT_FALSE(credentials_set);
EXPECT_TRUE(auth0.Empty());
- EXPECT_EQ(0u, warning_set.size());
+ EXPECT_EQ(0u, ignored_actions.size());
EXPECT_EQ(0u, logger.log_size());
// Check that we can set AuthCredentials.
@@ -2569,16 +2574,16 @@ TEST(ExtensionWebRequestHelpersTest, TestMergeOnAuthRequiredResponses) {
d1->auth_credentials.reset(new net::AuthCredentials(username, password));
deltas.push_back(d1);
deltas.sort(&InDecreasingExtensionInstallationTimeOrder);
- warning_set.clear();
+ ignored_actions.clear();
logger.clear();
net::AuthCredentials auth1;
credentials_set =
- MergeOnAuthRequiredResponses(deltas, &auth1, &warning_set, &logger);
+ MergeOnAuthRequiredResponses(deltas, &auth1, &ignored_actions, &logger);
EXPECT_TRUE(credentials_set);
EXPECT_FALSE(auth1.Empty());
EXPECT_EQ(username, auth1.username());
EXPECT_EQ(password, auth1.password());
- EXPECT_EQ(0u, warning_set.size());
+ EXPECT_EQ(0u, ignored_actions.size());
EXPECT_EQ(1u, logger.log_size());
// Check that we set AuthCredentials only once.
@@ -2587,17 +2592,19 @@ TEST(ExtensionWebRequestHelpersTest, TestMergeOnAuthRequiredResponses) {
d2->auth_credentials.reset(new net::AuthCredentials(username, password2));
deltas.push_back(d2);
deltas.sort(&InDecreasingExtensionInstallationTimeOrder);
- warning_set.clear();
+ ignored_actions.clear();
logger.clear();
net::AuthCredentials auth2;
credentials_set =
- MergeOnAuthRequiredResponses(deltas, &auth2, &warning_set, &logger);
+ MergeOnAuthRequiredResponses(deltas, &auth2, &ignored_actions, &logger);
EXPECT_TRUE(credentials_set);
EXPECT_FALSE(auth2.Empty());
EXPECT_EQ(username, auth1.username());
EXPECT_EQ(password, auth1.password());
- EXPECT_EQ(1u, warning_set.size());
- EXPECT_TRUE(HasWarning(warning_set, "extid2"));
+ EXPECT_EQ(1u, ignored_actions.size());
+ EXPECT_TRUE(
+ HasIgnoredAction(ignored_actions, "extid2",
+ web_request::IGNORED_ACTION_TYPE_AUTH_CREDENTIALS));
EXPECT_EQ(2u, logger.log_size());
// Check that we can set identical AuthCredentials twice without causing
@@ -2607,17 +2614,19 @@ TEST(ExtensionWebRequestHelpersTest, TestMergeOnAuthRequiredResponses) {
d3->auth_credentials.reset(new net::AuthCredentials(username, password));
deltas.push_back(d3);
deltas.sort(&InDecreasingExtensionInstallationTimeOrder);
- warning_set.clear();
+ ignored_actions.clear();
logger.clear();
net::AuthCredentials auth3;
credentials_set =
- MergeOnAuthRequiredResponses(deltas, &auth3, &warning_set, &logger);
+ MergeOnAuthRequiredResponses(deltas, &auth3, &ignored_actions, &logger);
EXPECT_TRUE(credentials_set);
EXPECT_FALSE(auth3.Empty());
EXPECT_EQ(username, auth1.username());
EXPECT_EQ(password, auth1.password());
- EXPECT_EQ(1u, warning_set.size());
- EXPECT_TRUE(HasWarning(warning_set, "extid2"));
+ EXPECT_EQ(1u, ignored_actions.size());
+ EXPECT_TRUE(
+ HasIgnoredAction(ignored_actions, "extid2",
+ web_request::IGNORED_ACTION_TYPE_AUTH_CREDENTIALS));
EXPECT_EQ(3u, logger.log_size());
}
diff --git a/chromium/chrome/browser/extensions/api/web_request/web_request_apitest.cc b/chromium/chrome/browser/extensions/api/web_request/web_request_apitest.cc
index 3b61cddcfb3..34dab4c0c64 100644
--- a/chromium/chrome/browser/extensions/api/web_request/web_request_apitest.cc
+++ b/chromium/chrome/browser/extensions/api/web_request/web_request_apitest.cc
@@ -15,12 +15,15 @@
#include "base/synchronization/lock.h"
#include "base/test/bind_test_util.h"
#include "base/test/scoped_feature_list.h"
+#include "base/time/time.h"
+#include "base/time/time_override.h"
#include "base/values.h"
#include "build/build_config.h"
#include "chrome/browser/browser_process.h"
#include "chrome/browser/chrome_notification_types.h"
#include "chrome/browser/devtools/url_constants.h"
#include "chrome/browser/extensions/active_tab_permission_granter.h"
+#include "chrome/browser/extensions/api/extension_action/test_extension_action_api_observer.h"
#include "chrome/browser/extensions/extension_action_runner.h"
#include "chrome/browser/extensions/extension_apitest.h"
#include "chrome/browser/extensions/extension_service.h"
@@ -31,6 +34,8 @@
#include "chrome/browser/net/profile_network_context_service_factory.h"
#include "chrome/browser/net/system_network_context_manager.h"
#include "chrome/browser/profiles/profile.h"
+#include "chrome/browser/profiles/profile_destroyer.h"
+#include "chrome/browser/profiles/profile_manager.h"
#include "chrome/browser/search/one_google_bar/one_google_bar_loader.h"
#include "chrome/browser/search/one_google_bar/one_google_bar_service.h"
#include "chrome/browser/search/one_google_bar/one_google_bar_service_factory.h"
@@ -47,7 +52,7 @@
#include "chrome/test/base/search_test_utils.h"
#include "chrome/test/base/ui_test_utils.h"
#include "chromeos/login/scoped_test_public_session_login_state.h"
-#include "components/google/core/browser/google_switches.h"
+#include "components/google/core/common/google_switches.h"
#include "components/prefs/pref_service.h"
#include "components/proxy_config/proxy_config_dictionary.h"
#include "components/proxy_config/proxy_config_pref_names.h"
@@ -58,6 +63,7 @@
#include "content/public/browser/notification_registrar.h"
#include "content/public/browser/notification_service.h"
#include "content/public/browser/render_frame_host.h"
+#include "content/public/browser/render_process_host.h"
#include "content/public/browser/render_view_host.h"
#include "content/public/browser/render_widget_host.h"
#include "content/public/browser/storage_partition.h"
@@ -68,6 +74,7 @@
#include "content/public/test/url_loader_interceptor.h"
#include "extensions/browser/api/web_request/web_request_api.h"
#include "extensions/browser/blocked_action_type.h"
+#include "extensions/browser/extension_prefs.h"
#include "extensions/browser/extension_system.h"
#include "extensions/common/extension_builder.h"
#include "extensions/common/extension_features.h"
@@ -89,6 +96,7 @@
#include "services/network/public/cpp/features.h"
#include "services/network/public/cpp/resource_request.h"
#include "services/network/public/cpp/simple_url_loader.h"
+#include "services/network/test/test_url_loader_client.h"
#include "third_party/blink/public/platform/web_input_event.h"
#if defined(OS_CHROMEOS)
@@ -268,16 +276,36 @@ class ExtensionWebRequestApiTest : public ExtensionApiTest {
const char* expected_content_regular_window,
const char* exptected_content_incognito_window);
- // TODO(https://crbug.com/857577): remove this hack. When an unrelated
- // browser issued request (typically from GaiaAuthFetcher) has run, it causes
- // the StoragePartitionImpl to create and cache a URLLoaderFactory without the
- // web request proxying. This resets it so one with the web request proxying
- // is created the next time a request is made.
- void ResetStoragePartitionURLLoaderFactory() {
- base::RunLoop().RunUntilIdle();
+ network::mojom::URLLoaderFactoryPtr CreateURLLoaderFactory() {
+ network::mojom::URLLoaderFactoryParamsPtr params =
+ network::mojom::URLLoaderFactoryParams::New();
+ params->process_id = network::mojom::kBrowserProcessId;
+ params->is_corb_enabled = false;
+ network::mojom::URLLoaderFactoryPtr loader_factory;
content::BrowserContext::GetDefaultStoragePartition(profile())
- ->ResetURLLoaderFactoryForBrowserProcessForTesting();
+ ->GetNetworkContext()
+ ->CreateURLLoaderFactory(mojo::MakeRequest(&loader_factory),
+ std::move(params));
+ return loader_factory;
}
+
+ void InstallWebRequestExtension(const std::string& name) {
+ constexpr char kManifest[] = R"({
+ "name": "%s",
+ "version": "1",
+ "manifest_version": 2,
+ "permissions": [
+ "webRequest"
+ ]
+ })";
+ auto dir = std::make_unique<TestExtensionDir>();
+ dir->WriteManifest(base::StringPrintf(kManifest, name.c_str()));
+ LoadExtension(dir->UnpackedPath());
+ test_dirs_.push_back(std::move(dir));
+ }
+
+ private:
+ std::vector<std::unique_ptr<TestExtensionDir>> test_dirs_;
};
class DevToolsFrontendInWebRequestApiTest : public ExtensionApiTest {
@@ -493,8 +521,53 @@ IN_PROC_BROWSER_TEST_F(ExtensionWebRequestApiTest,
#endif
IN_PROC_BROWSER_TEST_F(ExtensionWebRequestApiTest, MAYBE_WebRequestBlocking) {
ASSERT_TRUE(StartEmbeddedTestServer());
- ASSERT_TRUE(RunExtensionSubtest("webrequest", "test_blocking.html")) <<
- message_;
+ ASSERT_TRUE(RunExtensionSubtest("webrequest", "test_blocking.html"))
+ << message_;
+}
+
+IN_PROC_BROWSER_TEST_F(ExtensionWebRequestApiTest,
+ WebRequestBlockingSetCookieHeader) {
+ ASSERT_TRUE(StartEmbeddedTestServer());
+ ASSERT_TRUE(RunExtensionSubtest("webrequest", "test_blocking_cookie.html"))
+ << message_;
+}
+
+IN_PROC_BROWSER_TEST_F(ExtensionWebRequestApiTest, WebRequestRedirects) {
+ ASSERT_TRUE(StartEmbeddedTestServer());
+ ASSERT_TRUE(RunExtensionSubtest("webrequest", "test_redirects.html"))
+ << message_;
+}
+
+// Tests that redirects from secure to insecure don't send the referrer header.
+IN_PROC_BROWSER_TEST_F(ExtensionWebRequestApiTest,
+ WebRequestRedirectsToInsecure) {
+ ASSERT_TRUE(StartEmbeddedTestServer());
+ GURL insecure_destination =
+ embedded_test_server()->GetURL("/extensions/test_file.html");
+ net::EmbeddedTestServer https_test_server(
+ net::EmbeddedTestServer::TYPE_HTTPS);
+ https_test_server.ServeFilesFromDirectory(test_data_dir_);
+ ASSERT_TRUE(https_test_server.Start());
+
+ GURL url = https_test_server.GetURL("/webrequest/simulate_click.html");
+
+ base::ListValue custom_args;
+ custom_args.AppendString(url.spec());
+ custom_args.AppendString(insecure_destination.spec());
+
+ std::string config_string;
+ base::JSONWriter::Write(custom_args, &config_string);
+ ASSERT_TRUE(RunExtensionSubtestWithArg(
+ "webrequest", "test_redirects_from_secure.html", config_string.c_str()))
+ << message_;
+}
+
+IN_PROC_BROWSER_TEST_F(ExtensionWebRequestApiTest,
+ WebRequestSubresourceRedirects) {
+ ASSERT_TRUE(StartEmbeddedTestServer());
+ ASSERT_TRUE(
+ RunExtensionSubtest("webrequest", "test_subresource_redirects.html"))
+ << message_;
}
// Fails often on Windows dbg bots. http://crbug.com/177163
@@ -555,7 +628,12 @@ IN_PROC_BROWSER_TEST_F(ExtensionWebRequestApiTest,
IN_PROC_BROWSER_TEST_F(ExtensionWebRequestApiTest,
MAYBE_WebRequestDeclarative2) {
ASSERT_TRUE(StartEmbeddedTestServer());
- ASSERT_TRUE(RunExtensionSubtest("webrequest", "test_declarative2.html"))
+ const char* network_service_arg =
+ base::FeatureList::IsEnabled(network::features::kNetworkService)
+ ? "NetworkServiceEnabled"
+ : "NetworkServiceDisabled";
+ ASSERT_TRUE(RunExtensionSubtestWithArg("webrequest", "test_declarative2.html",
+ network_service_arg))
<< message_;
}
@@ -897,14 +975,22 @@ IN_PROC_BROWSER_TEST_F(ExtensionWebRequestApiTest,
// frames, this shouldn't show up as a blocked action.
EXPECT_EQ(BLOCKED_ACTION_NONE, runner->GetBlockedActions(extension));
- // If we revoke the extension's tab permissions, it should no longer receive
- // webRequest events.
+ // Revoke the extension's tab permissions.
ActiveTabPermissionGranter* granter =
TabHelper::FromWebContents(web_contents)->active_tab_permission_granter();
ASSERT_TRUE(granter);
granter->RevokeForTesting();
base::RunLoop().RunUntilIdle();
+
+ // The extension should no longer receive webRequest events since they are
+ // withheld. The extension icon should get updated to show the wants-to-run
+ // badge UI.
+ TestExtensionActionAPIObserver action_updated_waiter(profile(),
+ extension->id());
PerformXhrInFrame(main_frame, kHost, port, kXhrPath);
+ action_updated_waiter.Wait();
+ EXPECT_EQ(web_contents, action_updated_waiter.last_web_contents());
+
EXPECT_EQ(xhr_count,
GetWebRequestCountFromBackgroundPage(extension, profile()));
EXPECT_EQ(BLOCKED_ACTION_WEB_REQUEST, runner->GetBlockedActions(extension));
@@ -963,6 +1049,75 @@ IN_PROC_BROWSER_TEST_F(ExtensionWebRequestApiTest,
HasSeenWebRequestInBackgroundPage(extension, profile(), kCrossSiteHost));
}
+// Tests behavior when an extension has withheld access to a request's URL, but
+// not the initiator's (tab's) URL. Regression test for
+// https://crbug.com/891586.
+IN_PROC_BROWSER_TEST_F(ExtensionWebRequestApiTest,
+ WithheldHostPermissionsForCrossOriginWithoutInitiator) {
+ base::test::ScopedFeatureList scoped_feature_list;
+ scoped_feature_list.InitAndEnableFeature(
+ extensions::features::kRuntimeHostPermissions);
+
+ content::SetupCrossSiteRedirector(embedded_test_server());
+ ASSERT_TRUE(embedded_test_server()->Start());
+
+ // TODO(devlin): This is essentially copied from the webrequest_activetab
+ // API test extension, but has different permissions. Maybe it's worth having
+ // all tests use a common pattern?
+ TestExtensionDir test_dir;
+ test_dir.WriteManifest(
+ R"({
+ "name": "Web Request Withheld Hosts",
+ "manifest_version": 2,
+ "version": "0.1",
+ "background": { "scripts": ["background.js"] },
+ "permissions": ["*://b.com:*/*", "webRequest"]
+ })");
+ test_dir.WriteFile(FILE_PATH_LITERAL("background.js"),
+ R"(window.webRequestCount = 0;
+ window.requestedHostnames = [];
+
+ chrome.webRequest.onBeforeRequest.addListener(function(details) {
+ ++window.webRequestCount;
+ window.requestedHostnames.push((new URL(details.url)).hostname);
+ }, {urls:['<all_urls>']});
+ chrome.test.sendMessage('ready');)");
+
+ // Load an extension that registers a listener for webRequest events, and
+ // wait until it's initialized.
+ ExtensionTestMessageListener listener("ready", false);
+ const Extension* extension = LoadExtension(test_dir.UnpackedPath());
+ ASSERT_TRUE(extension) << message_;
+ ScriptingPermissionsModifier(profile(), base::WrapRefCounted(extension))
+ .SetWithholdHostPermissions(true);
+ EXPECT_TRUE(listener.WaitUntilSatisfied());
+
+ // Navigate to example.com, which has a cross-site script to b.com.
+ ui_test_utils::NavigateToURL(
+ browser(), embedded_test_server()->GetURL(
+ "example.com", "/extensions/cross_site_script.html"));
+
+ content::WebContents* web_contents =
+ browser()->tab_strip_model()->GetActiveWebContents();
+
+ ExtensionActionRunner* runner =
+ ExtensionActionRunner::GetForWebContents(web_contents);
+ ASSERT_TRUE(runner);
+
+ // Even though the extension has access to b.com, it shouldn't show that it
+ // wants to run, because example.com is not a requested host.
+ EXPECT_EQ(BLOCKED_ACTION_NONE, runner->GetBlockedActions(extension));
+ EXPECT_FALSE(
+ HasSeenWebRequestInBackgroundPage(extension, profile(), "b.com"));
+
+ // Navigating to b.com (so that the script is hosted on the same origin as
+ // the WebContents) should show the extension wants to run.
+ ui_test_utils::NavigateToURL(
+ browser(), embedded_test_server()->GetURL(
+ "b.com", "/extensions/cross_site_script.html"));
+ EXPECT_EQ(BLOCKED_ACTION_WEB_REQUEST, runner->GetBlockedActions(extension));
+}
+
// Verify that requests to clientsX.google.com are protected properly.
// First test requests from a standard renderer and then a request from the
// browser process.
@@ -1039,9 +1194,6 @@ IN_PROC_BROWSER_TEST_F(ExtensionWebRequestApiTest,
EXPECT_EQ(200, loader->ResponseInfo()->headers->response_code());
};
- // TODO(https://crbug.com/857577): remove this call.
- ResetStoragePartitionURLLoaderFactory();
-
// Now perform a request to "client1.google.com" from the browser process.
// This should *not* be visible to the WebRequest API. We should still have
// only seen the single render-initiated request from the first half of the
@@ -1075,7 +1227,7 @@ IN_PROC_BROWSER_TEST_F(ExtensionWebRequestApiTest,
// affecting requests.
PrefService* pref_service = browser()->profile()->GetPrefs();
pref_service->Set(proxy_config::prefs::kProxy,
- *ProxyConfigDictionary::CreatePacScript(
+ ProxyConfigDictionary::CreatePacScript(
embedded_test_server()->GetURL("/self.pac").spec(),
true /* pac_mandatory */));
// Flush the proxy configuration change over the Mojo pipe to avoid any races.
@@ -1238,6 +1390,33 @@ IN_PROC_BROWSER_TEST_F(ExtensionWebRequestApiTest, WebSocketRequestOnWorker) {
<< message_;
}
+// Tests the WebRequestProxyingWebSocket does not crash when there is a
+// connection error before AddChannelRequest is called. Regression test for
+// http://crbug.com/878574.
+IN_PROC_BROWSER_TEST_F(ExtensionWebRequestApiTest,
+ WebSocketConnectionErrorBeforeChannelRequest) {
+ if (!base::FeatureList::IsEnabled(network::features::kNetworkService))
+ return;
+
+ InstallWebRequestExtension("extension");
+
+ network::mojom::WebSocketPtr web_socket;
+ network::mojom::WebSocketRequest request = mojo::MakeRequest(&web_socket);
+ network::mojom::AuthenticationHandlerPtr auth_handler;
+ content::RenderFrameHost* host =
+ browser()->tab_strip_model()->GetActiveWebContents()->GetMainFrame();
+ extensions::BrowserContextKeyedAPIFactory<extensions::WebRequestAPI>::Get(
+ profile())
+ ->MaybeProxyWebSocket(host, &request, &auth_handler);
+ content::BrowserContext::GetDefaultStoragePartition(profile())
+ ->GetNetworkContext()
+ ->CreateWebSocket(std::move(request), network::mojom::kBrowserProcessId,
+ host->GetProcess()->GetID(),
+ url::Origin::Create(GURL("http://example.com")),
+ std::move(auth_handler));
+ web_socket.reset();
+}
+
// Test behavior when intercepting requests from a browser-initiated url fetch.
IN_PROC_BROWSER_TEST_F(ExtensionWebRequestApiTest,
WebRequestURLLoaderInterception) {
@@ -1362,9 +1541,6 @@ IN_PROC_BROWSER_TEST_F(ExtensionWebRequestApiTest,
}
};
- // TODO(https://crbug.com/857577): remove this call.
- ResetStoragePartitionURLLoaderFactory();
-
// Next, try a series of requests through URLRequestFetchers (rather than a
// renderer).
auto* url_loader_factory =
@@ -1452,6 +1628,80 @@ IN_PROC_BROWSER_TEST_F(ExtensionWebRequestApiTest, MinimumAccessInitiator) {
}
}
+IN_PROC_BROWSER_TEST_F(ExtensionWebRequestApiTest,
+ WebRequestApiClearsBindingOnFirstListener) {
+ if (!base::FeatureList::IsEnabled(network::features::kNetworkService))
+ return;
+
+ auto loader_factory = CreateURLLoaderFactory();
+ bool has_connection_error = false;
+ loader_factory.set_connection_error_handler(
+ base::BindLambdaForTesting([&]() { has_connection_error = true; }));
+
+ InstallWebRequestExtension("extension1");
+ content::BrowserContext::GetDefaultStoragePartition(profile())
+ ->FlushNetworkInterfaceForTesting();
+ EXPECT_TRUE(has_connection_error);
+
+ // The second time there should be no connection error.
+ loader_factory = CreateURLLoaderFactory();
+ has_connection_error = false;
+ loader_factory.set_connection_error_handler(
+ base::BindLambdaForTesting([&]() { has_connection_error = true; }));
+ InstallWebRequestExtension("extension2");
+ content::BrowserContext::GetDefaultStoragePartition(profile())
+ ->FlushNetworkInterfaceForTesting();
+ EXPECT_FALSE(has_connection_error);
+}
+
+// Regression test for http://crbug.com/878366.
+IN_PROC_BROWSER_TEST_F(ExtensionWebRequestApiTest,
+ WebRequestApiDoesNotCrashOnErrorAfterProfileDestroyed) {
+ if (!base::FeatureList::IsEnabled(network::features::kNetworkService))
+ return;
+
+ ASSERT_TRUE(StartEmbeddedTestServer());
+
+ // Create a profile that will be destroyed later.
+ base::ScopedAllowBlockingForTesting allow_blocking;
+ ProfileManager* profile_manager = g_browser_process->profile_manager();
+ Profile* tmp_profile = Profile::CreateProfile(
+ profile_manager->user_data_dir().AppendASCII("profile"), nullptr,
+ Profile::CreateMode::CREATE_MODE_SYNCHRONOUS);
+
+ // Create a WebRequestAPI instance that we can control the lifetime of.
+ auto api = std::make_unique<WebRequestAPI>(tmp_profile);
+ // Make sure we are proxying for |tmp_profile|.
+ api->ForceProxyForTesting();
+ content::BrowserContext::GetDefaultStoragePartition(tmp_profile)
+ ->FlushNetworkInterfaceForTesting();
+
+ network::mojom::URLLoaderFactoryPtr factory;
+ auto request = mojo::MakeRequest(&factory);
+ EXPECT_TRUE(api->MaybeProxyURLLoaderFactory(nullptr, false, &request));
+ auto params = network::mojom::URLLoaderFactoryParams::New();
+ params->process_id = 0;
+ content::BrowserContext::GetDefaultStoragePartition(tmp_profile)
+ ->GetNetworkContext()
+ ->CreateURLLoaderFactory(std::move(request), std::move(params));
+
+ network::TestURLLoaderClient client;
+ network::mojom::URLLoaderPtr loader;
+ network::ResourceRequest resource_request;
+ resource_request.url = embedded_test_server()->GetURL("/hung");
+ factory->CreateLoaderAndStart(
+ mojo::MakeRequest(&loader), 0, 0, network::mojom::kURLLoadOptionNone,
+ resource_request, client.CreateInterfacePtr(),
+ net::MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS));
+
+ // Destroy profile, unbind client to cause a connection error, and delete the
+ // WebRequestAPI. This will cause the connection error that will reach the
+ // proxy before the ProxySet shutdown code runs on the IO thread.
+ ProfileDestroyer::DestroyProfileWhenAppropriate(tmp_profile);
+ client.Unbind();
+ api.reset();
+}
+
// Test fixture which sets a custom NTP Page.
class NTPInterceptionWebRequestAPITest : public ExtensionApiTest {
public:
@@ -1491,6 +1741,9 @@ IN_PROC_BROWSER_TEST_F(NTPInterceptionWebRequestAPITest,
LoadExtension(test_data_dir_.AppendASCII("extension"));
ASSERT_TRUE(extension);
EXPECT_TRUE(listener.WaitUntilSatisfied());
+ // Wait for webRequest listeners to be set up.
+ content::BrowserContext::GetDefaultStoragePartition(profile())
+ ->FlushNetworkInterfaceForTesting();
// Have the extension listen for requests to |fake_ntp_script.js|.
listener.Reply(https_test_server()->GetURL("/fake_ntp_script.js").spec());
@@ -1552,9 +1805,7 @@ class LocalNTPInterceptionWebRequestAPITest
base::Unretained(this)));
ASSERT_TRUE(https_test_server_.InitializeAndListen());
ExtensionApiTest::SetUp();
- feature_list_.InitWithFeatures(
- {::features::kUseGoogleLocalNtp, ::features::kOneGoogleBarOnLocalNtp},
- {});
+ feature_list_.InitWithFeatures({::features::kUseGoogleLocalNtp}, {});
}
void SetUpCommandLine(base::CommandLine* command_line) override {
ExtensionApiTest::SetUpCommandLine(command_line);
@@ -1891,4 +2142,110 @@ IN_PROC_BROWSER_TEST_F(ExtensionApiTestWithManagementPolicy,
EXPECT_EQ(0, GetWebRequestCountFromBackgroundPage(extension, profile()));
}
+// A test fixture which mocks the Time::Now() function to ensure that the
+// default clock returns monotonically increasing time.
+class ExtensionWebRequestMockedClockTest : public ExtensionWebRequestApiTest {
+ public:
+ ExtensionWebRequestMockedClockTest()
+ : scoped_time_clock_override_(&ExtensionWebRequestMockedClockTest::Now,
+ nullptr,
+ nullptr) {}
+
+ private:
+ static base::Time Now() {
+ static base::Time now_time = base::Time::UnixEpoch();
+ now_time += base::TimeDelta::FromMilliseconds(1);
+ return now_time;
+ }
+
+ base::subtle::ScopedTimeClockOverrides scoped_time_clock_override_;
+ DISALLOW_COPY_AND_ASSIGN(ExtensionWebRequestMockedClockTest);
+};
+
+// Tests that we correctly dispatch the OnActionIgnored event on an extension
+// if the extension's proposed redirect is ignored.
+IN_PROC_BROWSER_TEST_F(ExtensionWebRequestMockedClockTest,
+ OnActionIgnored_Redirect) {
+ ASSERT_TRUE(StartEmbeddedTestServer());
+
+ // Load the two extensions. They redirect "google.com" main-frame urls to
+ // the corresponding "example.com and "foo.com" urls.
+ base::FilePath test_dir =
+ test_data_dir_.AppendASCII("webrequest/on_action_ignored");
+
+ // Load the first extension.
+ ExtensionTestMessageListener ready_1_listener("ready_1",
+ false /*will_reply*/);
+ const Extension* extension_1 =
+ LoadExtension(test_dir.AppendASCII("extension_1"));
+ ASSERT_TRUE(extension_1);
+ ASSERT_TRUE(ready_1_listener.WaitUntilSatisfied());
+ const std::string extension_id_1 = extension_1->id();
+
+ // Load the second extension.
+ ExtensionTestMessageListener ready_2_listener("ready_2",
+ false /*will_reply*/);
+ const Extension* extension_2 =
+ LoadExtension(test_dir.AppendASCII("extension_2"));
+ ASSERT_TRUE(extension_2);
+ ASSERT_TRUE(ready_2_listener.WaitUntilSatisfied());
+ const std::string extension_id_2 = extension_2->id();
+
+ const ExtensionPrefs* prefs = ExtensionPrefs::Get(profile());
+ EXPECT_LT(prefs->GetInstallTime(extension_id_1),
+ prefs->GetInstallTime(extension_id_2));
+
+ // The extensions will notify the browser if their proposed redirect was
+ // successful or not.
+ ExtensionTestMessageListener redirect_ignored_listener("redirect_ignored",
+ false /*will_reply*/);
+ ExtensionTestMessageListener redirect_successful_listener(
+ "redirect_successful", false /*will_reply*/);
+
+ const GURL url = embedded_test_server()->GetURL("google.com", "/simple.html");
+ const GURL expected_redirect_url_1 =
+ embedded_test_server()->GetURL("example.com", "/simple.html");
+ const GURL expected_redirect_url_2 =
+ embedded_test_server()->GetURL("foo.com", "/simple.html");
+
+ ui_test_utils::NavigateToURL(browser(), url);
+
+ content::WebContents* web_contents =
+ browser()->tab_strip_model()->GetActiveWebContents();
+ ASSERT_TRUE(web_contents);
+
+ // The second extension is the latest installed, hence it's redirect url
+ // should take precedence.
+ EXPECT_EQ(expected_redirect_url_2, web_contents->GetLastCommittedURL());
+ EXPECT_TRUE(redirect_ignored_listener.WaitUntilSatisfied());
+ EXPECT_EQ(extension_id_1,
+ redirect_ignored_listener.extension_id_for_message());
+ EXPECT_TRUE(redirect_successful_listener.WaitUntilSatisfied());
+ EXPECT_EQ(extension_id_2,
+ redirect_successful_listener.extension_id_for_message());
+
+ // Now let |extension_1| be installed after |extension_2|. For an unpacked
+ // extension, reloading is equivalent to a reinstall.
+ ready_1_listener.Reset();
+ ReloadExtension(extension_id_1);
+ ASSERT_TRUE(ready_1_listener.WaitUntilSatisfied());
+
+ EXPECT_LT(prefs->GetInstallTime(extension_id_2),
+ prefs->GetInstallTime(extension_id_1));
+
+ redirect_ignored_listener.Reset();
+ redirect_successful_listener.Reset();
+ ui_test_utils::NavigateToURL(browser(), url);
+
+ // The first extension is the latest installed, hence it's redirect url
+ // should take precedence.
+ EXPECT_EQ(expected_redirect_url_1, web_contents->GetLastCommittedURL());
+ EXPECT_TRUE(redirect_ignored_listener.WaitUntilSatisfied());
+ EXPECT_EQ(extension_id_2,
+ redirect_ignored_listener.extension_id_for_message());
+ EXPECT_TRUE(redirect_successful_listener.WaitUntilSatisfied());
+ EXPECT_EQ(extension_id_1,
+ redirect_successful_listener.extension_id_for_message());
+}
+
} // namespace extensions
diff --git a/chromium/chrome/browser/extensions/api/webrtc_logging_private/webrtc_logging_private_api.cc b/chromium/chrome/browser/extensions/api/webrtc_logging_private/webrtc_logging_private_api.cc
index 0bb5252379c..64673d94b64 100644
--- a/chromium/chrome/browser/extensions/api/webrtc_logging_private/webrtc_logging_private_api.cc
+++ b/chromium/chrome/browser/extensions/api/webrtc_logging_private/webrtc_logging_private_api.cc
@@ -578,7 +578,7 @@ bool WebrtcLoggingPrivateStartEventLoggingFunction::RunAsync() {
BrowserThread::UI, FROM_HERE,
base::BindOnce(&WebRtcLoggingHandlerHost::StartEventLogging,
webrtc_logging_handler_host, params->peer_connection_id,
- params->max_log_size_bytes, callback));
+ params->max_log_size_bytes, params->web_app_id, callback));
return true;
}
diff --git a/chromium/chrome/browser/extensions/api/webrtc_logging_private/webrtc_logging_private_apitest.cc b/chromium/chrome/browser/extensions/api/webrtc_logging_private/webrtc_logging_private_apitest.cc
index 086ddfa4c0a..ec714ee3042 100644
--- a/chromium/chrome/browser/extensions/api/webrtc_logging_private/webrtc_logging_private_apitest.cc
+++ b/chromium/chrome/browser/extensions/api/webrtc_logging_private/webrtc_logging_private_apitest.cc
@@ -13,19 +13,23 @@
#include "base/strings/stringprintf.h"
#include "base/test/scoped_command_line.h"
#include "base/test/scoped_feature_list.h"
+#include "build/build_config.h"
#include "chrome/browser/browser_process.h"
#include "chrome/browser/extensions/api/webrtc_logging_private/webrtc_logging_private_api.h"
#include "chrome/browser/extensions/extension_apitest.h"
#include "chrome/browser/extensions/extension_function_test_utils.h"
#include "chrome/browser/extensions/extension_tab_util.h"
+#include "chrome/browser/media/webrtc/webrtc_event_log_manager.h"
#include "chrome/browser/media/webrtc/webrtc_event_log_manager_common.h"
#include "chrome/browser/media/webrtc/webrtc_log_uploader.h"
#include "chrome/browser/ui/tabs/tab_strip_model.h"
#include "chrome/common/chrome_features.h"
#include "chrome/common/chrome_switches.h"
+#include "components/policy/core/browser/browser_policy_connector.h"
+#include "components/policy/core/common/mock_configuration_policy_provider.h"
+#include "components/policy/policy_constants.h"
#include "content/public/browser/notification_service.h"
#include "content/public/browser/render_view_host.h"
-#include "content/public/browser/webrtc_event_logger.h"
#include "content/public/test/test_utils.h"
#include "extensions/common/extension_builder.h"
#include "third_party/zlib/google/compression_utils.h"
@@ -34,16 +38,26 @@ using compression::GzipUncompress;
using extensions::Extension;
using extensions::WebrtcLoggingPrivateDiscardFunction;
using extensions::WebrtcLoggingPrivateSetMetaDataFunction;
+using extensions::WebrtcLoggingPrivateStartAudioDebugRecordingsFunction;
+using extensions::WebrtcLoggingPrivateStartEventLoggingFunction;
using extensions::WebrtcLoggingPrivateStartFunction;
using extensions::WebrtcLoggingPrivateStartRtpDumpFunction;
+using extensions::WebrtcLoggingPrivateStopAudioDebugRecordingsFunction;
using extensions::WebrtcLoggingPrivateStopFunction;
using extensions::WebrtcLoggingPrivateStopRtpDumpFunction;
using extensions::WebrtcLoggingPrivateStoreFunction;
using extensions::WebrtcLoggingPrivateUploadFunction;
using extensions::WebrtcLoggingPrivateUploadStoredFunction;
-using extensions::WebrtcLoggingPrivateStartAudioDebugRecordingsFunction;
-using extensions::WebrtcLoggingPrivateStopAudioDebugRecordingsFunction;
-using extensions::WebrtcLoggingPrivateStartEventLoggingFunction;
+using webrtc_event_logging::kMaxRemoteLogFileSizeBytes;
+using webrtc_event_logging::kStartRemoteLoggingFailureAlreadyLogging;
+using webrtc_event_logging::kStartRemoteLoggingFailureFeatureDisabled;
+using webrtc_event_logging::kStartRemoteLoggingFailureMaxSizeTooLarge;
+using webrtc_event_logging::kStartRemoteLoggingFailureMaxSizeTooSmall;
+using webrtc_event_logging::
+ kStartRemoteLoggingFailureUnknownOrInactivePeerConnection;
+using webrtc_event_logging::kStartRemoteLoggingFailureUnlimitedSizeDisallowed;
+using webrtc_event_logging::kWebRtcEventLogManagerUnlimitedFileSize;
+using webrtc_event_logging::WebRtcEventLogManager;
namespace utils = extension_function_test_utils;
@@ -53,6 +67,8 @@ static const char kTestLoggingSessionIdKey[] = "app_session_id";
static const char kTestLoggingSessionIdValue[] = "0123456789abcdef";
static const char kTestLoggingUrl[] = "dummy url string";
+constexpr int kWebAppId = 15; // Arbitrary.
+
std::string ParamsToString(const base::ListValue& parameters) {
std::string parameter_string;
EXPECT_TRUE(base::JSONWriter::Write(parameters, &parameter_string));
@@ -76,7 +92,6 @@ void InitializeTestMetaData(base::ListValue* parameters) {
class WebrtcLoggingPrivateApiTest : public extensions::ExtensionApiTest {
protected:
void SetUp() override {
- scoped_feature_list_.InitAndEnableFeature(features::kWebRtcRemoteEventLog);
extensions::ExtensionApiTest::SetUp();
extension_ = extensions::ExtensionBuilder("Test").Build();
}
@@ -310,6 +325,7 @@ class WebrtcLoggingPrivateApiTest : public extensions::ExtensionApiTest {
// TODO(crbug.com/829419): Return success/failure of the executed function.
void StartEventLogging(const std::string& peerConnectionId,
int maxLogSizeBytes,
+ int webAppId,
bool expect_success,
const std::string& expected_error = std::string()) {
DCHECK_EQ(expect_success, expected_error.empty());
@@ -318,6 +334,7 @@ class WebrtcLoggingPrivateApiTest : public extensions::ExtensionApiTest {
AppendTabIdAndUrl(&params);
params.AppendString(peerConnectionId);
params.AppendInteger(maxLogSizeBytes);
+ params.AppendInteger(webAppId);
if (expect_success) {
scoped_refptr<WebrtcLoggingPrivateStartEventLoggingFunction> function(
@@ -346,7 +363,7 @@ class WebrtcLoggingPrivateApiTest : public extensions::ExtensionApiTest {
}
void SetUpPeerConnection(const std::string& peer_connection_id) {
- auto* manager = content::WebRtcEventLogger::Get();
+ auto* manager = WebRtcEventLogManager::GetInstance();
auto* rph = web_contents()->GetRenderViewHost()->GetProcess();
const int render_process_id = rph->GetID();
@@ -361,30 +378,6 @@ class WebrtcLoggingPrivateApiTest : public extensions::ExtensionApiTest {
scoped_refptr<Extension> extension_;
};
-class WebrtcLoggingPrivateApiTestDisabledRemoteLogging
- : public WebrtcLoggingPrivateApiTest {
- protected:
- void SetUp() override {
- scoped_feature_list_.InitAndDisableFeature(features::kWebRtcRemoteEventLog);
- extensions::ExtensionApiTest::SetUp();
- extension_ = extensions::ExtensionBuilder("Test").Build();
- }
-};
-
-class WebrtcLoggingPrivateApiTestInIncognitoMode
- : public WebrtcLoggingPrivateApiTest {
- protected:
- Browser* GetBrowser() override {
- if (!browser_) {
- browser_ = CreateIncognitoBrowser();
- }
- return browser_;
- }
-
- private:
- Browser* browser_{nullptr}; // Does not own the object.
-};
-
// Helper class to temporarily tell the uploader to save the multipart buffer to
// a test string instead of uploading.
class ScopedOverrideUploadBuffer {
@@ -644,52 +637,143 @@ IN_PROC_BROWSER_TEST_F(WebrtcLoggingPrivateApiTest,
ASSERT_TRUE(StartAudioDebugRecordings(1));
}
-IN_PROC_BROWSER_TEST_F(WebrtcLoggingPrivateApiTest,
- StartEventLoggingForKnownPeerConnectionSucceeds) {
+#if !defined(OS_ANDROID)
+
+// Fixture for various tests over StartEventLogging. Intended to be sub-classed
+// to test different scenarios.
+class WebrtcLoggingPrivateApiStartEventLoggingTestBase
+ : public WebrtcLoggingPrivateApiTest {
+ public:
+ ~WebrtcLoggingPrivateApiStartEventLoggingTestBase() override = default;
+
+ protected:
+ void SetUp() override {
+ SetUpFeatures();
+ WebrtcLoggingPrivateApiTest::SetUp();
+ }
+
+ void SetUpFeatures() {
+ std::vector<base::Feature> enabled;
+ std::vector<base::Feature> disabled;
+
+ if (WebRtcEventLogCollectionFeature()) {
+ enabled.push_back(features::kWebRtcRemoteEventLog);
+ } else {
+ disabled.push_back(features::kWebRtcRemoteEventLog);
+ }
+
+ enabled.push_back(features::kWebRtcRemoteEventLogGzipped);
+
+ scoped_feature_list_.InitWithFeatures(enabled, disabled);
+ }
+
+ void SetUpInProcessBrowserTestFixture() override {
+ EXPECT_CALL(provider_, IsInitializationComplete(testing::_))
+ .WillRepeatedly(testing::Return(true));
+
+ policy::BrowserPolicyConnector::SetPolicyProviderForTesting(&provider_);
+ policy::PolicyMap values;
+
+ values.Set(policy::key::kWebRtcEventLogCollectionAllowed,
+ policy::POLICY_LEVEL_MANDATORY, policy::POLICY_SCOPE_USER,
+ policy::POLICY_SOURCE_ENTERPRISE_DEFAULT,
+ std::make_unique<base::Value>(WebRtcEventLogCollectionPolicy()),
+ nullptr);
+
+ provider_.UpdateChromePolicy(values);
+ }
+
+ // Whether the test should have WebRTC remote-bound event logging generally
+ // enabled (default behavior), or disabled (Finch kill-switch engaged).
+ virtual bool WebRtcEventLogCollectionFeature() const = 0;
+
+ // Whether the test should simulate running on a user profile which
+ // has the kWebRtcEventLogCollectionAllowed policy configured or not.
+ virtual bool WebRtcEventLogCollectionPolicy() const = 0;
+
+ private:
+ policy::MockConfigurationPolicyProvider provider_;
+};
+
+// Test StartEventLogging's behavior when the feature is active (kill-switch
+// from Finch *not* engaged, working in a profile where the policy is
+// configured).
+class WebrtcLoggingPrivateApiStartEventLoggingTestFeatureAndPolicyEnabled
+ : public WebrtcLoggingPrivateApiStartEventLoggingTestBase {
+ public:
+ ~WebrtcLoggingPrivateApiStartEventLoggingTestFeatureAndPolicyEnabled()
+ override = default;
+
+ bool WebRtcEventLogCollectionFeature() const override { return true; }
+
+ bool WebRtcEventLogCollectionPolicy() const override { return true; }
+};
+
+// Also covers StartEventLoggingForLegalWebAppIdSucceeds scenario.
+IN_PROC_BROWSER_TEST_F(
+ WebrtcLoggingPrivateApiStartEventLoggingTestFeatureAndPolicyEnabled,
+ StartEventLoggingForKnownPeerConnectionSucceeds) {
const std::string peer_connection_id = "id";
SetUpPeerConnection(peer_connection_id);
const int max_size_bytes = kMaxRemoteLogFileSizeBytes;
constexpr bool expect_success = true;
- StartEventLogging(peer_connection_id, max_size_bytes, expect_success);
+ StartEventLogging(peer_connection_id, max_size_bytes, kWebAppId,
+ expect_success);
}
-IN_PROC_BROWSER_TEST_F(WebrtcLoggingPrivateApiTest,
- StartEventLoggingWithUnlimitedSizeFails) {
+IN_PROC_BROWSER_TEST_F(
+ WebrtcLoggingPrivateApiStartEventLoggingTestFeatureAndPolicyEnabled,
+ StartEventLoggingWithUnlimitedSizeFails) {
const std::string peer_connection_id = "id";
SetUpPeerConnection(peer_connection_id);
const int max_size_bytes = kWebRtcEventLogManagerUnlimitedFileSize;
constexpr bool expect_success = false;
const std::string error_message =
kStartRemoteLoggingFailureUnlimitedSizeDisallowed;
- StartEventLogging(peer_connection_id, max_size_bytes, expect_success,
- error_message);
+ StartEventLogging(peer_connection_id, max_size_bytes, kWebAppId,
+ expect_success, error_message);
}
-IN_PROC_BROWSER_TEST_F(WebrtcLoggingPrivateApiTest,
- StartEventLoggingWithExcessiveMaxSizeFails) {
+IN_PROC_BROWSER_TEST_F(
+ WebrtcLoggingPrivateApiStartEventLoggingTestFeatureAndPolicyEnabled,
+ StartEventLoggingWithTooSmallMaxSize) {
+ const std::string peer_connection_id = "id";
+ SetUpPeerConnection(peer_connection_id);
+ const int max_size_bytes = 1;
+ constexpr bool expect_success = false;
+ const std::string error_message = kStartRemoteLoggingFailureMaxSizeTooSmall;
+ StartEventLogging(peer_connection_id, max_size_bytes, kWebAppId,
+ expect_success, error_message);
+}
+
+IN_PROC_BROWSER_TEST_F(
+ WebrtcLoggingPrivateApiStartEventLoggingTestFeatureAndPolicyEnabled,
+ StartEventLoggingWithExcessiveMaxSizeFails) {
const std::string peer_connection_id = "id";
SetUpPeerConnection(peer_connection_id);
const int max_size_bytes = kMaxRemoteLogFileSizeBytes + 1;
constexpr bool expect_success = false;
const std::string error_message = kStartRemoteLoggingFailureMaxSizeTooLarge;
- StartEventLogging(peer_connection_id, max_size_bytes, expect_success,
- error_message);
+ StartEventLogging(peer_connection_id, max_size_bytes, kWebAppId,
+ expect_success, error_message);
}
-IN_PROC_BROWSER_TEST_F(WebrtcLoggingPrivateApiTest,
- StartEventLoggingForNeverAddedPeerConnectionFails) {
+IN_PROC_BROWSER_TEST_F(
+ WebrtcLoggingPrivateApiStartEventLoggingTestFeatureAndPolicyEnabled,
+ StartEventLoggingForNeverAddedPeerConnectionFails) {
// Note that manager->PeerConnectionAdded() is not called.
const std::string peer_connection_id = "id";
const int max_size_bytes = kMaxRemoteLogFileSizeBytes;
constexpr bool expect_success = false;
const std::string error_message =
kStartRemoteLoggingFailureUnknownOrInactivePeerConnection;
- StartEventLogging(peer_connection_id, max_size_bytes, expect_success,
- error_message);
+ StartEventLogging(peer_connection_id, max_size_bytes, kWebAppId,
+ expect_success, error_message);
}
-IN_PROC_BROWSER_TEST_F(WebrtcLoggingPrivateApiTest,
- StartEventLoggingForWrongPeerConnectionIdFails) {
+IN_PROC_BROWSER_TEST_F(
+ WebrtcLoggingPrivateApiStartEventLoggingTestFeatureAndPolicyEnabled,
+ StartEventLoggingForWrongPeerConnectionIdFails) {
const std::string peer_connection_id_1 = "id1";
const std::string peer_connection_id_2 = "id2";
@@ -698,12 +782,13 @@ IN_PROC_BROWSER_TEST_F(WebrtcLoggingPrivateApiTest,
constexpr bool expect_success = false;
const std::string error_message =
kStartRemoteLoggingFailureUnknownOrInactivePeerConnection;
- StartEventLogging(peer_connection_id_2, max_size_bytes, expect_success,
- error_message);
+ StartEventLogging(peer_connection_id_2, max_size_bytes, kWebAppId,
+ expect_success, error_message);
}
-IN_PROC_BROWSER_TEST_F(WebrtcLoggingPrivateApiTest,
- StartEventLoggingForAlreadyLoggedPeerConnectionFails) {
+IN_PROC_BROWSER_TEST_F(
+ WebrtcLoggingPrivateApiStartEventLoggingTestFeatureAndPolicyEnabled,
+ StartEventLoggingForAlreadyLoggedPeerConnectionFails) {
const std::string peer_connection_id = "id";
SetUpPeerConnection(peer_connection_id);
@@ -712,36 +797,127 @@ IN_PROC_BROWSER_TEST_F(WebrtcLoggingPrivateApiTest,
// First call succeeds.
{
constexpr bool expect_success = true;
- StartEventLogging(peer_connection_id, max_size_bytes, expect_success);
+ StartEventLogging(peer_connection_id, max_size_bytes, kWebAppId,
+ expect_success);
}
// Second call fails.
{
constexpr bool expect_success = false;
const std::string error_message = kStartRemoteLoggingFailureAlreadyLogging;
- StartEventLogging(peer_connection_id, max_size_bytes, expect_success,
- error_message);
+ StartEventLogging(peer_connection_id, max_size_bytes, kWebAppId,
+ expect_success, error_message);
}
}
-IN_PROC_BROWSER_TEST_F(WebrtcLoggingPrivateApiTestDisabledRemoteLogging,
- StartEventLoggingFails) {
+IN_PROC_BROWSER_TEST_F(
+ WebrtcLoggingPrivateApiStartEventLoggingTestFeatureAndPolicyEnabled,
+ StartEventLoggingForTooLowWebAppIdFails) {
+ const std::string peer_connection_id = "id";
+ SetUpPeerConnection(peer_connection_id);
+ const int max_size_bytes = kMaxRemoteLogFileSizeBytes;
+ const size_t web_app_id =
+ webrtc_event_logging::kMinWebRtcEventLogWebAppId - 1;
+ ASSERT_LT(web_app_id, webrtc_event_logging::kMinWebRtcEventLogWebAppId);
+ constexpr bool expect_success = false;
+ const std::string error_message =
+ webrtc_event_logging::kStartRemoteLoggingFailureIllegalWebAppId;
+ StartEventLogging(peer_connection_id, max_size_bytes, web_app_id,
+ expect_success, error_message);
+}
+
+IN_PROC_BROWSER_TEST_F(
+ WebrtcLoggingPrivateApiStartEventLoggingTestFeatureAndPolicyEnabled,
+ StartEventLoggingForTooHighWebAppIdFails) {
+ const std::string peer_connection_id = "id";
+ SetUpPeerConnection(peer_connection_id);
+ const int max_size_bytes = kMaxRemoteLogFileSizeBytes;
+ const size_t web_app_id =
+ webrtc_event_logging::kMaxWebRtcEventLogWebAppId + 1;
+ ASSERT_GT(web_app_id, webrtc_event_logging::kMaxWebRtcEventLogWebAppId);
+ constexpr bool expect_success = false;
+ const std::string error_message =
+ webrtc_event_logging::kStartRemoteLoggingFailureIllegalWebAppId;
+ StartEventLogging(peer_connection_id, max_size_bytes, web_app_id,
+ expect_success, error_message);
+}
+
+// Testing with either the feature or the policy disabled (not both).
+class WebrtcLoggingPrivateApiStartEventLoggingTestFeatureOrPolicyDisabled
+ : public WebrtcLoggingPrivateApiStartEventLoggingTestBase,
+ public ::testing::WithParamInterface<bool> {
+ public:
+ WebrtcLoggingPrivateApiStartEventLoggingTestFeatureOrPolicyDisabled()
+ : feature_enabled_(GetParam()), policy_enabled_(!feature_enabled_) {}
+
+ ~WebrtcLoggingPrivateApiStartEventLoggingTestFeatureOrPolicyDisabled()
+ override = default;
+
+ protected:
+ bool WebRtcEventLogCollectionFeature() const override {
+ return feature_enabled_;
+ }
+
+ bool WebRtcEventLogCollectionPolicy() const override {
+ return policy_enabled_;
+ }
+
+ private:
+ const bool feature_enabled_;
+ const bool policy_enabled_;
+};
+
+IN_PROC_BROWSER_TEST_P(
+ WebrtcLoggingPrivateApiStartEventLoggingTestFeatureOrPolicyDisabled,
+ StartEventLoggingFails) {
const std::string peer_connection_id = "id";
SetUpPeerConnection(peer_connection_id);
const int max_size_bytes = kMaxRemoteLogFileSizeBytes;
constexpr bool expect_success = false;
const std::string error_message = kStartRemoteLoggingFailureFeatureDisabled;
- StartEventLogging(peer_connection_id, max_size_bytes, expect_success,
- error_message);
+ StartEventLogging(peer_connection_id, max_size_bytes, kWebAppId,
+ expect_success, error_message);
}
-IN_PROC_BROWSER_TEST_F(WebrtcLoggingPrivateApiTestInIncognitoMode,
- StartEventLoggingFails) {
+INSTANTIATE_TEST_CASE_P(
+ FeatureEnabled,
+ WebrtcLoggingPrivateApiStartEventLoggingTestFeatureOrPolicyDisabled,
+ ::testing::Bool());
+
+// Make sure that, even if both the feature and the policy enable remote-bound
+// event logging, it will be blocked for incognito sessions.
+class WebrtcLoggingPrivateApiStartEventLoggingTestInIncognitoMode
+ : public WebrtcLoggingPrivateApiStartEventLoggingTestBase {
+ public:
+ ~WebrtcLoggingPrivateApiStartEventLoggingTestInIncognitoMode() override =
+ default;
+
+ protected:
+ Browser* GetBrowser() override {
+ if (!browser_) {
+ browser_ = CreateIncognitoBrowser();
+ }
+ return browser_;
+ }
+
+ bool WebRtcEventLogCollectionFeature() const override { return true; }
+
+ bool WebRtcEventLogCollectionPolicy() const override { return true; }
+
+ private:
+ Browser* browser_{nullptr}; // Does not own the object.
+};
+
+IN_PROC_BROWSER_TEST_F(
+ WebrtcLoggingPrivateApiStartEventLoggingTestInIncognitoMode,
+ StartEventLoggingFails) {
const std::string peer_connection_id = "id";
SetUpPeerConnection(peer_connection_id);
const int max_size_bytes = kMaxRemoteLogFileSizeBytes;
constexpr bool expect_success = false;
const std::string error_message = kStartRemoteLoggingFailureFeatureDisabled;
- StartEventLogging(peer_connection_id, max_size_bytes, expect_success,
- error_message);
+ StartEventLogging(peer_connection_id, max_size_bytes, kWebAppId,
+ expect_success, error_message);
}
+
+#endif // !defined(OS_ANDROID)
diff --git a/chromium/chrome/browser/extensions/api/webrtc_logging_private/webrtc_logging_private_browsertest.cc b/chromium/chrome/browser/extensions/api/webrtc_logging_private/webrtc_logging_private_browsertest.cc
index 264e9c2a469..aa5ee121352 100644
--- a/chromium/chrome/browser/extensions/api/webrtc_logging_private/webrtc_logging_private_browsertest.cc
+++ b/chromium/chrome/browser/extensions/api/webrtc_logging_private/webrtc_logging_private_browsertest.cc
@@ -8,7 +8,7 @@
#include "build/build_config.h"
#include "chrome/browser/apps/platform_apps/app_browsertest_util.h"
#include "chrome/common/chrome_switches.h"
-#include "components/webrtc_logging/browser/log_list.h"
+#include "components/webrtc_logging/browser/text_log_list.h"
class WebrtcLoggingPrivateApiBrowserTest
: public extensions::PlatformAppBrowserTest {
@@ -17,8 +17,8 @@ class WebrtcLoggingPrivateApiBrowserTest
~WebrtcLoggingPrivateApiBrowserTest() override = default;
base::FilePath webrtc_logs_path() {
- return webrtc_logging::LogList::GetWebRtcLogDirectoryForBrowserContextPath(
- profile()->GetPath());
+ return webrtc_logging::TextLogList::
+ GetWebRtcLogDirectoryForBrowserContextPath(profile()->GetPath());
}
private:
diff --git a/chromium/chrome/browser/extensions/api/webstore_private/webstore_private_apitest.cc b/chromium/chrome/browser/extensions/api/webstore_private/webstore_private_apitest.cc
index 4819cef550e..e1ecf590919 100644
--- a/chromium/chrome/browser/extensions/api/webstore_private/webstore_private_apitest.cc
+++ b/chromium/chrome/browser/extensions/api/webstore_private/webstore_private_apitest.cc
@@ -28,7 +28,9 @@
#include "content/public/browser/gpu_data_manager.h"
#include "content/public/browser/notification_observer.h"
#include "content/public/browser/notification_registrar.h"
+#include "content/public/browser/render_frame_host.h"
#include "content/public/test/browser_test_utils.h"
+#include "content/public/test/test_navigation_observer.h"
#include "extensions/browser/api/management/management_api.h"
#include "extensions/browser/extension_dialog_auto_confirm.h"
#include "extensions/browser/extension_system.h"
@@ -187,34 +189,52 @@ class ExtensionWebstorePrivateApiTest : public ExtensionApiTest {
};
// Test cases for webstore origin frame blocking.
-// TODO(mkwst): Disabled until new X-Frame-Options behavior rolls into
-// Chromium, see crbug.com/226018.
IN_PROC_BROWSER_TEST_F(ExtensionWebstorePrivateApiTest,
- DISABLED_FrameWebstorePageBlocked) {
- base::string16 expected_title = base::UTF8ToUTF16("PASS: about:blank");
- base::string16 failure_title = base::UTF8ToUTF16("FAIL");
- content::TitleWatcher watcher(GetWebContents(), expected_title);
- watcher.AlsoWaitForTitle(failure_title);
+ FrameWebstorePageBlocked) {
GURL url = embedded_test_server()->GetURL(
"/extensions/api_test/webstore_private/noframe.html");
+ content::WebContents* web_contents = GetWebContents();
ui_test_utils::NavigateToURL(browser(), url);
- base::string16 final_title = watcher.WaitAndGetTitle();
- EXPECT_EQ(expected_title, final_title);
+
+ // Try to load the same URL, but with the current Chrome web store origin in
+ // an iframe (i.e. http://www.example.com)
+ content::TestNavigationObserver observer(web_contents);
+ ASSERT_TRUE(content::ExecuteScript(web_contents, "dropFrame()"));
+ WaitForLoadStop(web_contents);
+ content::RenderFrameHost* subframe =
+ content::ChildFrameAt(web_contents->GetMainFrame(), 0);
+ ASSERT_TRUE(subframe);
+
+ // The subframe load should fail due to XFO.
+ GURL iframe_url = embedded_test_server()->GetURL(
+ "www.example.com", "/extensions/api_test/webstore_private/noframe.html");
+ EXPECT_EQ(iframe_url, subframe->GetLastCommittedURL());
+ EXPECT_FALSE(observer.last_navigation_succeeded());
+ EXPECT_EQ(net::ERR_BLOCKED_BY_RESPONSE, observer.last_net_error_code());
}
-// TODO(mkwst): Disabled until new X-Frame-Options behavior rolls into
-// Chromium, see crbug.com/226018.
-IN_PROC_BROWSER_TEST_F(ExtensionWebstorePrivateApiTest,
- DISABLED_FrameErrorPageBlocked) {
- base::string16 expected_title = base::UTF8ToUTF16("PASS: about:blank");
- base::string16 failure_title = base::UTF8ToUTF16("FAIL");
- content::TitleWatcher watcher(GetWebContents(), expected_title);
- watcher.AlsoWaitForTitle(failure_title);
+IN_PROC_BROWSER_TEST_F(ExtensionWebstorePrivateApiTest, FrameErrorPageBlocked) {
GURL url = embedded_test_server()->GetURL(
"/extensions/api_test/webstore_private/noframe2.html");
+ content::WebContents* web_contents = GetWebContents();
ui_test_utils::NavigateToURL(browser(), url);
- base::string16 final_title = watcher.WaitAndGetTitle();
- EXPECT_EQ(expected_title, final_title);
+
+ // Try to load the same URL, but with the current Chrome web store origin in
+ // an iframe (i.e. http://www.example.com)
+ content::TestNavigationObserver observer(web_contents);
+ ASSERT_TRUE(content::ExecuteScript(web_contents, "dropFrame()"));
+ WaitForLoadStop(web_contents);
+ content::RenderFrameHost* subframe =
+ content::ChildFrameAt(web_contents->GetMainFrame(), 0);
+ ASSERT_TRUE(subframe);
+
+ // The subframe load should fail due to XFO.
+ GURL iframe_url = embedded_test_server()->GetURL(
+ "www.example.com",
+ "/nonesuch/extensions/api_test/webstore_private/noframe2.html ");
+ EXPECT_EQ(iframe_url, subframe->GetLastCommittedURL());
+ EXPECT_FALSE(observer.last_navigation_succeeded());
+ EXPECT_EQ(net::ERR_BLOCKED_BY_RESPONSE, observer.last_net_error_code());
}
// Test cases where the user accepts the install confirmation dialog.
@@ -351,24 +371,6 @@ IN_PROC_BROWSER_TEST_F(ExtensionWebstorePrivateApiTest, EmptyCrx) {
}
#if BUILDFLAG(ENABLE_SUPERVISED_USERS)
-
-class ExtensionWebstorePrivateApiTestSupervised
- : public ExtensionWebstorePrivateApiTest {
- public:
- void SetUpCommandLine(base::CommandLine* command_line) override {
- ExtensionWebstorePrivateApiTest::SetUpCommandLine(command_line);
- command_line->AppendSwitchASCII(switches::kSupervisedUserId, "not_empty");
- }
-};
-
-// Tests that extension installation is blocked for supervised users.
-// Note: This will have to be updated if we enable SU-initiated installs.
-IN_PROC_BROWSER_TEST_F(ExtensionWebstorePrivateApiTestSupervised,
- InstallBlocked) {
- ASSERT_TRUE(
- RunInstallTest("begin_install_fail_supervised.html", "extension.crx"));
-}
-
class ExtensionWebstorePrivateApiTestChild
: public ExtensionWebstorePrivateApiTest {
public: