summaryrefslogtreecommitdiffstats
path: root/chromium/extensions/browser
diff options
context:
space:
mode:
Diffstat (limited to 'chromium/extensions/browser')
-rw-r--r--chromium/extensions/browser/BUILD.gn14
-rw-r--r--chromium/extensions/browser/OWNERS1
-rw-r--r--chromium/extensions/browser/activity.cc1
-rw-r--r--chromium/extensions/browser/api/DEPS2
-rw-r--r--chromium/extensions/browser/api/alarms/BUILD.gn5
-rw-r--r--chromium/extensions/browser/api/alarms/alarm_manager.cc15
-rw-r--r--chromium/extensions/browser/api/async_api_function.cc9
-rw-r--r--chromium/extensions/browser/api/audio/audio_apitest_chromeos.cc17
-rw-r--r--chromium/extensions/browser/api/audio/audio_service_chromeos.cc4
-rw-r--r--chromium/extensions/browser/api/bluetooth_low_energy/bluetooth_low_energy_event_router.cc2
-rw-r--r--chromium/extensions/browser/api/bluetooth_socket/bluetooth_socket_event_dispatcher.cc4
-rw-r--r--chromium/extensions/browser/api/cast_channel/cast_channel_api.cc9
-rw-r--r--chromium/extensions/browser/api/cast_channel/cast_channel_apitest.cc19
-rw-r--r--chromium/extensions/browser/api/crash_report_private/crash_report_private_api.cc7
-rw-r--r--chromium/extensions/browser/api/declarative/deduping_factory.h2
-rw-r--r--chromium/extensions/browser/api/declarative/rules_registry.cc5
-rw-r--r--chromium/extensions/browser/api/declarative/rules_registry_service.cc2
-rw-r--r--chromium/extensions/browser/api/declarative_net_request/composite_matcher.cc75
-rw-r--r--chromium/extensions/browser/api/declarative_net_request/composite_matcher.h19
-rw-r--r--chromium/extensions/browser/api/declarative_net_request/composite_matcher_unittest.cc246
-rw-r--r--chromium/extensions/browser/api/declarative_net_request/constants.cc11
-rw-r--r--chromium/extensions/browser/api/declarative_net_request/constants.h44
-rw-r--r--chromium/extensions/browser/api/declarative_net_request/extension_url_pattern_index_matcher.cc11
-rw-r--r--chromium/extensions/browser/api/declarative_net_request/extension_url_pattern_index_matcher.h3
-rw-r--r--chromium/extensions/browser/api/declarative_net_request/file_sequence_helper.cc70
-rw-r--r--chromium/extensions/browser/api/declarative_net_request/file_sequence_helper.h13
-rw-r--r--chromium/extensions/browser/api/declarative_net_request/file_sequence_helper_unittest.cc54
-rw-r--r--chromium/extensions/browser/api/declarative_net_request/flat/extension_ruleset.fbs5
-rw-r--r--chromium/extensions/browser/api/declarative_net_request/flat_ruleset_indexer.cc13
-rw-r--r--chromium/extensions/browser/api/declarative_net_request/flat_ruleset_indexer_unittest.cc35
-rw-r--r--chromium/extensions/browser/api/declarative_net_request/index_helper.cc7
-rw-r--r--chromium/extensions/browser/api/declarative_net_request/indexed_rule.cc19
-rw-r--r--chromium/extensions/browser/api/declarative_net_request/indexed_rule_unittest.cc66
-rw-r--r--chromium/extensions/browser/api/declarative_net_request/indexed_ruleset_format_version_unittest.cc5
-rw-r--r--chromium/extensions/browser/api/declarative_net_request/parse_info.cc12
-rw-r--r--chromium/extensions/browser/api/declarative_net_request/parse_info.h2
-rw-r--r--chromium/extensions/browser/api/declarative_net_request/regex_rules_matcher.cc12
-rw-r--r--chromium/extensions/browser/api/declarative_net_request/regex_rules_matcher.h3
-rw-r--r--chromium/extensions/browser/api/declarative_net_request/request_action.cc39
-rw-r--r--chromium/extensions/browser/api/declarative_net_request/request_action.h15
-rw-r--r--chromium/extensions/browser/api/declarative_net_request/request_params.h10
-rw-r--r--chromium/extensions/browser/api/declarative_net_request/rules_monitor_service.cc102
-rw-r--r--chromium/extensions/browser/api/declarative_net_request/rules_monitor_service.h5
-rw-r--r--chromium/extensions/browser/api/declarative_net_request/ruleset_manager.cc14
-rw-r--r--chromium/extensions/browser/api/declarative_net_request/ruleset_matcher.cc19
-rw-r--r--chromium/extensions/browser/api/declarative_net_request/ruleset_matcher.h36
-rw-r--r--chromium/extensions/browser/api/declarative_net_request/ruleset_matcher_base.h6
-rw-r--r--chromium/extensions/browser/api/declarative_net_request/ruleset_matcher_unittest.cc98
-rw-r--r--chromium/extensions/browser/api/declarative_net_request/ruleset_source.cc18
-rw-r--r--chromium/extensions/browser/api/declarative_net_request/test_utils.cc93
-rw-r--r--chromium/extensions/browser/api/declarative_net_request/test_utils.h4
-rw-r--r--chromium/extensions/browser/api/declarative_net_request/utils.cc33
-rw-r--r--chromium/extensions/browser/api/declarative_net_request/utils.h17
-rw-r--r--chromium/extensions/browser/api/device_permissions_prompt.h1
-rw-r--r--chromium/extensions/browser/api/display_source/display_source_apitestbase.cc17
-rw-r--r--chromium/extensions/browser/api/display_source/wifi_display/wifi_display_media_service_impl.cc5
-rw-r--r--chromium/extensions/browser/api/document_scan/BUILD.gn13
-rw-r--r--chromium/extensions/browser/api/document_scan/document_scan_api.h5
-rw-r--r--chromium/extensions/browser/api/document_scan/document_scan_interface_chromeos.cc25
-rw-r--r--chromium/extensions/browser/api/document_scan/document_scan_interface_chromeos.h10
-rw-r--r--chromium/extensions/browser/api/document_scan/document_scan_interface_chromeos_unittest.cc13
-rw-r--r--chromium/extensions/browser/api/document_scan/document_scan_interface_nonchromeos.cc12
-rw-r--r--chromium/extensions/browser/api/extensions_api_client.cc6
-rw-r--r--chromium/extensions/browser/api/extensions_api_client.h6
-rw-r--r--chromium/extensions/browser/api/feedback_private/feedback_service.cc2
-rw-r--r--chromium/extensions/browser/api/file_system/BUILD.gn1
-rw-r--r--chromium/extensions/browser/api/file_system/file_system_api.cc62
-rw-r--r--chromium/extensions/browser/api/file_system/file_system_api.h2
-rw-r--r--chromium/extensions/browser/api/management/BUILD.gn1
-rw-r--r--chromium/extensions/browser/api/management/management_api.cc169
-rw-r--r--chromium/extensions/browser/api/management/management_api.h37
-rw-r--r--chromium/extensions/browser/api/management/management_api_constants.cc2
-rw-r--r--chromium/extensions/browser/api/management/management_api_constants.h1
-rw-r--r--chromium/extensions/browser/api/management/supervised_user_service_delegate.h68
-rw-r--r--chromium/extensions/browser/api/media_perception_private/media_perception_api_manager.cc2
-rw-r--r--chromium/extensions/browser/api/messaging/extension_message_port.cc23
-rw-r--r--chromium/extensions/browser/api/networking_private/networking_private_chromeos_unittest.cc2
-rw-r--r--chromium/extensions/browser/api/networking_private/networking_private_linux.cc7
-rw-r--r--chromium/extensions/browser/api/serial/serial_api.cc51
-rw-r--r--chromium/extensions/browser/api/serial/serial_apitest.cc56
-rw-r--r--chromium/extensions/browser/api/serial/serial_connection.cc54
-rw-r--r--chromium/extensions/browser/api/serial/serial_connection.h6
-rw-r--r--chromium/extensions/browser/api/serial/serial_port_manager.cc14
-rw-r--r--chromium/extensions/browser/api/socket/socket_api.cc9
-rw-r--r--chromium/extensions/browser/api/socket/socket_api.h4
-rw-r--r--chromium/extensions/browser/api/socket/tcp_socket.cc9
-rw-r--r--chromium/extensions/browser/api/sockets_tcp/sockets_tcp_api.cc10
-rw-r--r--chromium/extensions/browser/api/sockets_tcp/tcp_socket_event_dispatcher.cc4
-rw-r--r--chromium/extensions/browser/api/sockets_tcp_server/sockets_tcp_server_api.cc10
-rw-r--r--chromium/extensions/browser/api/sockets_tcp_server/tcp_server_socket_event_dispatcher.cc4
-rw-r--r--chromium/extensions/browser/api/sockets_udp/sockets_udp_api.cc10
-rw-r--r--chromium/extensions/browser/api/sockets_udp/udp_socket_event_dispatcher.cc4
-rw-r--r--chromium/extensions/browser/api/storage/settings_storage_quota_enforcer.cc1
-rw-r--r--chromium/extensions/browser/api/storage/storage_api.cc7
-rw-r--r--chromium/extensions/browser/api/system_storage/system_storage_eject_apitest.cc2
-rw-r--r--chromium/extensions/browser/api/test/test_api.cc2
-rw-r--r--chromium/extensions/browser/api/vpn_provider/vpn_service.cc2
-rw-r--r--chromium/extensions/browser/api/web_request/BUILD.gn1
-rw-r--r--chromium/extensions/browser/api/web_request/web_request_api.cc75
-rw-r--r--chromium/extensions/browser/api/web_request/web_request_api_helpers.cc309
-rw-r--r--chromium/extensions/browser/api/web_request/web_request_api_helpers.h17
-rw-r--r--chromium/extensions/browser/api/web_request/web_request_proxying_url_loader_factory.cc230
-rw-r--r--chromium/extensions/browser/api/web_request/web_request_proxying_url_loader_factory.h51
-rw-r--r--chromium/extensions/browser/app_sorting.h5
-rw-r--r--chromium/extensions/browser/app_window/app_window.cc9
-rw-r--r--chromium/extensions/browser/app_window/app_window.h3
-rw-r--r--chromium/extensions/browser/computed_hashes.cc1
-rw-r--r--chromium/extensions/browser/content_verifier.cc33
-rw-r--r--chromium/extensions/browser/content_verify_job_unittest.cc13
-rw-r--r--chromium/extensions/browser/crx_file_info.h3
-rw-r--r--chromium/extensions/browser/declarative_user_script_manager.cc28
-rw-r--r--chromium/extensions/browser/declarative_user_script_manager.h24
-rw-r--r--chromium/extensions/browser/declarative_user_script_set.cc (renamed from chromium/extensions/browser/declarative_user_script_master.cc)18
-rw-r--r--chromium/extensions/browser/declarative_user_script_set.h (renamed from chromium/extensions/browser/declarative_user_script_master.h)16
-rw-r--r--chromium/extensions/browser/event_listener_map.cc48
-rw-r--r--chromium/extensions/browser/event_listener_map.h2
-rw-r--r--chromium/extensions/browser/event_listener_map_unittest.cc286
-rw-r--r--chromium/extensions/browser/event_router_unittest.cc54
-rw-r--r--chromium/extensions/browser/events/event_ack_data.cc7
-rw-r--r--chromium/extensions/browser/extension_action.cc8
-rw-r--r--chromium/extensions/browser/extension_action.h13
-rw-r--r--chromium/extensions/browser/extension_event_histogram_value.h8
-rw-r--r--chromium/extensions/browser/extension_function.cc4
-rw-r--r--chromium/extensions/browser/extension_function_histogram_value.h13
-rw-r--r--chromium/extensions/browser/extension_host.h1
-rw-r--r--chromium/extensions/browser/extension_host_observer.h2
-rw-r--r--chromium/extensions/browser/extension_icon_image.cc8
-rw-r--r--chromium/extensions/browser/extension_navigation_throttle.cc11
-rw-r--r--chromium/extensions/browser/extension_pref_store.cc8
-rw-r--r--chromium/extensions/browser/extension_prefs.cc49
-rw-r--r--chromium/extensions/browser/extension_prefs.h10
-rw-r--r--chromium/extensions/browser/extension_protocols.cc28
-rw-r--r--chromium/extensions/browser/extension_registry.h2
-rw-r--r--chromium/extensions/browser/extension_registry_factory.h2
-rw-r--r--chromium/extensions/browser/extension_system.h9
-rw-r--r--chromium/extensions/browser/extension_user_script_loader.cc30
-rw-r--r--chromium/extensions/browser/extension_user_script_loader.h4
-rw-r--r--chromium/extensions/browser/extension_util.cc21
-rw-r--r--chromium/extensions/browser/extensions_browser_client.cc14
-rw-r--r--chromium/extensions/browser/extensions_browser_client.h14
-rw-r--r--chromium/extensions/browser/guest_view/extensions_guest_view_message_filter.cc13
-rw-r--r--chromium/extensions/browser/guest_view/mime_handler_view/mime_handler_view_attach_helper.cc5
-rw-r--r--chromium/extensions/browser/guest_view/mime_handler_view/mime_handler_view_browsertest.cc3
-rw-r--r--chromium/extensions/browser/guest_view/mime_handler_view/mime_handler_view_guest.cc13
-rw-r--r--chromium/extensions/browser/guest_view/mime_handler_view/mime_handler_view_guest.h3
-rw-r--r--chromium/extensions/browser/guest_view/mime_handler_view/mime_handler_view_interactive_uitest.cc2
-rw-r--r--chromium/extensions/browser/guest_view/mime_handler_view/test_mime_handler_view_guest.cc5
-rw-r--r--chromium/extensions/browser/guest_view/web_view/web_view_apitest.cc2
-rw-r--r--chromium/extensions/browser/guest_view/web_view/web_view_content_script_manager.cc32
-rw-r--r--chromium/extensions/browser/guest_view/web_view/web_view_find_helper.cc18
-rw-r--r--chromium/extensions/browser/guest_view/web_view/web_view_guest.cc28
-rw-r--r--chromium/extensions/browser/guest_view/web_view/web_view_guest.h14
-rw-r--r--chromium/extensions/browser/install/crx_install_error.cc10
-rw-r--r--chromium/extensions/browser/install/crx_install_error.h1
-rw-r--r--chromium/extensions/browser/media_router_extension_access_logger.cc11
-rw-r--r--chromium/extensions/browser/media_router_extension_access_logger.h33
-rw-r--r--chromium/extensions/browser/mock_extension_system.cc6
-rw-r--r--chromium/extensions/browser/mock_extension_system.h3
-rw-r--r--chromium/extensions/browser/notification_types.h7
-rw-r--r--chromium/extensions/browser/null_app_sorting.cc2
-rw-r--r--chromium/extensions/browser/null_app_sorting.h1
-rw-r--r--chromium/extensions/browser/process_manager.cc5
-rw-r--r--chromium/extensions/browser/process_manager.h2
-rw-r--r--chromium/extensions/browser/process_map_factory.h2
-rw-r--r--chromium/extensions/browser/requirements_checker.cc5
-rw-r--r--chromium/extensions/browser/sandboxed_unpacker.cc2
-rw-r--r--chromium/extensions/browser/sandboxed_unpacker_unittest.cc4
-rw-r--r--chromium/extensions/browser/service_worker_task_queue.cc19
-rw-r--r--chromium/extensions/browser/service_worker_task_queue.h1
-rw-r--r--chromium/extensions/browser/shared_user_script_manager.cc (renamed from chromium/extensions/browser/shared_user_script_master.cc)12
-rw-r--r--chromium/extensions/browser/shared_user_script_manager.h (renamed from chromium/extensions/browser/shared_user_script_master.h)14
-rw-r--r--chromium/extensions/browser/supervised_user_extensions_delegate.h57
-rw-r--r--chromium/extensions/browser/unloaded_extension_reason.h2
-rw-r--r--chromium/extensions/browser/updater/extension_cache_fake.cc9
-rw-r--r--chromium/extensions/browser/updater/extension_downloader.cc295
-rw-r--r--chromium/extensions/browser/updater/extension_downloader.h80
-rw-r--r--chromium/extensions/browser/updater/extension_downloader_delegate.cc4
-rw-r--r--chromium/extensions/browser/updater/extension_downloader_delegate.h16
-rw-r--r--chromium/extensions/browser/updater/extension_installer.cc4
-rw-r--r--chromium/extensions/browser/updater/manifest_fetch_data.cc82
-rw-r--r--chromium/extensions/browser/updater/manifest_fetch_data.h46
-rw-r--r--chromium/extensions/browser/updater/update_data_provider.cc26
-rw-r--r--chromium/extensions/browser/updater/update_service.cc15
-rw-r--r--chromium/extensions/browser/updater/update_service_unittest.cc30
-rw-r--r--chromium/extensions/browser/url_loader_factory_manager.cc2
-rw-r--r--chromium/extensions/browser/url_request_util.cc31
-rw-r--r--chromium/extensions/browser/user_script_loader.h2
-rw-r--r--chromium/extensions/browser/value_store/lazy_leveldb.cc2
-rw-r--r--chromium/extensions/browser/value_store/value_store_frontend.cc5
189 files changed, 3032 insertions, 1549 deletions
diff --git a/chromium/extensions/browser/BUILD.gn b/chromium/extensions/browser/BUILD.gn
index 86076a32693..42ddb608b35 100644
--- a/chromium/extensions/browser/BUILD.gn
+++ b/chromium/extensions/browser/BUILD.gn
@@ -100,8 +100,8 @@ jumbo_source_set("browser_sources") {
"declarative_user_script_manager.h",
"declarative_user_script_manager_factory.cc",
"declarative_user_script_manager_factory.h",
- "declarative_user_script_master.cc",
- "declarative_user_script_master.h",
+ "declarative_user_script_set.cc",
+ "declarative_user_script_set.h",
"deferred_start_render_host.h",
"device_local_account_util.cc",
"device_local_account_util.h",
@@ -282,6 +282,8 @@ jumbo_source_set("browser_sources") {
"management_policy.h",
"media_capture_util.cc",
"media_capture_util.h",
+ "media_router_extension_access_logger.cc",
+ "media_router_extension_access_logger.h",
"mojo/keep_alive_impl.cc",
"mojo/keep_alive_impl.h",
"notification_types.h",
@@ -329,12 +331,13 @@ jumbo_source_set("browser_sources") {
"service_worker_task_queue.h",
"service_worker_task_queue_factory.cc",
"service_worker_task_queue_factory.h",
- "shared_user_script_master.cc",
- "shared_user_script_master.h",
+ "shared_user_script_manager.cc",
+ "shared_user_script_manager.h",
"state_store.cc",
"state_store.h",
"suggest_permission_util.cc",
"suggest_permission_util.h",
+ "supervised_user_extensions_delegate.h",
"task_queue_util.cc",
"task_queue_util.h",
"ui_util.cc",
@@ -622,7 +625,6 @@ source_set("unit_tests") {
"api/declarative_webrequest/webrequest_condition_attribute_unittest.cc",
"api/declarative_webrequest/webrequest_condition_unittest.cc",
"api/document_scan/document_scan_api_unittest.cc",
- "api/document_scan/document_scan_interface_chromeos_unittest.cc",
"api/document_scan/fake_document_scan_interface.cc",
"api/document_scan/fake_document_scan_interface.h",
"api/file_handlers/app_file_handler_util_unittest.cc",
@@ -748,6 +750,7 @@ source_set("unit_tests") {
if (is_chromeos) {
sources += [
"api/audio/audio_device_id_calculator_unittest.cc",
+ "api/document_scan/document_scan_interface_chromeos_unittest.cc",
"api/feedback_private/access_rate_limiter_chromeos_unittest.cc",
"api/feedback_private/feedback_private_api_chromeos_unittest.cc",
"api/feedback_private/feedback_private_api_unittest_base_chromeos.cc",
@@ -765,6 +768,7 @@ source_set("unit_tests") {
deps += [
"//chromeos:test_support",
+ "//chromeos/dbus:lorgnette_proto",
"//chromeos/dbus:test_support",
"//chromeos/dbus/audio",
"//chromeos/dbus/media_analytics",
diff --git a/chromium/extensions/browser/OWNERS b/chromium/extensions/browser/OWNERS
index 4d854f8ec58..095363e7579 100644
--- a/chromium/extensions/browser/OWNERS
+++ b/chromium/extensions/browser/OWNERS
@@ -1,6 +1,5 @@
# Please talk to the apps shell team before adding DEPS.
per-file extension_event_histogram_value.h=set noparent
diff --git a/chromium/extensions/browser/activity.cc b/chromium/extensions/browser/activity.cc
index e5d0e13fe4b..94b228386e5 100644
--- a/chromium/extensions/browser/activity.cc
+++ b/chromium/extensions/browser/activity.cc
@@ -5,6 +5,7 @@
#include "extensions/browser/activity.h"
#include "base/logging.h"
+#include "base/notreached.h"
namespace extensions {
diff --git a/chromium/extensions/browser/api/DEPS b/chromium/extensions/browser/api/DEPS
index a8608a8aa09..83b09650b55 100644
--- a/chromium/extensions/browser/api/DEPS
+++ b/chromium/extensions/browser/api/DEPS
@@ -1,6 +1,8 @@
include_rules = [
"+components/device_event_log",
+ "+components/ukm",
"+services/device/public",
+ "+services/metrics/public/cpp",
"+storage/browser/file_system",
"+storage/common/file_system",
"+third_party/openscreen/src/cast/common/certificate/proto",
diff --git a/chromium/extensions/browser/api/alarms/BUILD.gn b/chromium/extensions/browser/api/alarms/BUILD.gn
index e6c7666c9e2..190d1a2baa5 100644
--- a/chromium/extensions/browser/api/alarms/BUILD.gn
+++ b/chromium/extensions/browser/api/alarms/BUILD.gn
@@ -17,7 +17,10 @@ source_set("alarms") {
"alarms_api_constants.h",
]
- deps = [ "//extensions/common/api" ]
+ deps = [
+ "//base/util/values:values_util",
+ "//extensions/common/api",
+ ]
public_deps = [ "//extensions/browser:browser_sources" ]
}
diff --git a/chromium/extensions/browser/api/alarms/alarm_manager.cc b/chromium/extensions/browser/api/alarms/alarm_manager.cc
index 2b3e1ac4afe..07edcf02925 100644
--- a/chromium/extensions/browser/api/alarms/alarm_manager.cc
+++ b/chromium/extensions/browser/api/alarms/alarm_manager.cc
@@ -15,7 +15,7 @@
#include "base/time/clock.h"
#include "base/time/default_clock.h"
#include "base/time/time.h"
-#include "base/value_conversions.h"
+#include "base/util/values/values_util.h"
#include "base/values.h"
#include "extensions/browser/api/alarms/alarms_api_constants.h"
#include "extensions/browser/event_router.h"
@@ -76,11 +76,12 @@ AlarmManager::AlarmList AlarmsFromValue(const std::string extension_id,
std::unique_ptr<Alarm> alarm(new Alarm());
if (list->GetDictionary(i, &alarm_dict) &&
alarms::Alarm::Populate(*alarm_dict, alarm->js_alarm.get())) {
- const base::Value* time_value = nullptr;
- if (alarm_dict->Get(kAlarmGranularity, &time_value)) {
- // It's okay to ignore the failure since we have minimum granularity.
- ignore_result(
- base::GetValueAsTimeDelta(*time_value, &alarm->granularity));
+ base::Optional<base::TimeDelta> delta =
+ util::ValueToTimeDelta(alarm_dict->FindKey(kAlarmGranularity));
+ if (delta) {
+ alarm->granularity = *delta;
+ // No else branch. It's okay to ignore the failure since we have
+ // minimum granularity.
}
alarm->minimum_granularity = base::TimeDelta::FromSecondsD(
(is_unpacked ? alarms_api_constants::kDevDelayMinimum
@@ -101,7 +102,7 @@ std::unique_ptr<base::ListValue> AlarmsToValue(
std::unique_ptr<base::DictionaryValue> alarm =
alarms[i]->js_alarm->ToValue();
alarm->SetKey(kAlarmGranularity,
- base::CreateTimeDeltaValue(alarms[i]->granularity));
+ util::TimeDeltaToValue(alarms[i]->granularity));
list->Append(std::move(alarm));
}
return list;
diff --git a/chromium/extensions/browser/api/async_api_function.cc b/chromium/extensions/browser/api/async_api_function.cc
index 5e5441fa6b0..975673903b8 100644
--- a/chromium/extensions/browser/api/async_api_function.cc
+++ b/chromium/extensions/browser/api/async_api_function.cc
@@ -5,7 +5,6 @@
#include "extensions/browser/api/async_api_function.h"
#include "base/bind.h"
-#include "base/task/post_task.h"
#include "content/public/browser/browser_task_traits.h"
#include "content/public/browser/browser_thread.h"
#include "extensions/browser/extension_system.h"
@@ -16,8 +15,7 @@ namespace extensions {
// AsyncApiFunction
AsyncApiFunction::AsyncApiFunction()
- : work_task_runner_(
- base::CreateSingleThreadTaskRunner({BrowserThread::IO})) {}
+ : work_task_runner_(content::GetIOThreadTaskRunner({})) {}
AsyncApiFunction::~AsyncApiFunction() {}
@@ -58,9 +56,8 @@ ExtensionFunction::ResponseAction AsyncApiFunction::Run() {
void AsyncApiFunction::AsyncWorkCompleted() {
if (!BrowserThread::CurrentlyOn(BrowserThread::UI)) {
- bool rv = base::PostTask(
- FROM_HERE, {BrowserThread::UI},
- base::BindOnce(&AsyncApiFunction::RespondOnUIThread, this));
+ bool rv = content::GetUIThreadTaskRunner({})->PostTask(
+ FROM_HERE, base::BindOnce(&AsyncApiFunction::RespondOnUIThread, this));
DCHECK(rv);
} else {
SendResponse(Respond());
diff --git a/chromium/extensions/browser/api/audio/audio_apitest_chromeos.cc b/chromium/extensions/browser/api/audio/audio_apitest_chromeos.cc
index 5b0d7ba30f5..45900d38efb 100644
--- a/chromium/extensions/browser/api/audio/audio_apitest_chromeos.cc
+++ b/chromium/extensions/browser/api/audio/audio_apitest_chromeos.cc
@@ -49,6 +49,9 @@ struct AudioNodeInfo {
const char* const name;
};
+const uint32_t kInputMaxSupportedChannels = 1;
+const uint32_t kOutputMaxSupportedChannels = 2;
+
const AudioNodeInfo kJabraSpeaker1 = {
false, kJabraSpeaker1Id, kJabraSpeaker1StableDeviceId, "Jabra Speaker",
"USB", "Jabra Speaker 1"};
@@ -74,12 +77,14 @@ const AudioNodeInfo kUSBCameraMic = {
"Webcam Mic", "USB", "Logitech Webcam"};
AudioNode CreateAudioNode(const AudioNodeInfo& info, int version) {
- return AudioNode(info.is_input, info.id, version == 2,
- // stable_device_id_v1:
- info.stable_id,
- // stable_device_id_v2:
- version == 2 ? info.stable_id ^ 0xFFFF : 0, info.device_name,
- info.type, info.name, false, 0);
+ return AudioNode(
+ info.is_input, info.id, version == 2,
+ // stable_device_id_v1:
+ info.stable_id,
+ // stable_device_id_v2:
+ version == 2 ? info.stable_id ^ 0xFFFF : 0, info.device_name, info.type,
+ info.name, false, 0,
+ info.is_input ? kInputMaxSupportedChannels : kOutputMaxSupportedChannels);
}
class AudioApiTest : public ShellApiTest {
diff --git a/chromium/extensions/browser/api/audio/audio_service_chromeos.cc b/chromium/extensions/browser/api/audio/audio_service_chromeos.cc
index 40d0a4cb457..b292104a6cb 100644
--- a/chromium/extensions/browser/api/audio/audio_service_chromeos.cc
+++ b/chromium/extensions/browser/api/audio/audio_service_chromeos.cc
@@ -362,8 +362,8 @@ AudioDeviceInfo AudioServiceImpl::ToAudioDeviceInfo(
info.is_active = device.active;
info.level =
device.is_input
- ? cras_audio_handler_->GetOutputVolumePercentForDevice(device.id)
- : cras_audio_handler_->GetInputGainPercentForDevice(device.id);
+ ? cras_audio_handler_->GetInputGainPercentForDevice(device.id)
+ : cras_audio_handler_->GetOutputVolumePercentForDevice(device.id);
info.stable_device_id = std::make_unique<std::string>(
id_calculator_->GetStableDeviceId(device.stable_device_id));
diff --git a/chromium/extensions/browser/api/bluetooth_low_energy/bluetooth_low_energy_event_router.cc b/chromium/extensions/browser/api/bluetooth_low_energy/bluetooth_low_energy_event_router.cc
index 95f22356ef9..31a5b61c141 100644
--- a/chromium/extensions/browser/api/bluetooth_low_energy/bluetooth_low_energy_event_router.cc
+++ b/chromium/extensions/browser/api/bluetooth_low_energy/bluetooth_low_energy_event_router.cc
@@ -669,7 +669,7 @@ void BluetoothLowEnergyEventRouter::WriteCharacteristicValue(
return;
}
- characteristic->WriteRemoteCharacteristic(
+ characteristic->DeprecatedWriteRemoteCharacteristic(
value, callback,
base::BindOnce(&BluetoothLowEnergyEventRouter::OnError,
weak_ptr_factory_.GetWeakPtr(), error_callback));
diff --git a/chromium/extensions/browser/api/bluetooth_socket/bluetooth_socket_event_dispatcher.cc b/chromium/extensions/browser/api/bluetooth_socket/bluetooth_socket_event_dispatcher.cc
index c8df92dfbcf..48b796db4ef 100644
--- a/chromium/extensions/browser/api/bluetooth_socket/bluetooth_socket_event_dispatcher.cc
+++ b/chromium/extensions/browser/api/bluetooth_socket/bluetooth_socket_event_dispatcher.cc
@@ -351,8 +351,8 @@ void BluetoothSocketEventDispatcher::PostEvent(const SocketParams& params,
std::unique_ptr<Event> event) {
DCHECK_CURRENTLY_ON(params.thread_id);
- base::PostTask(FROM_HERE, {BrowserThread::UI},
- base::BindOnce(&DispatchEvent, params.browser_context_id,
+ content::GetUIThreadTaskRunner({})->PostTask(
+ FROM_HERE, base::BindOnce(&DispatchEvent, params.browser_context_id,
params.extension_id, std::move(event)));
}
diff --git a/chromium/extensions/browser/api/cast_channel/cast_channel_api.cc b/chromium/extensions/browser/api/cast_channel/cast_channel_api.cc
index dc1f5bb8c59..5bd2b5daa9f 100644
--- a/chromium/extensions/browser/api/cast_channel/cast_channel_api.cc
+++ b/chromium/extensions/browser/api/cast_channel/cast_channel_api.cc
@@ -17,7 +17,6 @@
#include "base/json/json_writer.h"
#include "base/lazy_instance.h"
#include "base/strings/string_number_conversions.h"
-#include "base/task/post_task.h"
#include "base/values.h"
#include "components/cast_channel/cast_channel_enum.h"
#include "components/cast_channel/cast_message_util.h"
@@ -515,8 +514,8 @@ void CastChannelAPI::CastMessageHandler::OnError(
OnError::Create(channel_info, error_info);
std::unique_ptr<Event> event(new Event(
events::CAST_CHANNEL_ON_ERROR, OnError::kEventName, std::move(results)));
- base::PostTask(FROM_HERE, {BrowserThread::UI},
- base::BindOnce(ui_dispatch_cb_, std::move(event)));
+ content::GetUIThreadTaskRunner({})->PostTask(
+ FROM_HERE, base::BindOnce(ui_dispatch_cb_, std::move(event)));
}
void CastChannelAPI::CastMessageHandler::OnMessage(
@@ -536,8 +535,8 @@ void CastChannelAPI::CastMessageHandler::OnMessage(
std::unique_ptr<Event> event(new Event(events::CAST_CHANNEL_ON_MESSAGE,
OnMessage::kEventName,
std::move(results)));
- base::PostTask(FROM_HERE, {BrowserThread::UI},
- base::BindOnce(ui_dispatch_cb_, std::move(event)));
+ content::GetUIThreadTaskRunner({})->PostTask(
+ FROM_HERE, base::BindOnce(ui_dispatch_cb_, std::move(event)));
}
} // namespace extensions
diff --git a/chromium/extensions/browser/api/cast_channel/cast_channel_apitest.cc b/chromium/extensions/browser/api/cast_channel/cast_channel_apitest.cc
index bcf1c80d54f..8b4acb1cca4 100644
--- a/chromium/extensions/browser/api/cast_channel/cast_channel_apitest.cc
+++ b/chromium/extensions/browser/api/cast_channel/cast_channel_apitest.cc
@@ -8,7 +8,6 @@
#include "base/command_line.h"
#include "base/files/file_path.h"
#include "base/memory/ptr_util.h"
-#include "base/task/post_task.h"
#include "base/test/scoped_feature_list.h"
#include "base/timer/mock_timer.h"
#include "build/build_config.h"
@@ -100,7 +99,11 @@ class CastChannelAPITest : public extensions::ExtensionApiTest {
// Stub out DualMediaSinkService so it does not interfere with the test.
media_router::DualMediaSinkService::SetInstanceForTest(
new media_router::NoopDualMediaSinkService());
- feature_list_.InitAndDisableFeature(media_router::kDialMediaRouteProvider);
+ // The Media Route Providers must be disabled because they rely on the
+ // presence of a valid DualMediaSinkService.
+ feature_list_.InitWithFeatures(
+ {}, /* disabled_features */ {media_router::kDialMediaRouteProvider,
+ media_router::kCastMediaRouteProvider});
extensions::ExtensionApiTest::SetUp();
}
@@ -204,8 +207,8 @@ class CastChannelAPITest : public extensions::ExtensionApiTest {
protected:
void CallOnMessage(const std::string& message) {
- base::PostTask(FROM_HERE, {content::BrowserThread::IO},
- base::BindOnce(&CastChannelAPITest::DoCallOnMessage,
+ content::GetIOThreadTaskRunner({})->PostTask(
+ FROM_HERE, base::BindOnce(&CastChannelAPITest::DoCallOnMessage,
base::Unretained(this), GetApi(),
mock_cast_socket_, message));
}
@@ -220,8 +223,8 @@ class CastChannelAPITest : public extensions::ExtensionApiTest {
// Fires a timer on the IO thread.
void FireTimeout() {
- base::PostTask(FROM_HERE, {content::BrowserThread::IO},
- base::BindOnce(&CastChannelAPITest::DoFireTimeout,
+ content::GetIOThreadTaskRunner({})->PostTask(
+ FROM_HERE, base::BindOnce(&CastChannelAPITest::DoFireTimeout,
base::Unretained(this), mock_cast_socket_));
}
@@ -255,8 +258,8 @@ class CastChannelAPITest : public extensions::ExtensionApiTest {
};
ACTION_P2(InvokeObserverOnError, api_test, cast_socket_service) {
- base::PostTask(FROM_HERE, {content::BrowserThread::IO},
- base::BindOnce(&CastChannelAPITest::DoCallOnError,
+ content::GetIOThreadTaskRunner({})->PostTask(
+ FROM_HERE, base::BindOnce(&CastChannelAPITest::DoCallOnError,
base::Unretained(api_test),
base::Unretained(cast_socket_service)));
}
diff --git a/chromium/extensions/browser/api/crash_report_private/crash_report_private_api.cc b/chromium/extensions/browser/api/crash_report_private/crash_report_private_api.cc
index ed996bc1345..112afa3535f 100644
--- a/chromium/extensions/browser/api/crash_report_private/crash_report_private_api.cc
+++ b/chromium/extensions/browser/api/crash_report_private/crash_report_private_api.cc
@@ -7,7 +7,6 @@
#include "base/strings/strcat.h"
#include "base/strings/stringprintf.h"
#include "base/system/sys_info.h"
-#include "base/task/post_task.h"
#include "base/task/task_traits.h"
#include "base/task/thread_pool.h"
#include "base/time/default_clock.h"
@@ -216,8 +215,8 @@ ExtensionFunction::ResponseAction CrashReportPrivateReportErrorFunction::Run() {
// Consent checking may be blocking, so do it on a separate thread to avoid
// blocking the UI thread.
- PostTaskAndReplyWithResult(
- FROM_HERE, {base::ThreadPool(), base::MayBlock()},
+ base::ThreadPool::PostTaskAndReplyWithResult(
+ FROM_HERE, {base::MayBlock()},
base::BindOnce(&crash_reporter::GetClientCollectStatsConsent),
base::BindOnce(
&CrashReportPrivateReportErrorFunction::OnConsentCheckCompleted, this,
@@ -240,7 +239,7 @@ void CrashReportPrivateReportErrorFunction::OnConsentCheckCompleted(
->GetURLLoaderFactoryForBrowserProcess();
// Don't anonymize the report on the UI thread as it can take some time.
- PostTaskAndReplyWithResult(
+ base::ThreadPool::PostTaskAndReplyWithResult(
FROM_HERE, base::BindOnce(&AnonymizeErrorMessage, info.message),
base::BindOnce(
&ReportJavaScriptError, std::move(loader_factory), std::move(info),
diff --git a/chromium/extensions/browser/api/declarative/deduping_factory.h b/chromium/extensions/browser/api/declarative/deduping_factory.h
index cb96e0f75fb..67c7033353a 100644
--- a/chromium/extensions/browser/api/declarative/deduping_factory.h
+++ b/chromium/extensions/browser/api/declarative/deduping_factory.h
@@ -12,8 +12,8 @@
#include <unordered_map>
#include <unordered_set>
+#include "base/check.h"
#include "base/compiler_specific.h"
-#include "base/logging.h"
#include "base/macros.h"
#include "base/memory/ref_counted.h"
#include "base/stl_util.h"
diff --git a/chromium/extensions/browser/api/declarative/rules_registry.cc b/chromium/extensions/browser/api/declarative/rules_registry.cc
index 30b767cdb39..fd6feb20da6 100644
--- a/chromium/extensions/browser/api/declarative/rules_registry.cc
+++ b/chromium/extensions/browser/api/declarative/rules_registry.cc
@@ -12,7 +12,6 @@
#include "base/stl_util.h"
#include "base/strings/stringprintf.h"
#include "base/strings/utf_string_conversions.h"
-#include "base/task/post_task.h"
#include "base/time/time.h"
#include "base/values.h"
#include "content/public/browser/browser_task_traits.h"
@@ -348,8 +347,8 @@ void RulesRegistry::ProcessChangedRules(const std::string& extension_id) {
std::vector<const api::events::Rule*> new_rules;
GetRules(extension_id, &rules_, &new_rules);
- base::PostTask(
- FROM_HERE, {content::BrowserThread::UI},
+ content::GetUIThreadTaskRunner({})->PostTask(
+ FROM_HERE,
base::BindOnce(&RulesCacheDelegate::UpdateRules, cache_delegate_,
extension_id, RulesToValue(new_rules)));
}
diff --git a/chromium/extensions/browser/api/declarative/rules_registry_service.cc b/chromium/extensions/browser/api/declarative/rules_registry_service.cc
index 9e76ebf145c..19f4de09c21 100644
--- a/chromium/extensions/browser/api/declarative/rules_registry_service.cc
+++ b/chromium/extensions/browser/api/declarative/rules_registry_service.cc
@@ -42,7 +42,7 @@ const int RulesRegistryService::kInvalidRulesRegistryID = -1;
RulesRegistryService::RulesRegistryService(content::BrowserContext* context)
: current_rules_registry_id_(kDefaultRulesRegistryID),
- content_rules_registry_(NULL),
+ content_rules_registry_(nullptr),
browser_context_(context) {
if (browser_context_) {
extension_registry_observer_.Add(ExtensionRegistry::Get(browser_context_));
diff --git a/chromium/extensions/browser/api/declarative_net_request/composite_matcher.cc b/chromium/extensions/browser/api/declarative_net_request/composite_matcher.cc
index 8240f453bb0..70dae8c8409 100644
--- a/chromium/extensions/browser/api/declarative_net_request/composite_matcher.cc
+++ b/chromium/extensions/browser/api/declarative_net_request/composite_matcher.cc
@@ -5,6 +5,7 @@
#include "extensions/browser/api/declarative_net_request/composite_matcher.h"
#include <algorithm>
+#include <functional>
#include <iterator>
#include <set>
#include <utility>
@@ -73,29 +74,32 @@ CompositeMatcher::CompositeMatcher(MatcherList matchers)
CompositeMatcher::~CompositeMatcher() = default;
-CompositeMatcher::MatcherList CompositeMatcher::GetAndResetMatchers() {
- MatcherList result;
- std::swap(result, matchers_);
- OnMatchersModified();
- return result;
+void CompositeMatcher::AddOrUpdateRuleset(
+ std::unique_ptr<RulesetMatcher> matcher) {
+ MatcherList matchers;
+ matchers.push_back(std::move(matcher));
+ AddOrUpdateRulesets(std::move(matchers));
}
-void CompositeMatcher::SetMatchers(MatcherList matchers) {
- matchers_ = std::move(matchers);
+void CompositeMatcher::AddOrUpdateRulesets(MatcherList matchers) {
+ std::set<RulesetID> ids_to_remove;
+ for (const auto& matcher : matchers)
+ ids_to_remove.insert(matcher->id());
+
+ RemoveRulesetsWithIDs(ids_to_remove);
+ matchers_.insert(matchers_.end(), std::make_move_iterator(matchers.begin()),
+ std::make_move_iterator(matchers.end()));
OnMatchersModified();
}
-void CompositeMatcher::AddOrUpdateRuleset(
- std::unique_ptr<RulesetMatcher> new_matcher) {
- // A linear search is ok since the number of rulesets per extension is
- // expected to be quite small.
- base::EraseIf(matchers_,
- [&new_matcher](const std::unique_ptr<RulesetMatcher>& matcher) {
- return matcher->id() == new_matcher->id();
- });
- matchers_.push_back(std::move(new_matcher));
+void CompositeMatcher::RemoveRulesetsWithIDs(const std::set<RulesetID>& ids) {
+ size_t erased_count = base::EraseIf(
+ matchers_, [&ids](const std::unique_ptr<RulesetMatcher>& matcher) {
+ return base::Contains(ids, matcher->id());
+ });
- OnMatchersModified();
+ if (erased_count > 0)
+ OnMatchersModified();
}
std::set<RulesetID> CompositeMatcher::ComputeStaticRulesetIDs() const {
@@ -117,11 +121,21 @@ ActionInfo CompositeMatcher::GetBeforeRequestAction(
bool notify_request_withheld = false;
base::Optional<RequestAction> final_action;
+
+ // The priority of the highest priority matching allow or allowAllRequests
+ // rule within this matcher, or base::nullopt otherwise.
+ base::Optional<uint64_t> max_allow_rule_priority;
+
for (const auto& matcher : matchers_) {
base::Optional<RequestAction> action =
matcher->GetBeforeRequestAction(params);
- params.allow_rule_cache[matcher.get()] =
- action && action->IsAllowOrAllowAllRequests();
+
+ if (action && action->IsAllowOrAllowAllRequests()) {
+ max_allow_rule_priority =
+ max_allow_rule_priority
+ ? std::max(*max_allow_rule_priority, action->index_priority)
+ : action->index_priority;
+ }
if (action && action->type == RequestAction::Type::REDIRECT) {
// Redirecting requires host permissions.
@@ -139,6 +153,8 @@ ActionInfo CompositeMatcher::GetBeforeRequestAction(
GetMaxPriorityAction(std::move(final_action), std::move(action));
}
+ params.allow_rule_max_priority[this] = max_allow_rule_priority;
+
if (final_action)
return ActionInfo(std::move(final_action), false);
return ActionInfo(base::nullopt, notify_request_withheld);
@@ -147,16 +163,19 @@ ActionInfo CompositeMatcher::GetBeforeRequestAction(
std::vector<RequestAction> CompositeMatcher::GetModifyHeadersActions(
const RequestParams& params) const {
std::vector<RequestAction> modify_headers_actions;
+ DCHECK(params.allow_rule_max_priority.contains(this));
- for (const auto& matcher : matchers_) {
- // TODO(crbug.com/947591): An allow or allowAllRequests rule should override
- // all equal or lower priority modifyHeaders rules specified by |matcher|.
- DCHECK(params.allow_rule_cache.contains(matcher.get()));
- if (params.allow_rule_cache[matcher.get()])
- return std::vector<RequestAction>();
+ // The priority of the highest priority matching allow or allowAllRequests
+ // rule within this matcher, or base::nullopt if no such rule exists.
+ base::Optional<uint64_t> max_allow_rule_priority =
+ params.allow_rule_max_priority[this];
+ for (const auto& matcher : matchers_) {
+ // Plumb |max_allow_rule_priority| into GetModifyHeadersActions so that
+ // modifyHeaders rules with priorities less than or equal to the highest
+ // priority matching allow/allowAllRequests rule are ignored.
std::vector<RequestAction> actions_for_matcher =
- matcher->GetModifyHeadersActions(params);
+ matcher->GetModifyHeadersActions(params, max_allow_rule_priority);
modify_headers_actions.insert(
modify_headers_actions.end(),
@@ -166,9 +185,7 @@ std::vector<RequestAction> CompositeMatcher::GetModifyHeadersActions(
// Sort |modify_headers_actions| in descending order of priority.
std::sort(modify_headers_actions.begin(), modify_headers_actions.end(),
- [](const RequestAction& lhs, const RequestAction& rhs) {
- return lhs.index_priority > rhs.index_priority;
- });
+ std::greater<>());
return modify_headers_actions;
}
diff --git a/chromium/extensions/browser/api/declarative_net_request/composite_matcher.h b/chromium/extensions/browser/api/declarative_net_request/composite_matcher.h
index 0fae10217a6..85f66bc49eb 100644
--- a/chromium/extensions/browser/api/declarative_net_request/composite_matcher.h
+++ b/chromium/extensions/browser/api/declarative_net_request/composite_matcher.h
@@ -25,8 +25,7 @@ namespace declarative_net_request {
struct RequestAction;
-// Per extension instance which manages the different rulesets for an extension
-// while respecting their priorities.
+// Per extension instance which manages the different rulesets for an extension.
class CompositeMatcher {
public:
struct ActionInfo {
@@ -48,21 +47,21 @@ class CompositeMatcher {
using MatcherList = std::vector<std::unique_ptr<RulesetMatcher>>;
- // Each RulesetMatcher should have a distinct ID and priority.
+ // Each RulesetMatcher should have a distinct RulesetID.
explicit CompositeMatcher(MatcherList matchers);
~CompositeMatcher();
const MatcherList& matchers() const { return matchers_; }
- // Returns the set of matchers and resets |matchers_| to an empty vector.
- MatcherList GetAndResetMatchers();
+ // Inserts |matcher|, overwriting any existing RulesetMatcher with the same
+ // RulesetID.
+ void AddOrUpdateRuleset(std::unique_ptr<RulesetMatcher> matcher);
- // Updates the set of matchers. IDs for all the |matchers| must be unique.
- void SetMatchers(MatcherList matchers);
+ // Inserts |matchers| overwriting any matchers with the same RulesetID.
+ void AddOrUpdateRulesets(CompositeMatcher::MatcherList matchers);
- // Adds the |new_matcher| to the list of matchers. If a matcher with the
- // corresponding ID is already present, updates the matcher.
- void AddOrUpdateRuleset(std::unique_ptr<RulesetMatcher> new_matcher);
+ // Erases RulesetMatchers with the given RulesetIDs.
+ void RemoveRulesetsWithIDs(const std::set<RulesetID>& ids);
// Computes and returns the set of static RulesetIDs corresponding to
// |matchers_|.
diff --git a/chromium/extensions/browser/api/declarative_net_request/composite_matcher_unittest.cc b/chromium/extensions/browser/api/declarative_net_request/composite_matcher_unittest.cc
index 3b183413e5e..25ca0642d16 100644
--- a/chromium/extensions/browser/api/declarative_net_request/composite_matcher_unittest.cc
+++ b/chromium/extensions/browser/api/declarative_net_request/composite_matcher_unittest.cc
@@ -9,7 +9,6 @@
#include <vector>
#include "base/strings/stringprintf.h"
-#include "components/version_info/channel.h"
#include "extensions/browser/api/declarative_net_request/constants.h"
#include "extensions/browser/api/declarative_net_request/request_action.h"
#include "extensions/browser/api/declarative_net_request/request_params.h"
@@ -19,7 +18,6 @@
#include "extensions/common/api/declarative_net_request.h"
#include "extensions/common/api/declarative_net_request/constants.h"
#include "extensions/common/api/declarative_net_request/test_utils.h"
-#include "extensions/common/features/feature_channel.h"
#include "extensions/common/permissions/permissions_data.h"
#include "net/http/http_request_headers.h"
#include "testing/gmock/include/gmock/gmock.h"
@@ -28,6 +26,7 @@
namespace extensions {
namespace declarative_net_request {
+namespace {
using PageAccess = PermissionsData::PageAccess;
using ActionInfo = CompositeMatcher::ActionInfo;
@@ -36,6 +35,32 @@ namespace dnr_api = api::declarative_net_request;
using CompositeMatcherTest = ::testing::Test;
+TestRule CreateModifyHeadersRule(
+ int id,
+ int priority,
+ base::Optional<std::string> url_filter,
+ base::Optional<std::string> regex_filter,
+ base::Optional<std::vector<TestHeaderInfo>> request_headers_list,
+ base::Optional<std::vector<TestHeaderInfo>> response_headers_list) {
+ TestRule rule = CreateGenericRule();
+ rule.id = id;
+ rule.priority = priority;
+
+ if (url_filter)
+ rule.condition->url_filter = url_filter;
+ else if (regex_filter) {
+ rule.condition->url_filter.reset();
+ rule.condition->regex_filter = regex_filter;
+ }
+
+ rule.action->type = std::string("modifyHeaders");
+ if (request_headers_list)
+ rule.action->request_headers = std::move(request_headers_list);
+ if (response_headers_list)
+ rule.action->response_headers = std::move(response_headers_list);
+ return rule;
+}
+
// Ensure that the rules in a CompositeMatcher are in the same priority space.
TEST_F(CompositeMatcherTest, SamePrioritySpace) {
// Create the first ruleset matcher. It allows requests to google.com.
@@ -98,31 +123,19 @@ TEST_F(CompositeMatcherTest, SamePrioritySpace) {
// Tests the GetModifyHeadersActions method.
TEST_F(CompositeMatcherTest, GetModifyHeadersActions) {
- // TODO(crbug.com/947591): Remove the channel override once implementation of
- // modifyHeaders action is complete.
- ScopedCurrentChannel channel(::version_info::Channel::UNKNOWN);
-
- auto create_modify_headers_rule =
- [](int id, int priority, const std::string& url_filter,
- std::vector<TestHeaderInfo> request_headers_list) {
- TestRule rule = CreateGenericRule();
- rule.id = id;
- rule.priority = priority;
- rule.condition->url_filter = url_filter;
- rule.action->type = std::string("modifyHeaders");
- rule.action->request_headers = std::move(request_headers_list);
- return rule;
- };
-
- TestRule rule_1 = create_modify_headers_rule(
- kMinValidID, kMinValidPriority, "google.com",
- std::vector<TestHeaderInfo>({TestHeaderInfo("header1", "remove"),
- TestHeaderInfo("header2", "remove")}));
-
- TestRule rule_2 = create_modify_headers_rule(
- kMinValidID, kMinValidPriority + 1, "/path",
- std::vector<TestHeaderInfo>({TestHeaderInfo("header1", "remove"),
- TestHeaderInfo("header3", "remove")}));
+ TestRule rule_1 = CreateModifyHeadersRule(
+ kMinValidID, kMinValidPriority, "google.com", base::nullopt,
+ std::vector<TestHeaderInfo>(
+ {TestHeaderInfo("header1", "remove", base::nullopt),
+ TestHeaderInfo("header2", "set", "value2")}),
+ base::nullopt);
+
+ TestRule rule_2 = CreateModifyHeadersRule(
+ kMinValidID, kMinValidPriority + 1, "/path", base::nullopt, base::nullopt,
+ std::vector<TestHeaderInfo>(
+ {TestHeaderInfo("header1", "remove", base::nullopt),
+ TestHeaderInfo("header2", "append", "VALUE2"),
+ TestHeaderInfo("header3", "set", "VALUE3")}));
// Create the first ruleset matcher, which matches all requests from
// |google.com|.
@@ -164,15 +177,21 @@ TEST_F(CompositeMatcherTest, GetModifyHeadersActions) {
CreateRequestActionForTesting(RequestAction::Type::MODIFY_HEADERS,
*rule_1.id, *rule_1.priority, kSource1ID);
action_1.request_headers_to_modify = {
- RequestAction::HeaderInfo("header1", dnr_api::HEADER_OPERATION_REMOVE),
- RequestAction::HeaderInfo("header2", dnr_api::HEADER_OPERATION_REMOVE)};
+ RequestAction::HeaderInfo("header1", dnr_api::HEADER_OPERATION_REMOVE,
+ base::nullopt),
+ RequestAction::HeaderInfo("header2", dnr_api::HEADER_OPERATION_SET,
+ "value2")};
RequestAction action_2 =
CreateRequestActionForTesting(RequestAction::Type::MODIFY_HEADERS,
*rule_2.id, *rule_2.priority, kSource2ID);
- action_2.request_headers_to_modify = {
- RequestAction::HeaderInfo("header1", dnr_api::HEADER_OPERATION_REMOVE),
- RequestAction::HeaderInfo("header3", dnr_api::HEADER_OPERATION_REMOVE)};
+ action_2.response_headers_to_modify = {
+ RequestAction::HeaderInfo("header1", dnr_api::HEADER_OPERATION_REMOVE,
+ base::nullopt),
+ RequestAction::HeaderInfo("header2", dnr_api::HEADER_OPERATION_APPEND,
+ "VALUE2"),
+ RequestAction::HeaderInfo("header3", dnr_api::HEADER_OPERATION_SET,
+ "VALUE3")};
// |action_2| should be before |action_1| because |rule_2|
// has a higher priority.
@@ -200,21 +219,27 @@ TEST_F(CompositeMatcherTest, GetModifyHeadersActions) {
PageAccess::kAllowed);
// Re-create |action_1| and |action_2| with the updated rule
- // priorities. The headers removed by each action should not change.
+ // priorities. The headers modified by each action should not change.
actions = composite_matcher->GetModifyHeadersActions(google_params);
action_1 =
CreateRequestActionForTesting(RequestAction::Type::MODIFY_HEADERS,
*rule_1.id, *rule_1.priority, kSource1ID);
action_1.request_headers_to_modify = {
- RequestAction::HeaderInfo("header1", dnr_api::HEADER_OPERATION_REMOVE),
- RequestAction::HeaderInfo("header2", dnr_api::HEADER_OPERATION_REMOVE)};
+ RequestAction::HeaderInfo("header1", dnr_api::HEADER_OPERATION_REMOVE,
+ base::nullopt),
+ RequestAction::HeaderInfo("header2", dnr_api::HEADER_OPERATION_SET,
+ "value2")};
action_2 =
CreateRequestActionForTesting(RequestAction::Type::MODIFY_HEADERS,
*rule_2.id, *rule_2.priority, kSource2ID);
- action_2.request_headers_to_modify = {
- RequestAction::HeaderInfo("header1", dnr_api::HEADER_OPERATION_REMOVE),
- RequestAction::HeaderInfo("header3", dnr_api::HEADER_OPERATION_REMOVE)};
+ action_2.response_headers_to_modify = {
+ RequestAction::HeaderInfo("header1", dnr_api::HEADER_OPERATION_REMOVE,
+ base::nullopt),
+ RequestAction::HeaderInfo("header2", dnr_api::HEADER_OPERATION_APPEND,
+ "VALUE2"),
+ RequestAction::HeaderInfo("header3", dnr_api::HEADER_OPERATION_SET,
+ "VALUE3")};
// |action_1| should now be before |action_2| after their
// priorities have been reversed.
@@ -223,6 +248,150 @@ TEST_F(CompositeMatcherTest, GetModifyHeadersActions) {
::testing::Eq(::testing::ByRef(action_2))));
}
+// Tests that GetModifyHeadersActions method omits rules with an equal or lower
+// priority than a matched allow or allowAllRequests rule.
+TEST_F(CompositeMatcherTest, GetModifyHeadersActions_Priority) {
+ using HeaderInfo = RequestAction::HeaderInfo;
+ int allow_rule_priority = kMinValidPriority + 1;
+
+ TestRule allow_rule = CreateGenericRule();
+ allow_rule.id = kMinValidID;
+ allow_rule.condition->url_filter = std::string("google.com/1");
+ allow_rule.action->type = std::string("allow");
+ allow_rule.priority = allow_rule_priority;
+
+ TestRule url_rule_1 = CreateModifyHeadersRule(
+ kMinValidID + 1, allow_rule_priority - 1, "google.com", base::nullopt,
+ std::vector<TestHeaderInfo>(
+ {TestHeaderInfo("header1", "remove", base::nullopt)}),
+ base::nullopt);
+
+ TestRule url_rule_2 = CreateModifyHeadersRule(
+ kMinValidID + 2, allow_rule_priority, "google.com", base::nullopt,
+ std::vector<TestHeaderInfo>(
+ {TestHeaderInfo("header2", "remove", base::nullopt)}),
+ base::nullopt);
+
+ TestRule url_rule_3 = CreateModifyHeadersRule(
+ kMinValidID + 3, allow_rule_priority + 1, "google.com", base::nullopt,
+ std::vector<TestHeaderInfo>(
+ {TestHeaderInfo("header3", "remove", base::nullopt)}),
+ base::nullopt);
+
+ TestRule regex_rule_1 = CreateModifyHeadersRule(
+ kMinValidID + 4, allow_rule_priority - 1, base::nullopt, R"(google\.com)",
+ std::vector<TestHeaderInfo>(
+ {TestHeaderInfo("header4", "remove", base::nullopt)}),
+ base::nullopt);
+
+ TestRule regex_rule_2 = CreateModifyHeadersRule(
+ kMinValidID + 5, allow_rule_priority, base::nullopt, R"(google\.com)",
+ std::vector<TestHeaderInfo>(
+ {TestHeaderInfo("header5", "remove", base::nullopt)}),
+ base::nullopt);
+
+ TestRule regex_rule_3 = CreateModifyHeadersRule(
+ kMinValidID + 6, allow_rule_priority + 1, base::nullopt, R"(google\.com)",
+ std::vector<TestHeaderInfo>(
+ {TestHeaderInfo("header6", "remove", base::nullopt)}),
+ base::nullopt);
+
+ const RulesetID kSource1ID(1);
+ std::unique_ptr<RulesetMatcher> matcher_1;
+ ASSERT_TRUE(
+ CreateVerifiedMatcher({allow_rule, url_rule_1, url_rule_2, url_rule_3},
+ CreateTemporarySource(kSource1ID), &matcher_1));
+
+ const RulesetID kSource2ID(2);
+ std::unique_ptr<RulesetMatcher> matcher_2;
+ ASSERT_TRUE(CreateVerifiedMatcher({regex_rule_1, regex_rule_2, regex_rule_3},
+ CreateTemporarySource(kSource2ID),
+ &matcher_2));
+
+ // Create a CompositeMatcher with the rulesets.
+ std::vector<std::unique_ptr<RulesetMatcher>> matchers;
+ matchers.push_back(std::move(matcher_1));
+ matchers.push_back(std::move(matcher_2));
+ auto composite_matcher =
+ std::make_unique<CompositeMatcher>(std::move(matchers));
+
+ // Make a request to "http://google.com/1" which matches with all
+ // modifyHeaders rules and |allow_rule|.
+ GURL google_url = GURL("http://google.com/1");
+ RequestParams google_params;
+ google_params.url = &google_url;
+ google_params.element_type = url_pattern_index::flat::ElementType_SUBDOCUMENT;
+ google_params.is_third_party = false;
+
+ // Call GetBeforeRequestAction first to ensure that test and production code
+ // paths are consistent.
+ composite_matcher->GetBeforeRequestAction(google_params,
+ PageAccess::kAllowed);
+
+ std::vector<RequestAction> actions =
+ composite_matcher->GetModifyHeadersActions(google_params);
+
+ auto create_action_for_rule =
+ [](const TestRule& rule, const RulesetID& ruleset_id,
+ const std::vector<HeaderInfo>& request_headers) {
+ RequestAction action =
+ CreateRequestActionForTesting(RequestAction::Type::MODIFY_HEADERS,
+ *rule.id, *rule.priority, ruleset_id);
+
+ action.request_headers_to_modify = request_headers;
+ return action;
+ };
+
+ RequestAction header_3_action = create_action_for_rule(
+ url_rule_3, kSource1ID,
+ {HeaderInfo("header3", dnr_api::HEADER_OPERATION_REMOVE, base::nullopt)});
+ RequestAction header_6_action = create_action_for_rule(
+ regex_rule_3, kSource2ID,
+ {HeaderInfo("header6", dnr_api::HEADER_OPERATION_REMOVE, base::nullopt)});
+
+ // For the request to "http://google.com/1", since |url_rule_3| and
+ // |regex_rule_3| are the only rules with a greater priority than
+ // |allow_rule|, "header3" and "header4" should be removed.
+ EXPECT_THAT(actions, ::testing::UnorderedElementsAre(
+ ::testing::Eq(::testing::ByRef(header_3_action)),
+ ::testing::Eq(::testing::ByRef(header_6_action))));
+
+ // Make a request to "http://google.com/2" which should match with all
+ // modifyHeaders rules but not |allow_rule|.
+ google_url = GURL("http://google.com/2");
+ google_params.url = &google_url;
+
+ // Call GetBeforeRequestAction first to ensure that test and production code
+ // paths are consistent.
+ composite_matcher->GetBeforeRequestAction(google_params,
+ PageAccess::kAllowed);
+ actions = composite_matcher->GetModifyHeadersActions(google_params);
+
+ RequestAction header_1_action = create_action_for_rule(
+ url_rule_1, kSource1ID,
+ {HeaderInfo("header1", dnr_api::HEADER_OPERATION_REMOVE, base::nullopt)});
+ RequestAction header_2_action = create_action_for_rule(
+ url_rule_2, kSource1ID,
+ {HeaderInfo("header2", dnr_api::HEADER_OPERATION_REMOVE, base::nullopt)});
+ RequestAction header_4_action = create_action_for_rule(
+ regex_rule_1, kSource2ID,
+ {HeaderInfo("header4", dnr_api::HEADER_OPERATION_REMOVE, base::nullopt)});
+ RequestAction header_5_action = create_action_for_rule(
+ regex_rule_2, kSource2ID,
+ {HeaderInfo("header5", dnr_api::HEADER_OPERATION_REMOVE, base::nullopt)});
+
+ // For the request to "http://google.com/2", "header1" to "header6" should be
+ // removed since all modifyHeaders rules are matched and there is no matching
+ // allow/allowAllRequests rule.
+ EXPECT_THAT(actions, ::testing::UnorderedElementsAre(
+ ::testing::Eq(::testing::ByRef(header_1_action)),
+ ::testing::Eq(::testing::ByRef(header_2_action)),
+ ::testing::Eq(::testing::ByRef(header_3_action)),
+ ::testing::Eq(::testing::ByRef(header_4_action)),
+ ::testing::Eq(::testing::ByRef(header_5_action)),
+ ::testing::Eq(::testing::ByRef(header_6_action))));
+}
+
// Ensure CompositeMatcher detects requests to be notified based on the rule
// matched and whether the extenion has access to the request.
TEST_F(CompositeMatcherTest, NotifyWithholdFromPageAccess) {
@@ -393,5 +562,6 @@ TEST_F(CompositeMatcherTest, GetRedirectUrlFromPriority) {
}
}
+} // namespace
} // namespace declarative_net_request
} // namespace extensions
diff --git a/chromium/extensions/browser/api/declarative_net_request/constants.cc b/chromium/extensions/browser/api/declarative_net_request/constants.cc
index deb70eb42f2..692e1c23c2e 100644
--- a/chromium/extensions/browser/api/declarative_net_request/constants.cc
+++ b/chromium/extensions/browser/api/declarative_net_request/constants.cc
@@ -65,6 +65,15 @@ const char kErrorNoHeaderListsSpecified[] =
"one of these keys must be specified with a non-empty list.";
const char kErrorInvalidHeaderName[] =
"Rule with id * must specify a valid header name to be modified.";
+const char kErrorInvalidHeaderValue[] =
+ "Rule with id * specifies an invalid header value.";
+const char kErrorNoHeaderValueSpecified[] =
+ "Rule with id * must provide a value for a header to be appended/set.";
+const char kErrorHeaderValuePresent[] =
+ "Rule with id * must not provide a header value for a header to be "
+ "removed.";
+const char kErrorCannotAppendRequestHeader[] =
+ "Rule with id * must not specify a request header to be appended.";
const char kErrorListNotPassed[] = "Rules file must contain a list.";
const char kRuleCountExceeded[] =
@@ -109,6 +118,8 @@ const char kReadDynamicRulesJSONStatusHistogram[] =
"Extensions.DeclarativeNetRequest.ReadDynamicRulesJSONStatus";
const char kIsLargeRegexHistogram[] =
"Extensions.DeclarativeNetRequest.IsLargeRegexRule";
+const char kLoadRulesetResultHistogram[] =
+ "Extensions.DeclarativeNetRequest.LoadRulesetResult";
const char kActionCountPlaceholderBadgeText[] =
"<<declarativeNetRequestActionCount>>";
diff --git a/chromium/extensions/browser/api/declarative_net_request/constants.h b/chromium/extensions/browser/api/declarative_net_request/constants.h
index 7e4cdcfe7c8..8b54d660b1e 100644
--- a/chromium/extensions/browser/api/declarative_net_request/constants.h
+++ b/chromium/extensions/browser/api/declarative_net_request/constants.h
@@ -56,7 +56,11 @@ enum class ParseResult {
ERROR_NO_HEADERS_SPECIFIED,
ERROR_EMPTY_REQUEST_HEADERS_LIST,
ERROR_EMPTY_RESPONSE_HEADERS_LIST,
- ERROR_INVALID_HEADER_NAME
+ ERROR_INVALID_HEADER_NAME,
+ ERROR_INVALID_HEADER_VALUE,
+ ERROR_HEADER_VALUE_NOT_SPECIFIED,
+ ERROR_HEADER_VALUE_PRESENT,
+ ERROR_APPEND_REQUEST_HEADER_UNSUPPORTED
};
// Describes the ways in which updating dynamic rules can fail.
@@ -85,6 +89,39 @@ enum class UpdateDynamicRulesStatus {
kMaxValue = kErrorRegexRuleCountExceeded,
};
+// Describes the result of loading a single JSON Ruleset.
+// This is logged as part of UMA. Hence existing values should not be re-
+// numbered or deleted.
+enum class LoadRulesetResult {
+ // Ruleset loading succeeded.
+ kSuccess = 0,
+
+ // Ruleset loading failed since the provided path did not exist.
+ kErrorInvalidPath = 1,
+
+ // Ruleset loading failed due to a file read error.
+ kErrorCannotReadFile = 2,
+
+ // Ruleset loading failed due to a checksum mismatch.
+ kErrorChecksumMismatch = 3,
+
+ // Ruleset loading failed due to version header mismatch.
+ // TODO(karandeepb): This should be split into two cases:
+ // - When the indexed ruleset doesn't have the version header in the
+ // correct format.
+ // - When the indexed ruleset's version is not the same as that used by
+ // Chrome.
+ kErrorVersionMismatch = 4,
+
+ // Ruleset loading failed since the checksum for the ruleset wasn't found in
+ // prefs.
+ kErrorChecksumNotFound = 5,
+
+ // Magic constant used by histograms code. Should be equal to the largest enum
+ // value.
+ kMaxValue = kErrorChecksumNotFound,
+};
+
// Schemes which can be used as part of url transforms.
extern const char* const kAllowedTransformSchemes[4];
@@ -110,6 +147,10 @@ extern const char kErrorRegexTooLarge[];
extern const char kErrorRegexesTooLarge[];
extern const char kErrorNoHeaderListsSpecified[];
extern const char kErrorInvalidHeaderName[];
+extern const char kErrorInvalidHeaderValue[];
+extern const char kErrorNoHeaderValueSpecified[];
+extern const char kErrorHeaderValuePresent[];
+extern const char kErrorCannotAppendRequestHeader[];
extern const char kErrorListNotPassed[];
@@ -140,6 +181,7 @@ extern const char kManifestEnabledRulesCountHistogram[];
extern const char kUpdateDynamicRulesStatusHistogram[];
extern const char kReadDynamicRulesJSONStatusHistogram[];
extern const char kIsLargeRegexHistogram[];
+extern const char kLoadRulesetResultHistogram[];
// Placeholder text to use for getBadgeText extension function call, when the
// badge text is set to the DNR action count.
diff --git a/chromium/extensions/browser/api/declarative_net_request/extension_url_pattern_index_matcher.cc b/chromium/extensions/browser/api/declarative_net_request/extension_url_pattern_index_matcher.cc
index 3c2370d818b..71aa3281796 100644
--- a/chromium/extensions/browser/api/declarative_net_request/extension_url_pattern_index_matcher.cc
+++ b/chromium/extensions/browser/api/declarative_net_request/extension_url_pattern_index_matcher.cc
@@ -84,10 +84,19 @@ ExtensionUrlPatternIndexMatcher::GetAllowAllRequestsAction(
std::vector<RequestAction>
ExtensionUrlPatternIndexMatcher::GetModifyHeadersActions(
- const RequestParams& params) const {
+ const RequestParams& params,
+ base::Optional<uint64_t> min_priority) const {
+ // TODO(crbug.com/1083178): Plumb |min_priority| into UrlPatternIndexMatcher
+ // to prune more rules before matching on url filters.
std::vector<const flat_rule::UrlRule*> rules =
GetAllMatchingRules(params, flat::IndexType_modify_headers);
+ if (min_priority) {
+ base::EraseIf(rules, [&min_priority](const flat_rule::UrlRule* rule) {
+ return rule->priority() <= *min_priority;
+ });
+ }
+
return GetModifyHeadersActionsFromMetadata(params, rules, *metadata_list_);
}
diff --git a/chromium/extensions/browser/api/declarative_net_request/extension_url_pattern_index_matcher.h b/chromium/extensions/browser/api/declarative_net_request/extension_url_pattern_index_matcher.h
index ccf520ac914..a886abb681f 100644
--- a/chromium/extensions/browser/api/declarative_net_request/extension_url_pattern_index_matcher.h
+++ b/chromium/extensions/browser/api/declarative_net_request/extension_url_pattern_index_matcher.h
@@ -29,7 +29,8 @@ class ExtensionUrlPatternIndexMatcher final : public RulesetMatcherBase {
// RulesetMatcherBase override:
~ExtensionUrlPatternIndexMatcher() override;
std::vector<RequestAction> GetModifyHeadersActions(
- const RequestParams& params) const override;
+ const RequestParams& params,
+ base::Optional<uint64_t> min_priority) const override;
bool IsExtraHeadersMatcher() const override {
return is_extra_headers_matcher_;
}
diff --git a/chromium/extensions/browser/api/declarative_net_request/file_sequence_helper.cc b/chromium/extensions/browser/api/declarative_net_request/file_sequence_helper.cc
index f8018d903e7..9afe17d2dc4 100644
--- a/chromium/extensions/browser/api/declarative_net_request/file_sequence_helper.cc
+++ b/chromium/extensions/browser/api/declarative_net_request/file_sequence_helper.cc
@@ -18,7 +18,6 @@
#include "base/notreached.h"
#include "base/stl_util.h"
#include "base/strings/string_number_conversions.h"
-#include "base/task/post_task.h"
#include "content/public/browser/browser_task_traits.h"
#include "content/public/browser/browser_thread.h"
#include "extensions/browser/api/declarative_net_request/constants.h"
@@ -101,9 +100,8 @@ class ReindexHelper : public base::RefCountedThreadSafe<ReindexHelper> {
// In case of updates to the ruleset version, the change of ruleset checksum
// is expected.
- if (result.success &&
- ruleset->load_ruleset_result() ==
- RulesetMatcher::LoadRulesetResult::kLoadErrorVersionMismatch) {
+ if (result.success && ruleset->load_ruleset_result() ==
+ LoadRulesetResult::kErrorVersionMismatch) {
ruleset->set_new_checksum(result.ruleset_checksum);
// Also change the |expected_checksum| so that any subsequent load
@@ -131,21 +129,21 @@ class ReindexHelper : public base::RefCountedThreadSafe<ReindexHelper> {
DISALLOW_COPY_AND_ASSIGN(ReindexHelper);
};
-UpdateDynamicRulesStatus GetStatusForLoadRulesetError(
- RulesetMatcher::LoadRulesetResult result) {
- using Result = RulesetMatcher::LoadRulesetResult;
+UpdateDynamicRulesStatus GetUpdateDynamicRuleStatus(LoadRulesetResult result) {
switch (result) {
- case Result::kLoadSuccess:
+ case LoadRulesetResult::kSuccess:
break;
- case Result::kLoadErrorInvalidPath:
+ case LoadRulesetResult::kErrorInvalidPath:
return UpdateDynamicRulesStatus::kErrorCreateMatcher_InvalidPath;
- case Result::kLoadErrorFileRead:
+ case LoadRulesetResult::kErrorCannotReadFile:
return UpdateDynamicRulesStatus::kErrorCreateMatcher_FileReadError;
- case Result::kLoadErrorChecksumMismatch:
+ case LoadRulesetResult::kErrorChecksumMismatch:
return UpdateDynamicRulesStatus::kErrorCreateMatcher_ChecksumMismatch;
- case Result::kLoadErrorVersionMismatch:
+ case LoadRulesetResult::kErrorVersionMismatch:
return UpdateDynamicRulesStatus::kErrorCreateMatcher_VersionMismatch;
- case Result::kLoadResultMax:
+ case LoadRulesetResult::kErrorChecksumNotFound:
+ // Updating dynamic rules shouldn't require looking up checksum from
+ // prefs.
break;
}
@@ -207,7 +205,7 @@ bool GetNewDynamicRules(const RulesetSource& source,
int regex_rule_count = std::count_if(
new_rules->begin(), new_rules->end(),
[](const dnr_api::Rule& rule) { return !!rule.condition.regex_filter; });
- if (regex_rule_count > dnr_api::MAX_NUMBER_OF_REGEX_RULES) {
+ if (regex_rule_count > GetRegexRuleLimit()) {
*status = UpdateDynamicRulesStatus::kErrorRegexRuleCountExceeded;
*error = kDynamicRegexRuleCountExceeded;
return false;
@@ -336,23 +334,23 @@ std::unique_ptr<RulesetMatcher> RulesetInfo::TakeMatcher() {
return std::move(matcher_);
}
-RulesetMatcher::LoadRulesetResult RulesetInfo::load_ruleset_result() const {
- DCHECK(load_ruleset_result_);
+const base::Optional<LoadRulesetResult>& RulesetInfo::load_ruleset_result()
+ const {
// |matcher_| is valid only on success.
- DCHECK_EQ(load_ruleset_result_ == RulesetMatcher::kLoadSuccess, !!matcher_);
- return *load_ruleset_result_;
+ DCHECK_EQ(load_ruleset_result_ == LoadRulesetResult::kSuccess, !!matcher_);
+ return load_ruleset_result_;
}
void RulesetInfo::CreateVerifiedMatcher() {
DCHECK(expected_checksum_);
DCHECK(GetExtensionFileTaskRunner()->RunsTasksInCurrentSequence());
+ // Ensure we aren't calling this redundantly. If did_load_successfully()
+ // returns true, we should already have a valid RulesetMatcher.
+ DCHECK(!did_load_successfully());
+
load_ruleset_result_ = RulesetMatcher::CreateVerifiedMatcher(
source_, *expected_checksum_, &matcher_);
-
- UMA_HISTOGRAM_ENUMERATION(
- "Extensions.DeclarativeNetRequest.LoadRulesetResult",
- load_ruleset_result(), RulesetMatcher::kLoadResultMax);
}
LoadRequestData::LoadRequestData(ExtensionId extension_id)
@@ -371,7 +369,6 @@ void FileSequenceHelper::LoadRulesets(
LoadRequestData load_data,
LoadRulesetsUICallback ui_callback) const {
DCHECK(GetExtensionFileTaskRunner()->RunsTasksInCurrentSequence());
- DCHECK(!load_data.rulesets.empty());
bool success = true;
for (auto& ruleset : load_data.rulesets) {
@@ -381,10 +378,9 @@ void FileSequenceHelper::LoadRulesets(
if (success) {
// Set priority explicitly to avoid unwanted task priority inheritance.
- base::PostTask(
- FROM_HERE,
- {content::BrowserThread::UI, base::TaskPriority::USER_BLOCKING},
- base::BindOnce(std::move(ui_callback), std::move(load_data)));
+ content::GetUIThreadTaskRunner({base::TaskPriority::USER_BLOCKING})
+ ->PostTask(FROM_HERE, base::BindOnce(std::move(ui_callback),
+ std::move(load_data)));
return;
}
@@ -418,11 +414,10 @@ void FileSequenceHelper::UpdateDynamicRules(
base::UmaHistogramEnumeration(kUpdateDynamicRulesStatusHistogram, status);
// Set priority explicitly to avoid unwanted task priority inheritance.
- base::PostTask(
- FROM_HERE,
- {content::BrowserThread::UI, base::TaskPriority::USER_BLOCKING},
- base::BindOnce(std::move(ui_callback), std::move(load_data),
- std::move(error)));
+ content::GetUIThreadTaskRunner({base::TaskPriority::USER_BLOCKING})
+ ->PostTask(FROM_HERE,
+ base::BindOnce(std::move(ui_callback), std::move(load_data),
+ std::move(error)));
};
int new_ruleset_checksum = -1;
@@ -440,10 +435,10 @@ void FileSequenceHelper::UpdateDynamicRules(
dynamic_ruleset.set_expected_checksum(new_ruleset_checksum);
dynamic_ruleset.set_new_checksum(new_ruleset_checksum);
dynamic_ruleset.CreateVerifiedMatcher();
+ DCHECK(dynamic_ruleset.load_ruleset_result());
if (!dynamic_ruleset.did_load_successfully()) {
- status =
- GetStatusForLoadRulesetError(dynamic_ruleset.load_ruleset_result());
+ status = GetUpdateDynamicRuleStatus(*dynamic_ruleset.load_ruleset_result());
log_status_and_dispatch_callback(kInternalErrorUpdatingDynamicRules,
status);
return;
@@ -467,10 +462,9 @@ void FileSequenceHelper::OnRulesetsReindexed(LoadRulesetsUICallback ui_callback,
}
// The UI thread will handle success or failure.
- base::PostTask(
- FROM_HERE,
- {content::BrowserThread::UI, base::TaskPriority::USER_BLOCKING},
- base::BindOnce(std::move(ui_callback), std::move(load_data)));
+ content::GetUIThreadTaskRunner({base::TaskPriority::USER_BLOCKING})
+ ->PostTask(FROM_HERE,
+ base::BindOnce(std::move(ui_callback), std::move(load_data)));
}
} // namespace declarative_net_request
diff --git a/chromium/extensions/browser/api/declarative_net_request/file_sequence_helper.h b/chromium/extensions/browser/api/declarative_net_request/file_sequence_helper.h
index 4a9e77cb26f..c5e640d97c0 100644
--- a/chromium/extensions/browser/api/declarative_net_request/file_sequence_helper.h
+++ b/chromium/extensions/browser/api/declarative_net_request/file_sequence_helper.h
@@ -13,6 +13,7 @@
#include "base/macros.h"
#include "base/memory/weak_ptr.h"
#include "base/optional.h"
+#include "extensions/browser/api/declarative_net_request/constants.h"
#include "extensions/browser/api/declarative_net_request/ruleset_matcher.h"
#include "extensions/browser/api/declarative_net_request/ruleset_source.h"
#include "extensions/common/extension_id.h"
@@ -57,13 +58,13 @@ class RulesetInfo {
return reindexing_successful_;
}
- // Must be called after CreateVerifiedMatcher.
- RulesetMatcher::LoadRulesetResult load_ruleset_result() const;
+ // Returns the result of loading the ruleset. The return value is valid (not
+ // equal to base::nullopt) iff CreateVerifiedMatcher() has been called.
+ const base::Optional<LoadRulesetResult>& load_ruleset_result() const;
// Whether the ruleset loaded successfully.
bool did_load_successfully() const {
- return load_ruleset_result_ &&
- *load_ruleset_result_ == RulesetMatcher::kLoadSuccess;
+ return load_ruleset_result() == LoadRulesetResult::kSuccess;
}
// Must be invoked on the extension file task runner. Must only be called
@@ -78,7 +79,7 @@ class RulesetInfo {
// Stores the result of creating a verified matcher from the |source_|.
std::unique_ptr<RulesetMatcher> matcher_;
- base::Optional<RulesetMatcher::LoadRulesetResult> load_ruleset_result_;
+ base::Optional<LoadRulesetResult> load_ruleset_result_;
// The new checksum to be persisted to prefs. A new checksum should only be
// set in case of flatbuffer version mismatch.
@@ -114,7 +115,7 @@ class FileSequenceHelper {
// Loads rulesets for |load_data|. Invokes |ui_callback| on the UI thread once
// loading is done. Also tries to reindex the rulesets on failure.
- // |load_data.rulesets| must not be empty.
+ // This is a no-op if |load_data.rulesets| is empty.
using LoadRulesetsUICallback = base::OnceCallback<void(LoadRequestData)>;
void LoadRulesets(LoadRequestData load_data,
LoadRulesetsUICallback ui_callback) const;
diff --git a/chromium/extensions/browser/api/declarative_net_request/file_sequence_helper_unittest.cc b/chromium/extensions/browser/api/declarative_net_request/file_sequence_helper_unittest.cc
index 4f112cf8361..d8b18623c71 100644
--- a/chromium/extensions/browser/api/declarative_net_request/file_sequence_helper_unittest.cc
+++ b/chromium/extensions/browser/api/declarative_net_request/file_sequence_helper_unittest.cc
@@ -44,20 +44,23 @@ api::declarative_net_request::Rule GetAPIRule(const TestRule& rule) {
return result;
}
-struct LoadRulesetResult {
+struct TestLoadRulesetInfo {
bool has_new_checksum = false;
base::Optional<bool> reindexing_successful;
- RulesetMatcher::LoadRulesetResult load_result =
- RulesetMatcher::kLoadResultMax;
+ base::Optional<LoadRulesetResult> load_result;
};
struct TestCase {
explicit TestCase(RulesetSource source) : source(std::move(source)) {}
int checksum;
RulesetSource source;
- LoadRulesetResult expected_result;
+ TestLoadRulesetInfo expected_result;
};
+ExtensionId GenerateDummyExtensionID() {
+ return crx_file::id_util::GenerateId("dummy_extension");
+}
+
class FileSequenceHelperTest : public ExtensionsTest {
public:
FileSequenceHelperTest() = default;
@@ -115,9 +118,7 @@ class FileSequenceHelperTest : public ExtensionsTest {
}
void TestLoadRulesets(const std::vector<TestCase>& test_cases) {
- ExtensionId extension_id = crx_file::id_util::GenerateId("dummy_extension");
-
- LoadRequestData data(extension_id);
+ LoadRequestData data(GenerateDummyExtensionID());
for (const auto& test_case : test_cases) {
data.rulesets.emplace_back(test_case.source.Clone());
data.rulesets.back().set_expected_checksum(test_case.checksum);
@@ -133,16 +134,17 @@ class FileSequenceHelperTest : public ExtensionsTest {
for (size_t i = 0; i < data.rulesets.size(); i++) {
SCOPED_TRACE(base::StringPrintf("Testing ruleset %" PRIuS, i));
const RulesetInfo& ruleset = data.rulesets[i];
- const LoadRulesetResult& expected_result =
+ const TestLoadRulesetInfo& expected_result =
test_cases[i].expected_result;
EXPECT_EQ(expected_result.has_new_checksum,
ruleset.new_checksum().has_value());
EXPECT_EQ(expected_result.reindexing_successful,
ruleset.reindexing_successful());
+ ASSERT_TRUE(ruleset.load_ruleset_result());
EXPECT_EQ(expected_result.load_result,
ruleset.load_ruleset_result())
- << ruleset.load_ruleset_result();
+ << *ruleset.load_ruleset_result();
}
run_loop->Quit();
@@ -158,6 +160,22 @@ class FileSequenceHelperTest : public ExtensionsTest {
run_loop.Run();
}
+ void TestNoRulesetsToLoad() {
+ LoadRequestData data(GenerateDummyExtensionID());
+
+ base::RunLoop run_loop;
+ auto load_ruleset_callback = base::BindOnce(
+ [](base::RunLoop* run_loop, LoadRequestData data) { run_loop->Quit(); },
+ &run_loop);
+
+ auto load_ruleset_task = base::BindOnce(
+ &FileSequenceHelper::LoadRulesets, base::Unretained(helper_.get()),
+ std::move(data), std::move(load_ruleset_callback));
+ GetExtensionFileTaskRunner()->PostTask(FROM_HERE,
+ std::move(load_ruleset_task));
+ run_loop.Run();
+ }
+
// Initialize |num_rulesets| rulesets and returns the corresponding test
// cases.
std::vector<TestCase> InitializeRulesets(size_t num_rulesets) const {
@@ -174,7 +192,7 @@ class FileSequenceHelperTest : public ExtensionsTest {
&matcher, &test_case.checksum));
// Initially loading all the rulesets should succeed.
- test_case.expected_result.load_result = RulesetMatcher::kLoadSuccess;
+ test_case.expected_result.load_result = LoadRulesetResult::kSuccess;
}
return test_cases;
}
@@ -188,6 +206,10 @@ class FileSequenceHelperTest : public ExtensionsTest {
DISALLOW_COPY_AND_ASSIGN(FileSequenceHelperTest);
};
+TEST_F(FileSequenceHelperTest, NoRulesetsToLoad) {
+ TestNoRulesetsToLoad();
+}
+
TEST_F(FileSequenceHelperTest, IndexedRulesetDeleted) {
const size_t kNumRulesets = 3;
std::vector<TestCase> test_cases = InitializeRulesets(kNumRulesets);
@@ -219,9 +241,9 @@ TEST_F(FileSequenceHelperTest, ChecksumMismatch) {
test_cases[1].checksum--;
test_cases[2].checksum--;
test_cases[1].expected_result.load_result =
- RulesetMatcher::kLoadErrorChecksumMismatch;
+ LoadRulesetResult::kErrorChecksumMismatch;
test_cases[2].expected_result.load_result =
- RulesetMatcher::kLoadErrorChecksumMismatch;
+ LoadRulesetResult::kErrorChecksumMismatch;
test_cases[1].expected_result.reindexing_successful = false;
test_cases[2].expected_result.reindexing_successful = false;
@@ -242,7 +264,7 @@ TEST_F(FileSequenceHelperTest, RulesetFormatVersionMismatch) {
for (auto& test_case : test_cases) {
test_case.expected_result.reindexing_successful = true;
test_case.expected_result.has_new_checksum = true;
- test_case.expected_result.load_result = RulesetMatcher::kLoadSuccess;
+ test_case.expected_result.load_result = LoadRulesetResult::kSuccess;
}
TestLoadRulesets(test_cases);
@@ -264,10 +286,10 @@ TEST_F(FileSequenceHelperTest, JSONAndIndexedRulesetDeleted) {
test_cases[1].expected_result.reindexing_successful = false;
test_cases[0].expected_result.load_result =
- RulesetMatcher::kLoadErrorInvalidPath;
+ LoadRulesetResult::kErrorInvalidPath;
test_cases[1].expected_result.load_result =
- RulesetMatcher::kLoadErrorInvalidPath;
- test_cases[2].expected_result.load_result = RulesetMatcher::kLoadSuccess;
+ LoadRulesetResult::kErrorInvalidPath;
+ test_cases[2].expected_result.load_result = LoadRulesetResult::kSuccess;
TestLoadRulesets(test_cases);
}
diff --git a/chromium/extensions/browser/api/declarative_net_request/flat/extension_ruleset.fbs b/chromium/extensions/browser/api/declarative_net_request/flat/extension_ruleset.fbs
index 046cef8022d..f8dc1aac9f0 100644
--- a/chromium/extensions/browser/api/declarative_net_request/flat/extension_ruleset.fbs
+++ b/chromium/extensions/browser/api/declarative_net_request/flat/extension_ruleset.fbs
@@ -101,6 +101,8 @@ enum IndexType : ubyte {
/// The type of header operation for modifyHeaders rules. Corresponds to
/// extensions::api::declarative_net_request::HeaderOperation.
enum HeaderOperation : ubyte {
+ append,
+ set,
remove
}
@@ -112,6 +114,9 @@ table ModifyHeaderInfo {
/// case-insensitive, the header name is normalized by converting it to
/// lowercase.
header: string;
+ /// The value of the header to be set/appended. Should be specified only if
+ /// |operation| is append or set.
+ value: string;
}
/// Completely represents a rule with a regex filter.
diff --git a/chromium/extensions/browser/api/declarative_net_request/flat_ruleset_indexer.cc b/chromium/extensions/browser/api/declarative_net_request/flat_ruleset_indexer.cc
index ff9430d05f1..511e8c3f231 100644
--- a/chromium/extensions/browser/api/declarative_net_request/flat_ruleset_indexer.cc
+++ b/chromium/extensions/browser/api/declarative_net_request/flat_ruleset_indexer.cc
@@ -162,10 +162,17 @@ FlatVectorOffset<flat::ModifyHeaderInfo> BuildModifyHeaderInfoOffset(
for (const dnr_api::ModifyHeaderInfo& header_info : modify_header_list) {
flat::HeaderOperation operation = flat::HeaderOperation_remove;
+ FlatStringOffset header_value;
switch (header_info.operation) {
case dnr_api::HeaderOperation::HEADER_OPERATION_NONE:
- NOTREACHED();
+ case dnr_api::HEADER_OPERATION_APPEND:
+ operation = flat::HeaderOperation_append;
+ header_value = builder->CreateSharedString(*header_info.value);
+ break;
+ case dnr_api::HEADER_OPERATION_SET:
+ operation = flat::HeaderOperation_set;
+ header_value = builder->CreateSharedString(*header_info.value);
break;
case dnr_api::HEADER_OPERATION_REMOVE:
operation = flat::HeaderOperation_remove;
@@ -174,8 +181,8 @@ FlatVectorOffset<flat::ModifyHeaderInfo> BuildModifyHeaderInfoOffset(
FlatStringOffset header_name =
builder->CreateSharedString(base::ToLowerASCII(header_info.header));
- flat_modify_header_list.push_back(
- flat::CreateModifyHeaderInfo(*builder, operation, header_name));
+ flat_modify_header_list.push_back(flat::CreateModifyHeaderInfo(
+ *builder, operation, header_name, header_value));
}
return builder->CreateVector(flat_modify_header_list);
diff --git a/chromium/extensions/browser/api/declarative_net_request/flat_ruleset_indexer_unittest.cc b/chromium/extensions/browser/api/declarative_net_request/flat_ruleset_indexer_unittest.cc
index 24c08e49319..2769692c88f 100644
--- a/chromium/extensions/browser/api/declarative_net_request/flat_ruleset_indexer_unittest.cc
+++ b/chromium/extensions/browser/api/declarative_net_request/flat_ruleset_indexer_unittest.cc
@@ -60,7 +60,18 @@ std::vector<dnr_api::ModifyHeaderInfo> ToVector(
dnr_api::ModifyHeaderInfo header_info;
const flat::HeaderOperation flat_operation = flat_header_info->operation();
+ const flatbuffers::String* flat_value = flat_header_info->value();
switch (flat_operation) {
+ case flat::HeaderOperation_append:
+ header_info.operation = dnr_api::HEADER_OPERATION_APPEND;
+ DCHECK(flat_value);
+ header_info.value = std::make_unique<std::string>(ToString(flat_value));
+ break;
+ case flat::HeaderOperation_set:
+ header_info.operation = dnr_api::HEADER_OPERATION_SET;
+ DCHECK(flat_value);
+ header_info.value = std::make_unique<std::string>(ToString(flat_value));
+ break;
case flat::HeaderOperation_remove:
header_info.operation = dnr_api::HEADER_OPERATION_REMOVE;
break;
@@ -466,12 +477,18 @@ TEST_F(FlatRulesetIndexerTest, MultipleRules) {
// Modify headers rules.
std::vector<dnr_api::ModifyHeaderInfo> request_headers_1;
- request_headers_1.push_back(
- CreateModifyHeaderInfo(dnr_api::HEADER_OPERATION_REMOVE, "cookie"));
+ request_headers_1.push_back(CreateModifyHeaderInfo(
+ dnr_api::HEADER_OPERATION_SET, "cookie", "sample-cookie"));
std::vector<dnr_api::ModifyHeaderInfo> response_headers_1;
- response_headers_1.push_back(
- CreateModifyHeaderInfo(dnr_api::HEADER_OPERATION_REMOVE, "set-cookie"));
+ response_headers_1.push_back(CreateModifyHeaderInfo(
+ dnr_api::HEADER_OPERATION_REMOVE, "set-cookie", base::nullopt));
+
+ response_headers_1.push_back(CreateModifyHeaderInfo(
+ dnr_api::HEADER_OPERATION_APPEND, "custom-1", "value-1"));
+
+ response_headers_1.push_back(CreateModifyHeaderInfo(
+ dnr_api::HEADER_OPERATION_SET, "custom-2", "value-2"));
rules_to_index.push_back(CreateIndexedRule(
23, kMinValidPriority, flat_rule::OptionFlag_IS_CASE_INSENSITIVE,
@@ -482,8 +499,8 @@ TEST_F(FlatRulesetIndexerTest, MultipleRules) {
std::move(request_headers_1), std::move(response_headers_1)));
std::vector<dnr_api::ModifyHeaderInfo> request_headers_2;
- request_headers_2.push_back(
- CreateModifyHeaderInfo(dnr_api::HEADER_OPERATION_REMOVE, "referer"));
+ request_headers_2.push_back(CreateModifyHeaderInfo(
+ dnr_api::HEADER_OPERATION_REMOVE, "referer", base::nullopt));
rules_to_index.push_back(CreateIndexedRule(
24, kMinValidPriority, flat_rule::OptionFlag_IS_CASE_INSENSITIVE,
@@ -544,8 +561,10 @@ TEST_F(FlatRulesetIndexerTest, RegexRules) {
// Modify headers rule.
std::vector<dnr_api::ModifyHeaderInfo> request_headers;
- request_headers.push_back(
- CreateModifyHeaderInfo(dnr_api::HEADER_OPERATION_REMOVE, "referer"));
+ request_headers.push_back(CreateModifyHeaderInfo(
+ dnr_api::HEADER_OPERATION_REMOVE, "referer", base::nullopt));
+ request_headers.push_back(CreateModifyHeaderInfo(
+ dnr_api::HEADER_OPERATION_SET, "cookie", "sample-cookie"));
rules_to_index.push_back(CreateIndexedRule(
21, kMinValidPriority, flat_rule::OptionFlag_IS_CASE_INSENSITIVE,
flat_rule::ElementType_SUBDOCUMENT, flat_rule::ActivationType_NONE,
diff --git a/chromium/extensions/browser/api/declarative_net_request/index_helper.cc b/chromium/extensions/browser/api/declarative_net_request/index_helper.cc
index e573e2a0364..cfe9d0f36f6 100644
--- a/chromium/extensions/browser/api/declarative_net_request/index_helper.cc
+++ b/chromium/extensions/browser/api/declarative_net_request/index_helper.cc
@@ -11,6 +11,7 @@
#include "base/metrics/histogram_macros.h"
#include "base/time/time.h"
#include "extensions/browser/api/declarative_net_request/constants.h"
+#include "extensions/browser/api/declarative_net_request/utils.h"
#include "extensions/common/api/declarative_net_request.h"
#include "extensions/common/extension.h"
#include "extensions/common/manifest.h"
@@ -45,7 +46,7 @@ IndexHelper::Result CombineResults(
// Per-ruleset limits should have been enforced during ruleset indexing.
DCHECK_LE(index_result.regex_rules_count,
- static_cast<size_t>(dnr_api::MAX_NUMBER_OF_REGEX_RULES));
+ static_cast<size_t>(GetRegexRuleLimit()));
DCHECK_LE(index_result.rules_count, source->rule_count_limit());
if (!index_result.success) {
@@ -72,12 +73,12 @@ IndexHelper::Result CombineResults(
// Raise an install warning if the enabled rule count exceeds the API limits.
// We don't raise a hard error to maintain forwards compatibility.
- if (enabled_rules_count > static_cast<size_t>(dnr_api::MAX_NUMBER_OF_RULES)) {
+ if (enabled_rules_count > static_cast<size_t>(GetStaticRuleLimit())) {
total_result.warnings.emplace_back(
kEnabledRuleCountExceeded, manifest_keys::kDeclarativeNetRequestKey,
manifest_keys::kDeclarativeRuleResourcesKey);
} else if (enabled_regex_rules_count >
- static_cast<size_t>(dnr_api::MAX_NUMBER_OF_REGEX_RULES)) {
+ static_cast<size_t>(GetRegexRuleLimit())) {
total_result.warnings.emplace_back(
kEnabledRegexRuleCountExceeded,
manifest_keys::kDeclarativeNetRequestKey,
diff --git a/chromium/extensions/browser/api/declarative_net_request/indexed_rule.cc b/chromium/extensions/browser/api/declarative_net_request/indexed_rule.cc
index 2181175b7e5..330459e4708 100644
--- a/chromium/extensions/browser/api/declarative_net_request/indexed_rule.cc
+++ b/chromium/extensions/browser/api/declarative_net_request/indexed_rule.cc
@@ -436,6 +436,25 @@ ParseResult ValidateHeaders(
for (const auto& header_info : headers) {
if (!net::HttpUtil::IsValidHeaderName(header_info.header))
return ParseResult::ERROR_INVALID_HEADER_NAME;
+
+ // Ensure that request headers cannot be appended.
+ if (are_request_headers &&
+ header_info.operation == dnr_api::HEADER_OPERATION_APPEND) {
+ return ParseResult::ERROR_APPEND_REQUEST_HEADER_UNSUPPORTED;
+ }
+
+ if (header_info.value) {
+ if (!net::HttpUtil::IsValidHeaderValue(*header_info.value))
+ return ParseResult::ERROR_INVALID_HEADER_VALUE;
+
+ // Check that a remove operation must not specify a value.
+ if (header_info.operation == dnr_api::HEADER_OPERATION_REMOVE)
+ return ParseResult::ERROR_HEADER_VALUE_PRESENT;
+ } else if (header_info.operation == dnr_api::HEADER_OPERATION_APPEND ||
+ header_info.operation == dnr_api::HEADER_OPERATION_SET) {
+ // Check that an append or set operation must specify a value.
+ return ParseResult::ERROR_HEADER_VALUE_NOT_SPECIFIED;
+ }
}
return ParseResult::SUCCESS;
diff --git a/chromium/extensions/browser/api/declarative_net_request/indexed_rule_unittest.cc b/chromium/extensions/browser/api/declarative_net_request/indexed_rule_unittest.cc
index 1821cdd4e5a..04a1ff6a796 100644
--- a/chromium/extensions/browser/api/declarative_net_request/indexed_rule_unittest.cc
+++ b/chromium/extensions/browser/api/declarative_net_request/indexed_rule_unittest.cc
@@ -766,6 +766,7 @@ TEST_F(IndexedRuleTest, ModifyHeadersParsing) {
struct RawHeaderInfo {
dnr_api::HeaderOperation operation;
std::string header;
+ base::Optional<std::string> value;
};
using RawHeaderInfoList = std::vector<RawHeaderInfo>;
@@ -785,7 +786,8 @@ TEST_F(IndexedRuleTest, ModifyHeadersParsing) {
// Raise an error if the request or response headers list is specified,
// but empty.
{RawHeaderInfoList(),
- RawHeaderInfoList({{dnr_api::HEADER_OPERATION_REMOVE, "set-cookie"}}),
+ RawHeaderInfoList(
+ {{dnr_api::HEADER_OPERATION_REMOVE, "set-cookie", base::nullopt}}),
ParseResult::ERROR_EMPTY_REQUEST_HEADERS_LIST},
{base::nullopt, RawHeaderInfoList(),
@@ -794,21 +796,51 @@ TEST_F(IndexedRuleTest, ModifyHeadersParsing) {
// Raise an error if a header list contains an empty or invalid header
// name.
{base::nullopt,
- RawHeaderInfoList({{dnr_api::HEADER_OPERATION_REMOVE, ""}}),
+ RawHeaderInfoList(
+ {{dnr_api::HEADER_OPERATION_REMOVE, "", base::nullopt}}),
ParseResult::ERROR_INVALID_HEADER_NAME},
{base::nullopt,
- RawHeaderInfoList({{dnr_api::HEADER_OPERATION_REMOVE, "<<invalid>>"}}),
+ RawHeaderInfoList(
+ {{dnr_api::HEADER_OPERATION_REMOVE, "<<invalid>>", base::nullopt}}),
ParseResult::ERROR_INVALID_HEADER_NAME},
- // Parsing should succeed if only one non-empty header list is specified.
- {RawHeaderInfoList({{dnr_api::HEADER_OPERATION_REMOVE, "cookie"}}),
+ // Raise an error if a header list contains an invalid header value.
+ {base::nullopt,
+ RawHeaderInfoList({{dnr_api::HEADER_OPERATION_APPEND, "set-cookie",
+ "invalid\nvalue"}}),
+ ParseResult::ERROR_INVALID_HEADER_VALUE},
+
+ // Raise an error if a header value is specified for a remove rule.
+ {RawHeaderInfoList(
+ {{dnr_api::HEADER_OPERATION_REMOVE, "cookie", "remove"}}),
+ base::nullopt, ParseResult::ERROR_HEADER_VALUE_PRESENT},
+
+ // Raise an error if no header value is specified for an append or set
+ // rule.
+ {RawHeaderInfoList(
+ {{dnr_api::HEADER_OPERATION_SET, "cookie", base::nullopt}}),
+ base::nullopt, ParseResult::ERROR_HEADER_VALUE_NOT_SPECIFIED},
+
+ {base::nullopt,
+ RawHeaderInfoList(
+ {{dnr_api::HEADER_OPERATION_APPEND, "set-cookie", base::nullopt}}),
+ ParseResult::ERROR_HEADER_VALUE_NOT_SPECIFIED},
+
+ // Raise an error if a rule specifies a request header to be appended.
+ {RawHeaderInfoList(
+ {{dnr_api::HEADER_OPERATION_APPEND, "cookie", "cookie-value"}}),
+ base::nullopt, ParseResult::ERROR_APPEND_REQUEST_HEADER_UNSUPPORTED},
+
+ {RawHeaderInfoList(
+ {{dnr_api::HEADER_OPERATION_REMOVE, "cookie", base::nullopt},
+ {dnr_api::HEADER_OPERATION_SET, "referer", ""}}),
base::nullopt, ParseResult::SUCCESS},
- // Parsing should succeed if both header lists are specified and
- // non-empty.
- {RawHeaderInfoList({{dnr_api::HEADER_OPERATION_REMOVE, "referer"}}),
- RawHeaderInfoList({{dnr_api::HEADER_OPERATION_REMOVE, "set-cookie"}}),
+ {RawHeaderInfoList(
+ {{dnr_api::HEADER_OPERATION_REMOVE, "referer", base::nullopt}}),
+ RawHeaderInfoList(
+ {{dnr_api::HEADER_OPERATION_APPEND, "set-cookie", "abcd"}}),
ParseResult::SUCCESS},
};
@@ -821,11 +853,11 @@ TEST_F(IndexedRuleTest, ModifyHeadersParsing) {
if (cases[i].request_headers) {
rule.action.request_headers = std::make_unique<ModifyHeaderInfoList>();
for (auto header : *cases[i].request_headers) {
- rule.action.request_headers->push_back(
- CreateModifyHeaderInfo(header.operation, header.header));
+ rule.action.request_headers->push_back(CreateModifyHeaderInfo(
+ header.operation, header.header, header.value));
- expected_request_headers.push_back(
- CreateModifyHeaderInfo(header.operation, header.header));
+ expected_request_headers.push_back(CreateModifyHeaderInfo(
+ header.operation, header.header, header.value));
}
}
@@ -833,11 +865,11 @@ TEST_F(IndexedRuleTest, ModifyHeadersParsing) {
if (cases[i].response_headers) {
rule.action.response_headers = std::make_unique<ModifyHeaderInfoList>();
for (auto header : *cases[i].response_headers) {
- rule.action.response_headers->push_back(
- CreateModifyHeaderInfo(header.operation, header.header));
+ rule.action.response_headers->push_back(CreateModifyHeaderInfo(
+ header.operation, header.header, header.value));
- expected_response_headers.push_back(
- CreateModifyHeaderInfo(header.operation, header.header));
+ expected_response_headers.push_back(CreateModifyHeaderInfo(
+ header.operation, header.header, header.value));
}
}
diff --git a/chromium/extensions/browser/api/declarative_net_request/indexed_ruleset_format_version_unittest.cc b/chromium/extensions/browser/api/declarative_net_request/indexed_ruleset_format_version_unittest.cc
index ea29e068875..bf3f591949b 100644
--- a/chromium/extensions/browser/api/declarative_net_request/indexed_ruleset_format_version_unittest.cc
+++ b/chromium/extensions/browser/api/declarative_net_request/indexed_ruleset_format_version_unittest.cc
@@ -64,11 +64,14 @@ enum IndexType : ubyte {
count
}
enum HeaderOperation : ubyte {
+ append,
+ set,
remove
}
table ModifyHeaderInfo {
operation: HeaderOperation;
header: string;
+ value: string;
}
table RegexRule {
url_rule: url_pattern_index.flat.UrlRule;
@@ -146,7 +149,7 @@ TEST_F(IndexedRulesetFormatVersionTest, CheckVersionUpdated) {
EXPECT_EQ(StripCommentsAndWhitespace(kFlatbufferSchemaExpected),
StripCommentsAndWhitespace(flatbuffer_schema))
<< "Schema change detected; update this test and the schema version.";
- EXPECT_EQ(17, GetIndexedRulesetFormatVersionForTesting())
+ EXPECT_EQ(18, GetIndexedRulesetFormatVersionForTesting())
<< "Update this test if you update the schema version.";
}
diff --git a/chromium/extensions/browser/api/declarative_net_request/parse_info.cc b/chromium/extensions/browser/api/declarative_net_request/parse_info.cc
index 3069695505b..7c0c1474502 100644
--- a/chromium/extensions/browser/api/declarative_net_request/parse_info.cc
+++ b/chromium/extensions/browser/api/declarative_net_request/parse_info.cc
@@ -137,6 +137,18 @@ std::string GetError(ParseResult error_reason, const int* rule_id) {
case ParseResult::ERROR_INVALID_HEADER_NAME:
return ErrorUtils::FormatErrorMessage(kErrorInvalidHeaderName,
base::NumberToString(*rule_id));
+ case ParseResult::ERROR_INVALID_HEADER_VALUE:
+ return ErrorUtils::FormatErrorMessage(kErrorInvalidHeaderValue,
+ base::NumberToString(*rule_id));
+ case ParseResult::ERROR_HEADER_VALUE_NOT_SPECIFIED:
+ return ErrorUtils::FormatErrorMessage(kErrorNoHeaderValueSpecified,
+ base::NumberToString(*rule_id));
+ case ParseResult::ERROR_HEADER_VALUE_PRESENT:
+ return ErrorUtils::FormatErrorMessage(kErrorHeaderValuePresent,
+ base::NumberToString(*rule_id));
+ case ParseResult::ERROR_APPEND_REQUEST_HEADER_UNSUPPORTED:
+ return ErrorUtils::FormatErrorMessage(kErrorCannotAppendRequestHeader,
+ base::NumberToString(*rule_id));
case ParseResult::ERROR_REGEX_TOO_LARGE:
// These rules are ignored while indexing and so won't cause an error.
break;
diff --git a/chromium/extensions/browser/api/declarative_net_request/parse_info.h b/chromium/extensions/browser/api/declarative_net_request/parse_info.h
index 1bad05c35e3..2d2124a5ae8 100644
--- a/chromium/extensions/browser/api/declarative_net_request/parse_info.h
+++ b/chromium/extensions/browser/api/declarative_net_request/parse_info.h
@@ -9,7 +9,7 @@
#include <string>
#include <vector>
-#include "base/logging.h"
+#include "base/check.h"
#include "base/optional.h"
#include "extensions/browser/api/declarative_net_request/constants.h"
diff --git a/chromium/extensions/browser/api/declarative_net_request/regex_rules_matcher.cc b/chromium/extensions/browser/api/declarative_net_request/regex_rules_matcher.cc
index f8907712101..18c1cdc4581 100644
--- a/chromium/extensions/browser/api/declarative_net_request/regex_rules_matcher.cc
+++ b/chromium/extensions/browser/api/declarative_net_request/regex_rules_matcher.cc
@@ -6,6 +6,7 @@
#include <algorithm>
+#include "base/logging.h"
#include "base/strings/string_util.h"
#include "base/strings/stringprintf.h"
#include "components/url_pattern_index/url_pattern_index.h"
@@ -96,13 +97,20 @@ RegexRulesMatcher::RegexRulesMatcher(const ExtensionId& extension_id,
RegexRulesMatcher::~RegexRulesMatcher() = default;
std::vector<RequestAction> RegexRulesMatcher::GetModifyHeadersActions(
- const RequestParams& params) const {
+ const RequestParams& params,
+ base::Optional<uint64_t> min_priority) const {
const std::vector<RegexRuleInfo>& potential_matches =
GetPotentialMatches(params);
std::vector<const flat_rule::UrlRule*> rules;
for (const RegexRuleInfo& info : potential_matches) {
- if (info.regex_rule->action_type() == flat::ActionType_modify_headers &&
+ // Check for the rule's priority iff |min_priority| is specified.
+ bool has_sufficient_priority =
+ !min_priority ||
+ info.regex_rule->url_rule()->priority() > *min_priority;
+
+ if (has_sufficient_priority &&
+ info.regex_rule->action_type() == flat::ActionType_modify_headers &&
re2::RE2::PartialMatch(params.url->spec(), *info.regex)) {
rules.push_back(info.regex_rule->url_rule());
}
diff --git a/chromium/extensions/browser/api/declarative_net_request/regex_rules_matcher.h b/chromium/extensions/browser/api/declarative_net_request/regex_rules_matcher.h
index 5db5980e752..85b75bdbb5b 100644
--- a/chromium/extensions/browser/api/declarative_net_request/regex_rules_matcher.h
+++ b/chromium/extensions/browser/api/declarative_net_request/regex_rules_matcher.h
@@ -58,7 +58,8 @@ class RegexRulesMatcher final : public RulesetMatcherBase {
// RulesetMatcherBase override:
~RegexRulesMatcher() override;
std::vector<RequestAction> GetModifyHeadersActions(
- const RequestParams& params) const override;
+ const RequestParams& params,
+ base::Optional<uint64_t> min_priority) const override;
bool IsExtraHeadersMatcher() const override {
return is_extra_headers_matcher_;
}
diff --git a/chromium/extensions/browser/api/declarative_net_request/request_action.cc b/chromium/extensions/browser/api/declarative_net_request/request_action.cc
index aab953ca723..d6e19391b0f 100644
--- a/chromium/extensions/browser/api/declarative_net_request/request_action.cc
+++ b/chromium/extensions/browser/api/declarative_net_request/request_action.cc
@@ -4,6 +4,7 @@
#include "extensions/browser/api/declarative_net_request/request_action.h"
+#include <tuple>
#include <utility>
#include "extensions/browser/api/declarative_net_request/flat/extension_ruleset_generated.h"
@@ -20,6 +21,10 @@ namespace dnr_api = api::declarative_net_request;
dnr_api::HeaderOperation ConvertFlatHeaderOperation(
flat::HeaderOperation operation) {
switch (operation) {
+ case flat::HeaderOperation_append:
+ return dnr_api::HEADER_OPERATION_APPEND;
+ case flat::HeaderOperation_set:
+ return dnr_api::HEADER_OPERATION_SET;
case flat::HeaderOperation_remove:
return dnr_api::HEADER_OPERATION_REMOVE;
}
@@ -28,12 +33,27 @@ dnr_api::HeaderOperation ConvertFlatHeaderOperation(
} // namespace
RequestAction::HeaderInfo::HeaderInfo(std::string header,
- dnr_api::HeaderOperation operation)
- : header(std::move(header)), operation(operation) {}
+ dnr_api::HeaderOperation operation,
+ base::Optional<std::string> value)
+ : header(std::move(header)),
+ operation(operation),
+ value(std::move(value)) {}
RequestAction::HeaderInfo::HeaderInfo(const flat::ModifyHeaderInfo& info)
: header(CreateString<std::string>(*info.header())),
- operation(ConvertFlatHeaderOperation(info.operation())) {}
+ operation(ConvertFlatHeaderOperation(info.operation())) {
+ if (info.value())
+ value = CreateString<std::string>(*info.value());
+}
+
+RequestAction::HeaderInfo::~HeaderInfo() = default;
+RequestAction::HeaderInfo::HeaderInfo(const RequestAction::HeaderInfo& other) =
+ default;
+RequestAction::HeaderInfo& RequestAction::HeaderInfo::operator=(
+ const RequestAction::HeaderInfo& other) = default;
+RequestAction::HeaderInfo::HeaderInfo(RequestAction::HeaderInfo&&) = default;
+RequestAction::HeaderInfo& RequestAction::HeaderInfo::operator=(
+ RequestAction::HeaderInfo&&) = default;
RequestAction::RequestAction(RequestAction::Type type,
uint32_t rule_id,
@@ -56,6 +76,16 @@ RequestAction RequestAction::Clone() const {
RequestAction::RequestAction(const RequestAction&) = default;
+bool operator<(const RequestAction& lhs, const RequestAction& rhs) {
+ return std::tie(lhs.index_priority, lhs.ruleset_id, lhs.rule_id) <
+ std::tie(rhs.index_priority, rhs.ruleset_id, rhs.rule_id);
+}
+
+bool operator>(const RequestAction& lhs, const RequestAction& rhs) {
+ return std::tie(lhs.index_priority, lhs.ruleset_id, lhs.rule_id) >
+ std::tie(rhs.index_priority, rhs.ruleset_id, rhs.rule_id);
+}
+
base::Optional<RequestAction> GetMaxPriorityAction(
base::Optional<RequestAction> lhs,
base::Optional<RequestAction> rhs) {
@@ -63,8 +93,7 @@ base::Optional<RequestAction> GetMaxPriorityAction(
return rhs;
if (!rhs)
return lhs;
- return lhs->index_priority >= rhs->index_priority ? std::move(lhs)
- : std::move(rhs);
+ return lhs > rhs ? std::move(lhs) : std::move(rhs);
}
} // namespace declarative_net_request
diff --git a/chromium/extensions/browser/api/declarative_net_request/request_action.h b/chromium/extensions/browser/api/declarative_net_request/request_action.h
index 7bc7be29dbd..96781f28262 100644
--- a/chromium/extensions/browser/api/declarative_net_request/request_action.h
+++ b/chromium/extensions/browser/api/declarative_net_request/request_action.h
@@ -29,12 +29,20 @@ struct RequestAction {
// This is used instead of ModifyHeaderInfo so it can be copied in Clone().
struct HeaderInfo {
HeaderInfo(std::string header,
- api::declarative_net_request::HeaderOperation operation);
+ api::declarative_net_request::HeaderOperation operation,
+ base::Optional<std::string> value);
explicit HeaderInfo(const flat::ModifyHeaderInfo& info);
+ ~HeaderInfo();
+ HeaderInfo(const HeaderInfo& other);
+ HeaderInfo& operator=(const HeaderInfo& other);
+ HeaderInfo(HeaderInfo&&);
+ HeaderInfo& operator=(HeaderInfo&&);
// The name of the header to be modified, specified in lowercase.
std::string header;
api::declarative_net_request::HeaderOperation operation;
+ // The value for |header| to be appended or set.
+ base::Optional<std::string> value;
};
enum class Type {
@@ -112,6 +120,11 @@ struct RequestAction {
RequestAction(const RequestAction&);
};
+// Compares RequestAction by |index_priority|, breaking ties by |ruleset_id|
+// then |rule_id|.
+bool operator<(const RequestAction& lhs, const RequestAction& rhs);
+bool operator>(const RequestAction& lhs, const RequestAction& rhs);
+
base::Optional<RequestAction> GetMaxPriorityAction(
base::Optional<RequestAction> lhs,
base::Optional<RequestAction> rhs);
diff --git a/chromium/extensions/browser/api/declarative_net_request/request_params.h b/chromium/extensions/browser/api/declarative_net_request/request_params.h
index bcb169e8a2b..0b1eb4e5ee1 100644
--- a/chromium/extensions/browser/api/declarative_net_request/request_params.h
+++ b/chromium/extensions/browser/api/declarative_net_request/request_params.h
@@ -22,7 +22,7 @@ namespace extensions {
struct WebRequestInfo;
namespace declarative_net_request {
-class RulesetMatcher;
+class CompositeMatcher;
// Struct to hold parameters for a network request.
struct RequestParams {
@@ -44,10 +44,12 @@ struct RequestParams {
// ID of the parent RenderFrameHost.
content::GlobalFrameRoutingId parent_routing_id;
- // A map from RulesetMatchers to whether it has a matching allow or
- // allowAllRequests rule. Used as a cache to prevent additional calls to
+ // A map from CompositeMatcher to the priority of its highest priority
+ // matching allow or allowAllRequests rule if there is one, or base::nullopt
+ // otherwise. Used as a cache to prevent additional calls to
// GetBeforeRequestAction.
- mutable base::flat_map<const RulesetMatcher*, bool> allow_rule_cache;
+ mutable base::flat_map<const CompositeMatcher*, base::Optional<uint64_t>>
+ allow_rule_max_priority;
// Lower cased url, used for regex matching. Cached for performance.
mutable base::Optional<std::string> lower_cased_url_spec;
diff --git a/chromium/extensions/browser/api/declarative_net_request/rules_monitor_service.cc b/chromium/extensions/browser/api/declarative_net_request/rules_monitor_service.cc
index 1b00322037b..6e1123b8fe9 100644
--- a/chromium/extensions/browser/api/declarative_net_request/rules_monitor_service.cc
+++ b/chromium/extensions/browser/api/declarative_net_request/rules_monitor_service.cc
@@ -14,6 +14,7 @@
#include "base/lazy_instance.h"
#include "base/location.h"
#include "base/memory/ptr_util.h"
+#include "base/metrics/histogram_macros.h"
#include "base/stl_util.h"
#include "base/task/post_task.h"
#include "base/threading/thread_restrictions.h"
@@ -55,6 +56,10 @@ bool RulesetInfoCompareByID(const RulesetInfo& lhs, const RulesetInfo& rhs) {
return lhs.source().id() < rhs.source().id();
}
+void LogLoadRulesetResult(LoadRulesetResult result) {
+ UMA_HISTOGRAM_ENUMERATION(kLoadRulesetResultHistogram, result);
+}
+
} // namespace
// Helper to bridge tasks to FileSequenceHelper. Lives on the UI thread.
@@ -223,6 +228,7 @@ void RulesMonitorService::OnExtensionLoaded(
if (!prefs_->GetDNRStaticRulesetChecksum(extension->id(), source.id(),
&expected_ruleset_checksum)) {
// This might happen on prefs corruption.
+ LogLoadRulesetResult(LoadRulesetResult::kErrorChecksumNotFound);
ruleset_failed_to_load = true;
continue;
}
@@ -306,9 +312,8 @@ void RulesMonitorService::OnExtensionUninstalled(
RulesetSource::CreateDynamic(browser_context, extension->id());
DCHECK_EQ(source.json_path().DirName(), source.indexed_path().DirName());
GetExtensionFileTaskRunner()->PostTask(
- FROM_HERE,
- base::BindOnce(base::IgnoreResult(&base::DeleteFile),
- source.json_path().DirName(), false /* recursive */));
+ FROM_HERE, base::BindOnce(base::GetDeleteFileCallback(),
+ source.json_path().DirName()));
}
void RulesMonitorService::UpdateDynamicRulesInternal(
@@ -356,21 +361,16 @@ void RulesMonitorService::UpdateEnabledStaticRulesetsInternal(
LoadRequestData load_data(extension_id);
- // Don't hop to the file sequence if there are no rulesets to load.
- // TODO(karandeepb): Hop to the file sequence in this case as well to ensure
- // that subsequent updateEnabledRulesets calls complete in FIFO order.
- if (ids_to_enable.empty()) {
- OnNewStaticRulesetsLoaded(std::move(callback), std::move(ids_to_disable),
- std::move(ids_to_enable), std::move(load_data));
- return;
- }
+ // Don't short-circuit the case of |ids_to_enable| being empty by calling
+ // OnNewStaticRulesetsLoaded directly. This can interfere with the expected
+ // FIFO ordering of updateEnabledRulesets calls.
int expected_ruleset_checksum = -1;
for (const RulesetID& id_to_enable : ids_to_enable) {
if (!prefs_->GetDNRStaticRulesetChecksum(extension_id, id_to_enable,
&expected_ruleset_checksum)) {
// This might happen on prefs corruption.
- // TODO(crbug.com/754526): Log metrics on how often this happens.
+ LogLoadRulesetResult(LoadRulesetResult::kErrorChecksumNotFound);
std::move(callback).Run(kInternalErrorUpdatingEnabledRulesets);
return;
}
@@ -405,7 +405,7 @@ void RulesMonitorService::OnInitialRulesetsLoaded(LoadRequestData load_data) {
if (test_observer_)
test_observer_->OnRulesetLoadComplete(load_data.extension_id);
- UpdateRulesetChecksumsIfNeeded(load_data);
+ LogMetricsAndUpdateChecksumsIfNeeded(load_data);
// It's possible that the extension has been disabled since the initial load
// ruleset request. If it's disabled, do nothing.
@@ -441,7 +441,7 @@ void RulesMonitorService::OnInitialRulesetsLoaded(LoadRequestData load_data) {
// Per-ruleset limits should have been enforced during
// indexing/installation.
DCHECK_LE(matcher->GetRegexRulesCount(),
- static_cast<size_t>(dnr_api::MAX_NUMBER_OF_REGEX_RULES));
+ static_cast<size_t>(GetRegexRuleLimit()));
DCHECK_LE(matcher->GetRulesCount(), ruleset.source().rule_count_limit());
if (ruleset.source().is_dynamic_ruleset()) {
@@ -450,13 +450,12 @@ void RulesMonitorService::OnInitialRulesetsLoaded(LoadRequestData load_data) {
}
size_t new_rules_count = static_rules_count + matcher->GetRulesCount();
- if (new_rules_count > static_cast<size_t>(dnr_api::MAX_NUMBER_OF_RULES))
+ if (new_rules_count > static_cast<size_t>(GetStaticRuleLimit()))
continue;
size_t new_regex_rules_count =
static_regex_rules_count + matcher->GetRegexRulesCount();
- if (new_regex_rules_count >
- static_cast<size_t>(dnr_api::MAX_NUMBER_OF_REGEX_RULES)) {
+ if (new_regex_rules_count > static_cast<size_t>(GetRegexRuleLimit())) {
continue;
}
@@ -482,7 +481,7 @@ void RulesMonitorService::OnNewStaticRulesetsLoaded(
std::set<RulesetID> ids_to_disable,
std::set<RulesetID> ids_to_enable,
LoadRequestData load_data) {
- UpdateRulesetChecksumsIfNeeded(load_data);
+ LogMetricsAndUpdateChecksumsIfNeeded(load_data);
// It's possible that the extension has been disabled since the initial
// request. If it's disabled, return early.
@@ -523,7 +522,6 @@ void RulesMonitorService::OnNewStaticRulesetsLoaded(
new_matchers.reserve(load_data.rulesets.size());
for (RulesetInfo& ruleset : load_data.rulesets) {
if (!ruleset.did_load_successfully()) {
- // TODO(crbug.com/754526): Log metrics on how often this happens.
std::move(callback).Run(kInternalErrorUpdatingEnabledRulesets);
return;
}
@@ -533,7 +531,7 @@ void RulesMonitorService::OnNewStaticRulesetsLoaded(
// Per-ruleset limits should have been enforced during
// indexing/installation.
DCHECK_LE(matcher->GetRegexRulesCount(),
- static_cast<size_t>(dnr_api::MAX_NUMBER_OF_REGEX_RULES));
+ static_cast<size_t>(GetRegexRuleLimit()));
DCHECK_LE(matcher->GetRulesCount(), ruleset.source().rule_count_limit());
static_rules_count += matcher->GetRulesCount();
@@ -541,13 +539,12 @@ void RulesMonitorService::OnNewStaticRulesetsLoaded(
new_matchers.push_back(std::move(matcher));
}
- if (static_rules_count > static_cast<size_t>(dnr_api::MAX_NUMBER_OF_RULES)) {
+ if (static_rules_count > static_cast<size_t>(GetStaticRuleLimit())) {
std::move(callback).Run(kEnabledRulesetsRuleCountExceeded);
return;
}
- if (static_regex_rules_count >
- static_cast<size_t>(dnr_api::MAX_NUMBER_OF_REGEX_RULES)) {
+ if (static_regex_rules_count > static_cast<size_t>(GetRegexRuleLimit())) {
std::move(callback).Run(kEnabledRulesetsRegexRuleCountExceeded);
return;
}
@@ -564,26 +561,8 @@ void RulesMonitorService::OnNewStaticRulesetsLoaded(
bool had_extra_headers_matcher = ruleset_manager_.HasAnyExtraHeadersMatcher();
- // Do another pass over the existing matchers for the extension to compute the
- // final set of matchers.
- {
- CompositeMatcher::MatcherList old_matchers = matcher->GetAndResetMatchers();
- base::EraseIf(old_matchers,
- [&ids_to_disable, &ids_to_enable](
- const std::unique_ptr<RulesetMatcher>& matcher) {
- // We also check |ids_to_enable| to omit duplicate matchers.
- // |new_matchers| already contains RulesetMatchers
- // corresponding to |ids_to_enable|.
- return base::Contains(ids_to_disable, matcher->id()) ||
- base::Contains(ids_to_enable, matcher->id());
- });
-
- new_matchers.insert(new_matchers.end(),
- std::make_move_iterator(old_matchers.begin()),
- std::make_move_iterator(old_matchers.end()));
- }
-
- matcher->SetMatchers(std::move(new_matchers));
+ matcher->RemoveRulesetsWithIDs(ids_to_disable);
+ matcher->AddOrUpdateRulesets(std::move(new_matchers));
prefs_->SetDNREnabledStaticRulesets(load_data.extension_id,
matcher->ComputeStaticRulesetIDs());
@@ -615,34 +594,14 @@ void RulesMonitorService::OnDynamicRulesUpdated(
base::Optional<std::string> error) {
DCHECK_EQ(1u, load_data.rulesets.size());
- RulesetInfo& dynamic_ruleset = load_data.rulesets[0];
- DCHECK_EQ(dynamic_ruleset.did_load_successfully(), !error.has_value());
-
- // The extension may have been uninstalled by this point. Return early if
- // that's the case.
- if (!extension_registry_->GetInstalledExtension(load_data.extension_id)) {
- // Still dispatch the |callback|, even though it's probably a no-op.
- std::move(callback).Run(std::move(error));
- return;
- }
-
- // Update the ruleset checksums if needed. Note it's possible that
- // new_checksum() is valid while did_load_successfully() returns false below.
- // This should be rare but can happen when updating the rulesets succeeds but
- // we fail to create a RulesetMatcher from the indexed ruleset file (e.g. due
- // to a file read error). We still update the prefs checksum to ensure the
- // next ruleset load succeeds.
- // Note: We also do this for a non-enabled extension. The ruleset on the disk
- // has already been modified at this point. So we do want to update the
- // checksum for it to be in sync with what's on disk.
- if (dynamic_ruleset.new_checksum()) {
- prefs_->SetDNRDynamicRulesetChecksum(load_data.extension_id,
- *dynamic_ruleset.new_checksum());
- }
+ LogMetricsAndUpdateChecksumsIfNeeded(load_data);
// Respond to the extension.
std::move(callback).Run(std::move(error));
+ RulesetInfo& dynamic_ruleset = load_data.rulesets[0];
+ DCHECK_EQ(dynamic_ruleset.did_load_successfully(), !error.has_value());
+
if (!dynamic_ruleset.did_load_successfully())
return;
@@ -709,8 +668,15 @@ void RulesMonitorService::AdjustExtraHeaderListenerCountIfNeeded(
}
}
-void RulesMonitorService::UpdateRulesetChecksumsIfNeeded(
+void RulesMonitorService::LogMetricsAndUpdateChecksumsIfNeeded(
const LoadRequestData& load_data) {
+ for (const RulesetInfo& ruleset : load_data.rulesets) {
+ // The |load_ruleset_result()| might be empty if CreateVerifiedMatcher
+ // wasn't called on the ruleset.
+ if (ruleset.load_ruleset_result())
+ LogLoadRulesetResult(*ruleset.load_ruleset_result());
+ }
+
// The extension may have been uninstalled by this point. Return early if
// that's the case.
if (!extension_registry_->GetInstalledExtension(load_data.extension_id))
diff --git a/chromium/extensions/browser/api/declarative_net_request/rules_monitor_service.h b/chromium/extensions/browser/api/declarative_net_request/rules_monitor_service.h
index 72b4c52a1ce..60ba79a2ad3 100644
--- a/chromium/extensions/browser/api/declarative_net_request/rules_monitor_service.h
+++ b/chromium/extensions/browser/api/declarative_net_request/rules_monitor_service.h
@@ -183,8 +183,9 @@ class RulesMonitorService : public BrowserContextKeyedAPI,
// RulesetManager had an extra headers matcher before the update.
void AdjustExtraHeaderListenerCountIfNeeded(bool had_extra_headers_matcher);
- // Updates ruleset checksum in preferences from |load_data|.
- void UpdateRulesetChecksumsIfNeeded(const LoadRequestData& load_data);
+ // Logs metrics related to the result of loading rulesets and updates ruleset
+ // checksum in preferences from |load_data|.
+ void LogMetricsAndUpdateChecksumsIfNeeded(const LoadRequestData& load_data);
ScopedObserver<ExtensionRegistry, ExtensionRegistryObserver>
registry_observer_{this};
diff --git a/chromium/extensions/browser/api/declarative_net_request/ruleset_manager.cc b/chromium/extensions/browser/api/declarative_net_request/ruleset_manager.cc
index 2701918b228..7437d6ff597 100644
--- a/chromium/extensions/browser/api/declarative_net_request/ruleset_manager.cc
+++ b/chromium/extensions/browser/api/declarative_net_request/ruleset_manager.cc
@@ -16,7 +16,6 @@
#include "base/stl_util.h"
#include "base/time/time.h"
#include "base/timer/elapsed_timer.h"
-#include "components/version_info/channel.h"
#include "components/web_cache/browser/web_cache_manager.h"
#include "extensions/browser/api/declarative_net_request/composite_matcher.h"
#include "extensions/browser/api/declarative_net_request/constants.h"
@@ -32,7 +31,6 @@
#include "extensions/common/api/declarative_net_request.h"
#include "extensions/common/api/declarative_net_request/utils.h"
#include "extensions/common/constants.h"
-#include "extensions/common/features/feature_channel.h"
#include "url/origin.h"
namespace extensions {
@@ -415,15 +413,11 @@ std::vector<RequestAction> RulesetManager::EvaluateRequestInternal(
return actions;
}
- // TODO(crbug.com/947591): Remove the channel check once implementation of
- // modifyHeaders action is complete.
- if (GetCurrentChannel() != version_info::Channel::STABLE) {
- std::vector<RequestAction> modify_headers_actions =
- GetModifyHeadersActions(rulesets_to_evaluate, request, params);
+ std::vector<RequestAction> modify_headers_actions =
+ GetModifyHeadersActions(rulesets_to_evaluate, request, params);
- if (!modify_headers_actions.empty())
- return modify_headers_actions;
- }
+ if (!modify_headers_actions.empty())
+ return modify_headers_actions;
return actions;
}
diff --git a/chromium/extensions/browser/api/declarative_net_request/ruleset_matcher.cc b/chromium/extensions/browser/api/declarative_net_request/ruleset_matcher.cc
index b76d4917edf..9c2779095b7 100644
--- a/chromium/extensions/browser/api/declarative_net_request/ruleset_matcher.cc
+++ b/chromium/extensions/browser/api/declarative_net_request/ruleset_matcher.cc
@@ -23,7 +23,7 @@ namespace extensions {
namespace declarative_net_request {
// static
-RulesetMatcher::LoadRulesetResult RulesetMatcher::CreateVerifiedMatcher(
+LoadRulesetResult RulesetMatcher::CreateVerifiedMatcher(
const RulesetSource& source,
int expected_ruleset_checksum,
std::unique_ptr<RulesetMatcher>* matcher) {
@@ -33,21 +33,21 @@ RulesetMatcher::LoadRulesetResult RulesetMatcher::CreateVerifiedMatcher(
base::ElapsedTimer timer;
if (!base::PathExists(source.indexed_path()))
- return kLoadErrorInvalidPath;
+ return LoadRulesetResult::kErrorInvalidPath;
std::string ruleset_data;
if (!base::ReadFileToString(source.indexed_path(), &ruleset_data))
- return kLoadErrorFileRead;
+ return LoadRulesetResult::kErrorCannotReadFile;
if (!StripVersionHeaderAndParseVersion(&ruleset_data))
- return kLoadErrorVersionMismatch;
+ return LoadRulesetResult::kErrorVersionMismatch;
// This guarantees that no memory access will end up outside the buffer.
if (!IsValidRulesetData(
base::make_span(reinterpret_cast<const uint8_t*>(ruleset_data.data()),
ruleset_data.size()),
expected_ruleset_checksum)) {
- return kLoadErrorChecksumMismatch;
+ return LoadRulesetResult::kErrorChecksumMismatch;
}
UMA_HISTOGRAM_TIMES(
@@ -58,7 +58,7 @@ RulesetMatcher::LoadRulesetResult RulesetMatcher::CreateVerifiedMatcher(
// constructor.
*matcher = base::WrapUnique(new RulesetMatcher(
std::move(ruleset_data), source.id(), source.extension_id()));
- return kLoadSuccess;
+ return LoadRulesetResult::kSuccess;
}
RulesetMatcher::~RulesetMatcher() = default;
@@ -71,12 +71,13 @@ base::Optional<RequestAction> RulesetMatcher::GetBeforeRequestAction(
}
std::vector<RequestAction> RulesetMatcher::GetModifyHeadersActions(
- const RequestParams& params) const {
+ const RequestParams& params,
+ base::Optional<uint64_t> min_priority) const {
std::vector<RequestAction> modify_header_actions =
- url_pattern_index_matcher_.GetModifyHeadersActions(params);
+ url_pattern_index_matcher_.GetModifyHeadersActions(params, min_priority);
std::vector<RequestAction> regex_modify_header_actions =
- regex_matcher_.GetModifyHeadersActions(params);
+ regex_matcher_.GetModifyHeadersActions(params, min_priority);
modify_header_actions.insert(
modify_header_actions.end(),
diff --git a/chromium/extensions/browser/api/declarative_net_request/ruleset_matcher.h b/chromium/extensions/browser/api/declarative_net_request/ruleset_matcher.h
index 728abb28c10..0a964b9a98d 100644
--- a/chromium/extensions/browser/api/declarative_net_request/ruleset_matcher.h
+++ b/chromium/extensions/browser/api/declarative_net_request/ruleset_matcher.h
@@ -22,6 +22,7 @@ namespace extensions {
namespace declarative_net_request {
class RulesetSource;
+enum class LoadRulesetResult;
namespace flat {
struct ExtensionIndexedRuleset;
@@ -35,35 +36,8 @@ struct UrlRuleMetadata;
// inherits from RulesetMatcherBase.
class RulesetMatcher {
public:
- // Describes the result of creating a RulesetMatcher instance.
- // This is logged as part of UMA. Hence existing values should not be re-
- // numbered or deleted. New values should be added before kLoadRulesetMax.
- enum LoadRulesetResult {
- // Ruleset loading succeeded.
- kLoadSuccess = 0,
-
- // Ruleset loading failed since the provided path did not exist.
- kLoadErrorInvalidPath = 1,
-
- // Ruleset loading failed due to a file read error.
- kLoadErrorFileRead = 2,
-
- // Ruleset loading failed due to a checksum mismatch.
- kLoadErrorChecksumMismatch = 3,
-
- // Ruleset loading failed due to version header mismatch.
- // TODO(karandeepb): This should be split into two cases:
- // - When the indexed ruleset doesn't have the version header in the
- // correct format.
- // - When the indexed ruleset's version is not the same as that used by
- // Chrome.
- kLoadErrorVersionMismatch = 4,
-
- kLoadResultMax
- };
-
// Factory function to create a verified RulesetMatcher for |source|. Must be
- // called on a sequence where file IO is allowed. Returns kLoadSuccess on
+ // called on a sequence where file IO is allowed. Returns kSuccess on
// success along with the ruleset |matcher|.
static LoadRulesetResult CreateVerifiedMatcher(
const RulesetSource& source,
@@ -74,8 +48,12 @@ class RulesetMatcher {
base::Optional<RequestAction> GetBeforeRequestAction(
const RequestParams& params) const;
+
+ // Returns a list of actions corresponding to all matched
+ // modifyHeaders rules with priority greater than |min_priority| if specified.
std::vector<RequestAction> GetModifyHeadersActions(
- const RequestParams& params) const;
+ const RequestParams& params,
+ base::Optional<uint64_t> min_priority) const;
bool IsExtraHeadersMatcher() const;
size_t GetRulesCount() const;
diff --git a/chromium/extensions/browser/api/declarative_net_request/ruleset_matcher_base.h b/chromium/extensions/browser/api/declarative_net_request/ruleset_matcher_base.h
index 6abe5602393..34c62a64607 100644
--- a/chromium/extensions/browser/api/declarative_net_request/ruleset_matcher_base.h
+++ b/chromium/extensions/browser/api/declarative_net_request/ruleset_matcher_base.h
@@ -41,9 +41,11 @@ class RulesetMatcherBase {
base::Optional<RequestAction> GetBeforeRequestAction(
const RequestParams& params) const;
- // Returns a vector of RequestAction for all matching modifyHeaders rules.
+ // Returns a vector of RequestAction for all matching modifyHeaders rules
+ // with priority greater than |min_priority| if specified.
virtual std::vector<RequestAction> GetModifyHeadersActions(
- const RequestParams& params) const = 0;
+ const RequestParams& params,
+ base::Optional<uint64_t> min_priority) const = 0;
// Returns whether this modifies "extraHeaders".
virtual bool IsExtraHeadersMatcher() const = 0;
diff --git a/chromium/extensions/browser/api/declarative_net_request/ruleset_matcher_unittest.cc b/chromium/extensions/browser/api/declarative_net_request/ruleset_matcher_unittest.cc
index 9643aa5a875..63d4011a0d4 100644
--- a/chromium/extensions/browser/api/declarative_net_request/ruleset_matcher_unittest.cc
+++ b/chromium/extensions/browser/api/declarative_net_request/ruleset_matcher_unittest.cc
@@ -4,6 +4,7 @@
#include "extensions/browser/api/declarative_net_request/ruleset_matcher.h"
+#include <limits>
#include <utility>
#include <vector>
@@ -13,7 +14,6 @@
#include "base/strings/string_util.h"
#include "base/strings/stringprintf.h"
#include "components/url_pattern_index/flat/url_pattern_index_generated.h"
-#include "components/version_info/channel.h"
#include "content/public/browser/render_process_host.h"
#include "content/public/browser/web_contents.h"
#include "content/public/test/navigation_simulator.h"
@@ -29,7 +29,6 @@
#include "extensions/common/api/declarative_net_request.h"
#include "extensions/common/api/declarative_net_request/constants.h"
#include "extensions/common/api/declarative_net_request/test_utils.h"
-#include "extensions/common/features/feature_channel.h"
#include "net/http/http_request_headers.h"
#include "testing/gmock/include/gmock/gmock.h"
#include "testing/gtest/include/gtest/gtest.h"
@@ -166,7 +165,7 @@ TEST_F(RulesetMatcherTest, FailedVerification) {
std::string data = "invalid data";
ASSERT_EQ(static_cast<int>(data.size()),
base::WriteFile(source.indexed_path(), data.c_str(), data.size()));
- EXPECT_EQ(RulesetMatcher::kLoadErrorVersionMismatch,
+ EXPECT_EQ(LoadRulesetResult::kErrorVersionMismatch,
RulesetMatcher::CreateVerifiedMatcher(source, expected_checksum,
&matcher));
@@ -176,16 +175,12 @@ TEST_F(RulesetMatcherTest, FailedVerification) {
data = GetVersionHeaderForTesting() + "invalid data";
ASSERT_EQ(static_cast<int>(data.size()),
base::WriteFile(source.indexed_path(), data.c_str(), data.size()));
- EXPECT_EQ(RulesetMatcher::kLoadErrorChecksumMismatch,
+ EXPECT_EQ(LoadRulesetResult::kErrorChecksumMismatch,
RulesetMatcher::CreateVerifiedMatcher(source, expected_checksum,
&matcher));
}
TEST_F(RulesetMatcherTest, ModifyHeaders_IsExtraHeaderMatcher) {
- // TODO(crbug.com/947591): Remove the channel override once implementation of
- // modifyHeaders action is complete.
- ScopedCurrentChannel channel(::version_info::Channel::UNKNOWN);
-
TestRule rule = CreateGenericRule();
rule.condition->url_filter = std::string("example.com");
std::unique_ptr<RulesetMatcher> matcher;
@@ -193,33 +188,29 @@ TEST_F(RulesetMatcherTest, ModifyHeaders_IsExtraHeaderMatcher) {
EXPECT_FALSE(matcher->IsExtraHeadersMatcher());
rule.action->type = std::string("modifyHeaders");
- rule.action->response_headers =
- std::vector<TestHeaderInfo>({TestHeaderInfo("HEADER3", "remove")});
+ rule.action->response_headers = std::vector<TestHeaderInfo>(
+ {TestHeaderInfo("HEADER3", "append", "VALUE3")});
ASSERT_TRUE(CreateVerifiedMatcher({rule}, CreateTemporarySource(), &matcher));
EXPECT_TRUE(matcher->IsExtraHeadersMatcher());
}
TEST_F(RulesetMatcherTest, ModifyHeaders) {
- // TODO(crbug.com/947591): Remove the channel override once implementation of
- // modifyHeaders action is complete.
- ScopedCurrentChannel channel(::version_info::Channel::UNKNOWN);
-
TestRule rule_1 = CreateGenericRule();
rule_1.id = kMinValidID;
rule_1.priority = kMinValidPriority + 1;
rule_1.condition->url_filter = std::string("example.com");
rule_1.action->type = std::string("modifyHeaders");
- rule_1.action->request_headers =
- std::vector<TestHeaderInfo>({TestHeaderInfo("header1", "remove")});
+ rule_1.action->request_headers = std::vector<TestHeaderInfo>(
+ {TestHeaderInfo("header1", "remove", base::nullopt)});
TestRule rule_2 = CreateGenericRule();
rule_2.id = kMinValidID + 1;
rule_2.priority = kMinValidPriority;
rule_2.condition->url_filter = std::string("example.com");
rule_2.action->type = std::string("modifyHeaders");
- rule_2.action->request_headers =
- std::vector<TestHeaderInfo>({TestHeaderInfo("header1", "remove"),
- TestHeaderInfo("header2", "remove")});
+ rule_2.action->request_headers = std::vector<TestHeaderInfo>(
+ {TestHeaderInfo("header1", "set", "value1"),
+ TestHeaderInfo("header2", "remove", base::nullopt)});
std::unique_ptr<RulesetMatcher> matcher;
ASSERT_TRUE(CreateVerifiedMatcher({rule_1, rule_2}, CreateTemporarySource(),
@@ -233,20 +224,21 @@ TEST_F(RulesetMatcherTest, ModifyHeaders) {
params.is_third_party = true;
std::vector<RequestAction> modify_header_actions =
- matcher->GetModifyHeadersActions(params);
+ matcher->GetModifyHeadersActions(params, 0u /* min_priority */);
RequestAction expected_rule_1_action = CreateRequestActionForTesting(
RequestAction::Type::MODIFY_HEADERS, *rule_1.id, *rule_1.priority);
- expected_rule_1_action.request_headers_to_modify = {
- RequestAction::HeaderInfo("header1", dnr_api::HEADER_OPERATION_REMOVE)};
+ expected_rule_1_action.request_headers_to_modify = {RequestAction::HeaderInfo(
+ "header1", dnr_api::HEADER_OPERATION_REMOVE, base::nullopt)};
RequestAction expected_rule_2_action = CreateRequestActionForTesting(
RequestAction::Type::MODIFY_HEADERS, *rule_2.id, *rule_2.priority);
expected_rule_2_action.request_headers_to_modify = {
- RequestAction::HeaderInfo("header1", dnr_api::HEADER_OPERATION_REMOVE),
- RequestAction::HeaderInfo("header2", dnr_api::HEADER_OPERATION_REMOVE)};
+ RequestAction::HeaderInfo("header1", dnr_api::HEADER_OPERATION_SET,
+ "value1"),
+ RequestAction::HeaderInfo("header2", dnr_api::HEADER_OPERATION_REMOVE,
+ base::nullopt)};
- ASSERT_EQ(2u, modify_header_actions.size());
EXPECT_THAT(modify_header_actions,
testing::UnorderedElementsAre(
testing::Eq(testing::ByRef(expected_rule_1_action)),
@@ -455,10 +447,6 @@ TEST_F(RulesetMatcherTest, UrlTransform) {
// Tests regex rules are evaluated correctly for different action types.
TEST_F(RulesetMatcherTest, RegexRules) {
- // TODO(crbug.com/947591): Remove the channel override once implementation of
- // modifyHeaders action is complete.
- ScopedCurrentChannel channel(::version_info::Channel::UNKNOWN);
-
auto create_regex_rule = [](size_t id, const std::string& regex_filter) {
TestRule rule = CreateGenericRule();
rule.id = id;
@@ -497,7 +485,7 @@ TEST_F(RulesetMatcherTest, RegexRules) {
create_regex_rule(6, R"(^(?:http|https)://[a-z\.]+\.org)");
modify_headers_rule.action->type = "modifyHeaders";
modify_headers_rule.action->request_headers =
- std::vector<TestHeaderInfo>({TestHeaderInfo("header1", "remove")});
+ std::vector<TestHeaderInfo>({TestHeaderInfo("header1", "set", "value1")});
rules.push_back(modify_headers_rule);
std::unique_ptr<RulesetMatcher> matcher;
@@ -564,7 +552,8 @@ TEST_F(RulesetMatcherTest, RegexRules) {
test_case.expected_modify_header_action = CreateRequestActionForTesting(
RequestAction::Type::MODIFY_HEADERS, *modify_headers_rule.id);
test_case.expected_modify_header_action->request_headers_to_modify = {
- RequestAction::HeaderInfo("header1", dnr_api::HEADER_OPERATION_REMOVE)};
+ RequestAction::HeaderInfo("header1", dnr_api::HEADER_OPERATION_SET,
+ "value1")};
test_cases.push_back(std::move(test_case));
}
@@ -584,7 +573,7 @@ TEST_F(RulesetMatcherTest, RegexRules) {
matcher->GetBeforeRequestAction(params));
std::vector<RequestAction> modify_header_actions =
- matcher->GetModifyHeadersActions(params);
+ matcher->GetModifyHeadersActions(params, 0u /* min_priority */);
if (test_case.expected_modify_header_action) {
EXPECT_THAT(modify_header_actions,
@@ -862,10 +851,6 @@ TEST_F(RulesetMatcherTest, RegexAndFilterListRules_RedirectPriority) {
}
TEST_F(RulesetMatcherTest, RegexAndFilterListRules_ModifyHeaders) {
- // TODO(crbug.com/947591): Remove the channel override once implementation of
- // modifyHeaders action is complete.
- ScopedCurrentChannel channel(::version_info::Channel::UNKNOWN);
-
std::vector<TestRule> rules;
TestRule rule = CreateGenericRule();
@@ -873,16 +858,18 @@ TEST_F(RulesetMatcherTest, RegexAndFilterListRules_ModifyHeaders) {
rule.priority = kMinValidPriority + 1;
rule.action->type = "modifyHeaders";
rule.condition->url_filter = "abc";
- rule.action->request_headers =
- std::vector<TestHeaderInfo>({TestHeaderInfo("header1", "remove"),
- TestHeaderInfo("header2", "remove")});
+ rule.action->request_headers = std::vector<TestHeaderInfo>(
+ {TestHeaderInfo("header1", "remove", base::nullopt),
+ TestHeaderInfo("header2", "remove", base::nullopt)});
rules.push_back(rule);
RequestAction action_1 = CreateRequestActionForTesting(
RequestAction::Type::MODIFY_HEADERS, 1, *rule.priority);
action_1.request_headers_to_modify = {
- RequestAction::HeaderInfo("header1", dnr_api::HEADER_OPERATION_REMOVE),
- RequestAction::HeaderInfo("header2", dnr_api::HEADER_OPERATION_REMOVE)};
+ RequestAction::HeaderInfo("header1", dnr_api::HEADER_OPERATION_REMOVE,
+ base::nullopt),
+ RequestAction::HeaderInfo("header2", dnr_api::HEADER_OPERATION_REMOVE,
+ base::nullopt)};
rule = CreateGenericRule();
rule.id = 2;
@@ -890,16 +877,18 @@ TEST_F(RulesetMatcherTest, RegexAndFilterListRules_ModifyHeaders) {
rule.condition->url_filter.reset();
rule.condition->regex_filter = "example";
rule.action->type = "modifyHeaders";
- rule.action->request_headers =
- std::vector<TestHeaderInfo>({TestHeaderInfo("header1", "remove"),
- TestHeaderInfo("header3", "remove")});
+ rule.action->request_headers = std::vector<TestHeaderInfo>(
+ {TestHeaderInfo("header1", "remove", base::nullopt),
+ TestHeaderInfo("header3", "remove", base::nullopt)});
rules.push_back(rule);
RequestAction action_2 = CreateRequestActionForTesting(
RequestAction::Type::MODIFY_HEADERS, 2, *rule.priority);
action_2.request_headers_to_modify = {
- RequestAction::HeaderInfo("header1", dnr_api::HEADER_OPERATION_REMOVE),
- RequestAction::HeaderInfo("header3", dnr_api::HEADER_OPERATION_REMOVE)};
+ RequestAction::HeaderInfo("header1", dnr_api::HEADER_OPERATION_REMOVE,
+ base::nullopt),
+ RequestAction::HeaderInfo("header3", dnr_api::HEADER_OPERATION_REMOVE,
+ base::nullopt)};
std::unique_ptr<RulesetMatcher> matcher;
ASSERT_TRUE(CreateVerifiedMatcher(rules, CreateTemporarySource(), &matcher));
@@ -910,7 +899,8 @@ TEST_F(RulesetMatcherTest, RegexAndFilterListRules_ModifyHeaders) {
RequestParams params;
params.url = &url;
- EXPECT_TRUE(matcher->GetModifyHeadersActions(params).empty());
+ EXPECT_TRUE(matcher->GetModifyHeadersActions(params, 0u /* min_priority */)
+ .empty());
}
{
@@ -920,7 +910,7 @@ TEST_F(RulesetMatcherTest, RegexAndFilterListRules_ModifyHeaders) {
params.url = &url;
std::vector<RequestAction> actions =
- matcher->GetModifyHeadersActions(params);
+ matcher->GetModifyHeadersActions(params, 0u /* min_priority */);
EXPECT_THAT(actions, testing::UnorderedElementsAre(
testing::Eq(testing::ByRef(action_1))));
}
@@ -932,7 +922,7 @@ TEST_F(RulesetMatcherTest, RegexAndFilterListRules_ModifyHeaders) {
params.url = &url;
std::vector<RequestAction> actions =
- matcher->GetModifyHeadersActions(params);
+ matcher->GetModifyHeadersActions(params, 0u /* min_priority */);
EXPECT_THAT(actions, testing::UnorderedElementsAre(
testing::Eq(testing::ByRef(action_2))));
}
@@ -945,10 +935,18 @@ TEST_F(RulesetMatcherTest, RegexAndFilterListRules_ModifyHeaders) {
params.url = &url;
std::vector<RequestAction> actions =
- matcher->GetModifyHeadersActions(params);
+ matcher->GetModifyHeadersActions(params, 0u /* min_priority */);
EXPECT_THAT(actions, testing::UnorderedElementsAre(
testing::Eq(testing::ByRef(action_1)),
testing::Eq(testing::ByRef(action_2))));
+
+ // GetModifyHeadersActions specifies a minimum priority greater than the
+ // rules' priority, so no actions should be returned.
+ EXPECT_TRUE(
+ matcher
+ ->GetModifyHeadersActions(
+ params, std::numeric_limits<uint64_t>::max() /* min_priority */)
+ .empty());
}
}
diff --git a/chromium/extensions/browser/api/declarative_net_request/ruleset_source.cc b/chromium/extensions/browser/api/declarative_net_request/ruleset_source.cc
index 4189b4b36ac..5f25b196f97 100644
--- a/chromium/extensions/browser/api/declarative_net_request/ruleset_source.cc
+++ b/chromium/extensions/browser/api/declarative_net_request/ruleset_source.cc
@@ -23,7 +23,6 @@
#include "base/strings/utf_string_conversions.h"
#include "base/timer/elapsed_timer.h"
#include "base/values.h"
-#include "components/version_info/channel.h"
#include "content/public/browser/browser_context.h"
#include "extensions/browser/api/declarative_net_request/constants.h"
#include "extensions/browser/api/declarative_net_request/flat_ruleset_indexer.h"
@@ -36,7 +35,6 @@
#include "extensions/common/error_utils.h"
#include "extensions/common/extension.h"
#include "extensions/common/extension_resource.h"
-#include "extensions/common/features/feature_channel.h"
#include "extensions/common/file_util.h"
#include "extensions/common/install_warning.h"
#include "extensions/common/manifest_constants.h"
@@ -142,8 +140,7 @@ ReadJSONRulesResult ParseRulesFromJSON(const base::FilePath& json_path,
}
const bool is_regex_rule = !!parsed_rule.condition.regex_filter;
- if (is_regex_rule &&
- ++regex_rule_count > dnr_api::MAX_NUMBER_OF_REGEX_RULES) {
+ if (is_regex_rule && ++regex_rule_count > GetRegexRuleLimit()) {
// Only add the install warning once.
if (!regex_rule_count_exceeded) {
regex_rule_count_exceeded = true;
@@ -317,7 +314,7 @@ RulesetSource RulesetSource::CreateStatic(
extension.path().Append(info.relative_path),
extension.path().Append(
file_util::GetIndexedRulesetRelativePath(info.id.value())),
- info.id, dnr_api::MAX_NUMBER_OF_RULES, extension.id(), info.enabled);
+ info.id, GetStaticRuleLimit(), extension.id(), info.enabled);
}
// static
@@ -330,7 +327,7 @@ RulesetSource RulesetSource::CreateDynamic(content::BrowserContext* context,
return RulesetSource(
dynamic_ruleset_directory.AppendASCII(kDynamicRulesJSONFilename),
dynamic_ruleset_directory.AppendASCII(kDynamicIndexedRulesFilename),
- kDynamicRulesetID, dnr_api::MAX_NUMBER_OF_DYNAMIC_RULES, extension_id,
+ kDynamicRulesetID, GetDynamicRuleLimit(), extension_id,
true /* enabled_by_default */);
}
@@ -414,15 +411,6 @@ ParseInfo RulesetSource::IndexAndPersistRules(
if (!inserted)
return ParseInfo(ParseResult::ERROR_DUPLICATE_IDS, &rule_id);
- // Ensure modifyHeaders actions don't have any side-effects on Stable
- // since it's under development.
- // TODO(crbug.com/947591): Remove the channel check once implementation
- // of modifyHeaders action is complete.
- if (rule.action.type == dnr_api::RULE_ACTION_TYPE_MODIFYHEADERS &&
- GetCurrentChannel() == version_info::Channel::STABLE) {
- continue;
- }
-
IndexedRule indexed_rule;
ParseResult parse_result = IndexedRule::CreateIndexedRule(
std::move(rule), base_url, &indexed_rule);
diff --git a/chromium/extensions/browser/api/declarative_net_request/test_utils.cc b/chromium/extensions/browser/api/declarative_net_request/test_utils.cc
index 34eeec46669..a6c468bd1f8 100644
--- a/chromium/extensions/browser/api/declarative_net_request/test_utils.cc
+++ b/chromium/extensions/browser/api/declarative_net_request/test_utils.cc
@@ -61,8 +61,13 @@ bool operator==(const RequestAction::HeaderInfo& lhs,
std::ostream& operator<<(std::ostream& output,
const RequestAction::HeaderInfo& header_info) {
- return output << dnr_api::ToString(header_info.operation) << ":"
- << header_info.header;
+ output << "\nRequestAction::HeaderInfo\n";
+ output << "\t|operation| " << dnr_api::ToString(header_info.operation)
+ << "\n";
+ output << "\t|header| " << header_info.header << "\n";
+ output << "\t|value| "
+ << (header_info.value ? *header_info.value : std::string("nullopt"));
+ return output;
}
// Note: This is not declared in the anonymous namespace so that we can use it
@@ -83,8 +88,8 @@ bool operator==(const RequestAction& lhs, const RequestAction& rhs) {
std::vector<RequestAction::HeaderInfo> b) {
auto header_info_comparator = [](const RequestAction::HeaderInfo& lhs,
const RequestAction::HeaderInfo& rhs) {
- return std::make_pair(lhs.header, lhs.operation) >
- std::make_pair(rhs.header, rhs.operation);
+ return std::make_tuple(lhs.header, lhs.operation, lhs.value) >
+ std::make_tuple(rhs.header, rhs.operation, rhs.value);
};
std::sort(a.begin(), a.end(), header_info_comparator);
@@ -138,9 +143,9 @@ std::ostream& operator<<(std::ostream& output, const RequestAction& action) {
output << "|index_priority| " << action.index_priority << "\n";
output << "|ruleset_id| " << action.ruleset_id << "\n";
output << "|extension_id| " << action.extension_id << "\n";
- output << "|request_headers_to_modify| "
+ output << "|request_headers_to_modify|"
<< ::testing::PrintToString(action.request_headers_to_modify) << "\n";
- output << "|response_headers_to_modify| "
+ output << "|response_headers_to_modify|"
<< ::testing::PrintToString(action.response_headers_to_modify);
return output;
}
@@ -238,6 +243,21 @@ std::ostream& operator<<(std::ostream& output, const ParseResult& result) {
case ParseResult::ERROR_INVALID_REGEX_FILTER:
output << "ERROR_INVALID_REGEX_FILTER";
break;
+ case ParseResult::ERROR_REGEX_TOO_LARGE:
+ output << "ERROR_REGEX_TOO_LARGE";
+ break;
+ case ParseResult::ERROR_MULTIPLE_FILTERS_SPECIFIED:
+ output << "ERROR_MULTIPLE_FILTERS_SPECIFIED";
+ break;
+ case ParseResult::ERROR_REGEX_SUBSTITUTION_WITHOUT_FILTER:
+ output << "ERROR_REGEX_SUBSTITUTION_WITHOUT_FILTER";
+ break;
+ case ParseResult::ERROR_INVALID_REGEX_SUBSTITUTION:
+ output << "ERROR_INVALID_REGEX_SUBSTITUTION";
+ break;
+ case ParseResult::ERROR_INVALID_ALLOW_ALL_REQUESTS_RESOURCE_TYPE:
+ output << "ERROR_INVALID_ALLOW_ALL_REQUESTS_RESOURCE_TYPE";
+ break;
case ParseResult::ERROR_NO_HEADERS_SPECIFIED:
output << "ERROR_NO_HEADERS_SPECIFIED";
break;
@@ -250,20 +270,41 @@ std::ostream& operator<<(std::ostream& output, const ParseResult& result) {
case ParseResult::ERROR_INVALID_HEADER_NAME:
output << "ERROR_INVALID_HEADER_NAME";
break;
- case ParseResult::ERROR_REGEX_TOO_LARGE:
- output << "ERROR_REGEX_TOO_LARGE";
+ case ParseResult::ERROR_INVALID_HEADER_VALUE:
+ output << "ERROR_INVALID_HEADER_VALUE";
break;
- case ParseResult::ERROR_MULTIPLE_FILTERS_SPECIFIED:
- output << "ERROR_MULTIPLE_FILTERS_SPECIFIED";
+ case ParseResult::ERROR_HEADER_VALUE_NOT_SPECIFIED:
+ output << "ERROR_HEADER_VALUE_NOT_SPECIFIED";
break;
- case ParseResult::ERROR_REGEX_SUBSTITUTION_WITHOUT_FILTER:
- output << "ERROR_REGEX_SUBSTITUTION_WITHOUT_FILTER";
+ case ParseResult::ERROR_HEADER_VALUE_PRESENT:
+ output << "ERROR_HEADER_VALUE_PRESENT";
break;
- case ParseResult::ERROR_INVALID_REGEX_SUBSTITUTION:
- output << "ERROR_INVALID_REGEX_SUBSTITUTION";
+ case ParseResult::ERROR_APPEND_REQUEST_HEADER_UNSUPPORTED:
+ output << "ERROR_APPEND_REQUEST_HEADER_UNSUPPORTED";
break;
- case ParseResult::ERROR_INVALID_ALLOW_ALL_REQUESTS_RESOURCE_TYPE:
- output << "ERROR_INVALID_ALLOW_ALL_REQUESTS_RESOURCE_TYPE";
+ }
+ return output;
+}
+
+std::ostream& operator<<(std::ostream& output, LoadRulesetResult result) {
+ switch (result) {
+ case LoadRulesetResult::kSuccess:
+ output << "kSuccess";
+ break;
+ case LoadRulesetResult::kErrorInvalidPath:
+ output << "kErrorInvalidPath";
+ break;
+ case LoadRulesetResult::kErrorCannotReadFile:
+ output << "kErrorCannotReadFile";
+ break;
+ case LoadRulesetResult::kErrorChecksumMismatch:
+ output << "kErrorChecksumMismatch";
+ break;
+ case LoadRulesetResult::kErrorVersionMismatch:
+ output << "kErrorVersionMismatch";
+ break;
+ case LoadRulesetResult::kErrorChecksumNotFound:
+ output << "kErrorChecksumNotFound";
break;
}
return output;
@@ -285,7 +326,7 @@ bool AreAllIndexedStaticRulesetsValid(
std::unique_ptr<RulesetMatcher> matcher;
if (RulesetMatcher::CreateVerifiedMatcher(std::move(source),
expected_checksum, &matcher) !=
- RulesetMatcher::kLoadSuccess) {
+ LoadRulesetResult::kSuccess) {
return false;
}
}
@@ -318,10 +359,9 @@ bool CreateVerifiedMatcher(const std::vector<TestRule>& rules,
*expected_checksum = result.ruleset_checksum;
// Create verified matcher.
- RulesetMatcher::LoadRulesetResult load_result =
- RulesetMatcher::CreateVerifiedMatcher(source, result.ruleset_checksum,
- matcher);
- return load_result == RulesetMatcher::kLoadSuccess;
+ LoadRulesetResult load_result = RulesetMatcher::CreateVerifiedMatcher(
+ source, result.ruleset_checksum, matcher);
+ return load_result == LoadRulesetResult::kSuccess;
}
RulesetSource CreateTemporarySource(RulesetID id,
@@ -335,18 +375,25 @@ RulesetSource CreateTemporarySource(RulesetID id,
dnr_api::ModifyHeaderInfo CreateModifyHeaderInfo(
dnr_api::HeaderOperation operation,
- std::string header) {
+ std::string header,
+ base::Optional<std::string> value) {
dnr_api::ModifyHeaderInfo header_info;
header_info.operation = operation;
header_info.header = header;
+ if (value)
+ header_info.value = std::make_unique<std::string>(*value);
+
return header_info;
}
bool EqualsForTesting(const dnr_api::ModifyHeaderInfo& lhs,
const dnr_api::ModifyHeaderInfo& rhs) {
- return lhs.operation == rhs.operation && lhs.header == rhs.header;
+ bool are_values_equal = lhs.value && rhs.value ? *lhs.value == *rhs.value
+ : lhs.value == rhs.value;
+ return lhs.operation == rhs.operation && lhs.header == rhs.header &&
+ are_values_equal;
}
RulesetManagerObserver::RulesetManagerObserver(RulesetManager* manager)
diff --git a/chromium/extensions/browser/api/declarative_net_request/test_utils.h b/chromium/extensions/browser/api/declarative_net_request/test_utils.h
index c67fbc39053..378ca7a29ee 100644
--- a/chromium/extensions/browser/api/declarative_net_request/test_utils.h
+++ b/chromium/extensions/browser/api/declarative_net_request/test_utils.h
@@ -57,6 +57,7 @@ std::ostream& operator<<(std::ostream& output, const RequestAction& action);
std::ostream& operator<<(std::ostream& output, const ParseResult& result);
std::ostream& operator<<(std::ostream& output,
const base::Optional<RequestAction>& action);
+std::ostream& operator<<(std::ostream& output, LoadRulesetResult result);
// Returns true if the given extension's indexed static rulesets are all valid.
// Should be called on a sequence where file IO is allowed.
@@ -77,7 +78,8 @@ RulesetSource CreateTemporarySource(RulesetID id = kMinValidStaticRulesetID,
api::declarative_net_request::ModifyHeaderInfo CreateModifyHeaderInfo(
api::declarative_net_request::HeaderOperation operation,
- std::string header);
+ std::string header,
+ base::Optional<std::string> value);
bool EqualsForTesting(
const api::declarative_net_request::ModifyHeaderInfo& lhs,
diff --git a/chromium/extensions/browser/api/declarative_net_request/utils.cc b/chromium/extensions/browser/api/declarative_net_request/utils.cc
index 792709e090f..a0428894c32 100644
--- a/chromium/extensions/browser/api/declarative_net_request/utils.cc
+++ b/chromium/extensions/browser/api/declarative_net_request/utils.cc
@@ -39,7 +39,7 @@ namespace dnr_api = api::declarative_net_request;
// url_pattern_index.fbs. Whenever an extension with an indexed ruleset format
// version different from the one currently used by Chrome is loaded, the
// extension ruleset will be reindexed.
-constexpr int kIndexedRulesetFormatVersion = 17;
+constexpr int kIndexedRulesetFormatVersion = 18;
// This static assert is meant to catch cases where
// url_pattern_index::kUrlPatternIndexFormatVersion is incremented without
@@ -49,13 +49,16 @@ static_assert(url_pattern_index::kUrlPatternIndexFormatVersion == 6,
"also updated kIndexedRulesetFormatVersion above.");
constexpr int kInvalidIndexedRulesetFormatVersion = -1;
-
int g_indexed_ruleset_format_version_for_testing =
kInvalidIndexedRulesetFormatVersion;
constexpr int kInvalidOverrideChecksumForTest = -1;
int g_override_checksum_for_test = kInvalidOverrideChecksumForTest;
+constexpr int kInvalidRuleLimit = -1;
+int g_static_rule_limit_for_testing = kInvalidRuleLimit;
+int g_regex_rule_limit_for_testing = kInvalidRuleLimit;
+
int GetIndexedRulesetFormatVersion() {
return g_indexed_ruleset_format_version_for_testing ==
kInvalidIndexedRulesetFormatVersion
@@ -287,5 +290,31 @@ std::vector<std::string> GetPublicRulesetIDs(const Extension& extension,
return ids;
}
+int GetStaticRuleLimit() {
+ return g_static_rule_limit_for_testing == kInvalidRuleLimit
+ ? dnr_api::MAX_NUMBER_OF_RULES
+ : g_static_rule_limit_for_testing;
+}
+
+int GetDynamicRuleLimit() {
+ return dnr_api::MAX_NUMBER_OF_DYNAMIC_RULES;
+}
+
+int GetRegexRuleLimit() {
+ return g_regex_rule_limit_for_testing == kInvalidRuleLimit
+ ? dnr_api::MAX_NUMBER_OF_REGEX_RULES
+ : g_regex_rule_limit_for_testing;
+}
+
+ScopedRuleLimitOverride CreateScopedStaticRuleLimitOverrideForTesting(
+ int limit) {
+ return base::AutoReset<int>(&g_static_rule_limit_for_testing, limit);
+}
+
+ScopedRuleLimitOverride CreateScopedRegexRuleLimitOverrideForTesting(
+ int limit) {
+ return base::AutoReset<int>(&g_regex_rule_limit_for_testing, limit);
+}
+
} // namespace declarative_net_request
} // namespace extensions
diff --git a/chromium/extensions/browser/api/declarative_net_request/utils.h b/chromium/extensions/browser/api/declarative_net_request/utils.h
index f8f36f352f2..6e840a8d42f 100644
--- a/chromium/extensions/browser/api/declarative_net_request/utils.h
+++ b/chromium/extensions/browser/api/declarative_net_request/utils.h
@@ -99,6 +99,23 @@ std::string GetPublicRulesetID(const Extension& extension,
std::vector<std::string> GetPublicRulesetIDs(const Extension& extension,
const CompositeMatcher& matcher);
+// Returns the per-extension static rule limit.
+int GetStaticRuleLimit();
+
+// Returns the per-extension dynamic rule limit.
+int GetDynamicRuleLimit();
+
+// Returns the per-extension regex rules limit. This is enforced separately for
+// static and dynamic rulesets.
+int GetRegexRuleLimit();
+
+// Test helpers to override the various rule limits until the returned value is
+// in scope.
+using ScopedRuleLimitOverride = base::AutoReset<int>;
+ScopedRuleLimitOverride CreateScopedStaticRuleLimitOverrideForTesting(
+ int limit);
+ScopedRuleLimitOverride CreateScopedRegexRuleLimitOverrideForTesting(int limit);
+
// Helper to convert a flatbufffers::String to a string-like object with type T.
template <typename T>
T CreateString(const flatbuffers::String& str) {
diff --git a/chromium/extensions/browser/api/device_permissions_prompt.h b/chromium/extensions/browser/api/device_permissions_prompt.h
index 72d238d53d3..972bacd6197 100644
--- a/chromium/extensions/browser/api/device_permissions_prompt.h
+++ b/chromium/extensions/browser/api/device_permissions_prompt.h
@@ -11,7 +11,6 @@
#include <vector>
#include "base/callback_forward.h"
-#include "base/logging.h"
#include "base/macros.h"
#include "base/memory/ref_counted.h"
#include "base/strings/string16.h"
diff --git a/chromium/extensions/browser/api/display_source/display_source_apitestbase.cc b/chromium/extensions/browser/api/display_source/display_source_apitestbase.cc
index b9a4e9e5b2f..a230c358c3f 100644
--- a/chromium/extensions/browser/api/display_source/display_source_apitestbase.cc
+++ b/chromium/extensions/browser/api/display_source/display_source_apitestbase.cc
@@ -10,7 +10,6 @@
#include "base/bind.h"
#include "base/memory/ptr_util.h"
-#include "base/task/post_task.h"
#include "content/public/browser/browser_task_traits.h"
#include "content/public/browser/browser_thread.h"
#include "net/base/ip_address.h"
@@ -339,8 +338,8 @@ void MockDisplaySourceConnectionDelegate::Connect(
// And store udp port to udp_port_ string in order to be used
// In a message exchange. Then make a base::PostTask
// on UI thread and call OnSinkConnected() to proceed with the test
- base::PostTask(
- FROM_HERE, {BrowserThread::IO},
+ content::GetIOThreadTaskRunner({})->PostTask(
+ FROM_HERE,
base::BindOnce(&MockDisplaySourceConnectionDelegate::BindToUdpSocket,
base::Unretained(this)));
}
@@ -432,8 +431,8 @@ EnqueueSinkMessage(std::string message) {
AdaptMessagePattern(found_clientport_key, kClientPortKey, kUdpPortLength,
udp_port_, message);
- base::PostTask(FROM_HERE, {BrowserThread::UI},
- base::BindOnce(message_received_cb_, message));
+ content::GetUIThreadTaskRunner({})->PostTask(
+ FROM_HERE, base::BindOnce(message_received_cb_, message));
}
void MockDisplaySourceConnectionDelegate::
@@ -488,8 +487,8 @@ void MockDisplaySourceConnectionDelegate::BindToUdpSocket() {
udp_port_ = std::to_string(port);
// When we got an udp socket established and udp port is known
// Change sink's status to connected and proceed with the test.
- base::PostTask(
- FROM_HERE, {BrowserThread::UI},
+ content::GetUIThreadTaskRunner({})->PostTask(
+ FROM_HERE,
base::BindOnce(&MockDisplaySourceConnectionDelegate::OnSinkConnected,
base::Unretained(this)));
break;
@@ -526,8 +525,8 @@ void MockDisplaySourceConnectionDelegate::OnMediaPacketReceived(
// We received at least one media packet.
// Test is completed.
socket_->Close();
- base::PostTask(
- FROM_HERE, {BrowserThread::UI},
+ content::GetUIThreadTaskRunner({})->PostTask(
+ FROM_HERE,
base::BindOnce(&MockDisplaySourceConnectionDelegate::Disconnect,
base::Unretained(this), StringCallback()));
return;
diff --git a/chromium/extensions/browser/api/display_source/wifi_display/wifi_display_media_service_impl.cc b/chromium/extensions/browser/api/display_source/wifi_display/wifi_display_media_service_impl.cc
index 49fbd813d15..6da57bb3cb1 100644
--- a/chromium/extensions/browser/api/display_source/wifi_display/wifi_display_media_service_impl.cc
+++ b/chromium/extensions/browser/api/display_source/wifi_display/wifi_display_media_service_impl.cc
@@ -10,7 +10,6 @@
#include "base/big_endian.h"
#include "base/bind.h"
#include "base/memory/ptr_util.h"
-#include "base/task/post_task.h"
#include "content/public/browser/browser_task_traits.h"
#include "content/public/browser/browser_thread.h"
#include "mojo/public/cpp/bindings/strong_binding.h"
@@ -56,8 +55,8 @@ void WiFiDisplayMediaServiceImpl::Create(
void WiFiDisplayMediaServiceImpl::BindToReceiver(
mojo::PendingReceiver<mojom::WiFiDisplayMediaService> receiver,
content::RenderFrameHost* render_frame_host) {
- base::PostTask(
- FROM_HERE, {BrowserThread::IO},
+ content::GetIOThreadTaskRunner({})->PostTask(
+ FROM_HERE,
base::BindOnce(WiFiDisplayMediaServiceImpl::Create, std::move(receiver)));
}
diff --git a/chromium/extensions/browser/api/document_scan/BUILD.gn b/chromium/extensions/browser/api/document_scan/BUILD.gn
index 7ac8b406a51..141506a87b5 100644
--- a/chromium/extensions/browser/api/document_scan/BUILD.gn
+++ b/chromium/extensions/browser/api/document_scan/BUILD.gn
@@ -13,15 +13,22 @@ source_set("document_scan") {
"document_scan_api.h",
"document_scan_interface.cc",
"document_scan_interface.h",
- "document_scan_interface_chromeos.cc",
- "document_scan_interface_chromeos.h",
]
- if (!is_chromeos) {
+ if (is_chromeos) {
+ sources += [
+ "document_scan_interface_chromeos.cc",
+ "document_scan_interface_chromeos.h",
+ ]
+ } else {
sources += [ "document_scan_interface_nonchromeos.cc" ]
}
deps = [ "//extensions/common/api" ]
+ if (is_chromeos) {
+ deps += [ "//chromeos/dbus:lorgnette_proto" ]
+ }
+
public_deps = [ "//extensions/browser:browser_sources" ]
}
diff --git a/chromium/extensions/browser/api/document_scan/document_scan_api.h b/chromium/extensions/browser/api/document_scan/document_scan_api.h
index ba490af6616..3044227c624 100644
--- a/chromium/extensions/browser/api/document_scan/document_scan_api.h
+++ b/chromium/extensions/browser/api/document_scan/document_scan_api.h
@@ -9,7 +9,6 @@
#include <string>
#include <vector>
-#include "base/macros.h"
#include "extensions/browser/api/document_scan/document_scan_interface.h"
#include "extensions/browser/extension_function.h"
#include "extensions/common/api/document_scan.h"
@@ -21,6 +20,8 @@ class DocumentScanScanFunction : public ExtensionFunction {
public:
DECLARE_EXTENSION_FUNCTION("documentScan.scan", DOCUMENT_SCAN_SCAN)
DocumentScanScanFunction();
+ DocumentScanScanFunction(const DocumentScanScanFunction&) = delete;
+ DocumentScanScanFunction& operator=(const DocumentScanScanFunction&) = delete;
protected:
~DocumentScanScanFunction() override;
@@ -41,8 +42,6 @@ class DocumentScanScanFunction : public ExtensionFunction {
std::unique_ptr<document_scan::Scan::Params> params_;
std::unique_ptr<DocumentScanInterface> document_scan_interface_;
-
- DISALLOW_COPY_AND_ASSIGN(DocumentScanScanFunction);
};
} // namespace api
diff --git a/chromium/extensions/browser/api/document_scan/document_scan_interface_chromeos.cc b/chromium/extensions/browser/api/document_scan/document_scan_interface_chromeos.cc
index 2517319a22b..11a5169008e 100644
--- a/chromium/extensions/browser/api/document_scan/document_scan_interface_chromeos.cc
+++ b/chromium/extensions/browser/api/document_scan/document_scan_interface_chromeos.cc
@@ -9,6 +9,7 @@
#include "base/base64.h"
#include "base/bind.h"
+#include "base/logging.h"
#include "chromeos/dbus/dbus_thread_manager.h"
#include "chromeos/dbus/lorgnette_manager_client.h"
#include "third_party/cros_system_api/dbus/service_constants.h"
@@ -42,25 +43,15 @@ void DocumentScanInterfaceChromeos::ListScanners(
void DocumentScanInterfaceChromeos::OnScannerListReceived(
ListScannersResultsCallback callback,
- base::Optional<chromeos::LorgnetteManagerClient::ScannerTable> scanners) {
+ base::Optional<lorgnette::ListScannersResponse> response) {
std::vector<ScannerDescription> scanner_descriptions;
- if (scanners.has_value()) {
- for (const auto& scanner : scanners.value()) {
+ if (response) {
+ for (const auto& scanner : response->scanners()) {
ScannerDescription description;
- description.name = scanner.first;
- const auto& entry = scanner.second;
- auto info_it = entry.find(lorgnette::kScannerPropertyManufacturer);
- if (info_it != entry.end()) {
- description.manufacturer = info_it->second;
- }
- info_it = entry.find(lorgnette::kScannerPropertyModel);
- if (info_it != entry.end()) {
- description.model = info_it->second;
- }
- info_it = entry.find(lorgnette::kScannerPropertyType);
- if (info_it != entry.end()) {
- description.scanner_type = info_it->second;
- }
+ description.name = scanner.name();
+ description.manufacturer = scanner.manufacturer();
+ description.model = scanner.model();
+ description.scanner_type = scanner.type();
description.image_mime_type = kScannerImageMimeTypePng;
scanner_descriptions.push_back(description);
}
diff --git a/chromium/extensions/browser/api/document_scan/document_scan_interface_chromeos.h b/chromium/extensions/browser/api/document_scan/document_scan_interface_chromeos.h
index b25eaa39fa5..ebbc0031dce 100644
--- a/chromium/extensions/browser/api/document_scan/document_scan_interface_chromeos.h
+++ b/chromium/extensions/browser/api/document_scan/document_scan_interface_chromeos.h
@@ -7,9 +7,8 @@
#include <string>
-#include "base/macros.h"
#include "base/optional.h"
-#include "chromeos/dbus/lorgnette_manager_client.h"
+#include "chromeos/dbus/lorgnette/lorgnette_service.pb.h"
#include "extensions/browser/api/document_scan/document_scan_interface.h"
namespace extensions {
@@ -18,6 +17,9 @@ namespace api {
class DocumentScanInterfaceChromeos : public DocumentScanInterface {
public:
DocumentScanInterfaceChromeos();
+ DocumentScanInterfaceChromeos(const DocumentScanInterfaceChromeos&) = delete;
+ DocumentScanInterfaceChromeos& operator=(
+ const DocumentScanInterfaceChromeos&) = delete;
~DocumentScanInterfaceChromeos() override;
// DocumentScanInterface:
@@ -30,11 +32,9 @@ class DocumentScanInterfaceChromeos : public DocumentScanInterface {
private:
void OnScannerListReceived(
ListScannersResultsCallback callback,
- base::Optional<chromeos::LorgnetteManagerClient::ScannerTable> scanners);
+ base::Optional<lorgnette::ListScannersResponse> response);
void OnScanCompleted(ScanResultsCallback callback,
base::Optional<std::string> image_data);
-
- DISALLOW_COPY_AND_ASSIGN(DocumentScanInterfaceChromeos);
};
} // namespace api
diff --git a/chromium/extensions/browser/api/document_scan/document_scan_interface_chromeos_unittest.cc b/chromium/extensions/browser/api/document_scan/document_scan_interface_chromeos_unittest.cc
index 0d99d9a1f2f..f969fb6434a 100644
--- a/chromium/extensions/browser/api/document_scan/document_scan_interface_chromeos_unittest.cc
+++ b/chromium/extensions/browser/api/document_scan/document_scan_interface_chromeos_unittest.cc
@@ -46,11 +46,14 @@ TEST_F(DocumentScanInterfaceChromeosTest, ListScanners) {
constexpr const char* kScannerManufacturer = "Jacques-Louis David";
constexpr const char* kScannerModel = "Le Havre";
constexpr const char* kScannerType = "Impressionism";
- GetLorgnetteManagerClient()->AddScannerTableEntry(
- kScannerName,
- {{lorgnette::kScannerPropertyManufacturer, kScannerManufacturer},
- {lorgnette::kScannerPropertyModel, kScannerModel},
- {lorgnette::kScannerPropertyType, kScannerType}});
+ lorgnette::ScannerInfo scanner;
+ scanner.set_name(kScannerName);
+ scanner.set_manufacturer(kScannerManufacturer);
+ scanner.set_model(kScannerModel);
+ scanner.set_type(kScannerType);
+ lorgnette::ListScannersResponse response;
+ *response.add_scanners() = std::move(scanner);
+ GetLorgnetteManagerClient()->SetListScannersResponse(response);
base::RunLoop run_loop;
scan_interface_.ListScanners(base::BindOnce(
diff --git a/chromium/extensions/browser/api/document_scan/document_scan_interface_nonchromeos.cc b/chromium/extensions/browser/api/document_scan/document_scan_interface_nonchromeos.cc
index e5a0ca0b18f..16b476599b5 100644
--- a/chromium/extensions/browser/api/document_scan/document_scan_interface_nonchromeos.cc
+++ b/chromium/extensions/browser/api/document_scan/document_scan_interface_nonchromeos.cc
@@ -4,7 +4,6 @@
#include <utility>
-#include "base/macros.h"
#include "extensions/browser/api/document_scan/document_scan_interface.h"
namespace {
@@ -18,8 +17,12 @@ namespace api {
class DocumentScanInterfaceImpl : public DocumentScanInterface {
public:
- DocumentScanInterfaceImpl() {}
- ~DocumentScanInterfaceImpl() override {}
+ DocumentScanInterfaceImpl() = default;
+ ~DocumentScanInterfaceImpl() override = default;
+
+ DocumentScanInterfaceImpl(const DocumentScanInterfaceImpl&) = delete;
+ DocumentScanInterfaceImpl& operator=(const DocumentScanInterfaceImpl&) =
+ delete;
void ListScanners(ListScannersResultsCallback callback) override {
std::move(callback).Run(std::vector<ScannerDescription>(), "");
@@ -30,9 +33,6 @@ class DocumentScanInterfaceImpl : public DocumentScanInterface {
ScanResultsCallback callback) override {
std::move(callback).Run("", "", kScanFunctionNotImplementedError);
}
-
- private:
- DISALLOW_COPY_AND_ASSIGN(DocumentScanInterfaceImpl);
};
// static
diff --git a/chromium/extensions/browser/api/extensions_api_client.cc b/chromium/extensions/browser/api/extensions_api_client.cc
index abb2202284b..18e27f0ee78 100644
--- a/chromium/extensions/browser/api/extensions_api_client.cc
+++ b/chromium/extensions/browser/api/extensions_api_client.cc
@@ -5,12 +5,12 @@
#include "extensions/browser/api/extensions_api_client.h"
#include "extensions/browser/api/device_permissions_prompt.h"
-#include "extensions/browser/api/management/supervised_user_service_delegate.h"
#include "extensions/browser/api/system_display/display_info_provider.h"
#include "extensions/browser/api/virtual_keyboard_private/virtual_keyboard_delegate.h"
#include "extensions/browser/guest_view/extensions_guest_view_manager_delegate.h"
#include "extensions/browser/guest_view/mime_handler_view/mime_handler_view_guest_delegate.h"
#include "extensions/browser/guest_view/web_view/web_view_permission_helper_delegate.h"
+#include "extensions/browser/supervised_user_extensions_delegate.h"
namespace extensions {
class AppViewGuestDelegate;
@@ -120,8 +120,8 @@ ManagementAPIDelegate* ExtensionsAPIClient::CreateManagementAPIDelegate()
return nullptr;
}
-std::unique_ptr<SupervisedUserServiceDelegate>
-ExtensionsAPIClient::CreateSupervisedUserServiceDelegate() const {
+std::unique_ptr<SupervisedUserExtensionsDelegate>
+ExtensionsAPIClient::CreateSupervisedUserExtensionsDelegate() const {
return nullptr;
}
diff --git a/chromium/extensions/browser/api/extensions_api_client.h b/chromium/extensions/browser/api/extensions_api_client.h
index 81a7cad5880..67b8c3fda8f 100644
--- a/chromium/extensions/browser/api/extensions_api_client.h
+++ b/chromium/extensions/browser/api/extensions_api_client.h
@@ -55,7 +55,7 @@ class NetworkingCastPrivateDelegate;
class NonNativeFileSystemDelegate;
class RulesCacheDelegate;
class SettingsObserver;
-class SupervisedUserServiceDelegate;
+class SupervisedUserExtensionsDelegate;
class ValueStoreCache;
class ValueStoreFactory;
class VirtualKeyboardDelegate;
@@ -170,8 +170,8 @@ class ExtensionsAPIClient {
// Creates a delegate for calling into the SupervisedUserService from the
// Management API.
- virtual std::unique_ptr<SupervisedUserServiceDelegate>
- CreateSupervisedUserServiceDelegate() const;
+ virtual std::unique_ptr<SupervisedUserExtensionsDelegate>
+ CreateSupervisedUserExtensionsDelegate() const;
// Creates and returns the DisplayInfoProvider used by the
// chrome.system.display extension API.
diff --git a/chromium/extensions/browser/api/feedback_private/feedback_service.cc b/chromium/extensions/browser/api/feedback_private/feedback_service.cc
index 9ef9363edc7..260b3ec7996 100644
--- a/chromium/extensions/browser/api/feedback_private/feedback_service.cc
+++ b/chromium/extensions/browser/api/feedback_private/feedback_service.cc
@@ -20,7 +20,7 @@
#if defined(OS_CHROMEOS)
#include "ash/public/cpp/assistant/controller/assistant_controller.h"
-#include "chromeos/services/assistant/public/mojom/assistant.mojom.h"
+#include "chromeos/services/assistant/public/cpp/assistant_service.h"
#include "extensions/browser/api/feedback_private/log_source_access_manager.h"
#include "mojo/public/cpp/bindings/remote.h"
#endif // defined(OS_CHROMEOS)
diff --git a/chromium/extensions/browser/api/file_system/BUILD.gn b/chromium/extensions/browser/api/file_system/BUILD.gn
index 262b58d976a..516aba105f1 100644
--- a/chromium/extensions/browser/api/file_system/BUILD.gn
+++ b/chromium/extensions/browser/api/file_system/BUILD.gn
@@ -19,6 +19,7 @@ source_set("file_system") {
deps = [
"//base",
+ "//base/util/values:values_util",
"//content/public/browser",
"//extensions/browser/api/file_handlers",
"//extensions/common",
diff --git a/chromium/extensions/browser/api/file_system/file_system_api.cc b/chromium/extensions/browser/api/file_system/file_system_api.cc
index 706354d8ecb..5c899c4eed3 100644
--- a/chromium/extensions/browser/api/file_system/file_system_api.cc
+++ b/chromium/extensions/browser/api/file_system/file_system_api.cc
@@ -22,9 +22,8 @@
#include "base/strings/string_util.h"
#include "base/strings/stringprintf.h"
#include "base/strings/utf_string_conversions.h"
-#include "base/task/post_task.h"
#include "base/task/thread_pool.h"
-#include "base/value_conversions.h"
+#include "base/util/values/values_util.h"
#include "base/values.h"
#include "build/build_config.h"
#include "content/public/browser/browser_context.h"
@@ -188,8 +187,8 @@ void PassFileInfoToUIThread(const FileInfoOptCallback& callback,
DCHECK_CURRENTLY_ON(content::BrowserThread::IO);
std::unique_ptr<base::File::Info> file_info(
result == base::File::FILE_OK ? new base::File::Info(info) : NULL);
- base::PostTask(FROM_HERE, {content::BrowserThread::UI},
- base::BindOnce(callback, std::move(file_info)));
+ content::GetUIThreadTaskRunner({})->PostTask(
+ FROM_HERE, base::BindOnce(callback, std::move(file_info)));
}
// Gets a WebContents instance handle for a platform app hosted in
@@ -227,7 +226,7 @@ void SetLastChooseEntryDirectory(ExtensionPrefs* prefs,
const base::FilePath& path) {
prefs->UpdateExtensionPref(
extension_id, kLastChooseEntryDirectory,
- base::Value::ToUniquePtrValue(base::CreateFilePathValue(path)));
+ base::Value::ToUniquePtrValue(::util::FilePathToValue(path)));
}
} // namespace file_system_api
@@ -395,8 +394,8 @@ void FileSystemChooseEntryFunction::ShowPicker(
else if (g_paths_to_be_picked_for_test)
test_paths = *g_paths_to_be_picked_for_test;
- base::PostTask(
- FROM_HERE, {content::BrowserThread::UI},
+ content::GetUIThreadTaskRunner({})->PostTask(
+ FROM_HERE,
test_paths.size() > 0
? base::BindOnce(&FileSystemChooseEntryFunction::FilesSelected,
this, test_paths)
@@ -498,9 +497,16 @@ void FileSystemChooseEntryFunction::FilesSelected(
} else {
last_choose_directory = paths[0].DirName();
}
- file_system_api::SetLastChooseEntryDirectory(
- ExtensionPrefs::Get(browser_context()), extension()->id(),
- last_choose_directory);
+
+ if (extension_->is_extension()) {
+ ExtensionsBrowserClient::Get()->SetLastSaveFilePath(browser_context(),
+ last_choose_directory);
+ } else {
+ file_system_api::SetLastChooseEntryDirectory(
+ ExtensionPrefs::Get(browser_context()), extension()->id(),
+ last_choose_directory);
+ }
+
if (is_directory_) {
// Get the WebContents for the app window to be the parent window of the
// confirmation dialog if necessary.
@@ -542,8 +548,8 @@ void FileSystemChooseEntryFunction::ConfirmDirectoryAccessAsync(
const base::FilePath check_path =
non_native_path ? paths[0] : base::MakeAbsoluteFilePath(paths[0]);
if (check_path.empty()) {
- base::PostTask(
- FROM_HERE, {content::BrowserThread::UI},
+ content::GetUIThreadTaskRunner({})->PostTask(
+ FROM_HERE,
base::BindOnce(&FileSystemChooseEntryFunction::FileSelectionCanceled,
this));
return;
@@ -559,23 +565,23 @@ void FileSystemChooseEntryFunction::ConfirmDirectoryAccessAsync(
if (g_skip_directory_confirmation_for_test) {
if (g_allow_directory_access_for_test)
break;
- base::PostTask(
- FROM_HERE, {content::BrowserThread::UI},
+ content::GetUIThreadTaskRunner({})->PostTask(
+ FROM_HERE,
base::BindOnce(&FileSystemChooseEntryFunction::FileSelectionCanceled,
this));
return;
}
- base::PostTask(
- FROM_HERE, {content::BrowserThread::UI},
+ content::GetUIThreadTaskRunner({})->PostTask(
+ FROM_HERE,
base::BindOnce(
&FileSystemChooseEntryFunction::ConfirmSensitiveDirectoryAccess,
this, paths, web_contents));
return;
}
- base::PostTask(
- FROM_HERE, {content::BrowserThread::UI},
+ content::GetUIThreadTaskRunner({})->PostTask(
+ FROM_HERE,
base::BindOnce(&FileSystemChooseEntryFunction::OnDirectoryAccessConfirmed,
this, paths));
}
@@ -619,10 +625,10 @@ void FileSystemChooseEntryFunction::BuildFileTypeInfo(
ui::SelectFileDialog::FileTypeInfo* file_type_info,
const base::FilePath::StringType& suggested_extension,
const AcceptOptions* accepts,
- const bool* acceptsAllTypes) {
+ const bool* accepts_all_types) {
file_type_info->include_all_files = true;
- if (acceptsAllTypes)
- file_type_info->include_all_files = *acceptsAllTypes;
+ if (accepts_all_types)
+ file_type_info->include_all_files = *accepts_all_types;
bool need_suggestion =
!file_type_info->include_all_files && !suggested_extension.empty();
@@ -745,8 +751,14 @@ ExtensionFunction::ResponseAction FileSystemChooseEntryFunction::Run() {
file_type_info.allowed_paths = ui::SelectFileDialog::FileTypeInfo::ANY_PATH;
- base::FilePath previous_path = file_system_api::GetLastChooseEntryDirectory(
- ExtensionPrefs::Get(browser_context()), extension()->id());
+ base::FilePath previous_path;
+ if (extension_->is_extension()) {
+ previous_path =
+ ExtensionsBrowserClient::Get()->GetSaveFilePath(browser_context());
+ } else {
+ previous_path = file_system_api::GetLastChooseEntryDirectory(
+ ExtensionPrefs::Get(browser_context()), extension()->id());
+ }
if (previous_path.empty()) {
SetInitialPathAndShowPicker(previous_path, suggested_name, file_type_info,
@@ -826,8 +838,8 @@ ExtensionFunction::ResponseAction FileSystemRetainEntryFunction::Run() {
// It is safe to use base::Unretained() for operation_runner(), since it
// is owned by |context| which will delete it on the IO thread.
- base::PostTask(
- FROM_HERE, {content::BrowserThread::IO},
+ content::GetIOThreadTaskRunner({})->PostTask(
+ FROM_HERE,
base::BindOnce(
base::IgnoreResult(
&storage::FileSystemOperationRunner::GetMetadata),
diff --git a/chromium/extensions/browser/api/file_system/file_system_api.h b/chromium/extensions/browser/api/file_system/file_system_api.h
index 7df036af4c6..2a95c4d89fd 100644
--- a/chromium/extensions/browser/api/file_system/file_system_api.h
+++ b/chromium/extensions/browser/api/file_system/file_system_api.h
@@ -140,7 +140,7 @@ class FileSystemChooseEntryFunction : public FileSystemEntryFunction {
ui::SelectFileDialog::FileTypeInfo* file_type_info,
const base::FilePath::StringType& suggested_extension,
const AcceptOptions* accepts,
- const bool* acceptsAllTypes);
+ const bool* accepts_all_types);
static void BuildSuggestion(const std::string* opt_name,
base::FilePath* suggested_name,
base::FilePath::StringType* suggested_extension);
diff --git a/chromium/extensions/browser/api/management/BUILD.gn b/chromium/extensions/browser/api/management/BUILD.gn
index 7692a4e1b99..7670df786f0 100644
--- a/chromium/extensions/browser/api/management/BUILD.gn
+++ b/chromium/extensions/browser/api/management/BUILD.gn
@@ -14,7 +14,6 @@ source_set("management") {
"management_api_constants.cc",
"management_api_constants.h",
"management_api_delegate.h",
- "supervised_user_service_delegate.h",
]
deps = [ "//extensions/common/api" ]
diff --git a/chromium/extensions/browser/api/management/management_api.cc b/chromium/extensions/browser/api/management/management_api.cc
index f19d3e9253f..c44d29df281 100644
--- a/chromium/extensions/browser/api/management/management_api.cc
+++ b/chromium/extensions/browser/api/management/management_api.cc
@@ -48,11 +48,6 @@
#include "url/gurl.h"
#include "url/url_constants.h"
-#if defined(OS_CHROMEOS)
-#include "components/web_modal/web_contents_modal_dialog_manager.h"
-#include "content/public/browser/web_contents.h"
-#endif
-
using content::BrowserThread;
namespace keys = extension_management_api_constants;
@@ -436,53 +431,42 @@ ExtensionFunction::ResponseAction ManagementSetEnabledFunction::Run() {
bool should_enable = params->enabled;
- const SupervisedUserServiceDelegate* supervised_user_service_delegate =
- ManagementAPI::GetFactoryInstance()
- ->Get(browser_context())
- ->GetSupervisedUserServiceDelegate();
-
- const bool is_supervised_child_who_may_install_extensions =
- supervised_user_service_delegate
- ? supervised_user_service_delegate
- ->IsSupervisedChildWhoMayInstallExtensions(browser_context())
- : false;
-
const ManagementPolicy* policy =
ExtensionSystem::Get(browser_context())->management_policy();
-
if (!policy->ExtensionMayModifySettings(extension(), target_extension,
nullptr)) {
return RespondNow(Error(keys::kUserCantModifyError, extension_id_));
}
- disable_reason::DisableReason reason = disable_reason::DISABLE_NONE;
- bool disallow_enable =
- should_enable &&
- policy->MustRemainDisabled(target_extension, &reason, nullptr);
-
- // Figure out if we should prompt for parental approval.
- bool prompt_parent_for_approval =
- disallow_enable && is_supervised_child_who_may_install_extensions &&
- reason == disable_reason::DISABLE_CUSTODIAN_APPROVAL_REQUIRED;
-
- // If the extension can't be enabled, only continue if we plan to prompt for
- // parental approval. For any child or other type of managed user, if
- // extension installation has been blocked, we stop the enabling of the
- // extension here.
- if (disallow_enable && !prompt_parent_for_approval) {
- LOG(ERROR) << "ManagementSetEnabledFunction::Run: extension may not be "
- "enabled, and we're not prompting for parent approval";
+ SupervisedUserExtensionsDelegate* supervised_user_extensions_delegate =
+ ManagementAPI::GetFactoryInstance()
+ ->Get(browser_context())
+ ->GetSupervisedUserExtensionsDelegate();
+ if (supervised_user_extensions_delegate &&
+ supervised_user_extensions_delegate->IsChild(browser_context()) &&
+ // Don't prompt the user if the extension has unsupported requirements.
+ // TODO(crbug/1071978): If OnRequirementsChecked() passes, the extension
+ // will enable, bypassing parent approval.
+ !HasUnsupportedRequirements(extension_id_) &&
+ // Only ask for parent approval if the extension still requires approval.
+ !supervised_user_extensions_delegate->IsExtensionAllowedByParent(
+ *target_extension, browser_context())) {
+ // Either ask for parent permission or notify the child that their parent
+ // has disabled this action.
+ auto parent_permission_callback = base::BindOnce(
+ &ManagementSetEnabledFunction::OnParentPermissionDialogDone, this);
+ auto error_callback = base::BindOnce(
+ &ManagementSetEnabledFunction::OnBlockedByParentDialogDone, this);
+ AddRef(); // Matched in OnParentPermissionDialogDone() or
+ // OnBlockedByParentDialogDone().
+ supervised_user_extensions_delegate->PromptForParentPermissionOrShowError(
+ *target_extension, browser_context(), GetSenderWebContents(),
+ std::move(parent_permission_callback), std::move(error_callback));
+ return RespondLater();
+ }
-#if defined(OS_CHROMEOS)
- // On ChromeOS, if this is a child, show the dialog indicating that enabling
- // extensions has been blocked by a parent.
- if (supervised_user_service_delegate &&
- supervised_user_service_delegate->IsChild(browser_context())) {
- AddRef(); // Matched in OnBlockedByParentDialogDone().
- ShowBlockedByParentDialog(target_extension);
- return RespondLater();
- }
-#endif
+ if (should_enable &&
+ policy->MustRemainDisabled(target_extension, nullptr, nullptr)) {
return RespondNow(Error(keys::kUserCantModifyError, extension_id_));
}
@@ -492,8 +476,7 @@ ExtensionFunction::ResponseAction ManagementSetEnabledFunction::Run() {
if (!currently_enabled && should_enable) {
ExtensionPrefs* prefs = ExtensionPrefs::Get(browser_context());
- if (!prompt_parent_for_approval &&
- prefs->DidExtensionEscalatePermissions(extension_id_)) {
+ if (prefs->DidExtensionEscalatePermissions(extension_id_)) {
if (!user_gesture())
return RespondNow(Error(keys::kGestureNeededForEscalationError));
@@ -503,8 +486,7 @@ ExtensionFunction::ResponseAction ManagementSetEnabledFunction::Run() {
base::Bind(&ManagementSetEnabledFunction::OnInstallPromptDone, this));
return RespondLater();
}
- if (prefs->GetDisableReasons(extension_id_) &
- disable_reason::DISABLE_UNSUPPORTED_REQUIREMENT) {
+ if (HasUnsupportedRequirements(extension_id_)) {
// Recheck the requirements.
requirements_checker_ =
std::make_unique<RequirementsChecker>(target_extension);
@@ -513,18 +495,6 @@ ExtensionFunction::ResponseAction ManagementSetEnabledFunction::Run() {
this)); // This bind creates a reference.
return RespondLater();
}
- // Handle parental approval for child accounts that have the ability to
- // install extensions.
- if (prompt_parent_for_approval &&
- // Don't re-prompt the parent for extensions that have already been
- // approved for a child.
- !supervised_user_service_delegate->IsExtensionAllowedByParent(
- *target_extension, browser_context())) {
- LOG(ERROR) << "ManagementSetEnabledFunction::Run: prompting for parent "
- "approval";
- return RequestParentPermission(target_extension);
- }
-
delegate->EnableExtension(browser_context(), extension_id_);
} else if (currently_enabled && !params->enabled) {
delegate->DisableExtension(
@@ -551,6 +521,13 @@ void ManagementSetEnabledFunction::OnInstallPromptDone(bool did_accept) {
Release(); // Balanced in Run().
}
+bool ManagementSetEnabledFunction::HasUnsupportedRequirements(
+ const std::string& extension_id) {
+ ExtensionPrefs* prefs = ExtensionPrefs::Get(browser_context());
+ return prefs->GetDisableReasons(extension_id) &
+ disable_reason::DISABLE_UNSUPPORTED_REQUIREMENT;
+}
+
void ManagementSetEnabledFunction::OnRequirementsChecked(
const PreloadCheck::Errors& errors) {
if (errors.empty()) {
@@ -564,30 +541,11 @@ void ManagementSetEnabledFunction::OnRequirementsChecked(
}
}
-ExtensionFunction::ResponseAction
-ManagementSetEnabledFunction::RequestParentPermission(
- const Extension* extension) {
- content::WebContents* web_contents = GetSenderWebContents();
- if (!web_contents)
- return RespondNow(Error(keys::kWebContentsDisappearedError));
-
- // Show parental approval prompt.
- auto callback = base::BindOnce(
- &ManagementSetEnabledFunction::OnParentPermissionDone, this);
- SupervisedUserServiceDelegate* supervised_user_service_delegate =
- ManagementAPI::GetFactoryInstance()
- ->Get(browser_context())
- ->GetSupervisedUserServiceDelegate();
- DCHECK(supervised_user_service_delegate);
- supervised_user_service_delegate->ShowParentPermissionDialogForExtension(
- *extension, browser_context(), web_contents, std::move(callback));
- return RespondLater();
-}
-
-void ManagementSetEnabledFunction::OnParentPermissionDone(
- SupervisedUserServiceDelegate::ParentPermissionDialogResult result) {
+void ManagementSetEnabledFunction::OnParentPermissionDialogDone(
+ SupervisedUserExtensionsDelegate::ParentPermissionDialogResult result) {
+#if defined(OS_CHROMEOS)
switch (result) {
- case SupervisedUserServiceDelegate::ParentPermissionDialogResult::
+ case SupervisedUserExtensionsDelegate::ParentPermissionDialogResult::
kParentPermissionReceived: {
const ManagementAPIDelegate* delegate =
ManagementAPI::GetFactoryInstance()
@@ -598,49 +556,21 @@ void ManagementSetEnabledFunction::OnParentPermissionDone(
break;
}
- case SupervisedUserServiceDelegate::ParentPermissionDialogResult::
+ case SupervisedUserExtensionsDelegate::ParentPermissionDialogResult::
kParentPermissionCanceled: {
Respond(Error(keys::kUserDidNotReEnableError));
break;
}
- case SupervisedUserServiceDelegate::ParentPermissionDialogResult::
+ case SupervisedUserExtensionsDelegate::ParentPermissionDialogResult::
kParentPermissionFailed: {
Respond(Error(keys::kParentPermissionFailedError));
break;
}
}
-}
-
-void ManagementSetEnabledFunction::ShowBlockedByParentDialog(
- const Extension* extension) {
-#if defined(OS_CHROMEOS)
- DCHECK(extension);
- SupervisedUserServiceDelegate* supervised_user_service_delegate =
- ManagementAPI::GetFactoryInstance()
- ->Get(browser_context())
- ->GetSupervisedUserServiceDelegate();
-
- supervised_user_service_delegate
- ->RecordExtensionEnableBlockedByParentDialogUmaMetric();
-
- content::WebContents* contents = GetSenderWebContents();
- web_modal::WebContentsModalDialogManager* manager =
- web_modal::WebContentsModalDialogManager::FromWebContents(contents);
- if (!contents || !contents->GetTopLevelNativeWindow() || !manager) {
- // If the contents are null, or there is no top level native window to
- // anchor the dialog on, or no dialog manager, skip showing the dialog and
- // return the error immediately.
- OnBlockedByParentDialogDone();
- return;
- }
- supervised_user_service_delegate
- ->ShowExtensionEnableBlockedByParentDialogForExtension(
- extension, contents,
- base::BindOnce(
- &ManagementSetEnabledFunction::OnBlockedByParentDialogDone,
- this));
-#endif
+ // Matches the AddRef in Run().
+ Release();
+#endif // defined(OS_CHROMEOS)
}
void ManagementSetEnabledFunction::OnBlockedByParentDialogDone() {
@@ -648,7 +578,7 @@ void ManagementSetEnabledFunction::OnBlockedByParentDialogDone() {
Respond(Error(keys::kUserCantModifyError, extension_id_));
// Matches the AddRef in Run().
Release();
-#endif
+#endif // defined(OS_CHROMEOS)
}
ManagementUninstallFunctionBase::ManagementUninstallFunctionBase() = default;
@@ -1180,8 +1110,9 @@ void ManagementEventRouter::BroadcastEvent(
ManagementAPI::ManagementAPI(content::BrowserContext* context)
: browser_context_(context),
delegate_(ExtensionsAPIClient::Get()->CreateManagementAPIDelegate()),
- supervised_user_service_delegate_(
- ExtensionsAPIClient::Get()->CreateSupervisedUserServiceDelegate()) {
+ supervised_user_extensions_delegate_(
+ ExtensionsAPIClient::Get()
+ ->CreateSupervisedUserExtensionsDelegate()) {
EventRouter* event_router = EventRouter::Get(browser_context_);
event_router->RegisterObserver(this, management::OnInstalled::kEventName);
event_router->RegisterObserver(this, management::OnUninstalled::kEventName);
diff --git a/chromium/extensions/browser/api/management/management_api.h b/chromium/extensions/browser/api/management/management_api.h
index 1e195465151..89b4205333a 100644
--- a/chromium/extensions/browser/api/management/management_api.h
+++ b/chromium/extensions/browser/api/management/management_api.h
@@ -14,13 +14,13 @@
#include "base/strings/string16.h"
#include "components/keyed_service/core/keyed_service.h"
#include "extensions/browser/api/management/management_api_delegate.h"
-#include "extensions/browser/api/management/supervised_user_service_delegate.h"
#include "extensions/browser/browser_context_keyed_api_factory.h"
#include "extensions/browser/event_router.h"
#include "extensions/browser/extension_event_histogram_value.h"
#include "extensions/browser/extension_function.h"
#include "extensions/browser/extension_registry_observer.h"
#include "extensions/browser/preload_check.h"
+#include "extensions/browser/supervised_user_extensions_delegate.h"
#include "services/data_decoder/public/cpp/data_decoder.h"
namespace extensions {
@@ -115,24 +115,18 @@ class ManagementSetEnabledFunction : public ExtensionFunction {
private:
void OnInstallPromptDone(bool did_accept);
- void OnRequirementsChecked(const PreloadCheck::Errors& errors);
-
- ExtensionFunction::ResponseAction RequestParentPermission(
- const Extension* extension);
+ bool HasUnsupportedRequirements(const std::string& extension_id);
- void OnParentPermissionDone(
- SupervisedUserServiceDelegate::ParentPermissionDialogResult result);
+ void OnRequirementsChecked(const PreloadCheck::Errors& errors);
- // Shows the dialog that tells the user that the parent has blocked the
- // installation of extensions, apps, etc.
- void ShowBlockedByParentDialog(const Extension* extension);
+ // Called when the user dismisses the Parent Permission Dialog.
+ void OnParentPermissionDialogDone(
+ SupervisedUserExtensionsDelegate::ParentPermissionDialogResult result);
- // Called when the dialog shown by ShowBlockedByParentDialog() is dismissed.
+ // Called when the user dismisses the Extension Install Blocked By Parent
+ // Dialog.
void OnBlockedByParentDialogDone();
- std::unique_ptr<SupervisedUserServiceDelegate::ParentPermissionDialogResult>
- parental_permission_dialog_;
-
std::string extension_id_;
std::unique_ptr<InstallPromptDelegate> install_prompt_;
@@ -334,16 +328,17 @@ class ManagementAPI : public BrowserContextKeyedAPI,
// Returns the SupervisedUserService delegate, which might be null depending
// on the extensions embedder.
- SupervisedUserServiceDelegate* GetSupervisedUserServiceDelegate() const {
- return supervised_user_service_delegate_.get();
+ SupervisedUserExtensionsDelegate* GetSupervisedUserExtensionsDelegate()
+ const {
+ return supervised_user_extensions_delegate_.get();
}
void set_delegate_for_test(std::unique_ptr<ManagementAPIDelegate> delegate) {
delegate_ = std::move(delegate);
}
- void set_supervised_user_service_delegate_for_test(
- std::unique_ptr<SupervisedUserServiceDelegate> delegate) {
- supervised_user_service_delegate_ = std::move(delegate);
+ void set_supervised_user_extensions_delegate_for_test(
+ std::unique_ptr<SupervisedUserExtensionsDelegate> delegate) {
+ supervised_user_extensions_delegate_ = std::move(delegate);
}
private:
@@ -360,8 +355,8 @@ class ManagementAPI : public BrowserContextKeyedAPI,
std::unique_ptr<ManagementEventRouter> management_event_router_;
std::unique_ptr<ManagementAPIDelegate> delegate_;
- std::unique_ptr<SupervisedUserServiceDelegate>
- supervised_user_service_delegate_;
+ std::unique_ptr<SupervisedUserExtensionsDelegate>
+ supervised_user_extensions_delegate_;
DISALLOW_COPY_AND_ASSIGN(ManagementAPI);
};
diff --git a/chromium/extensions/browser/api/management/management_api_constants.cc b/chromium/extensions/browser/api/management/management_api_constants.cc
index 5069a509e44..686075749ac 100644
--- a/chromium/extensions/browser/api/management/management_api_constants.cc
+++ b/chromium/extensions/browser/api/management/management_api_constants.cc
@@ -63,8 +63,6 @@ const char kInstallReplacementAndroidAppNotFromWebstoreError[] =
"Only extensions from the web store can install replacement Android apps.";
const char kInstallReplacementAndroidAppCannotInstallApp[] =
"Could not install Android App.";
-const char kWebContentsDisappearedError[] =
- "Web contents disappeared while attempting to enable extension.";
const char kParentPermissionFailedError[] = "Parent Permission Request Failed.";
} // namespace extension_management_api_constants
diff --git a/chromium/extensions/browser/api/management/management_api_constants.h b/chromium/extensions/browser/api/management/management_api_constants.h
index d93cbbdcf57..a0c5aeb7736 100644
--- a/chromium/extensions/browser/api/management/management_api_constants.h
+++ b/chromium/extensions/browser/api/management/management_api_constants.h
@@ -44,7 +44,6 @@ extern const char kGestureNeededForInstallReplacementAndroidAppError[];
extern const char kInstallReplacementAndroidAppCannotInstallApp[];
extern const char kInstallReplacementAndroidAppInvalidContextError[];
extern const char kInstallReplacementAndroidAppNotFromWebstoreError[];
-extern const char kWebContentsDisappearedError[];
extern const char kParentPermissionFailedError[];
} // namespace extension_management_api_constants
diff --git a/chromium/extensions/browser/api/management/supervised_user_service_delegate.h b/chromium/extensions/browser/api/management/supervised_user_service_delegate.h
deleted file mode 100644
index 57b879d844c..00000000000
--- a/chromium/extensions/browser/api/management/supervised_user_service_delegate.h
+++ /dev/null
@@ -1,68 +0,0 @@
-// Copyright 2020 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 EXTENSIONS_BROWSER_API_MANAGEMENT_SUPERVISED_USER_SERVICE_DELEGATE_H_
-#define EXTENSIONS_BROWSER_API_MANAGEMENT_SUPERVISED_USER_SERVICE_DELEGATE_H_
-
-#include "base/callback.h"
-#include "extensions/common/extension.h"
-
-namespace content {
-class BrowserContext;
-class WebContents;
-} // namespace content
-
-namespace extensions {
-
-class SupervisedUserServiceDelegate {
- public:
- virtual ~SupervisedUserServiceDelegate() = default;
-
- // Returns true if |context| represents a supervised child account.
- virtual bool IsChild(content::BrowserContext* context) const = 0;
-
- // Returns true if |context| represents a supervised child account
- // who may install extensions with parent permission.
- virtual bool IsSupervisedChildWhoMayInstallExtensions(
- content::BrowserContext* context) const = 0;
-
- // Returns true if the current child user is allowed to install the specified
- // |extension|.
- virtual bool IsExtensionAllowedByParent(
- const extensions::Extension& extension,
- content::BrowserContext* context) const = 0;
-
- // Result of the parent permission dialog invocation.
- enum class ParentPermissionDialogResult {
- kParentPermissionReceived,
- kParentPermissionCanceled,
- kParentPermissionFailed,
- };
-
- using ParentPermissionDialogDoneCallback =
- base::OnceCallback<void(ParentPermissionDialogResult)>;
-
- // Shows a parent permission dialog for |extension| and call |done_callback|
- // when it completes.
- virtual void ShowParentPermissionDialogForExtension(
- const extensions::Extension& extension,
- content::BrowserContext* context,
- content::WebContents* contents,
- ParentPermissionDialogDoneCallback done_callback) = 0;
-
- // Shows a dialog indicating that |extension| has been blocked and call
- // |done_callback| when it completes.
- virtual void ShowExtensionEnableBlockedByParentDialogForExtension(
- const extensions::Extension* extension,
- content::WebContents* contents,
- base::OnceClosure done_callback) = 0;
-
- // Records UMA metrics for supervised users trying to install or enable an
- // extension when this action is blocked by the parent.
- virtual void RecordExtensionEnableBlockedByParentDialogUmaMetric() = 0;
-};
-
-} // namespace extensions
-
-#endif // EXTENSIONS_BROWSER_API_MANAGEMENT_SUPERVISED_USER_SERVICE_DELEGATE_H_
diff --git a/chromium/extensions/browser/api/media_perception_private/media_perception_api_manager.cc b/chromium/extensions/browser/api/media_perception_private/media_perception_api_manager.cc
index a06c5c79819..ca357c884dc 100644
--- a/chromium/extensions/browser/api/media_perception_private/media_perception_api_manager.cc
+++ b/chromium/extensions/browser/api/media_perception_private/media_perception_api_manager.cc
@@ -413,7 +413,6 @@ void MediaPerceptionAPIManager::SendMojoInvitation(
base::kNullProcessHandle,
channel.TakeLocalEndpoint());
- media_perception_service_.reset();
media_perception_service_.Bind(
mojo::PendingRemote<
chromeos::media_perception::mojom::MediaPerceptionService>(
@@ -469,7 +468,6 @@ void MediaPerceptionAPIManager::OnBootstrapMojoConnection(
return;
}
- media_perception_controller_.reset();
auto controller_receiver =
media_perception_controller_.BindNewPipeAndPassReceiver();
diff --git a/chromium/extensions/browser/api/messaging/extension_message_port.cc b/chromium/extensions/browser/api/messaging/extension_message_port.cc
index d0213afb567..fc89cf6ac3d 100644
--- a/chromium/extensions/browser/api/messaging/extension_message_port.cc
+++ b/chromium/extensions/browser/api/messaging/extension_message_port.cc
@@ -45,7 +45,7 @@ class ExtensionMessagePort::FrameTracker : public content::WebContentsObserver,
public ProcessManagerObserver {
public:
explicit FrameTracker(ExtensionMessagePort* port)
- : pm_observer_(this), port_(port), interstitial_frame_(nullptr) {}
+ : pm_observer_(this), port_(port) {}
~FrameTracker() override {}
void TrackExtensionProcessFrames() {
@@ -56,17 +56,6 @@ class ExtensionMessagePort::FrameTracker : public content::WebContentsObserver,
Observe(tab);
}
- void TrackInterstitialFrame(content::WebContents* tab,
- content::RenderFrameHost* interstitial_frame) {
- // |tab| should never be nullptr, because an interstitial's lifetime is
- // tied to a tab. This is a CHECK, not a DCHECK because we really need an
- // observer subject to detect frame removal (via DidDetachInterstitialPage).
- CHECK(tab);
- DCHECK(interstitial_frame);
- interstitial_frame_ = interstitial_frame;
- Observe(tab);
- }
-
private:
// content::WebContentsObserver overrides:
void RenderFrameDeleted(content::RenderFrameHost* render_frame_host)
@@ -82,11 +71,6 @@ class ExtensionMessagePort::FrameTracker : public content::WebContentsObserver,
}
}
- void DidDetachInterstitialPage() override {
- if (interstitial_frame_)
- port_->UnregisterFrame(interstitial_frame_);
- }
-
// extensions::ProcessManagerObserver overrides:
void OnExtensionFrameUnregistered(
const std::string& extension_id,
@@ -102,11 +86,6 @@ class ExtensionMessagePort::FrameTracker : public content::WebContentsObserver,
ScopedObserver<ProcessManager, ProcessManagerObserver> pm_observer_;
ExtensionMessagePort* port_; // Owns this FrameTracker.
- // Set to the main frame of an interstitial if we are tracking an interstitial
- // page, because RenderFrameDeleted is never triggered for frames in an
- // interstitial (and we only support tracking the interstitial's main frame).
- content::RenderFrameHost* interstitial_frame_;
-
DISALLOW_COPY_AND_ASSIGN(FrameTracker);
};
diff --git a/chromium/extensions/browser/api/networking_private/networking_private_chromeos_unittest.cc b/chromium/extensions/browser/api/networking_private/networking_private_chromeos_unittest.cc
index 208cfd3398d..fed448ac062 100644
--- a/chromium/extensions/browser/api/networking_private/networking_private_chromeos_unittest.cc
+++ b/chromium/extensions/browser/api/networking_private/networking_private_chromeos_unittest.cc
@@ -1099,6 +1099,7 @@ TEST_F(NetworkingPrivateApiTest, GetCellularProperties) {
.Build())
.Set("ConnectionState", "Connected")
.Set("GUID", "cellular_guid")
+ .Set("Metered", true)
.Set("Name", "cellular")
.Set("Source", "User")
.Set("Type", "Cellular")
@@ -1158,6 +1159,7 @@ TEST_F(NetworkingPrivateApiTest, GetCellularPropertiesFromWebUi) {
.Build())
.Set("ConnectionState", "Connected")
.Set("GUID", "cellular_guid")
+ .Set("Metered", true)
.Set("Name", "cellular")
.Set("Source", "User")
.Set("Type", "Cellular")
diff --git a/chromium/extensions/browser/api/networking_private/networking_private_linux.cc b/chromium/extensions/browser/api/networking_private/networking_private_linux.cc
index f938c2d4715..0a0bcd94f9d 100644
--- a/chromium/extensions/browser/api/networking_private/networking_private_linux.cc
+++ b/chromium/extensions/browser/api/networking_private/networking_private_linux.cc
@@ -13,7 +13,6 @@
#include "base/strings/string16.h"
#include "base/strings/string_split.h"
#include "base/strings/utf_string_conversions.h"
-#include "base/task/post_task.h"
#include "components/onc/onc_constants.h"
#include "content/public/browser/browser_task_traits.h"
#include "content/public/browser/browser_thread.h"
@@ -136,7 +135,7 @@ void GetCachedNetworkPropertiesCallback(
} // namespace
NetworkingPrivateLinux::NetworkingPrivateLinux()
- : dbus_thread_("Networking Private DBus"), network_manager_proxy_(NULL) {
+ : dbus_thread_("Networking Private DBus"), network_manager_proxy_(nullptr) {
base::Thread::Options thread_options(base::MessagePumpType::IO, 0);
dbus_thread_.StartWithOptions(thread_options);
@@ -1221,8 +1220,8 @@ void NetworkingPrivateLinux::PostOnNetworksChangedToUIThread(
std::unique_ptr<GuidList> guid_list) {
AssertOnDBusThread();
- base::PostTask(
- FROM_HERE, {content::BrowserThread::UI},
+ content::GetUIThreadTaskRunner({})->PostTask(
+ FROM_HERE,
base::BindOnce(&NetworkingPrivateLinux::OnNetworksChangedEventTask,
base::Unretained(this), std::move(guid_list)));
}
diff --git a/chromium/extensions/browser/api/serial/serial_api.cc b/chromium/extensions/browser/api/serial/serial_api.cc
index 096f736cba1..a0bfd248b16 100644
--- a/chromium/extensions/browser/api/serial/serial_api.cc
+++ b/chromium/extensions/browser/api/serial/serial_api.cc
@@ -81,8 +81,35 @@ ExtensionFunction::ResponseAction SerialGetDevicesFunction::Run() {
void SerialGetDevicesFunction::OnGotDevices(
std::vector<device::mojom::SerialPortInfoPtr> devices) {
- Respond(ArgumentList(serial::GetDevices::Results::Create(
- mojo::ConvertTo<std::vector<serial::DeviceInfo>>(devices))));
+ std::vector<extensions::api::serial::DeviceInfo> results;
+ for (const auto& device : devices) {
+ extensions::api::serial::DeviceInfo info;
+ info.path = device->path.AsUTF8Unsafe();
+ if (device->has_vendor_id)
+ info.vendor_id = std::make_unique<int>(device->vendor_id);
+ if (device->has_product_id)
+ info.product_id = std::make_unique<int>(device->product_id);
+ if (device->display_name)
+ info.display_name = std::make_unique<std::string>(*device->display_name);
+ results.push_back(std::move(info));
+
+#if defined(OS_MACOSX)
+ if (device->alternate_path) {
+ extensions::api::serial::DeviceInfo alternate_info;
+ alternate_info.path = device->alternate_path->AsUTF8Unsafe();
+ if (device->has_vendor_id)
+ alternate_info.vendor_id = std::make_unique<int>(device->vendor_id);
+ if (device->has_product_id)
+ alternate_info.product_id = std::make_unique<int>(device->product_id);
+ if (device->display_name) {
+ alternate_info.display_name =
+ std::make_unique<std::string>(*device->display_name);
+ }
+ results.push_back(std::move(alternate_info));
+ }
+#endif // defined(OS_MACOSX)
+ }
+ Respond(ArgumentList(serial::GetDevices::Results::Create(results)));
}
SerialConnectFunction::SerialConnectFunction() {}
@@ -438,23 +465,3 @@ void SerialClearBreakFunction::OnClearBreak(bool success) {
} // namespace api
} // namespace extensions
-
-namespace mojo {
-
-// static
-extensions::api::serial::DeviceInfo
-TypeConverter<extensions::api::serial::DeviceInfo,
- device::mojom::SerialPortInfoPtr>::
- Convert(const device::mojom::SerialPortInfoPtr& device) {
- extensions::api::serial::DeviceInfo info;
- info.path = device->path.AsUTF8Unsafe();
- if (device->has_vendor_id)
- info.vendor_id.reset(new int(static_cast<int>(device->vendor_id)));
- if (device->has_product_id)
- info.product_id.reset(new int(static_cast<int>(device->product_id)));
- if (device->display_name)
- info.display_name.reset(new std::string(device->display_name.value()));
- return info;
-}
-
-} // namespace mojo
diff --git a/chromium/extensions/browser/api/serial/serial_apitest.cc b/chromium/extensions/browser/api/serial/serial_apitest.cc
index c268ac59e72..9aa02113827 100644
--- a/chromium/extensions/browser/api/serial/serial_apitest.cc
+++ b/chromium/extensions/browser/api/serial/serial_apitest.cc
@@ -86,8 +86,6 @@ class FakeSerialPort : public device::mojom::SerialPort {
private:
// device::mojom::SerialPort methods:
void Open(device::mojom::SerialConnectionOptionsPtr options,
- mojo::ScopedDataPipeConsumerHandle in_stream,
- mojo::ScopedDataPipeProducerHandle out_stream,
mojo::PendingRemote<device::mojom::SerialPortClient> client,
OpenCallback callback) override {
if (client_) {
@@ -99,22 +97,35 @@ class FakeSerialPort : public device::mojom::SerialPort {
DoConfigurePort(*options);
DCHECK(client);
client_.Bind(std::move(client));
- SetUpInStreamPipe(std::move(in_stream));
- SetUpOutStreamPipe(std::move(out_stream));
std::move(callback).Run(true);
}
- void ClearSendError(mojo::ScopedDataPipeConsumerHandle consumer) override {
- if (in_stream_) {
+
+ void StartWriting(mojo::ScopedDataPipeConsumerHandle consumer) override {
+ if (in_stream_)
return;
- }
- SetUpInStreamPipe(std::move(consumer));
+
+ in_stream_ = std::move(consumer);
+ in_stream_watcher_.Watch(
+ in_stream_.get(),
+ MOJO_HANDLE_SIGNAL_READABLE | MOJO_HANDLE_SIGNAL_PEER_CLOSED,
+ MOJO_TRIGGER_CONDITION_SIGNALS_SATISFIED,
+ base::BindRepeating(&FakeSerialPort::DoWrite, base::Unretained(this)));
+ in_stream_watcher_.ArmOrNotify();
}
- void ClearReadError(mojo::ScopedDataPipeProducerHandle producer) override {
- if (out_stream_) {
+
+ void StartReading(mojo::ScopedDataPipeProducerHandle producer) override {
+ if (out_stream_)
return;
- }
- SetUpOutStreamPipe(std::move(producer));
+
+ out_stream_ = std::move(producer);
+ out_stream_watcher_.Watch(
+ out_stream_.get(),
+ MOJO_HANDLE_SIGNAL_WRITABLE | MOJO_HANDLE_SIGNAL_PEER_CLOSED,
+ MOJO_TRIGGER_CONDITION_SIGNALS_SATISFIED,
+ base::BindRepeating(&FakeSerialPort::DoRead, base::Unretained(this)));
+ out_stream_watcher_.ArmOrNotify();
}
+
void Flush(FlushCallback callback) override { std::move(callback).Run(true); }
void GetControlSignals(GetControlSignalsCallback callback) override {
auto signals = device::mojom::SerialPortControlSignals::New();
@@ -152,16 +163,6 @@ class FakeSerialPort : public device::mojom::SerialPort {
std::move(callback).Run();
}
- void SetUpInStreamPipe(mojo::ScopedDataPipeConsumerHandle consumer) {
- in_stream_.swap(consumer);
- in_stream_watcher_.Watch(
- in_stream_.get(),
- MOJO_HANDLE_SIGNAL_READABLE | MOJO_HANDLE_SIGNAL_PEER_CLOSED,
- MOJO_TRIGGER_CONDITION_SIGNALS_SATISFIED,
- base::BindRepeating(&FakeSerialPort::DoWrite, base::Unretained(this)));
- in_stream_watcher_.ArmOrNotify();
- }
-
void DoWrite(MojoResult result, const mojo::HandleSignalsState& state) {
const void* data;
uint32_t num_bytes;
@@ -201,16 +202,6 @@ class FakeSerialPort : public device::mojom::SerialPort {
NOTREACHED();
}
- void SetUpOutStreamPipe(mojo::ScopedDataPipeProducerHandle producer) {
- out_stream_.swap(producer);
- out_stream_watcher_.Watch(
- out_stream_.get(),
- MOJO_HANDLE_SIGNAL_WRITABLE | MOJO_HANDLE_SIGNAL_PEER_CLOSED,
- MOJO_TRIGGER_CONDITION_SIGNALS_SATISFIED,
- base::BindRepeating(&FakeSerialPort::DoRead, base::Unretained(this)));
- out_stream_watcher_.ArmOrNotify();
- }
-
void DoRead(MojoResult result, const mojo::HandleSignalsState& state) {
if (result != MOJO_RESULT_OK) {
out_stream_.reset();
@@ -311,6 +302,7 @@ class FakeSerialPortManager : public device::mojom::SerialPortManager {
}
void GetPort(const base::UnguessableToken& token,
+ bool use_alternate_path,
mojo::PendingReceiver<device::mojom::SerialPort> receiver,
mojo::PendingRemote<device::mojom::SerialPortConnectionWatcher>
watcher) override {
diff --git a/chromium/extensions/browser/api/serial/serial_connection.cc b/chromium/extensions/browser/api/serial/serial_connection.cc
index f8fb970a6e5..5df8db36db8 100644
--- a/chromium/extensions/browser/api/serial/serial_connection.cc
+++ b/chromium/extensions/browser/api/serial/serial_connection.cc
@@ -209,13 +209,8 @@ void SerialConnection::SetPaused(bool paused) {
} else {
// If |receive_pipe_| is closed and there is no pending ReceiveError event,
// try to reconnect the data pipe.
- if (!receive_pipe_ && !read_error_) {
- mojo::ScopedDataPipeProducerHandle producer;
- mojo::ScopedDataPipeConsumerHandle consumer;
- CreatePipe(&producer, &consumer);
- SetUpReceiveDataPipe(std::move(consumer));
- serial_port_->ClearReadError(std::move(producer));
- }
+ if (!receive_pipe_ && !read_error_)
+ SetUpReceiveDataPipe();
receive_pipe_watcher_.ArmOrNotify();
receive_timeout_task_.Cancel();
SetTimeoutCallback();
@@ -249,22 +244,12 @@ void SerialConnection::Open(const api::serial::ConnectionOptions& options,
if (options.send_timeout.get())
set_send_timeout(*options.send_timeout);
- mojo::ScopedDataPipeProducerHandle receive_producer;
- mojo::ScopedDataPipeConsumerHandle receive_consumer;
- CreatePipe(&receive_producer, &receive_consumer);
-
- mojo::ScopedDataPipeProducerHandle send_producer;
- mojo::ScopedDataPipeConsumerHandle send_consumer;
- CreatePipe(&send_producer, &send_consumer);
-
mojo::PendingRemote<device::mojom::SerialPortClient> client;
auto client_receiver = client.InitWithNewPipeAndPassReceiver();
serial_port_->Open(
- device::mojom::SerialConnectionOptions::From(options),
- std::move(send_consumer), std::move(receive_producer), std::move(client),
+ device::mojom::SerialConnectionOptions::From(options), std::move(client),
mojo::WrapCallbackWithDefaultInvokeIfNotRun(
base::BindOnce(&SerialConnection::OnOpen, weak_factory_.GetWeakPtr(),
- std::move(receive_consumer), std::move(send_producer),
std::move(client_receiver), std::move(callback)),
false));
}
@@ -281,9 +266,12 @@ void SerialConnection::CreatePipe(
CHECK_EQ(MOJO_RESULT_OK, mojo::CreateDataPipe(&options, producer, consumer));
}
-void SerialConnection::SetUpReceiveDataPipe(
- mojo::ScopedDataPipeConsumerHandle consumer) {
- receive_pipe_ = std::move(consumer);
+void SerialConnection::SetUpReceiveDataPipe() {
+ mojo::ScopedDataPipeProducerHandle producer;
+ CreatePipe(&producer, &receive_pipe_);
+
+ serial_port_->StartReading(std::move(producer));
+
receive_pipe_watcher_.Watch(
receive_pipe_.get(),
MOJO_HANDLE_SIGNAL_READABLE | MOJO_HANDLE_SIGNAL_PEER_CLOSED,
@@ -292,9 +280,12 @@ void SerialConnection::SetUpReceiveDataPipe(
weak_factory_.GetWeakPtr()));
}
-void SerialConnection::SetUpSendDataPipe(
- mojo::ScopedDataPipeProducerHandle producer) {
- send_pipe_ = std::move(producer);
+void SerialConnection::SetUpSendDataPipe() {
+ mojo::ScopedDataPipeConsumerHandle consumer;
+ CreatePipe(&send_pipe_, &consumer);
+
+ serial_port_->StartWriting(std::move(consumer));
+
send_pipe_watcher_.Watch(
send_pipe_.get(),
MOJO_HANDLE_SIGNAL_WRITABLE | MOJO_HANDLE_SIGNAL_PEER_CLOSED,
@@ -330,8 +321,6 @@ void SerialConnection::OnSendError(device::mojom::SerialSendError error) {
}
void SerialConnection::OnOpen(
- mojo::ScopedDataPipeConsumerHandle consumer,
- mojo::ScopedDataPipeProducerHandle producer,
mojo::PendingReceiver<device::mojom::SerialPortClient> client_receiver,
OpenCompleteCallback callback,
bool success) {
@@ -340,8 +329,8 @@ void SerialConnection::OnOpen(
return;
}
- SetUpReceiveDataPipe(std::move(consumer));
- SetUpSendDataPipe(std::move(producer));
+ SetUpReceiveDataPipe();
+ SetUpSendDataPipe();
client_receiver_.Bind(std::move(client_receiver));
client_receiver_.set_disconnect_handler(base::BindOnce(
&SerialConnection::OnClientReceiverClosed, weak_factory_.GetWeakPtr()));
@@ -419,13 +408,8 @@ bool SerialConnection::Send(const std::vector<uint8_t>& data,
DCHECK(data_to_send_.empty());
data_to_send_.assign(data.begin(), data.end());
- if (!send_pipe_) {
- mojo::ScopedDataPipeProducerHandle producer;
- mojo::ScopedDataPipeConsumerHandle consumer;
- CreatePipe(&producer, &consumer);
- SetUpSendDataPipe(std::move(producer));
- serial_port_->ClearSendError(std::move(consumer));
- }
+ if (!send_pipe_)
+ SetUpSendDataPipe();
send_pipe_watcher_.ArmOrNotify();
send_timeout_task_.Cancel();
diff --git a/chromium/extensions/browser/api/serial/serial_connection.h b/chromium/extensions/browser/api/serial/serial_connection.h
index 9ee96ad3758..29cf85cb16e 100644
--- a/chromium/extensions/browser/api/serial/serial_connection.h
+++ b/chromium/extensions/browser/api/serial/serial_connection.h
@@ -146,8 +146,6 @@ class SerialConnection : public ApiResource,
void OnSendError(device::mojom::SerialSendError error) override;
void OnOpen(
- mojo::ScopedDataPipeConsumerHandle consumer,
- mojo::ScopedDataPipeProducerHandle producer,
mojo::PendingReceiver<device::mojom::SerialPortClient> client_receiver,
OpenCompleteCallback callback,
bool success);
@@ -160,8 +158,8 @@ class SerialConnection : public ApiResource,
void CreatePipe(mojo::ScopedDataPipeProducerHandle* producer,
mojo::ScopedDataPipeConsumerHandle* consumer);
- void SetUpReceiveDataPipe(mojo::ScopedDataPipeConsumerHandle producer);
- void SetUpSendDataPipe(mojo::ScopedDataPipeProducerHandle consumer);
+ void SetUpReceiveDataPipe();
+ void SetUpSendDataPipe();
void SetTimeoutCallback();
diff --git a/chromium/extensions/browser/api/serial/serial_port_manager.cc b/chromium/extensions/browser/api/serial/serial_port_manager.cc
index 4194ea83be0..559eb121954 100644
--- a/chromium/extensions/browser/api/serial/serial_port_manager.cc
+++ b/chromium/extensions/browser/api/serial/serial_port_manager.cc
@@ -9,6 +9,7 @@
#include "base/bind.h"
#include "base/lazy_instance.h"
#include "base/no_destructor.h"
+#include "build/build_config.h"
#include "content/public/browser/browser_task_traits.h"
#include "content/public/browser/browser_thread.h"
#include "content/public/browser/device_service.h"
@@ -188,10 +189,21 @@ void SerialPortManager::OnGotDevicesToGetPort(
for (auto& device : devices) {
if (device->path.AsUTF8Unsafe() == path) {
- port_manager_->GetPort(device->token, std::move(receiver),
+ port_manager_->GetPort(device->token, /*use_alternate_path=*/false,
+ std::move(receiver),
/*watcher=*/mojo::NullRemote());
return;
}
+
+#if defined(OS_MACOSX)
+ if (device->alternate_path &&
+ device->alternate_path->AsUTF8Unsafe() == path) {
+ port_manager_->GetPort(device->token, /*use_alternate_path=*/true,
+ std::move(receiver),
+ /*watcher=*/mojo::NullRemote());
+ return;
+ }
+#endif // defined(OS_MACOSX)
}
}
diff --git a/chromium/extensions/browser/api/socket/socket_api.cc b/chromium/extensions/browser/api/socket/socket_api.cc
index 5227ee331cd..6daca9a2902 100644
--- a/chromium/extensions/browser/api/socket/socket_api.cc
+++ b/chromium/extensions/browser/api/socket/socket_api.cc
@@ -9,7 +9,6 @@
#include <vector>
#include "base/bind.h"
-#include "base/task/post_task.h"
#include "base/values.h"
#include "build/build_config.h"
#include "content/public/browser/browser_context.h"
@@ -127,8 +126,8 @@ void SocketAsyncApiFunction::OpenFirewallHole(const std::string& address,
? AppFirewallHole::PortType::TCP
: AppFirewallHole::PortType::UDP;
- base::PostTask(
- FROM_HERE, {BrowserThread::UI},
+ content::GetUIThreadTaskRunner({})->PostTask(
+ FROM_HERE,
base::BindOnce(&SocketAsyncApiFunction::OpenFirewallHoleOnUIThread,
this, type, local_address.port(), socket_id));
return;
@@ -148,8 +147,8 @@ void SocketAsyncApiFunction::OpenFirewallHoleOnUIThread(
AppFirewallHoleManager::Get(browser_context());
std::unique_ptr<AppFirewallHole, BrowserThread::DeleteOnUIThread> hole(
manager->Open(type, port, extension_id()).release());
- base::PostTask(FROM_HERE, {BrowserThread::IO},
- base::BindOnce(&SocketAsyncApiFunction::OnFirewallHoleOpened,
+ content::GetIOThreadTaskRunner({})->PostTask(
+ FROM_HERE, base::BindOnce(&SocketAsyncApiFunction::OnFirewallHoleOpened,
this, socket_id, std::move(hole)));
}
diff --git a/chromium/extensions/browser/api/socket/socket_api.h b/chromium/extensions/browser/api/socket/socket_api.h
index 8b2ac098706..c1c7904d8fd 100644
--- a/chromium/extensions/browser/api/socket/socket_api.h
+++ b/chromium/extensions/browser/api/socket/socket_api.h
@@ -72,7 +72,7 @@ class SocketResourceManagerInterface {
template <typename T>
class SocketResourceManager : public SocketResourceManagerInterface {
public:
- SocketResourceManager() : manager_(NULL) {}
+ SocketResourceManager() : manager_(nullptr) {}
bool SetBrowserContext(content::BrowserContext* context) override {
manager_ = ApiResourceManager<T>::Get(context);
@@ -81,7 +81,7 @@ class SocketResourceManager : public SocketResourceManagerInterface {
"If this assertion is failing during a test, then it is likely that "
"TestExtensionSystem is failing to provide an instance of "
"ApiResourceManager<Socket>.";
- return manager_ != NULL;
+ return !!manager_;
}
int Add(Socket* socket) override {
diff --git a/chromium/extensions/browser/api/socket/tcp_socket.cc b/chromium/extensions/browser/api/socket/tcp_socket.cc
index b01331a2c09..9aafd37de0f 100644
--- a/chromium/extensions/browser/api/socket/tcp_socket.cc
+++ b/chromium/extensions/browser/api/socket/tcp_socket.cc
@@ -12,7 +12,6 @@
#include "base/logging.h"
#include "base/macros.h"
#include "base/memory/ptr_util.h"
-#include "base/task/post_task.h"
#include "content/public/browser/browser_context.h"
#include "content/public/browser/browser_task_traits.h"
#include "content/public/browser/browser_thread.h"
@@ -139,8 +138,8 @@ void TCPSocket::Connect(const net::AddressList& address,
base::BindOnce(&TCPSocket::OnConnectCompleteOnUIThread, task_runner_,
std::move(completion_callback));
- base::PostTask(FROM_HERE, {content::BrowserThread::UI},
- base::BindOnce(&TCPSocket::ConnectOnUIThread,
+ content::GetUIThreadTaskRunner({})->PostTask(
+ FROM_HERE, base::BindOnce(&TCPSocket::ConnectOnUIThread,
storage_partition_, browser_context_, address,
client_socket_.BindNewPipeAndPassReceiver(),
std::move(completion_callback_ui)));
@@ -263,8 +262,8 @@ void TCPSocket::Listen(const std::string& address,
base::BindOnce(&TCPSocket::OnListenCompleteOnUIThread, task_runner_,
std::move(completion_callback));
- base::PostTask(
- FROM_HERE, {content::BrowserThread::UI},
+ content::GetUIThreadTaskRunner({})->PostTask(
+ FROM_HERE,
base::BindOnce(&TCPSocket::ListenOnUIThread, storage_partition_,
browser_context_, ip_end_point, backlog,
server_socket_.BindNewPipeAndPassReceiver(),
diff --git a/chromium/extensions/browser/api/sockets_tcp/sockets_tcp_api.cc b/chromium/extensions/browser/api/sockets_tcp/sockets_tcp_api.cc
index 73597138d33..1cd59b1f01f 100644
--- a/chromium/extensions/browser/api/sockets_tcp/sockets_tcp_api.cc
+++ b/chromium/extensions/browser/api/sockets_tcp/sockets_tcp_api.cc
@@ -163,7 +163,7 @@ void SocketsTcpUpdateFunction::Work() {
}
SocketsTcpSetPausedFunction::SocketsTcpSetPausedFunction()
- : socket_event_dispatcher_(NULL) {}
+ : socket_event_dispatcher_(nullptr) {}
SocketsTcpSetPausedFunction::~SocketsTcpSetPausedFunction() {}
@@ -177,7 +177,7 @@ bool SocketsTcpSetPausedFunction::Prepare() {
"If this assertion is failing during a test, then it is likely that "
"TestExtensionSystem is failing to provide an instance of "
"TCPSocketEventDispatcher.";
- return socket_event_dispatcher_ != NULL;
+ return !!socket_event_dispatcher_;
}
void SocketsTcpSetPausedFunction::Work() {
@@ -264,7 +264,7 @@ void SocketsTcpSetNoDelayFunction::OnCompleted(bool success) {
}
SocketsTcpConnectFunction::SocketsTcpConnectFunction()
- : socket_event_dispatcher_(NULL) {}
+ : socket_event_dispatcher_(nullptr) {}
SocketsTcpConnectFunction::~SocketsTcpConnectFunction() {}
@@ -278,7 +278,7 @@ bool SocketsTcpConnectFunction::Prepare() {
"If this assertion is failing during a test, then it is likely that "
"TestExtensionSystem is failing to provide an instance of "
"TCPSocketEventDispatcher.";
- return socket_event_dispatcher_ != NULL;
+ return !!socket_event_dispatcher_;
}
void SocketsTcpConnectFunction::AsyncWorkStart() {
@@ -457,7 +457,7 @@ bool SocketsTcpGetSocketsFunction::Prepare() { return true; }
void SocketsTcpGetSocketsFunction::Work() {
std::vector<sockets_tcp::SocketInfo> socket_infos;
std::unordered_set<int>* resource_ids = GetSocketIds();
- if (resource_ids != NULL) {
+ if (resource_ids) {
for (int socket_id : *resource_ids) {
ResumableTCPSocket* socket = GetTcpSocket(socket_id);
if (socket) {
diff --git a/chromium/extensions/browser/api/sockets_tcp/tcp_socket_event_dispatcher.cc b/chromium/extensions/browser/api/sockets_tcp/tcp_socket_event_dispatcher.cc
index 69f7e9c1be8..8bab3a92a30 100644
--- a/chromium/extensions/browser/api/sockets_tcp/tcp_socket_event_dispatcher.cc
+++ b/chromium/extensions/browser/api/sockets_tcp/tcp_socket_event_dispatcher.cc
@@ -183,8 +183,8 @@ void TCPSocketEventDispatcher::PostEvent(const ReadParams& params,
std::unique_ptr<Event> event) {
DCHECK_CURRENTLY_ON(params.thread_id);
- base::PostTask(FROM_HERE, {BrowserThread::UI},
- base::BindOnce(&DispatchEvent, params.browser_context_id,
+ content::GetUIThreadTaskRunner({})->PostTask(
+ FROM_HERE, base::BindOnce(&DispatchEvent, params.browser_context_id,
params.extension_id, std::move(event)));
}
diff --git a/chromium/extensions/browser/api/sockets_tcp_server/sockets_tcp_server_api.cc b/chromium/extensions/browser/api/sockets_tcp_server/sockets_tcp_server_api.cc
index 4664d5808c2..f7b4cf5d008 100644
--- a/chromium/extensions/browser/api/sockets_tcp_server/sockets_tcp_server_api.cc
+++ b/chromium/extensions/browser/api/sockets_tcp_server/sockets_tcp_server_api.cc
@@ -123,7 +123,7 @@ void SocketsTcpServerUpdateFunction::Work() {
}
SocketsTcpServerSetPausedFunction::SocketsTcpServerSetPausedFunction()
- : socket_event_dispatcher_(NULL) {}
+ : socket_event_dispatcher_(nullptr) {}
SocketsTcpServerSetPausedFunction::~SocketsTcpServerSetPausedFunction() {}
@@ -138,7 +138,7 @@ bool SocketsTcpServerSetPausedFunction::Prepare() {
"If this assertion is failing during a test, then it is likely that "
"TestExtensionSystem is failing to provide an instance of "
"TCPServerSocketEventDispatcher.";
- return socket_event_dispatcher_ != NULL;
+ return !!socket_event_dispatcher_;
}
void SocketsTcpServerSetPausedFunction::Work() {
@@ -160,7 +160,7 @@ void SocketsTcpServerSetPausedFunction::Work() {
}
SocketsTcpServerListenFunction::SocketsTcpServerListenFunction()
- : socket_event_dispatcher_(NULL) {}
+ : socket_event_dispatcher_(nullptr) {}
SocketsTcpServerListenFunction::~SocketsTcpServerListenFunction() {}
@@ -175,7 +175,7 @@ bool SocketsTcpServerListenFunction::Prepare() {
"If this assertion is failing during a test, then it is likely that "
"TestExtensionSystem is failing to provide an instance of "
"TCPServerSocketEventDispatcher.";
- return socket_event_dispatcher_ != NULL;
+ return !!socket_event_dispatcher_;
}
void SocketsTcpServerListenFunction::AsyncWorkStart() {
@@ -297,7 +297,7 @@ bool SocketsTcpServerGetSocketsFunction::Prepare() { return true; }
void SocketsTcpServerGetSocketsFunction::Work() {
std::vector<sockets_tcp_server::SocketInfo> socket_infos;
std::unordered_set<int>* resource_ids = GetSocketIds();
- if (resource_ids != NULL) {
+ if (resource_ids) {
for (int socket_id : *resource_ids) {
ResumableTCPServerSocket* socket = GetTcpSocket(socket_id);
if (socket) {
diff --git a/chromium/extensions/browser/api/sockets_tcp_server/tcp_server_socket_event_dispatcher.cc b/chromium/extensions/browser/api/sockets_tcp_server/tcp_server_socket_event_dispatcher.cc
index 14d16fd8f87..587a0d12a33 100644
--- a/chromium/extensions/browser/api/sockets_tcp_server/tcp_server_socket_event_dispatcher.cc
+++ b/chromium/extensions/browser/api/sockets_tcp_server/tcp_server_socket_event_dispatcher.cc
@@ -185,8 +185,8 @@ void TCPServerSocketEventDispatcher::PostEvent(const AcceptParams& params,
std::unique_ptr<Event> event) {
DCHECK_CURRENTLY_ON(params.thread_id);
- base::PostTask(FROM_HERE, {BrowserThread::UI},
- base::BindOnce(&DispatchEvent, params.browser_context_id,
+ content::GetUIThreadTaskRunner({})->PostTask(
+ FROM_HERE, base::BindOnce(&DispatchEvent, params.browser_context_id,
params.extension_id, std::move(event)));
}
diff --git a/chromium/extensions/browser/api/sockets_udp/sockets_udp_api.cc b/chromium/extensions/browser/api/sockets_udp/sockets_udp_api.cc
index 2c17cbe5308..2c7ca4a6503 100644
--- a/chromium/extensions/browser/api/sockets_udp/sockets_udp_api.cc
+++ b/chromium/extensions/browser/api/sockets_udp/sockets_udp_api.cc
@@ -142,7 +142,7 @@ void SocketsUdpUpdateFunction::Work() {
}
SocketsUdpSetPausedFunction::SocketsUdpSetPausedFunction()
- : socket_event_dispatcher_(NULL) {}
+ : socket_event_dispatcher_(nullptr) {}
SocketsUdpSetPausedFunction::~SocketsUdpSetPausedFunction() {}
@@ -156,7 +156,7 @@ bool SocketsUdpSetPausedFunction::Prepare() {
"If this assertion is failing during a test, then it is likely that "
"TestExtensionSystem is failing to provide an instance of "
"UDPSocketEventDispatcher.";
- return socket_event_dispatcher_ != NULL;
+ return !!socket_event_dispatcher_;
}
void SocketsUdpSetPausedFunction::Work() {
@@ -178,7 +178,7 @@ void SocketsUdpSetPausedFunction::Work() {
}
SocketsUdpBindFunction::SocketsUdpBindFunction()
- : socket_event_dispatcher_(NULL) {}
+ : socket_event_dispatcher_(nullptr) {}
SocketsUdpBindFunction::~SocketsUdpBindFunction() {}
@@ -192,7 +192,7 @@ bool SocketsUdpBindFunction::Prepare() {
"If this assertion is failing during a test, then it is likely that "
"TestExtensionSystem is failing to provide an instance of "
"UDPSocketEventDispatcher.";
- return socket_event_dispatcher_ != NULL;
+ return !!socket_event_dispatcher_;
}
void SocketsUdpBindFunction::AsyncWorkStart() {
@@ -363,7 +363,7 @@ bool SocketsUdpGetSocketsFunction::Prepare() { return true; }
void SocketsUdpGetSocketsFunction::Work() {
std::vector<sockets_udp::SocketInfo> socket_infos;
std::unordered_set<int>* resource_ids = GetSocketIds();
- if (resource_ids != NULL) {
+ if (resource_ids) {
for (int socket_id : *resource_ids) {
ResumableUDPSocket* socket = GetUdpSocket(socket_id);
if (socket) {
diff --git a/chromium/extensions/browser/api/sockets_udp/udp_socket_event_dispatcher.cc b/chromium/extensions/browser/api/sockets_udp/udp_socket_event_dispatcher.cc
index 14774d2cf85..a1fd9f34e15 100644
--- a/chromium/extensions/browser/api/sockets_udp/udp_socket_event_dispatcher.cc
+++ b/chromium/extensions/browser/api/sockets_udp/udp_socket_event_dispatcher.cc
@@ -171,8 +171,8 @@ void UDPSocketEventDispatcher::PostEvent(const ReceiveParams& params,
std::unique_ptr<Event> event) {
DCHECK_CURRENTLY_ON(params.thread_id);
- base::PostTask(FROM_HERE, {BrowserThread::UI},
- base::BindOnce(&DispatchEvent, params.browser_context_id,
+ content::GetUIThreadTaskRunner({})->PostTask(
+ FROM_HERE, base::BindOnce(&DispatchEvent, params.browser_context_id,
params.extension_id, std::move(event)));
}
diff --git a/chromium/extensions/browser/api/storage/settings_storage_quota_enforcer.cc b/chromium/extensions/browser/api/storage/settings_storage_quota_enforcer.cc
index 87c6bc64dea..6523da98fac 100644
--- a/chromium/extensions/browser/api/storage/settings_storage_quota_enforcer.cc
+++ b/chromium/extensions/browser/api/storage/settings_storage_quota_enforcer.cc
@@ -8,6 +8,7 @@
#include "base/bind.h"
#include "base/json/json_writer.h"
+#include "base/logging.h"
#include "base/stl_util.h"
#include "base/strings/stringprintf.h"
#include "extensions/common/extension_api.h"
diff --git a/chromium/extensions/browser/api/storage/storage_api.cc b/chromium/extensions/browser/api/storage/storage_api.cc
index 04768c98a98..9a3b94d6cf8 100644
--- a/chromium/extensions/browser/api/storage/storage_api.cc
+++ b/chromium/extensions/browser/api/storage/storage_api.cc
@@ -12,7 +12,6 @@
#include "base/bind.h"
#include "base/strings/stringprintf.h"
-#include "base/task/post_task.h"
#include "base/values.h"
#include "content/public/browser/browser_task_traits.h"
#include "content/public/browser/browser_thread.h"
@@ -22,8 +21,6 @@
namespace extensions {
-using content::BrowserThread;
-
// SettingsFunction
SettingsFunction::SettingsFunction()
@@ -77,8 +74,8 @@ ExtensionFunction::ResponseAction SettingsFunction::Run() {
void SettingsFunction::AsyncRunWithStorage(ValueStore* storage) {
ResponseValue response = RunWithStorage(storage);
- base::PostTask(
- FROM_HERE, {BrowserThread::UI},
+ content::GetUIThreadTaskRunner({})->PostTask(
+ FROM_HERE,
base::BindOnce(&SettingsFunction::Respond, this, std::move(response)));
}
diff --git a/chromium/extensions/browser/api/system_storage/system_storage_eject_apitest.cc b/chromium/extensions/browser/api/system_storage/system_storage_eject_apitest.cc
index 5fb71798efc..d87a81a33b1 100644
--- a/chromium/extensions/browser/api/system_storage/system_storage_eject_apitest.cc
+++ b/chromium/extensions/browser/api/system_storage/system_storage_eject_apitest.cc
@@ -34,7 +34,7 @@ using storage_monitor::TestStorageMonitor;
class SystemStorageEjectApiTest : public extensions::ShellApiTest {
public:
- SystemStorageEjectApiTest() : monitor_(NULL) {}
+ SystemStorageEjectApiTest() : monitor_(nullptr) {}
~SystemStorageEjectApiTest() override {}
protected:
diff --git a/chromium/extensions/browser/api/test/test_api.cc b/chromium/extensions/browser/api/test/test_api.cc
index 01e9d167057..8458efa2f41 100644
--- a/chromium/extensions/browser/api/test/test_api.cc
+++ b/chromium/extensions/browser/api/test/test_api.cc
@@ -129,7 +129,7 @@ void TestGetConfigFunction::set_test_config_state(
}
TestGetConfigFunction::TestConfigState::TestConfigState()
- : config_state_(NULL) {}
+ : config_state_(nullptr) {}
// static
TestGetConfigFunction::TestConfigState*
diff --git a/chromium/extensions/browser/api/vpn_provider/vpn_service.cc b/chromium/extensions/browser/api/vpn_provider/vpn_service.cc
index 16c453e67fa..ee4624091d8 100644
--- a/chromium/extensions/browser/api/vpn_provider/vpn_service.cc
+++ b/chromium/extensions/browser/api/vpn_provider/vpn_service.cc
@@ -545,7 +545,7 @@ void VpnService::OnExtensionUnloaded(
base::DoNothing(), base::BindOnce(DoNothingFailureCallback));
}
if (reason == extensions::UnloadedExtensionReason::DISABLE ||
- reason == extensions::UnloadedExtensionReason::BLACKLIST) {
+ reason == extensions::UnloadedExtensionReason::BLOCKLIST) {
DestroyConfigurationsForExtension(extension);
}
}
diff --git a/chromium/extensions/browser/api/web_request/BUILD.gn b/chromium/extensions/browser/api/web_request/BUILD.gn
index 117c87d9f72..ac64cd54722 100644
--- a/chromium/extensions/browser/api/web_request/BUILD.gn
+++ b/chromium/extensions/browser/api/web_request/BUILD.gn
@@ -43,6 +43,7 @@ source_set("web_request") {
]
deps = [
+ "//components/ukm/content",
"//components/web_cache/browser",
"//content/public/browser",
"//content/public/common",
diff --git a/chromium/extensions/browser/api/web_request/web_request_api.cc b/chromium/extensions/browser/api/web_request/web_request_api.cc
index 50db1d2502b..7c5498c16b1 100644
--- a/chromium/extensions/browser/api/web_request/web_request_api.cc
+++ b/chromium/extensions/browser/api/web_request/web_request_api.cc
@@ -26,6 +26,7 @@
#include "base/task/post_task.h"
#include "base/time/time.h"
#include "base/values.h"
+#include "components/ukm/content/source_url_recorder.h"
#include "content/public/browser/browser_context.h"
#include "content/public/browser/browser_task_traits.h"
#include "content/public/browser/browser_thread.h"
@@ -689,11 +690,11 @@ bool WebRequestAPI::MaybeProxyURLLoaderFactory(
mojo::PendingRemote<network::mojom::TrustedURLLoaderHeaderClient>*
header_client) {
DCHECK_CURRENTLY_ON(BrowserThread::UI);
+ auto* web_contents = content::WebContents::FromRenderFrameHost(frame);
if (!MayHaveProxies()) {
bool skip_proxy = true;
// There are a few internal WebUIs that use WebView tag that are whitelisted
// for webRequest.
- auto* web_contents = content::WebContents::FromRenderFrameHost(frame);
if (web_contents && WebViewGuest::IsGuest(web_contents)) {
auto* guest_web_contents =
WebViewGuest::GetTopLevelWebContents(web_contents);
@@ -742,12 +743,15 @@ bool WebRequestAPI::MaybeProxyURLLoaderFactory(
(browser_context->IsOffTheRecord() &&
ExtensionsBrowserClient::Get()->GetOriginalContext(browser_context) ==
browser_context_));
+ const ukm::SourceId ukm_source_id =
+ web_contents ? ukm::GetSourceIdForWebContentsDocument(web_contents)
+ : ukm::kInvalidSourceId;
WebRequestProxyingURLLoaderFactory::StartProxying(
browser_context, is_navigation ? -1 : render_process_id,
&request_id_generator_, std::move(navigation_ui_data),
std::move(navigation_id), std::move(proxied_receiver),
std::move(target_factory_remote), std::move(header_client_receiver),
- proxies_.get(), type);
+ proxies_.get(), type, ukm_source_id);
return true;
}
@@ -893,10 +897,9 @@ struct ExtensionWebRequestEventRouter::BlockedRequest {
// for OnBeforeSendHeaders.
net::HttpRequestHeaders* request_headers = nullptr;
- // The response headers that were received from the server and subsequently
- // filtered by the Declarative Net Request API. Only valid for
+ // The response headers that were received from the server. Only valid for
// OnHeadersReceived.
- scoped_refptr<const net::HttpResponseHeaders> filtered_response_headers;
+ scoped_refptr<const net::HttpResponseHeaders> original_response_headers;
// Location where to override response headers. Only valid for
// OnHeadersReceived.
@@ -1104,8 +1107,14 @@ int ExtensionWebRequestEventRouter::OnBeforeRequest(
*new_url = action.redirect_url.value();
return net::OK;
case DNRRequestAction::Type::MODIFY_HEADERS:
- // TODO(crbug.com/947591): Evaluate modify headers DNR actions.
- NOTREACHED();
+ // Unlike other actions, allow web request extensions to intercept the
+ // request here. The headers will be modified during subsequent request
+ // stages.
+ DCHECK(std::all_of(request->dnr_actions->begin(),
+ request->dnr_actions->end(), [](const auto& action) {
+ return action.type ==
+ DNRRequestAction::Type::MODIFY_HEADERS;
+ }));
break;
}
}
@@ -1136,15 +1145,20 @@ int ExtensionWebRequestEventRouter::OnBeforeSendHeaders(
if (ShouldHideEvent(browser_context, *request))
return net::OK;
- // TODO(crbug.com/947591): Handle request header modification by the
- // Declarative Net Request API.
-
bool initialize_blocked_requests = false;
initialize_blocked_requests |=
ProcessDeclarativeRules(browser_context, keys::kOnBeforeSendHeadersEvent,
request, ON_BEFORE_SEND_HEADERS, nullptr);
+ DCHECK(request->dnr_actions);
+ initialize_blocked_requests |= std::any_of(
+ request->dnr_actions->begin(), request->dnr_actions->end(),
+ [](const DNRRequestAction& action) {
+ return action.type == DNRRequestAction::Type::MODIFY_HEADERS &&
+ !action.request_headers_to_modify.empty();
+ });
+
int extra_info_spec = 0;
RawListeners listeners =
GetMatchingListeners(browser_context, keys::kOnBeforeSendHeadersEvent,
@@ -1217,16 +1231,19 @@ int ExtensionWebRequestEventRouter::OnHeadersReceived(
if (ShouldHideEvent(browser_context, *request))
return net::OK;
- // TODO(crbug.com/947591): Handle header modification by the Declarative Net
- // Request API.
- scoped_refptr<const net::HttpResponseHeaders> filtered_response_headers =
- original_response_headers;
-
bool initialize_blocked_requests = false;
+ DCHECK(request->dnr_actions);
+ initialize_blocked_requests |= std::any_of(
+ request->dnr_actions->begin(), request->dnr_actions->end(),
+ [](const DNRRequestAction& action) {
+ return action.type == DNRRequestAction::Type::MODIFY_HEADERS &&
+ !action.response_headers_to_modify.empty();
+ });
+
initialize_blocked_requests |= ProcessDeclarativeRules(
browser_context, keys::kOnHeadersReceivedEvent, request,
- ON_HEADERS_RECEIVED, filtered_response_headers.get());
+ ON_HEADERS_RECEIVED, original_response_headers);
int extra_info_spec = 0;
RawListeners listeners =
@@ -1237,8 +1254,7 @@ int ExtensionWebRequestEventRouter::OnHeadersReceived(
!GetAndSetSignaled(request->id, kOnHeadersReceived)) {
std::unique_ptr<WebRequestEventDetails> event_details(
CreateEventDetails(*request, extra_info_spec));
- event_details->SetResponseHeaders(*request,
- filtered_response_headers.get());
+ event_details->SetResponseHeaders(*request, original_response_headers);
initialize_blocked_requests |= DispatchEvent(
browser_context, request, listeners, std::move(event_details));
@@ -1258,7 +1274,7 @@ int ExtensionWebRequestEventRouter::OnHeadersReceived(
blocked_request.request = request;
blocked_request.callback = std::move(callback);
blocked_request.override_response_headers = override_response_headers;
- blocked_request.filtered_response_headers = filtered_response_headers;
+ blocked_request.original_response_headers = original_response_headers;
blocked_request.new_url = preserve_fragment_on_redirect_url;
if (blocked_request.num_handlers_blocking == 0) {
@@ -2014,7 +2030,7 @@ helpers::EventResponseDelta CalculateDelta(
}
case ExtensionWebRequestEventRouter::kOnHeadersReceived: {
const net::HttpResponseHeaders* old_headers =
- blocked_request->filtered_response_headers.get();
+ blocked_request->original_response_headers.get();
helpers::ResponseHeaders* new_headers =
response->response_headers.get();
return helpers::CalculateOnHeadersReceivedDelta(
@@ -2229,6 +2245,7 @@ int ExtensionWebRequestEventRouter::ExecuteDeltas(
helpers::MergeCancelOfResponses(blocked_request.response_deltas, &canceled);
extension_web_request_api_helpers::IgnoredActions ignored_actions;
+ std::vector<const DNRRequestAction*> matched_dnr_actions;
if (blocked_request.event == kOnBeforeRequest) {
CHECK(!blocked_request.callback.is_null());
helpers::MergeOnBeforeRequestResponses(
@@ -2240,15 +2257,14 @@ int ExtensionWebRequestEventRouter::ExecuteDeltas(
*request, blocked_request.response_deltas,
blocked_request.request_headers, &ignored_actions,
&request_headers_removed, &request_headers_set,
- &request_headers_modified);
-
+ &request_headers_modified, &matched_dnr_actions);
} else if (blocked_request.event == kOnHeadersReceived) {
CHECK(!blocked_request.callback.is_null());
helpers::MergeOnHeadersReceivedResponses(
*request, blocked_request.response_deltas,
- blocked_request.filtered_response_headers.get(),
+ blocked_request.original_response_headers.get(),
blocked_request.override_response_headers, blocked_request.new_url,
- &ignored_actions, &response_headers_modified);
+ &ignored_actions, &response_headers_modified, &matched_dnr_actions);
} else if (blocked_request.event == kOnAuthRequired) {
CHECK(blocked_request.callback.is_null());
CHECK(!blocked_request.auth_callback.is_null());
@@ -2266,6 +2282,9 @@ int ExtensionWebRequestEventRouter::ExecuteDeltas(
std::move(ignored_actions));
}
+ for (const DNRRequestAction* action : matched_dnr_actions)
+ OnDNRActionMatched(browser_context, *request, *action);
+
const bool redirected =
blocked_request.new_url && !blocked_request.new_url->is_empty();
@@ -2330,7 +2349,7 @@ bool ExtensionWebRequestEventRouter::ProcessDeclarativeRules(
const std::string& event_name,
const WebRequestInfo* request,
RequestStage request_stage,
- const net::HttpResponseHeaders* filtered_response_headers) {
+ const net::HttpResponseHeaders* original_response_headers) {
int rules_registry_id = request->is_web_view
? request->web_view_rules_registry_id
: RulesRegistryService::kDefaultRulesRegistryID;
@@ -2384,7 +2403,7 @@ bool ExtensionWebRequestEventRouter::ProcessDeclarativeRules(
blocked_request.request = request;
blocked_request.is_incognito |= IsIncognitoBrowserContext(browser_context);
blocked_request.blocking_time = base::Time::Now();
- blocked_request.filtered_response_headers = filtered_response_headers;
+ blocked_request.original_response_headers = original_response_headers;
return true;
}
@@ -2393,7 +2412,7 @@ bool ExtensionWebRequestEventRouter::ProcessDeclarativeRules(
WebRequestRulesRegistry* rules_registry = it.first;
helpers::EventResponseDeltas result = rules_registry->CreateDeltas(
PermissionHelper::Get(browser_context),
- WebRequestData(request, request_stage, filtered_response_headers),
+ WebRequestData(request, request_stage, original_response_headers),
it.second);
if (!result.empty()) {
@@ -2422,7 +2441,7 @@ void ExtensionWebRequestEventRouter::OnRulesRegistryReady(
BlockedRequest& blocked_request = it->second;
ProcessDeclarativeRules(browser_context, event_name, blocked_request.request,
request_stage,
- blocked_request.filtered_response_headers.get());
+ blocked_request.original_response_headers.get());
DecrementBlockCount(browser_context, std::string(), event_name, request_id,
nullptr, 0 /* extra_info_spec */);
}
diff --git a/chromium/extensions/browser/api/web_request/web_request_api_helpers.cc b/chromium/extensions/browser/api/web_request/web_request_api_helpers.cc
index 2e5874d5ac8..58012fe6fe5 100644
--- a/chromium/extensions/browser/api/web_request/web_request_api_helpers.cc
+++ b/chromium/extensions/browser/api/web_request/web_request_api_helpers.cc
@@ -23,7 +23,6 @@
#include "base/strings/string_number_conversions.h"
#include "base/strings/string_util.h"
#include "base/strings/stringprintf.h"
-#include "base/task/post_task.h"
#include "base/time/time.h"
#include "base/values.h"
#include "components/web_cache/browser/web_cache_manager.h"
@@ -31,6 +30,7 @@
#include "content/public/browser/browser_task_traits.h"
#include "content/public/browser/browser_thread.h"
#include "content/public/browser/render_process_host.h"
+#include "extensions/browser/api/declarative_net_request/request_action.h"
#include "extensions/browser/api/extensions_api_client.h"
#include "extensions/browser/api/web_request/web_request_api_constants.h"
#include "extensions/browser/api/web_request/web_request_info.h"
@@ -38,6 +38,7 @@
#include "extensions/browser/extension_system.h"
#include "extensions/browser/extensions_browser_client.h"
#include "extensions/browser/runtime_data.h"
+#include "extensions/common/api/declarative_net_request.h"
#include "extensions/common/extension_messages.h"
#include "net/cookies/cookie_util.h"
#include "net/cookies/parsed_cookie.h"
@@ -56,11 +57,13 @@ using net::cookie_util::ParsedRequestCookies;
namespace keys = extension_web_request_api_constants;
namespace web_request = extensions::api::web_request;
+using DNRRequestAction = extensions::declarative_net_request::RequestAction;
namespace extension_web_request_api_helpers {
namespace {
+namespace dnr_api = extensions::api::declarative_net_request;
using ParsedResponseCookies = std::vector<std::unique_ptr<net::ParsedCookie>>;
void ClearCacheOnNavigationOnUI() {
@@ -329,20 +332,178 @@ static_assert(static_cast<size_t>(ResponseHeaderType::kMaxValue) - 1 ==
static_assert(ValidateHeaderEntries(kResponseHeaderEntries),
"Invalid response header entries");
-bool HasMatchingRemovedDNRRequestHeader(
- const extensions::WebRequestInfo& request,
- const std::string& header) {
- // TODO(crbug.com/947591): Reimplement this method with
- // |action.request_headers_to_modify|.
- return false;
+// Represents an action to be taken on a given header.
+struct DNRHeaderAction {
+ DNRHeaderAction(const DNRRequestAction::HeaderInfo* header_info,
+ const extensions::ExtensionId* extension_id)
+ : header_info(header_info), extension_id(extension_id) {}
+
+ // Returns whether for the same header, the operation specified by
+ // |next_action| conflicts with the operation specified by this action.
+ bool ConflictsWithSubsequentAction(const DNRHeaderAction& next_action) const {
+ DCHECK_EQ(header_info->header, next_action.header_info->header);
+
+ switch (header_info->operation) {
+ case dnr_api::HEADER_OPERATION_APPEND:
+ return next_action.header_info->operation !=
+ dnr_api::HEADER_OPERATION_APPEND;
+ case dnr_api::HEADER_OPERATION_SET:
+ return *extension_id != *next_action.extension_id ||
+ next_action.header_info->operation !=
+ dnr_api::HEADER_OPERATION_APPEND;
+ case dnr_api::HEADER_OPERATION_REMOVE:
+ return true;
+ case dnr_api::HEADER_OPERATION_NONE:
+ NOTREACHED();
+ return true;
+ }
+ }
+
+ // Non-owning pointers to HeaderInfo and ExtensionId.
+ const DNRRequestAction::HeaderInfo* header_info;
+ const extensions::ExtensionId* extension_id;
+};
+
+// Helper to modify request headers from
+// |request_action.request_headers_to_modify|. Returns whether or not request
+// headers were actually modified and modifies |removed_headers|, |set_headers|
+// and |header_actions|. |header_actions| maps a header name to the operation
+// to be performed on the header.
+bool ModifyRequestHeadersForAction(
+ net::HttpRequestHeaders* headers,
+ const DNRRequestAction& request_action,
+ std::set<std::string>* removed_headers,
+ std::set<std::string>* set_headers,
+ std::map<base::StringPiece, DNRHeaderAction>* header_actions) {
+ bool request_headers_modified = false;
+ for (const DNRRequestAction::HeaderInfo& header_info :
+ request_action.request_headers_to_modify) {
+ bool header_modified = false;
+ const std::string& header = header_info.header;
+
+ DNRHeaderAction header_action(&header_info, &request_action.extension_id);
+ auto iter = header_actions->find(header);
+ if (iter != header_actions->end() &&
+ iter->second.ConflictsWithSubsequentAction(header_action)) {
+ continue;
+ }
+ header_actions->emplace(header, header_action);
+
+ // TODO(crbug.com/1088103): Record request headers modified by the
+ // Declarative Net Request API.
+ switch (header_info.operation) {
+ case extensions::api::declarative_net_request::HEADER_OPERATION_SET:
+ headers->SetHeader(header, *header_info.value);
+ header_modified = true;
+ set_headers->insert(header);
+ break;
+ case extensions::api::declarative_net_request::HEADER_OPERATION_REMOVE: {
+ while (headers->HasHeader(header)) {
+ header_modified = true;
+ headers->RemoveHeader(header);
+ }
+
+ if (header_modified)
+ removed_headers->insert(header);
+ break;
+ }
+ case extensions::api::declarative_net_request::HEADER_OPERATION_APPEND:
+ case extensions::api::declarative_net_request::HEADER_OPERATION_NONE:
+ NOTREACHED();
+ }
+
+ request_headers_modified |= header_modified;
+ }
+
+ return request_headers_modified;
}
-bool HasMatchingRemovedDNRResponseHeader(
- const extensions::WebRequestInfo& request,
- const std::string& header) {
- // TODO(crbug.com/947591): Reimplement this method with
- // |action.response_headers_to_modify|.
- return false;
+// Helper to modify response headers from |request_action|. Returns whether or
+// not response headers were actually modified and modifies |header_actions|.
+// |header_actions| maps a header name to a list of operations to be performed
+// on the header.
+bool ModifyResponseHeadersForAction(
+ const net::HttpResponseHeaders* original_response_headers,
+ scoped_refptr<net::HttpResponseHeaders>* override_response_headers,
+ const DNRRequestAction& request_action,
+ std::map<base::StringPiece, std::vector<DNRHeaderAction>>* header_actions) {
+ bool response_headers_modified = false;
+
+ // Check for |header| in |override_response_headers| if headers have been
+ // modified, otherwise, check in |original_response_headers|.
+ auto has_header = [&original_response_headers,
+ &override_response_headers](std::string header) {
+ return override_response_headers->get()
+ ? override_response_headers->get()->HasHeader(header)
+ : original_response_headers->HasHeader(header);
+ };
+
+ // Create a copy of |original_response_headers| iff we really want to modify
+ // the response headers.
+ auto create_override_headers_if_needed =
+ [&original_response_headers](
+ scoped_refptr<net::HttpResponseHeaders>* override_response_headers) {
+ if (override_response_headers->get() == nullptr) {
+ *override_response_headers =
+ base::MakeRefCounted<net::HttpResponseHeaders>(
+ original_response_headers->raw_headers());
+ }
+ };
+
+ for (const DNRRequestAction::HeaderInfo& header_info :
+ request_action.response_headers_to_modify) {
+ bool header_modified = false;
+ const std::string& header = header_info.header;
+
+ DNRHeaderAction header_action(&header_info, &request_action.extension_id);
+ auto iter = header_actions->find(header);
+
+ // Checking the first DNRHeaderAction should suffice for determining if a
+ // conflict exists, since the contents of |header_actions| for a given
+ // header will always be one of:
+ // [remove]
+ // [append+] one or more appends
+ // [set, append*] set, any number of appends from the same extension
+ if (iter != header_actions->end() &&
+ (*header_actions)[header][0].ConflictsWithSubsequentAction(
+ header_action)) {
+ continue;
+ }
+ (*header_actions)[header].push_back(header_action);
+
+ // TODO(crbug.com/1088103): Record response headers modified by the
+ // Declarative Net Request API.
+ switch (header_info.operation) {
+ case extensions::api::declarative_net_request::HEADER_OPERATION_REMOVE: {
+ if (has_header(header)) {
+ header_modified = true;
+ create_override_headers_if_needed(override_response_headers);
+ override_response_headers->get()->RemoveHeader(header);
+ }
+
+ break;
+ }
+ case extensions::api::declarative_net_request::HEADER_OPERATION_APPEND: {
+ header_modified = true;
+ create_override_headers_if_needed(override_response_headers);
+ override_response_headers->get()->AddHeader(header, *header_info.value);
+ break;
+ }
+ case extensions::api::declarative_net_request::HEADER_OPERATION_SET: {
+ header_modified = true;
+ create_override_headers_if_needed(override_response_headers);
+ override_response_headers->get()->RemoveHeader(header);
+ override_response_headers->get()->AddHeader(header, *header_info.value);
+ break;
+ }
+ case extensions::api::declarative_net_request::HEADER_OPERATION_NONE:
+ NOTREACHED();
+ }
+
+ response_headers_modified |= header_modified;
+ }
+
+ return response_headers_modified;
}
} // namespace
@@ -920,16 +1081,36 @@ void MergeOnBeforeSendHeadersResponses(
IgnoredActions* ignored_actions,
std::set<std::string>* removed_headers,
std::set<std::string>* set_headers,
- bool* request_headers_modified) {
+ bool* request_headers_modified,
+ std::vector<const DNRRequestAction*>* matched_dnr_actions) {
DCHECK(request_headers_modified);
DCHECK(removed_headers->empty());
DCHECK(set_headers->empty());
+ DCHECK(request.dnr_actions);
+ DCHECK(matched_dnr_actions);
*request_headers_modified = false;
- // Exhaustive subsets of |set_headers|. Split into a set for added headers and
- // a set for overridden headers.
- std::set<std::string> overridden_headers;
- std::set<std::string> added_headers;
+ std::map<base::StringPiece, DNRHeaderAction> dnr_header_actions;
+ for (const auto& action : *request.dnr_actions) {
+ bool headers_modified_for_action =
+ ModifyRequestHeadersForAction(request_headers, action, removed_headers,
+ set_headers, &dnr_header_actions);
+
+ *request_headers_modified |= headers_modified_for_action;
+ if (headers_modified_for_action)
+ matched_dnr_actions->push_back(&action);
+ }
+
+ // A strict subset of |removed_headers| consisting of headers removed by the
+ // web request API. Used for metrics.
+ // TODO(crbug.com/1098945): Use base::StringPiece to avoid copying header
+ // names.
+ std::set<std::string> web_request_removed_headers;
+
+ // Subsets of |set_headers| consisting of headers modified by the web request
+ // API. Split into a set for added headers and a set for overridden headers.
+ std::set<std::string> web_request_overridden_headers;
+ std::set<std::string> web_request_added_headers;
// We assume here that the deltas are sorted in decreasing extension
// precedence (i.e. decreasing extension installation time).
@@ -951,16 +1132,20 @@ void MergeOnBeforeSendHeadersResponses(
const std::string key = base::ToLowerASCII(modification.name());
const std::string& value = modification.value();
- // We must not modify anything that has been deleted before.
- if (base::Contains(*removed_headers, key)) {
+ // We must not modify anything that was specified to be removed by the
+ // Declarative Net Request API. Note that the actual header
+ // modifications made by Declarative Net Request should be represented
+ // in |removed_headers| and |set_headers|.
+ auto iter = dnr_header_actions.find(key);
+ if (iter != dnr_header_actions.end() &&
+ iter->second.header_info->operation ==
+ dnr_api::HEADER_OPERATION_REMOVE) {
extension_conflicts = true;
break;
}
- // Prevent extensions from adding any header removed by the Declarative
- // Net Request API.
- DCHECK(request.dnr_actions);
- if (HasMatchingRemovedDNRRequestHeader(request, key)) {
+ // We must not modify anything that has been deleted before.
+ if (base::Contains(*removed_headers, key)) {
extension_conflicts = true;
break;
}
@@ -998,11 +1183,11 @@ void MergeOnBeforeSendHeadersResponses(
while (modification.GetNext()) {
std::string key = base::ToLowerASCII(modification.name());
if (!request_headers->HasHeader(key)) {
- added_headers.insert(key);
- } else if (!base::Contains(added_headers, key)) {
+ web_request_added_headers.insert(key);
+ } else if (!base::Contains(web_request_added_headers, key)) {
// Note: |key| will only be present in |added_headers| if this is an
// identical edit.
- overridden_headers.insert(key);
+ web_request_overridden_headers.insert(key);
}
set_headers->insert(key);
@@ -1013,8 +1198,11 @@ void MergeOnBeforeSendHeadersResponses(
// Perform all deletions and record which keys were deleted.
{
for (const auto& header : delta.deleted_request_headers) {
+ std::string lowercase_header = base::ToLowerASCII(header);
+
request_headers->RemoveHeader(header);
- removed_headers->insert(base::ToLowerASCII(header));
+ removed_headers->insert(lowercase_header);
+ web_request_removed_headers.insert(lowercase_header);
}
}
*request_headers_modified = true;
@@ -1039,23 +1227,24 @@ void MergeOnBeforeSendHeadersResponses(
IsStringLowerCaseASCII));
DCHECK(std::all_of(set_headers->begin(), set_headers->end(),
IsStringLowerCaseASCII));
- DCHECK(std::all_of(overridden_headers.begin(), overridden_headers.end(),
- IsStringLowerCaseASCII));
- DCHECK(std::all_of(added_headers.begin(), added_headers.end(),
- IsStringLowerCaseASCII));
- DCHECK(*set_headers == base::STLSetUnion<std::set<std::string>>(
- added_headers, overridden_headers));
- DCHECK(base::STLSetIntersection<std::set<std::string>>(added_headers,
- overridden_headers)
+ DCHECK(base::STLIncludes(
+ *set_headers,
+ base::STLSetUnion<std::set<std::string>>(
+ web_request_added_headers, web_request_overridden_headers)));
+ DCHECK(base::STLSetIntersection<std::set<std::string>>(
+ web_request_added_headers, web_request_overridden_headers)
.empty());
DCHECK(base::STLSetIntersection<std::set<std::string>>(*removed_headers,
*set_headers)
.empty());
+ DCHECK(base::STLIncludes(*removed_headers, web_request_removed_headers));
// Record request header removals, additions and modifications.
- record_request_headers(*removed_headers, &RecordRequestHeaderRemoved);
- record_request_headers(added_headers, &RecordRequestHeaderAdded);
- record_request_headers(overridden_headers, &RecordRequestHeaderChanged);
+ record_request_headers(web_request_removed_headers,
+ &RecordRequestHeaderRemoved);
+ record_request_headers(web_request_added_headers, &RecordRequestHeaderAdded);
+ record_request_headers(web_request_overridden_headers,
+ &RecordRequestHeaderChanged);
// Currently, conflicts are ignored while merging cookies.
MergeCookiesInOnBeforeSendHeadersResponses(request.url, deltas,
@@ -1290,10 +1479,25 @@ void MergeOnHeadersReceivedResponses(
scoped_refptr<net::HttpResponseHeaders>* override_response_headers,
GURL* preserve_fragment_on_redirect_url,
IgnoredActions* ignored_actions,
- bool* response_headers_modified) {
+ bool* response_headers_modified,
+ std::vector<const DNRRequestAction*>* matched_dnr_actions) {
DCHECK(response_headers_modified);
*response_headers_modified = false;
+ DCHECK(request.dnr_actions);
+ DCHECK(matched_dnr_actions);
+
+ std::map<base::StringPiece, std::vector<DNRHeaderAction>> dnr_header_actions;
+ for (const auto& action : *request.dnr_actions) {
+ bool headers_modified_for_action = ModifyResponseHeadersForAction(
+ original_response_headers, override_response_headers, action,
+ &dnr_header_actions);
+
+ *response_headers_modified |= headers_modified_for_action;
+ if (headers_modified_for_action)
+ matched_dnr_actions->push_back(&action);
+ }
+
// Here we collect which headers we have removed or added so far due to
// extensions of higher precedence. Header keys are always stored as
// lower case.
@@ -1322,18 +1526,28 @@ void MergeOnHeadersReceivedResponses(
// this takes care of precedence.
bool extension_conflicts = false;
for (const ResponseHeader& header : delta.deleted_response_headers) {
- if (removed_headers.find(ToLowerCase(header)) != removed_headers.end()) {
+ ResponseHeader lowercase_header(ToLowerCase(header));
+ if (base::Contains(removed_headers, lowercase_header) ||
+ base::Contains(dnr_header_actions, lowercase_header.first)) {
extension_conflicts = true;
break;
}
}
- // Prevent extensions from adding any response header which was removed by
- // the Declarative Net Request API.
- DCHECK(request.dnr_actions);
+ // Prevent extensions from adding any response header which was specified to
+ // be removed or set by the Declarative Net Request API. However, multiple
+ // appends are allowed.
if (!extension_conflicts) {
for (const ResponseHeader& header : delta.added_response_headers) {
- if (HasMatchingRemovedDNRResponseHeader(request, header.first)) {
+ ResponseHeader lowercase_header(ToLowerCase(header));
+
+ auto it = dnr_header_actions.find(lowercase_header.first);
+ if (it == dnr_header_actions.end())
+ continue;
+
+ // Multiple appends are allowed.
+ if (it->second[0].header_info->operation !=
+ dnr_api::HEADER_OPERATION_APPEND) {
extension_conflicts = true;
break;
}
@@ -1406,6 +1620,7 @@ void MergeOnHeadersReceivedResponses(
std::set<base::StringPiece> modified_header_names;
std::set<base::StringPiece> added_header_names;
std::set<base::StringPiece> removed_header_names;
+
for (const ResponseHeader& header : added_headers) {
// Skip logging this header if this was subsequently removed by an
// extension.
@@ -1467,8 +1682,8 @@ void ClearCacheOnNavigation() {
if (content::BrowserThread::CurrentlyOn(content::BrowserThread::UI)) {
ClearCacheOnNavigationOnUI();
} else {
- base::PostTask(FROM_HERE, {content::BrowserThread::UI},
- base::BindOnce(&ClearCacheOnNavigationOnUI));
+ content::GetUIThreadTaskRunner({})->PostTask(
+ FROM_HERE, base::BindOnce(&ClearCacheOnNavigationOnUI));
}
}
diff --git a/chromium/extensions/browser/api/web_request/web_request_api_helpers.h b/chromium/extensions/browser/api/web_request/web_request_api_helpers.h
index a90a34b999b..cd7d01a62cc 100644
--- a/chromium/extensions/browser/api/web_request/web_request_api_helpers.h
+++ b/chromium/extensions/browser/api/web_request/web_request_api_helpers.h
@@ -38,6 +38,11 @@ class BrowserContext;
namespace extensions {
class Extension;
struct WebRequestInfo;
+
+namespace declarative_net_request {
+struct RequestAction;
+} // namespace declarative_net_request
+
} // namespace extensions
namespace extension_web_request_api_helpers {
@@ -435,6 +440,8 @@ void MergeCookiesInOnBeforeSendHeadersResponses(
// are tried to be resolved.
// Stores in |request_headers_modified| whether the request headers were
// modified.
+// Any actions within |request.dnr_actions| which result in headers being
+// modified are added to |matched_dnr_actions|.
void MergeOnBeforeSendHeadersResponses(
const extensions::WebRequestInfo& request,
const EventResponseDeltas& deltas,
@@ -442,7 +449,9 @@ void MergeOnBeforeSendHeadersResponses(
IgnoredActions* ignored_actions,
std::set<std::string>* removed_headers,
std::set<std::string>* set_headers,
- bool* request_headers_modified);
+ bool* request_headers_modified,
+ std::vector<const extensions::declarative_net_request::RequestAction*>*
+ matched_dnr_actions);
// Modifies the "Set-Cookie" headers in |override_response_headers| according to
// |deltas.response_cookie_modifications|. If |override_response_headers| is
// NULL, a copy of |original_response_headers| is created. Conflicts are
@@ -460,6 +469,8 @@ void MergeCookiesInOnHeadersReceivedResponses(
// sure that the URL provided by the extension isn't modified by having its
// fragment overwritten by that of the original URL). Stores in
// |response_headers_modified| whether the response headers were modified.
+// Any actions within |request.dnr_actions| which result in headers being
+// modified are added to |matched_dnr_actions|.
void MergeOnHeadersReceivedResponses(
const extensions::WebRequestInfo& request,
const EventResponseDeltas& deltas,
@@ -467,7 +478,9 @@ void MergeOnHeadersReceivedResponses(
scoped_refptr<net::HttpResponseHeaders>* override_response_headers,
GURL* preserve_fragment_on_redirect_url,
IgnoredActions* ignored_actions,
- bool* response_headers_modified);
+ bool* response_headers_modified,
+ std::vector<const extensions::declarative_net_request::RequestAction*>*
+ matched_dnr_actions);
// Merge the responses of blocked onAuthRequired handlers. The first
// registered listener that supplies authentication credentials in a response,
// if any, will have its authentication credentials used. |request| must be
diff --git a/chromium/extensions/browser/api/web_request/web_request_proxying_url_loader_factory.cc b/chromium/extensions/browser/api/web_request/web_request_proxying_url_loader_factory.cc
index dbb25b166a8..e26a21f26b6 100644
--- a/chromium/extensions/browser/api/web_request/web_request_proxying_url_loader_factory.cc
+++ b/chromium/extensions/browser/api/web_request/web_request_proxying_url_loader_factory.cc
@@ -10,6 +10,7 @@
#include "base/bind.h"
#include "base/callback_helpers.h"
#include "base/feature_list.h"
+#include "base/metrics/histogram_macros.h"
#include "base/strings/stringprintf.h"
#include "base/task/post_task.h"
#include "components/keyed_service/content/browser_context_keyed_service_shutdown_notifier_factory.h"
@@ -21,12 +22,18 @@
#include "extensions/browser/api/web_request/permission_helper.h"
#include "extensions/browser/extension_navigation_ui_data.h"
#include "extensions/browser/extension_registry.h"
+#include "extensions/common/extension_features.h"
#include "extensions/common/manifest_handlers/web_accessible_resources_info.h"
#include "net/base/completion_repeating_callback.h"
+#include "net/http/http_response_headers.h"
+#include "net/http/http_status_code.h"
#include "net/http/http_util.h"
#include "net/url_request/redirect_info.h"
#include "net/url_request/redirect_util.h"
#include "net/url_request/url_request.h"
+#include "services/metrics/public/cpp/ukm_builders.h"
+#include "services/metrics/public/cpp/ukm_recorder.h"
+#include "services/metrics/public/cpp/ukm_source_id.h"
#include "services/network/public/cpp/features.h"
#include "third_party/blink/public/common/loader/throttling_url_loader.h"
#include "third_party/blink/public/platform/resource_request_blocked_reason.h"
@@ -91,6 +98,7 @@ WebRequestProxyingURLLoaderFactory::InProgressRequest::InProgressRequest(
int32_t network_service_request_id,
int32_t routing_id,
uint32_t options,
+ ukm::SourceId ukm_source_id,
const network::ResourceRequest& request,
const net::MutableNetworkTrafficAnnotationTag& traffic_annotation,
mojo::PendingReceiver<network::mojom::URLLoader> loader_receiver,
@@ -102,6 +110,7 @@ WebRequestProxyingURLLoaderFactory::InProgressRequest::InProgressRequest(
network_service_request_id_(network_service_request_id),
routing_id_(routing_id),
options_(options),
+ ukm_source_id_(ukm_source_id),
traffic_annotation_(traffic_annotation),
proxied_loader_receiver_(this, std::move(loader_receiver)),
target_client_(std::move(client)),
@@ -111,10 +120,10 @@ WebRequestProxyingURLLoaderFactory::InProgressRequest::InProgressRequest(
ExtensionWebRequestEventRouter::GetInstance()
->HasAnyExtraHeadersListener(factory_->browser_context_)) {
// If there is a client error, clean up the request.
- target_client_.set_disconnect_handler(base::BindOnce(
- &WebRequestProxyingURLLoaderFactory::InProgressRequest::OnRequestError,
- weak_factory_.GetWeakPtr(),
- network::URLLoaderCompletionStatus(net::ERR_ABORTED)));
+ target_client_.set_disconnect_handler(
+ base::BindOnce(&WebRequestProxyingURLLoaderFactory::InProgressRequest::
+ OnClientDisconnected,
+ weak_factory_.GetWeakPtr()));
proxied_loader_receiver_.set_disconnect_with_reason_handler(
base::BindOnce(&WebRequestProxyingURLLoaderFactory::InProgressRequest::
OnLoaderDisconnected,
@@ -129,6 +138,7 @@ WebRequestProxyingURLLoaderFactory::InProgressRequest::InProgressRequest(
request_(request),
original_initiator_(request.request_initiator),
request_id_(request_id),
+ ukm_source_id_(ukm::kInvalidSourceId),
proxied_loader_receiver_(this),
for_cors_preflight_(true),
has_any_extra_headers_listeners_(
@@ -136,6 +146,18 @@ WebRequestProxyingURLLoaderFactory::InProgressRequest::InProgressRequest(
->HasAnyExtraHeadersListener(factory_->browser_context_)) {}
WebRequestProxyingURLLoaderFactory::InProgressRequest::~InProgressRequest() {
+ DCHECK_NE(state_, State::kInvalid);
+ if (request_.keepalive && !for_cors_preflight_) {
+ UMA_HISTOGRAM_ENUMERATION("Extensions.WebRequest.KeepaliveRequestState",
+ state_);
+ if (base::FeatureList::IsEnabled(
+ extensions_features::kReportKeepaliveUkm)) {
+ ukm::builders::Extensions_WebRequest_KeepaliveRequestFinished(
+ ukm_source_id_)
+ .SetState(state_)
+ .Record(ukm::UkmRecorder::Get());
+ }
+ }
// This is important to ensure that no outstanding blocking requests continue
// to reference state owned by this object.
if (info_) {
@@ -186,20 +208,23 @@ void WebRequestProxyingURLLoaderFactory::InProgressRequest::
void WebRequestProxyingURLLoaderFactory::InProgressRequest::RestartInternal() {
DCHECK_EQ(info_->url, request_.url)
<< "UpdateRequestInfo must have been called first";
+ is_header_client_receiver_paused_ = false;
// If the header client will be used, we start the request immediately, and
// OnBeforeSendHeaders and OnSendHeaders will be handled there. Otherwise,
// send these events before the request starts.
base::RepeatingCallback<void(int)> continuation;
+ const auto state_on_error = State::kRejectedByOnBeforeRequest;
if (current_request_uses_header_client_) {
- continuation = base::BindRepeating(
- &InProgressRequest::ContinueToStartRequest, weak_factory_.GetWeakPtr());
+ continuation =
+ base::BindRepeating(&InProgressRequest::ContinueToStartRequest,
+ weak_factory_.GetWeakPtr(), state_on_error);
} else if (for_cors_preflight_) {
// In this case we do nothing because extensions should see nothing.
return;
} else {
continuation =
base::BindRepeating(&InProgressRequest::ContinueToBeforeSendHeaders,
- weak_factory_.GetWeakPtr());
+ weak_factory_.GetWeakPtr(), state_on_error);
}
redirect_url_ = GURL();
bool should_collapse_initiator = false;
@@ -214,7 +239,7 @@ void WebRequestProxyingURLLoaderFactory::InProgressRequest::RestartInternal() {
status.extended_error_code = static_cast<int>(
blink::ResourceRequestBlockedReason::kCollapsedByClient);
}
- OnRequestError(status);
+ OnRequestError(status, state_on_error);
return;
}
@@ -229,8 +254,10 @@ void WebRequestProxyingURLLoaderFactory::InProgressRequest::RestartInternal() {
// Pause the header client, since we want to wait until OnBeforeRequest has
// finished before processing any future events.
- if (header_client_receiver_.is_bound())
+ if (header_client_receiver_.is_bound()) {
header_client_receiver_.Pause();
+ is_header_client_receiver_paused_ = true;
+ }
return;
}
DCHECK_EQ(net::OK, result);
@@ -318,7 +345,7 @@ void WebRequestProxyingURLLoaderFactory::InProgressRequest::OnReceiveRedirect(
if (redirect_url_ != redirect_info.new_url &&
!IsRedirectSafe(request_.url, redirect_info.new_url,
info_->is_navigation_request)) {
- OnRequestError(
+ OnNetworkError(
network::URLLoaderCompletionStatus(net::ERR_UNSAFE_REDIRECT));
return;
}
@@ -368,10 +395,11 @@ void WebRequestProxyingURLLoaderFactory::InProgressRequest::
void WebRequestProxyingURLLoaderFactory::InProgressRequest::OnComplete(
const network::URLLoaderCompletionStatus& status) {
if (status.error_code != net::OK) {
- OnRequestError(status);
+ OnNetworkError(status);
return;
}
+ state_ = kCompleted;
target_client_->OnComplete(status);
ExtensionWebRequestEventRouter::GetInstance()->OnCompleted(
factory_->browser_context_, &info_.value(), status.error_code);
@@ -422,12 +450,14 @@ void WebRequestProxyingURLLoaderFactory::InProgressRequest::OnLoaderCreated(
header_client_receiver_.reset();
header_client_receiver_.Bind(std::move(receiver));
+ if (is_header_client_receiver_paused_)
+ header_client_receiver_.Pause();
if (for_cors_preflight_) {
// In this case we don't have |target_loader_| and
// |proxied_client_receiver_|, and |receiver| is the only connection to the
// network service, so we observe mojo connection errors.
header_client_receiver_.set_disconnect_handler(base::BindOnce(
- &WebRequestProxyingURLLoaderFactory::InProgressRequest::OnRequestError,
+ &WebRequestProxyingURLLoaderFactory::InProgressRequest::OnNetworkError,
weak_factory_.GetWeakPtr(),
network::URLLoaderCompletionStatus(net::ERR_FAILED)));
}
@@ -443,7 +473,7 @@ void WebRequestProxyingURLLoaderFactory::InProgressRequest::OnBeforeSendHeaders(
request_.headers = headers;
on_before_send_headers_callback_ = std::move(callback);
- ContinueToBeforeSendHeaders(net::OK);
+ ContinueToBeforeSendHeadersWithOk();
}
void WebRequestProxyingURLLoaderFactory::InProgressRequest::OnHeadersReceived(
@@ -539,9 +569,10 @@ void WebRequestProxyingURLLoaderFactory::InProgressRequest::
}
void WebRequestProxyingURLLoaderFactory::InProgressRequest::
- ContinueToBeforeSendHeaders(int error_code) {
+ ContinueToBeforeSendHeaders(State state_on_error, int error_code) {
if (error_code != net::OK) {
- OnRequestError(network::URLLoaderCompletionStatus(error_code));
+ OnRequestError(network::URLLoaderCompletionStatus(error_code),
+ state_on_error);
return;
}
@@ -558,8 +589,10 @@ void WebRequestProxyingURLLoaderFactory::InProgressRequest::
// intuitive), |onBeforeSendHeaders| is only dispatched for HTTP and HTTPS
// requests.
- auto continuation = base::BindRepeating(
- &InProgressRequest::ContinueToSendHeaders, weak_factory_.GetWeakPtr());
+ const auto state_on_error = State::kRejectedByOnBeforeSendHeaders;
+ auto continuation =
+ base::BindRepeating(&InProgressRequest::ContinueToSendHeaders,
+ weak_factory_.GetWeakPtr(), state_on_error);
int result =
ExtensionWebRequestEventRouter::GetInstance()->OnBeforeSendHeaders(
factory_->browser_context_, &info_.value(), continuation,
@@ -568,7 +601,8 @@ void WebRequestProxyingURLLoaderFactory::InProgressRequest::
if (result == net::ERR_BLOCKED_BY_CLIENT) {
// The request was cancelled synchronously. Dispatch an error notification
// and terminate the request.
- OnRequestError(network::URLLoaderCompletionStatus(result));
+ OnRequestError(network::URLLoaderCompletionStatus(result),
+ state_on_error);
return;
}
@@ -585,21 +619,26 @@ void WebRequestProxyingURLLoaderFactory::InProgressRequest::
DCHECK_EQ(net::OK, result);
}
- ContinueToSendHeaders(std::set<std::string>(), std::set<std::string>(),
- net::OK);
+ ContinueToSendHeadersWithOk(std::set<std::string>(), std::set<std::string>());
}
void WebRequestProxyingURLLoaderFactory::InProgressRequest::
- ContinueToStartRequest(int error_code) {
+ ContinueToBeforeSendHeadersWithOk() {
+ ContinueToBeforeSendHeaders(State::kInvalid, net::OK);
+}
+void WebRequestProxyingURLLoaderFactory::InProgressRequest::
+ ContinueToStartRequest(State state_on_error, int error_code) {
if (error_code != net::OK) {
- OnRequestError(network::URLLoaderCompletionStatus(error_code));
+ OnRequestError(network::URLLoaderCompletionStatus(error_code),
+ state_on_error);
return;
}
if (current_request_uses_header_client_ && !redirect_url_.is_empty()) {
if (for_cors_preflight_) {
// CORS preflight doesn't support redirect.
- OnRequestError(network::URLLoaderCompletionStatus(net::ERR_FAILED));
+ OnRequestError(network::URLLoaderCompletionStatus(net::ERR_FAILED),
+ state_on_error);
return;
}
HandleBeforeRequestRedirect();
@@ -609,8 +648,10 @@ void WebRequestProxyingURLLoaderFactory::InProgressRequest::
if (proxied_client_receiver_.is_bound())
proxied_client_receiver_.Resume();
- if (header_client_receiver_.is_bound())
+ if (header_client_receiver_.is_bound()) {
header_client_receiver_.Resume();
+ is_header_client_receiver_paused_ = false;
+ }
if (for_cors_preflight_) {
// For CORS preflight requests, we have already started the request in
@@ -640,11 +681,18 @@ void WebRequestProxyingURLLoaderFactory::InProgressRequest::
}
void WebRequestProxyingURLLoaderFactory::InProgressRequest::
- ContinueToSendHeaders(const std::set<std::string>& removed_headers,
+ ContinueToStartRequestWithOk() {
+ ContinueToStartRequest(State::kInvalid, net::OK);
+}
+
+void WebRequestProxyingURLLoaderFactory::InProgressRequest::
+ ContinueToSendHeaders(State state_on_error,
+ const std::set<std::string>& removed_headers,
const std::set<std::string>& set_headers,
int error_code) {
if (error_code != net::OK) {
- OnRequestError(network::URLLoaderCompletionStatus(error_code));
+ OnRequestError(network::URLLoaderCompletionStatus(error_code),
+ state_on_error);
return;
}
@@ -690,7 +738,13 @@ void WebRequestProxyingURLLoaderFactory::InProgressRequest::
}
if (!current_request_uses_header_client_)
- ContinueToStartRequest(net::OK);
+ ContinueToStartRequestWithOk();
+}
+
+void WebRequestProxyingURLLoaderFactory::InProgressRequest::
+ ContinueToSendHeadersWithOk(const std::set<std::string>& removed_headers,
+ const std::set<std::string>& set_headers) {
+ ContinueToSendHeaders(State::kInvalid, removed_headers, set_headers, net::OK);
}
void WebRequestProxyingURLLoaderFactory::InProgressRequest::ContinueAuthRequest(
@@ -698,6 +752,8 @@ void WebRequestProxyingURLLoaderFactory::InProgressRequest::ContinueAuthRequest(
WebRequestAPI::AuthRequestCallback callback,
int error_code) {
if (error_code != net::OK) {
+ // Here we come from an onHeaderReceived failure.
+ state_ = State::kRejectedByOnHeadersReceivedForAuth;
base::SequencedTaskRunnerHandle::Get()->PostTask(
FROM_HERE, base::BindOnce(std::move(callback), base::nullopt,
true /* should_cancel */));
@@ -756,6 +812,7 @@ void WebRequestProxyingURLLoaderFactory::InProgressRequest::
AUTH_REQUIRED_RESPONSE_CANCEL_AUTH:
completion = base::BindOnce(std::move(callback), base::nullopt,
true /* should_cancel */);
+ state_ = State::kRejectedByOnAuthRequired;
break;
default:
NOTREACHED();
@@ -770,7 +827,18 @@ void WebRequestProxyingURLLoaderFactory::InProgressRequest::
void WebRequestProxyingURLLoaderFactory::InProgressRequest::
ContinueToHandleOverrideHeaders(int error_code) {
if (error_code != net::OK) {
- OnRequestError(network::URLLoaderCompletionStatus(error_code));
+ const int status_code = current_response_->headers
+ ? current_response_->headers->response_code()
+ : 0;
+ State state;
+ if (status_code == net::HTTP_UNAUTHORIZED) {
+ state = State::kRejectedByOnHeadersReceivedForAuth;
+ } else if (net::HttpResponseHeaders::IsRedirectResponseCode(status_code)) {
+ state = State::kRejectedByOnHeadersReceivedForRedirect;
+ } else {
+ state = State::kRejectedByOnHeadersReceivedForFinalResponse;
+ }
+ OnRequestError(network::URLLoaderCompletionStatus(error_code), state);
return;
}
@@ -787,7 +855,8 @@ void WebRequestProxyingURLLoaderFactory::InProgressRequest::
}
if (for_cors_preflight_ && !redirect_url_.is_empty()) {
- OnRequestError(network::URLLoaderCompletionStatus(net::ERR_FAILED));
+ OnRequestError(network::URLLoaderCompletionStatus(net::ERR_FAILED),
+ State::kRejectedByOnHeadersReceivedForRedirect);
return;
}
@@ -816,10 +885,15 @@ void WebRequestProxyingURLLoaderFactory::InProgressRequest::
ContinueToResponseStarted(int error_code) {
DCHECK(!for_cors_preflight_);
if (error_code != net::OK) {
- OnRequestError(network::URLLoaderCompletionStatus(error_code));
+ OnRequestError(network::URLLoaderCompletionStatus(error_code),
+ State::kRejectedByOnHeadersReceivedForFinalResponse);
return;
}
+ if (state_ == State::kInProgress) {
+ state_ = State::kInProgressWithFinalResponseReceived;
+ }
+
DCHECK(!current_request_uses_header_client_ || !override_headers_);
if (override_headers_)
current_response_->headers = override_headers_;
@@ -863,7 +937,8 @@ void WebRequestProxyingURLLoaderFactory::InProgressRequest::
ContinueToBeforeRedirect(const net::RedirectInfo& redirect_info,
int error_code) {
if (error_code != net::OK) {
- OnRequestError(network::URLLoaderCompletionStatus(error_code));
+ OnRequestError(network::URLLoaderCompletionStatus(error_code),
+ kRejectedByOnHeadersReceivedForRedirect);
return;
}
@@ -907,7 +982,19 @@ void WebRequestProxyingURLLoaderFactory::InProgressRequest::
current_response_->headers.get(), &override_headers_,
&redirect_url_);
if (result == net::ERR_BLOCKED_BY_CLIENT) {
- OnRequestError(network::URLLoaderCompletionStatus(result));
+ const int status_code = current_response_->headers
+ ? current_response_->headers->response_code()
+ : 0;
+ State state;
+ if (status_code == net::HTTP_UNAUTHORIZED) {
+ state = State::kRejectedByOnHeadersReceivedForAuth;
+ } else if (net::HttpResponseHeaders::IsRedirectResponseCode(
+ status_code)) {
+ state = State::kRejectedByOnHeadersReceivedForRedirect;
+ } else {
+ state = State::kRejectedByOnHeadersReceivedForFinalResponse;
+ }
+ OnRequestError(network::URLLoaderCompletionStatus(result), state);
return;
}
@@ -930,17 +1017,41 @@ void WebRequestProxyingURLLoaderFactory::InProgressRequest::
copyable_callback.Run(net::OK);
}
void WebRequestProxyingURLLoaderFactory::InProgressRequest::OnRequestError(
- const network::URLLoaderCompletionStatus& status) {
+ const network::URLLoaderCompletionStatus& status,
+ State state) {
if (target_client_)
target_client_->OnComplete(status);
ExtensionWebRequestEventRouter::GetInstance()->OnErrorOccurred(
factory_->browser_context_, &info_.value(), true /* started */,
status.error_code);
+ state_ = state;
// Deletes |this|.
factory_->RemoveRequest(network_service_request_id_, request_id_);
}
+void WebRequestProxyingURLLoaderFactory::InProgressRequest::OnNetworkError(
+ const network::URLLoaderCompletionStatus& status) {
+ State state = state_;
+ if (state_ == State::kInProgress) {
+ state = State::kRejectedByNetworkError;
+ } else if (state_ == State::kInProgressWithFinalResponseReceived) {
+ state = State::kRejectedByNetworkErrorAfterReceivingFinalResponse;
+ }
+ OnRequestError(status, state);
+}
+
+void WebRequestProxyingURLLoaderFactory::InProgressRequest::
+ OnClientDisconnected() {
+ State state = state_;
+ if (state_ == State::kInProgress) {
+ state = State::kDetachedFromClient;
+ } else if (state_ == State::kInProgressWithFinalResponseReceived) {
+ state = State::kDetachedFromClientAfterReceivingResponse;
+ }
+ OnRequestError(network::URLLoaderCompletionStatus(net::ERR_ABORTED), state);
+}
+
void WebRequestProxyingURLLoaderFactory::InProgressRequest::
OnLoaderDisconnected(uint32_t custom_reason,
const std::string& description) {
@@ -953,10 +1064,11 @@ void WebRequestProxyingURLLoaderFactory::InProgressRequest::
factory_->request_id_generator_->SaveID(
routing_id_, network_service_request_id_, request_id_);
+ state_ = State::kRedirectFollowedByAnotherInProgressRequest;
// Deletes |this|.
factory_->RemoveRequest(network_service_request_id_, request_id_);
} else {
- OnRequestError(network::URLLoaderCompletionStatus(net::ERR_ABORTED));
+ OnNetworkError(network::URLLoaderCompletionStatus(net::ERR_ABORTED));
}
}
@@ -991,17 +1103,20 @@ WebRequestProxyingURLLoaderFactory::WebRequestProxyingURLLoaderFactory(
mojo::PendingReceiver<network::mojom::TrustedURLLoaderHeaderClient>
header_client_receiver,
WebRequestAPI::ProxySet* proxies,
- content::ContentBrowserClient::URLLoaderFactoryType loader_factory_type)
+ content::ContentBrowserClient::URLLoaderFactoryType loader_factory_type,
+ ukm::SourceId ukm_source_id)
: browser_context_(browser_context),
render_process_id_(render_process_id),
request_id_generator_(request_id_generator),
navigation_ui_data_(std::move(navigation_ui_data)),
navigation_id_(std::move(navigation_id)),
proxies_(proxies),
- loader_factory_type_(loader_factory_type) {
+ loader_factory_type_(loader_factory_type),
+ ukm_source_id_(ukm_source_id) {
DCHECK_CURRENTLY_ON(content::BrowserThread::UI);
- // base::Unretained is safe here because the callback will be canceled when
- // |shutdown_notifier_| is destroyed, and |proxies_| owns this.
+ // base::Unretained is safe here because the callback will be
+ // canceled when |shutdown_notifier_| is destroyed, and |proxies_|
+ // owns this.
shutdown_notifier_ =
ShutdownNotifierFactory::GetInstance()
->Get(browser_context)
@@ -1032,14 +1147,16 @@ void WebRequestProxyingURLLoaderFactory::StartProxying(
mojo::PendingReceiver<network::mojom::TrustedURLLoaderHeaderClient>
header_client_receiver,
WebRequestAPI::ProxySet* proxies,
- content::ContentBrowserClient::URLLoaderFactoryType loader_factory_type) {
+ content::ContentBrowserClient::URLLoaderFactoryType loader_factory_type,
+ ukm::SourceId ukm_source_id) {
DCHECK_CURRENTLY_ON(content::BrowserThread::UI);
auto proxy = std::make_unique<WebRequestProxyingURLLoaderFactory>(
browser_context, render_process_id, request_id_generator,
std::move(navigation_ui_data), std::move(navigation_id),
std::move(loader_receiver), std::move(target_factory_remote),
- std::move(header_client_receiver), proxies, loader_factory_type);
+ std::move(header_client_receiver), proxies, loader_factory_type,
+ ukm_source_id);
proxies->AddProxy(std::move(proxy));
}
@@ -1054,35 +1171,36 @@ void WebRequestProxyingURLLoaderFactory::CreateLoaderAndStart(
const net::MutableNetworkTrafficAnnotationTag& traffic_annotation) {
DCHECK_CURRENTLY_ON(content::BrowserThread::UI);
- // Make sure we are not proxying a browser initiated non-navigation request
- // except for loading service worker scripts.
+ // Make sure we are not proxying a browser initiated non-navigation
+ // request except for loading service worker scripts.
DCHECK(render_process_id_ != -1 || navigation_ui_data_ ||
IsForServiceWorkerScript());
- // The |web_request_id| doesn't really matter. It just needs to be unique
- // per-BrowserContext so extensions can make sense of it. Note that
- // |network_service_request_id_| by contrast is not necessarily unique, so we
- // don't use it for identity here. This request ID may be the same as a
- // previous request if the previous request was redirected to a URL that
- // required a different loader.
+ // The |web_request_id| doesn't really matter. It just needs to be
+ // unique per-BrowserContext so extensions can make sense of it.
+ // Note that |network_service_request_id_| by contrast is not
+ // necessarily unique, so we don't use it for identity here. This
+ // request ID may be the same as a previous request if the previous
+ // request was redirected to a URL that required a different loader.
const uint64_t web_request_id =
request_id_generator_->Generate(routing_id, request_id);
if (request_id) {
- // Only requests with a non-zero request ID can have their proxy associated
- // with said ID. This is necessary to support correlation against any auth
- // events received by the browser. Requests with a request ID of 0 therefore
- // do not support dispatching |WebRequest.onAuthRequired| events.
+ // Only requests with a non-zero request ID can have their proxy
+ // associated with said ID. This is necessary to support
+ // correlation against any auth events received by the browser.
+ // Requests with a request ID of 0 therefore do not support
+ // dispatching |WebRequest.onAuthRequired| events.
proxies_->AssociateProxyWithRequestId(
this, content::GlobalRequestID(render_process_id_, request_id));
network_request_id_to_web_request_id_.emplace(request_id, web_request_id);
}
auto result = requests_.emplace(
- web_request_id,
- std::make_unique<InProgressRequest>(
- this, web_request_id, request_id, routing_id, options, request,
- traffic_annotation, std::move(loader_receiver), std::move(client)));
+ web_request_id, std::make_unique<InProgressRequest>(
+ this, web_request_id, request_id, routing_id, options,
+ ukm_source_id_, request, traffic_annotation,
+ std::move(loader_receiver), std::move(client)));
result.first->second->Restart();
}
diff --git a/chromium/extensions/browser/api/web_request/web_request_proxying_url_loader_factory.h b/chromium/extensions/browser/api/web_request/web_request_proxying_url_loader_factory.h
index 35c4bda6134..67e79302271 100644
--- a/chromium/extensions/browser/api/web_request/web_request_proxying_url_loader_factory.h
+++ b/chromium/extensions/browser/api/web_request/web_request_proxying_url_loader_factory.h
@@ -25,6 +25,7 @@
#include "mojo/public/cpp/bindings/remote.h"
#include "net/base/completion_once_callback.h"
#include "net/traffic_annotation/network_traffic_annotation.h"
+#include "services/metrics/public/cpp/ukm_source_id.h"
#include "services/network/public/cpp/resource_request.h"
#include "services/network/public/mojom/network_context.mojom.h"
#include "services/network/public/mojom/url_loader.mojom.h"
@@ -54,6 +55,7 @@ class WebRequestProxyingURLLoaderFactory
int32_t routing_id,
int32_t network_service_request_id,
uint32_t options,
+ ukm::SourceId ukm_source_id,
const network::ResourceRequest& request,
const net::MutableNetworkTrafficAnnotationTag& traffic_annotation,
mojo::PendingReceiver<network::mojom::URLLoader> loader_receiver,
@@ -106,15 +108,41 @@ class WebRequestProxyingURLLoaderFactory
OnHeadersReceivedCallback callback) override;
private:
+ // The state of an InprogressRequest. This is reported via UMA and UKM
+ // at the end of the request, so do not change enum values.
+ enum State {
+ kInProgress = 0,
+ kInProgressWithFinalResponseReceived,
+ kInvalid, // This is an invalid state and must not be recorded.
+ kRedirectFollowedByAnotherInProgressRequest,
+ kRejectedByNetworkError,
+ kRejectedByNetworkErrorAfterReceivingFinalResponse,
+ kDetachedFromClient,
+ kDetachedFromClientAfterReceivingResponse,
+ kRejectedByOnBeforeRequest,
+ kRejectedByOnBeforeSendHeaders,
+ kRejectedByOnHeadersReceivedForFinalResponse,
+ kRejectedByOnHeadersReceivedForRedirect,
+ kRejectedByOnHeadersReceivedForAuth,
+ kRejectedByOnAuthRequired,
+ kCompleted,
+ kMaxValue = kCompleted,
+ };
// These two methods combined form the implementation of Restart().
void UpdateRequestInfo();
void RestartInternal();
- void ContinueToBeforeSendHeaders(int error_code);
- void ContinueToSendHeaders(const std::set<std::string>& removed_headers,
+ void ContinueToBeforeSendHeaders(State state_on_error, int error_code);
+ void ContinueToBeforeSendHeadersWithOk();
+ void ContinueToSendHeaders(State state_on_error,
+ const std::set<std::string>& removed_headers,
const std::set<std::string>& set_headers,
int error_code);
- void ContinueToStartRequest(int error_code);
+ void ContinueToSendHeadersWithOk(
+ const std::set<std::string>& removed_headers,
+ const std::set<std::string>& set_headers);
+ void ContinueToStartRequest(State state_on_error, int error_code);
+ void ContinueToStartRequestWithOk();
void ContinueToHandleOverrideHeaders(int error_code);
void ContinueToResponseStarted(int error_code);
void ContinueAuthRequest(const net::AuthChallengeInfo& auth_info,
@@ -127,7 +155,10 @@ class WebRequestProxyingURLLoaderFactory
int error_code);
void HandleResponseOrRedirectHeaders(
net::CompletionOnceCallback continuation);
- void OnRequestError(const network::URLLoaderCompletionStatus& status);
+ void OnRequestError(const network::URLLoaderCompletionStatus& status,
+ State state);
+ void OnNetworkError(const network::URLLoaderCompletionStatus& status);
+ void OnClientDisconnected();
void OnLoaderDisconnected(uint32_t custom_reason,
const std::string& description);
bool IsRedirectSafe(const GURL& from_url,
@@ -142,6 +173,7 @@ class WebRequestProxyingURLLoaderFactory
const int32_t network_service_request_id_ = 0;
const int32_t routing_id_ = 0;
const uint32_t options_ = 0;
+ const ukm::SourceId ukm_source_id_;
const net::MutableNetworkTrafficAnnotationTag traffic_annotation_;
mojo::Receiver<network::mojom::URLLoader> proxied_loader_receiver_;
mojo::Remote<network::mojom::URLLoaderClient> target_client_;
@@ -179,6 +211,7 @@ class WebRequestProxyingURLLoaderFactory
OnHeadersReceivedCallback on_headers_received_callback_;
mojo::Receiver<network::mojom::TrustedHeaderClient> header_client_receiver_{
this};
+ bool is_header_client_receiver_paused_ = false;
// If |has_any_extra_headers_listeners_| is set to false and a redirect is
// in progress, this stores the parameters to FollowRedirect that came from
@@ -195,6 +228,7 @@ class WebRequestProxyingURLLoaderFactory
DISALLOW_COPY_AND_ASSIGN(FollowRedirectParams);
};
std::unique_ptr<FollowRedirectParams> pending_follow_redirect_params_;
+ State state_ = State::kInProgress;
base::WeakPtrFactory<InProgressRequest> weak_factory_{this};
@@ -213,7 +247,8 @@ class WebRequestProxyingURLLoaderFactory
mojo::PendingReceiver<network::mojom::TrustedURLLoaderHeaderClient>
header_client_receiver,
WebRequestAPI::ProxySet* proxies,
- content::ContentBrowserClient::URLLoaderFactoryType loader_factory_type);
+ content::ContentBrowserClient::URLLoaderFactoryType loader_factory_type,
+ ukm::SourceId ukm_source_id);
~WebRequestProxyingURLLoaderFactory() override;
@@ -229,7 +264,8 @@ class WebRequestProxyingURLLoaderFactory
mojo::PendingReceiver<network::mojom::TrustedURLLoaderHeaderClient>
header_client_receiver,
WebRequestAPI::ProxySet* proxies,
- content::ContentBrowserClient::URLLoaderFactoryType loader_factory_type);
+ content::ContentBrowserClient::URLLoaderFactoryType loader_factory_type,
+ ukm::SourceId ukm_source_id);
// network::mojom::URLLoaderFactory:
void CreateLoaderAndStart(
@@ -289,6 +325,9 @@ class WebRequestProxyingURLLoaderFactory
const content::ContentBrowserClient::URLLoaderFactoryType
loader_factory_type_;
+ // A UKM source ID associated with the content::WebContents of the initiator
+ // frame.
+ const ukm::SourceId ukm_source_id_;
// Mapping from our own internally generated request ID to an
// InProgressRequest instance.
diff --git a/chromium/extensions/browser/app_sorting.h b/chromium/extensions/browser/app_sorting.h
index ee242d00cb7..c37e74f1c35 100644
--- a/chromium/extensions/browser/app_sorting.h
+++ b/chromium/extensions/browser/app_sorting.h
@@ -21,6 +21,11 @@ class AppSorting {
AppSorting() {}
virtual ~AppSorting() {}
+ // Signals that ordinals for the WebAppProvider system should (or can) be
+ // loaded now. Calls to the WebAppProvider system should not be done before
+ // this is called. Called from WebAppUiManagerImpl::Start().
+ virtual void InitializePageOrdinalMapFromWebApps() = 0;
+
// Resolves any conflicts the might be created as a result of syncing that
// results in two icons having the same page and app launch ordinal. After
// this is called it is guaranteed that there are no collisions of NTP icons.
diff --git a/chromium/extensions/browser/app_window/app_window.cc b/chromium/extensions/browser/app_window/app_window.cc
index 2aca418397b..e4bb82c7f5f 100644
--- a/chromium/extensions/browser/app_window/app_window.cc
+++ b/chromium/extensions/browser/app_window/app_window.cc
@@ -275,9 +275,6 @@ void AppWindow::Init(const GURL& url,
// Initialize the window
CreateParams new_params = LoadDefaults(params);
window_type_ = new_params.window_type;
- UMA_HISTOGRAM_ENUMERATION("Apps.Window.Type", new_params.window_type,
- WINDOW_TYPE_COUNT);
-
window_key_ = new_params.window_key;
// Windows cannot be always-on-top in fullscreen mode for security reasons.
@@ -921,10 +918,10 @@ void AppWindow::NavigationStateChanged(content::WebContents* source,
}
void AppWindow::EnterFullscreenModeForTab(
- content::WebContents* source,
- const GURL& origin,
+ content::RenderFrameHost* requesting_frame,
const blink::mojom::FullscreenOptions& options) {
- ToggleFullscreenModeForTab(source, true);
+ ToggleFullscreenModeForTab(WebContents::FromRenderFrameHost(requesting_frame),
+ true);
}
void AppWindow::ExitFullscreenModeForTab(content::WebContents* source) {
diff --git a/chromium/extensions/browser/app_window/app_window.h b/chromium/extensions/browser/app_window/app_window.h
index c31c6dcfa28..d510a765a85 100644
--- a/chromium/extensions/browser/app_window/app_window.h
+++ b/chromium/extensions/browser/app_window/app_window.h
@@ -408,8 +408,7 @@ class AppWindow : public content::WebContentsDelegate,
void NavigationStateChanged(content::WebContents* source,
content::InvalidateTypes changed_flags) override;
void EnterFullscreenModeForTab(
- content::WebContents* source,
- const GURL& origin,
+ content::RenderFrameHost* requesting_frame,
const blink::mojom::FullscreenOptions& options) override;
void ExitFullscreenModeForTab(content::WebContents* source) override;
bool IsFullscreenForTabOrPending(const content::WebContents* source) override;
diff --git a/chromium/extensions/browser/computed_hashes.cc b/chromium/extensions/browser/computed_hashes.cc
index e21cd2356dc..d2b98d6aca5 100644
--- a/chromium/extensions/browser/computed_hashes.cc
+++ b/chromium/extensions/browser/computed_hashes.cc
@@ -14,6 +14,7 @@
#include "base/files/file_util.h"
#include "base/json/json_reader.h"
#include "base/json/json_writer.h"
+#include "base/logging.h"
#include "base/stl_util.h"
#include "base/timer/elapsed_timer.h"
#include "base/values.h"
diff --git a/chromium/extensions/browser/content_verifier.cc b/chromium/extensions/browser/content_verifier.cc
index feec17b834e..6bcf0ed5134 100644
--- a/chromium/extensions/browser/content_verifier.cc
+++ b/chromium/extensions/browser/content_verifier.cc
@@ -16,7 +16,6 @@
#include "base/metrics/histogram_macros.h"
#include "base/stl_util.h"
#include "base/strings/string_util.h"
-#include "base/task/post_task.h"
#include "base/threading/thread_restrictions.h"
#include "base/timer/elapsed_timer.h"
#include "content/public/browser/browser_context.h"
@@ -324,8 +323,8 @@ class ContentVerifier::HashHelper {
if (was_cancelled)
return;
- base::PostTask(
- FROM_HERE, {content::BrowserThread::IO},
+ content::GetIOThreadTaskRunner({})->PostTask(
+ FROM_HERE,
base::BindOnce(std::move(callback), content_hash, was_cancelled));
}
@@ -448,8 +447,8 @@ void ContentVerifier::Start() {
void ContentVerifier::Shutdown() {
shutdown_on_ui_ = true;
delegate_->Shutdown();
- base::PostTask(FROM_HERE, {content::BrowserThread::IO},
- base::BindOnce(&ContentVerifier::ShutdownOnIO, this));
+ content::GetIOThreadTaskRunner({})->PostTask(
+ FROM_HERE, base::BindOnce(&ContentVerifier::ShutdownOnIO, this));
observer_.RemoveAll();
}
@@ -511,8 +510,8 @@ void ContentVerifier::GetContentHash(
// TODO(lazyboy): Make CreateJobFor return a scoped_refptr instead of raw
// pointer to fix this. Also add unit test to exercise this code path
// explicitly.
- base::PostTask(FROM_HERE, {content::BrowserThread::IO},
- base::BindOnce(base::DoNothing::Once<ContentHashCallback>(),
+ content::GetIOThreadTaskRunner({})->PostTask(
+ FROM_HERE, base::BindOnce(base::DoNothing::Once<ContentHashCallback>(),
std::move(callback)));
return;
}
@@ -522,8 +521,8 @@ void ContentVerifier::GetContentHash(
auto cache_iter = cache_.find(cache_key);
if (cache_iter != cache_.end()) {
// Currently, we expect |callback| to be called asynchronously.
- base::PostTask(FROM_HERE, {content::BrowserThread::IO},
- base::BindOnce(std::move(callback), cache_iter->second));
+ content::GetIOThreadTaskRunner({})->PostTask(
+ FROM_HERE, base::BindOnce(std::move(callback), cache_iter->second));
return;
}
@@ -549,8 +548,8 @@ bool ContentVerifier::ShouldComputeHashesOnInstall(const Extension& extension) {
void ContentVerifier::VerifyFailed(const ExtensionId& extension_id,
ContentVerifyJob::FailureReason reason) {
if (!content::BrowserThread::CurrentlyOn(content::BrowserThread::UI)) {
- base::PostTask(FROM_HERE, {content::BrowserThread::UI},
- base::BindOnce(&ContentVerifier::VerifyFailed, this,
+ content::GetUIThreadTaskRunner({})->PostTask(
+ FROM_HERE, base::BindOnce(&ContentVerifier::VerifyFailed, this,
extension_id, reason));
return;
}
@@ -572,8 +571,8 @@ void ContentVerifier::OnExtensionLoaded(
std::unique_ptr<ContentVerifierIOData::ExtensionData> io_data =
CreateIOData(extension, delegate_.get());
if (io_data) {
- base::PostTask(FROM_HERE, {content::BrowserThread::IO},
- base::BindOnce(&ContentVerifier::OnExtensionLoadedOnIO, this,
+ content::GetIOThreadTaskRunner({})->PostTask(
+ FROM_HERE, base::BindOnce(&ContentVerifier::OnExtensionLoadedOnIO, this,
extension->id(), extension->path(),
extension->version(), std::move(io_data)));
}
@@ -600,8 +599,8 @@ void ContentVerifier::OnExtensionUnloaded(
UnloadedExtensionReason reason) {
if (shutdown_on_ui_)
return;
- base::PostTask(FROM_HERE, {content::BrowserThread::IO},
- base::BindOnce(&ContentVerifier::OnExtensionUnloadedOnIO, this,
+ content::GetIOThreadTaskRunner({})->PostTask(
+ FROM_HERE, base::BindOnce(&ContentVerifier::OnExtensionUnloadedOnIO, this,
extension->id(), extension->version()));
}
@@ -679,8 +678,8 @@ ContentHash::FetchKey ContentVerifier::GetFetchKey(
// even though it needs to finish initialization on the UI thread.
mojo::PendingRemote<network::mojom::URLLoaderFactory>
url_loader_factory_remote;
- base::PostTask(
- FROM_HERE, {content::BrowserThread::UI},
+ content::GetUIThreadTaskRunner({})->PostTask(
+ FROM_HERE,
base::BindOnce(
&ContentVerifier::BindURLLoaderFactoryReceiverOnUIThread, this,
url_loader_factory_remote.InitWithNewPipeAndPassReceiver()));
diff --git a/chromium/extensions/browser/content_verify_job_unittest.cc b/chromium/extensions/browser/content_verify_job_unittest.cc
index a947718e467..ba2952bb918 100644
--- a/chromium/extensions/browser/content_verify_job_unittest.cc
+++ b/chromium/extensions/browser/content_verify_job_unittest.cc
@@ -8,7 +8,6 @@
#include "base/files/file_util.h"
#include "base/files/scoped_temp_dir.h"
#include "base/path_service.h"
-#include "base/task/post_task.h"
#include "base/test/bind_test_util.h"
#include "base/version.h"
#include "content/public/browser/browser_task_traits.h"
@@ -241,8 +240,8 @@ class ContentVerifyJobUnittest : public ExtensionsTest {
private:
void StartJob(scoped_refptr<ContentVerifyJob> job) {
- base::PostTask(FROM_HERE, {content::BrowserThread::IO},
- base::BindOnce(&ContentVerifyJob::Start, job,
+ content::GetIOThreadTaskRunner({})->PostTask(
+ FROM_HERE, base::BindOnce(&ContentVerifyJob::Start, job,
base::Unretained(content_verifier_.get())));
}
@@ -808,8 +807,8 @@ class ContentVerifyJobWithHashFetchUnittest : public ContentVerifyJobUnittest {
// we've already deleted verified_contents.json.
// Use this opportunity to
base::RunLoop run_loop;
- base::PostTaskAndReply(
- FROM_HERE, {content::BrowserThread::IO},
+ content::GetIOThreadTaskRunner({})->PostTaskAndReply(
+ FROM_HERE,
base::BindOnce(
[](scoped_refptr<ContentVerifier> content_verifier) {
content_verifier->ClearCacheForTesting();
@@ -880,8 +879,8 @@ TEST_F(ContentVerifyJobWithHashFetchUnittest, ReadErrorBeforeHashReady) {
};
base::RunLoop run_loop;
- base::PostTask(FROM_HERE, {content::BrowserThread::IO},
- base::BindOnce(do_read_abort_and_done, verify_job,
+ content::GetIOThreadTaskRunner({})->PostTask(
+ FROM_HERE, base::BindOnce(do_read_abort_and_done, verify_job,
content_verifier(), run_loop.QuitClosure()));
run_loop.Run();
diff --git a/chromium/extensions/browser/crx_file_info.h b/chromium/extensions/browser/crx_file_info.h
index 09eff245938..20645da28b5 100644
--- a/chromium/extensions/browser/crx_file_info.h
+++ b/chromium/extensions/browser/crx_file_info.h
@@ -8,6 +8,7 @@
#include <string>
#include "base/files/file_path.h"
+#include "base/version.h"
#include "extensions/common/extension_id.h"
namespace crx_file {
@@ -32,7 +33,7 @@ struct CRXFileInfo {
crx_file::VerifierFormat required_format;
ExtensionId extension_id;
std::string expected_hash;
- std::string expected_version;
+ base::Version expected_version;
};
} // namespace extensions
diff --git a/chromium/extensions/browser/declarative_user_script_manager.cc b/chromium/extensions/browser/declarative_user_script_manager.cc
index 84f7e266d5c..e4709f744ef 100644
--- a/chromium/extensions/browser/declarative_user_script_manager.cc
+++ b/chromium/extensions/browser/declarative_user_script_manager.cc
@@ -6,7 +6,7 @@
#include "content/public/browser/browser_context.h"
#include "extensions/browser/declarative_user_script_manager_factory.h"
-#include "extensions/browser/declarative_user_script_master.h"
+#include "extensions/browser/declarative_user_script_set.h"
namespace extensions {
@@ -26,24 +26,24 @@ DeclarativeUserScriptManager* DeclarativeUserScriptManager::Get(
browser_context);
}
-DeclarativeUserScriptMaster*
-DeclarativeUserScriptManager::GetDeclarativeUserScriptMasterByID(
+DeclarativeUserScriptSet*
+DeclarativeUserScriptManager::GetDeclarativeUserScriptSetByID(
const HostID& host_id) {
- auto it = declarative_user_script_masters_.find(host_id);
+ auto it = declarative_user_script_sets_.find(host_id);
- if (it != declarative_user_script_masters_.end())
+ if (it != declarative_user_script_sets_.end())
return it->second.get();
- return CreateDeclarativeUserScriptMaster(host_id);
+ return CreateDeclarativeUserScriptSet(host_id);
}
-DeclarativeUserScriptMaster*
-DeclarativeUserScriptManager::CreateDeclarativeUserScriptMaster(
+DeclarativeUserScriptSet*
+DeclarativeUserScriptManager::CreateDeclarativeUserScriptSet(
const HostID& host_id) {
// Inserts a new DeclarativeUserScriptManager and returns a ptr to it.
- return declarative_user_script_masters_
+ return declarative_user_script_sets_
.insert(
- std::make_pair(host_id, std::make_unique<DeclarativeUserScriptMaster>(
+ std::make_pair(host_id, std::make_unique<DeclarativeUserScriptSet>(
browser_context_, host_id)))
.first->second.get();
}
@@ -52,10 +52,10 @@ void DeclarativeUserScriptManager::OnExtensionUnloaded(
content::BrowserContext* browser_context,
const Extension* extension,
UnloadedExtensionReason reason) {
- for (const auto& val : declarative_user_script_masters_) {
- DeclarativeUserScriptMaster* master = val.second.get();
- if (master->host_id().id() == extension->id())
- master->ClearScripts();
+ for (const auto& val : declarative_user_script_sets_) {
+ DeclarativeUserScriptSet* set = val.second.get();
+ if (set->host_id().id() == extension->id())
+ set->ClearScripts();
}
}
diff --git a/chromium/extensions/browser/declarative_user_script_manager.h b/chromium/extensions/browser/declarative_user_script_manager.h
index 5ebed9f45f9..cbac791467d 100644
--- a/chromium/extensions/browser/declarative_user_script_manager.h
+++ b/chromium/extensions/browser/declarative_user_script_manager.h
@@ -19,9 +19,9 @@ class BrowserContext;
}
namespace extensions {
-class DeclarativeUserScriptMaster;
+class DeclarativeUserScriptSet;
-// Manages a set of DeclarativeUserScriptMaster objects for script injections.
+// Manages a set of DeclarativeUserScriptSet objects for script injections.
class DeclarativeUserScriptManager : public KeyedService,
public ExtensionRegistryObserver {
public:
@@ -33,27 +33,27 @@ class DeclarativeUserScriptManager : public KeyedService,
// |context|.
static DeclarativeUserScriptManager* Get(content::BrowserContext* context);
- // Gets the user script master for declarative scripts by the given
- // HostID; if one does not exist, a new object will be created.
- DeclarativeUserScriptMaster* GetDeclarativeUserScriptMasterByID(
+ // Gets the user script set for declarative scripts by the given HostId.
+ // If one does not exist, a new object will be created.
+ DeclarativeUserScriptSet* GetDeclarativeUserScriptSetByID(
const HostID& host_id);
private:
- using UserScriptMasterMap =
- std::map<HostID, std::unique_ptr<DeclarativeUserScriptMaster>>;
+ using UserScriptSetMap =
+ std::map<HostID, std::unique_ptr<DeclarativeUserScriptSet>>;
// ExtensionRegistryObserver:
void OnExtensionUnloaded(content::BrowserContext* browser_context,
const Extension* extension,
UnloadedExtensionReason reason) override;
- // Creates a DeclarativeUserScriptMaster object.
- DeclarativeUserScriptMaster* CreateDeclarativeUserScriptMaster(
+ // Creates a DeclarativeUserScriptSet object.
+ DeclarativeUserScriptSet* CreateDeclarativeUserScriptSet(
const HostID& host_id);
- // A map of DeclarativeUserScriptMasters for each host; each master
- // is lazily initialized.
- UserScriptMasterMap declarative_user_script_masters_;
+ // A map of DeclarativeUserScriptSets for each host; each set is lazily
+ // initialized.
+ UserScriptSetMap declarative_user_script_sets_;
content::BrowserContext* browser_context_;
diff --git a/chromium/extensions/browser/declarative_user_script_master.cc b/chromium/extensions/browser/declarative_user_script_set.cc
index c8f1a828895..82ca77c8e41 100644
--- a/chromium/extensions/browser/declarative_user_script_master.cc
+++ b/chromium/extensions/browser/declarative_user_script_set.cc
@@ -2,7 +2,7 @@
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
-#include "extensions/browser/declarative_user_script_master.h"
+#include "extensions/browser/declarative_user_script_set.h"
#include "content/public/browser/browser_context.h"
#include "extensions/browser/extension_user_script_loader.h"
@@ -12,7 +12,7 @@
namespace extensions {
-DeclarativeUserScriptMaster::DeclarativeUserScriptMaster(
+DeclarativeUserScriptSet::DeclarativeUserScriptSet(
content::BrowserContext* browser_context,
const HostID& host_id)
: host_id_(host_id) {
@@ -28,35 +28,33 @@ DeclarativeUserScriptMaster::DeclarativeUserScriptMaster(
}
}
-DeclarativeUserScriptMaster::~DeclarativeUserScriptMaster() {
-}
+DeclarativeUserScriptSet::~DeclarativeUserScriptSet() {}
-void DeclarativeUserScriptMaster::AddScript(
- std::unique_ptr<UserScript> script) {
+void DeclarativeUserScriptSet::AddScript(std::unique_ptr<UserScript> script) {
std::unique_ptr<UserScriptList> scripts(new UserScriptList());
scripts->push_back(std::move(script));
loader_->AddScripts(std::move(scripts));
}
-void DeclarativeUserScriptMaster::AddScripts(
+void DeclarativeUserScriptSet::AddScripts(
std::unique_ptr<UserScriptList> scripts,
int render_process_id,
int render_view_id) {
loader_->AddScripts(std::move(scripts), render_process_id, render_view_id);
}
-void DeclarativeUserScriptMaster::RemoveScript(const UserScriptIDPair& script) {
+void DeclarativeUserScriptSet::RemoveScript(const UserScriptIDPair& script) {
std::set<UserScriptIDPair> scripts;
scripts.insert(script);
RemoveScripts(scripts);
}
-void DeclarativeUserScriptMaster::RemoveScripts(
+void DeclarativeUserScriptSet::RemoveScripts(
const std::set<UserScriptIDPair>& scripts) {
loader_->RemoveScripts(scripts);
}
-void DeclarativeUserScriptMaster::ClearScripts() {
+void DeclarativeUserScriptSet::ClearScripts() {
loader_->ClearScripts();
}
diff --git a/chromium/extensions/browser/declarative_user_script_master.h b/chromium/extensions/browser/declarative_user_script_set.h
index 7542ba398da..2c63d017dae 100644
--- a/chromium/extensions/browser/declarative_user_script_master.h
+++ b/chromium/extensions/browser/declarative_user_script_set.h
@@ -2,8 +2,8 @@
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
-#ifndef EXTENSIONS_BROWSER_DECLARATIVE_USER_SCRIPT_MASTER_H_
-#define EXTENSIONS_BROWSER_DECLARATIVE_USER_SCRIPT_MASTER_H_
+#ifndef EXTENSIONS_BROWSER_DECLARATIVE_USER_SCRIPT_SET_H_
+#define EXTENSIONS_BROWSER_DECLARATIVE_USER_SCRIPT_SET_H_
#include <memory>
#include <set>
@@ -27,11 +27,11 @@ struct UserScriptIDPair;
// UserScriptLoader to which file loading and shared memory management
// operations are delegated, and provides an interface for adding, removing,
// and clearing scripts.
-class DeclarativeUserScriptMaster {
+class DeclarativeUserScriptSet {
public:
- DeclarativeUserScriptMaster(content::BrowserContext* browser_context,
- const HostID& host_id);
- ~DeclarativeUserScriptMaster();
+ DeclarativeUserScriptSet(content::BrowserContext* browser_context,
+ const HostID& host_id);
+ ~DeclarativeUserScriptSet();
// Adds script to shared memory region. This may not happen right away if a
// script load is in progress.
@@ -70,9 +70,9 @@ class DeclarativeUserScriptMaster {
// and notifying renderers of script updates.
std::unique_ptr<UserScriptLoader> loader_;
- DISALLOW_COPY_AND_ASSIGN(DeclarativeUserScriptMaster);
+ DISALLOW_COPY_AND_ASSIGN(DeclarativeUserScriptSet);
};
} // namespace extensions
-#endif // EXTENSIONS_BROWSER_DECLARATIVE_USER_SCRIPT_MASTER_H_
+#endif // EXTENSIONS_BROWSER_DECLARATIVE_USER_SCRIPT_SET_H_
diff --git a/chromium/extensions/browser/event_listener_map.cc b/chromium/extensions/browser/event_listener_map.cc
index 29a399e8b5a..f3beb4d8faa 100644
--- a/chromium/extensions/browser/event_listener_map.cc
+++ b/chromium/extensions/browser/event_listener_map.cc
@@ -96,10 +96,12 @@ bool EventListener::IsLazy() const {
void EventListener::MakeLazy() {
// A lazy listener neither has a process attached to it nor it has a worker
- // thread id (if the listener was for a service worker), so reset these values
+ // thread (if the listener was for a service worker), so reset these values
// below to reflect that.
- if (is_for_service_worker_)
+ if (is_for_service_worker_) {
worker_thread_id_ = kMainThreadId;
+ service_worker_version_id_ = blink::mojom::kInvalidServiceWorkerVersionId;
+ }
process_ = nullptr;
}
@@ -165,13 +167,18 @@ std::unique_ptr<EventMatcher> EventListenerMap::ParseEventMatcher(
}
bool EventListenerMap::RemoveListener(const EventListener* listener) {
- ListenerList& listeners = listeners_[listener->event_name()];
+ auto listener_itr = listeners_.find(listener->event_name());
+ if (listener_itr == listeners_.end())
+ return false;
+ ListenerList& listeners = listener_itr->second;
for (auto& it : listeners) {
if (it->Equals(listener)) {
CleanupListener(it.get());
// Popping from the back should be cheaper than erase(it).
std::swap(it, listeners.back());
listeners.pop_back();
+ if (listeners.empty())
+ listeners_.erase(listener_itr);
delegate_->OnListenerRemoved(listener);
return true;
}
@@ -229,18 +236,24 @@ bool EventListenerMap::HasProcessListener(
void EventListenerMap::RemoveListenersForExtension(
const std::string& extension_id) {
- for (auto& it : listeners_) {
- auto& listener_map = it.second;
- for (auto it2 = listener_map.begin(); it2 != listener_map.end();) {
+ for (auto it = listeners_.begin(); it != listeners_.end();) {
+ auto& listener_list = it->second;
+ for (auto it2 = listener_list.begin(); it2 != listener_list.end();) {
if ((*it2)->extension_id() == extension_id) {
std::unique_ptr<EventListener> listener_removed = std::move(*it2);
CleanupListener(listener_removed.get());
- it2 = listener_map.erase(it2);
+ it2 = listener_list.erase(it2);
delegate_->OnListenerRemoved(listener_removed.get());
} else {
++it2;
}
}
+ // Check if we removed all the listeners from the list. If so,
+ // remove the list entry entirely.
+ if (listener_list.empty())
+ it = listeners_.erase(it);
+ else
+ ++it;
}
}
@@ -289,7 +302,7 @@ void EventListenerMap::LoadFilteredLazyListeners(
// https://crbug.com/773103.
Extension::GetBaseURLFromExtensionId(extension_id),
blink::mojom::kInvalidServiceWorkerVersionId, kMainThreadId,
- nullptr));
+ filter->CreateDeepCopy()));
} else {
AddListener(EventListener::ForExtension(it.key(), extension_id, nullptr,
filter->CreateDeepCopy()));
@@ -322,18 +335,24 @@ std::set<const EventListener*> EventListenerMap::GetEventListeners(
void EventListenerMap::RemoveListenersForProcess(
const content::RenderProcessHost* process) {
CHECK(process);
- for (auto& it : listeners_) {
- auto& listener_map = it.second;
- for (auto it2 = listener_map.begin(); it2 != listener_map.end();) {
+ for (auto it = listeners_.begin(); it != listeners_.end();) {
+ auto& listener_list = it->second;
+ for (auto it2 = listener_list.begin(); it2 != listener_list.end();) {
if ((*it2)->process() == process) {
std::unique_ptr<EventListener> listener_removed = std::move(*it2);
CleanupListener(listener_removed.get());
- it2 = listener_map.erase(it2);
+ it2 = listener_list.erase(it2);
delegate_->OnListenerRemoved(listener_removed.get());
} else {
++it2;
}
}
+ // Check if we removed all the listeners from the list. If so,
+ // remove the list entry entirely.
+ if (listener_list.empty())
+ it = listeners_.erase(it);
+ else
+ ++it;
}
}
@@ -341,6 +360,11 @@ void EventListenerMap::CleanupListener(EventListener* listener) {
// If the listener doesn't have a filter then we have nothing to clean up.
if (listener->matcher_id() == -1)
return;
+ // If we're removing the final listener for an event, we can remove the
+ // entry from |filtered_events_|, as well.
+ auto iter = listeners_.find(listener->event_name());
+ if (iter->second.size() == 1)
+ filtered_events_.erase(iter->first);
event_filter_.RemoveEventMatcher(listener->matcher_id());
CHECK_EQ(1u, listeners_by_matcher_id_.erase(listener->matcher_id()));
}
diff --git a/chromium/extensions/browser/event_listener_map.h b/chromium/extensions/browser/event_listener_map.h
index 28143b8cc7b..50f196debd7 100644
--- a/chromium/extensions/browser/event_listener_map.h
+++ b/chromium/extensions/browser/event_listener_map.h
@@ -124,7 +124,7 @@ class EventListener {
const bool is_for_service_worker_ = false;
- const int64_t service_worker_version_id_ =
+ int64_t service_worker_version_id_ =
blink::mojom::kInvalidServiceWorkerVersionId;
// If this listener is for a service worker (i.e.
diff --git a/chromium/extensions/browser/event_listener_map_unittest.cc b/chromium/extensions/browser/event_listener_map_unittest.cc
index 393a9e9a948..2659770a5b8 100644
--- a/chromium/extensions/browser/event_listener_map_unittest.cc
+++ b/chromium/extensions/browser/event_listener_map_unittest.cc
@@ -29,6 +29,19 @@ const char kEvent1Name[] = "event1";
const char kEvent2Name[] = "event2";
const char kURL[] = "https://google.com/some/url";
+// Returns appropriate worker version id for tests.
+int64_t GetWorkerVersionId(bool lazy) {
+ static constexpr int64_t kDummyServiceWorkerVersionId = 199;
+ return lazy ? blink::mojom::kInvalidServiceWorkerVersionId
+ : kDummyServiceWorkerVersionId;
+}
+
+// Returns appropriate worker thread id for tests.
+int GetWorkerThreadId(bool lazy) {
+ static constexpr int kDummyServiceWorkerThreadId = 99;
+ return lazy ? kMainThreadId : kDummyServiceWorkerThreadId;
+}
+
using EventListenerConstructor =
base::RepeatingCallback<std::unique_ptr<EventListener>(
const std::string& /* event_name */,
@@ -86,6 +99,21 @@ class EventListenerMapTest : public ExtensionsTest {
GURL(), EventRouter::USER_GESTURE_UNKNOWN, info);
}
+ std::unique_ptr<EventListener> CreateLazyListener(
+ const std::string& event_name,
+ const ExtensionId& extension_id,
+ std::unique_ptr<base::DictionaryValue> filter,
+ bool is_for_service_worker) {
+ if (is_for_service_worker) {
+ return EventListener::ForExtensionServiceWorker(
+ event_name, extension_id, nullptr,
+ Extension::GetBaseURLFromExtensionId(extension_id),
+ GetWorkerVersionId(true), GetWorkerThreadId(true), std::move(filter));
+ }
+ return EventListener::ForExtension(event_name, extension_id, nullptr,
+ std::move(filter));
+ }
+
protected:
void TestUnfilteredEventsGoToAllListeners(
const EventListenerConstructor& constructor);
@@ -100,6 +128,11 @@ class EventListenerMapTest : public ExtensionsTest {
content::RenderProcessHost* process_;
};
+// Parameterized version of test to run with |is_for_service_worker|.
+class EventListenerMapWithContextTest
+ : public EventListenerMapTest,
+ public testing::WithParamInterface<bool /* is_for_service_worker */> {};
+
std::unique_ptr<EventListener> CreateEventListenerForExtension(
const std::string& extension_id,
const std::string& event_name,
@@ -118,6 +151,17 @@ std::unique_ptr<EventListener> CreateEventListenerForURL(
std::move(filter));
}
+std::unique_ptr<EventListener> CreateEventListenerForExtensionServiceWorker(
+ const std::string& extension_id,
+ const std::string& event_name,
+ content::RenderProcessHost* process,
+ std::unique_ptr<base::DictionaryValue> filter) {
+ return EventListener::ForExtensionServiceWorker(
+ event_name, extension_id, process,
+ Extension::GetBaseURLFromExtensionId(extension_id),
+ GetWorkerVersionId(false), GetWorkerThreadId(false), std::move(filter));
+}
+
void EventListenerMapTest::TestUnfilteredEventsGoToAllListeners(
const EventListenerConstructor& constructor) {
listeners_->AddListener(constructor.Run(
@@ -136,28 +180,76 @@ TEST_F(EventListenerMapTest, UnfilteredEventsGoToAllListenersForURLs) {
base::BindRepeating(&CreateEventListenerForURL, GURL(kURL)));
}
+TEST_F(EventListenerMapTest,
+ UnfilteredEventsGoToAllListenersForExtensionServiceWorkers) {
+ TestUnfilteredEventsGoToAllListeners(base::BindRepeating(
+ &CreateEventListenerForExtensionServiceWorker, kExt1Id));
+}
+
TEST_F(EventListenerMapTest, FilteredEventsGoToAllMatchingListeners) {
- listeners_->AddListener(EventListener::ForExtension(
- kEvent1Name, kExt1Id, nullptr, CreateHostSuffixFilter("google.com")));
- listeners_->AddListener(EventListener::ForExtension(
- kEvent1Name, kExt1Id, nullptr, std::make_unique<DictionaryValue>()));
+ auto create_filter = [&](const std::string& filter_str) {
+ return CreateHostSuffixFilter(filter_str);
+ };
+ auto create_empty_filter = []() {
+ return std::make_unique<base::DictionaryValue>();
+ };
+
+ for (bool is_for_service_worker : {false, true}) {
+ listeners_->AddListener(CreateLazyListener(kEvent1Name, kExt1Id,
+ create_filter("google.com"),
+ is_for_service_worker));
+ listeners_->AddListener(CreateLazyListener(
+ kEvent1Name, kExt1Id, create_empty_filter(), is_for_service_worker));
+ }
std::unique_ptr<Event> event(CreateNamedEvent(kEvent1Name));
event->filter_info.url = GURL("http://www.google.com");
std::set<const EventListener*> targets(listeners_->GetEventListeners(*event));
- ASSERT_EQ(2u, targets.size());
+ ASSERT_EQ(4u, targets.size());
}
-TEST_F(EventListenerMapTest, FilteredEventsOnlyGoToMatchingListeners) {
- listeners_->AddListener(EventListener::ForExtension(
- kEvent1Name, kExt1Id, nullptr, CreateHostSuffixFilter("google.com")));
- listeners_->AddListener(EventListener::ForExtension(
- kEvent1Name, kExt1Id, nullptr, CreateHostSuffixFilter("yahoo.com")));
+TEST_P(EventListenerMapWithContextTest,
+ FilteredEventsOnlyGoToMatchingListeners) {
+ const bool is_for_service_worker = GetParam();
+ struct TestCase {
+ const std::string filter_host_suffix;
+ const std::string url_of_event;
+ } kTestCases[] = {
+ {"google.com", "http://www.google.com"},
+ {"yahoo.com", "http://www.yahoo.com"},
+ };
+ for (const TestCase& test_case : kTestCases) {
+ listeners_->AddListener(
+ CreateLazyListener(kEvent1Name, kExt1Id,
+ CreateHostSuffixFilter(test_case.filter_host_suffix),
+ is_for_service_worker));
+ }
- std::unique_ptr<Event> event(CreateNamedEvent(kEvent1Name));
- event->filter_info.url = GURL("http://www.google.com");
- std::set<const EventListener*> targets(listeners_->GetEventListeners(*event));
- ASSERT_EQ(1u, targets.size());
+ // Matching filters.
+ for (const TestCase& test_case : kTestCases) {
+ SCOPED_TRACE(base::StringPrintf("host_suffix = %s, url = %s",
+ test_case.filter_host_suffix.c_str(),
+ test_case.url_of_event.c_str()));
+ std::unique_ptr<Event> event(
+ CreateEvent(kEvent1Name, GURL(test_case.url_of_event)));
+ std::set<const EventListener*> targets(
+ listeners_->GetEventListeners(*event));
+ ASSERT_EQ(1u, targets.size());
+ EXPECT_TRUE(
+ CreateLazyListener(kEvent1Name, kExt1Id,
+ CreateHostSuffixFilter(test_case.filter_host_suffix),
+ is_for_service_worker)
+ ->Equals(*targets.begin()));
+ }
+
+ // Non-matching filter.
+ {
+ std::unique_ptr<Event> event(
+ CreateEvent(kEvent1Name, GURL("http://does_not_match.com")));
+ std::set<const EventListener*> targets(
+ listeners_->GetEventListeners(*event));
+ EXPECT_TRUE(targets.empty());
+ }
}
TEST_F(EventListenerMapTest, LazyAndUnlazyListenersGetReturned) {
@@ -198,6 +290,11 @@ TEST_F(EventListenerMapTest, TestRemovingByProcessForURL) {
base::BindRepeating(&CreateEventListenerForURL, GURL(kURL)));
}
+TEST_F(EventListenerMapTest, TestRemovingByProcessForExtensionServiceWorker) {
+ TestRemovingByProcess(base::BindRepeating(
+ &CreateEventListenerForExtensionServiceWorker, kExt1Id));
+}
+
void EventListenerMapTest::TestRemovingByListener(
const EventListenerConstructor& constructor) {
listeners_->AddListener(constructor.Run(
@@ -225,14 +322,23 @@ TEST_F(EventListenerMapTest, TestRemovingByListenerForURL) {
base::BindRepeating(&CreateEventListenerForURL, GURL(kURL)));
}
-TEST_F(EventListenerMapTest, TestLazyDoubleAddIsUndoneByRemove) {
- listeners_->AddListener(EventListener::ForExtension(
- kEvent1Name, kExt1Id, nullptr, CreateHostSuffixFilter("google.com")));
- listeners_->AddListener(EventListener::ForExtension(
- kEvent1Name, kExt1Id, nullptr, CreateHostSuffixFilter("google.com")));
+TEST_F(EventListenerMapTest, TestRemovingByListenerForExtensionServiceWorker) {
+ TestRemovingByListener(base::BindRepeating(
+ &CreateEventListenerForExtensionServiceWorker, kExt1Id));
+}
- std::unique_ptr<EventListener> listener(EventListener::ForExtension(
- kEvent1Name, kExt1Id, nullptr, CreateHostSuffixFilter("google.com")));
+TEST_P(EventListenerMapWithContextTest, TestLazyDoubleAddIsUndoneByRemove) {
+ const bool is_for_service_worker = GetParam();
+ listeners_->AddListener(CreateLazyListener(
+ kEvent1Name, kExt1Id, CreateHostSuffixFilter("google.com"),
+ is_for_service_worker));
+ listeners_->AddListener(CreateLazyListener(
+ kEvent1Name, kExt1Id, CreateHostSuffixFilter("google.com"),
+ is_for_service_worker));
+
+ std::unique_ptr<EventListener> listener = CreateLazyListener(
+ kEvent1Name, kExt1Id, CreateHostSuffixFilter("google.com"),
+ is_for_service_worker);
listeners_->RemoveListener(listener.get());
std::unique_ptr<Event> event(CreateNamedEvent(kEvent1Name));
@@ -250,10 +356,14 @@ TEST_F(EventListenerMapTest, HostSuffixFilterEquality) {
}
TEST_F(EventListenerMapTest, RemoveListenersForExtension) {
- listeners_->AddListener(EventListener::ForExtension(
- kEvent1Name, kExt1Id, nullptr, CreateHostSuffixFilter("google.com")));
- listeners_->AddListener(EventListener::ForExtension(
- kEvent2Name, kExt1Id, nullptr, CreateHostSuffixFilter("google.com")));
+ for (bool is_for_service_worker : {false, true}) {
+ listeners_->AddListener(CreateLazyListener(
+ kEvent1Name, kExt1Id, CreateHostSuffixFilter("google.com"),
+ is_for_service_worker));
+ listeners_->AddListener(CreateLazyListener(
+ kEvent2Name, kExt1Id, CreateHostSuffixFilter("google.com"),
+ is_for_service_worker));
+ }
listeners_->RemoveListenersForExtension(kExt1Id);
@@ -269,11 +379,15 @@ TEST_F(EventListenerMapTest, RemoveListenersForExtension) {
ASSERT_EQ(0u, targets.size());
}
-TEST_F(EventListenerMapTest, AddExistingFilteredListener) {
- bool first_new = listeners_->AddListener(EventListener::ForExtension(
- kEvent1Name, kExt1Id, nullptr, CreateHostSuffixFilter("google.com")));
- bool second_new = listeners_->AddListener(EventListener::ForExtension(
- kEvent1Name, kExt1Id, nullptr, CreateHostSuffixFilter("google.com")));
+TEST_P(EventListenerMapWithContextTest, AddExistingFilteredListener) {
+ const bool is_for_service_worker = GetParam();
+
+ bool first_new = listeners_->AddListener(CreateLazyListener(
+ kEvent1Name, kExt1Id, CreateHostSuffixFilter("google.com"),
+ is_for_service_worker));
+ bool second_new = listeners_->AddListener(CreateLazyListener(
+ kEvent1Name, kExt1Id, CreateHostSuffixFilter("google.com"),
+ is_for_service_worker));
ASSERT_TRUE(first_new);
ASSERT_FALSE(second_new);
@@ -307,11 +421,20 @@ TEST_F(EventListenerMapTest, AddExistingUnfilteredListenerForURLs) {
base::BindRepeating(&CreateEventListenerForURL, GURL(kURL)));
}
+TEST_F(EventListenerMapTest,
+ AddExistingUnfilteredListenerForExtensionServiceWorker) {
+ TestAddExistingUnfilteredListener(base::BindRepeating(
+ &CreateEventListenerForExtensionServiceWorker, kExt1Id));
+}
+
TEST_F(EventListenerMapTest, RemovingRouters) {
listeners_->AddListener(EventListener::ForExtension(
kEvent1Name, kExt1Id, process_, std::unique_ptr<DictionaryValue>()));
listeners_->AddListener(EventListener::ForURL(
kEvent1Name, GURL(kURL), process_, std::unique_ptr<DictionaryValue>()));
+ listeners_->AddListener(CreateEventListenerForExtensionServiceWorker(
+ kExt1Id, kEvent1Name, process_,
+ std::unique_ptr<base::DictionaryValue>()));
listeners_->RemoveListenersForProcess(process_);
ASSERT_FALSE(listeners_->HasListenerForEvent(kEvent1Name));
}
@@ -339,41 +462,86 @@ TEST_F(EventListenerMapTest, HasListenerForEventForURL) {
base::BindRepeating(&CreateEventListenerForURL, GURL(kURL)));
}
+TEST_F(EventListenerMapTest, HasListenerForEventForExtensionServiceWorker) {
+ TestHasListenerForEvent(base::BindRepeating(
+ &CreateEventListenerForExtensionServiceWorker, kExt1Id));
+}
+
TEST_F(EventListenerMapTest, HasListenerForExtension) {
ASSERT_FALSE(listeners_->HasListenerForExtension(kExt1Id, kEvent1Name));
- // Non-lazy listener.
- listeners_->AddListener(EventListener::ForExtension(
- kEvent1Name, kExt1Id, process_, std::unique_ptr<DictionaryValue>()));
- // Lazy listener.
- listeners_->AddListener(EventListener::ForExtension(
- kEvent1Name, kExt1Id, nullptr, std::unique_ptr<DictionaryValue>()));
-
- ASSERT_FALSE(listeners_->HasListenerForExtension(kExt1Id, kEvent2Name));
- ASSERT_TRUE(listeners_->HasListenerForExtension(kExt1Id, kEvent1Name));
- ASSERT_FALSE(listeners_->HasListenerForExtension(kExt2Id, kEvent1Name));
- listeners_->RemoveListenersForProcess(process_);
- ASSERT_TRUE(listeners_->HasListenerForExtension(kExt1Id, kEvent1Name));
- listeners_->RemoveListenersForExtension(kExt1Id);
- ASSERT_FALSE(listeners_->HasListenerForExtension(kExt1Id, kEvent1Name));
+ auto create_event_listener = [&](bool is_for_service_worker, bool lazy) {
+ auto filter = std::unique_ptr<base::DictionaryValue>();
+ if (is_for_service_worker) {
+ return EventListener::ForExtensionServiceWorker(
+ kEvent1Name, kExt1Id, lazy ? nullptr : process_,
+ Extension::GetBaseURLFromExtensionId(kExt1Id),
+ GetWorkerVersionId(lazy), GetWorkerThreadId(lazy), std::move(filter));
+ }
+ return EventListener::ForExtension(
+ kEvent1Name, kExt1Id, lazy ? nullptr : process_, std::move(filter));
+ };
+
+ for (bool is_for_service_worker : {false, true}) {
+ // Non-lazy listener.
+ listeners_->AddListener(
+ create_event_listener(is_for_service_worker, false));
+ // Lazy listener.
+ listeners_->AddListener(create_event_listener(is_for_service_worker, true));
+
+ ASSERT_FALSE(listeners_->HasListenerForExtension(kExt1Id, kEvent2Name));
+ ASSERT_TRUE(listeners_->HasListenerForExtension(kExt1Id, kEvent1Name));
+ ASSERT_FALSE(listeners_->HasListenerForExtension(kExt2Id, kEvent1Name));
+ listeners_->RemoveListenersForProcess(process_);
+ ASSERT_TRUE(listeners_->HasListenerForExtension(kExt1Id, kEvent1Name));
+ listeners_->RemoveListenersForExtension(kExt1Id);
+ ASSERT_FALSE(listeners_->HasListenerForExtension(kExt1Id, kEvent1Name));
+ }
}
-TEST_F(EventListenerMapTest, AddLazyListenersFromPreferences) {
+TEST_P(EventListenerMapWithContextTest, AddLazyListenersFromPreferences) {
+ const bool is_for_service_worker = GetParam();
+ struct TestCase {
+ const std::string filter_host_suffix;
+ const std::string url_of_event;
+ } kTestCases[] = {
+ {"google.com", "http://www.google.com"},
+ {"yahoo.com", "http://www.yahoo.com"},
+ };
auto filter_list = std::make_unique<ListValue>();
- filter_list->Append(CreateHostSuffixFilter("google.com"));
- filter_list->Append(CreateHostSuffixFilter("yahoo.com"));
+ for (const TestCase& test_case : kTestCases)
+ filter_list->Append(CreateHostSuffixFilter(test_case.filter_host_suffix));
DictionaryValue filtered_listeners;
filtered_listeners.Set(kEvent1Name, std::move(filter_list));
- listeners_->LoadFilteredLazyListeners(kExt1Id, false, filtered_listeners);
+ listeners_->LoadFilteredLazyListeners(kExt1Id, is_for_service_worker,
+ filtered_listeners);
+
+ // Matching filters.
+ for (const TestCase& test_case : kTestCases) {
+ SCOPED_TRACE(base::StringPrintf("host_suffix = %s, url = %s",
+ test_case.filter_host_suffix.c_str(),
+ test_case.url_of_event.c_str()));
+ std::unique_ptr<Event> event(
+ CreateEvent(kEvent1Name, GURL(test_case.url_of_event)));
+ std::set<const EventListener*> targets(
+ listeners_->GetEventListeners(*event));
+ ASSERT_EQ(1u, targets.size());
+ EXPECT_TRUE(
+ CreateLazyListener(kEvent1Name, kExt1Id,
+ CreateHostSuffixFilter(test_case.filter_host_suffix),
+ is_for_service_worker)
+ ->Equals(*targets.begin()));
+ }
- std::unique_ptr<Event> event(
- CreateEvent(kEvent1Name, GURL("http://www.google.com")));
- std::set<const EventListener*> targets(listeners_->GetEventListeners(*event));
- ASSERT_EQ(1u, targets.size());
- std::unique_ptr<EventListener> listener(EventListener::ForExtension(
- kEvent1Name, kExt1Id, nullptr, CreateHostSuffixFilter("google.com")));
- ASSERT_TRUE((*targets.begin())->Equals(listener.get()));
+ // Non-matching filter.
+ {
+ std::unique_ptr<Event> event(
+ CreateEvent(kEvent1Name, GURL("http://does_not_match.com")));
+ std::set<const EventListener*> targets(
+ listeners_->GetEventListeners(*event));
+ EXPECT_EQ(0u, targets.size());
+ }
}
TEST_F(EventListenerMapTest, CorruptedExtensionPrefsShouldntCrash) {
@@ -382,6 +550,7 @@ TEST_F(EventListenerMapTest, CorruptedExtensionPrefsShouldntCrash) {
filtered_listeners.Set(kEvent1Name, CreateHostSuffixFilter("google.com"));
listeners_->LoadFilteredLazyListeners(kExt1Id, false, filtered_listeners);
+ listeners_->LoadFilteredLazyListeners(kExt1Id, true, filtered_listeners);
std::unique_ptr<Event> event(
CreateEvent(kEvent1Name, GURL("http://www.google.com")));
@@ -389,6 +558,13 @@ TEST_F(EventListenerMapTest, CorruptedExtensionPrefsShouldntCrash) {
ASSERT_EQ(0u, targets.size());
}
+INSTANTIATE_TEST_SUITE_P(NonServiceWorker,
+ EventListenerMapWithContextTest,
+ testing::Values(false));
+INSTANTIATE_TEST_SUITE_P(ServiceWorker,
+ EventListenerMapWithContextTest,
+ testing::Values(true));
+
} // namespace
} // namespace extensions
diff --git a/chromium/extensions/browser/event_router_unittest.cc b/chromium/extensions/browser/event_router_unittest.cc
index cea182cba67..54bf7ccc34e 100644
--- a/chromium/extensions/browser/event_router_unittest.cc
+++ b/chromium/extensions/browser/event_router_unittest.cc
@@ -91,6 +91,19 @@ std::unique_ptr<EventListener> CreateEventListenerForURL(
std::move(filter));
}
+std::unique_ptr<EventListener> CreateEventListenerForExtensionServiceWorker(
+ const std::string& extension_id,
+ int64_t service_worker_version_id,
+ int worker_thread_id,
+ const std::string& event_name,
+ content::RenderProcessHost* process,
+ std::unique_ptr<base::DictionaryValue> filter) {
+ return EventListener::ForExtensionServiceWorker(
+ event_name, extension_id, process,
+ Extension::GetBaseURLFromExtensionId(extension_id),
+ service_worker_version_id, worker_thread_id, std::move(filter));
+}
+
// Creates an extension. If |component| is true, it is created as a component
// extension. If |persistent| is true, it is created with a persistent
// background page; otherwise it is created with an event page.
@@ -174,7 +187,8 @@ class EventRouterTest : public ExtensionsTest {
DISALLOW_COPY_AND_ASSIGN(EventRouterTest);
};
-class EventRouterFilterTest : public ExtensionsTest {
+class EventRouterFilterTest : public ExtensionsTest,
+ public testing::WithParamInterface<bool> {
public:
EventRouterFilterTest() {}
@@ -198,7 +212,9 @@ class EventRouterFilterTest : public ExtensionsTest {
const DictionaryValue* GetFilteredEvents(const std::string& extension_id) {
return event_router()->GetFilteredEvents(
- extension_id, EventRouter::RegisteredEventType::kLazy);
+ extension_id, is_for_service_worker()
+ ? EventRouter::RegisteredEventType::kServiceWorker
+ : EventRouter::RegisteredEventType::kLazy);
}
bool ContainsFilter(const std::string& extension_id,
@@ -222,6 +238,8 @@ class EventRouterFilterTest : public ExtensionsTest {
return false;
}
+ bool is_for_service_worker() const { return GetParam(); }
+
private:
const ListValue* GetFilterList(const std::string& extension_id,
const std::string& event_name) {
@@ -314,6 +332,13 @@ TEST_F(EventRouterTest, EventRouterObserverForURLs) {
&CreateEventListenerForURL, GURL("http://google.com/path")));
}
+TEST_F(EventRouterTest, EventRouterObserverForServiceWorkers) {
+ RunEventRouterObserverTest(base::BindRepeating(
+ &CreateEventListenerForExtensionServiceWorker, "extension_id",
+ // Dummy version_id and thread_id.
+ 99, 199));
+}
+
TEST_F(EventRouterTest, TestReportEvent) {
EventRouter router(browser_context(), nullptr);
scoped_refptr<const Extension> normal = ExtensionBuilder("Test").Build();
@@ -353,19 +378,29 @@ TEST_F(EventRouterTest, TestReportEvent) {
}
// Tests adding and removing events with filters.
-TEST_F(EventRouterFilterTest, Basic) {
+TEST_P(EventRouterFilterTest, Basic) {
// For the purpose of this test, "." is important in |event_name| as it
// exercises the code path that uses |event_name| as a key in DictionaryValue.
const std::string kEventName = "webNavigation.onBeforeNavigate";
const std::string kExtensionId = "mbflcebpggnecokmikipoihdbecnjfoj";
const std::string kHostSuffixes[] = {"foo.com", "bar.com", "baz.com"};
+
+ base::Optional<ServiceWorkerIdentifier> worker_identifier = base::nullopt;
+ if (is_for_service_worker()) {
+ ServiceWorkerIdentifier identifier;
+ identifier.scope = Extension::GetBaseURLFromExtensionId(kExtensionId);
+ identifier.version_id = 99; // Dummy version_id.
+ identifier.thread_id = 199; // Dummy thread_id.
+ worker_identifier =
+ base::make_optional<ServiceWorkerIdentifier>(std::move(identifier));
+ }
std::vector<std::unique_ptr<DictionaryValue>> filters;
for (size_t i = 0; i < base::size(kHostSuffixes); ++i) {
std::unique_ptr<base::DictionaryValue> filter =
CreateHostSuffixFilter(kHostSuffixes[i]);
event_router()->AddFilteredEventListener(kEventName, render_process_host(),
- kExtensionId, base::nullopt,
+ kExtensionId, worker_identifier,
*filter, true);
filters.push_back(std::move(filter));
}
@@ -388,7 +423,7 @@ TEST_F(EventRouterFilterTest, Basic) {
// Remove the second filter.
event_router()->RemoveFilteredEventListener(kEventName, render_process_host(),
- kExtensionId, base::nullopt,
+ kExtensionId, worker_identifier,
*filters[1], true);
ASSERT_TRUE(ContainsFilter(kExtensionId, kEventName, *filters[0]));
ASSERT_FALSE(ContainsFilter(kExtensionId, kEventName, *filters[1]));
@@ -396,7 +431,7 @@ TEST_F(EventRouterFilterTest, Basic) {
// Remove the first filter.
event_router()->RemoveFilteredEventListener(kEventName, render_process_host(),
- kExtensionId, base::nullopt,
+ kExtensionId, worker_identifier,
*filters[0], true);
ASSERT_FALSE(ContainsFilter(kExtensionId, kEventName, *filters[0]));
ASSERT_FALSE(ContainsFilter(kExtensionId, kEventName, *filters[1]));
@@ -404,11 +439,16 @@ TEST_F(EventRouterFilterTest, Basic) {
// Remove the third filter.
event_router()->RemoveFilteredEventListener(kEventName, render_process_host(),
- kExtensionId, base::nullopt,
+ kExtensionId, worker_identifier,
*filters[2], true);
ASSERT_FALSE(ContainsFilter(kExtensionId, kEventName, *filters[0]));
ASSERT_FALSE(ContainsFilter(kExtensionId, kEventName, *filters[1]));
ASSERT_FALSE(ContainsFilter(kExtensionId, kEventName, *filters[2]));
}
+INSTANTIATE_TEST_SUITE_P(Lazy, EventRouterFilterTest, testing::Values(false));
+INSTANTIATE_TEST_SUITE_P(ServiceWorker,
+ EventRouterFilterTest,
+ testing::Values(true));
+
} // namespace extensions
diff --git a/chromium/extensions/browser/events/event_ack_data.cc b/chromium/extensions/browser/events/event_ack_data.cc
index 0861a854108..6647bdf4236 100644
--- a/chromium/extensions/browser/events/event_ack_data.cc
+++ b/chromium/extensions/browser/events/event_ack_data.cc
@@ -10,7 +10,6 @@
#include "base/bind.h"
#include "base/callback.h"
#include "base/guid.h"
-#include "base/task/post_task.h"
#include "content/public/browser/browser_task_traits.h"
#include "content/public/browser/browser_thread.h"
#include "content/public/browser/service_worker_context.h"
@@ -123,8 +122,7 @@ void EventAckData::IncrementInflightEvent(
event_id, unacked_events_);
} else {
content::ServiceWorkerContext::RunTask(
- base::CreateSingleThreadTaskRunner({content::BrowserThread::IO}),
- FROM_HERE, context,
+ content::GetIOThreadTaskRunner({}), FROM_HERE, context,
base::BindOnce(&EventAckData::StartExternalRequestOnCoreThread, context,
render_process_id, version_id, event_id,
unacked_events_));
@@ -146,8 +144,7 @@ void EventAckData::DecrementInflightEvent(
std::move(failure_callback));
} else {
content::ServiceWorkerContext::RunTask(
- base::CreateSingleThreadTaskRunner({content::BrowserThread::IO}),
- FROM_HERE, context,
+ content::GetIOThreadTaskRunner({}), FROM_HERE, context,
base::BindOnce(&EventAckData::FinishExternalRequestOnCoreThread,
context, render_process_id, version_id, event_id,
worker_stopped, unacked_events_,
diff --git a/chromium/extensions/browser/extension_action.cc b/chromium/extensions/browser/extension_action.cc
index 7d79f0fd3ff..c196a478b43 100644
--- a/chromium/extensions/browser/extension_action.cc
+++ b/chromium/extensions/browser/extension_action.cc
@@ -117,7 +117,7 @@ void ExtensionAction::SetIcon(int tab_id, const gfx::Image& image) {
SetValue(&icon_, tab_id, image);
}
-bool ExtensionAction::ParseIconFromCanvasDictionary(
+ExtensionAction::IconParseResult ExtensionAction::ParseIconFromCanvasDictionary(
const base::DictionaryValue& dict,
gfx::ImageSkia* icon) {
for (base::DictionaryValue::Iterator iter(dict); !iter.IsAtEnd();
@@ -131,7 +131,7 @@ bool ExtensionAction::ParseIconFromCanvasDictionary(
} else if (iter.value().GetAsString(&binary_string64)) {
std::string binary_string;
if (!base::Base64Decode(binary_string64, &binary_string))
- return false;
+ return IconParseResult::kDecodeFailure;
pickle = IPC::Message(binary_string.c_str(), binary_string.length());
} else {
continue;
@@ -139,7 +139,7 @@ bool ExtensionAction::ParseIconFromCanvasDictionary(
base::PickleIterator pickle_iter(pickle);
SkBitmap bitmap;
if (!IPC::ReadParam(&pickle, &pickle_iter, &bitmap))
- return false;
+ return IconParseResult::kUnpickleFailure;
CHECK(!bitmap.isNull());
// Chrome helpfully scales the provided icon(s), but let's not go overboard.
@@ -150,7 +150,7 @@ bool ExtensionAction::ParseIconFromCanvasDictionary(
float scale = static_cast<float>(bitmap.width()) / ActionIconSize();
icon->AddRepresentation(gfx::ImageSkiaRep(bitmap, scale));
}
- return true;
+ return IconParseResult::kSuccess;
}
gfx::Image ExtensionAction::GetExplicitlySetIcon(int tab_id) const {
diff --git a/chromium/extensions/browser/extension_action.h b/chromium/extensions/browser/extension_action.h
index c17ba49b897..646c00dfd31 100644
--- a/chromium/extensions/browser/extension_action.h
+++ b/chromium/extensions/browser/extension_action.h
@@ -42,6 +42,12 @@ class ExtensionAction {
// the UI.
};
+ enum class IconParseResult {
+ kSuccess,
+ kDecodeFailure,
+ kUnpickleFailure,
+ };
+
static extension_misc::ExtensionIcons ActionIconSize();
// Returns the default icon to use when no other is available (the puzzle
@@ -95,9 +101,10 @@ class ExtensionAction {
void SetIcon(int tab_id, const gfx::Image& image);
// Tries to parse |*icon| from a dictionary {"19": imageData19, "38":
- // imageData38}, returning false if a value is corrupt.
- static bool ParseIconFromCanvasDictionary(const base::DictionaryValue& dict,
- gfx::ImageSkia* icon);
+ // imageData38}, and returns the result of the parsing attempt.
+ static IconParseResult ParseIconFromCanvasDictionary(
+ const base::DictionaryValue& dict,
+ gfx::ImageSkia* icon);
// Gets the icon that has been set using |SetIcon| for the tab.
gfx::Image GetExplicitlySetIcon(int tab_id) const;
diff --git a/chromium/extensions/browser/extension_event_histogram_value.h b/chromium/extensions/browser/extension_event_histogram_value.h
index 85e848099cf..1e932c91cb5 100644
--- a/chromium/extensions/browser/extension_event_histogram_value.h
+++ b/chromium/extensions/browser/extension_event_histogram_value.h
@@ -78,9 +78,9 @@ enum HistogramValue {
BRAILLE_DISPLAY_PRIVATE_ON_DISPLAY_STATE_CHANGED = 57,
BRAILLE_DISPLAY_PRIVATE_ON_KEY_EVENT = 58,
BROWSER_ACTION_ON_CLICKED = 59,
- CAST_STREAMING_RTP_STREAM_ON_ERROR = 60,
- CAST_STREAMING_RTP_STREAM_ON_STARTED = 61,
- CAST_STREAMING_RTP_STREAM_ON_STOPPED = 62,
+ DELETED_CAST_STREAMING_RTP_STREAM_ON_ERROR = 60,
+ DELETED_CAST_STREAMING_RTP_STREAM_ON_STARTED = 61,
+ DELETED_CAST_STREAMING_RTP_STREAM_ON_STOPPED = 62,
COMMANDS_ON_COMMAND = 63,
CONTEXT_MENUS_INTERNAL_ON_CLICKED = 64,
CONTEXT_MENUS_ON_CLICKED = 65,
@@ -475,6 +475,8 @@ enum HistogramValue {
PASSWORDS_PRIVATE_ON_COMPROMISED_CREDENTIALS_INFO_CHANGED = 453,
TERMINAL_PRIVATE_ON_A11Y_STATUS_CHANGED = 454,
PASSWORDS_PRIVATE_ON_PASSWORD_CHECK_STATUS_CHANGED = 455,
+ INPUT_IME_ON_ASSISTIVE_WINDOW_BUTTON_CLICKED = 456,
+ INPUT_IME_ON_SUGGESTIONS_CHANGED = 457,
// Last entry: Add new entries above, then run:
// python tools/metrics/histograms/update_extension_histograms.py
ENUM_BOUNDARY
diff --git a/chromium/extensions/browser/extension_function.cc b/chromium/extensions/browser/extension_function.cc
index d77b5be02c8..42b36d79a71 100644
--- a/chromium/extensions/browser/extension_function.cc
+++ b/chromium/extensions/browser/extension_function.cc
@@ -617,6 +617,10 @@ bool ExtensionFunction::HasOptionalArgument(size_t index) {
void ExtensionFunction::WriteToConsole(blink::mojom::ConsoleMessageLevel level,
const std::string& message) {
+ // TODO(crbug.com/1096166): Service Worker-based extensions don't have a
+ // RenderFrameHost.
+ if (!render_frame_host_)
+ return;
// Only the main frame handles dev tools messages.
WebContents::FromRenderFrameHost(render_frame_host_)
->GetMainFrame()
diff --git a/chromium/extensions/browser/extension_function_histogram_value.h b/chromium/extensions/browser/extension_function_histogram_value.h
index ba368bfea56..c6aab73e37a 100644
--- a/chromium/extensions/browser/extension_function_histogram_value.h
+++ b/chromium/extensions/browser/extension_function_histogram_value.h
@@ -1364,7 +1364,7 @@ enum HistogramValue {
AUTOTESTPRIVATE_GETARCPACKAGE = 1301,
AUTOTESTPRIVATE_LAUNCHARCAPP = 1302,
AUTOTESTPRIVATE_CLOSEAPP = 1303,
- ACCESSIBILITY_PRIVATE_SETSWITCHACCESSMENUSTATE = 1304,
+ DELETED_ACCESSIBILITY_PRIVATE_SETSWITCHACCESSMENUSTATE = 1304,
AUTOTESTPRIVATE_SENDASSISTANTTEXTQUERY = 1305,
AUTOTESTPRIVATE_SETCROSTINIAPPSCALED = 1306,
ACTIVITYLOGPRIVATE_DELETEACTIVITIESBYEXTENSION = 1307,
@@ -1534,6 +1534,17 @@ enum HistogramValue {
DECLARATIVENETREQUEST_UPDATEENABLEDRULESETS = 1471,
DECLARATIVENETREQUEST_GETENABLEDRULESETS = 1472,
TERMINALPRIVATE_OPENWINDOW = 1473,
+ AUTOTESTPRIVATE_SETPLUGINVMPOLICY = 1474,
+ AUTOTESTPRIVATE_SHOWPLUGINVMINSTALLER = 1475,
+ PASSWORDSPRIVATE_REMOVESAVEDPASSWORDS = 1476,
+ PASSWORDSPRIVATE_REMOVEPASSWORDEXCEPTIONS = 1477,
+ AUTOTESTPRIVATE_WAITFORAMBIENTPHOTOANIMATION = 1478,
+ INPUT_IME_SETASSISTIVEWINDOWPROPERTIES = 1479,
+ PASSWORDSPRIVATE_MOVEPASSWORDTOACCOUNT = 1480,
+ AUTOTESTPRIVATE_DISABLESWITCHACCESSDIALOG = 1481,
+ ENTERPRISE_NETWORKINGATTRIBUTES_GETNETWORKDETAILS = 1482,
+ INPUTMETHODPRIVATE_SETAUTOCORRECTRANGE = 1483,
+ PLATFORMKEYSINTERNAL_GETPUBLICKEYBYSPKI = 1484,
// Last entry: Add new entries above, then run:
// python tools/metrics/histograms/update_extension_histograms.py
ENUM_BOUNDARY
diff --git a/chromium/extensions/browser/extension_host.h b/chromium/extensions/browser/extension_host.h
index 3b4afb96942..ee031971ea4 100644
--- a/chromium/extensions/browser/extension_host.h
+++ b/chromium/extensions/browser/extension_host.h
@@ -11,7 +11,6 @@
#include <string>
#include <unordered_map>
-#include "base/logging.h"
#include "base/macros.h"
#include "base/observer_list.h"
#include "base/timer/elapsed_timer.h"
diff --git a/chromium/extensions/browser/extension_host_observer.h b/chromium/extensions/browser/extension_host_observer.h
index 5bad883494c..b5357b5df9e 100644
--- a/chromium/extensions/browser/extension_host_observer.h
+++ b/chromium/extensions/browser/extension_host_observer.h
@@ -21,7 +21,7 @@ class ExtensionHostObserver {
// ExtensionHost it's given.
// Called when an ExtensionHost is destroyed.
- virtual void OnExtensionHostDestroyed(const ExtensionHost* host) {}
+ virtual void OnExtensionHostDestroyed(ExtensionHost* host) {}
// Called when the ExtensionHost has finished the first load.
virtual void OnExtensionHostDidStopFirstLoad(const ExtensionHost* host) {}
diff --git a/chromium/extensions/browser/extension_icon_image.cc b/chromium/extensions/browser/extension_icon_image.cc
index 34c4df9ef38..bcf238ec2e4 100644
--- a/chromium/extensions/browser/extension_icon_image.cc
+++ b/chromium/extensions/browser/extension_icon_image.cc
@@ -87,8 +87,8 @@ class IconImage::Source : public gfx::ImageSkiaSource {
// gfx::ImageSkiaSource overrides:
gfx::ImageSkiaRep GetImageForScale(float scale) override;
- // Used to load images, possibly asynchronously. NULLed out when the IconImage
- // is destroyed.
+ // Used to load images, possibly asynchronously. nullptr'ed out when the
+ // IconImage is destroyed.
IconImage* host_;
// Image whose representations will be used until |host_| loads the real
@@ -107,7 +107,7 @@ IconImage::Source::~Source() {
}
void IconImage::Source::ResetHost() {
- host_ = NULL;
+ host_ = nullptr;
}
gfx::ImageSkiaRep IconImage::Source::GetImageForScale(float scale) {
@@ -132,7 +132,7 @@ IconImage::IconImage(content::BrowserContext* context,
resource_size_in_dip_(resource_size_in_dip),
keep_original_size_(keep_original_size),
did_complete_initial_load_(false),
- source_(NULL),
+ source_(nullptr),
default_icon_(gfx::ImageSkiaOperations::CreateResizedImage(
default_icon,
skia::ImageOperations::RESIZE_BEST,
diff --git a/chromium/extensions/browser/extension_navigation_throttle.cc b/chromium/extensions/browser/extension_navigation_throttle.cc
index 8b046da23ad..40f245e8adf 100644
--- a/chromium/extensions/browser/extension_navigation_throttle.cc
+++ b/chromium/extensions/browser/extension_navigation_throttle.cc
@@ -10,6 +10,7 @@
#include "content/public/browser/browser_thread.h"
#include "content/public/browser/navigation_handle.h"
#include "content/public/browser/render_frame_host.h"
+#include "content/public/browser/storage_partition_config.h"
#include "content/public/browser/web_contents.h"
#include "content/public/common/url_constants.h"
#include "extensions/browser/extension_registry.h"
@@ -107,16 +108,16 @@ ExtensionNavigationThrottle::WillStartOrRedirectRequest() {
const Extension* owner_extension =
registry->enabled_extensions().GetByID(owner_extension_id);
- std::string partition_domain;
- std::string partition_id;
- bool in_memory = false;
+ content::StoragePartitionConfig storage_partition_config =
+ content::StoragePartitionConfig::CreateDefault();
bool is_guest = WebViewGuest::GetGuestPartitionConfigForSite(
navigation_handle()->GetStartingSiteInstance()->GetSiteURL(),
- &partition_domain, &partition_id, &in_memory);
+ &storage_partition_config);
bool allowed = true;
url_request_util::AllowCrossRendererResourceLoadHelper(
- is_guest, target_extension, owner_extension, partition_id, url.path(),
+ is_guest, target_extension, owner_extension,
+ storage_partition_config.partition_name(), url.path(),
navigation_handle()->GetPageTransition(), &allowed);
if (!allowed)
return content::NavigationThrottle::BLOCK_REQUEST;
diff --git a/chromium/extensions/browser/extension_pref_store.cc b/chromium/extensions/browser/extension_pref_store.cc
index 80e7a08b9b9..ff530d3887c 100644
--- a/chromium/extensions/browser/extension_pref_store.cc
+++ b/chromium/extensions/browser/extension_pref_store.cc
@@ -21,10 +21,8 @@ void ExtensionPrefStore::OnInitializationCompleted() {
void ExtensionPrefStore::OnPrefValueChanged(const std::string& key) {
CHECK(extension_pref_value_map_);
- const base::Value *winner =
- extension_pref_value_map_->GetEffectivePrefValue(key,
- incognito_pref_store_,
- NULL);
+ const base::Value* winner = extension_pref_value_map_->GetEffectivePrefValue(
+ key, incognito_pref_store_, nullptr);
if (winner) {
SetValue(key, winner->CreateDeepCopy(),
WriteablePrefStore::DEFAULT_PREF_WRITE_FLAGS);
@@ -36,7 +34,7 @@ void ExtensionPrefStore::OnPrefValueChanged(const std::string& key) {
void ExtensionPrefStore::OnExtensionPrefValueMapDestruction() {
CHECK(extension_pref_value_map_);
extension_pref_value_map_->RemoveObserver(this);
- extension_pref_value_map_ = NULL;
+ extension_pref_value_map_ = nullptr;
}
ExtensionPrefStore::~ExtensionPrefStore() {
diff --git a/chromium/extensions/browser/extension_prefs.cc b/chromium/extensions/browser/extension_prefs.cc
index eac7d0aa27b..3c212c8bde9 100644
--- a/chromium/extensions/browser/extension_prefs.cc
+++ b/chromium/extensions/browser/extension_prefs.cc
@@ -786,10 +786,6 @@ int ExtensionPrefs::GetDisableReasons(const std::string& extension_id) const {
int value = -1;
if (ReadPrefAsInteger(extension_id, kPrefDisableReasons, &value) &&
value >= 0) {
- // TODO(crbug.com/860198): After we've gotten rid of the migration code for
- // DEPRECATED_DISABLE_UNKNOWN_FROM_SYNC, we should maybe filter it out here
- // just to be sure:
- // value = value & ~disable_reason::DEPRECATED_DISABLE_UNKNOWN_FROM_SYNC;
return value;
}
return disable_reason::DISABLE_NONE;
@@ -1966,6 +1962,10 @@ ExtensionPrefs::ExtensionPrefs(
MigrateToNewWithholdingPref();
MigrateToNewExternalUninstallPref();
+
+ MigrateYoutubeOffBookmarkApps();
+
+ MigrateDeprecatedDisableReasons();
}
AppSorting* ExtensionPrefs::app_sorting() const {
@@ -2246,6 +2246,47 @@ void ExtensionPrefs::FinishExtensionInfoPrefs(
observer.OnExtensionRegistered(extension_id, install_time, is_enabled);
}
+void ExtensionPrefs::MigrateDeprecatedDisableReasons() {
+ std::unique_ptr<ExtensionsInfo> extensions_info(GetInstalledExtensionsInfo());
+
+ for (const auto& info : *extensions_info) {
+ const ExtensionId& extension_id = info->extension_id;
+ int disable_reasons = GetDisableReasons(extension_id);
+ if ((disable_reasons &
+ disable_reason::DEPRECATED_DISABLE_UNKNOWN_FROM_SYNC) == 0)
+ continue;
+ disable_reasons &= ~disable_reason::DEPRECATED_DISABLE_UNKNOWN_FROM_SYNC;
+ if (disable_reasons == 0) {
+ // We don't know exactly why the extension was disabled, but we don't
+ // want to just suddenly re-enable it. Default to disabling it by the
+ // user (which was most likely for coming in from sync, and is
+ // reversible).
+ disable_reasons = disable_reason::DISABLE_USER_ACTION;
+ }
+ ReplaceDisableReasons(extension_id, disable_reasons);
+ }
+}
+
+void ExtensionPrefs::MigrateYoutubeOffBookmarkApps() {
+ const base::DictionaryValue* extensions_dictionary =
+ prefs_->GetDictionary(pref_names::kExtensions);
+ DCHECK(extensions_dictionary->is_dict());
+
+ const base::DictionaryValue* youtube_dictionary = nullptr;
+ if (!extensions_dictionary->GetDictionary(extension_misc::kYoutubeAppId,
+ &youtube_dictionary)) {
+ return;
+ }
+ int creation_flags = 0;
+ if (!youtube_dictionary->GetInteger(kPrefCreationFlags, &creation_flags) ||
+ (creation_flags & Extension::FROM_BOOKMARK) == 0) {
+ return;
+ }
+ ScopedExtensionPrefUpdate update(prefs_, extension_misc::kYoutubeAppId);
+ creation_flags &= ~Extension::FROM_BOOKMARK;
+ update->SetInteger(kPrefCreationFlags, creation_flags);
+}
+
void ExtensionPrefs::MigrateObsoleteExtensionPrefs() {
const base::Value* extensions_dictionary =
prefs_->GetDictionary(pref_names::kExtensions);
diff --git a/chromium/extensions/browser/extension_prefs.h b/chromium/extensions/browser/extension_prefs.h
index 139a76a0f44..a85df0eca5b 100644
--- a/chromium/extensions/browser/extension_prefs.h
+++ b/chromium/extensions/browser/extension_prefs.h
@@ -625,6 +625,16 @@ class ExtensionPrefs : public KeyedService {
void SetDNRUseActionCountAsBadgeText(const ExtensionId& extension_id,
bool use_action_count_as_badge_text);
+ // Migrates the disable reasons extension pref for extensions that were
+ // disabled due to a deprecated reason.
+ // TODO(archanasimha): Remove this around M89.
+ void MigrateDeprecatedDisableReasons();
+
+ // Looks to see if the Youtube extension is installed, and removes the
+ // FROM_BOOKMARK flag from it's creation flags.
+ // TODO(dmurph): Remove this in m90.
+ void MigrateYoutubeOffBookmarkApps();
+
// Iterates over the extension pref entries and removes any obsolete keys. We
// need to do this here specially (rather than in
// MigrateObsoleteProfilePrefs()) because these entries are subkeys of the
diff --git a/chromium/extensions/browser/extension_protocols.cc b/chromium/extensions/browser/extension_protocols.cc
index 87082a4fe65..5a7e8ea1b62 100644
--- a/chromium/extensions/browser/extension_protocols.cc
+++ b/chromium/extensions/browser/extension_protocols.cc
@@ -28,12 +28,12 @@
#include "base/metrics/histogram.h"
#include "base/metrics/histogram_functions.h"
#include "base/metrics/histogram_macros.h"
+#include "base/metrics/user_metrics.h"
#include "base/numerics/safe_conversions.h"
#include "base/strings/string_number_conversions.h"
#include "base/strings/string_util.h"
#include "base/strings/stringprintf.h"
#include "base/strings/utf_string_conversions.h"
-#include "base/task/post_task.h"
#include "base/task/thread_pool.h"
#include "base/threading/thread_restrictions.h"
#include "base/timer/elapsed_timer.h"
@@ -57,6 +57,7 @@
#include "extensions/browser/guest_view/web_view/web_view_guest.h"
#include "extensions/browser/guest_view/web_view/web_view_renderer_state.h"
#include "extensions/browser/info_map.h"
+#include "extensions/browser/media_router_extension_access_logger.h"
#include "extensions/browser/url_request_util.h"
#include "extensions/common/constants.h"
#include "extensions/common/extension.h"
@@ -84,6 +85,7 @@
#include "third_party/blink/public/common/features.h"
#include "third_party/blink/public/common/loader/resource_type_util.h"
#include "third_party/blink/public/mojom/loader/resource_load_info.mojom-shared.h"
+#include "url/origin.h"
#include "url/url_util.h"
using content::BrowserContext;
@@ -144,10 +146,8 @@ void ReadResourceFilePathAndLastModifiedTime(
base::TimeDelta::FromDays(30).InSeconds(), 50);
} else {
UMA_HISTOGRAM_CUSTOM_COUNTS("Extensions.ResourceLastModifiedNegativeDelta",
- -delta_seconds,
- 1,
- base::TimeDelta::FromDays(30).InSeconds(),
- 50);
+ -delta_seconds, 1,
+ base::TimeDelta::FromDays(30).InSeconds(), 50);
}
}
@@ -464,6 +464,20 @@ class ExtensionURLLoaderFactory : public network::mojom::URLLoaderFactory {
&send_cors_header, &follow_symlinks_anywhere);
}
+ // If the extension is the Media Router Component Extension used to support
+ // Casting scenarios, log metrics needed to track migration away from this
+ // extension.
+ // TODO(crbug.com/1097594): Remove this metric logging once migration away
+ // from the Media Router Component Extension completes.
+ const MediaRouterExtensionAccessLogger* media_router_access_logger =
+ ExtensionsBrowserClient::Get()->GetMediaRouterAccessLogger();
+ if (media_router_access_logger && request.request_initiator.has_value() &&
+ (extension.get()->id() == extension_misc::kCastExtensionIdRelease ||
+ extension.get()->id() == extension_misc::kCastExtensionIdDev)) {
+ media_router_access_logger->LogMediaRouterComponentExtensionUse(
+ request.request_initiator.value(), browser_context_);
+ }
+
if (IsBackgroundPageURL(request.url)) {
// Handle background page requests immediately with a simple generated
// chunk of HTML.
@@ -584,8 +598,8 @@ class ExtensionURLLoaderFactory : public network::mojom::URLLoaderFactory {
bool send_cors_header) {
request.url = net::FilePathToFileURL(*read_file_path);
- base::PostTask(
- FROM_HERE, {content::BrowserThread::IO},
+ content::GetIOThreadTaskRunner({})->PostTask(
+ FROM_HERE,
base::BindOnce(
&StartVerifyJob, std::move(request), std::move(loader),
std::move(client), std::move(content_verifier), resource,
diff --git a/chromium/extensions/browser/extension_registry.h b/chromium/extensions/browser/extension_registry.h
index 2d2514bc0a9..4ead3937297 100644
--- a/chromium/extensions/browser/extension_registry.h
+++ b/chromium/extensions/browser/extension_registry.h
@@ -33,7 +33,7 @@ class ExtensionRegistryObserver;
enum class UnloadedExtensionReason;
// ExtensionRegistry holds sets of the installed extensions for a given
-// BrowserContext. An incognito browser context and its master browser context
+// BrowserContext. An incognito browser context and its original browser context
// share a single registry.
class ExtensionRegistry : public KeyedService {
public:
diff --git a/chromium/extensions/browser/extension_registry_factory.h b/chromium/extensions/browser/extension_registry_factory.h
index e2fcfe5d862..ec476404dc6 100644
--- a/chromium/extensions/browser/extension_registry_factory.h
+++ b/chromium/extensions/browser/extension_registry_factory.h
@@ -15,7 +15,7 @@ namespace extensions {
class ExtensionRegistry;
// Factory for ExtensionRegistry objects. ExtensionRegistry objects are shared
-// between an incognito browser context and its master browser context.
+// between an incognito browser context and its original browser context.
class ExtensionRegistryFactory : public BrowserContextKeyedServiceFactory {
public:
static ExtensionRegistry* GetForBrowserContext(
diff --git a/chromium/extensions/browser/extension_system.h b/chromium/extensions/browser/extension_system.h
index eb43586b944..c4a604a714e 100644
--- a/chromium/extensions/browser/extension_system.h
+++ b/chromium/extensions/browser/extension_system.h
@@ -40,7 +40,7 @@ class ManagementPolicy;
class QuotaService;
class RuntimeData;
class ServiceWorkerManager;
-class SharedUserScriptMaster;
+class SharedUserScriptManager;
class StateStore;
class ValueStoreFactory;
enum class UnloadedExtensionReason;
@@ -85,8 +85,8 @@ class ExtensionSystem : public KeyedService {
// The ServiceWorkerManager is created at startup.
virtual ServiceWorkerManager* service_worker_manager() = 0;
- // The SharedUserScriptMaster is created at startup.
- virtual SharedUserScriptMaster* shared_user_script_master() = 0;
+ // The SharedUserScriptManager is created at startup.
+ virtual SharedUserScriptManager* shared_user_script_manager() = 0;
// The StateStore is created at startup.
virtual StateStore* state_store() = 0;
@@ -127,6 +127,9 @@ class ExtensionSystem : public KeyedService {
// Signaled when the extension system has completed its startup tasks.
virtual const base::OneShotEvent& ready() const = 0;
+ // Whether the extension system is ready.
+ virtual bool is_ready() const = 0;
+
// Returns the content verifier, if any.
virtual ContentVerifier* content_verifier() = 0;
diff --git a/chromium/extensions/browser/extension_user_script_loader.cc b/chromium/extensions/browser/extension_user_script_loader.cc
index b39d77881ea..bda32210c0d 100644
--- a/chromium/extensions/browser/extension_user_script_loader.cc
+++ b/chromium/extensions/browser/extension_user_script_loader.cc
@@ -19,7 +19,6 @@
#include "base/memory/read_only_shared_memory_region.h"
#include "base/one_shot_event.h"
#include "base/strings/string_util.h"
-#include "base/task/post_task.h"
#include "base/version.h"
#include "content/public/browser/browser_context.h"
#include "content/public/browser/browser_task_traits.h"
@@ -77,8 +76,8 @@ void VerifyContent(const VerifyContentInfo& info) {
void ForwardVerifyContentToIO(const VerifyContentInfo& info) {
DCHECK_CURRENTLY_ON(content::BrowserThread::UI);
- base::PostTask(FROM_HERE, {content::BrowserThread::IO},
- base::BindOnce(&VerifyContent, info));
+ content::GetIOThreadTaskRunner({})->PostTask(
+ FROM_HERE, base::BindOnce(&VerifyContent, info));
}
// Loads user scripts from the extension who owns these scripts.
@@ -115,14 +114,14 @@ bool LoadScriptContent(const HostID& host_id,
// Call VerifyContent() after yielding on UI thread so it is ensured that
// ContentVerifierIOData is populated at the time we call VerifyContent().
// Priority set explicitly to avoid unwanted task priority inheritance.
- base::PostTask(
- FROM_HERE,
- {content::BrowserThread::UI, base::TaskPriority::USER_BLOCKING},
- base::BindOnce(
- &ForwardVerifyContentToIO,
- VerifyContentInfo(verifier, host_id.id(),
- script_file->extension_root(),
- script_file->relative_path(), content)));
+ content::GetUIThreadTaskRunner({base::TaskPriority::USER_BLOCKING})
+ ->PostTask(
+ FROM_HERE,
+ base::BindOnce(
+ &ForwardVerifyContentToIO,
+ VerifyContentInfo(verifier, host_id.id(),
+ script_file->extension_root(),
+ script_file->relative_path(), content)));
}
}
@@ -196,11 +195,10 @@ void LoadScriptsOnFileTaskRunner(
base::ReadOnlySharedMemoryRegion memory =
UserScriptLoader::Serialize(*user_scripts);
// Explicit priority to prevent unwanted task priority inheritance.
- base::PostTask(
- FROM_HERE,
- {content::BrowserThread::UI, base::TaskPriority::USER_BLOCKING},
- base::BindOnce(std::move(callback), std::move(user_scripts),
- std::move(memory)));
+ content::GetUIThreadTaskRunner({base::TaskPriority::USER_BLOCKING})
+ ->PostTask(FROM_HERE,
+ base::BindOnce(std::move(callback), std::move(user_scripts),
+ std::move(memory)));
}
} // namespace
diff --git a/chromium/extensions/browser/extension_user_script_loader.h b/chromium/extensions/browser/extension_user_script_loader.h
index 1c72669f7f7..5e6c570caa3 100644
--- a/chromium/extensions/browser/extension_user_script_loader.h
+++ b/chromium/extensions/browser/extension_user_script_loader.h
@@ -31,8 +31,8 @@ class ExtensionUserScriptLoader : public UserScriptLoader,
};
using HostsInfo = std::map<HostID, PathAndLocaleInfo>;
- // The listen_for_extension_system_loaded is only set true when initilizing
- // the Extension System, e.g, when constructs SharedUserScriptMaster in
+ // The listen_for_extension_system_loaded is only set true when initializing
+ // the Extension System, e.g, when constructs SharedUserScriptManager in
// ExtensionSystemImpl.
ExtensionUserScriptLoader(content::BrowserContext* browser_context,
const HostID& host_id,
diff --git a/chromium/extensions/browser/extension_util.cc b/chromium/extensions/browser/extension_util.cc
index 448496763d8..93c9c913745 100644
--- a/chromium/extensions/browser/extension_util.cc
+++ b/chromium/extensions/browser/extension_util.cc
@@ -20,9 +20,26 @@
#include "extensions/common/manifest_handlers/shared_module_info.h"
#include "extensions/common/permissions/permissions_data.h"
+#if defined(OS_CHROMEOS)
+#include "base/system/sys_info.h"
+#endif
+
namespace extensions {
namespace util {
+namespace {
+
+#if defined(OS_CHROMEOS)
+bool IsSigninProfileTestExtensionOnTestImage(const Extension* extension) {
+ if (extension->id() != extension_misc::kSigninProfileTestExtensionId)
+ return false;
+ base::SysInfo::CrashIfChromeOSNonTestImage();
+ return true;
+}
+#endif
+
+} // namespace
+
bool CanBeIncognitoEnabled(const Extension* extension) {
return IncognitoInfo::IsIncognitoAllowed(extension) &&
(!extension->is_platform_app() ||
@@ -43,6 +60,10 @@ bool IsIncognitoEnabled(const std::string& extension_id,
return true;
if (extension->is_login_screen_extension())
return true;
+#if defined(OS_CHROMEOS)
+ if (IsSigninProfileTestExtensionOnTestImage(extension))
+ return true;
+#endif
}
return ExtensionPrefs::Get(context)->IsIncognitoEnabled(extension_id);
}
diff --git a/chromium/extensions/browser/extensions_browser_client.cc b/chromium/extensions/browser/extensions_browser_client.cc
index f2a503e5d6d..acfe874d74e 100644
--- a/chromium/extensions/browser/extensions_browser_client.cc
+++ b/chromium/extensions/browser/extensions_browser_client.cc
@@ -104,4 +104,18 @@ bool ExtensionsBrowserClient::ShouldForceWebRequestExtraHeaders(
return false;
}
+base::FilePath ExtensionsBrowserClient::GetSaveFilePath(
+ content::BrowserContext* context) {
+ return base::FilePath();
+}
+
+void ExtensionsBrowserClient::SetLastSaveFilePath(
+ content::BrowserContext* context,
+ const base::FilePath& path) {}
+
+const MediaRouterExtensionAccessLogger*
+ExtensionsBrowserClient::GetMediaRouterAccessLogger() const {
+ return nullptr;
+}
+
} // namespace extensions
diff --git a/chromium/extensions/browser/extensions_browser_client.h b/chromium/extensions/browser/extensions_browser_client.h
index e2723b1a42e..757ed5668b9 100644
--- a/chromium/extensions/browser/extensions_browser_client.h
+++ b/chromium/extensions/browser/extensions_browser_client.h
@@ -32,13 +32,13 @@ namespace base {
class CommandLine;
class FilePath;
class ListValue;
-}
+} // namespace base
namespace content {
class BrowserContext;
class RenderFrameHost;
class WebContents;
-}
+} // namespace content
namespace network {
namespace mojom {
@@ -62,6 +62,7 @@ class ExtensionSystem;
class ExtensionSystemProvider;
class ExtensionWebContentsObserver;
class KioskDelegate;
+class MediaRouterExtensionAccessLogger;
class ProcessManagerDelegate;
class ProcessMap;
class RuntimeAPIDelegate;
@@ -348,6 +349,15 @@ class ExtensionsBrowserClient {
virtual bool ShouldForceWebRequestExtraHeaders(
content::BrowserContext* context) const;
+ // Gets and sets the last save (download) path for a given context.
+ virtual base::FilePath GetSaveFilePath(content::BrowserContext* context);
+ virtual void SetLastSaveFilePath(content::BrowserContext* context,
+ const base::FilePath& path);
+
+ // Retrieves the media router access logger for this session.
+ virtual const MediaRouterExtensionAccessLogger* GetMediaRouterAccessLogger()
+ const;
+
private:
std::vector<std::unique_ptr<ExtensionsBrowserAPIProvider>> providers_;
diff --git a/chromium/extensions/browser/guest_view/extensions_guest_view_message_filter.cc b/chromium/extensions/browser/guest_view/extensions_guest_view_message_filter.cc
index e5045479ec4..7c442c9b471 100644
--- a/chromium/extensions/browser/guest_view/extensions_guest_view_message_filter.cc
+++ b/chromium/extensions/browser/guest_view/extensions_guest_view_message_filter.cc
@@ -9,7 +9,6 @@
#include "base/bind.h"
#include "base/guid.h"
#include "base/stl_util.h"
-#include "base/task/post_task.h"
#include "base/time/time.h"
#include "components/guest_view/browser/bad_message.h"
#include "components/guest_view/browser/guest_view_manager.h"
@@ -119,8 +118,8 @@ void ExtensionsGuestViewMessageFilter::CreateMimeHandlerViewGuest(
const gfx::Size& element_size,
mojo::PendingRemote<mime_handler::BeforeUnloadControl>
before_unload_control) {
- base::PostTask(
- FROM_HERE, {content::BrowserThread::UI},
+ content::GetUIThreadTaskRunner({})->PostTask(
+ FROM_HERE,
base::BindOnce(&ExtensionsGuestViewMessageFilter::
CreateMimeHandlerViewGuestOnUIThread,
this, render_frame_id, view_id, element_instance_id,
@@ -131,8 +130,8 @@ void ExtensionsGuestViewMessageFilter::ReadyToCreateMimeHandlerView(
int32_t render_frame_id,
bool success) {
if (!content::BrowserThread::CurrentlyOn(content::BrowserThread::UI)) {
- base::PostTask(
- FROM_HERE, {content::BrowserThread::UI},
+ content::GetUIThreadTaskRunner({})->PostTask(
+ FROM_HERE,
base::BindOnce(
&ExtensionsGuestViewMessageFilter::ReadyToCreateMimeHandlerView,
this, render_frame_id, success));
@@ -205,8 +204,8 @@ void ExtensionsGuestViewMessageFilter::CreateEmbeddedMimeHandlerViewGuest(
const gfx::Size& element_size,
content::mojom::TransferrableURLLoaderPtr transferrable_url_loader) {
if (!content::BrowserThread::CurrentlyOn(content::BrowserThread::UI)) {
- base::PostTask(FROM_HERE, {content::BrowserThread::UI},
- base::BindOnce(&ExtensionsGuestViewMessageFilter::
+ content::GetUIThreadTaskRunner({})->PostTask(
+ FROM_HERE, base::BindOnce(&ExtensionsGuestViewMessageFilter::
CreateEmbeddedMimeHandlerViewGuest,
this, render_frame_id, tab_id, original_url,
element_instance_id, element_size,
diff --git a/chromium/extensions/browser/guest_view/mime_handler_view/mime_handler_view_attach_helper.cc b/chromium/extensions/browser/guest_view/mime_handler_view/mime_handler_view_attach_helper.cc
index eb79c6efff9..2c03600704c 100644
--- a/chromium/extensions/browser/guest_view/mime_handler_view/mime_handler_view_attach_helper.cc
+++ b/chromium/extensions/browser/guest_view/mime_handler_view/mime_handler_view_attach_helper.cc
@@ -8,7 +8,6 @@
#include "base/containers/flat_map.h"
#include "base/memory/ptr_util.h"
#include "base/no_destructor.h"
-#include "base/task/post_task.h"
#include "base/unguessable_token.h"
#include "content/public/browser/browser_task_traits.h"
#include "content/public/browser/browser_thread.h"
@@ -101,8 +100,8 @@ bool MimeHandlerViewAttachHelper::OverrideBodyForInterceptedResponse(
SkColorGetB(color), token.c_str(), mime_type.c_str(), token.c_str());
payload->assign(html_str);
*data_pipe_size = kFullPageMimeHandlerViewDataPipeSize;
- base::PostTaskAndReply(
- FROM_HERE, {BrowserThread::UI},
+ content::GetUIThreadTaskRunner({})->PostTaskAndReply(
+ FROM_HERE,
base::BindOnce(CreateFullPageMimeHandlerView,
navigating_frame_tree_node_id, resource_url, mime_type,
stream_id, token),
diff --git a/chromium/extensions/browser/guest_view/mime_handler_view/mime_handler_view_browsertest.cc b/chromium/extensions/browser/guest_view/mime_handler_view/mime_handler_view_browsertest.cc
index 901ba976b29..0f077fe076e 100644
--- a/chromium/extensions/browser/guest_view/mime_handler_view/mime_handler_view_browsertest.cc
+++ b/chromium/extensions/browser/guest_view/mime_handler_view/mime_handler_view_browsertest.cc
@@ -21,6 +21,7 @@
#include "components/guest_view/browser/test_guest_view_manager.h"
#include "components/javascript_dialogs/app_modal_dialog_controller.h"
#include "components/javascript_dialogs/app_modal_dialog_view.h"
+#include "components/printing/common/print.mojom.h"
#include "components/printing/common/print_messages.h"
#include "content/public/browser/browser_thread.h"
#include "content/public/browser/navigation_handle.h"
@@ -194,7 +195,7 @@ class PrintPreviewWaiter : public content::BrowserMessageFilter {
return false;
}
- void OnDidStartPreview(const PrintHostMsg_DidStartPreview_Params& params,
+ void OnDidStartPreview(const printing::mojom::DidStartPreviewParams& params,
const PrintHostMsg_PreviewIds& ids) {
// Expect that there is at least one page.
did_load_ = true;
diff --git a/chromium/extensions/browser/guest_view/mime_handler_view/mime_handler_view_guest.cc b/chromium/extensions/browser/guest_view/mime_handler_view/mime_handler_view_guest.cc
index e1789871c94..390b07fc577 100644
--- a/chromium/extensions/browser/guest_view/mime_handler_view/mime_handler_view_guest.cc
+++ b/chromium/extensions/browser/guest_view/mime_handler_view/mime_handler_view_guest.cc
@@ -354,22 +354,19 @@ void MimeHandlerViewGuest::OnRenderFrameHostDeleted(int process_id,
}
void MimeHandlerViewGuest::EnterFullscreenModeForTab(
- content::WebContents*,
- const GURL& origin,
+ content::RenderFrameHost* requesting_frame,
const blink::mojom::FullscreenOptions& options) {
if (SetFullscreenState(true)) {
- auto* delegate = embedder_web_contents()->GetDelegate();
- if (delegate) {
- delegate->EnterFullscreenModeForTab(embedder_web_contents(), origin,
- options);
+ if (auto* delegate = embedder_web_contents()->GetDelegate()) {
+ delegate->EnterFullscreenModeForTab(
+ embedder_web_contents()->GetMainFrame(), options);
}
}
}
void MimeHandlerViewGuest::ExitFullscreenModeForTab(content::WebContents*) {
if (SetFullscreenState(false)) {
- auto* delegate = embedder_web_contents()->GetDelegate();
- if (delegate)
+ if (auto* delegate = embedder_web_contents()->GetDelegate())
delegate->ExitFullscreenModeForTab(embedder_web_contents());
}
}
diff --git a/chromium/extensions/browser/guest_view/mime_handler_view/mime_handler_view_guest.h b/chromium/extensions/browser/guest_view/mime_handler_view/mime_handler_view_guest.h
index 242db17f8f3..56babf6fff5 100644
--- a/chromium/extensions/browser/guest_view/mime_handler_view/mime_handler_view_guest.h
+++ b/chromium/extensions/browser/guest_view/mime_handler_view/mime_handler_view_guest.h
@@ -147,8 +147,7 @@ class MimeHandlerViewGuest
bool SaveFrame(const GURL& url, const content::Referrer& referrer) final;
void OnRenderFrameHostDeleted(int process_id, int routing_id) final;
void EnterFullscreenModeForTab(
- content::WebContents* web_contents,
- const GURL& origin,
+ content::RenderFrameHost* requesting_frame,
const blink::mojom::FullscreenOptions& options) override;
void ExitFullscreenModeForTab(content::WebContents*) override;
bool IsFullscreenForTabOrPending(
diff --git a/chromium/extensions/browser/guest_view/mime_handler_view/mime_handler_view_interactive_uitest.cc b/chromium/extensions/browser/guest_view/mime_handler_view/mime_handler_view_interactive_uitest.cc
index a7ecd72b4a8..f6a8fa27565 100644
--- a/chromium/extensions/browser/guest_view/mime_handler_view/mime_handler_view_interactive_uitest.cc
+++ b/chromium/extensions/browser/guest_view/mime_handler_view/mime_handler_view_interactive_uitest.cc
@@ -14,7 +14,7 @@
#include "base/test/test_timeouts.h"
#include "build/build_config.h"
#include "chrome/browser/extensions/extension_apitest.h"
-#include "chrome/browser/ui/exclusive_access/fullscreen_controller_test.h"
+#include "chrome/browser/ui/exclusive_access/exclusive_access_test.h"
#include "chrome/test/base/interactive_test_utils.h"
#include "chrome/test/base/ui_test_utils.h"
#include "components/guest_view/browser/test_guest_view_manager.h"
diff --git a/chromium/extensions/browser/guest_view/mime_handler_view/test_mime_handler_view_guest.cc b/chromium/extensions/browser/guest_view/mime_handler_view/test_mime_handler_view_guest.cc
index 1bff1925b5a..f67c024c166 100644
--- a/chromium/extensions/browser/guest_view/mime_handler_view/test_mime_handler_view_guest.cc
+++ b/chromium/extensions/browser/guest_view/mime_handler_view/test_mime_handler_view_guest.cc
@@ -5,7 +5,6 @@
#include "extensions/browser/guest_view/mime_handler_view/test_mime_handler_view_guest.h"
#include "base/bind.h"
-#include "base/task/post_task.h"
#include "base/time/time.h"
#include "content/public/browser/browser_task_traits.h"
#include "content/public/browser/browser_thread.h"
@@ -45,8 +44,8 @@ void TestMimeHandlerViewGuest::CreateWebContents(
// Delay the creation of the guest's WebContents if |delay_| is set.
if (delay_) {
auto delta = base::TimeDelta::FromMilliseconds(delay_);
- base::PostDelayedTask(
- FROM_HERE, {content::BrowserThread::UI},
+ content::GetUIThreadTaskRunner({})->PostDelayedTask(
+ FROM_HERE,
base::BindOnce(&TestMimeHandlerViewGuest::CallBaseCreateWebContents,
weak_ptr_factory_.GetWeakPtr(),
create_params.CreateDeepCopy(), std::move(callback)),
diff --git a/chromium/extensions/browser/guest_view/web_view/web_view_apitest.cc b/chromium/extensions/browser/guest_view/web_view/web_view_apitest.cc
index 78968aca5bd..54b0a42f03a 100644
--- a/chromium/extensions/browser/guest_view/web_view/web_view_apitest.cc
+++ b/chromium/extensions/browser/guest_view/web_view/web_view_apitest.cc
@@ -483,7 +483,7 @@ IN_PROC_BROWSER_TEST_F(WebViewAPITest, TestContextMenu) {
gfx::Point guest_context_menu_position(5, 5);
gfx::Point root_context_menu_position =
guest_view->TransformPointToRootCoordSpace(guest_context_menu_position);
- content::SimulateRoutedMouseClickAt(
+ content::SimulateMouseClickAt(
root_web_contents, blink::WebInputEvent::kNoModifiers,
blink::WebMouseEvent::Button::kRight, root_context_menu_position);
context_menu_filter->Wait();
diff --git a/chromium/extensions/browser/guest_view/web_view/web_view_content_script_manager.cc b/chromium/extensions/browser/guest_view/web_view/web_view_content_script_manager.cc
index 3844ae9b43c..20c5615c025 100644
--- a/chromium/extensions/browser/guest_view/web_view/web_view_content_script_manager.cc
+++ b/chromium/extensions/browser/guest_view/web_view/web_view_content_script_manager.cc
@@ -14,7 +14,7 @@
#include "content/public/browser/render_frame_host.h"
#include "content/public/browser/render_process_host.h"
#include "extensions/browser/declarative_user_script_manager.h"
-#include "extensions/browser/declarative_user_script_master.h"
+#include "extensions/browser/declarative_user_script_set.h"
#include "extensions/browser/extension_system.h"
#include "extensions/browser/guest_view/web_view/web_view_constants.h"
#include "extensions/browser/guest_view/web_view/web_view_renderer_state.h"
@@ -53,10 +53,10 @@ void WebViewContentScriptManager::AddContentScripts(
std::unique_ptr<UserScriptList> scripts) {
DCHECK_CURRENTLY_ON(BrowserThread::UI);
- DeclarativeUserScriptMaster* master =
+ DeclarativeUserScriptSet* script_set =
DeclarativeUserScriptManager::Get(browser_context_)
- ->GetDeclarativeUserScriptMasterByID(host_id);
- DCHECK(master);
+ ->GetDeclarativeUserScriptSetByID(host_id);
+ DCHECK(script_set);
// We need to update WebViewRenderState.
std::set<int> ids_to_add;
@@ -90,18 +90,18 @@ void WebViewContentScriptManager::AddContentScripts(
}
if (!to_delete.empty())
- master->RemoveScripts(to_delete);
+ script_set->RemoveScripts(to_delete);
// Step 3: makes WebViewContentScriptManager become an observer of the
// |loader| for scripts loaded event.
- UserScriptLoader* loader = master->loader();
+ UserScriptLoader* loader = script_set->loader();
DCHECK(loader);
if (!user_script_loader_observer_.IsObserving(loader))
user_script_loader_observer_.Add(loader);
- // Step 4: adds new scripts to the master.
- master->AddScripts(std::move(scripts), embedder_process_id,
- render_frame_host->GetRoutingID());
+ // Step 4: adds new scripts to the set.
+ script_set->AddScripts(std::move(scripts), embedder_process_id,
+ render_frame_host->GetRoutingID());
// Step 5: creates an entry in |webview_host_id_map_| for the given
// |embedder_process_id| and |view_instance_id| if it doesn't exist.
@@ -146,16 +146,16 @@ void WebViewContentScriptManager::RemoveContentScripts(
if (script_map_iter == guest_content_script_map_.end())
return;
- DeclarativeUserScriptMaster* master =
+ DeclarativeUserScriptSet* script_set =
DeclarativeUserScriptManager::Get(browser_context_)
- ->GetDeclarativeUserScriptMasterByID(host_id);
- CHECK(master);
+ ->GetDeclarativeUserScriptSetByID(host_id);
+ CHECK(script_set);
// We need to update WebViewRenderState.
std::set<int> ids_to_delete;
std::set<UserScriptIDPair> scripts_to_delete;
- // Step 1: removes content scripts from |master| and updates
+ // Step 1: removes content scripts from |set| and updates
// |guest_content_script_map_|.
std::map<std::string, UserScriptIDPair>& map = script_map_iter->second;
// If the |script_name_list| is empty, all the content scripts added by the
@@ -182,13 +182,13 @@ void WebViewContentScriptManager::RemoveContentScripts(
// Step 2: makes WebViewContentScriptManager become an observer of the
// |loader| for scripts loaded event.
- UserScriptLoader* loader = master->loader();
+ UserScriptLoader* loader = script_set->loader();
DCHECK(loader);
if (!user_script_loader_observer_.IsObserving(loader))
user_script_loader_observer_.Add(loader);
- // Step 3: removes content scripts from master.
- master->RemoveScripts(scripts_to_delete);
+ // Step 3: removes content scripts from set.
+ script_set->RemoveScripts(scripts_to_delete);
// Step 4: updates WebViewRenderState.
if (!ids_to_delete.empty()) {
diff --git a/chromium/extensions/browser/guest_view/web_view/web_view_find_helper.cc b/chromium/extensions/browser/guest_view/web_view/web_view_find_helper.cc
index defb854a1a7..95cb7df01c3 100644
--- a/chromium/extensions/browser/guest_view/web_view/web_view_find_helper.cc
+++ b/chromium/extensions/browser/guest_view/web_view/web_view_find_helper.cc
@@ -103,31 +103,29 @@ void WebViewFindHelper::Find(
// No duplicate insertions.
DCHECK(insert_result.second);
- // Find options including the implicit |findNext| field.
blink::mojom::FindOptionsPtr full_options =
insert_result.first->second->options().Clone();
- // Set |findNext| implicitly.
if (current_find_session_) {
const base::string16& current_search_text =
current_find_session_->search_text();
bool current_match_case = current_find_session_->options()->match_case;
- full_options->find_next = !current_search_text.empty() &&
- current_search_text == search_text &&
- current_match_case == options->match_case;
+ full_options->new_session = current_search_text.empty() ||
+ current_search_text != search_text ||
+ current_match_case != options->match_case;
} else {
- full_options->find_next = false;
+ full_options->new_session = true;
}
// Link find requests that are a part of the same find session.
- if (full_options->find_next && current_find_session_) {
+ if (!full_options->new_session && current_find_session_) {
DCHECK(current_find_request_id_ != current_find_session_->request_id());
current_find_session_->AddFindNextRequest(
insert_result.first->second->AsWeakPtr());
}
// Update the current find session, if necessary.
- if (!full_options->find_next)
+ if (full_options->new_session)
current_find_session_ = insert_result.first->second;
// Handle the empty |search_text| case internally.
@@ -157,7 +155,7 @@ void WebViewFindHelper::FindReply(int request_id,
WebViewFindHelper::FindInfo* find_info = find_iterator->second.get();
// Handle canceled find requests.
- if (!find_info->options()->find_next &&
+ if (find_info->options()->new_session &&
find_info_map_.begin()->first < request_id) {
DCHECK_NE(current_find_session_->request_id(),
find_info_map_.begin()->first);
@@ -167,7 +165,7 @@ void WebViewFindHelper::FindReply(int request_id,
}
// Clears the results for |findupdate| for a new find session.
- if (!find_info->replied() && !find_info->options()->find_next)
+ if (!find_info->replied() && find_info->options()->new_session)
find_update_event_.reset(new FindUpdateEvent(find_info->search_text()));
// Aggregate the find results.
diff --git a/chromium/extensions/browser/guest_view/web_view/web_view_guest.cc b/chromium/extensions/browser/guest_view/web_view/web_view_guest.cc
index cac525bd5da..ff08c4063be 100644
--- a/chromium/extensions/browser/guest_view/web_view/web_view_guest.cc
+++ b/chromium/extensions/browser/guest_view/web_view/web_view_guest.cc
@@ -37,6 +37,7 @@
#include "content/public/browser/render_widget_host_view.h"
#include "content/public/browser/site_instance.h"
#include "content/public/browser/storage_partition.h"
+#include "content/public/browser/storage_partition_config.h"
#include "content/public/browser/web_contents.h"
#include "content/public/browser/web_contents_delegate.h"
#include "content/public/common/content_switches.h"
@@ -264,9 +265,7 @@ GuestViewBase* WebViewGuest::Create(WebContents* owner_web_contents) {
// static
bool WebViewGuest::GetGuestPartitionConfigForSite(
const GURL& site,
- std::string* partition_domain,
- std::string* partition_name,
- bool* in_memory) {
+ content::StoragePartitionConfig* storage_partition_config) {
if (!site.SchemeIs(content::kGuestScheme))
return false;
@@ -274,19 +273,22 @@ bool WebViewGuest::GetGuestPartitionConfigForSite(
// URL was created, so it needs to be decoded. Since it was created via
// EscapeQueryParamValue(), it should have no path separators or control codes
// when unescaped, but safest to check for that and fail if it does.
+ std::string partition_name;
if (!net::UnescapeBinaryURLComponentSafe(site.query_piece(),
true /* fail_on_path_separators */,
- partition_name)) {
+ &partition_name)) {
return false;
}
// Since guest URLs are only used for packaged apps, there must be an app
// id in the URL.
CHECK(site.has_host());
- *partition_domain = site.host();
// Since persistence is optional, the path must either be empty or the
// literal string.
- *in_memory = (site.path() != "/persist");
+ bool in_memory = (site.path() != "/persist");
+
+ *storage_partition_config = content::StoragePartitionConfig::Create(
+ site.host(), partition_name, in_memory);
return true;
}
@@ -1001,11 +1003,9 @@ void WebViewGuest::ReportFrameNameChange(const std::string& name) {
void WebViewGuest::PushWebViewStateToIOThread() {
const GURL& site_url = web_contents()->GetSiteInstance()->GetSiteURL();
- std::string partition_domain;
- std::string partition_id;
- bool in_memory;
- if (!GetGuestPartitionConfigForSite(
- site_url, &partition_domain, &partition_id, &in_memory)) {
+ content::StoragePartitionConfig storage_partition_config =
+ content::StoragePartitionConfig::CreateDefault();
+ if (!GetGuestPartitionConfigForSite(site_url, &storage_partition_config)) {
NOTREACHED();
return;
}
@@ -1014,7 +1014,7 @@ void WebViewGuest::PushWebViewStateToIOThread() {
web_view_info.embedder_process_id =
owner_web_contents()->GetMainFrame()->GetProcess()->GetID();
web_view_info.instance_id = view_instance_id();
- web_view_info.partition_id = partition_id;
+ web_view_info.partition_id = storage_partition_config.partition_name();
web_view_info.owner_host = owner_host();
web_view_info.rules_registry_id = rules_registry_id_;
@@ -1407,11 +1407,11 @@ void WebViewGuest::WebContentsCreated(WebContents* source_contents,
}
void WebViewGuest::EnterFullscreenModeForTab(
- WebContents* web_contents,
- const GURL& origin,
+ content::RenderFrameHost* requesting_frame,
const blink::mojom::FullscreenOptions& options) {
// Ask the embedder for permission.
base::DictionaryValue request_info;
+ const GURL& origin = requesting_frame->GetLastCommittedURL().GetOrigin();
request_info.SetString(webview::kOrigin, origin.spec());
web_view_permission_helper_->RequestPermission(
WEB_VIEW_PERMISSION_TYPE_FULLSCREEN, request_info,
diff --git a/chromium/extensions/browser/guest_view/web_view/web_view_guest.h b/chromium/extensions/browser/guest_view/web_view/web_view_guest.h
index 27c3c4460bf..23a25d4034a 100644
--- a/chromium/extensions/browser/guest_view/web_view/web_view_guest.h
+++ b/chromium/extensions/browser/guest_view/web_view/web_view_guest.h
@@ -23,6 +23,10 @@
#include "extensions/browser/script_executor.h"
#include "third_party/blink/public/mojom/frame/find_in_page.mojom.h"
+namespace content {
+class StoragePartitionConfig;
+} // namespace content
+
namespace extensions {
class WebViewInternalFindFunction;
@@ -50,10 +54,9 @@ class WebViewGuest : public guest_view::GuestView<WebViewGuest> {
// a specially formatted URL, based on the application it is hosted by and
// the partition requested by it. The format for that URL is:
// chrome-guest://partition_domain/persist?partition_name
- static bool GetGuestPartitionConfigForSite(const GURL& site,
- std::string* partition_domain,
- std::string* partition_name,
- bool* in_memory);
+ static bool GetGuestPartitionConfigForSite(
+ const GURL& site,
+ content::StoragePartitionConfig* storage_partition_config);
// Opposite of GetGuestPartitionConfigForSite: Creates a specially formatted
// URL used by the SiteInstance associated with the WebViewGuest. See
@@ -252,8 +255,7 @@ class WebViewGuest : public guest_view::GuestView<WebViewGuest> {
const GURL& target_url,
content::WebContents* new_contents) final;
void EnterFullscreenModeForTab(
- content::WebContents* web_contents,
- const GURL& origin,
+ content::RenderFrameHost* requesting_frame,
const blink::mojom::FullscreenOptions& options) final;
void ExitFullscreenModeForTab(content::WebContents* web_contents) final;
bool IsFullscreenForTabOrPending(
diff --git a/chromium/extensions/browser/install/crx_install_error.cc b/chromium/extensions/browser/install/crx_install_error.cc
index 12d2f22f60e..d61f059ccf6 100644
--- a/chromium/extensions/browser/install/crx_install_error.cc
+++ b/chromium/extensions/browser/install/crx_install_error.cc
@@ -84,4 +84,14 @@ bool CrxInstallError::IsCrxVerificationFailedError() const {
std::end(kVerificationFailureReasons);
}
+// Returns true if the error occurred during crx installation due to mismatch in
+// expectations from the manifest.
+bool CrxInstallError::IsCrxExpectationsFailedError() const {
+ if (type() != CrxInstallErrorType::OTHER)
+ return false;
+ const CrxInstallErrorDetail failure_reason = detail();
+ return failure_reason == CrxInstallErrorDetail::UNEXPECTED_ID ||
+ failure_reason == CrxInstallErrorDetail::MISMATCHED_VERSION;
+}
+
} // namespace extensions
diff --git a/chromium/extensions/browser/install/crx_install_error.h b/chromium/extensions/browser/install/crx_install_error.h
index 8cce45e9c04..5336cf2c39f 100644
--- a/chromium/extensions/browser/install/crx_install_error.h
+++ b/chromium/extensions/browser/install/crx_install_error.h
@@ -82,6 +82,7 @@ class CrxInstallError {
CrxInstallErrorDetail detail() const;
SandboxedUnpackerFailureReason sandbox_failure_detail() const;
bool IsCrxVerificationFailedError() const;
+ bool IsCrxExpectationsFailedError() const;
private:
CrxInstallErrorType type_;
diff --git a/chromium/extensions/browser/media_router_extension_access_logger.cc b/chromium/extensions/browser/media_router_extension_access_logger.cc
new file mode 100644
index 00000000000..ce62d79d484
--- /dev/null
+++ b/chromium/extensions/browser/media_router_extension_access_logger.cc
@@ -0,0 +1,11 @@
+// Copyright 2020 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 "extensions/browser/media_router_extension_access_logger.h"
+
+namespace extensions {
+
+MediaRouterExtensionAccessLogger::~MediaRouterExtensionAccessLogger() = default;
+
+} // namespace extensions
diff --git a/chromium/extensions/browser/media_router_extension_access_logger.h b/chromium/extensions/browser/media_router_extension_access_logger.h
new file mode 100644
index 00000000000..279e7ff7615
--- /dev/null
+++ b/chromium/extensions/browser/media_router_extension_access_logger.h
@@ -0,0 +1,33 @@
+// Copyright 2020 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 EXTENSIONS_BROWSER_MEDIA_ROUTER_EXTENSION_ACCESS_LOGGER_H_
+#define EXTENSIONS_BROWSER_MEDIA_ROUTER_EXTENSION_ACCESS_LOGGER_H_
+
+namespace content {
+class BrowserContext;
+}
+
+namespace url {
+class Origin;
+}
+
+namespace extensions {
+
+// Logs accesses of extension resources for the Media Router Component
+// Extension.
+class MediaRouterExtensionAccessLogger {
+ public:
+ virtual ~MediaRouterExtensionAccessLogger();
+
+ // Logs that |origin| accesses a resource from the Media Router Component
+ // Extension (the extension used to support casting to Chromecast devices).
+ virtual void LogMediaRouterComponentExtensionUse(
+ const url::Origin& origin,
+ content::BrowserContext* context) const = 0;
+};
+
+} // namespace extensions
+
+#endif // EXTENSIONS_BROWSER_MEDIA_ROUTER_EXTENSION_ACCESS_LOGGER_H_
diff --git a/chromium/extensions/browser/mock_extension_system.cc b/chromium/extensions/browser/mock_extension_system.cc
index cfff37cb5f4..b17f7162448 100644
--- a/chromium/extensions/browser/mock_extension_system.cc
+++ b/chromium/extensions/browser/mock_extension_system.cc
@@ -37,7 +37,7 @@ ServiceWorkerManager* MockExtensionSystem::service_worker_manager() {
return nullptr;
}
-SharedUserScriptMaster* MockExtensionSystem::shared_user_script_master() {
+SharedUserScriptManager* MockExtensionSystem::shared_user_script_manager() {
return nullptr;
}
@@ -69,6 +69,10 @@ const base::OneShotEvent& MockExtensionSystem::ready() const {
return ready_;
}
+bool MockExtensionSystem::is_ready() const {
+ return ready_.is_signaled();
+}
+
ContentVerifier* MockExtensionSystem::content_verifier() {
return nullptr;
}
diff --git a/chromium/extensions/browser/mock_extension_system.h b/chromium/extensions/browser/mock_extension_system.h
index 9db5999abcc..2075eddb548 100644
--- a/chromium/extensions/browser/mock_extension_system.h
+++ b/chromium/extensions/browser/mock_extension_system.h
@@ -36,7 +36,7 @@ class MockExtensionSystem : public ExtensionSystem {
RuntimeData* runtime_data() override;
ManagementPolicy* management_policy() override;
ServiceWorkerManager* service_worker_manager() override;
- SharedUserScriptMaster* shared_user_script_master() override;
+ SharedUserScriptManager* shared_user_script_manager() override;
StateStore* state_store() override;
StateStore* rules_store() override;
scoped_refptr<ValueStoreFactory> store_factory() override;
@@ -44,6 +44,7 @@ class MockExtensionSystem : public ExtensionSystem {
QuotaService* quota_service() override;
AppSorting* app_sorting() override;
const base::OneShotEvent& ready() const override;
+ bool is_ready() const override;
ContentVerifier* content_verifier() override;
std::unique_ptr<ExtensionSet> GetDependentExtensions(
const Extension* extension) override;
diff --git a/chromium/extensions/browser/notification_types.h b/chromium/extensions/browser/notification_types.h
index 10b992eaae2..356a1495a76 100644
--- a/chromium/extensions/browser/notification_types.h
+++ b/chromium/extensions/browser/notification_types.h
@@ -39,13 +39,6 @@ enum NotificationType {
// DEPRECATED: Use extensions::InstallObserver::OnFinishCrxInstall()
NOTIFICATION_CRX_INSTALLER_DONE = NOTIFICATION_EXTENSIONS_START,
- // Sent when the known installed extensions have all been loaded. In
- // testing scenarios this can happen multiple times if extensions are
- // unloaded and reloaded. The source is a BrowserContext*.
- //
- // DEPRECATED: Use ExtensionSystem::Get(browser_context)->ready().Post().
- NOTIFICATION_EXTENSIONS_READY_DEPRECATED,
-
// An error occurred while attempting to load an extension. The details are a
// string with details about why the load failed.
// DEPRECATED: Use extensions::LoadErrorReporter::OnLoadFailure()
diff --git a/chromium/extensions/browser/null_app_sorting.cc b/chromium/extensions/browser/null_app_sorting.cc
index a81ceba693e..6040148b766 100644
--- a/chromium/extensions/browser/null_app_sorting.cc
+++ b/chromium/extensions/browser/null_app_sorting.cc
@@ -23,6 +23,8 @@ NullAppSorting::NullAppSorting() {
NullAppSorting::~NullAppSorting() {
}
+void NullAppSorting::InitializePageOrdinalMapFromWebApps() {}
+
void NullAppSorting::FixNTPOrdinalCollisions() {
}
diff --git a/chromium/extensions/browser/null_app_sorting.h b/chromium/extensions/browser/null_app_sorting.h
index c8533091159..5edbc9fd158 100644
--- a/chromium/extensions/browser/null_app_sorting.h
+++ b/chromium/extensions/browser/null_app_sorting.h
@@ -20,6 +20,7 @@ class NullAppSorting : public AppSorting {
~NullAppSorting() override;
// AppSorting overrides:
+ void InitializePageOrdinalMapFromWebApps() override;
void FixNTPOrdinalCollisions() override;
void EnsureValidOrdinals(
const std::string& extension_id,
diff --git a/chromium/extensions/browser/process_manager.cc b/chromium/extensions/browser/process_manager.cc
index 374f722809b..fc25df40852 100644
--- a/chromium/extensions/browser/process_manager.cc
+++ b/chromium/extensions/browser/process_manager.cc
@@ -17,11 +17,11 @@
#include "base/one_shot_event.h"
#include "base/single_thread_task_runner.h"
#include "base/strings/string_number_conversions.h"
-#include "base/task/post_task.h"
#include "base/threading/thread_task_runner_handle.h"
#include "base/time/time.h"
#include "content/public/browser/browser_context.h"
#include "content/public/browser/browser_task_traits.h"
+#include "content/public/browser/browser_thread.h"
#include "content/public/browser/devtools_agent_host.h"
#include "content/public/browser/navigation_controller.h"
#include "content/public/browser/navigation_entry.h"
@@ -256,8 +256,7 @@ ProcessManager::ProcessManager(BrowserContext* context,
: extension_registry_(extension_registry),
site_instance_(content::SiteInstance::Create(context)),
browser_context_(context),
- worker_task_runner_(
- base::CreateSingleThreadTaskRunner({content::BrowserThread::IO})),
+ worker_task_runner_(content::GetIOThreadTaskRunner({})),
startup_background_hosts_created_(false),
last_background_close_sequence_id_(0) {
// ExtensionRegistry is shared between incognito and regular contexts.
diff --git a/chromium/extensions/browser/process_manager.h b/chromium/extensions/browser/process_manager.h
index 37dc3c3bc8c..1feb9e44423 100644
--- a/chromium/extensions/browser/process_manager.h
+++ b/chromium/extensions/browser/process_manager.h
@@ -243,7 +243,7 @@ class ProcessManager : public KeyedService,
protected:
static ProcessManager* Create(content::BrowserContext* context);
- // |context| is incognito pass the master context as |original_context|.
+ // |context| is incognito pass the original context as |original_context|.
// Otherwise pass the same context for both. Pass the ExtensionRegistry for
// |context| as |registry|, or override it for testing.
ProcessManager(content::BrowserContext* context,
diff --git a/chromium/extensions/browser/process_map_factory.h b/chromium/extensions/browser/process_map_factory.h
index 051df653150..53509efddf7 100644
--- a/chromium/extensions/browser/process_map_factory.h
+++ b/chromium/extensions/browser/process_map_factory.h
@@ -15,7 +15,7 @@ namespace extensions {
class ProcessMap;
// Factory for ProcessMap objects. ProcessMap objects are shared between an
-// incognito browser context and its master browser context.
+// incognito browser context and its original browser context.
class ProcessMapFactory : public BrowserContextKeyedServiceFactory {
public:
static ProcessMap* GetForBrowserContext(content::BrowserContext* context);
diff --git a/chromium/extensions/browser/requirements_checker.cc b/chromium/extensions/browser/requirements_checker.cc
index 4fa47ab3192..d2f307d4600 100644
--- a/chromium/extensions/browser/requirements_checker.cc
+++ b/chromium/extensions/browser/requirements_checker.cc
@@ -7,7 +7,6 @@
#include "base/bind.h"
#include "base/strings/string_util.h"
#include "base/strings/utf_string_conversions.h"
-#include "base/task/post_task.h"
#include "build/build_config.h"
#include "content/public/browser/browser_task_traits.h"
#include "content/public/browser/browser_thread.h"
@@ -78,8 +77,8 @@ void RequirementsChecker::PostRunCallback() {
// to maintain the assumption in
// ExtensionService::LoadExtensionsFromCommandLineFlag(). Remove these helper
// functions after crbug.com/708354 is addressed.
- base::PostTask(FROM_HERE, {content::BrowserThread::UI},
- base::BindOnce(&RequirementsChecker::RunCallback,
+ content::GetUIThreadTaskRunner({})->PostTask(
+ FROM_HERE, base::BindOnce(&RequirementsChecker::RunCallback,
weak_ptr_factory_.GetWeakPtr()));
}
diff --git a/chromium/extensions/browser/sandboxed_unpacker.cc b/chromium/extensions/browser/sandboxed_unpacker.cc
index 779a5c24947..b9b3495634b 100644
--- a/chromium/extensions/browser/sandboxed_unpacker.cc
+++ b/chromium/extensions/browser/sandboxed_unpacker.cc
@@ -156,7 +156,7 @@ base::Optional<crx_file::VerifierFormat> g_verifier_format_override_for_test;
SandboxedUnpackerClient::SandboxedUnpackerClient()
: RefCountedDeleteOnSequence<SandboxedUnpackerClient>(
- base::CreateSingleThreadTaskRunner({content::BrowserThread::UI})) {
+ content::GetUIThreadTaskRunner({})) {
DCHECK_CURRENTLY_ON(BrowserThread::UI);
}
diff --git a/chromium/extensions/browser/sandboxed_unpacker_unittest.cc b/chromium/extensions/browser/sandboxed_unpacker_unittest.cc
index 58cffa60117..c40af80202e 100644
--- a/chromium/extensions/browser/sandboxed_unpacker_unittest.cc
+++ b/chromium/extensions/browser/sandboxed_unpacker_unittest.cc
@@ -465,8 +465,8 @@ TEST_F(SandboxedUnpackerTest, InvalidMessagesFile) {
EXPECT_FALSE(base::PathExists(install_path));
EXPECT_TRUE(base::MatchPattern(
GetInstallErrorMessage(),
- base::ASCIIToUTF16("*_locales?en_US?messages.json': Line: 4, column: 1,"
- " Syntax error.'.")))
+ base::ASCIIToUTF16(
+ "*_locales?en_US?messages.json': Line: 4, column: 1,*")))
<< GetInstallErrorMessage();
ASSERT_EQ(CrxInstallErrorType::SANDBOXED_UNPACKER_FAILURE,
GetInstallErrorType());
diff --git a/chromium/extensions/browser/service_worker_task_queue.cc b/chromium/extensions/browser/service_worker_task_queue.cc
index 802b2d4af63..c3cf263c01a 100644
--- a/chromium/extensions/browser/service_worker_task_queue.cc
+++ b/chromium/extensions/browser/service_worker_task_queue.cc
@@ -9,7 +9,6 @@
#include <vector>
#include "base/bind.h"
-#include "base/task/post_task.h"
#include "content/public/browser/browser_context.h"
#include "content/public/browser/browser_task_traits.h"
#include "content/public/browser/browser_thread.h"
@@ -101,8 +100,8 @@ void ServiceWorkerTaskQueue::DidStartWorkerForScopeOnCoreThread(
thread_id);
}
} else {
- base::PostTask(
- FROM_HERE, {content::BrowserThread::UI},
+ content::GetUIThreadTaskRunner({})->PostTask(
+ FROM_HERE,
base::BindOnce(&ServiceWorkerTaskQueue::DidStartWorkerForScope,
task_queue, context_id, version_id, process_id,
thread_id));
@@ -118,8 +117,8 @@ void ServiceWorkerTaskQueue::DidStartWorkerFailOnCoreThread(
if (task_queue)
task_queue->DidStartWorkerFail(context_id);
} else {
- base::PostTask(FROM_HERE, {content::BrowserThread::UI},
- base::BindOnce(&ServiceWorkerTaskQueue::DidStartWorkerFail,
+ content::GetUIThreadTaskRunner({})->PostTask(
+ FROM_HERE, base::BindOnce(&ServiceWorkerTaskQueue::DidStartWorkerFail,
task_queue, context_id));
}
}
@@ -428,7 +427,7 @@ void ServiceWorkerTaskQueue::DeactivateExtension(const Extension* extension) {
->UnregisterServiceWorker(
extension->url(),
base::BindOnce(&ServiceWorkerTaskQueue::DidUnregisterServiceWorker,
- weak_factory_.GetWeakPtr(), extension_id));
+ weak_factory_.GetWeakPtr(), extension_id, *sequence));
}
void ServiceWorkerTaskQueue::RunTasksAfterStartWorker(
@@ -454,8 +453,7 @@ void ServiceWorkerTaskQueue::RunTasksAfterStartWorker(
weak_factory_.GetWeakPtr(), context_id, service_worker_context);
} else {
content::ServiceWorkerContext::RunTask(
- base::CreateSingleThreadTaskRunner({content::BrowserThread::IO}),
- FROM_HERE, service_worker_context,
+ content::GetIOThreadTaskRunner({}), FROM_HERE, service_worker_context,
base::BindOnce(
&ServiceWorkerTaskQueue::StartServiceWorkerOnCoreThreadToRunTasks,
weak_factory_.GetWeakPtr(), context_id, service_worker_context));
@@ -498,7 +496,12 @@ void ServiceWorkerTaskQueue::DidRegisterServiceWorker(
void ServiceWorkerTaskQueue::DidUnregisterServiceWorker(
const ExtensionId& extension_id,
+ ActivationSequence sequence,
bool success) {
+ // Extension run with |sequence| was already deactivated.
+ if (!IsCurrentSequence(extension_id, sequence))
+ return;
+
// TODO(lazyboy): Handle success = false case.
if (!success)
LOG(ERROR) << "Failed to unregister service worker!";
diff --git a/chromium/extensions/browser/service_worker_task_queue.h b/chromium/extensions/browser/service_worker_task_queue.h
index 2245d7b115d..2b4147ecd6d 100644
--- a/chromium/extensions/browser/service_worker_task_queue.h
+++ b/chromium/extensions/browser/service_worker_task_queue.h
@@ -167,6 +167,7 @@ class ServiceWorkerTaskQueue : public KeyedService,
void DidRegisterServiceWorker(const SequencedContextId& context_id,
bool success);
void DidUnregisterServiceWorker(const ExtensionId& extension_id,
+ ActivationSequence sequence,
bool success);
void DidStartWorkerForScope(const SequencedContextId& context_id,
diff --git a/chromium/extensions/browser/shared_user_script_master.cc b/chromium/extensions/browser/shared_user_script_manager.cc
index 9d573c7d116..6d7453a703e 100644
--- a/chromium/extensions/browser/shared_user_script_master.cc
+++ b/chromium/extensions/browser/shared_user_script_manager.cc
@@ -2,7 +2,7 @@
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
-#include "extensions/browser/shared_user_script_master.h"
+#include "extensions/browser/shared_user_script_manager.h"
#include "extensions/browser/extension_util.h"
#include "extensions/common/host_id.h"
@@ -10,7 +10,7 @@
namespace extensions {
-SharedUserScriptMaster::SharedUserScriptMaster(
+SharedUserScriptManager::SharedUserScriptManager(
content::BrowserContext* browser_context)
: loader_(browser_context,
HostID(),
@@ -19,15 +19,15 @@ SharedUserScriptMaster::SharedUserScriptMaster(
extension_registry_observer_.Add(ExtensionRegistry::Get(browser_context_));
}
-SharedUserScriptMaster::~SharedUserScriptMaster() {}
+SharedUserScriptManager::~SharedUserScriptManager() {}
-void SharedUserScriptMaster::OnExtensionLoaded(
+void SharedUserScriptManager::OnExtensionLoaded(
content::BrowserContext* browser_context,
const Extension* extension) {
loader_.AddScripts(GetScriptsMetadata(extension));
}
-void SharedUserScriptMaster::OnExtensionUnloaded(
+void SharedUserScriptManager::OnExtensionUnloaded(
content::BrowserContext* browser_context,
const Extension* extension,
UnloadedExtensionReason reason) {
@@ -39,7 +39,7 @@ void SharedUserScriptMaster::OnExtensionUnloaded(
loader_.RemoveScripts(scripts_to_remove);
}
-std::unique_ptr<UserScriptList> SharedUserScriptMaster::GetScriptsMetadata(
+std::unique_ptr<UserScriptList> SharedUserScriptManager::GetScriptsMetadata(
const Extension* extension) {
bool incognito_enabled =
util::IsIncognitoEnabled(extension->id(), browser_context_);
diff --git a/chromium/extensions/browser/shared_user_script_master.h b/chromium/extensions/browser/shared_user_script_manager.h
index 3a5b005cafd..55da0eb62a9 100644
--- a/chromium/extensions/browser/shared_user_script_master.h
+++ b/chromium/extensions/browser/shared_user_script_manager.h
@@ -2,8 +2,8 @@
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
-#ifndef EXTENSIONS_BROWSER_SHARED_USER_SCRIPT_MASTER_H_
-#define EXTENSIONS_BROWSER_SHARED_USER_SCRIPT_MASTER_H_
+#ifndef EXTENSIONS_BROWSER_SHARED_USER_SCRIPT_MANAGER_H_
+#define EXTENSIONS_BROWSER_SHARED_USER_SCRIPT_MANAGER_H_
#include <memory>
#include <set>
@@ -25,10 +25,10 @@ namespace extensions {
// Manages statically-defined user scripts for all extensions. Owns a
// UserScriptLoader to which file loading and shared memory management
// operations are delegated.
-class SharedUserScriptMaster : public ExtensionRegistryObserver {
+class SharedUserScriptManager : public ExtensionRegistryObserver {
public:
- explicit SharedUserScriptMaster(content::BrowserContext* browser_context);
- ~SharedUserScriptMaster() override;
+ explicit SharedUserScriptManager(content::BrowserContext* browser_context);
+ ~SharedUserScriptManager() override;
UserScriptLoader* script_loader() { return &loader_; }
@@ -54,9 +54,9 @@ class SharedUserScriptMaster : public ExtensionRegistryObserver {
ScopedObserver<ExtensionRegistry, ExtensionRegistryObserver>
extension_registry_observer_{this};
- DISALLOW_COPY_AND_ASSIGN(SharedUserScriptMaster);
+ DISALLOW_COPY_AND_ASSIGN(SharedUserScriptManager);
};
} // namespace extensions
-#endif // EXTENSIONS_BROWSER_SHARED_USER_SCRIPT_MASTER_H_
+#endif // EXTENSIONS_BROWSER_SHARED_USER_SCRIPT_MANAGER_H_
diff --git a/chromium/extensions/browser/supervised_user_extensions_delegate.h b/chromium/extensions/browser/supervised_user_extensions_delegate.h
new file mode 100644
index 00000000000..4b4e9f4f0ae
--- /dev/null
+++ b/chromium/extensions/browser/supervised_user_extensions_delegate.h
@@ -0,0 +1,57 @@
+// Copyright 2020 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 EXTENSIONS_BROWSER_SUPERVISED_USER_EXTENSIONS_DELEGATE_H_
+#define EXTENSIONS_BROWSER_SUPERVISED_USER_EXTENSIONS_DELEGATE_H_
+
+#include "base/callback.h"
+#include "extensions/common/extension.h"
+
+namespace content {
+class BrowserContext;
+class WebContents;
+} // namespace content
+
+namespace extensions {
+
+class SupervisedUserExtensionsDelegate {
+ public:
+ // Result of the parent permission dialog invocation.
+ enum class ParentPermissionDialogResult {
+ kParentPermissionReceived,
+ kParentPermissionCanceled,
+ kParentPermissionFailed,
+ };
+
+ using ParentPermissionDialogDoneCallback =
+ base::OnceCallback<void(ParentPermissionDialogResult)>;
+
+ virtual ~SupervisedUserExtensionsDelegate() = default;
+
+ // Returns true if |context| represents a supervised child account.
+ virtual bool IsChild(content::BrowserContext* context) const = 0;
+
+ // Returns true if the parent has already approved the |extension|.
+ virtual bool IsExtensionAllowedByParent(
+ const extensions::Extension& extension,
+ content::BrowserContext* context) const = 0;
+
+ // If the current user is a child, the child user has a custodian/parent, the
+ // kSupervisedUserInitiatedExtensionInstall feature flag is enabled, and the
+ // parent has enabled the "Permissions for sites, apps and extensions" toggle,
+ // then display the Parent Permission Dialog and call
+ // |parent_permission_callback|. Otherwise, display the Extension Install
+ // Blocked by Parent Dialog and call |error_callback|. The two paths are
+ // mutually exclusive.
+ virtual void PromptForParentPermissionOrShowError(
+ const extensions::Extension& extension,
+ content::BrowserContext* browser_context,
+ content::WebContents* web_contents,
+ ParentPermissionDialogDoneCallback parent_permission_callback,
+ base::OnceClosure error_callback) = 0;
+};
+
+} // namespace extensions
+
+#endif // EXTENSIONS_BROWSER_SUPERVISED_USER_EXTENSIONS_DELEGATE_H_
diff --git a/chromium/extensions/browser/unloaded_extension_reason.h b/chromium/extensions/browser/unloaded_extension_reason.h
index 168112ae245..5ee12382ce5 100644
--- a/chromium/extensions/browser/unloaded_extension_reason.h
+++ b/chromium/extensions/browser/unloaded_extension_reason.h
@@ -14,7 +14,7 @@ enum class UnloadedExtensionReason {
UPDATE, // Extension is being updated to a newer version.
UNINSTALL, // Extension is being uninstalled.
TERMINATE, // Extension has terminated.
- BLACKLIST, // Extension has been blacklisted.
+ BLOCKLIST, // Extension has been blocklisted.
PROFILE_SHUTDOWN, // Profile is being shut down.
LOCK_ALL, // All extensions for the profile are blocked.
MIGRATED_TO_COMPONENT, // Extension is being migrated to a component
diff --git a/chromium/extensions/browser/updater/extension_cache_fake.cc b/chromium/extensions/browser/updater/extension_cache_fake.cc
index 5425a994477..3275bb13ff7 100644
--- a/chromium/extensions/browser/updater/extension_cache_fake.cc
+++ b/chromium/extensions/browser/updater/extension_cache_fake.cc
@@ -6,7 +6,6 @@
#include "base/bind.h"
#include "base/stl_util.h"
-#include "base/task/post_task.h"
#include "content/public/browser/browser_task_traits.h"
#include "content/public/browser/browser_thread.h"
@@ -17,11 +16,11 @@ ExtensionCacheFake::ExtensionCacheFake() = default;
ExtensionCacheFake::~ExtensionCacheFake() = default;
void ExtensionCacheFake::Start(const base::Closure& callback) {
- base::PostTask(FROM_HERE, {content::BrowserThread::UI}, callback);
+ content::GetUIThreadTaskRunner({})->PostTask(FROM_HERE, callback);
}
void ExtensionCacheFake::Shutdown(const base::Closure& callback) {
- base::PostTask(FROM_HERE, {content::BrowserThread::UI}, callback);
+ content::GetUIThreadTaskRunner({})->PostTask(FROM_HERE, callback);
}
void ExtensionCacheFake::AllowCaching(const std::string& id) {
@@ -52,8 +51,8 @@ void ExtensionCacheFake::PutExtension(const std::string& id,
if (base::Contains(allowed_extensions_, id)) {
cache_[id].first = version;
cache_[id].second = file_path;
- base::PostTask(FROM_HERE, {content::BrowserThread::UI},
- base::BindOnce(callback, file_path, false));
+ content::GetUIThreadTaskRunner({})->PostTask(
+ FROM_HERE, base::BindOnce(callback, file_path, false));
} else {
callback.Run(file_path, true);
}
diff --git a/chromium/extensions/browser/updater/extension_downloader.cc b/chromium/extensions/browser/updater/extension_downloader.cc
index 2806def0117..a8c378d4d6b 100644
--- a/chromium/extensions/browser/updater/extension_downloader.cc
+++ b/chromium/extensions/browser/updater/extension_downloader.cc
@@ -134,6 +134,10 @@ bool ShouldRetryRequest(const network::SimpleURLLoader* loader) {
return response_code >= 500 && response_code < 600;
}
+bool ShouldRetryRequestForExtensionNotFoundInCache(const int net_error_code) {
+ return net_error_code == net::ERR_INTERNET_DISCONNECTED;
+}
+
// This parses and updates a URL query such that the value of the |authuser|
// query parameter is incremented by 1. If parameter was not present in the URL,
// it will be added with a value of 1. All other query keys and values are
@@ -203,6 +207,27 @@ ExtensionDownloader::ExtensionFetch::ExtensionFetch(
ExtensionDownloader::ExtensionFetch::~ExtensionFetch() = default;
+ExtensionDownloader::FetchDataGroupKey::FetchDataGroupKey() = default;
+
+ExtensionDownloader::FetchDataGroupKey::FetchDataGroupKey(
+ const FetchDataGroupKey& other) = default;
+
+ExtensionDownloader::FetchDataGroupKey::FetchDataGroupKey(
+ const int request_id,
+ const GURL& update_url,
+ const bool is_force_installed)
+ : request_id(request_id),
+ update_url(update_url),
+ is_force_installed(is_force_installed) {}
+
+ExtensionDownloader::FetchDataGroupKey::~FetchDataGroupKey() = default;
+
+bool ExtensionDownloader::FetchDataGroupKey::operator<(
+ const FetchDataGroupKey& other) const {
+ return std::tie(request_id, update_url, is_force_installed) <
+ std::tie(other.request_id, other.update_url, other.is_force_installed);
+}
+
ExtensionDownloader::ExtraParams::ExtraParams() : is_corrupt_reinstall(false) {}
ExtensionDownloader::ExtensionDownloader(
@@ -324,6 +349,11 @@ void ExtensionDownloader::set_test_delegate(
g_test_delegate = delegate;
}
+void ExtensionDownloader::SetBackoffPolicyForTesting(
+ const net::BackoffEntry::Policy* backoff_policy) {
+ manifests_queue_.set_backoff_policy(backoff_policy);
+}
+
bool ExtensionDownloader::AddExtensionData(
const std::string& id,
const base::Version& version,
@@ -403,8 +433,11 @@ bool ExtensionDownloader::AddExtensionData(
// Find or create a ManifestFetchData to add this extension to.
bool added = false;
- auto existing_iter =
- fetches_preparing_.find(std::make_pair(request_id, update_url));
+ bool is_new_extension_force_installed =
+ extension_location == Manifest::Location::EXTERNAL_POLICY_DOWNLOAD;
+ FetchDataGroupKey key(request_id, update_url,
+ is_new_extension_force_installed);
+ auto existing_iter = fetches_preparing_.find(key);
if (existing_iter != fetches_preparing_.end() &&
!existing_iter->second.empty()) {
// Try to add to the ManifestFetchData at the end of the list.
@@ -421,8 +454,9 @@ bool ExtensionDownloader::AddExtensionData(
std::unique_ptr<ManifestFetchData> fetch(
CreateManifestFetchData(update_url, request_id, fetch_priority));
ManifestFetchData* fetch_ptr = fetch.get();
- fetches_preparing_[std::make_pair(request_id, update_url)].push_back(
- std::move(fetch));
+ if (is_new_extension_force_installed)
+ fetch_ptr->set_is_all_external_policy_download();
+ fetches_preparing_[key].push_back(std::move(fetch));
added = fetch_ptr->AddExtension(id, version.GetString(), optional_ping_data,
extra.update_url_data, install_source,
extension_location, fetch_priority);
@@ -456,13 +490,12 @@ void ExtensionDownloader::StartUpdateCheck(
g_test_delegate->StartUpdateCheck(this, delegate_, std::move(fetch_data));
return;
}
-
+ const ExtensionIdSet extension_ids = fetch_data->GetExtensionIds();
if (!ExtensionsBrowserClient::Get()->IsBackgroundUpdateAllowed()) {
NotifyExtensionsDownloadStageChanged(
- fetch_data->extension_ids(),
- ExtensionDownloaderDelegate::Stage::FINISHED);
+ extension_ids, ExtensionDownloaderDelegate::Stage::FINISHED);
NotifyExtensionsDownloadFailed(
- fetch_data->extension_ids(), fetch_data->request_ids(),
+ extension_ids, fetch_data->request_ids(),
ExtensionDownloaderDelegate::Error::DISABLED);
return;
}
@@ -472,7 +505,7 @@ void ExtensionDownloader::StartUpdateCheck(
if (fetch_data->full_url() == i->full_url()) {
// This url is already scheduled to be fetched.
NotifyExtensionsDownloadStageChanged(
- fetch_data->extension_ids(),
+ extension_ids,
ExtensionDownloaderDelegate::Stage::QUEUED_FOR_MANIFEST);
i->Merge(*fetch_data);
return;
@@ -482,7 +515,7 @@ void ExtensionDownloader::StartUpdateCheck(
if (manifests_queue_.active_request() &&
manifests_queue_.active_request()->full_url() == fetch_data->full_url()) {
NotifyExtensionsDownloadStageChanged(
- fetch_data->extension_ids(),
+ extension_ids,
ExtensionDownloaderDelegate::Stage::DOWNLOADING_MANIFEST);
manifests_queue_.active_request()->Merge(*fetch_data);
} else {
@@ -491,8 +524,7 @@ void ExtensionDownloader::StartUpdateCheck(
fetch_data->full_url().possibly_invalid_spec().length());
NotifyExtensionsDownloadStageChanged(
- fetch_data->extension_ids(),
- ExtensionDownloaderDelegate::Stage::QUEUED_FOR_MANIFEST);
+ extension_ids, ExtensionDownloaderDelegate::Stage::QUEUED_FOR_MANIFEST);
manifests_queue_.ScheduleRequest(std::move(fetch_data));
}
}
@@ -515,12 +547,11 @@ network::mojom::URLLoaderFactory* ExtensionDownloader::GetURLLoaderFactoryToUse(
void ExtensionDownloader::CreateManifestLoader() {
const ManifestFetchData* active_request = manifests_queue_.active_request();
+ const ExtensionIdSet extension_ids = active_request->GetExtensionIds();
NotifyExtensionsDownloadStageChanged(
- active_request->extension_ids(),
- ExtensionDownloaderDelegate::Stage::DOWNLOADING_MANIFEST);
- std::vector<base::StringPiece> id_vector(
- active_request->extension_ids().begin(),
- active_request->extension_ids().end());
+ extension_ids, ExtensionDownloaderDelegate::Stage::DOWNLOADING_MANIFEST);
+ std::vector<base::StringPiece> id_vector(extension_ids.begin(),
+ extension_ids.end());
std::string id_list = base::JoinString(id_vector, ",");
VLOG(2) << "Fetching " << active_request->full_url() << " for " << id_list;
VLOG(2) << "Update interactivity: "
@@ -605,10 +636,132 @@ void ExtensionDownloader::CreateManifestLoader() {
base::Unretained(this)));
}
+void ExtensionDownloader::RetryManifestFetchRequest() {
+ constexpr base::TimeDelta backoff_delay;
+ NotifyExtensionsDownloadStageChanged(
+ manifests_queue_.active_request()->GetExtensionIds(),
+ ExtensionDownloaderDelegate::Stage::DOWNLOADING_MANIFEST_RETRY);
+ manifests_queue_.RetryRequest(backoff_delay);
+}
+
+void ExtensionDownloader::ReportManifestFetchFailure(
+ ManifestFetchData* fetch_data,
+ ExtensionDownloaderDelegate::Error error,
+ const ExtensionDownloaderDelegate::FailureData& data) {
+ const ExtensionIdSet extension_ids = fetch_data->GetExtensionIds();
+ NotifyExtensionsDownloadStageChanged(
+ extension_ids, ExtensionDownloaderDelegate::Stage::FINISHED);
+ NotifyExtensionsDownloadFailedWithFailureData(
+ extension_ids, fetch_data->request_ids(), error, data);
+}
+
+void ExtensionDownloader::TryFetchingExtensionsFromCache(
+ ManifestFetchData* fetch_data,
+ ExtensionDownloaderDelegate::Error error,
+ const int net_error,
+ const int response_code,
+ const base::Optional<ManifestInvalidErrorList>& manifest_invalid_errors) {
+ const ExtensionIdSet extension_ids = fetch_data->GetExtensionIds();
+ ExtensionIdSet extensions_fetched_from_cache;
+ for (const auto& extension_id : extension_ids) {
+ // Extension is fetched here only in cases when we fail to fetch the update
+ // manifest or parsing of update manifest failed. In such cases, we don't
+ // have expected version and expected hash. Thus, passing empty hash and
+ // version would not be a problem as we only check for the expected hash and
+ // version if we have them.
+ auto extension_fetch_data(std::make_unique<ExtensionFetch>(
+ extension_id, fetch_data->base_url(), /*hash not fetched*/ "",
+ /*version not fetched*/ "", fetch_data->request_ids()));
+ base::Optional<base::FilePath> cached_crx_path = GetCachedExtension(
+ *extension_fetch_data, /*manifest_fetch_failed*/ true);
+ if (cached_crx_path) {
+ delegate_->OnExtensionDownloadStageChanged(
+ extension_id, ExtensionDownloaderDelegate::Stage::FINISHED);
+ NotifyDelegateDownloadFinished(std::move(extension_fetch_data), true,
+ cached_crx_path.value(), false);
+ extensions_fetched_from_cache.insert(extension_id);
+ }
+ }
+ // All the extensions were found in the cache, no need to retry any request or
+ // report failure.
+ if (extensions_fetched_from_cache.size() == extension_ids.size())
+ return;
+ fetch_data->RemoveExtensions(extensions_fetched_from_cache,
+ manifest_query_params_);
+
+ if (ShouldRetryRequestForExtensionNotFoundInCache(net_error)) {
+ RetryManifestFetchRequest();
+ return;
+ }
+ if (error == ExtensionDownloaderDelegate::Error::MANIFEST_FETCH_FAILED) {
+ ExtensionDownloaderDelegate::FailureData failure_data(
+ -net_error,
+ response_code > 0 ? base::Optional<int>(response_code) : base::nullopt,
+ manifests_queue_.active_request_failure_count());
+ ReportManifestFetchFailure(fetch_data, error, failure_data);
+ return;
+ }
+ DCHECK(manifest_invalid_errors);
+ ManifestInvalidErrorList errors_for_remaining_extensions;
+ for (const auto& manifest_invalid_error : manifest_invalid_errors.value()) {
+ if (!extensions_fetched_from_cache.count(manifest_invalid_error.first))
+ errors_for_remaining_extensions.push_back(manifest_invalid_error);
+ }
+ NotifyExtensionsDownloadStageChanged(
+ fetch_data->GetExtensionIds(),
+ ExtensionDownloaderDelegate::Stage::FINISHED);
+ NotifyExtensionsManifestInvalidFailure(errors_for_remaining_extensions,
+ fetch_data->request_ids());
+}
+
+void ExtensionDownloader::RetryRequestOrHandleFailureOnManifestFetchFailure(
+ const network::SimpleURLLoader* loader,
+ const int response_code) {
+ bool all_force_installed_extensions =
+ manifests_queue_.active_request()->is_all_external_policy_download();
+
+ const int net_error = manifest_loader_->NetError();
+ const int request_failure_count =
+ manifests_queue_.active_request_failure_count();
+ // If the device is offline, do not retry for force installed extensions,
+ // try installing it from cache. Try fetching from cache only on first attempt
+ // in this case, because we will retry the request only if there was no entry
+ // in cache corresponding to this extension and there is no point in trying to
+ // fetch extension from cache again.
+ if (net_error == net::ERR_INTERNET_DISCONNECTED &&
+ all_force_installed_extensions && request_failure_count == 0) {
+ TryFetchingExtensionsFromCache(
+ manifests_queue_.active_request(),
+ ExtensionDownloaderDelegate::Error::MANIFEST_FETCH_FAILED, net_error,
+ response_code, base::nullopt /*manifest_invalid_errors*/);
+ return;
+ }
+ if (ShouldRetryRequest(loader) && request_failure_count < kMaxRetries) {
+ RetryManifestFetchRequest();
+ return;
+ }
+ const GURL url = loader->GetFinalURL();
+ RETRY_HISTOGRAM("ManifestFetchFailure", request_failure_count, url);
+ if (all_force_installed_extensions) {
+ TryFetchingExtensionsFromCache(
+ manifests_queue_.active_request(),
+ ExtensionDownloaderDelegate::Error::MANIFEST_FETCH_FAILED, net_error,
+ response_code, base::nullopt /*manifest_invalid_errors*/);
+ } else {
+ ExtensionDownloaderDelegate::FailureData failure_data(
+ -net_error,
+ response_code > 0 ? base::Optional<int>(response_code) : base::nullopt,
+ request_failure_count);
+ ReportManifestFetchFailure(
+ manifests_queue_.active_request(),
+ ExtensionDownloaderDelegate::Error::MANIFEST_FETCH_FAILED,
+ failure_data);
+ }
+}
+
void ExtensionDownloader::OnManifestLoadComplete(
std::unique_ptr<std::string> response_body) {
const GURL url = manifest_loader_->GetFinalURL();
- int net_error = manifest_loader_->NetError();
DCHECK(manifests_queue_.active_request());
int response_code = -1;
@@ -618,7 +771,6 @@ void ExtensionDownloader::OnManifestLoadComplete(
VLOG(2) << response_code << " " << url;
- const base::TimeDelta& backoff_delay = base::TimeDelta::FromMilliseconds(0);
const int request_failure_count =
manifests_queue_.active_request_failure_count();
@@ -628,7 +780,7 @@ void ExtensionDownloader::OnManifestLoadComplete(
RETRY_HISTOGRAM("ManifestFetchSuccess", request_failure_count, url);
VLOG(2) << "beginning manifest parse for " << url;
NotifyExtensionsDownloadStageChanged(
- manifests_queue_.active_request()->extension_ids(),
+ manifests_queue_.active_request()->GetExtensionIds(),
ExtensionDownloaderDelegate::Stage::PARSING_MANIFEST);
auto callback = base::BindOnce(&ExtensionDownloader::HandleManifestResults,
weak_ptr_factory_.GetWeakPtr(),
@@ -637,30 +789,8 @@ void ExtensionDownloader::OnManifestLoadComplete(
} else {
VLOG(1) << "Failed to fetch manifest '" << url.possibly_invalid_spec()
<< "' response code:" << response_code;
- const auto* loader = manifest_loader_.get();
- if (ShouldRetryRequest(loader) && request_failure_count < kMaxRetries) {
- NotifyExtensionsDownloadStageChanged(
- manifests_queue_.active_request()->extension_ids(),
- ExtensionDownloaderDelegate::Stage::DOWNLOADING_MANIFEST_RETRY);
- manifests_queue_.RetryRequest(backoff_delay);
- } else {
- RETRY_HISTOGRAM("ManifestFetchFailure",
- manifests_queue_.active_request_failure_count(),
- url);
- NotifyExtensionsDownloadStageChanged(
- manifests_queue_.active_request()->extension_ids(),
- ExtensionDownloaderDelegate::Stage::FINISHED);
- ExtensionDownloaderDelegate::FailureData failure_data(
- -net_error,
- response_code > 0 ? base::Optional<int>(response_code)
- : base::nullopt,
- manifests_queue_.active_request_failure_count());
- NotifyExtensionsDownloadFailedWithFailureData(
- manifests_queue_.active_request()->extension_ids(),
- manifests_queue_.active_request()->request_ids(),
- ExtensionDownloaderDelegate::Error::MANIFEST_FETCH_FAILED,
- failure_data);
- }
+ RetryRequestOrHandleFailureOnManifestFetchFailure(manifest_loader_.get(),
+ response_code);
}
manifest_loader_.reset();
file_url_loader_factory_.reset();
@@ -678,18 +808,17 @@ void ExtensionDownloader::HandleManifestResults(
VLOG(2) << "parsing manifest failed (" << fetch_data->full_url() << ")";
DCHECK(error.has_value());
ManifestInvalidErrorList manifest_invalid_errors;
- manifest_invalid_errors.reserve(fetch_data->extension_ids().size());
+ const ExtensionIdSet extension_ids = fetch_data->GetExtensionIds();
+ manifest_invalid_errors.reserve(extension_ids.size());
// If the manifest parsing failed for all the extensions with a common
// error, add all extensions in the list with that error.
- for (const auto& extension_id : fetch_data->extension_ids()) {
+ for (const auto& extension_id : extension_ids) {
manifest_invalid_errors.push_back(
std::make_pair(extension_id, error.value().error));
}
- NotifyExtensionsDownloadStageChanged(
- fetch_data->extension_ids(),
- ExtensionDownloaderDelegate::Stage::FINISHED);
- NotifyExtensionsManifestInvalidFailure(manifest_invalid_errors,
- fetch_data->request_ids());
+ TryFetchingExtensionsFromCache(
+ fetch_data.get(), ExtensionDownloaderDelegate::Error::MANIFEST_INVALID,
+ 0 /*net_error_code*/, 0 /*response_code*/, manifest_invalid_errors);
return;
} else {
VLOG(2) << "parsing manifest succeeded (" << fetch_data->full_url() << ")";
@@ -698,9 +827,9 @@ void ExtensionDownloader::HandleManifestResults(
// Report manifest update check status.
NotifyExtensionManifestUpdateCheckStatus(results->update_list);
+ const ExtensionIdSet extension_ids = fetch_data->GetExtensionIds();
NotifyExtensionsDownloadStageChanged(
- fetch_data->extension_ids(),
- ExtensionDownloaderDelegate::Stage::MANIFEST_LOADED);
+ extension_ids, ExtensionDownloaderDelegate::Stage::MANIFEST_LOADED);
std::vector<UpdateManifestResult*> to_update;
std::set<std::string> no_updates;
@@ -713,9 +842,14 @@ void ExtensionDownloader::HandleManifestResults(
GURL crx_url = update->crx_url;
NotifyUpdateFound(extension_id, update->version);
+ if (fetch_data->is_all_external_policy_download() && crx_url.is_empty()) {
+ DCHECK_EQ(fetch_data->fetch_priority(),
+ ManifestFetchData::FetchPriority::FOREGROUND);
+ }
FetchUpdatedExtension(std::make_unique<ExtensionFetch>(
- update->extension_id, crx_url, update->package_hash, update->version,
- fetch_data->request_ids()));
+ extension_id, crx_url, update->package_hash,
+ update->version, fetch_data->request_ids()),
+ update->info);
}
// If the manifest response included a <daystart> element, we want to save
@@ -725,7 +859,7 @@ void ExtensionDownloader::HandleManifestResults(
Time day_start =
Time::Now() - TimeDelta::FromSeconds(results->daystart_elapsed_seconds);
- for (const std::string& id : fetch_data->extension_ids()) {
+ for (const ExtensionId& id : extension_ids) {
ExtensionDownloaderDelegate::PingResult& result = ping_results_[id];
result.did_ping = fetch_data->DidPing(id, ManifestFetchData::ROLLCALL);
result.day_start = day_start;
@@ -843,9 +977,10 @@ void ExtensionDownloader::DetermineUpdates(
// are already inserted into |errors|.
ExtensionIdSet extension_errors;
+ const ExtensionIdSet extension_ids = fetch_data.GetExtensionIds();
// For each extensions in the current batch, greedily find an update from
// |possible_updates|.
- for (const std::string& extension_id : fetch_data.extension_ids()) {
+ for (const auto& extension_id : extension_ids) {
const auto it = update_groups.find(extension_id);
if (it == update_groups.end()) {
VLOG(2) << "Manifest doesn't have an update entry for " << extension_id;
@@ -893,7 +1028,8 @@ void ExtensionDownloader::DetermineUpdates(
}
base::Optional<base::FilePath> ExtensionDownloader::GetCachedExtension(
- const ExtensionFetch& fetch_data) {
+ const ExtensionFetch& fetch_data,
+ bool manifest_fetch_failed) {
if (!extension_cache_) {
delegate_->OnExtensionDownloadCacheStatusRetrieved(
fetch_data.id,
@@ -908,8 +1044,9 @@ base::Optional<base::FilePath> ExtensionDownloader::GetCachedExtension(
fetch_data.id, ExtensionDownloaderDelegate::CacheStatus::CACHE_MISS);
return base::nullopt;
}
-
- if (version != fetch_data.version) {
+ // If manifest fetch is failed, we need not verify the version of the cache as
+ // we will try to install the version present in the cache.
+ if (!manifest_fetch_failed && version != fetch_data.version) {
delegate_->OnExtensionDownloadCacheStatusRetrieved(
fetch_data.id,
ExtensionDownloaderDelegate::CacheStatus::CACHE_OUTDATED);
@@ -917,7 +1054,10 @@ base::Optional<base::FilePath> ExtensionDownloader::GetCachedExtension(
}
delegate_->OnExtensionDownloadCacheStatusRetrieved(
- fetch_data.id, ExtensionDownloaderDelegate::CacheStatus::CACHE_HIT);
+ fetch_data.id, manifest_fetch_failed
+ ? ExtensionDownloaderDelegate::CacheStatus::
+ CACHE_HIT_ON_MANIFEST_FETCH_FAILURE
+ : ExtensionDownloaderDelegate::CacheStatus::CACHE_HIT);
base::FilePath crx_path;
// Now get .crx file path.
@@ -931,7 +1071,8 @@ base::Optional<base::FilePath> ExtensionDownloader::GetCachedExtension(
// Begins (or queues up) download of an updated extension.
void ExtensionDownloader::FetchUpdatedExtension(
- std::unique_ptr<ExtensionFetch> fetch_data) {
+ std::unique_ptr<ExtensionFetch> fetch_data,
+ base::Optional<std::string> info) {
if (!fetch_data->url.is_valid()) {
// TODO(asargent): This can sometimes be invalid. See crbug.com/130881.
DLOG(WARNING) << "Invalid URL: '" << fetch_data->url.possibly_invalid_spec()
@@ -939,9 +1080,12 @@ void ExtensionDownloader::FetchUpdatedExtension(
delegate_->OnExtensionDownloadStageChanged(
fetch_data->id, ExtensionDownloaderDelegate::Stage::FINISHED);
if (fetch_data->url.is_empty()) {
- NotifyExtensionsDownloadFailed(
+ // We expect to receive initialised |info| from the manifest parser in
+ // case of no updates status in the update manifest.
+ ExtensionDownloaderDelegate::FailureData data(info.value_or(""));
+ NotifyExtensionsDownloadFailedWithFailureData(
{fetch_data->id}, fetch_data->request_ids,
- ExtensionDownloaderDelegate::Error::CRX_FETCH_URL_EMPTY);
+ ExtensionDownloaderDelegate::Error::CRX_FETCH_URL_EMPTY, data);
} else {
NotifyExtensionsDownloadFailed(
{fetch_data->id}, fetch_data->request_ids,
@@ -971,7 +1115,7 @@ void ExtensionDownloader::FetchUpdatedExtension(
return;
}
base::Optional<base::FilePath> cached_crx_path =
- GetCachedExtension(*fetch_data);
+ GetCachedExtension(*fetch_data, /*manifest_fetch_failed*/ false);
if (cached_crx_path) {
delegate_->OnExtensionDownloadStageChanged(
fetch_data->id, ExtensionDownloaderDelegate::Stage::FINISHED);
@@ -1002,7 +1146,9 @@ void ExtensionDownloader::NotifyDelegateDownloadFinished(
CRXFileInfo crx_info(crx_path, required_format);
crx_info.expected_hash = package_hash;
crx_info.extension_id = id;
- crx_info.expected_version = version;
+ // TODO(https://crbug.com/1076376): Change |version| in ExtensionFetch from
+ // std::string to base::Version.
+ crx_info.expected_version = base::Version(version);
delegate_->OnExtensionDownloadFinished(
crx_info, file_ownership_passed, url, ping_results_[id], request_ids,
from_cache ? base::BindRepeating(&ExtensionDownloader::CacheInstallDone,
@@ -1140,19 +1286,8 @@ void ExtensionDownloader::OnExtensionLoadComplete(base::FilePath crx_path) {
extensions_queue_.reset_active_request();
delegate_->OnExtensionDownloadStageChanged(
id, ExtensionDownloaderDelegate::Stage::FINISHED);
- if (extension_cache_) {
- const std::string& version = fetch_data->version;
- const std::string& expected_hash = fetch_data->package_hash;
- extension_cache_->PutExtension(
- id, expected_hash, crx_path, version,
- base::BindRepeating(
- &ExtensionDownloader::NotifyDelegateDownloadFinished,
- weak_ptr_factory_.GetWeakPtr(), base::Passed(&fetch_data),
- false));
- } else {
- NotifyDelegateDownloadFinished(std::move(fetch_data), false, crx_path,
- true);
- }
+ NotifyDelegateDownloadFinished(std::move(fetch_data), false, crx_path,
+ true);
} else if (IterateFetchCredentialsAfterFailure(&active_request,
response_code)) {
delegate_->OnExtensionDownloadStageChanged(
@@ -1174,8 +1309,6 @@ void ExtensionDownloader::OnExtensionLoadComplete(base::FilePath crx_path) {
RETRY_HISTOGRAM("CrxFetchFailure",
extensions_queue_.active_request_failure_count(),
url);
- // net_error is 0 (net::OK) or negative. (See net/base/net_errors.h)
- base::UmaHistogramSparse("Extensions.CrxFetchError", -net_error);
delegate_->OnExtensionDownloadStageChanged(
id, ExtensionDownloaderDelegate::Stage::FINISHED);
ExtensionDownloaderDelegate::FailureData failure_data(
diff --git a/chromium/extensions/browser/updater/extension_downloader.h b/chromium/extensions/browser/updater/extension_downloader.h
index e2059b9a3ad..56ac50ddcab 100644
--- a/chromium/extensions/browser/updater/extension_downloader.h
+++ b/chromium/extensions/browser/updater/extension_downloader.h
@@ -144,6 +144,11 @@ class ExtensionDownloader {
ping_enabled_domain_ = domain;
}
+ // Set backoff policy for manifest queue for testing with less initial delay
+ // so the tests do not timeout on retries.
+ void SetBackoffPolicyForTesting(
+ const net::BackoffEntry::Policy* backoff_policy);
+
// Sets a test delegate to use by any instances of this class. The |delegate|
// should outlive all instances.
static void set_test_delegate(ExtensionDownloaderTestDelegate* delegate);
@@ -229,6 +234,28 @@ class ExtensionDownloader {
ExtraParams();
};
+ // We limit the number of extensions grouped together in one batch to avoid
+ // running into the limits on the length of http GET requests, this represents
+ // the key for grouping these extensions.
+ struct FetchDataGroupKey {
+ FetchDataGroupKey();
+ FetchDataGroupKey(const FetchDataGroupKey& other);
+ FetchDataGroupKey(const int request_id,
+ const GURL& update_url,
+ const bool is_force_installed);
+ ~FetchDataGroupKey();
+
+ bool operator<(const FetchDataGroupKey& other) const;
+
+ int request_id{0};
+ GURL update_url;
+ // The extensions in current ManifestFetchData are all force installed
+ // (Manifest::Location::EXTERNAL_POLICY_DOWNLOAD) or not. In a
+ // ManifestFetchData we would have either all the extensions as force
+ // installed or we would none extensions as force installed.
+ bool is_force_installed{false};
+ };
+
enum class UpdateAvailability {
kAvailable,
kNoUpdate,
@@ -258,6 +285,33 @@ class ExtensionDownloader {
// Called by RequestQueue when a new manifest load request is started.
void CreateManifestLoader();
+ // Retries the active request with some backoff delay.
+ void RetryManifestFetchRequest();
+
+ // Reports failures if we failed to fetch the manifest or the fetched manifest
+ // was invalid.
+ void ReportManifestFetchFailure(
+ ManifestFetchData* fetch_data,
+ ExtensionDownloaderDelegate::Error error,
+ const ExtensionDownloaderDelegate::FailureData& data);
+
+ // Tries fetching the extension from cache if manifest fetch is failed for
+ // force installed extensions, and notifies the failure reason for remaining
+ // extensions.
+ void TryFetchingExtensionsFromCache(
+ ManifestFetchData* fetch_data,
+ ExtensionDownloaderDelegate::Error error,
+ const int net_error,
+ const int response_code,
+ const base::Optional<ManifestInvalidErrorList>& manifest_invalid_errors);
+
+ // Makes a retry attempt, reports failure by calling
+ // AddFailureDataOnManifestFetchFailed when fetching of update manifest
+ // failed.
+ void RetryRequestOrHandleFailureOnManifestFetchFailure(
+ const network::SimpleURLLoader* loader,
+ const int response_code);
+
// Handles the result of a manifest fetch.
void OnManifestLoadComplete(std::unique_ptr<std::string> response_body);
@@ -283,12 +337,18 @@ class ExtensionDownloader {
ManifestInvalidErrorList* errors);
// Checks whether extension is presented in cache. If yes, return path to its
- // cached CRX, base::nullopt otherwise.
+ // cached CRX, base::nullopt otherwise. |manifest_fetch_failed| flag indicates
+ // whether the lookup in cache is performed after the manifest is fetched or
+ // due to failure while fetching or parsing manifest.
base::Optional<base::FilePath> GetCachedExtension(
- const ExtensionFetch& fetch_data);
+ const ExtensionFetch& fetch_data,
+ bool manifest_fetch_failed);
- // Begins (or queues up) download of an updated extension.
- void FetchUpdatedExtension(std::unique_ptr<ExtensionFetch> fetch_data);
+ // Begins (or queues up) download of an updated extension. |info| represents
+ // additional information about the extension update from the info field in
+ // the update manifest.
+ void FetchUpdatedExtension(std::unique_ptr<ExtensionFetch> fetch_data,
+ base::Optional<std::string> info);
// Called by RequestQueue when a new extension load request is started.
void CreateExtensionLoader();
@@ -388,13 +448,11 @@ class ExtensionDownloader {
// Collects UMA samples that are reported when ReportStats() is called.
URLStats url_stats_;
- // List of data on fetches we're going to do. We limit the number of
- // extensions grouped together in one batch to avoid running into the limits
- // on the length of http GET requests, so there might be multiple
- // ManifestFetchData* objects with the same base_url.
- using FetchMap = std::map<std::pair<int, GURL>,
- std::vector<std::unique_ptr<ManifestFetchData>>>;
- FetchMap fetches_preparing_;
+ // We limit the number of extensions grouped together in one batch to avoid
+ // running into the limits on the length of http GET requests, so there might
+ // be multiple ManifestFetchData* objects with the same update_url.
+ std::map<FetchDataGroupKey, std::vector<std::unique_ptr<ManifestFetchData>>>
+ fetches_preparing_;
// Outstanding url loader requests for manifests and updates.
std::unique_ptr<network::SimpleURLLoader> manifest_loader_;
diff --git a/chromium/extensions/browser/updater/extension_downloader_delegate.cc b/chromium/extensions/browser/updater/extension_downloader_delegate.cc
index dc7dd473ca8..02d98fe0a38 100644
--- a/chromium/extensions/browser/updater/extension_downloader_delegate.cc
+++ b/chromium/extensions/browser/updater/extension_downloader_delegate.cc
@@ -32,6 +32,10 @@ ExtensionDownloaderDelegate::FailureData::FailureData(
ManifestInvalidError manifest_invalid_error)
: manifest_invalid_error(manifest_invalid_error) {}
+ExtensionDownloaderDelegate::FailureData::FailureData(
+ const std::string& additional_info)
+ : additional_info(additional_info) {}
+
ExtensionDownloaderDelegate::FailureData::~FailureData() = default;
ExtensionDownloaderDelegate::~ExtensionDownloaderDelegate() = default;
diff --git a/chromium/extensions/browser/updater/extension_downloader_delegate.h b/chromium/extensions/browser/updater/extension_downloader_delegate.h
index 84d7803b7a0..0ba28d76a3b 100644
--- a/chromium/extensions/browser/updater/extension_downloader_delegate.h
+++ b/chromium/extensions/browser/updater/extension_downloader_delegate.h
@@ -124,9 +124,13 @@ class ExtensionDownloaderDelegate {
// Cache entry is good and will be used.
CACHE_HIT = 4,
+ // Cache entry will be used in case we fail to fetch the manifest for the
+ // extension.
+ CACHE_HIT_ON_MANIFEST_FETCH_FAILURE = 5,
+
// Magic constant used by the histogram macros.
// Always update it to the max value.
- kMaxValue = CACHE_HIT,
+ kMaxValue = CACHE_HIT_ON_MANIFEST_FETCH_FAILURE,
};
// Passed as an argument to the completion callbacks to signal whether
@@ -143,8 +147,9 @@ class ExtensionDownloaderDelegate {
base::Time day_start;
};
- // Contains the error codes when Force installed extension fail to install
- // with error CRX_FETCH_FAILED, MANIFEST_FETCH_FAILED or MANIFEST_INVALID.
+ // Additional information in case of force installed extension install failure
+ // due to CRX_FETCH_FAILED, MANIFEST_FETCH_FAILED, MANIFEST_INVALID,
+ // CRX_FETCH_URL_EMPTY.
struct FailureData {
FailureData();
FailureData(const FailureData& other);
@@ -153,6 +158,7 @@ class ExtensionDownloaderDelegate {
const base::Optional<int> response,
const int fetch_attempts);
explicit FailureData(ManifestInvalidError manifest_invalid_error);
+ explicit FailureData(const std::string& additional_info);
~FailureData();
// Network error code in case of CRX_FETCH_FAILED or MANIFEST_FETCH_FAILED.
@@ -166,6 +172,10 @@ class ExtensionDownloaderDelegate {
// errors occurred while parsing the update manifest and the errors in the
// internal details of the parsed manifest.
const base::Optional<ManifestInvalidError> manifest_invalid_error;
+ // Info field in the update manifest returned by the server. Currently it is
+ // only set when no update is available and install fails with the error
+ // CRX_FETCH_URL_EMPTY.
+ const base::Optional<std::string> additional_info;
};
// A callback that is called to indicate if ExtensionDownloader should ignore
diff --git a/chromium/extensions/browser/updater/extension_installer.cc b/chromium/extensions/browser/updater/extension_installer.cc
index ce88e3aeb23..60a074809fa 100644
--- a/chromium/extensions/browser/updater/extension_installer.cc
+++ b/chromium/extensions/browser/updater/extension_installer.cc
@@ -12,7 +12,6 @@
#include "base/files/scoped_temp_dir.h"
#include "base/logging.h"
#include "base/strings/string_number_conversions.h"
-#include "base/task/post_task.h"
#include "base/threading/thread_task_runner_handle.h"
#include "components/update_client/update_client_errors.h"
#include "content/public/browser/browser_task_traits.h"
@@ -45,8 +44,7 @@ void ExtensionInstaller::Install(
std::unique_ptr<InstallParams> /*install_params*/,
ProgressCallback /*progress_callback*/,
UpdateClientCallback update_client_callback) {
- auto ui_thread =
- base::CreateSingleThreadTaskRunner({content::BrowserThread::UI});
+ auto ui_thread = content::GetUIThreadTaskRunner({});
DCHECK(ui_thread);
DCHECK(!extension_installer_callback_.is_null());
if (base::PathExists(unpack_path)) {
diff --git a/chromium/extensions/browser/updater/manifest_fetch_data.cc b/chromium/extensions/browser/updater/manifest_fetch_data.cc
index 1246974885a..afb8318e619 100644
--- a/chromium/extensions/browser/updater/manifest_fetch_data.cc
+++ b/chromium/extensions/browser/updater/manifest_fetch_data.cc
@@ -46,6 +46,23 @@ void AddEnabledStateToPing(std::string* ping_value,
} // namespace
+ManifestFetchData::ExtensionData::ExtensionData() : version(base::Version()) {}
+
+ManifestFetchData::ExtensionData::ExtensionData(const ExtensionData& other) =
+ default;
+
+ManifestFetchData::ExtensionData::ExtensionData(
+ const base::Version& version,
+ const std::string& update_url_data,
+ const std::string& install_source,
+ Manifest::Location extension_location)
+ : version(version),
+ update_url_data(update_url_data),
+ install_source(install_source),
+ extension_location(extension_location) {}
+
+ManifestFetchData::ExtensionData::~ExtensionData() = default;
+
// static
std::string ManifestFetchData::GetSimpleLocationString(Manifest::Location loc) {
std::string result = kInvalidLocation;
@@ -87,14 +104,9 @@ ManifestFetchData::ManifestFetchData(const GURL& update_url,
full_url_(update_url),
brand_code_(brand_code),
ping_mode_(ping_mode),
- fetch_priority_(fetch_priority) {
- std::string query =
- full_url_.has_query() ? full_url_.query() + "&" : std::string();
- query += base_query_params;
- GURL::Replacements replacements;
- replacements.SetQueryStr(query);
- full_url_ = full_url_.ReplaceComponents(replacements);
-
+ fetch_priority_(fetch_priority),
+ is_all_external_policy_download_(false) {
+ UpdateFullUrl(base_query_params);
request_ids_.insert(request_id);
}
@@ -129,7 +141,9 @@ bool ManifestFetchData::AddExtension(const std::string& id,
const std::string& install_source,
Manifest::Location extension_location,
FetchPriority fetch_priority) {
- if (extension_ids_.find(id) != extension_ids_.end()) {
+ DCHECK(!is_all_external_policy_download_ ||
+ extension_location == Manifest::Location::EXTERNAL_POLICY_DOWNLOAD);
+ if (extensions_data_.find(id) != extensions_data_.end()) {
NOTREACHED() << "Duplicate extension id " << id;
return false;
}
@@ -192,20 +206,60 @@ bool ManifestFetchData::AddExtension(const std::string& id,
// Check against our max url size, exempting the first extension added.
int new_size = full_url_.possibly_invalid_spec().size() + extra.size();
- if (!extension_ids_.empty() && new_size > kExtensionsManifestMaxURLSize) {
+ if (!extensions_data_.empty() && new_size > kExtensionsManifestMaxURLSize) {
UMA_HISTOGRAM_PERCENTAGE("Extensions.UpdateCheckHitUrlSizeLimit", 1);
return false;
}
UMA_HISTOGRAM_PERCENTAGE("Extensions.UpdateCheckHitUrlSizeLimit", 0);
// We have room so go ahead and add the extension.
- extension_ids_.insert(id);
+ extensions_data_[id] = ExtensionData(base::Version(version), update_url_data,
+ install_source, extension_location);
full_url_ = GURL(full_url_.possibly_invalid_spec() + extra);
return true;
}
+void ManifestFetchData::UpdateFullUrl(const std::string& base_query_params) {
+ std::string query =
+ full_url_.has_query() ? full_url_.query() + "&" : std::string();
+ query += base_query_params;
+ GURL::Replacements replacements;
+ replacements.SetQueryStr(query);
+ full_url_ = full_url_.ReplaceComponents(replacements);
+}
+
+void ManifestFetchData::RemoveExtensions(const ExtensionIdSet& id_to_remove,
+ const std::string& base_query_params) {
+ const std::map<ExtensionId, ExtensionData> extensions_data =
+ std::move(extensions_data_);
+ extensions_data_.clear();
+ full_url_ = base_url_;
+ UpdateFullUrl(base_query_params);
+
+ for (const auto& data : extensions_data) {
+ const ExtensionId& extension_id = data.first;
+ if (id_to_remove.count(extension_id))
+ continue;
+ const ExtensionData& extension_data = data.second;
+ auto it = pings_.find(extension_id);
+ const PingData* optional_ping_data =
+ it != pings_.end() ? &(it->second) : nullptr;
+ AddExtension(extension_id, extension_data.version.GetString(),
+ optional_ping_data, extension_data.update_url_data,
+ extension_data.install_source,
+ extension_data.extension_location, fetch_priority_);
+ }
+}
+
+ExtensionIdSet ManifestFetchData::GetExtensionIds() const {
+ ExtensionIdSet extension_ids;
+ for (const auto& extension_data : extensions_data_)
+ extension_ids.insert(extension_data.first);
+ return extension_ids;
+}
+
bool ManifestFetchData::Includes(const std::string& extension_id) const {
- return extension_ids_.find(extension_id) != extension_ids_.end();
+ return extensions_data_.find(extension_id) != extensions_data_.end();
}
bool ManifestFetchData::DidPing(const std::string& extension_id,
@@ -231,4 +285,8 @@ void ManifestFetchData::Merge(const ManifestFetchData& other) {
request_ids_.insert(other.request_ids_.begin(), other.request_ids_.end());
}
+void ManifestFetchData::set_is_all_external_policy_download() {
+ is_all_external_policy_download_ = true;
+}
+
} // namespace extensions
diff --git a/chromium/extensions/browser/updater/manifest_fetch_data.h b/chromium/extensions/browser/updater/manifest_fetch_data.h
index b183e2e5833..0bbb0132f0b 100644
--- a/chromium/extensions/browser/updater/manifest_fetch_data.h
+++ b/chromium/extensions/browser/updater/manifest_fetch_data.h
@@ -10,6 +10,7 @@
#include <string>
#include "base/macros.h"
+#include "base/version.h"
#include "extensions/common/manifest.h"
#include "url/gurl.h"
@@ -108,14 +109,22 @@ class ManifestFetchData {
const GURL& base_url() const { return base_url_; }
const GURL& full_url() const { return full_url_; }
- const std::set<std::string>& extension_ids() const { return extension_ids_; }
+ ExtensionIdSet GetExtensionIds() const;
const std::set<int>& request_ids() const { return request_ids_; }
bool foreground_check() const { return fetch_priority_ == FOREGROUND; }
FetchPriority fetch_priority() const { return fetch_priority_; }
+ bool is_all_external_policy_download() const {
+ return is_all_external_policy_download_;
+ }
// Returns true if the given id is included in this manifest fetch.
bool Includes(const std::string& extension_id) const;
+ // Resets the full url to base url and removes |id_to_remove| from
+ // the ManifestFetchData.
+ void RemoveExtensions(const ExtensionIdSet& id_to_remove,
+ const std::string& base_query_params);
+
// Returns true if a ping parameter for |type| was added to full_url for this
// extension id.
bool DidPing(const std::string& extension_id, PingType type) const;
@@ -126,9 +135,36 @@ class ManifestFetchData {
// to this ManifestFetchData).
void Merge(const ManifestFetchData& other);
+ // Assigns true if all the extensions are force installed.
+ void set_is_all_external_policy_download();
+
private:
- // The set of extension id's for this ManifestFetchData.
- std::set<std::string> extension_ids_;
+ // Contains supplementary data needed to construct update manifest fetch
+ // query.
+ struct ExtensionData {
+ ExtensionData();
+ ExtensionData(const ExtensionData& other);
+ ExtensionData(const base::Version& version,
+ const std::string& update_url_data,
+ const std::string& install_source,
+ Manifest::Location extension_location);
+
+ ~ExtensionData();
+ base::Version version;
+ std::string update_url_data;
+ std::string install_source;
+ Manifest::Location extension_location{Manifest::Location::INTERNAL};
+ };
+
+ const std::map<ExtensionId, ExtensionData>& extensions_data() const {
+ return extensions_data_;
+ }
+
+ // Appends query parameters to the full url if any.
+ void UpdateFullUrl(const std::string& base_query_params);
+
+ // The set of extension data for each extension.
+ std::map<std::string, ExtensionData> extensions_data_;
// The set of ping data we actually sent.
std::map<std::string, PingData> pings_;
@@ -157,6 +193,10 @@ class ManifestFetchData {
// The priority of the update.
FetchPriority fetch_priority_;
+ // The flag is set to true if all the extensions are force installed
+ // extensions.
+ bool is_all_external_policy_download_;
+
DISALLOW_COPY_AND_ASSIGN(ManifestFetchData);
};
diff --git a/chromium/extensions/browser/updater/update_data_provider.cc b/chromium/extensions/browser/updater/update_data_provider.cc
index ee6f6b221bd..ead0cac88c5 100644
--- a/chromium/extensions/browser/updater/update_data_provider.cc
+++ b/chromium/extensions/browser/updater/update_data_provider.cc
@@ -12,7 +12,6 @@
#include "base/files/file_util.h"
#include "base/optional.h"
#include "base/strings/string_util.h"
-#include "base/task/post_task.h"
#include "base/task/thread_pool.h"
#include "components/crx_file/crx_verifier.h"
#include "components/update_client/utils.h"
@@ -154,23 +153,20 @@ void UpdateDataProvider::RunInstallCallback(
if (!browser_context_) {
base::ThreadPool::PostTask(
FROM_HERE, {base::TaskPriority::BEST_EFFORT, base::MayBlock()},
- base::BindOnce(base::IgnoreResult(&base::DeleteFile), unpacked_dir,
- true));
- base::CreateSingleThreadTaskRunner({content::BrowserThread::UI})
- ->PostTask(
- FROM_HERE,
- base::BindOnce(std::move(update_client_callback),
- update_client::CrxInstaller::Result(
- update_client::InstallError::GENERIC_ERROR)));
+ base::BindOnce(base::GetDeletePathRecursivelyCallback(), unpacked_dir));
+ content::GetUIThreadTaskRunner({})->PostTask(
+ FROM_HERE,
+ base::BindOnce(std::move(update_client_callback),
+ update_client::CrxInstaller::Result(
+ update_client::InstallError::GENERIC_ERROR)));
return;
}
- base::CreateSingleThreadTaskRunner({content::BrowserThread::UI})
- ->PostTask(
- FROM_HERE,
- base::BindOnce(InstallUpdateCallback, browser_context_, extension_id,
- public_key, unpacked_dir, install_immediately,
- std::move(update_client_callback)));
+ content::GetUIThreadTaskRunner({})->PostTask(
+ FROM_HERE,
+ base::BindOnce(InstallUpdateCallback, browser_context_, extension_id,
+ public_key, unpacked_dir, install_immediately,
+ std::move(update_client_callback)));
}
} // namespace extensions
diff --git a/chromium/extensions/browser/updater/update_service.cc b/chromium/extensions/browser/updater/update_service.cc
index 2c57317abe9..2b62acd4ae9 100644
--- a/chromium/extensions/browser/updater/update_service.cc
+++ b/chromium/extensions/browser/updater/update_service.cc
@@ -135,14 +135,15 @@ void UpdateService::OnEvent(Events event, const std::string& extension_id) {
break;
}
- base::Value attributes(base::Value::Type::DICTIONARY);
- if (should_perform_action_on_omaha_attributes &&
- base::FeatureList::IsEnabled(
- extensions_features::kDisableMalwareExtensionsRemotely)) {
- attributes = GetExtensionOmahaAttributes(extension_id);
+ if (should_perform_action_on_omaha_attributes) {
+ base::Value attributes(base::Value::Type::DICTIONARY);
+ if (base::FeatureList::IsEnabled(
+ extensions_features::kDisableMalwareExtensionsRemotely)) {
+ attributes = GetExtensionOmahaAttributes(extension_id);
+ }
+ ExtensionSystem::Get(browser_context_)
+ ->PerformActionBasedOnOmahaAttributes(extension_id, attributes);
}
- ExtensionSystem::Get(browser_context_)
- ->PerformActionBasedOnOmahaAttributes(extension_id, attributes);
}
UpdateService::UpdateService(
diff --git a/chromium/extensions/browser/updater/update_service_unittest.cc b/chromium/extensions/browser/updater/update_service_unittest.cc
index 8b17ff6a9d8..1dd9e3cc094 100644
--- a/chromium/extensions/browser/updater/update_service_unittest.cc
+++ b/chromium/extensions/browser/updater/update_service_unittest.cc
@@ -497,6 +497,36 @@ TEST_F(UpdateServiceTest, UninstallPings) {
}
}
+TEST_F(UpdateServiceTest, NoPerformAction) {
+ base::test::ScopedFeatureList feature_list;
+ feature_list.InitAndEnableFeature(
+ extensions_features::kDisableMalwareExtensionsRemotely);
+ std::string extension_id = "lpcaedmchfhocbbapmcbpinfpgnhiddi";
+ ExtensionRegistry* registry = ExtensionRegistry::Get(browser_context());
+ scoped_refptr<const Extension> extension1 =
+ ExtensionBuilder("1").SetVersion("1.2").SetID(extension_id).Build();
+ EXPECT_TRUE(registry->AddEnabled(extension1));
+
+ update_client()->set_is_malware_update_item();
+ update_client()->set_delay_update();
+
+ ExtensionUpdateCheckParams update_check_params;
+ update_check_params.update_info[extension_id] = ExtensionUpdateData();
+
+ bool executed = false;
+ update_service()->StartUpdateCheck(
+ update_check_params,
+ base::BindOnce([](bool* executed) { *executed = true; }, &executed));
+ EXPECT_FALSE(executed);
+
+ const auto& request = update_client()->update_request(0);
+ EXPECT_THAT(request.extension_ids, testing::ElementsAre(extension_id));
+
+ update_client()->RunDelayedUpdate(
+ 0, UpdateClientEvents::COMPONENT_CHECKING_FOR_UPDATES);
+ EXPECT_FALSE(registry->disabled_extensions().GetByID(extension_id));
+}
+
TEST_F(UpdateServiceTest, CheckOmahaAttributes) {
base::test::ScopedFeatureList feature_list;
feature_list.InitAndEnableFeature(
diff --git a/chromium/extensions/browser/url_loader_factory_manager.cc b/chromium/extensions/browser/url_loader_factory_manager.cc
index 346e5367a3b..0f2bfc2bdd8 100644
--- a/chromium/extensions/browser/url_loader_factory_manager.cc
+++ b/chromium/extensions/browser/url_loader_factory_manager.cc
@@ -179,7 +179,6 @@ const char* kHardcodedPartOfAllowlist[] = {
"999BD8D1929F9ABB817E9368480D93BAB2A0983D",
"99E06C364BBB2D1F82A9D20BC1645BF21E478259",
"9C6A186F8D3C5FD0CC8DCF49682FA726BD8A7705",
- "A04F08A772F1C83B7A14ED29788ACA4F000BBE05",
"A059797AECB77D24DEB248C3413D99B0D3BF9A8C",
"A07DA0EDB967D027E3B220208AD085FDC44C3231",
"A3660FA31A0DBF07C9F80D5342FF215DBC962719",
@@ -206,7 +205,6 @@ const char* kHardcodedPartOfAllowlist[] = {
"CC93FDEE1B0440FAD87F17E287C606205B87E6AD",
"CD8AF9C47DDE6327F8D9A3EFA81F34C6B6C26EBB",
"CF40F6289951CBFA3B83B792EFA774E2EA06E4C0",
- "D347F78F32567E90BC32D9C16B085254EA269590",
"D572BE31227F6D0BE95B9430BE2D5F21D7D9CF9A",
"D7C3879A8898618E3A23B0E6BFB6A38D01606246",
"DC39837AC518B832FCB2D2DC1CE8BA148F54758E",
diff --git a/chromium/extensions/browser/url_request_util.cc b/chromium/extensions/browser/url_request_util.cc
index 897ef43f0d6..070f288467b 100644
--- a/chromium/extensions/browser/url_request_util.cc
+++ b/chromium/extensions/browser/url_request_util.cc
@@ -84,28 +84,21 @@ bool AllowCrossRendererResourceLoad(const GURL& url,
if (resource_type == blink::mojom::ResourceType::kMainFrame) {
*allowed = true;
return true;
- } else if (resource_type == blink::mojom::ResourceType::kSubFrame) {
- // When navigating in subframe, allow if it is the same origin
- // as the top-level frame. This can only be the case if the subframe
- // request is coming from the extension process.
- if (process_map.Contains(child_id)) {
- *allowed = true;
- return true;
- }
+ }
- // Also allow if the file is explicitly listed as a web_accessible_resource.
- if (WebAccessibleResourcesInfo::IsResourceWebAccessible(
- extension, resource_path.as_string())) {
- *allowed = true;
- return true;
- }
+ // When navigating in subframe, allow if it is the same origin
+ // as the top-level frame. This can only be the case if the subframe
+ // request is coming from the extension process.
+ if (resource_type == blink::mojom::ResourceType::kSubFrame &&
+ process_map.Contains(child_id)) {
+ *allowed = true;
+ return true;
}
- // Since not all subresources are required to be listed in a v2
- // manifest, we must allow all subresource loads if there are any web
- // accessible resources. See http://crbug.com/179127.
- if (!blink::IsResourceTypeFrame(resource_type) &&
- WebAccessibleResourcesInfo::HasWebAccessibleResources(extension)) {
+ // Allow web accessible extension resources to be loaded as
+ // subresources/sub-frames.
+ if (WebAccessibleResourcesInfo::IsResourceWebAccessible(
+ extension, resource_path.as_string())) {
*allowed = true;
return true;
}
diff --git a/chromium/extensions/browser/user_script_loader.h b/chromium/extensions/browser/user_script_loader.h
index c48efc0d38e..92f62ce06a7 100644
--- a/chromium/extensions/browser/user_script_loader.h
+++ b/chromium/extensions/browser/user_script_loader.h
@@ -36,7 +36,7 @@ namespace extensions {
// renderers of new shared memory region when new renderers appear, or when
// script reloading completes. Script loading lives on the UI thread. Instances
// of this class are embedded within classes with names ending in
-// UserScriptMaster. These "master" classes implement the strategy for which
+// UserScriptManager. These "manager" classes implement the strategy for which
// scripts to load/unload on this logical unit of scripts.
class UserScriptLoader : public content::RenderProcessHostCreationObserver {
public:
diff --git a/chromium/extensions/browser/value_store/lazy_leveldb.cc b/chromium/extensions/browser/value_store/lazy_leveldb.cc
index afb48169eea..b8138730d31 100644
--- a/chromium/extensions/browser/value_store/lazy_leveldb.cc
+++ b/chromium/extensions/browser/value_store/lazy_leveldb.cc
@@ -102,7 +102,7 @@ ValueStore::Status LazyLevelDb::Read(const std::string& key,
return ToValueStoreError(s);
base::Optional<base::Value> read_value =
- base::JSONReader().ReadToValue(value_as_json);
+ base::JSONReader::Read(value_as_json);
if (!read_value) {
return ValueStore::Status(ValueStore::CORRUPTION, FixCorruption(&key),
kInvalidJson);
diff --git a/chromium/extensions/browser/value_store/value_store_frontend.cc b/chromium/extensions/browser/value_store/value_store_frontend.cc
index 9a7cebcda08..3391c0da5cf 100644
--- a/chromium/extensions/browser/value_store/value_store_frontend.cc
+++ b/chromium/extensions/browser/value_store/value_store_frontend.cc
@@ -11,7 +11,6 @@
#include "base/logging.h"
#include "base/macros.h"
#include "base/memory/scoped_refptr.h"
-#include "base/task/post_task.h"
#include "base/trace_event/trace_event.h"
#include "content/public/browser/browser_task_traits.h"
#include "content/public/browser/browser_thread.h"
@@ -45,8 +44,8 @@ class ValueStoreFrontend::Backend : public base::RefCountedThreadSafe<Backend> {
<< " failed: " << result.status().message;
}
- base::PostTask(FROM_HERE, {BrowserThread::UI},
- base::BindOnce(&ValueStoreFrontend::Backend::RunCallback,
+ content::GetUIThreadTaskRunner({})->PostTask(
+ FROM_HERE, base::BindOnce(&ValueStoreFrontend::Backend::RunCallback,
this, std::move(callback), std::move(value)));
}