diff options
Diffstat (limited to 'chromium/chrome/browser/extensions/api')
184 files changed, 3678 insertions, 2722 deletions
diff --git a/chromium/chrome/browser/extensions/api/activity_log_private/activity_log_private_api.cc b/chromium/chrome/browser/extensions/api/activity_log_private/activity_log_private_api.cc index ab0b80cca93..a2f3244e5a3 100644 --- a/chromium/chrome/browser/extensions/api/activity_log_private/activity_log_private_api.cc +++ b/chromium/chrome/browser/extensions/api/activity_log_private/activity_log_private_api.cc @@ -81,7 +81,7 @@ bool ActivityLogAPI::IsExtensionWhitelisted(const std::string& extension_id) { // TODO(devlin): Pass in a HashedExtensionId to avoid this conversion. return FeatureProvider::GetPermissionFeatures() ->GetFeature("activityLogPrivate") - ->IsIdInWhitelist(HashedExtensionId(extension_id)); + ->IsIdInAllowlist(HashedExtensionId(extension_id)); } void ActivityLogAPI::OnListenerAdded(const EventListenerInfo& details) { diff --git a/chromium/chrome/browser/extensions/api/automation/automation_apitest.cc b/chromium/chrome/browser/extensions/api/automation/automation_apitest.cc index 965b7118cd1..3d50db2f6db 100644 --- a/chromium/chrome/browser/extensions/api/automation/automation_apitest.cc +++ b/chromium/chrome/browser/extensions/api/automation/automation_apitest.cc @@ -61,7 +61,7 @@ class AutomationApiTest : public ExtensionApiTest { void StartEmbeddedTestServer() { base::FilePath test_data; - ASSERT_TRUE(PathService::Get(chrome::DIR_TEST_DATA, &test_data)); + ASSERT_TRUE(base::PathService::Get(chrome::DIR_TEST_DATA, &test_data)); embedded_test_server()->ServeFilesFromDirectory( test_data.AppendASCII("extensions/api_test") .AppendASCII(kSitesDir)); @@ -262,7 +262,8 @@ IN_PROC_BROWSER_TEST_F(AutomationApiTest, DesktopNotSupported) { } #endif // defined(USE_AURA) -IN_PROC_BROWSER_TEST_F(AutomationApiTest, CloseTab) { +// Flaky test on site_per_browser_tests: https://crbug.com/833318 +IN_PROC_BROWSER_TEST_F(AutomationApiTest, DISABLED_CloseTab) { StartEmbeddedTestServer(); ASSERT_TRUE(RunExtensionSubtest("automation/tests/tabs", "close_tab.html")) << message_; diff --git a/chromium/chrome/browser/extensions/api/automation_internal/automation_internal_api.cc b/chromium/chrome/browser/extensions/api/automation_internal/automation_internal_api.cc index 2a1b390978b..ef8e0dfa2d1 100644 --- a/chromium/chrome/browser/extensions/api/automation_internal/automation_internal_api.cc +++ b/chromium/chrome/browser/extensions/api/automation_internal/automation_internal_api.cc @@ -151,7 +151,7 @@ bool CanRequestAutomation(const Extension* extension, int tab_id = ExtensionTabUtil::GetTabId(contents); std::string unused_error; - return extension->permissions_data()->CanAccessPage(extension, url, tab_id, + return extension->permissions_data()->CanAccessPage(url, tab_id, &unused_error); } @@ -345,6 +345,9 @@ AutomationInternalPerformActionFunction::ConvertToAXActionData( case api::automation::ACTION_TYPE_BLUR: action->action = ax::mojom::Action::kBlur; break; + case api::automation::ACTION_TYPE_CLEARACCESSIBILITYFOCUS: + action->action = ax::mojom::Action::kClearAccessibilityFocus; + break; case api::automation::ACTION_TYPE_DECREMENT: action->action = ax::mojom::Action::kDecrement; break; @@ -383,6 +386,9 @@ AutomationInternalPerformActionFunction::ConvertToAXActionData( case api::automation::ACTION_TYPE_LOADINLINETEXTBOXES: action->action = ax::mojom::Action::kLoadInlineTextBoxes; break; + case api::automation::ACTION_TYPE_SETACCESSIBILITYFOCUS: + action->action = ax::mojom::Action::kSetAccessibilityFocus; + break; case api::automation::ACTION_TYPE_SCROLLTOMAKEVISIBLE: action->action = ax::mojom::Action::kScrollToMakeVisible; break; diff --git a/chromium/chrome/browser/extensions/api/autotest_private/autotest_private_api.cc b/chromium/chrome/browser/extensions/api/autotest_private/autotest_private_api.cc index a7d7901447f..27bf5a2193f 100644 --- a/chromium/chrome/browser/extensions/api/autotest_private/autotest_private_api.cc +++ b/chromium/chrome/browser/extensions/api/autotest_private/autotest_private_api.cc @@ -32,6 +32,7 @@ #include "base/feature_list.h" #include "chrome/browser/chromeos/arc/arc_util.h" #include "chrome/browser/chromeos/login/lock/screen_locker.h" +#include "chrome/browser/chromeos/printing/cups_printers_manager.h" #include "chrome/browser/chromeos/system/input_device_settings.h" #include "chrome/browser/profiles/profile_manager.h" #include "chrome/browser/ui/ash/login_screen_client.h" @@ -42,6 +43,7 @@ #include "components/user_manager/user_manager.h" #include "content/public/common/service_manager_connection.h" #include "mojo/public/cpp/bindings/associated_binding.h" +#include "net/base/filename_util.h" #include "services/service_manager/public/cpp/connector.h" #include "ui/base/ui_base_features.h" #include "ui/message_center/message_center.h" @@ -494,6 +496,63 @@ ExtensionFunction::ResponseAction AutotestPrivateGetPrinterListFunction::Run() { return RespondNow(OneArgument(std::move(values))); } +AutotestPrivateUpdatePrinterFunction::AutotestPrivateUpdatePrinterFunction() = + default; +AutotestPrivateUpdatePrinterFunction::~AutotestPrivateUpdatePrinterFunction() = + default; + +ExtensionFunction::ResponseAction AutotestPrivateUpdatePrinterFunction::Run() { + std::unique_ptr<api::autotest_private::UpdatePrinter::Params> params( + api::autotest_private::UpdatePrinter::Params::Create(*args_)); + EXTENSION_FUNCTION_VALIDATE(params); + DVLOG(1) << "AutotestPrivateUpdatePrinterFunction"; +#if defined(OS_CHROMEOS) + const api::autotest_private::Printer& js_printer = params->printer; + chromeos::Printer printer(js_printer.printer_id ? *js_printer.printer_id + : ""); + printer.set_display_name(js_printer.printer_name); + if (js_printer.printer_desc) + printer.set_description(*js_printer.printer_desc); + + if (js_printer.printer_make_and_model) + printer.set_make_and_model(*js_printer.printer_make_and_model); + + if (js_printer.printer_uri) + printer.set_uri(*js_printer.printer_uri); + + if (js_printer.printer_ppd) { + const GURL ppd = + net::FilePathToFileURL(base::FilePath(*js_printer.printer_ppd)); + if (ppd.is_valid()) + printer.mutable_ppd_reference()->user_supplied_ppd_url = ppd.spec(); + else + LOG(ERROR) << "Invalid ppd path: " << *js_printer.printer_ppd; + } + auto printers_manager = chromeos::CupsPrintersManager::Create( + ProfileManager::GetActiveUserProfile()); + printers_manager->UpdateConfiguredPrinter(printer); +#endif + return RespondNow(NoArguments()); +} + +AutotestPrivateRemovePrinterFunction::AutotestPrivateRemovePrinterFunction() = + default; +AutotestPrivateRemovePrinterFunction::~AutotestPrivateRemovePrinterFunction() = + default; + +ExtensionFunction::ResponseAction AutotestPrivateRemovePrinterFunction::Run() { + std::unique_ptr<api::autotest_private::RemovePrinter::Params> params( + api::autotest_private::RemovePrinter::Params::Create(*args_)); + EXTENSION_FUNCTION_VALIDATE(params); + DVLOG(1) << "AutotestPrivateRemovePrinterFunction"; +#if defined(OS_CHROMEOS) + auto printers_manager = chromeos::CupsPrintersManager::Create( + ProfileManager::GetActiveUserProfile()); + printers_manager->RemoveConfiguredPrinter(params->printer_id); +#endif + return RespondNow(NoArguments()); +} + ExtensionFunction::ResponseAction AutotestPrivateGetPlayStoreStateFunction::Run() { DVLOG(1) << "AutotestPrivateGetPlayStoreStateFunction"; diff --git a/chromium/chrome/browser/extensions/api/autotest_private/autotest_private_api.h b/chromium/chrome/browser/extensions/api/autotest_private/autotest_private_api.h index 63388ec5b8d..4575604fc44 100644 --- a/chromium/chrome/browser/extensions/api/autotest_private/autotest_private_api.h +++ b/chromium/chrome/browser/extensions/api/autotest_private/autotest_private_api.h @@ -242,6 +242,32 @@ class AutotestPrivateGetPrinterListFunction : public UIThreadExtensionFunction { DISALLOW_COPY_AND_ASSIGN(AutotestPrivateGetPrinterListFunction); }; +class AutotestPrivateUpdatePrinterFunction : public UIThreadExtensionFunction { + public: + AutotestPrivateUpdatePrinterFunction(); + DECLARE_EXTENSION_FUNCTION("autotestPrivate.updatePrinter", + AUTOTESTPRIVATE_UPDATEPRINTER) + + private: + ~AutotestPrivateUpdatePrinterFunction() override; + ResponseAction Run() override; + + DISALLOW_COPY_AND_ASSIGN(AutotestPrivateUpdatePrinterFunction); +}; + +class AutotestPrivateRemovePrinterFunction : public UIThreadExtensionFunction { + public: + AutotestPrivateRemovePrinterFunction(); + DECLARE_EXTENSION_FUNCTION("autotestPrivate.removePrinter", + AUTOTESTPRIVATE_REMOVEPRINTER) + + private: + ~AutotestPrivateRemovePrinterFunction() override; + ResponseAction Run() override; + + DISALLOW_COPY_AND_ASSIGN(AutotestPrivateRemovePrinterFunction); +}; + // Don't kill the browser when we're in a browser test. void SetAutotestPrivateTest(); diff --git a/chromium/chrome/browser/extensions/api/autotest_private/autotest_private_apitest.cc b/chromium/chrome/browser/extensions/api/autotest_private/autotest_private_apitest.cc index 3442d293c2c..e1bd15e7fba 100644 --- a/chromium/chrome/browser/extensions/api/autotest_private/autotest_private_apitest.cc +++ b/chromium/chrome/browser/extensions/api/autotest_private/autotest_private_apitest.cc @@ -6,12 +6,16 @@ #include "chrome/browser/extensions/api/autotest_private/autotest_private_api.h" #include "chrome/browser/extensions/extension_apitest.h" +namespace extensions { + #if defined(OS_CHROMEOS) IN_PROC_BROWSER_TEST_F(ExtensionApiTest, AutotestPrivate) { // Turn on testing mode so we don't kill the browser. - extensions::AutotestPrivateAPI::GetFactoryInstance() + AutotestPrivateAPI::GetFactoryInstance() ->Get(browser()->profile()) ->set_test_mode(true); ASSERT_TRUE(RunComponentExtensionTest("autotest_private")) << message_; } #endif + +} // namespace extensions diff --git a/chromium/chrome/browser/extensions/api/bluetooth_low_energy/bluetooth_low_energy_apitest.cc b/chromium/chrome/browser/extensions/api/bluetooth_low_energy/bluetooth_low_energy_apitest.cc index 1b40c8253fb..7d50faf9277 100644 --- a/chromium/chrome/browser/extensions/api/bluetooth_low_energy/bluetooth_low_energy_apitest.cc +++ b/chromium/chrome/browser/extensions/api/bluetooth_low_energy/bluetooth_low_energy_apitest.cc @@ -98,14 +98,14 @@ const char kTestDescriptorId1[] = "desc_id1"; const char kTestDescriptorUuid1[] = "1222"; const uint8_t kTestDescriptorDefaultValue1[] = {0x04, 0x05}; -class BluetoothLowEnergyApiTest : public ExtensionApiTest { +class BluetoothLowEnergyApiTest : public extensions::ExtensionApiTest { public: BluetoothLowEnergyApiTest() {} ~BluetoothLowEnergyApiTest() override {} void SetUpOnMainThread() override { - ExtensionApiTest::SetUpOnMainThread(); + extensions::ExtensionApiTest::SetUpOnMainThread(); empty_extension_ = extensions::ExtensionBuilder("Test").Build(); SetUpMocks(); } diff --git a/chromium/chrome/browser/extensions/api/bluetooth_low_energy/bluetooth_low_energy_apitest_chromeos.cc b/chromium/chrome/browser/extensions/api/bluetooth_low_energy/bluetooth_low_energy_apitest_chromeos.cc index 9dc43888e84..7dca7b82ff6 100644 --- a/chromium/chrome/browser/extensions/api/bluetooth_low_energy/bluetooth_low_energy_apitest_chromeos.cc +++ b/chromium/chrome/browser/extensions/api/bluetooth_low_energy/bluetooth_low_energy_apitest_chromeos.cc @@ -11,7 +11,7 @@ #include "chrome/browser/chromeos/ownership/fake_owner_settings_service.h" #include "chrome/browser/chromeos/settings/scoped_cros_settings_test_helper.h" #include "chrome/browser/extensions/extension_apitest.h" -#include "components/signin/core/account_id/account_id.h" +#include "components/account_id/account_id.h" #include "components/user_manager/scoped_user_manager.h" #include "content/public/test/browser_test.h" #include "extensions/common/switches.h" diff --git a/chromium/chrome/browser/extensions/api/bookmark_manager_private/bookmark_manager_private_api.cc b/chromium/chrome/browser/extensions/api/bookmark_manager_private/bookmark_manager_private_api.cc index bdc5848ab26..bbda385c078 100644 --- a/chromium/chrome/browser/extensions/api/bookmark_manager_private/bookmark_manager_private_api.cc +++ b/chromium/chrome/browser/extensions/api/bookmark_manager_private/bookmark_manager_private_api.cc @@ -552,7 +552,8 @@ bool BookmarkManagerPrivateStartDragFunction::RunOnReady() { if (!EditBookmarksEnabled()) return false; - if (GetViewType(GetSenderWebContents()) != VIEW_TYPE_TAB_CONTENTS) { + content::WebContents* web_contents = GetSenderWebContents(); + if (GetViewType(web_contents) != VIEW_TYPE_TAB_CONTENTS) { NOTREACHED(); return false; } @@ -566,9 +567,6 @@ bool BookmarkManagerPrivateStartDragFunction::RunOnReady() { if (!GetNodesFromVector(model, params->id_list, &nodes)) return false; - content::WebContents* web_contents = GetAssociatedWebContents(); - CHECK(web_contents); - ui::DragDropTypes::DragEventSource source = ui::DragDropTypes::DRAG_EVENT_SOURCE_MOUSE; if (params->is_from_touch) @@ -594,7 +592,8 @@ bool BookmarkManagerPrivateDropFunction::RunOnReady() { if (!CanBeModified(drop_parent)) return false; - if (GetViewType(GetSenderWebContents()) != VIEW_TYPE_TAB_CONTENTS) { + content::WebContents* web_contents = GetSenderWebContents(); + if (GetViewType(web_contents) != VIEW_TYPE_TAB_CONTENTS) { NOTREACHED(); return false; } @@ -605,8 +604,6 @@ bool BookmarkManagerPrivateDropFunction::RunOnReady() { else drop_index = drop_parent->child_count(); - WebContents* web_contents = GetAssociatedWebContents(); - CHECK(web_contents); BookmarkManagerPrivateDragEventRouter* router = BookmarkManagerPrivateDragEventRouter::FromWebContents(web_contents); diff --git a/chromium/chrome/browser/extensions/api/bookmark_manager_private/bookmark_manager_private_apitest.cc b/chromium/chrome/browser/extensions/api/bookmark_manager_private/bookmark_manager_private_apitest.cc index 35c4ad6bc47..ad4ac598a5b 100644 --- a/chromium/chrome/browser/extensions/api/bookmark_manager_private/bookmark_manager_private_apitest.cc +++ b/chromium/chrome/browser/extensions/api/bookmark_manager_private/bookmark_manager_private_apitest.cc @@ -26,6 +26,8 @@ using bookmarks::BookmarkModel; using bookmarks::BookmarkNode; +namespace extensions { + IN_PROC_BROWSER_TEST_F(ExtensionApiTest, BookmarkManager) { // Add managed bookmarks. Profile* profile = browser()->profile(); @@ -71,3 +73,5 @@ IN_PROC_BROWSER_TEST_F(ExtensionApiTest, BookmarkManagerEditDisabled) { ASSERT_TRUE(RunComponentExtensionTest("bookmark_manager/edit_disabled")) << message_; } + +} // namespace extensions diff --git a/chromium/chrome/browser/extensions/api/bookmarks/bookmark_apitest.cc b/chromium/chrome/browser/extensions/api/bookmarks/bookmark_apitest.cc index c4cdaf3aa3b..51335d49624 100644 --- a/chromium/chrome/browser/extensions/api/bookmarks/bookmark_apitest.cc +++ b/chromium/chrome/browser/extensions/api/bookmarks/bookmark_apitest.cc @@ -21,6 +21,8 @@ using bookmarks::BookmarkModel; +namespace extensions { + IN_PROC_BROWSER_TEST_F(ExtensionApiTest, Bookmarks) { // Add test managed bookmarks to verify that the bookmarks API can read them // and can't modify them. @@ -44,3 +46,5 @@ IN_PROC_BROWSER_TEST_F(ExtensionApiTest, Bookmarks) { ASSERT_TRUE(RunExtensionTest("bookmarks")) << message_; } + +} // namespace extensions diff --git a/chromium/chrome/browser/extensions/api/bookmarks/bookmarks_api.cc b/chromium/chrome/browser/extensions/api/bookmarks/bookmarks_api.cc index d45e3c8e17f..f092d098467 100644 --- a/chromium/chrome/browser/extensions/api/bookmarks/bookmarks_api.cc +++ b/chromium/chrome/browser/extensions/api/bookmarks/bookmarks_api.cc @@ -90,7 +90,7 @@ base::FilePath GetDefaultFilepathForBookmarkExport() { base::i18n::ReplaceIllegalCharactersInPath(&filename, '_'); base::FilePath default_path; - PathService::Get(chrome::DIR_USER_DOCUMENTS, &default_path); + base::PathService::Get(chrome::DIR_USER_DOCUMENTS, &default_path); return default_path.Append(filename); } @@ -733,7 +733,7 @@ void BookmarksIOFunction::ShowSelectFileDialog( // either FileSelectionCanceled, MultiFilesSelected, or FileSelected AddRef(); - WebContents* web_contents = GetAssociatedWebContents(); + WebContents* web_contents = GetSenderWebContents(); select_file_dialog_ = ui::SelectFileDialog::Create( this, std::make_unique<ChromeSelectFilePolicy>(web_contents)); diff --git a/chromium/chrome/browser/extensions/api/browsing_data/browsing_data_test.cc b/chromium/chrome/browser/extensions/api/browsing_data/browsing_data_test.cc index f0e724e64a3..aeea3eef7bb 100644 --- a/chromium/chrome/browser/extensions/api/browsing_data/browsing_data_test.cc +++ b/chromium/chrome/browser/extensions/api/browsing_data/browsing_data_test.cc @@ -348,6 +348,7 @@ IN_PROC_BROWSER_TEST_F(ExtensionBrowsingDataTest, RemoveBrowsingDataAll) { content::BrowsingDataRemover::DATA_TYPE_COOKIES | content::BrowsingDataRemover::DATA_TYPE_CHANNEL_IDS | (content::BrowsingDataRemover::DATA_TYPE_DOM_STORAGE & + ~content::BrowsingDataRemover::DATA_TYPE_BACKGROUND_FETCH & ~content::BrowsingDataRemover::DATA_TYPE_EMBEDDER_DOM_STORAGE) | content::BrowsingDataRemover::DATA_TYPE_CACHE | content::BrowsingDataRemover::DATA_TYPE_DOWNLOADS | @@ -548,6 +549,7 @@ IN_PROC_BROWSER_TEST_F(ExtensionBrowsingDataTest, SettingsFunctionSiteData) { (content::BrowsingDataRemover::DATA_TYPE_COOKIES | content::BrowsingDataRemover::DATA_TYPE_CHANNEL_IDS | content::BrowsingDataRemover::DATA_TYPE_DOM_STORAGE) & + ~content::BrowsingDataRemover::DATA_TYPE_BACKGROUND_FETCH & ~content::BrowsingDataRemover::DATA_TYPE_EMBEDDER_DOM_STORAGE; int supported_site_data = supported_site_data_except_plugins | @@ -579,6 +581,7 @@ IN_PROC_BROWSER_TEST_F(ExtensionBrowsingDataTest, SettingsFunctionAssorted) { (content::BrowsingDataRemover::DATA_TYPE_COOKIES | content::BrowsingDataRemover::DATA_TYPE_CHANNEL_IDS | content::BrowsingDataRemover::DATA_TYPE_DOM_STORAGE) & + ~content::BrowsingDataRemover::DATA_TYPE_BACKGROUND_FETCH & ~content::BrowsingDataRemover::DATA_TYPE_EMBEDDER_DOM_STORAGE; SetPrefsAndVerifySettings( diff --git a/chromium/chrome/browser/extensions/api/cast_streaming/OWNERS b/chromium/chrome/browser/extensions/api/cast_streaming/OWNERS index 41c70ee8aee..6234a6a3dc5 100644 --- a/chromium/chrome/browser/extensions/api/cast_streaming/OWNERS +++ b/chromium/chrome/browser/extensions/api/cast_streaming/OWNERS @@ -1,4 +1,4 @@ -hubbe@chromium.org miu@chromium.org +xjz@chromium.org # COMPONENT: Internals>Cast>Streaming diff --git a/chromium/chrome/browser/extensions/api/cast_streaming/cast_streaming_apitest.cc b/chromium/chrome/browser/extensions/api/cast_streaming/cast_streaming_apitest.cc index 9c15fa49d72..2b5a2595bc0 100644 --- a/chromium/chrome/browser/extensions/api/cast_streaming/cast_streaming_apitest.cc +++ b/chromium/chrome/browser/extensions/api/cast_streaming/cast_streaming_apitest.cc @@ -17,8 +17,10 @@ #include "base/strings/string_number_conversions.h" #include "base/strings/stringprintf.h" #include "base/threading/thread_restrictions.h" +#include "build/build_config.h" #include "chrome/browser/extensions/extension_apitest.h" #include "chrome/common/chrome_switches.h" +#include "content/public/common/content_features.h" #include "content/public/common/content_switches.h" #include "extensions/common/switches.h" #include "media/base/bind_to_current_loop.h" @@ -34,6 +36,7 @@ #include "net/base/rand_callback.h" #include "net/log/net_log_source.h" #include "net/socket/udp_server_socket.h" +#include "testing/gtest/include/gtest/gtest-param-test.h" #include "testing/gtest/include/gtest/gtest.h" using media::cast::test::GetFreeLocalPort; @@ -320,7 +323,23 @@ class TestPatternReceiver : public media::cast::InProcessReceiver { } // namespace -class CastStreamingApiTestWithPixelOutput : public CastStreamingApiTest { +class CastStreamingApiTestWithPixelOutput + : public CastStreamingApiTest, + public testing::WithParamInterface<bool> { + public: + CastStreamingApiTestWithPixelOutput() { + std::vector<base::Feature> audio_service_oop_features = { + features::kAudioServiceAudioStreams, + features::kAudioServiceOutOfProcess}; + if (GetParam()) { + // Force audio service out of process to enabled. + audio_service_features_.InitWithFeatures(audio_service_oop_features, {}); + } else { + // Force audio service out of process to disabled. + audio_service_features_.InitWithFeatures({}, audio_service_oop_features); + } + } + void SetUp() override { EnablePixelOutput(); CastStreamingApiTest::SetUp(); @@ -330,6 +349,9 @@ class CastStreamingApiTestWithPixelOutput : public CastStreamingApiTest { command_line->AppendSwitchASCII(::switches::kWindowSize, "128,128"); CastStreamingApiTest::SetUpCommandLine(command_line); } + + private: + base::test::ScopedFeatureList audio_service_features_; }; // Tests the Cast streaming API and its basic functionality end-to-end. An @@ -337,12 +359,13 @@ class CastStreamingApiTestWithPixelOutput : public CastStreamingApiTest { // use the API to send it out. At the same time, this test launches an // in-process Cast receiver, listening on a localhost UDP socket, to receive the // content and check whether it matches expectations. -#if defined(NDEBUG) +#if defined(NDEBUG) && !defined(OS_MACOSX) #define MAYBE_EndToEnd EndToEnd #else +// Flaky on Mac: https://crbug.com/841387 #define MAYBE_EndToEnd DISABLED_EndToEnd // crbug.com/396413 #endif -IN_PROC_BROWSER_TEST_F(CastStreamingApiTestWithPixelOutput, MAYBE_EndToEnd) { +IN_PROC_BROWSER_TEST_P(CastStreamingApiTestWithPixelOutput, MAYBE_EndToEnd) { std::unique_ptr<net::UDPServerSocket> receive_socket( new net::UDPServerSocket(NULL, net::NetLogSource())); receive_socket->AllowAddressReuse(); @@ -390,8 +413,33 @@ IN_PROC_BROWSER_TEST_F(CastStreamingApiTestWithPixelOutput, MAYBE_EndToEnd) { cast_environment->Shutdown(); } -IN_PROC_BROWSER_TEST_F(CastStreamingApiTestWithPixelOutput, RtpStreamError) { +#if !defined(OS_MACOSX) +#define MAYBE_RtpStreamError RtpStreamError +#else +// Flaky on Mac https://crbug.com/841986 +#define MAYBE_RtpStreamError DISABLED_RtpStreamError +#endif +IN_PROC_BROWSER_TEST_P(CastStreamingApiTestWithPixelOutput, + MAYBE_RtpStreamError) { ASSERT_TRUE(RunExtensionSubtest("cast_streaming", "rtp_stream_error.html")); } +// We run these tests with the audio service both in and out of the the browser +// process to have waterfall coverage while the feature rolls out. It should be +// removed after launch. Note: CastStreamingApiTestWithPixelOutput.EndToEnd is +// the only integration test exercising audio service loopback streams, so it's +// a very important test to have. +#if (defined(OS_LINUX) && !defined(OS_CHROMEOS)) || defined(OS_MACOSX) || \ + defined(OS_WIN) +// Supported platforms. +INSTANTIATE_TEST_CASE_P(, + CastStreamingApiTestWithPixelOutput, + ::testing::Bool()); +#else +// Platforms where the out of process audio service isn't supported +INSTANTIATE_TEST_CASE_P(, + CastStreamingApiTestWithPixelOutput, + ::testing::Values(false)); +#endif + } // namespace extensions diff --git a/chromium/chrome/browser/extensions/api/cast_streaming/performance_test.cc b/chromium/chrome/browser/extensions/api/cast_streaming/performance_test.cc index 91d65b3d1f6..4f627788518 100644 --- a/chromium/chrome/browser/extensions/api/cast_streaming/performance_test.cc +++ b/chromium/chrome/browser/extensions/api/cast_streaming/performance_test.cc @@ -345,9 +345,8 @@ class TestPatternReceiver : public media::cast::InProcessReceiver { DISALLOW_COPY_AND_ASSIGN(TestPatternReceiver); }; -class CastV2PerformanceTest - : public ExtensionApiTest, - public testing::WithParamInterface<int> { +class CastV2PerformanceTest : public extensions::ExtensionApiTest, + public testing::WithParamInterface<int> { public: CastV2PerformanceTest() {} @@ -401,7 +400,7 @@ class CastV2PerformanceTest EnablePixelOutput(); if (!HasFlag(kUseGpu)) UseSoftwareCompositing(); - ExtensionApiTest::SetUp(); + extensions::ExtensionApiTest::SetUp(); } void SetUpCommandLine(base::CommandLine* command_line) override { @@ -424,7 +423,7 @@ class CastV2PerformanceTest extensions::switches::kWhitelistedExtensionID, kExtensionId); - ExtensionApiTest::SetUpCommandLine(command_line); + extensions::ExtensionApiTest::SetUpCommandLine(command_line); } void GetTraceEvents(trace_analyzer::TraceAnalyzer* analyzer, diff --git a/chromium/chrome/browser/extensions/api/certificate_provider/certificate_provider_apitest.cc b/chromium/chrome/browser/extensions/api/certificate_provider/certificate_provider_apitest.cc index 01671bd64be..62ab1eae2b9 100644 --- a/chromium/chrome/browser/extensions/api/certificate_provider/certificate_provider_apitest.cc +++ b/chromium/chrome/browser/extensions/api/certificate_provider/certificate_provider_apitest.cc @@ -143,7 +143,7 @@ void EnterWrongPin(chromeos::CertificateProviderService* service) { EXPECT_EQ(SK_ColorRED, view->error_label_for_testing()->enabled_color()); } -class CertificateProviderApiTest : public ExtensionApiTest { +class CertificateProviderApiTest : public extensions::ExtensionApiTest { public: CertificateProviderApiTest() {} @@ -152,11 +152,11 @@ class CertificateProviderApiTest : public ExtensionApiTest { .WillRepeatedly(Return(true)); policy::BrowserPolicyConnector::SetPolicyProviderForTesting(&provider_); - ExtensionApiTest::SetUpInProcessBrowserTestFixture(); + extensions::ExtensionApiTest::SetUpInProcessBrowserTestFixture(); } void SetUpOnMainThread() override { - ExtensionApiTest::SetUpOnMainThread(); + extensions::ExtensionApiTest::SetUpOnMainThread(); // Set up the AutoSelectCertificateForUrls policy to avoid the client // certificate selection dialog. const std::string autoselect_pattern = diff --git a/chromium/chrome/browser/extensions/api/chrome_extensions_api_client.cc b/chromium/chrome/browser/extensions/api/chrome_extensions_api_client.cc index bd9b3d8ba8e..c1a95cdfe0d 100644 --- a/chromium/chrome/browser/extensions/api/chrome_extensions_api_client.cc +++ b/chromium/chrome/browser/extensions/api/chrome_extensions_api_client.cc @@ -32,13 +32,16 @@ #include "chrome/browser/guest_view/mime_handler_view/chrome_mime_handler_view_guest_delegate.h" #include "chrome/browser/guest_view/web_view/chrome_web_view_guest_delegate.h" #include "chrome/browser/guest_view/web_view/chrome_web_view_permission_helper_delegate.h" +#include "chrome/browser/search/instant_io_context.h" #include "chrome/browser/ui/pdf/chrome_pdf_web_contents_helper_client.h" #include "chrome/browser/ui/webui/devtools_ui.h" +#include "chrome/common/webui_url_constants.h" #include "components/pdf/browser/pdf_web_contents_helper.h" #include "components/signin/core/browser/signin_header_helper.h" #include "content/public/browser/browser_context.h" #include "content/public/browser/browser_thread.h" #include "extensions/browser/api/virtual_keyboard_private/virtual_keyboard_delegate.h" +#include "extensions/browser/api/web_request/web_request_info.h" #include "extensions/browser/guest_view/web_view/web_view_guest.h" #include "extensions/browser/guest_view/web_view/web_view_permission_helper.h" #include "google_apis/gaia/gaia_urls.h" @@ -105,8 +108,28 @@ bool ChromeExtensionsAPIClient::ShouldHideResponseHeader( } bool ChromeExtensionsAPIClient::ShouldHideBrowserNetworkRequest( - const GURL& url) const { - return DevToolsUI::IsFrontendResourceURL(url); + const WebRequestInfo& request) const { + DCHECK_CURRENTLY_ON(content::BrowserThread::IO); + + // Exclude main frame navigation requests. + bool is_browser_request = request.render_process_id == -1 && + request.type != content::RESOURCE_TYPE_MAIN_FRAME; + + // Hide requests made by the Devtools frontend. + bool is_sensitive_request = + is_browser_request && DevToolsUI::IsFrontendResourceURL(request.url); + + // Hide requests made by the browser on behalf of the NTP. + is_sensitive_request |= + (is_browser_request && + request.initiator == + url::Origin::Create(GURL(chrome::kChromeUINewTabURL))); + + // Hide requests made by the NTP Instant renderer. + is_sensitive_request |= InstantIOContext::IsInstantProcess( + request.resource_context, request.render_process_id); + + return is_sensitive_request; } AppViewGuestDelegate* ChromeExtensionsAPIClient::CreateAppViewGuestDelegate() diff --git a/chromium/chrome/browser/extensions/api/chrome_extensions_api_client.h b/chromium/chrome/browser/extensions/api/chrome_extensions_api_client.h index dbe7a3e7b35..a99acde774b 100644 --- a/chromium/chrome/browser/extensions/api/chrome_extensions_api_client.h +++ b/chromium/chrome/browser/extensions/api/chrome_extensions_api_client.h @@ -32,7 +32,8 @@ class ChromeExtensionsAPIClient : public ExtensionsAPIClient { override; bool ShouldHideResponseHeader(const GURL& url, const std::string& header_name) const override; - bool ShouldHideBrowserNetworkRequest(const GURL& url) const override; + bool ShouldHideBrowserNetworkRequest( + const WebRequestInfo& request) const override; AppViewGuestDelegate* CreateAppViewGuestDelegate() const override; ExtensionOptionsGuestDelegate* CreateExtensionOptionsGuestDelegate( ExtensionOptionsGuest* guest) const override; diff --git a/chromium/chrome/browser/extensions/api/chrome_extensions_api_client_unittest.cc b/chromium/chrome/browser/extensions/api/chrome_extensions_api_client_unittest.cc index 8e2738c02a5..45762a579c3 100644 --- a/chromium/chrome/browser/extensions/api/chrome_extensions_api_client_unittest.cc +++ b/chromium/chrome/browser/extensions/api/chrome_extensions_api_client_unittest.cc @@ -4,13 +4,26 @@ #include "chrome/browser/extensions/api/chrome_extensions_api_client.h" +#include "base/macros.h" +#include "chrome/common/webui_url_constants.h" +#include "content/public/test/test_browser_thread_bundle.h" +#include "extensions/browser/api/web_request/web_request_info.h" #include "google_apis/gaia/gaia_urls.h" #include "testing/gtest/include/gtest/gtest.h" #include "url/gurl.h" namespace extensions { -TEST(TestChromeExtensionsAPIClient, ShouldHideResponseHeader) { +class ChromeExtensionsAPIClientTest : public testing::Test { + public: + ChromeExtensionsAPIClientTest() = default; + + private: + content::TestBrowserThreadBundle thread_bundle_; + DISALLOW_COPY_AND_ASSIGN(ChromeExtensionsAPIClientTest); +}; + +TEST_F(ChromeExtensionsAPIClientTest, ShouldHideResponseHeader) { ChromeExtensionsAPIClient client; EXPECT_TRUE(client.ShouldHideResponseHeader( GaiaUrls::GetInstance()->gaia_url(), "X-Chrome-ID-Consistency-Response")); @@ -22,4 +35,26 @@ TEST(TestChromeExtensionsAPIClient, ShouldHideResponseHeader) { GaiaUrls::GetInstance()->gaia_url(), "Google-Accounts-SignOut")); } +TEST_F(ChromeExtensionsAPIClientTest, ShouldHideBrowserNetworkRequest) { + ChromeExtensionsAPIClient client; + + // Requests made by the browser with chrome://newtab as its initiator should + // not be visible to extensions. + WebRequestInfo request; + request.url = GURL("https://example.com/script.js"); + request.initiator = url::Origin::Create(GURL(chrome::kChromeUINewTabURL)); + request.render_process_id = -1; + request.type = content::ResourceType::RESOURCE_TYPE_SCRIPT; + EXPECT_TRUE(client.ShouldHideBrowserNetworkRequest(request)); + + // Main frame requests should always be visible to extensions. + request.type = content::ResourceType::RESOURCE_TYPE_MAIN_FRAME; + EXPECT_FALSE(client.ShouldHideBrowserNetworkRequest(request)); + + // Similar requests made by the renderer should be visible to extensions. + request.type = content::ResourceType::RESOURCE_TYPE_SCRIPT; + request.render_process_id = 2; + EXPECT_FALSE(client.ShouldHideBrowserNetworkRequest(request)); +} + } // namespace extensions diff --git a/chromium/chrome/browser/extensions/api/cloud_print_private/cloud_print_private_api.cc b/chromium/chrome/browser/extensions/api/cloud_print_private/cloud_print_private_api.cc index 3547cd4ce23..193801d9a5f 100644 --- a/chromium/chrome/browser/extensions/api/cloud_print_private/cloud_print_private_api.cc +++ b/chromium/chrome/browser/extensions/api/cloud_print_private/cloud_print_private_api.cc @@ -9,6 +9,7 @@ #include "chrome/browser/printing/cloud_print/cloud_print_proxy_service.h" #include "chrome/browser/printing/cloud_print/cloud_print_proxy_service_factory.h" +#include "chrome/browser/profiles/profile.h" #include "chrome/common/extensions/api/cloud_print_private.h" #include "google_apis/google_api_keys.h" #include "net/base/network_interfaces.h" @@ -44,31 +45,30 @@ CloudPrintPrivateSetupConnectorFunction:: ~CloudPrintPrivateSetupConnectorFunction() { } -bool CloudPrintPrivateSetupConnectorFunction::RunAsync() { +ExtensionFunction::ResponseAction +CloudPrintPrivateSetupConnectorFunction::Run() { using api::cloud_print_private::SetupConnector::Params; std::unique_ptr<Params> params(Params::Create(*args_)); if (CloudPrintTestsDelegate::Get()) { CloudPrintTestsDelegate::Get()->SetupConnector( params->user_email, params->robot_email, params->credentials, params->user_settings); - SendResponse(true); - return true; + return RespondNow(NoArguments()); } base::Value user_settings_value = base::Value::FromUniquePtrValue(params->user_settings.ToValue()); CloudPrintProxyService* service = - CloudPrintProxyServiceFactory::GetForProfile(GetProfile()); + CloudPrintProxyServiceFactory::GetForProfile( + Profile::FromBrowserContext(browser_context())); if (!service) { - error_ = kErrorIncognito; - return false; + return RespondNow(Error(kErrorIncognito)); } service->EnableForUserWithRobot(params->credentials, params->robot_email, params->user_email, std::move(user_settings_value)); - SendResponse(true); - return true; + return RespondNow(NoArguments()); } CloudPrintPrivateGetHostNameFunction::CloudPrintPrivateGetHostNameFunction() { @@ -77,13 +77,11 @@ CloudPrintPrivateGetHostNameFunction::CloudPrintPrivateGetHostNameFunction() { CloudPrintPrivateGetHostNameFunction::~CloudPrintPrivateGetHostNameFunction() { } -bool CloudPrintPrivateGetHostNameFunction::RunAsync() { - SetResult(std::make_unique<base::Value>( +ExtensionFunction::ResponseAction CloudPrintPrivateGetHostNameFunction::Run() { + return RespondNow(OneArgument(std::make_unique<base::Value>( CloudPrintTestsDelegate::Get() ? CloudPrintTestsDelegate::Get()->GetHostName() - : net::GetHostName())); - SendResponse(true); - return true; + : net::GetHostName()))); } CloudPrintPrivateGetPrintersFunction::CloudPrintPrivateGetPrintersFunction() { @@ -94,25 +92,28 @@ CloudPrintPrivateGetPrintersFunction::~CloudPrintPrivateGetPrintersFunction() { void CloudPrintPrivateGetPrintersFunction::SendResults( const std::vector<std::string>& printers) { - results_ = api::cloud_print_private::GetPrinters::Results::Create(printers); - SendResponse(true); + Respond(ArgumentList( + api::cloud_print_private::GetPrinters::Results::Create(printers))); } -bool CloudPrintPrivateGetPrintersFunction::RunAsync() { +ExtensionFunction::ResponseAction CloudPrintPrivateGetPrintersFunction::Run() { if (CloudPrintTestsDelegate::Get()) { - SendResults(CloudPrintTestsDelegate::Get()->GetPrinters()); - return true; + return RespondNow( + ArgumentList(api::cloud_print_private::GetPrinters::Results::Create( + CloudPrintTestsDelegate::Get()->GetPrinters()))); } CloudPrintProxyService* service = - CloudPrintProxyServiceFactory::GetForProfile(GetProfile()); - if (!service) { - error_ = kErrorIncognito; - return false; - } + CloudPrintProxyServiceFactory::GetForProfile( + Profile::FromBrowserContext(browser_context())); + if (!service) + return RespondNow(Error(kErrorIncognito)); + + // TODO(https://crbug.com/845250): CloudPrintProxyService::GetPrinters() may + // not invoke the callback, which means this function may never respond. service->GetPrinters( base::Bind(&CloudPrintPrivateGetPrintersFunction::SendResults, this)); - return true; + return RespondLater(); } @@ -122,13 +123,11 @@ CloudPrintPrivateGetClientIdFunction::CloudPrintPrivateGetClientIdFunction() { CloudPrintPrivateGetClientIdFunction::~CloudPrintPrivateGetClientIdFunction() { } -bool CloudPrintPrivateGetClientIdFunction::RunAsync() { - SetResult(std::make_unique<base::Value>( +ExtensionFunction::ResponseAction CloudPrintPrivateGetClientIdFunction::Run() { + return RespondNow(OneArgument(std::make_unique<base::Value>( CloudPrintTestsDelegate::Get() ? CloudPrintTestsDelegate::Get()->GetClientId() - : google_apis::GetOAuth2ClientID(google_apis::CLIENT_CLOUD_PRINT))); - SendResponse(true); - return true; + : google_apis::GetOAuth2ClientID(google_apis::CLIENT_CLOUD_PRINT)))); } } // namespace extensions diff --git a/chromium/chrome/browser/extensions/api/cloud_print_private/cloud_print_private_api.h b/chromium/chrome/browser/extensions/api/cloud_print_private/cloud_print_private_api.h index 0c1e3b60ef6..4305893e576 100644 --- a/chromium/chrome/browser/extensions/api/cloud_print_private/cloud_print_private_api.h +++ b/chromium/chrome/browser/extensions/api/cloud_print_private/cloud_print_private_api.h @@ -9,7 +9,7 @@ #include <vector> #include "build/build_config.h" -#include "chrome/browser/extensions/chrome_extension_function.h" +#include "extensions/browser/extension_function.h" #include "printing/buildflags/buildflags.h" #if !BUILDFLAG(ENABLE_PRINT_PREVIEW) || defined(OS_CHROMEOS) @@ -49,7 +49,7 @@ class CloudPrintTestsDelegate { }; class CloudPrintPrivateSetupConnectorFunction - : public ChromeAsyncExtensionFunction { + : public UIThreadExtensionFunction { public: DECLARE_EXTENSION_FUNCTION("cloudPrintPrivate.setupConnector", CLOUDPRINTPRIVATE_SETUPCONNECTOR) @@ -60,11 +60,10 @@ class CloudPrintPrivateSetupConnectorFunction ~CloudPrintPrivateSetupConnectorFunction() override; // ExtensionFunction: - bool RunAsync() override; + ResponseAction Run() override; }; -class CloudPrintPrivateGetHostNameFunction - : public ChromeAsyncExtensionFunction { +class CloudPrintPrivateGetHostNameFunction : public UIThreadExtensionFunction { public: DECLARE_EXTENSION_FUNCTION("cloudPrintPrivate.getHostName", CLOUDPRINTPRIVATE_GETHOSTNAME) @@ -75,11 +74,10 @@ class CloudPrintPrivateGetHostNameFunction ~CloudPrintPrivateGetHostNameFunction() override; // ExtensionFunction: - bool RunAsync() override; + ResponseAction Run() override; }; -class CloudPrintPrivateGetPrintersFunction - : public ChromeAsyncExtensionFunction { +class CloudPrintPrivateGetPrintersFunction : public UIThreadExtensionFunction { public: DECLARE_EXTENSION_FUNCTION("cloudPrintPrivate.getPrinters", CLOUDPRINTPRIVATE_GETPRINTERS) @@ -93,11 +91,10 @@ class CloudPrintPrivateGetPrintersFunction void SendResults(const std::vector<std::string>& printers); // ExtensionFunction: - bool RunAsync() override; + ResponseAction Run() override; }; -class CloudPrintPrivateGetClientIdFunction - : public ChromeAsyncExtensionFunction { +class CloudPrintPrivateGetClientIdFunction : public UIThreadExtensionFunction { public: DECLARE_EXTENSION_FUNCTION("cloudPrintPrivate.getClientId", CLOUDPRINTPRIVATE_GETCLIENTID); @@ -108,7 +105,7 @@ class CloudPrintPrivateGetClientIdFunction ~CloudPrintPrivateGetClientIdFunction() override; // ExtensionFunction: - bool RunAsync() override; + ResponseAction Run() override; }; } // namespace extensions diff --git a/chromium/chrome/browser/extensions/api/cloud_print_private/cloud_print_private_apitest.cc b/chromium/chrome/browser/extensions/api/cloud_print_private/cloud_print_private_apitest.cc index 7145f7ca185..a00d71d51b3 100644 --- a/chromium/chrome/browser/extensions/api/cloud_print_private/cloud_print_private_apitest.cc +++ b/chromium/chrome/browser/extensions/api/cloud_print_private/cloud_print_private_apitest.cc @@ -22,10 +22,10 @@ using ::testing::Return; using ::testing::_; // A base class for tests below. -class ExtensionCloudPrintPrivateApiTest : public ExtensionApiTest { +class ExtensionCloudPrintPrivateApiTest : public extensions::ExtensionApiTest { public: void SetUpCommandLine(base::CommandLine* command_line) override { - ExtensionApiTest::SetUpCommandLine(command_line); + extensions::ExtensionApiTest::SetUpCommandLine(command_line); command_line->AppendSwitchASCII( switches::kCloudPrintURL, "http://www.cloudprintapp.com/extensions/api_test/" @@ -33,7 +33,7 @@ class ExtensionCloudPrintPrivateApiTest : public ExtensionApiTest { } void SetUpOnMainThread() override { - ExtensionApiTest::SetUpOnMainThread(); + extensions::ExtensionApiTest::SetUpOnMainThread(); // Start up the test server and get us ready for calling the install // API functions. host_resolver()->AddRule("www.cloudprintapp.com", "127.0.0.1"); diff --git a/chromium/chrome/browser/extensions/api/command_line_private/command_line_private_apitest.cc b/chromium/chrome/browser/extensions/api/command_line_private/command_line_private_apitest.cc index 36de0cea254..cdbd1f1bf16 100644 --- a/chromium/chrome/browser/extensions/api/command_line_private/command_line_private_apitest.cc +++ b/chromium/chrome/browser/extensions/api/command_line_private/command_line_private_apitest.cc @@ -11,9 +11,9 @@ namespace { const char kTestCommandLineSwitch[] = "command-line-private-api-test-foo"; } // namespace -class CommandLinePrivateApiTest : public ExtensionApiTest { +class CommandLinePrivateApiTest : public extensions::ExtensionApiTest { void SetUpCommandLine(base::CommandLine* command_line) override { - ExtensionApiTest::SetUpCommandLine(command_line); + extensions::ExtensionApiTest::SetUpCommandLine(command_line); command_line->AppendSwitch(kTestCommandLineSwitch); } }; diff --git a/chromium/chrome/browser/extensions/api/cookies/cookies_api.cc b/chromium/chrome/browser/extensions/api/cookies/cookies_api.cc index 13790f2f9eb..639053961b0 100644 --- a/chromium/chrome/browser/extensions/api/cookies/cookies_api.cc +++ b/chromium/chrome/browser/extensions/api/cookies/cookies_api.cc @@ -82,18 +82,7 @@ network::mojom::CookieManager* ParseStoreCookieManager( return nullptr; } } else { - // The store ID was not specified; use the current execution context's - // cookie store by default. - // GetCurrentBrowser() already takes into account incognito settings. - // TODO(rdevlin.cronin): Relying on the current execution context is - // almost never the right answer; clean this up. - Browser* current_browser = - ChromeExtensionFunctionDetails(function).GetCurrentBrowser(); - if (!current_browser) { - function->SetError(keys::kNoCookieStoreFoundError); - return nullptr; - } - store_profile = current_browser->profile(); + store_profile = function->GetProfile(); *store_id = cookies_helpers::GetStoreIdFromProfile(store_profile); } @@ -400,6 +389,16 @@ void CookiesSetFunction::GetCookieListCallback( DCHECK_CURRENTLY_ON(BrowserThread::UI); DCHECK_EQ(SET_COMPLETED, state_); state_ = GET_COMPLETED; + + if (!success_) { + std::string name = parsed_args_->details.name.get() + ? *parsed_args_->details.name + : std::string(); + error_ = ErrorUtils::FormatErrorMessage(keys::kCookieSetFailedError, name); + SendResponse(false); + return; + } + for (const net::CanonicalCookie& cookie : cookie_list) { // Return the first matching cookie. Relies on the fact that the // CookieMonster returns them in canonical order (longest path, then @@ -415,15 +414,7 @@ void CookiesSetFunction::GetCookieListCallback( } } - if (!success_) { - std::string name = - parsed_args_->details.name.get() ? *parsed_args_->details.name - : std::string(); - // TODO(rdevlin.cronin): Avoid setting both error_ and results_ in the - // same call. - error_ = ErrorUtils::FormatErrorMessage(keys::kCookieSetFailedError, name); - } - SendResponse(success_); + SendResponse(true); } CookiesRemoveFunction::CookiesRemoveFunction() { diff --git a/chromium/chrome/browser/extensions/api/dashboard_private/dashboard_private_api.cc b/chromium/chrome/browser/extensions/api/dashboard_private/dashboard_private_api.cc index c2bb77b851e..662509209a3 100644 --- a/chromium/chrome/browser/extensions/api/dashboard_private/dashboard_private_api.cc +++ b/chromium/chrome/browser/extensions/api/dashboard_private/dashboard_private_api.cc @@ -124,7 +124,7 @@ void DashboardPrivateShowPermissionPromptForDelegatedInstallFunction:: return; } - content::WebContents* web_contents = GetAssociatedWebContents(); + content::WebContents* web_contents = GetSenderWebContents(); if (!web_contents) { // The browser window has gone away. Respond(BuildResponse(api::dashboard_private::RESULT_USER_CANCELLED, diff --git a/chromium/chrome/browser/extensions/api/data_reduction_proxy/data_reduction_proxy_api.cc b/chromium/chrome/browser/extensions/api/data_reduction_proxy/data_reduction_proxy_api.cc index 56b6ad30049..0b33e5f5b76 100644 --- a/chromium/chrome/browser/extensions/api/data_reduction_proxy/data_reduction_proxy_api.cc +++ b/chromium/chrome/browser/extensions/api/data_reduction_proxy/data_reduction_proxy_api.cc @@ -22,8 +22,11 @@ DataReductionProxyClearDataSavingsFunction::Run() { data_reduction_proxy::DataReductionProxySettings* settings = DataReductionProxyChromeSettingsFactory::GetForBrowserContext( browser_context()); - settings->data_reduction_proxy_service()->compression_stats()-> - ClearDataSavingStatistics(); + settings->data_reduction_proxy_service() + ->compression_stats() + ->ClearDataSavingStatistics( + data_reduction_proxy::DataReductionProxySavingsClearedReason:: + USER_ACTION_EXTENSION); return RespondNow(NoArguments()); } diff --git a/chromium/chrome/browser/extensions/api/debugger/debugger_api.cc b/chromium/chrome/browser/extensions/api/debugger/debugger_api.cc index 849602a866f..a163e7751bc 100644 --- a/chromium/chrome/browser/extensions/api/debugger/debugger_api.cc +++ b/chromium/chrome/browser/extensions/api/debugger/debugger_api.cc @@ -368,7 +368,7 @@ bool DebuggerFunction::InitAgentHost() { if (result && web_contents) { // TODO(rdevlin.cronin) This should definitely be GetLastCommittedURL(). GURL url = web_contents->GetVisibleURL(); - if (PermissionsData::IsRestrictedUrl(url, extension(), &error_)) + if (extension()->permissions_data()->IsRestrictedUrl(url, &error_)) return false; agent_host_ = DevToolsAgentHost::GetOrCreateFor(web_contents); } @@ -377,9 +377,8 @@ bool DebuggerFunction::InitAgentHost() { ProcessManager::Get(GetProfile()) ->GetBackgroundHostForExtension(*debuggee_.extension_id); if (extension_host) { - if (PermissionsData::IsRestrictedUrl(extension_host->GetURL(), - extension(), - &error_)) { + if (extension()->permissions_data()->IsRestrictedUrl( + extension_host->GetURL(), &error_)) { return false; } agent_host_ = @@ -388,9 +387,8 @@ bool DebuggerFunction::InitAgentHost() { } else if (debuggee_.target_id) { agent_host_ = DevToolsAgentHost::GetForId(*debuggee_.target_id); if (agent_host_.get()) { - if (PermissionsData::IsRestrictedUrl(agent_host_->GetURL(), - extension(), - &error_)) { + if (extension()->permissions_data()->IsRestrictedUrl( + agent_host_->GetURL(), &error_)) { agent_host_ = nullptr; return false; } diff --git a/chromium/chrome/browser/extensions/api/debugger/debugger_apitest.cc b/chromium/chrome/browser/extensions/api/debugger/debugger_apitest.cc index 28f88e20e62..bdd6e19bf5e 100644 --- a/chromium/chrome/browser/extensions/api/debugger/debugger_apitest.cc +++ b/chromium/chrome/browser/extensions/api/debugger/debugger_apitest.cc @@ -164,8 +164,8 @@ IN_PROC_BROWSER_TEST_F(DebuggerApiTest, DebuggerNotAllowedOnOtherExtensionPages) { // Load another arbitrary extension with an associated resource (popup.html). base::FilePath path; - ASSERT_TRUE(PathService::Get(chrome::DIR_TEST_DATA, &path)); - path = path.AppendASCII("extensions").AppendASCII("good_unpacked"); + ASSERT_TRUE(base::PathService::Get(chrome::DIR_TEST_DATA, &path)); + path = path.AppendASCII("extensions").AppendASCII("simple_with_popup"); const Extension* another_extension = LoadExtension(path); ASSERT_TRUE(another_extension); diff --git a/chromium/chrome/browser/extensions/api/debugger/debugger_extension_apitest.cc b/chromium/chrome/browser/extensions/api/debugger/debugger_extension_apitest.cc index a8a3ef89437..efdbfbebade 100644 --- a/chromium/chrome/browser/extensions/api/debugger/debugger_extension_apitest.cc +++ b/chromium/chrome/browser/extensions/api/debugger/debugger_extension_apitest.cc @@ -7,10 +7,10 @@ #include "chrome/common/chrome_switches.h" #include "extensions/common/switches.h" -class ExtensionApiTestWithSwitch : public ExtensionApiTest { +class ExtensionApiTestWithSwitch : public extensions::ExtensionApiTest { public: void SetUpCommandLine(base::CommandLine* command_line) override { - ExtensionApiTest::SetUpCommandLine(command_line); + extensions::ExtensionApiTest::SetUpCommandLine(command_line); command_line->AppendSwitch(switches::kSilentDebuggerExtensionAPI); command_line->AppendSwitch(extensions::switches::kExtensionsOnChromeURLs); } diff --git a/chromium/chrome/browser/extensions/api/debugger/extension_dev_tools_infobar.cc b/chromium/chrome/browser/extensions/api/debugger/extension_dev_tools_infobar.cc index 41b8582f234..fdc19ab8c55 100644 --- a/chromium/chrome/browser/extensions/api/debugger/extension_dev_tools_infobar.cc +++ b/chromium/chrome/browser/extensions/api/debugger/extension_dev_tools_infobar.cc @@ -30,6 +30,8 @@ class ExtensionDevToolsInfoBarDelegate : public ConfirmInfoBarDelegate { bool ShouldExpire(const NavigationDetails& details) const override; void InfoBarDismissed() override; base::string16 GetMessageText() const override; + gfx::ElideBehavior GetMessageElideBehavior() const override; + int GetButtons() const override; bool Cancel() override; @@ -69,6 +71,14 @@ base::string16 ExtensionDevToolsInfoBarDelegate::GetMessageText() const { return l10n_util::GetStringFUTF16(IDS_DEV_TOOLS_INFOBAR_LABEL, client_name_); } +gfx::ElideBehavior ExtensionDevToolsInfoBarDelegate::GetMessageElideBehavior() + const { + // The important part of the message text above is at the end: + // "... is debugging the browser". If the extension name is very long, + // we'd rather truncate it instead. See https://crbug.com/823194. + return gfx::ELIDE_HEAD; +} + int ExtensionDevToolsInfoBarDelegate::GetButtons() const { return BUTTON_CANCEL; } diff --git a/chromium/chrome/browser/extensions/api/declarative_content/declarative_content_apitest.cc b/chromium/chrome/browser/extensions/api/declarative_content/declarative_content_apitest.cc index 4f2b43e14fd..a0660161c16 100644 --- a/chromium/chrome/browser/extensions/api/declarative_content/declarative_content_apitest.cc +++ b/chromium/chrome/browser/extensions/api/declarative_content/declarative_content_apitest.cc @@ -841,9 +841,9 @@ IN_PROC_BROWSER_TEST_F(DeclarativeContentApiTest, WebContentsWithoutTabAddedNotificationAtOnLoaded) { // Add a web contents to the tab strip in a way that doesn't trigger // NOTIFICATION_TAB_ADDED. - content::WebContents* contents = content::WebContents::Create( + std::unique_ptr<content::WebContents> contents = content::WebContents::Create( content::WebContents::CreateParams(profile())); - browser()->tab_strip_model()->AppendWebContents(contents, false); + browser()->tab_strip_model()->AppendWebContents(std::move(contents), false); // The actual extension contents don't matter here -- we're just looking to // trigger OnExtensionLoaded. @@ -868,8 +868,8 @@ IN_PROC_BROWSER_TEST_F(DeclarativeContentApiTest, browser()->tab_strip_model()->GetWebContentsAt(0); AddTabAtIndex(1, GURL("http://test2/"), ui::PAGE_TRANSITION_LINK); - std::unique_ptr<content::WebContents> tab2( - browser()->tab_strip_model()->GetWebContentsAt(1)); + content::WebContents* tab2 = + browser()->tab_strip_model()->GetWebContentsAt(1); // Add a rule matching the second tab. const std::string kAddTestRules = @@ -886,8 +886,7 @@ IN_PROC_BROWSER_TEST_F(DeclarativeContentApiTest, "}], 'add_rules');\n"; EXPECT_EQ("add_rules", ExecuteScriptInBackgroundPage(extension->id(), kAddTestRules)); - EXPECT_TRUE(page_action->GetIsVisible( - ExtensionTabUtil::GetTabId(tab2.get()))); + EXPECT_TRUE(page_action->GetIsVisible(ExtensionTabUtil::GetTabId(tab2))); // Remove the rule. const std::string kRemoveTestRule1 = "removeRule('2', 'remove_rule1');\n"; @@ -896,7 +895,8 @@ IN_PROC_BROWSER_TEST_F(DeclarativeContentApiTest, // Remove the second tab, then trigger a rule evaluation for the remaining // tab. - tab2.reset(); + browser()->tab_strip_model()->DetachWebContentsAt( + browser()->tab_strip_model()->GetIndexOfWebContents(tab2)); NavigateInRenderer(tab1, GURL("http://test1/")); EXPECT_TRUE(page_action->GetIsVisible(ExtensionTabUtil::GetTabId(tab1))); } diff --git a/chromium/chrome/browser/extensions/api/declarative_net_request/declarative_net_request_apitest.cc b/chromium/chrome/browser/extensions/api/declarative_net_request/declarative_net_request_apitest.cc index e46d400da4d..97ade6a7f58 100644 --- a/chromium/chrome/browser/extensions/api/declarative_net_request/declarative_net_request_apitest.cc +++ b/chromium/chrome/browser/extensions/api/declarative_net_request/declarative_net_request_apitest.cc @@ -12,14 +12,14 @@ namespace { -class DeclarativeNetRequestAPItest : public ExtensionApiTest { +class DeclarativeNetRequestAPItest : public extensions::ExtensionApiTest { public: DeclarativeNetRequestAPItest() {} protected: // ExtensionApiTest override. void SetUpOnMainThread() override { - ExtensionApiTest::SetUpOnMainThread(); + extensions::ExtensionApiTest::SetUpOnMainThread(); base::FilePath test_data_dir = test_data_dir_.AppendASCII("declarative_net_request"); diff --git a/chromium/chrome/browser/extensions/api/declarative_net_request/declarative_net_request_browsertest.cc b/chromium/chrome/browser/extensions/api/declarative_net_request/declarative_net_request_browsertest.cc index 13840d16ecd..8f7580f1594 100644 --- a/chromium/chrome/browser/extensions/api/declarative_net_request/declarative_net_request_browsertest.cc +++ b/chromium/chrome/browser/extensions/api/declarative_net_request/declarative_net_request_browsertest.cc @@ -6,12 +6,16 @@ #include <algorithm> #include <memory> +#include <set> +#include <vector> #include "base/files/file_util.h" #include "base/files/scoped_temp_dir.h" +#include "base/json/json_string_value_serializer.h" #include "base/macros.h" #include "base/memory/scoped_refptr.h" #include "base/path_service.h" +#include "base/rand_util.h" #include "base/test/histogram_tester.h" #include "base/threading/thread_restrictions.h" #include "base/values.h" @@ -31,7 +35,7 @@ #include "components/proxy_config/proxy_config_pref_names.h" #include "content/public/browser/browser_thread.h" #include "content/public/browser/navigation_entry.h" -#include "content/public/browser/notification_source.h" +#include "content/public/browser/notification_service.h" #include "content/public/browser/render_frame_host.h" #include "content/public/test/browser_test_utils.h" #include "content/public/test/test_utils.h" @@ -44,13 +48,12 @@ #include "extensions/browser/extension_registry.h" #include "extensions/browser/extension_system.h" #include "extensions/browser/extension_util.h" -#include "extensions/browser/notification_types.h" -#include "extensions/browser/runtime_data.h" #include "extensions/common/api/declarative_net_request/constants.h" #include "extensions/common/api/declarative_net_request/test_utils.h" #include "extensions/common/constants.h" #include "extensions/common/extension_id.h" #include "extensions/common/url_pattern.h" +#include "extensions/test/extension_test_message_listener.h" #include "net/dns/mock_host_resolver.h" #include "net/test/spawned_test_server/spawned_test_server.h" #include "net/test/test_data_directory.h" @@ -90,8 +93,8 @@ class URLRequestMonitor : public RulesetManager::TestObserver { private: // RulesetManager::TestObserver implementation. - void OnShouldBlockRequest(const WebRequestInfo& request, - bool is_incognito_context) override { + void OnEvaluateRequest(const WebRequestInfo& request, + bool is_incognito_context) override { if (request.url == url_) GetAndResetRequestSeen(true); } @@ -115,12 +118,12 @@ class DeclarativeNetRequestBrowserTest public: DeclarativeNetRequestBrowserTest() {} - // ExtensionBrowserTest override. + // ExtensionBrowserTest overrides: void SetUpOnMainThread() override { ExtensionBrowserTest::SetUpOnMainThread(); base::FilePath test_root_path; - PathService::Get(chrome::DIR_TEST_DATA, &test_root_path); + base::PathService::Get(chrome::DIR_TEST_DATA, &test_root_path); test_root_path = test_root_path.AppendASCII("extensions") .AppendASCII("declarative_net_request"); embedded_test_server()->ServeFilesFromDirectory(test_root_path); @@ -132,6 +135,19 @@ class DeclarativeNetRequestBrowserTest ASSERT_TRUE(temp_dir_.CreateUniqueTempDir()); } + void CreatedBrowserMainParts( + content::BrowserMainParts* browser_main_parts) override { + // At this point, the notification service is initialized but the profile + // and extensions have not. Initialize |background_page_ready_listener_| to + // listen for messages from extensions. + CHECK(content::NotificationService::current()); + + background_page_ready_listener_ = + std::make_unique<ExtensionTestMessageListener>("ready", + false /*will_reply*/); + + ExtensionBrowserTest::CreatedBrowserMainParts(browser_main_parts); + } protected: content::WebContents* web_contents(Browser* browser) const { @@ -184,6 +200,7 @@ class DeclarativeNetRequestBrowserTest kJSONRulesFilename, rules, hosts, has_background_script_); + background_page_ready_listener_->Reset(); const Extension* extension = nullptr; switch (GetParam()) { case ExtensionLoadType::PACKED: @@ -201,6 +218,10 @@ class DeclarativeNetRequestBrowserTest // Ensure the ruleset is also loaded on the IO thread. content::RunAllTasksUntilIdle(); + // Wait for the background page to load if needed. + if (has_background_script_) + WaitForBackgroundScriptToLoad(extension->id()); + // Ensure no load errors were reported. EXPECT_TRUE(LoadErrorReporter::GetInstance()->GetErrors()->empty()); @@ -220,9 +241,81 @@ class DeclarativeNetRequestBrowserTest {URLPattern::kAllUrlsPattern}); } + void WaitForBackgroundScriptToLoad(const ExtensionId& extension_id) { + ASSERT_TRUE(background_page_ready_listener_->WaitUntilSatisfied()); + ASSERT_EQ(extension_id, + background_page_ready_listener_->extension_id_for_message()); + background_page_ready_listener_->Reset(); + } + + void AddWhitelistedPages(const ExtensionId& extension_id, + const std::vector<std::string>& patterns) { + UpdateWhitelistedPages(extension_id, patterns, "addWhitelistedPages"); + } + + void RemoveWhitelistedPages(const ExtensionId& extension_id, + const std::vector<std::string>& patterns) { + UpdateWhitelistedPages(extension_id, patterns, "removeWhitelistedPages"); + } + + // Verifies that the result of getWhitelistedPages call is the same as + // |expected_patterns|. + void VerifyGetWhitelistedPages( + const ExtensionId& extension_id, + const std::set<std::string>& expected_patterns) { + static constexpr char kScript[] = R"( + chrome.declarativeNetRequest.getWhitelistedPages(function(patterns) { + window.domAutomationController.send(chrome.runtime.lastError + ? 'error' + : JSON.stringify(patterns)); + }); + )"; + + const std::string result = + ExecuteScriptInBackgroundPage(extension_id, kScript); + ASSERT_NE("error", result); + + // Parse |result| as a list and deserialize it to a set of strings. + std::unique_ptr<base::Value> value = + JSONStringValueDeserializer(result).Deserialize( + nullptr /*error_code*/, nullptr /*error_message*/); + ASSERT_TRUE(value); + ASSERT_TRUE(value->is_list()); + std::set<std::string> patterns; + for (const auto& pattern_value : value->GetList()) { + ASSERT_TRUE(pattern_value.is_string()); + patterns.insert(pattern_value.GetString()); + } + + EXPECT_EQ(expected_patterns, patterns); + } + private: + void UpdateWhitelistedPages(const ExtensionId& extension_id, + const std::vector<std::string>& patterns, + const std::string& function_name) { + static constexpr char kScript[] = R"( + chrome.declarativeNetRequest.%s(%s, function() { + window.domAutomationController.send(chrome.runtime.lastError + ? 'error' + : 'success'); + }); + )"; + + // Serialize |patterns| to JSON. + std::unique_ptr<base::ListValue> list = ToListValue(patterns); + std::string json_string; + ASSERT_TRUE(JSONStringValueSerializer(&json_string).Serialize(*list)); + + EXPECT_EQ("success", ExecuteScriptInBackgroundPage( + extension_id, + base::StringPrintf(kScript, function_name.c_str(), + json_string.c_str()))); + } + base::ScopedTempDir temp_dir_; bool has_background_script_ = false; + std::unique_ptr<ExtensionTestMessageListener> background_page_ready_listener_; DISALLOW_COPY_AND_ASSIGN(DeclarativeNetRequestBrowserTest); }; @@ -273,6 +366,7 @@ IN_PROC_BROWSER_TEST_P(DeclarativeNetRequestBrowserTest, for (const auto& rule_data : rules_data) { TestRule rule = CreateGenericRule(); rule.condition->url_filter = rule_data.url_filter; + rule.condition->resource_types = std::vector<std::string>({"main_frame"}); rule.id = rule_data.id; rules.push_back(rule); } @@ -301,6 +395,7 @@ IN_PROC_BROWSER_TEST_P(DeclarativeNetRequestBrowserTest, TestRule rule = CreateGenericRule(); rule.condition->url_filter = std::string("pages_with_script/page2.html?q=bye^"); + rule.condition->resource_types = std::vector<std::string>({"main_frame"}); ASSERT_NO_FATAL_FAILURE(LoadExtensionWithRules({rule})); // '^' (Separator character) matches anything except a letter, a digit or @@ -538,18 +633,21 @@ IN_PROC_BROWSER_TEST_P(DeclarativeNetRequestBrowserTest, Whitelist) { TestRule rule = CreateGenericRule(); int id = kMinValidID; - // Block all requests ending with numbers 1 to |kNumRequests|. + // Block all main-frame requests ending with numbers 1 to |kNumRequests|. std::vector<TestRule> rules; for (int i = 1; i <= kNumRequests; ++i) { rule.id = id++; rule.condition->url_filter = base::StringPrintf("num=%d|", i); + rule.condition->resource_types = std::vector<std::string>({"main_frame"}); rules.push_back(rule); } - // Whitelist all requests ending with even numbers from 1 to |kNumRequests|. + // Whitelist all main-frame requests ending with even numbers from 1 to + // |kNumRequests|. for (int i = 2; i <= kNumRequests; i += 2) { rule.id = id++; rule.condition->url_filter = base::StringPrintf("num=%d|", i); + rule.condition->resource_types = std::vector<std::string>({"main_frame"}); rule.action->type = std::string("whitelist"); rules.push_back(rule); } @@ -577,9 +675,10 @@ IN_PROC_BROWSER_TEST_P(DeclarativeNetRequestBrowserTest, Whitelist) { // enabled. IN_PROC_BROWSER_TEST_P(DeclarativeNetRequestBrowserTest, Enable_Disable_Reload_Uninstall) { - // Block all requests to example.com + // Block all main frame requests to example.com TestRule rule = CreateGenericRule(); rule.condition->url_filter = std::string("example.com"); + rule.condition->resource_types = std::vector<std::string>({"main_frame"}); ASSERT_NO_FATAL_FAILURE(LoadExtensionWithRules({rule})); const ExtensionId extension_id = last_loaded_extension_id(); @@ -650,6 +749,7 @@ IN_PROC_BROWSER_TEST_P(DeclarativeNetRequestBrowserTest, for (const auto& rule_data : rules_data) { TestRule rule = CreateGenericRule(); rule.condition->url_filter = rule_data.url_filter; + rule.condition->resource_types = std::vector<std::string>({"main_frame"}); rule.id = rule_data.id; if (rule_data.add_to_first_extension) rules_1.push_back(rule); @@ -705,6 +805,7 @@ IN_PROC_BROWSER_TEST_P(DeclarativeNetRequestBrowserTest, rule.priority = kMinValidPriority; rule.action->type = std::string("redirect"); rule.condition->url_filter = std::string("example.com"); + rule.condition->resource_types = std::vector<std::string>({"main_frame"}); base::Time last_extension_install_time = base::Time::Min(); @@ -762,6 +863,7 @@ IN_PROC_BROWSER_TEST_P(DeclarativeNetRequestBrowserTest, BlockAndRedirect) { rule.condition->url_filter = rule_data.url_filter; rule.id = rule_data.id; rule.priority = kMinValidPriority; + rule.condition->resource_types = std::vector<std::string>({"main_frame"}); rule.action->type = rule_data.action_type; rule.action->redirect_url = rule_data.redirect_url; rules.push_back(rule); @@ -844,13 +946,14 @@ IN_PROC_BROWSER_TEST_P(DeclarativeNetRequestBrowserTest, RedirectPriority) { rule.action->type = std::string("redirect"); rule.action->redirect_url = redirect_url_for_priority(j); rule.condition->url_filter = pattern; + rule.condition->resource_types = std::vector<std::string>({"main_frame"}); rules.push_back(rule); } } // Shuffle the rules to ensure that the order in which rules are added has no // effect on the test. - std::random_shuffle(rules.begin(), rules.end()); + base::RandomShuffle(rules.begin(), rules.end()); ASSERT_NO_FATAL_FAILURE(LoadExtensionWithRules(rules)); for (size_t i = 0; i <= kNumPatternTypes + 1; ++i) { @@ -877,9 +980,10 @@ IN_PROC_BROWSER_TEST_P(DeclarativeNetRequestBrowserTest, RedirectPriority) { // from an incognito context. IN_PROC_BROWSER_TEST_P(DeclarativeNetRequestBrowserTest, BlockRequests_Incognito) { - // Block all requests to example.com + // Block all main-frame requests to example.com. TestRule rule = CreateGenericRule(); rule.condition->url_filter = std::string("example.com"); + rule.condition->resource_types = std::vector<std::string>({"main_frame"}); ASSERT_NO_FATAL_FAILURE(LoadExtensionWithRules({rule})); ExtensionId extension_id = last_loaded_extension_id(); @@ -1106,7 +1210,7 @@ IN_PROC_BROWSER_TEST_P(DeclarativeNetRequestBrowserTest, rules_2, "extension_2", {URLPattern::kAllUrlsPattern})); const std::string extension_id_2 = last_loaded_extension_id(); - auto get_manifest_url = [](const std::string& extension_id) { + auto get_manifest_url = [](const ExtensionId& extension_id) { return GURL(base::StringPrintf("%s://%s/manifest.json", extensions::kExtensionScheme, extension_id.c_str())); @@ -1137,37 +1241,13 @@ IN_PROC_BROWSER_TEST_P(DeclarativeNetRequestBrowserTest_Packed, ASSERT_TRUE(dnr_extension); EXPECT_EQ("Test extension", dnr_extension->name()); - // Ensure the background page is ready before dispatching the script to it. - if (!ExtensionSystem::Get(profile())->runtime_data()->IsBackgroundPageReady( - dnr_extension)) { - content::WindowedNotificationObserver( - NOTIFICATION_EXTENSION_BACKGROUND_PAGE_READY, - content::Source<Extension>(dnr_extension)) - .Wait(); - } + constexpr char kGoogleDotCom[] = "https://www.google.com/"; - // Whitelist "https://www.google.com/". - const char* script1 = R"( - chrome.declarativeNetRequest.addWhitelistedPages( - ['https://www.google.com/'], function() { - window.domAutomationController.send('success'); - }); - )"; - EXPECT_EQ("success", - ExecuteScriptInBackgroundPage(last_loaded_extension_id(), script1)); + // Whitelist |kGoogleDotCom|. + AddWhitelistedPages(dnr_extension->id(), {kGoogleDotCom}); // Ensure that the page was whitelisted. - const char* script2 = R"( - chrome.declarativeNetRequest.getWhitelistedPages(function(patterns) { - if (patterns.length === 1 && patterns[0] === 'https://www.google.com/') - window.domAutomationController.send('success'); - else - window.domAutomationController.send('error'); - }); - )"; - - EXPECT_EQ("success", - ExecuteScriptInBackgroundPage(last_loaded_extension_id(), script2)); + VerifyGetWhitelistedPages(dnr_extension->id(), {kGoogleDotCom}); } // Tests that the pages whitelisted using the page whitelisting API are @@ -1191,46 +1271,16 @@ IN_PROC_BROWSER_TEST_P(DeclarativeNetRequestBrowserTest_Packed, ASSERT_TRUE(dnr_extension); // Ensure the background page is ready before dispatching the script to it. - if (!ExtensionSystem::Get(profile())->runtime_data()->IsBackgroundPageReady( - dnr_extension)) { - content::WindowedNotificationObserver( - NOTIFICATION_EXTENSION_BACKGROUND_PAGE_READY, - content::Source<Extension>(dnr_extension)) - .Wait(); - } + WaitForBackgroundScriptToLoad(dnr_extension->id()); + + constexpr char kGoogleDotCom[] = "https://www.google.com/"; + + VerifyGetWhitelistedPages(dnr_extension->id(), {kGoogleDotCom}); + + // Remove |kGoogleDotCom| from the whitelist. + RemoveWhitelistedPages(dnr_extension->id(), {kGoogleDotCom}); - const char* script1 = R"( - chrome.declarativeNetRequest.getWhitelistedPages(function(patterns) { - if (patterns.length === 1 && patterns[0] === "https://www.google.com/") - window.domAutomationController.send("success"); - else - window.domAutomationController.send("error"); - }); - )"; - ASSERT_EQ("success", - ExecuteScriptInBackgroundPage(dnr_extension->id(), script1)); - - // Remove "https://www.google.com/" from the whitelist. - const char* script2 = R"( - chrome.declarativeNetRequest.removeWhitelistedPages( - ["https://www.google.com/"], function() { - window.domAutomationController.send("success"); - }); - )"; - ASSERT_EQ("success", - ExecuteScriptInBackgroundPage(dnr_extension->id(), script2)); - - // Ensure that the page was removed from the whitelist. - const char* script3 = R"( - chrome.declarativeNetRequest.getWhitelistedPages(function(patterns) { - if (patterns.length === 0) - window.domAutomationController.send("success"); - else - window.domAutomationController.send("error"); - }); - )"; - EXPECT_EQ("success", - ExecuteScriptInBackgroundPage(dnr_extension->id(), script3)); + VerifyGetWhitelistedPages(dnr_extension->id(), {}); } // Test fixture to verify that host permissions for the request url and the @@ -1357,7 +1407,8 @@ class DeclarativeNetRequestResourceTypeBrowserTest DeclarativeNetRequestResourceTypeBrowserTest() {} protected: - // TODO(crbug.com/696822): Add tests for "object", "ping", "other", "font". + // TODO(crbug.com/696822): Add tests for "object", "ping", "other", "font", + // "csp_report". enum ResourceTypeMask { kNone = 0, kSubframe = 1 << 0, @@ -1453,17 +1504,11 @@ class DeclarativeNetRequestResourceTypeBrowserTest {"block_websocket.com", 7, {"websocket"}, {}}, {"block_image_and_stylesheet.com", 8, {"image", "stylesheet"}, {}}, {"block_subframe_and_xhr.com", 11, {"sub_frame", "xmlhttprequest"}, {}}, - // With renderer side navigation, the main frame origin serves as the - // initiator for main frame page loads. Hence to ensure that the main - // frame page load is not blocked, also exclude the "other" resource - // type, which is used for main frame requests currently. - // TODO(crbug.com/696822): Change "other" to "main_frame" once it is - // implemented. - {"block_all.com", 9, {}, {"other"}}, + {"block_all.com", 9, {}, {}}, {"block_all_but_xhr_and_script.com", 10, {}, - {"xmlhttprequest", "script", "other"}}, + {"xmlhttprequest", "script"}}, }; std::vector<TestRule> rules; diff --git a/chromium/chrome/browser/extensions/api/declarative_net_request/rule_indexing_unittest.cc b/chromium/chrome/browser/extensions/api/declarative_net_request/rule_indexing_unittest.cc index 0e5c1f20ae2..34bcef26e9f 100644 --- a/chromium/chrome/browser/extensions/api/declarative_net_request/rule_indexing_unittest.cc +++ b/chromium/chrome/browser/extensions/api/declarative_net_request/rule_indexing_unittest.cc @@ -223,8 +223,9 @@ TEST_P(RuleIndexingTest, InvalidRedirectRulePriority) { TEST_P(RuleIndexingTest, NoApplicableResourceTypes) { TestRule rule = CreateGenericRule(); rule.condition->excluded_resource_types = std::vector<std::string>( - {"sub_frame", "stylesheet", "script", "image", "font", "object", - "xmlhttprequest", "ping", "media", "websocket", "other"}); + {"main_frame", "sub_frame", "stylesheet", "script", "image", "font", + "object", "xmlhttprequest", "ping", "csp_report", "media", "websocket", + "other"}); AddRule(rule); LoadAndExpectError( ParseInfo(ParseResult::ERROR_NO_APPLICABLE_RESOURCE_TYPES, 0u) diff --git a/chromium/chrome/browser/extensions/api/declarative_net_request/ruleset_manager_unittest.cc b/chromium/chrome/browser/extensions/api/declarative_net_request/ruleset_manager_unittest.cc index 01b106a0d14..ff1ca03b826 100644 --- a/chromium/chrome/browser/extensions/api/declarative_net_request/ruleset_manager_unittest.cc +++ b/chromium/chrome/browser/extensions/api/declarative_net_request/ruleset_manager_unittest.cc @@ -42,6 +42,8 @@ class RulesetManagerTest : public DNRTestBase { RulesetManagerTest() {} protected: + using Action = RulesetManager::Action; + // Helper to create a ruleset matcher instance for the given |rules|. void CreateMatcherForRules(const std::vector<TestRule>& rules, const std::string& extension_dirname, @@ -140,8 +142,12 @@ TEST_P(RulesetManagerTest, MultipleRulesets) { GetRequestForURL("http://three.com"); WebRequestInfo request_three_info(request_three.get()); - // Test all possible combinations with |rule_one| and |rule_two| enabled. - const bool is_incognito_context = false; + auto should_block_request = [manager](const WebRequestInfo& request) { + GURL redirect_url; + return manager->EvaluateRequest(request, false /*is_incognito_context*/, + &redirect_url) == Action::BLOCK; + }; + for (int mask = 0; mask < 4; mask++) { SCOPED_TRACE(base::StringPrintf("Testing ruleset mask %d", mask)); @@ -170,14 +176,11 @@ TEST_P(RulesetManagerTest, MultipleRulesets) { ASSERT_EQ(expected_matcher_count, manager->GetMatcherCountForTest()); - EXPECT_EQ( - (mask & kEnableRulesetOne) != 0, - manager->ShouldBlockRequest(request_one_info, is_incognito_context)); - EXPECT_EQ( - (mask & kEnableRulesetTwo) != 0, - manager->ShouldBlockRequest(request_two_info, is_incognito_context)); - EXPECT_FALSE( - manager->ShouldBlockRequest(request_three_info, is_incognito_context)); + EXPECT_EQ((mask & kEnableRulesetOne) != 0, + should_block_request(request_one_info)); + EXPECT_EQ((mask & kEnableRulesetTwo) != 0, + should_block_request(request_two_info)); + EXPECT_FALSE(should_block_request(request_three_info)); // Remove the rulesets. if (mask & kEnableRulesetOne) @@ -205,24 +208,30 @@ TEST_P(RulesetManagerTest, IncognitoRequests) { GetRequestForURL("http://example.com"); WebRequestInfo request_info(request.get()); + GURL redirect_url; + // By default, the extension is disabled in incognito mode. So requests from // incognito contexts should not be evaluated. EXPECT_FALSE(util::IsIncognitoEnabled(last_loaded_extension()->id(), browser_context())); - EXPECT_FALSE( - manager->ShouldBlockRequest(request_info, true /*is_incognito_context*/)); - EXPECT_TRUE(manager->ShouldBlockRequest(request_info, - false /*is_incognito_context*/)); + EXPECT_EQ(Action::NONE, + manager->EvaluateRequest( + request_info, true /*is_incognito_context*/, &redirect_url)); + EXPECT_EQ(Action::BLOCK, + manager->EvaluateRequest( + request_info, false /*is_incognito_context*/, &redirect_url)); // Enabling the extension in incognito mode, should cause requests from // incognito contexts to also be evaluated. SetIncognitoEnabled(last_loaded_extension(), true /*incognito_enabled*/); EXPECT_TRUE(util::IsIncognitoEnabled(last_loaded_extension()->id(), browser_context())); - EXPECT_TRUE( - manager->ShouldBlockRequest(request_info, true /*is_incognito_context*/)); - EXPECT_TRUE(manager->ShouldBlockRequest(request_info, - false /*is_incognito_context*/)); + EXPECT_EQ(Action::BLOCK, + manager->EvaluateRequest( + request_info, true /*is_incognito_context*/, &redirect_url)); + EXPECT_EQ(Action::BLOCK, + manager->EvaluateRequest( + request_info, false /*is_incognito_context*/, &redirect_url)); } // Test redirect rules. @@ -250,8 +259,9 @@ TEST_P(RulesetManagerTest, Redirect) { GetRequestForURL("http://example.com"); request->set_initiator(base::nullopt); extensions::WebRequestInfo request_info1(request.get()); - EXPECT_TRUE(manager->ShouldRedirectRequest( - request_info1, is_incognito_context, &redirect_url1)); + EXPECT_EQ(Action::REDIRECT, + manager->EvaluateRequest(request_info1, is_incognito_context, + &redirect_url1)); EXPECT_EQ(GURL("http://google.com"), redirect_url1); // Change the initiator to "xyz.com". It should not be redirected since we @@ -259,16 +269,18 @@ TEST_P(RulesetManagerTest, Redirect) { GURL redirect_url2; request->set_initiator(url::Origin::Create(GURL("http://xyz.com"))); extensions::WebRequestInfo request_info2(request.get()); - EXPECT_FALSE(manager->ShouldRedirectRequest( - request_info2, is_incognito_context, &redirect_url2)); + EXPECT_EQ(Action::NONE, + manager->EvaluateRequest(request_info2, is_incognito_context, + &redirect_url2)); // Change the initiator to "abc.com". It should be redirected since we have // the required host permissions. GURL redirect_url3; request->set_initiator(url::Origin::Create(GURL("http://abc.com"))); extensions::WebRequestInfo request_info3(request.get()); - EXPECT_TRUE(manager->ShouldRedirectRequest( - request_info3, is_incognito_context, &redirect_url3)); + EXPECT_EQ(Action::REDIRECT, + manager->EvaluateRequest(request_info3, is_incognito_context, + &redirect_url3)); EXPECT_EQ(GURL("http://google.com"), redirect_url3); // Ensure web-socket requests are not redirected. @@ -276,8 +288,9 @@ TEST_P(RulesetManagerTest, Redirect) { request = GetRequestForURL("ws://example.com"); request->set_initiator(base::nullopt); extensions::WebRequestInfo request_info4(request.get()); - EXPECT_FALSE(manager->ShouldRedirectRequest( - request_info4, is_incognito_context, &redirect_url4)); + EXPECT_EQ(Action::NONE, + manager->EvaluateRequest(request_info4, is_incognito_context, + &redirect_url4)); } // Tests that an extension can't block or redirect resources on the chrome- @@ -320,48 +333,40 @@ TEST_P(RulesetManagerTest, ExtensionScheme) { EXPECT_EQ(2u, manager->GetMatcherCountForTest()); - // Ensure that "http://example.com" will be blocked and redirected. + // Ensure that "http://example.com" will be blocked (with blocking taking + // priority over redirection). std::unique_ptr<net::URLRequest> request = GetRequestForURL("http://example.com"); - EXPECT_TRUE(manager->ShouldBlockRequest(WebRequestInfo(request.get()), - false /*is_incognito_context*/)); GURL redirect_url; - EXPECT_TRUE(manager->ShouldRedirectRequest(WebRequestInfo(request.get()), - false /*is_incognito_context*/, - &redirect_url)); - EXPECT_EQ(GURL("http://google.com"), redirect_url); + EXPECT_EQ(Action::BLOCK, manager->EvaluateRequest( + WebRequestInfo(request.get()), + false /*is_incognito_context*/, &redirect_url)); // Ensure that the background page for |extension_1| won't be blocked or // redirected. GURL background_page_url_1 = BackgroundInfo::GetBackgroundURL(extension_1); EXPECT_TRUE(!background_page_url_1.is_empty()); request = GetRequestForURL(background_page_url_1.spec()); - EXPECT_FALSE(manager->ShouldBlockRequest(WebRequestInfo(request.get()), - false /*is_incognito_context*/)); - EXPECT_FALSE(manager->ShouldRedirectRequest(WebRequestInfo(request.get()), - false /*is_incognito_context*/, - &redirect_url)); + EXPECT_EQ(Action::NONE, manager->EvaluateRequest( + WebRequestInfo(request.get()), + false /*is_incognito_context*/, &redirect_url)); // Ensure that the background page for |extension_2| won't be blocked or // redirected. GURL background_page_url_2 = BackgroundInfo::GetBackgroundURL(extension_2); EXPECT_TRUE(!background_page_url_2.is_empty()); request = GetRequestForURL(background_page_url_2.spec()); - EXPECT_FALSE(manager->ShouldBlockRequest(WebRequestInfo(request.get()), - false /*is_incognito_context*/)); - EXPECT_FALSE(manager->ShouldRedirectRequest(WebRequestInfo(request.get()), - false /*is_incognito_context*/, - &redirect_url)); + EXPECT_EQ(Action::NONE, manager->EvaluateRequest( + WebRequestInfo(request.get()), + false /*is_incognito_context*/, &redirect_url)); // Also ensure that an arbitrary url on the chrome extension scheme is also // not blocked or redirected. request = GetRequestForURL(base::StringPrintf("%s://%s/%s", kExtensionScheme, "extension_id", "path")); - EXPECT_FALSE(manager->ShouldBlockRequest(WebRequestInfo(request.get()), - false /*is_incognito_context*/)); - EXPECT_FALSE(manager->ShouldRedirectRequest(WebRequestInfo(request.get()), - false /*is_incognito_context*/, - &redirect_url)); + EXPECT_EQ(Action::NONE, manager->EvaluateRequest( + WebRequestInfo(request.get()), + false /*is_incognito_context*/, &redirect_url)); } INSTANTIATE_TEST_CASE_P(, diff --git a/chromium/chrome/browser/extensions/api/declarative_webrequest/webrequest_action_unittest.cc b/chromium/chrome/browser/extensions/api/declarative_webrequest/webrequest_action_unittest.cc index 4b88dec5ca5..c2cdf33f448 100644 --- a/chromium/chrome/browser/extensions/api/declarative_webrequest/webrequest_action_unittest.cc +++ b/chromium/chrome/browser/extensions/api/declarative_webrequest/webrequest_action_unittest.cc @@ -12,7 +12,6 @@ #include "base/json/json_file_value_serializer.h" #include "base/macros.h" #include "base/memory/ref_counted.h" -#include "base/message_loop/message_loop.h" #include "base/test/values_test_util.h" #include "base/time/time.h" #include "base/values.h" diff --git a/chromium/chrome/browser/extensions/api/desktop_capture/desktop_capture_apitest.cc b/chromium/chrome/browser/extensions/api/desktop_capture/desktop_capture_apitest.cc index c6c75b48921..66e3efd2644 100644 --- a/chromium/chrome/browser/extensions/api/desktop_capture/desktop_capture_apitest.cc +++ b/chromium/chrome/browser/extensions/api/desktop_capture/desktop_capture_apitest.cc @@ -254,7 +254,7 @@ IN_PROC_BROWSER_TEST_F(DesktopCaptureApiTest, MAYBE_ChooseDesktopMedia) { IN_PROC_BROWSER_TEST_F(DesktopCaptureApiTest, DISABLED_Delegation) { // Initialize test server. base::FilePath test_data; - EXPECT_TRUE(PathService::Get(chrome::DIR_TEST_DATA, &test_data)); + EXPECT_TRUE(base::PathService::Get(chrome::DIR_TEST_DATA, &test_data)); embedded_test_server()->ServeFilesFromDirectory(test_data.AppendASCII( "extensions/api_test/desktop_capture_delegate")); ASSERT_TRUE(embedded_test_server()->Start()); diff --git a/chromium/chrome/browser/extensions/api/developer_private/developer_private_api.cc b/chromium/chrome/browser/extensions/api/developer_private/developer_private_api.cc index c7f44caf9f0..ce0daf6bb50 100644 --- a/chromium/chrome/browser/extensions/api/developer_private/developer_private_api.cc +++ b/chromium/chrome/browser/extensions/api/developer_private/developer_private_api.cc @@ -46,7 +46,6 @@ #include "chrome/browser/ui/extensions/app_launch_params.h" #include "chrome/browser/ui/extensions/application_launch.h" #include "chrome/browser/ui/tabs/tab_strip_model.h" -#include "chrome/browser/ui/webui/extensions/extension_loader_handler.h" #include "chrome/common/extensions/api/developer_private.h" #include "chrome/common/extensions/manifest_handlers/app_launch_info.h" #include "chrome/common/pref_names.h" @@ -81,6 +80,7 @@ #include "extensions/common/feature_switch.h" #include "extensions/common/install_warning.h" #include "extensions/common/manifest.h" +#include "extensions/common/manifest_constants.h" #include "extensions/common/manifest_handlers/options_page_info.h" #include "extensions/common/manifest_url_handlers.h" #include "extensions/common/permissions/permissions_data.h" @@ -91,6 +91,7 @@ #include "storage/browser/fileapi/file_system_operation.h" #include "storage/browser/fileapi/file_system_operation_runner.h" #include "storage/browser/fileapi/isolated_context.h" +#include "third_party/re2/src/re2/re2.h" #include "ui/base/l10n/l10n_util.h" namespace extensions { @@ -122,6 +123,9 @@ const char kCannotRepairHealthyExtension[] = "Cannot repair a healthy extension."; const char kCannotRepairPolicyExtension[] = "Cannot repair a policy-installed extension."; +const char kCannotChangeHostPermissions[] = + "Cannot change host permissions for the given extension."; +const char kInvalidHost[] = "Invalid host."; const char kUnpackedAppsFolder[] = "apps_target"; const char kManifestFile[] = "manifest.json"; @@ -134,10 +138,43 @@ ExtensionService* GetExtensionService(content::BrowserContext* context) { std::string ReadFileToString(const base::FilePath& path) { std::string data; + // This call can fail, but it doesn't matter for our purposes. If it fails, + // we simply return an empty string for the manifest, and ignore it. ignore_result(base::ReadFileToString(path, &data)); return data; } +using GetManifestErrorCallback = + base::OnceCallback<void(const base::FilePath& file_path, + const std::string& error, + size_t line_number, + const std::string& manifest)>; +// Takes in an |error| string and tries to parse it as a manifest error (with +// line number), asynchronously calling |callback| with the results. +void GetManifestError(const std::string& error, + const base::FilePath& extension_path, + GetManifestErrorCallback callback) { + size_t line = 0u; + size_t column = 0u; + std::string regex = base::StringPrintf("%s Line: (\\d+), column: (\\d+), .*", + manifest_errors::kManifestParseError); + // If this was a JSON parse error, we can highlight the exact line with the + // error. Otherwise, we should still display the manifest (for consistency, + // reference, and so that if we ever make this really fancy and add an editor, + // it's ready). + // + // This regex call can fail, but if it does, we just don't highlight anything. + re2::RE2::FullMatch(error, regex, &line, &column); + + // This will read the manifest and call AddFailure with the read manifest + // contents. + base::PostTaskWithTraitsAndReplyWithResult( + FROM_HERE, {base::MayBlock(), base::TaskPriority::USER_BLOCKING}, + base::BindOnce(&ReadFileToString, + extension_path.Append(kManifestFilename)), + base::BindOnce(std::move(callback), extension_path, error, line)); +} + bool UserCanModifyExtensionConfiguration( const Extension* extension, content::BrowserContext* browser_context, @@ -396,14 +433,13 @@ void DeveloperPrivateEventRouter::OnAppWindowRemoved(AppWindow* window) { void DeveloperPrivateEventRouter::OnExtensionCommandAdded( const std::string& extension_id, const Command& added_command) { - BroadcastItemStateChanged(developer::EVENT_TYPE_PREFS_CHANGED, - extension_id); + BroadcastItemStateChanged(developer::EVENT_TYPE_COMMAND_ADDED, extension_id); } void DeveloperPrivateEventRouter::OnExtensionCommandRemoved( const std::string& extension_id, const Command& removed_command) { - BroadcastItemStateChanged(developer::EVENT_TYPE_PREFS_CHANGED, + BroadcastItemStateChanged(developer::EVENT_TYPE_COMMAND_REMOVED, extension_id); } @@ -610,11 +646,9 @@ ExtensionFunction::ResponseAction DeveloperPrivateAutoUpdateFunction::Run() { ExtensionUpdater::CheckParams params; params.fetch_priority = ManifestFetchData::FetchPriority::FOREGROUND; params.install_immediately = true; - // TODO(crbug.com/714018): Replace base::BindRepeating with base::BindOnce. - params.callback = - base::BindRepeating(&DeveloperPrivateAutoUpdateFunction::OnComplete, - this /* ref counted */); - updater->CheckNow(params); + params.callback = base::BindOnce( + &DeveloperPrivateAutoUpdateFunction::OnComplete, this /* refcounted */); + updater->CheckNow(std::move(params)); } return RespondLater(); } @@ -834,12 +868,8 @@ DeveloperPrivateUpdateExtensionConfigurationFunction::Run() { } if (update.run_on_all_urls) { ScriptingPermissionsModifier modifier(browser_context(), extension); - if (!modifier.CanAffectExtension( - extension->permissions_data()->active_permissions()) && - !modifier.HasAffectedExtension()) { - return RespondNow( - Error("Cannot modify all urls of extension: " + extension->id())); - } + if (!modifier.CanAffectExtension()) + return RespondNow(Error(kCannotChangeHostPermissions)); modifier.SetAllowedOnAllUrls(*update.run_on_all_urls); } @@ -911,11 +941,10 @@ void DeveloperPrivateReloadFunction::OnLoadFailure( const std::string& error) { if (file_path == reloading_extension_path_) { // Reload failed - create an error to pass back to the extension. - ExtensionLoaderHandler::GetManifestError( + GetManifestError( error, file_path, - // TODO(devlin): Update GetManifestError to take a OnceCallback. - base::BindRepeating(&DeveloperPrivateReloadFunction::OnGotManifestError, - this)); // Creates a reference. + base::BindOnce(&DeveloperPrivateReloadFunction::OnGotManifestError, + this)); // Creates a reference. ClearObservers(); } } @@ -1035,7 +1064,7 @@ ExtensionFunction::ResponseAction DeveloperPrivateLoadUnpackedFunction::Run() { return RespondLater(); } - if (!ShowPicker(ui::SelectFileDialog::SELECT_FOLDER, + if (!ShowPicker(ui::SelectFileDialog::SELECT_EXISTING_FOLDER, l10n_util::GetStringUTF16(IDS_EXTENSION_LOAD_FROM_DIRECTORY), ui::SelectFileDialog::FileTypeInfo(), 0 /* file_type_index */)) { @@ -1077,7 +1106,7 @@ void DeveloperPrivateLoadUnpackedFunction::OnLoadComplete( return; } - ExtensionLoaderHandler::GetManifestError( + GetManifestError( error, file_path, base::Bind(&DeveloperPrivateLoadUnpackedFunction::OnGotManifestError, this)); @@ -1878,6 +1907,75 @@ DeveloperPrivateUpdateExtensionCommandFunction::Run() { return RespondNow(NoArguments()); } +DeveloperPrivateAddHostPermissionFunction:: + DeveloperPrivateAddHostPermissionFunction() = default; +DeveloperPrivateAddHostPermissionFunction:: + ~DeveloperPrivateAddHostPermissionFunction() = default; + +ExtensionFunction::ResponseAction +DeveloperPrivateAddHostPermissionFunction::Run() { + std::unique_ptr<developer::AddHostPermission::Params> params( + developer::AddHostPermission::Params::Create(*args_)); + EXTENSION_FUNCTION_VALIDATE(params); + + GURL host(params->host); + if (!host.is_valid() || host.path_piece().length() > 1 || host.has_query() || + host.has_ref()) { + return RespondNow(Error(kInvalidHost)); + } + + const Extension* extension = GetExtensionById(params->extension_id); + if (!extension) + return RespondNow(Error(kNoSuchExtensionError)); + + ScriptingPermissionsModifier scripting_modifier(browser_context(), extension); + if (!scripting_modifier.CanAffectExtension()) + return RespondNow(Error(kCannotChangeHostPermissions)); + + // Only grant withheld permissions. This also ensures that we won't grant + // any permission for a host that shouldn't be accessible to the extension, + // like chrome:-scheme urls. + if (!extension->permissions_data() + ->withheld_permissions() + .HasEffectiveAccessToURL(host)) { + return RespondNow(Error("Cannot grant a permission that wasn't withheld.")); + } + + scripting_modifier.GrantHostPermission(host); + return RespondNow(NoArguments()); +} + +DeveloperPrivateRemoveHostPermissionFunction:: + DeveloperPrivateRemoveHostPermissionFunction() = default; +DeveloperPrivateRemoveHostPermissionFunction:: + ~DeveloperPrivateRemoveHostPermissionFunction() = default; + +ExtensionFunction::ResponseAction +DeveloperPrivateRemoveHostPermissionFunction::Run() { + std::unique_ptr<developer::RemoveHostPermission::Params> params( + developer::RemoveHostPermission::Params::Create(*args_)); + EXTENSION_FUNCTION_VALIDATE(params); + + GURL host(params->host); + if (!host.is_valid() || host.path_piece().length() > 1 || host.has_query() || + host.has_ref()) { + return RespondNow(Error(kInvalidHost)); + } + + const Extension* extension = GetExtensionById(params->extension_id); + if (!extension) + return RespondNow(Error(kNoSuchExtensionError)); + + ScriptingPermissionsModifier scripting_modifier(browser_context(), extension); + if (!scripting_modifier.CanAffectExtension()) + return RespondNow(Error(kCannotChangeHostPermissions)); + + if (!scripting_modifier.HasGrantedHostPermission(host)) + return RespondNow(Error("Cannot remove a host that hasn't been granted.")); + + scripting_modifier.RemoveGrantedHostPermission(host); + return RespondNow(NoArguments()); +} } // namespace api diff --git a/chromium/chrome/browser/extensions/api/developer_private/developer_private_api.h b/chromium/chrome/browser/extensions/api/developer_private/developer_private_api.h index 11767ee4130..e1fb6581e13 100644 --- a/chromium/chrome/browser/extensions/api/developer_private/developer_private_api.h +++ b/chromium/chrome/browser/extensions/api/developer_private/developer_private_api.h @@ -753,6 +753,36 @@ class DeveloperPrivateUpdateExtensionCommandFunction ResponseAction Run() override; }; +class DeveloperPrivateAddHostPermissionFunction + : public DeveloperPrivateAPIFunction { + public: + DECLARE_EXTENSION_FUNCTION("developerPrivate.addHostPermission", + DEVELOPERPRIVATE_ADDHOSTPERMISSION); + DeveloperPrivateAddHostPermissionFunction(); + + private: + ~DeveloperPrivateAddHostPermissionFunction() override; + + ResponseAction Run() override; + + DISALLOW_COPY_AND_ASSIGN(DeveloperPrivateAddHostPermissionFunction); +}; + +class DeveloperPrivateRemoveHostPermissionFunction + : public DeveloperPrivateAPIFunction { + public: + DECLARE_EXTENSION_FUNCTION("developerPrivate.removeHostPermission", + DEVELOPERPRIVATE_REMOVEHOSTPERMISSION); + DeveloperPrivateRemoveHostPermissionFunction(); + + private: + ~DeveloperPrivateRemoveHostPermissionFunction() override; + + ResponseAction Run() override; + + DISALLOW_COPY_AND_ASSIGN(DeveloperPrivateRemoveHostPermissionFunction); +}; + } // namespace api } // namespace extensions diff --git a/chromium/chrome/browser/extensions/api/developer_private/developer_private_api_unittest.cc b/chromium/chrome/browser/extensions/api/developer_private/developer_private_api_unittest.cc index 5fcb562cce6..5f3a822df78 100644 --- a/chromium/chrome/browser/extensions/api/developer_private/developer_private_api_unittest.cc +++ b/chromium/chrome/browser/extensions/api/developer_private/developer_private_api_unittest.cc @@ -11,6 +11,7 @@ #include "base/macros.h" #include "base/scoped_observer.h" #include "base/strings/utf_string_conversions.h" +#include "base/test/scoped_feature_list.h" #include "chrome/browser/chrome_notification_types.h" #include "chrome/browser/extensions/chrome_test_extension_loader.h" #include "chrome/browser/extensions/error_console/error_console.h" @@ -53,8 +54,8 @@ #include "extensions/browser/test_extension_registry_observer.h" #include "extensions/common/extension.h" #include "extensions/common/extension_builder.h" +#include "extensions/common/extension_features.h" #include "extensions/common/extension_set.h" -#include "extensions/common/feature_switch.h" #include "extensions/common/manifest_constants.h" #include "extensions/common/value_builder.h" #include "extensions/test/test_extension_dir.h" @@ -70,6 +71,8 @@ namespace extensions { namespace { const char kGoodCrx[] = "ldnnhddmnhbkjipkidpdiheffobcpfmf"; +constexpr char kInvalidHost[] = "invalid host"; +constexpr char kInvalidHostError[] = "Invalid host."; std::unique_ptr<KeyedService> BuildAPI(content::BrowserContext* context) { return std::make_unique<DeveloperPrivateAPI>(context); @@ -299,9 +302,7 @@ void DeveloperPrivateApiUnitTest::UpdateProfileConfigurationDevMode( new api::DeveloperPrivateUpdateProfileConfigurationFunction()); std::unique_ptr<base::ListValue> args = ListBuilder() - .Append(DictionaryBuilder() - .SetBoolean("inDeveloperMode", dev_mode) - .Build()) + .Append(DictionaryBuilder().Set("inDeveloperMode", dev_mode).Build()) .Build(); EXPECT_TRUE(RunFunction(function, *args)) << function->GetError(); } @@ -360,13 +361,16 @@ void DeveloperPrivateApiUnitTest::TearDown() { // Test developerPrivate.updateExtensionConfiguration. TEST_F(DeveloperPrivateApiUnitTest, DeveloperPrivateUpdateExtensionConfiguration) { - FeatureSwitch::ScopedOverride scripts_require_action( - FeatureSwitch::scripts_require_action(), true); + base::test::ScopedFeatureList scoped_feature_list; + scoped_feature_list.InitAndEnableFeature(features::kRuntimeHostPermissions); // Sadly, we need a "real" directory here, because toggling prefs causes // a reload (which needs a path). const Extension* extension = LoadUnpackedExtension(); const std::string& id = extension->id(); + ScriptingPermissionsModifier(profile(), base::WrapRefCounted(extension)) + .SetAllowedOnAllUrls(false); + TestExtensionPrefSetting( base::Bind(&HasPrefsPermission, &util::IsIncognitoEnabled, profile(), id), "incognitoAccess", id); @@ -402,13 +406,15 @@ TEST_F(DeveloperPrivateApiUnitTest, DeveloperPrivatePackFunction) { // Use a temp dir isolating the extension dir and its generated files. base::ScopedTempDir temp_dir; ASSERT_TRUE(temp_dir.CreateUniqueTempDir()); - base::FilePath root_path = data_dir().AppendASCII("good_unpacked"); + base::FilePath root_path = data_dir().AppendASCII("simple_with_popup"); ASSERT_TRUE(base::CopyDirectory(root_path, temp_dir.GetPath(), true)); base::FilePath temp_root_path = temp_dir.GetPath().Append(root_path.BaseName()); - base::FilePath crx_path = temp_dir.GetPath().AppendASCII("good_unpacked.crx"); - base::FilePath pem_path = temp_dir.GetPath().AppendASCII("good_unpacked.pem"); + base::FilePath crx_path = + temp_dir.GetPath().AppendASCII("simple_with_popup.crx"); + base::FilePath pem_path = + temp_dir.GetPath().AppendASCII("simple_with_popup.pem"); EXPECT_FALSE(base::PathExists(crx_path)) << "crx should not exist before the test is run!"; @@ -453,7 +459,8 @@ TEST_F(DeveloperPrivateApiUnitTest, DeveloperPrivateChoosePath) { std::unique_ptr<content::WebContents> web_contents( content::WebContentsTester::CreateTestWebContents(profile(), nullptr)); - base::FilePath expected_dir_path = data_dir().AppendASCII("good_unpacked"); + base::FilePath expected_dir_path = + data_dir().AppendASCII("simple_with_popup"); api::EntryPicker::SkipPickerAndAlwaysSelectPathForTest(&expected_dir_path); // Try selecting a directory. @@ -471,7 +478,7 @@ TEST_F(DeveloperPrivateApiUnitTest, DeveloperPrivateChoosePath) { // Try selecting a pem file. base::FilePath expected_file_path = - data_dir().AppendASCII("good_unpacked.pem"); + data_dir().AppendASCII("simple_with_popup.pem"); api::EntryPicker::SkipPickerAndAlwaysSelectPathForTest(&expected_file_path); choose_args.Clear(); choose_args.AppendString("FILE"); @@ -496,7 +503,7 @@ TEST_F(DeveloperPrivateApiUnitTest, DeveloperPrivateLoadUnpacked) { std::unique_ptr<content::WebContents> web_contents( content::WebContentsTester::CreateTestWebContents(profile(), nullptr)); - base::FilePath path = data_dir().AppendASCII("good_unpacked"); + base::FilePath path = data_dir().AppendASCII("simple_with_popup"); api::EntryPicker::SkipPickerAndAlwaysSelectPathForTest(&path); // Try loading a good extension (it should succeed, and the extension should @@ -1144,7 +1151,7 @@ TEST_F(DeveloperPrivateApiUnitTest, RepairPolicyExtension) { } // Test developerPrivate.updateProfileConfiguration: Try to turn on devMode -// when DeveloperToolsDisabled policy is active. +// when DeveloperToolsAvailability policy disallows developer tools. TEST_F(DeveloperPrivateApiUnitTest, DeveloperPrivateDevModeDisabledPolicy) { testing_pref_service()->SetManagedPref(prefs::kExtensionsUIDeveloperMode, std::make_unique<base::Value>(false)); @@ -1161,7 +1168,7 @@ TEST_F(DeveloperPrivateApiUnitTest, DeveloperPrivateDevModeDisabledPolicy) { } // Test developerPrivate.updateProfileConfiguration: Try to turn on devMode -// (without DeveloperToolsDisabled policy). +// (without DeveloperToolsAvailability policy). TEST_F(DeveloperPrivateApiUnitTest, DeveloperPrivateDevMode) { UpdateProfileConfigurationDevMode(false); EXPECT_FALSE( @@ -1188,7 +1195,7 @@ TEST_F(DeveloperPrivateApiUnitTest, LoadUnpackedFailsWithoutDevMode) { std::unique_ptr<content::WebContents> web_contents( content::WebContentsTester::CreateTestWebContents(profile(), nullptr)); - base::FilePath path = data_dir().AppendASCII("good_unpacked"); + base::FilePath path = data_dir().AppendASCII("simple_with_popup"); api::EntryPicker::SkipPickerAndAlwaysSelectPathForTest(&path); PrefService* prefs = profile()->GetPrefs(); @@ -1206,7 +1213,7 @@ TEST_F(DeveloperPrivateApiUnitTest, LoadUnpackedFailsWithBlacklistingPolicy) { std::unique_ptr<content::WebContents> web_contents( content::WebContentsTester::CreateTestWebContents(profile(), nullptr)); - base::FilePath path = data_dir().AppendASCII("good_unpacked"); + base::FilePath path = data_dir().AppendASCII("simple_with_popup"); api::EntryPicker::SkipPickerAndAlwaysSelectPathForTest(&path); { @@ -1294,6 +1301,98 @@ TEST_F(DeveloperPrivateApiUnitTest, InstallDroppedFileUserScript) { EXPECT_EQ("My user script", extension->name()); } +TEST_F(DeveloperPrivateApiUnitTest, GrantHostPermission) { + base::test::ScopedFeatureList feature_list; + feature_list.InitAndEnableFeature(features::kRuntimeHostPermissions); + + scoped_refptr<const Extension> extension = + ExtensionBuilder("test").AddPermission("<all_urls>").Build(); + service()->AddExtension(extension.get()); + ScriptingPermissionsModifier modifier(profile(), extension.get()); + EXPECT_TRUE(modifier.IsAllowedOnAllUrls()); + modifier.SetAllowedOnAllUrls(false); + + auto run_add_host_permission = [this, extension](base::StringPiece host, + bool should_succeed, + const char* expected_error) { + SCOPED_TRACE(host); + scoped_refptr<UIThreadExtensionFunction> function = + base::MakeRefCounted<api::DeveloperPrivateAddHostPermissionFunction>(); + + std::string args = base::StringPrintf(R"(["%s", "%s"])", + extension->id().c_str(), host.data()); + if (should_succeed) { + EXPECT_TRUE(api_test_utils::RunFunction(function.get(), args, profile())) + << function->GetError(); + } else { + EXPECT_EQ(expected_error, api_test_utils::RunFunctionAndReturnError( + function.get(), args, profile())); + } + }; + + GURL host("https://example.com"); + EXPECT_FALSE(modifier.HasGrantedHostPermission(host)); + run_add_host_permission(host.spec(), true, nullptr); + + run_add_host_permission(kInvalidHost, false, kInvalidHostError); + run_add_host_permission("https://example.com/foobar", false, + kInvalidHostError); + run_add_host_permission("https://example.com/#foobar", false, + kInvalidHostError); + + GURL chrome_host("chrome://settings"); + run_add_host_permission(chrome_host.spec(), false, + "Cannot grant a permission that wasn't withheld."); + EXPECT_FALSE(modifier.HasGrantedHostPermission(chrome_host)); +} + +TEST_F(DeveloperPrivateApiUnitTest, RemoveHostPermission) { + base::test::ScopedFeatureList feature_list; + feature_list.InitAndEnableFeature(features::kRuntimeHostPermissions); + + scoped_refptr<const Extension> extension = + ExtensionBuilder("test").AddPermission("<all_urls>").Build(); + service()->AddExtension(extension.get()); + ScriptingPermissionsModifier modifier(profile(), extension.get()); + EXPECT_TRUE(modifier.IsAllowedOnAllUrls()); + modifier.SetAllowedOnAllUrls(false); + + auto run_remove_host_permission = [this, extension]( + base::StringPiece host, + bool should_succeed, + const char* expected_error) { + SCOPED_TRACE(host); + scoped_refptr<UIThreadExtensionFunction> function = base::MakeRefCounted< + api::DeveloperPrivateRemoveHostPermissionFunction>(); + std::string args = base::StringPrintf(R"(["%s", "%s"])", + extension->id().c_str(), host.data()); + if (should_succeed) { + EXPECT_TRUE(api_test_utils::RunFunction(function.get(), args, profile())) + << function->GetError(); + } else { + EXPECT_EQ(expected_error, api_test_utils::RunFunctionAndReturnError( + function.get(), args, profile())); + } + }; + + GURL host("https://example.com"); + run_remove_host_permission(host.spec(), false, + "Cannot remove a host that hasn't been granted."); + + modifier.GrantHostPermission(host); + EXPECT_TRUE(modifier.HasGrantedHostPermission(host)); + + run_remove_host_permission("https://example.com/foobar", false, + kInvalidHostError); + run_remove_host_permission("https://example.com/#foobar", false, + kInvalidHostError); + run_remove_host_permission(kInvalidHost, false, kInvalidHostError); + EXPECT_TRUE(modifier.HasGrantedHostPermission(host)); + + run_remove_host_permission(host.spec(), true, nullptr); + EXPECT_FALSE(modifier.HasGrantedHostPermission(host)); +} + class DeveloperPrivateZipInstallerUnitTest : public DeveloperPrivateApiUnitTest { public: @@ -1358,7 +1457,7 @@ TEST_F(DeveloperPrivateApiSupervisedUserUnitTest, std::unique_ptr<content::WebContents> web_contents( content::WebContentsTester::CreateTestWebContents(profile(), nullptr)); - base::FilePath path = data_dir().AppendASCII("good_unpacked"); + base::FilePath path = data_dir().AppendASCII("simple_with_popup"); api::EntryPicker::SkipPickerAndAlwaysSelectPathForTest(&path); ASSERT_TRUE(profile()->IsSupervised()); diff --git a/chromium/chrome/browser/extensions/api/developer_private/developer_private_apitest.cc b/chromium/chrome/browser/extensions/api/developer_private/developer_private_apitest.cc index aaa7aced75d..570844d39d4 100644 --- a/chromium/chrome/browser/extensions/api/developer_private/developer_private_apitest.cc +++ b/chromium/chrome/browser/extensions/api/developer_private/developer_private_apitest.cc @@ -34,7 +34,7 @@ IN_PROC_BROWSER_TEST_F(DeveloperPrivateApiTest, Basics) { // Tests opening the developer tools for an app window. IN_PROC_BROWSER_TEST_F(DeveloperPrivateApiTest, InspectAppWindowView) { base::FilePath dir; - PathService::Get(chrome::DIR_TEST_DATA, &dir); + base::PathService::Get(chrome::DIR_TEST_DATA, &dir); dir = dir.AppendASCII("extensions") .AppendASCII("platform_apps") .AppendASCII("minimal"); @@ -85,7 +85,7 @@ IN_PROC_BROWSER_TEST_F(DeveloperPrivateApiTest, InspectAppWindowView) { IN_PROC_BROWSER_TEST_F(DeveloperPrivateApiTest, InspectEmbeddedOptionsPage) { base::FilePath dir; - PathService::Get(chrome::DIR_TEST_DATA, &dir); + base::PathService::Get(chrome::DIR_TEST_DATA, &dir); // Load an extension that only has an embedded options_ui page. const Extension* extension = LoadExtension(dir.AppendASCII("extensions") .AppendASCII("delayed_install") diff --git a/chromium/chrome/browser/extensions/api/developer_private/extension_info_generator.cc b/chromium/chrome/browser/extensions/api/developer_private/extension_info_generator.cc index 15b031d88d6..0b0d24d3096 100644 --- a/chromium/chrome/browser/extensions/api/developer_private/extension_info_generator.cc +++ b/chromium/chrome/browser/extensions/api/developer_private/extension_info_generator.cc @@ -25,7 +25,6 @@ #include "chrome/browser/extensions/shared_module_service.h" #include "chrome/browser/profiles/profile.h" #include "chrome/browser/ui/webui/extensions/extension_icon_source.h" -#include "chrome/common/chrome_features.h" #include "chrome/common/extensions/command.h" #include "chrome/common/extensions/manifest_handlers/app_launch_info.h" #include "chrome/common/pref_names.h" @@ -40,7 +39,6 @@ #include "extensions/browser/path_util.h" #include "extensions/browser/warning_service.h" #include "extensions/common/extension_set.h" -#include "extensions/common/feature_switch.h" #include "extensions/common/install_warning.h" #include "extensions/common/manifest.h" #include "extensions/common/manifest_handlers/background_info.h" @@ -402,7 +400,8 @@ void ExtensionInfoGenerator::CreateExtensionInfoHelper( // File access. ManagementPolicy* management_policy = extension_system_->management_policy(); info->file_access.is_enabled = - extension.wants_file_access() && + (extension.wants_file_access() || + Manifest::ShouldAlwaysAllowFileAccess(extension.location())) && management_policy->UserMayModifySettings(&extension, nullptr); info->file_access.is_active = util::AllowFileAccess(extension.id(), browser_context_); @@ -534,12 +533,9 @@ void ExtensionInfoGenerator::CreateExtensionInfoHelper( // Runs on all urls. ScriptingPermissionsModifier permissions_modifier( browser_context_, base::WrapRefCounted(&extension)); - info->run_on_all_urls.is_enabled = - (FeatureSwitch::scripts_require_action()->IsEnabled() && - permissions_modifier.CanAffectExtension( - extension.permissions_data()->active_permissions())) || - permissions_modifier.HasAffectedExtension(); - info->run_on_all_urls.is_active = permissions_modifier.IsAllowedOnAllUrls(); + info->run_on_all_urls.is_enabled = permissions_modifier.CanAffectExtension(); + info->run_on_all_urls.is_active = info->run_on_all_urls.is_enabled && + permissions_modifier.IsAllowedOnAllUrls(); // Runtime warnings. std::vector<std::string> warnings = @@ -599,37 +595,16 @@ const std::string& ExtensionInfoGenerator::GetDefaultIconUrl( if (str->empty()) { *str = GetIconUrlFromImage( ui::ResourceBundle::GetSharedInstance().GetImageNamed( - is_app ? IDR_APP_DEFAULT_ICON : IDR_EXTENSION_DEFAULT_ICON), - is_greyscale); + is_app ? IDR_APP_DEFAULT_ICON : IDR_EXTENSION_DEFAULT_ICON)); } return *str; } std::string ExtensionInfoGenerator::GetIconUrlFromImage( - const gfx::Image& image, - bool should_greyscale) { - // Ignore |should_greyscale| if MD Extensions are enabled. - // TODO(dpapad): Remove should_greyscale logic once non-MD Extensions UI is - // removed. - should_greyscale = - should_greyscale && - !base::FeatureList::IsEnabled(features::kMaterialDesignExtensions); - + const gfx::Image& image) { scoped_refptr<base::RefCountedMemory> data; - if (should_greyscale) { - color_utils::HSL shift = {-1, 0, 0.6}; - const SkBitmap* bitmap = image.ToSkBitmap(); - DCHECK(bitmap); - SkBitmap grey = SkBitmapOperations::CreateHSLShiftedBitmap(*bitmap, shift); - scoped_refptr<base::RefCountedBytes> image_bytes( - new base::RefCountedBytes()); - gfx::PNGCodec::EncodeBGRASkBitmap(grey, false, &image_bytes->data()); - data = image_bytes; - } else { - data = image.As1xPNGBytes(); - } - + data = image.As1xPNGBytes(); std::string base_64; base::Base64Encode(base::StringPiece(data->front_as<char>(), data->size()), &base_64); @@ -641,8 +616,7 @@ void ExtensionInfoGenerator::OnImageLoaded( std::unique_ptr<developer::ExtensionInfo> info, const gfx::Image& icon) { if (!icon.IsEmpty()) { - info->icon_url = GetIconUrlFromImage( - icon, info->state != developer::EXTENSION_STATE_ENABLED); + info->icon_url = GetIconUrlFromImage(icon); } else { bool is_app = info->type == developer::EXTENSION_TYPE_HOSTED_APP || diff --git a/chromium/chrome/browser/extensions/api/developer_private/extension_info_generator.h b/chromium/chrome/browser/extensions/api/developer_private/extension_info_generator.h index 8fb11cc4305..84628f86bd8 100644 --- a/chromium/chrome/browser/extensions/api/developer_private/extension_info_generator.h +++ b/chromium/chrome/browser/extensions/api/developer_private/extension_info_generator.h @@ -69,9 +69,8 @@ class ExtensionInfoGenerator { // Returns the icon url for the default icon to use. const std::string& GetDefaultIconUrl(bool is_app, bool is_disabled); - // Returns an icon url from the given image, optionally applying a greyscale. - std::string GetIconUrlFromImage(const gfx::Image& image, - bool should_greyscale); + // Returns an icon url from the given image. + std::string GetIconUrlFromImage(const gfx::Image& image); // Various systems, cached for convenience. content::BrowserContext* browser_context_; diff --git a/chromium/chrome/browser/extensions/api/developer_private/extension_info_generator_unittest.cc b/chromium/chrome/browser/extensions/api/developer_private/extension_info_generator_unittest.cc index eac82c44d0b..7e371c03d6d 100644 --- a/chromium/chrome/browser/extensions/api/developer_private/extension_info_generator_unittest.cc +++ b/chromium/chrome/browser/extensions/api/developer_private/extension_info_generator_unittest.cc @@ -15,6 +15,7 @@ #include "base/run_loop.h" #include "base/strings/string_util.h" #include "base/strings/utf_string_conversions.h" +#include "base/test/scoped_feature_list.h" #include "build/build_config.h" #include "chrome/browser/extensions/api/developer_private/inspectable_views_finder.h" #include "chrome/browser/extensions/chrome_test_extension_loader.h" @@ -32,6 +33,7 @@ #include "extensions/common/constants.h" #include "extensions/common/extension.h" #include "extensions/common/extension_builder.h" +#include "extensions/common/extension_features.h" #include "extensions/common/feature_switch.h" #include "extensions/common/permissions/permission_message.h" #include "extensions/common/permissions/permissions_data.h" @@ -253,7 +255,7 @@ TEST_F(ExtensionInfoGeneratorUnitTest, BasicInfoTest) { base::UTF8ToUTF16("message"), StackTrace(1, StackFrame(1, 1, base::UTF8ToUTF16("source"), base::UTF8ToUTF16("function"))), - kContextUrl, logging::LOG_VERBOSE, 1, 1)); + kContextUrl, logging::LOG_WARNING, 1, 1)); // It's not feasible to validate every field here, because that would be // a duplication of the logic in the method itself. Instead, test a handful @@ -301,7 +303,7 @@ TEST_F(ExtensionInfoGeneratorUnitTest, BasicInfoTest) { ASSERT_EQ(1u, info->manifest_errors.size()); const api::developer_private::RuntimeError& runtime_error_verbose = info->runtime_errors[1]; - EXPECT_EQ(api::developer_private::ERROR_LEVEL_LOG, + EXPECT_EQ(api::developer_private::ERROR_LEVEL_WARN, runtime_error_verbose.severity); const api::developer_private::ManifestError& manifest_error = info->manifest_errors[0]; @@ -390,9 +392,9 @@ TEST_F(ExtensionInfoGeneratorUnitTest, GenerateExtensionsJSONData) { // urls, and only when the switch is on. TEST_F(ExtensionInfoGeneratorUnitTest, ExtensionInfoRunOnAllUrls) { // Start with the switch enabled. - std::unique_ptr<FeatureSwitch::ScopedOverride> enable_scripts_switch( - new FeatureSwitch::ScopedOverride(FeatureSwitch::scripts_require_action(), - true)); + auto scoped_feature_list = std::make_unique<base::test::ScopedFeatureList>(); + scoped_feature_list->InitAndEnableFeature(features::kRuntimeHostPermissions); + // Two extensions - one with all urls, one without. scoped_refptr<const Extension> all_urls_extension = CreateExtension( "all_urls", ListBuilder().Append(kAllHostsPermission).Build(), @@ -403,55 +405,31 @@ TEST_F(ExtensionInfoGeneratorUnitTest, ExtensionInfoRunOnAllUrls) { std::unique_ptr<developer::ExtensionInfo> info = GenerateExtensionInfo(all_urls_extension->id()); - // The extension should want all urls, but not currently have it. + // The extension should want all urls, and have it currently granted. EXPECT_TRUE(info->run_on_all_urls.is_enabled); - EXPECT_FALSE(info->run_on_all_urls.is_active); + EXPECT_TRUE(info->run_on_all_urls.is_active); - // Give the extension all urls. + // Revoke the all urls permission. ScriptingPermissionsModifier permissions_modifier(profile(), all_urls_extension); - permissions_modifier.SetAllowedOnAllUrls(true); + permissions_modifier.SetAllowedOnAllUrls(false); - // Now the extension should both want and have all urls. + // Now the extension want all urls, but not have it granted. info = GenerateExtensionInfo(all_urls_extension->id()); EXPECT_TRUE(info->run_on_all_urls.is_enabled); - EXPECT_TRUE(info->run_on_all_urls.is_active); + EXPECT_FALSE(info->run_on_all_urls.is_active); // The other extension should neither want nor have all urls. info = GenerateExtensionInfo(no_urls_extension->id()); EXPECT_FALSE(info->run_on_all_urls.is_enabled); EXPECT_FALSE(info->run_on_all_urls.is_active); - // Revoke the first extension's permissions. - permissions_modifier.SetAllowedOnAllUrls(false); - - // Turn off the switch and load another extension (so permissions are - // re-initialized). - enable_scripts_switch.reset(); - - // Since the extension doesn't have access to all urls (but normally would), - // the extension should have the "want" flag even with the switch off. - info = GenerateExtensionInfo(all_urls_extension->id()); - EXPECT_TRUE(info->run_on_all_urls.is_enabled); - EXPECT_FALSE(info->run_on_all_urls.is_active); - - // If we grant the extension all urls, then the checkbox should still be - // there, since it has an explicitly-set user preference. - permissions_modifier.SetAllowedOnAllUrls(true); - info = GenerateExtensionInfo(all_urls_extension->id()); - EXPECT_TRUE(info->run_on_all_urls.is_enabled); - EXPECT_TRUE(info->run_on_all_urls.is_active); - - // Load another extension with all urls (so permissions get re-init'd). - all_urls_extension = CreateExtension( - "all_urls_II", ListBuilder().Append(kAllHostsPermission).Build(), - Manifest::INTERNAL); - - // Even though the extension has all_urls permission, the checkbox shouldn't - // show up without the switch. + // Turn off the switch. With the switch off, the run_on_all_urls control + // should never be enabled. + scoped_feature_list.reset(); info = GenerateExtensionInfo(all_urls_extension->id()); EXPECT_FALSE(info->run_on_all_urls.is_enabled); - EXPECT_TRUE(info->run_on_all_urls.is_active); + EXPECT_FALSE(info->run_on_all_urls.is_active); } // Test that file:// access checkbox does not show up when the user can't @@ -472,6 +450,20 @@ TEST_F(ExtensionInfoGeneratorUnitTest, ExtensionInfoLockedAllUrls) { EXPECT_FALSE(info->file_access.is_active); } +// Tests that file:// access checkbox shows up for extensions with activeTab +// permission. See crbug.com/850643. +TEST_F(ExtensionInfoGeneratorUnitTest, ActiveTabFileUrls) { + scoped_refptr<const Extension> extension = + CreateExtension("activeTab", ListBuilder().Append("activeTab").Build(), + Manifest::INTERNAL); + std::unique_ptr<developer::ExtensionInfo> info = + GenerateExtensionInfo(extension->id()); + + EXPECT_TRUE(extension->wants_file_access()); + EXPECT_TRUE(info->file_access.is_enabled); + EXPECT_FALSE(info->file_access.is_active); +} + // Tests that blacklisted extensions are returned by the ExtensionInfoGenerator. TEST_F(ExtensionInfoGeneratorUnitTest, Blacklisted) { const scoped_refptr<const Extension> extension1 = CreateExtension( diff --git a/chromium/chrome/browser/extensions/api/downloads/downloads_api.cc b/chromium/chrome/browser/extensions/api/downloads/downloads_api.cc index b09f914f0ca..7d33e085088 100644 --- a/chromium/chrome/browser/extensions/api/downloads/downloads_api.cc +++ b/chromium/chrome/browser/extensions/api/downloads/downloads_api.cc @@ -24,7 +24,7 @@ #include "base/macros.h" #include "base/memory/ptr_util.h" #include "base/memory/weak_ptr.h" -#include "base/message_loop/message_loop.h" +#include "base/message_loop/message_loop_current.h" #include "base/metrics/histogram_macros.h" #include "base/single_thread_task_runner.h" #include "base/stl_util.h" @@ -41,6 +41,7 @@ #include "chrome/browser/download/download_core_service_factory.h" #include "chrome/browser/download/download_danger_prompt.h" #include "chrome/browser/download/download_file_icon_extractor.h" +#include "chrome/browser/download/download_open_prompt.h" #include "chrome/browser/download/download_prefs.h" #include "chrome/browser/download/download_query.h" #include "chrome/browser/download/download_shelf.h" @@ -149,6 +150,7 @@ const char kDangerKey[] = "danger"; const char kDangerSafe[] = "safe"; const char kDangerUncommon[] = "uncommon"; const char kDangerUnwanted[] = "unwanted"; +const char kDangerWhitelistedByPolicy[] = "whitelistedByPolicy"; const char kDangerUrl[] = "url"; const char kEndTimeKey[] = "endTime"; const char kEndedAfterKey[] = "endedAfter"; @@ -183,16 +185,11 @@ const char kFinalUrlRegexKey[] = "finalUrlRegex"; // Note: Any change to the danger type strings, should be accompanied by a // corresponding change to downloads.json. const char* const kDangerStrings[] = { - kDangerSafe, - kDangerFile, - kDangerUrl, - kDangerContent, - kDangerSafe, - kDangerUncommon, - kDangerAccepted, - kDangerHost, - kDangerUnwanted -}; + kDangerSafe, kDangerFile, + kDangerUrl, kDangerContent, + kDangerSafe, kDangerUncommon, + kDangerAccepted, kDangerHost, + kDangerUnwanted, kDangerWhitelistedByPolicy}; static_assert(arraysize(kDangerStrings) == download::DOWNLOAD_DANGER_TYPE_MAX, "kDangerStrings should have DOWNLOAD_DANGER_TYPE_MAX elements"); @@ -636,7 +633,11 @@ class ExtensionDownloadsEventRouterData : public base::SupportsUserData::Data { json_(std::move(json_item)), creator_conflict_action_(downloads::FILENAME_CONFLICT_ACTION_UNIQUIFY), determined_conflict_action_( - downloads::FILENAME_CONFLICT_ACTION_UNIQUIFY) { + downloads::FILENAME_CONFLICT_ACTION_UNIQUIFY), + is_download_completed_(download_item->GetState() == + DownloadItem::COMPLETE), + is_completed_download_deleted_( + download_item->GetFileExternallyRemoved()) { DCHECK_CURRENTLY_ON(BrowserThread::UI); download_item->SetUserData(kKey, base::WrapUnique(this)); } @@ -648,6 +649,16 @@ class ExtensionDownloadsEventRouterData : public base::SupportsUserData::Data { } } + void set_is_download_completed(bool is_download_completed) { + is_download_completed_ = is_download_completed; + } + void set_is_completed_download_deleted(bool is_completed_download_deleted) { + is_completed_download_deleted_ = is_completed_download_deleted; + } + bool is_download_completed() { return is_download_completed_; } + bool is_completed_download_deleted() { + return is_completed_download_deleted_; + } const base::DictionaryValue& json() const { return *json_; } void set_json(std::unique_ptr<base::DictionaryValue> json_item) { json_ = std::move(json_item); @@ -869,6 +880,8 @@ class ExtensionDownloadsEventRouterData : public base::SupportsUserData::Data { int updated_; int changed_fired_; + // Dictionary representing the current state of the download. It is cleared + // when download completes. std::unique_ptr<base::DictionaryValue> json_; base::Closure filename_no_change_; @@ -884,6 +897,11 @@ class ExtensionDownloadsEventRouterData : public base::SupportsUserData::Data { determined_conflict_action_; DeterminerInfo determiner_; + // Whether a download is complete and whether the completed download is + // deleted. + bool is_download_completed_; + bool is_completed_download_deleted_; + std::unique_ptr<base::WeakPtrFactory<ExtensionDownloadsEventRouterData>> weak_ptr_factory_; @@ -1410,6 +1428,9 @@ ExtensionFunction::ResponseAction DownloadsShowDefaultFolderFunction::Run() { return RespondNow(NoArguments()); } +DownloadsOpenFunction::OnPromptCreatedCallback* + DownloadsOpenFunction::on_prompt_created_cb_ = nullptr; + DownloadsOpenFunction::DownloadsOpenFunction() {} DownloadsOpenFunction::~DownloadsOpenFunction() {} @@ -1430,9 +1451,48 @@ ExtensionFunction::ResponseAction DownloadsOpenFunction::Run() { errors::kOpenPermission, &error)) { return RespondNow(Error(error)); } - download_item->OpenDownload(); + Browser* browser = ChromeExtensionFunctionDetails(this).GetCurrentBrowser(); + if (Fault(!browser, errors::kInvisibleContext, &error)) + return RespondNow(Error(error)); + content::WebContents* web_contents = + browser->tab_strip_model()->GetActiveWebContents(); + if (Fault(!web_contents, errors::kInvisibleContext, &error)) + return RespondNow(Error(error)); + if (GetSenderWebContents() && + GetSenderWebContents()->HasRecentInteractiveInputEvent()) { + download_item->OpenDownload(); + return RespondNow(NoArguments()); + } + // Prompt user for ack to open the download. + // TODO(qinmin): check if user prefers to open all download using the same + // extension, or check the recent user gesture on the originating webcontents + // to avoid showing the prompt. + DownloadOpenPrompt* download_open_prompt = + DownloadOpenPrompt::CreateDownloadOpenConfirmationDialog( + web_contents, extension()->name(), download_item->GetFullPath(), + base::BindOnce(&DownloadsOpenFunction::OpenPromptDone, this, + params->download_id)); + if (on_prompt_created_cb_) + std::move(*on_prompt_created_cb_).Run(download_open_prompt); RecordApiFunctions(DOWNLOADS_FUNCTION_OPEN); - return RespondNow(NoArguments()); + return RespondLater(); +} + +void DownloadsOpenFunction::OpenPromptDone(int download_id, bool accept) { + DCHECK_CURRENTLY_ON(BrowserThread::UI); + std::string error; + if (Fault(!accept, errors::kOpenPermission, &error)) { + Respond(Error(error)); + return; + } + DownloadItem* download_item = + GetDownload(browser_context(), include_incognito(), download_id); + if (Fault(!download_item, errors::kFileAlreadyDeleted, &error)) { + Respond(Error(error)); + return; + } + download_item->OpenDownload(); + Respond(NoArguments()); } DownloadsDragFunction::DownloadsDragFunction() {} @@ -1458,8 +1518,7 @@ ExtensionFunction::ResponseAction DownloadsDragFunction::Run() { gfx::NativeView view = web_contents->GetNativeView(); { // Enable nested tasks during DnD, while |DragDownload()| blocks. - base::MessageLoop::ScopedNestableTaskAllower allow( - base::MessageLoop::current()); + base::MessageLoopCurrent::ScopedNestableTaskAllower allow; DragDownloadItem(download_item, icon, view); } return RespondNow(NoArguments()); @@ -1827,6 +1886,9 @@ void ExtensionDownloadsEventRouter::OnDownloadCreated( downloads::OnDeterminingFilename::kEventName))) { return; } + + // download_item->GetFileExternallyRemoved() should always return false for + // unfinished download. std::unique_ptr<base::DictionaryValue> json_item( DownloadItemToJSON(download_item, profile_)); DispatchEvent(events::DOWNLOADS_ON_CREATED, downloads::OnCreated::kEventName, @@ -1836,7 +1898,10 @@ void ExtensionDownloadsEventRouter::OnDownloadCreated( (router->HasEventListener(downloads::OnChanged::kEventName) || router->HasEventListener( downloads::OnDeterminingFilename::kEventName))) { - new ExtensionDownloadsEventRouterData(download_item, std::move(json_item)); + new ExtensionDownloadsEventRouterData( + download_item, download_item->GetState() == DownloadItem::COMPLETE + ? nullptr + : std::move(json_item)); } } @@ -1857,44 +1922,65 @@ void ExtensionDownloadsEventRouter::OnDownloadUpdated( download_item, std::unique_ptr<base::DictionaryValue>(new base::DictionaryValue())); } - std::unique_ptr<base::DictionaryValue> new_json( - DownloadItemToJSON(download_item, profile_)); + std::unique_ptr<base::DictionaryValue> new_json; std::unique_ptr<base::DictionaryValue> delta(new base::DictionaryValue()); delta->SetInteger(kIdKey, download_item->GetId()); - std::set<std::string> new_fields; bool changed = false; + // For completed downloads, update can only happen when file is removed. + if (data->is_download_completed()) { + if (data->is_completed_download_deleted() != + download_item->GetFileExternallyRemoved()) { + DCHECK(!data->is_completed_download_deleted()); + DCHECK(download_item->GetFileExternallyRemoved()); + std::string exists = kExistsKey; + delta->SetBoolean(exists + ".current", false); + delta->SetBoolean(exists + ".previous", true); + changed = true; + } + } else { + new_json = DownloadItemToJSON(download_item, profile_); + std::set<std::string> new_fields; + // For each field in the new json representation of the download_item except + // the bytesReceived field, if the field has changed from the previous old + // json, set the differences in the |delta| object and remember that + // something significant changed. + for (base::DictionaryValue::Iterator iter(*new_json); !iter.IsAtEnd(); + iter.Advance()) { + new_fields.insert(iter.key()); + if (IsDownloadDeltaField(iter.key())) { + const base::Value* old_value = NULL; + if (!data->json().HasKey(iter.key()) || + (data->json().Get(iter.key(), &old_value) && + !iter.value().Equals(old_value))) { + delta->Set(iter.key() + ".current", iter.value().CreateDeepCopy()); + if (old_value) + delta->Set(iter.key() + ".previous", old_value->CreateDeepCopy()); + changed = true; + } + } + } - // For each field in the new json representation of the download_item except - // the bytesReceived field, if the field has changed from the previous old - // json, set the differences in the |delta| object and remember that something - // significant changed. - for (base::DictionaryValue::Iterator iter(*new_json); !iter.IsAtEnd(); - iter.Advance()) { - new_fields.insert(iter.key()); - if (IsDownloadDeltaField(iter.key())) { - const base::Value* old_value = NULL; - if (!data->json().HasKey(iter.key()) || - (data->json().Get(iter.key(), &old_value) && - !iter.value().Equals(old_value))) { - delta->Set(iter.key() + ".current", iter.value().CreateDeepCopy()); - if (old_value) - delta->Set(iter.key() + ".previous", old_value->CreateDeepCopy()); + // If a field was in the previous json but is not in the new json, set the + // difference in |delta|. + for (base::DictionaryValue::Iterator iter(data->json()); !iter.IsAtEnd(); + iter.Advance()) { + if ((new_fields.find(iter.key()) == new_fields.end()) && + IsDownloadDeltaField(iter.key())) { + // estimatedEndTime disappears after completion, but bytesReceived + // stays. + delta->Set(iter.key() + ".previous", iter.value().CreateDeepCopy()); changed = true; } } } - // If a field was in the previous json but is not in the new json, set the - // difference in |delta|. - for (base::DictionaryValue::Iterator iter(data->json()); - !iter.IsAtEnd(); iter.Advance()) { - if ((new_fields.find(iter.key()) == new_fields.end()) && - IsDownloadDeltaField(iter.key())) { - // estimatedEndTime disappears after completion, but bytesReceived stays. - delta->Set(iter.key() + ".previous", iter.value().CreateDeepCopy()); - changed = true; - } - } + data->set_is_download_completed(download_item->GetState() == + DownloadItem::COMPLETE); + // download_item->GetFileExternallyRemoved() should always return false for + // unfinished download. + data->set_is_completed_download_deleted( + download_item->GetFileExternallyRemoved()); + data->set_json(std::move(new_json)); // Update the OnChangedStat and dispatch the event if something significant // changed. Replace the stored json with the new json. @@ -1905,7 +1991,6 @@ void ExtensionDownloadsEventRouter::OnDownloadUpdated( Event::WillDispatchCallback(), std::move(delta)); data->OnChangedFired(); } - data->set_json(std::move(new_json)); } void ExtensionDownloadsEventRouter::OnDownloadRemoved( diff --git a/chromium/chrome/browser/extensions/api/downloads/downloads_api.h b/chromium/chrome/browser/extensions/api/downloads/downloads_api.h index cd6e5759ce8..77c386894fc 100644 --- a/chromium/chrome/browser/extensions/api/downloads/downloads_api.h +++ b/chromium/chrome/browser/extensions/api/downloads/downloads_api.h @@ -24,6 +24,7 @@ #include "extensions/browser/warning_set.h" class DownloadFileIconExtractor; +class DownloadOpenPrompt; namespace extensions { class ExtensionRegistry; @@ -243,10 +244,20 @@ class DownloadsOpenFunction : public UIThreadExtensionFunction { DownloadsOpenFunction(); ResponseAction Run() override; + typedef base::OnceCallback<void(DownloadOpenPrompt*)> OnPromptCreatedCallback; + static void set_on_prompt_created_cb_for_testing( + OnPromptCreatedCallback* on_prompt_created_cb) { + on_prompt_created_cb_ = on_prompt_created_cb; + } + protected: ~DownloadsOpenFunction() override; private: + void OpenPromptDone(int download_id, bool accept); + + static OnPromptCreatedCallback* on_prompt_created_cb_; + DISALLOW_COPY_AND_ASSIGN(DownloadsOpenFunction); }; diff --git a/chromium/chrome/browser/extensions/api/downloads/downloads_api_browsertest.cc b/chromium/chrome/browser/extensions/api/downloads/downloads_api_browsertest.cc index 97f0d633093..67974097916 100644 --- a/chromium/chrome/browser/extensions/api/downloads/downloads_api_browsertest.cc +++ b/chromium/chrome/browser/extensions/api/downloads/downloads_api_browsertest.cc @@ -14,7 +14,7 @@ #include "base/json/json_reader.h" #include "base/macros.h" #include "base/memory/ptr_util.h" -#include "base/message_loop/message_loop.h" +#include "base/message_loop/message_loop_current.h" #include "base/run_loop.h" #include "base/strings/stringprintf.h" #include "base/test/bind_test_util.h" @@ -23,6 +23,7 @@ #include "chrome/browser/download/download_core_service.h" #include "chrome/browser/download/download_core_service_factory.h" #include "chrome/browser/download/download_file_icon_extractor.h" +#include "chrome/browser/download/download_open_prompt.h" #include "chrome/browser/download/download_prefs.h" #include "chrome/browser/download/download_test_file_activity_observer.h" #include "chrome/browser/extensions/api/downloads/downloads_api.h" @@ -51,6 +52,7 @@ #include "content/public/common/content_features.h" #include "content/public/test/download_test_observer.h" #include "content/public/test/test_download_http_response.h" +#include "content/public/test/test_navigation_observer.h" #include "content/public/test/test_utils.h" #include "extensions/browser/event_router.h" #include "extensions/browser/notification_types.h" @@ -85,6 +87,8 @@ const char kFirstDownloadUrl[] = "/download1"; const char kSecondDownloadUrl[] = "/download2"; const int kDownloadSize = 1024 * 10; +void OnFileDeleted(bool success) {} + // Comparator that orders download items by their ID. Can be used with // std::sort. struct DownloadIdComparator { @@ -97,6 +101,16 @@ bool IsDownloadExternallyRemoved(download::DownloadItem* item) { return item->GetFileExternallyRemoved(); } +void OnOpenPromptCreated(download::DownloadItem* item, + DownloadOpenPrompt* prompt) { + EXPECT_FALSE(item->GetOpened()); + // Posts a task to accept the DownloadOpenPrompt. + BrowserThread::PostTask( + BrowserThread::UI, FROM_HERE, + base::BindOnce(&DownloadOpenPrompt::AcceptConfirmationDialogForTesting, + base::Unretained(prompt))); +} + class DownloadsEventsListener : public content::NotificationObserver { public: DownloadsEventsListener() @@ -245,6 +259,8 @@ class DownloadsEventsListener : public content::NotificationObserver { return success; } + base::circular_deque<std::unique_ptr<Event>>* events() { return &events_; } + private: bool waiting_; base::Time last_wait_; @@ -255,6 +271,44 @@ class DownloadsEventsListener : public content::NotificationObserver { DISALLOW_COPY_AND_ASSIGN(DownloadsEventsListener); }; +// Object waiting for a download open event. +class DownloadOpenObserver : public download::DownloadItem::Observer { + public: + explicit DownloadOpenObserver(download::DownloadItem* item) + : open_observer_(this), item_(item) { + open_observer_.Add(item); + } + + ~DownloadOpenObserver() override = default; + + void WaitForEvent() { + if (item_ && !item_->GetOpened()) { + base::RunLoop run_loop; + completion_closure_ = run_loop.QuitClosure(); + run_loop.Run(); + } + } + + private: + // download::DownloadItem::Observer + void OnDownloadOpened(download::DownloadItem* item) override { + if (!completion_closure_.is_null()) + std::move(completion_closure_).Run(); + } + + void OnDownloadDestroyed(download::DownloadItem* item) override { + open_observer_.Remove(item); + item_ = nullptr; + } + + ScopedObserver<download::DownloadItem, download::DownloadItem::Observer> + open_observer_; + download::DownloadItem* item_; + base::OnceClosure completion_closure_; + + DISALLOW_COPY_AND_ASSIGN(DownloadOpenObserver); +}; + class DownloadExtensionTest : public ExtensionApiTest { public: DownloadExtensionTest() @@ -600,6 +654,8 @@ class DownloadExtensionTest : public ExtensionApiTest { DownloadsEventsListener* events_listener() { return events_listener_.get(); } + const Extension* extension() { return extension_; } + private: void SetUpExtensionFunction(UIThreadExtensionFunction* function) { if (extension_) { @@ -860,12 +916,34 @@ IN_PROC_BROWSER_TEST_F(DownloadExtensionTest, RunFunctionAndReturnError( open_function, DownloadItemIdAsArgList(download_item)).c_str()); + // RunFunctionAndReturnError() will trigger a navigation. Wait for it to + // finish before showing the prompt dialog. Otherwise the dialog will get + // automatically closed. + content::TestNavigationObserver navigation_observer( + browser()->tab_strip_model()->GetActiveWebContents()); + navigation_observer.WaitForNavigationFinished(); EXPECT_FALSE(download_item->GetOpened()); - open_function = new DownloadsOpenFunction(); - open_function->set_user_gesture(true); - EXPECT_TRUE(RunFunction(open_function, - DownloadItemIdAsArgList(download_item))); + scoped_refptr<DownloadsOpenFunction> scoped_open(new DownloadsOpenFunction()); + scoped_open->set_user_gesture(true); + base::ListValue list_value; + list_value.GetList().emplace_back(static_cast<int>(download_item->GetId())); + scoped_open->SetArgs(&list_value); + scoped_open->set_browser_context(browser()->profile()); + scoped_open->set_extension(extension()); + DownloadsOpenFunction::OnPromptCreatedCallback callback = + base::BindOnce(&OnOpenPromptCreated, base::Unretained(download_item)); + DownloadsOpenFunction::set_on_prompt_created_cb_for_testing(&callback); + api_test_utils::SendResponseHelper response_helper(scoped_open.get()); + std::unique_ptr<ExtensionFunctionDispatcher> dispatcher( + new ExtensionFunctionDispatcher(browser()->profile())); + scoped_open->set_dispatcher(dispatcher->AsWeakPtr()); + scoped_open->RunWithValidation()->Execute(); + response_helper.WaitForResponse(); + EXPECT_TRUE(response_helper.has_response()); + EXPECT_TRUE(response_helper.GetResponse()); + DownloadOpenObserver observer(download_item); + observer.WaitForEvent(); EXPECT_TRUE(download_item->GetOpened()); } @@ -1718,7 +1796,7 @@ class CustomResponse : public net::test_server::HttpResponse { if (first_request_) { *callback_ = std::move(done); - *task_runner_ = base::MessageLoop::current()->task_runner().get(); + *task_runner_ = base::MessageLoopCurrent::Get()->task_runner().get(); send.Run(response, base::BindRepeating([]() {})); } else { send.Run(response, std::move(done)); @@ -4345,6 +4423,52 @@ IN_PROC_BROWSER_TEST_F(DownloadExtensionTest, observer->WaitForFinished(); } +// Test that file deletion event is correctly generated after download +// completion. +IN_PROC_BROWSER_TEST_F(DownloadExtensionTest, + DownloadExtensionTest_DeleteFileAfterCompletion) { + ASSERT_TRUE(StartEmbeddedTestServer()); + GoOnTheRecord(); + LoadExtension("downloads_split"); + std::string download_url = embedded_test_server()->GetURL("/slow?0").spec(); + + // Start downloading a file. + std::unique_ptr<base::Value> result(RunFunctionAndReturnResult( + new DownloadsDownloadFunction(), + base::StringPrintf("[{\"url\": \"%s\"}]", download_url.c_str()))); + ASSERT_TRUE(result.get()); + int result_id = -1; + ASSERT_TRUE(result->GetAsInteger(&result_id)); + DownloadItem* item = GetCurrentManager()->GetDownload(result_id); + ASSERT_TRUE(item); + ScopedCancellingItem canceller(item); + ASSERT_EQ(download_url, item->GetOriginalUrl().spec()); + + ASSERT_TRUE(WaitFor(downloads::OnCreated::kEventName, + base::StringPrintf(R"([{"danger": "safe",)" + R"( "incognito": false,)" + R"( "id": %d,)" + R"( "mime": "text/plain",)" + R"( "paused": false,)" + R"( "url": "%s"}])", + result_id, download_url.c_str()))); + ASSERT_TRUE(WaitFor(downloads::OnChanged::kEventName, + base::StringPrintf(R"([{"id": %d,)" + R"( "state": {)" + R"( "previous": "in_progress",)" + R"( "current": "complete"}}])", + result_id))); + + item->DeleteFile(base::BindRepeating(OnFileDeleted)); + + ASSERT_TRUE(WaitFor(downloads::OnChanged::kEventName, + base::StringPrintf(R"([{"id": %d,)" + R"( "exists": {)" + R"( "previous": true,)" + R"( "current": false}}])", + result_id))); +} + class DownloadsApiTest : public ExtensionApiTest { public: DownloadsApiTest() {} diff --git a/chromium/chrome/browser/extensions/api/easy_unlock_private/easy_unlock_private_api.cc b/chromium/chrome/browser/extensions/api/easy_unlock_private/easy_unlock_private_api.cc index 6692d07a51f..0a705f95d3e 100644 --- a/chromium/chrome/browser/extensions/api/easy_unlock_private/easy_unlock_private_api.cc +++ b/chromium/chrome/browser/extensions/api/easy_unlock_private/easy_unlock_private_api.cc @@ -27,29 +27,28 @@ #include "chrome/browser/chromeos/login/easy_unlock/easy_unlock_tpm_key_manager.h" #include "chrome/browser/chromeos/login/easy_unlock/easy_unlock_tpm_key_manager_factory.h" #include "chrome/browser/extensions/api/easy_unlock_private/easy_unlock_private_connection_manager.h" -#include "chrome/browser/extensions/api/easy_unlock_private/easy_unlock_private_crypto_delegate.h" #include "chrome/browser/profiles/profile.h" #include "chrome/browser/ui/proximity_auth/proximity_auth_error_bubble.h" #include "chrome/common/extensions/api/easy_unlock_private.h" #include "chrome/grit/generated_resources.h" #include "chromeos/components/proximity_auth/bluetooth_low_energy_setup_connection_finder.h" -#include "chromeos/components/proximity_auth/bluetooth_util.h" #include "chromeos/components/proximity_auth/logging/logging.h" #include "chromeos/components/proximity_auth/proximity_auth_client.h" #include "chromeos/components/proximity_auth/screenlock_bridge.h" #include "chromeos/components/proximity_auth/screenlock_state.h" #include "chromeos/components/proximity_auth/switches.h" +#include "components/account_id/account_id.h" #include "components/cryptauth/cryptauth_device_manager.h" #include "components/cryptauth/cryptauth_enrollment_manager.h" #include "components/cryptauth/cryptauth_enrollment_utils.h" #include "components/cryptauth/proto/cryptauth_api.pb.h" #include "components/cryptauth/remote_device.h" #include "components/cryptauth/secure_message_delegate_impl.h" -#include "components/signin/core/account_id/account_id.h" #include "components/strings/grit/components_strings.h" #include "components/user_manager/user_manager.h" #include "content/public/browser/web_contents.h" #include "extensions/browser/browser_context_keyed_api_factory.h" +#include "extensions/browser/view_type_utils.h" #include "ui/base/l10n/l10n_util.h" #include "ui/chromeos/devicetype_utils.h" #include "ui/gfx/geometry/rect.h" @@ -67,13 +66,6 @@ static base::LazyInstance<BrowserContextKeyedAPIFactory<EasyUnlockPrivateAPI>>:: DestructorAtExit g_easy_unlock_private_api_factory = LAZY_INSTANCE_INITIALIZER; -// Utility method for getting the API's crypto delegate. -EasyUnlockPrivateCryptoDelegate* GetCryptoDelegate( - content::BrowserContext* context) { - return BrowserContextKeyedAPIFactory<EasyUnlockPrivateAPI>::Get(context) - ->GetCryptoDelegate(); -} - EasyUnlockPrivateConnectionManager* GetConnectionManager( content::BrowserContext* context) { return BrowserContextKeyedAPIFactory<EasyUnlockPrivateAPI>::Get(context) @@ -93,12 +85,6 @@ EasyUnlockPrivateAPI::EasyUnlockPrivateAPI(content::BrowserContext* context) EasyUnlockPrivateAPI::~EasyUnlockPrivateAPI() {} -EasyUnlockPrivateCryptoDelegate* EasyUnlockPrivateAPI::GetCryptoDelegate() { - if (!crypto_delegate_) - crypto_delegate_ = EasyUnlockPrivateCryptoDelegate::Create(); - return crypto_delegate_.get(); -} - void EasyUnlockPrivateAPI::Shutdown() { // Any dependency which references BrowserContext must be cleaned up here. connection_manager_.reset(); @@ -318,369 +304,6 @@ ExtensionFunction::ResponseAction EasyUnlockPrivateGetStringsFunction::Run() { return RespondNow(OneArgument(std::move(strings))); } -EasyUnlockPrivatePerformECDHKeyAgreementFunction:: -EasyUnlockPrivatePerformECDHKeyAgreementFunction() {} - -EasyUnlockPrivatePerformECDHKeyAgreementFunction:: -~EasyUnlockPrivatePerformECDHKeyAgreementFunction() {} - -ExtensionFunction::ResponseAction -EasyUnlockPrivatePerformECDHKeyAgreementFunction::Run() { - std::unique_ptr<easy_unlock_private::PerformECDHKeyAgreement::Params> params = - easy_unlock_private::PerformECDHKeyAgreement::Params::Create(*args_); - EXTENSION_FUNCTION_VALIDATE(params); - - GetCryptoDelegate(browser_context())->PerformECDHKeyAgreement( - *params, - base::Bind(&EasyUnlockPrivatePerformECDHKeyAgreementFunction::OnData, - this)); - // TODO(https://crbug.com/829182): Resolve this. - return did_respond() ? AlreadyResponded() : RespondLater(); -} - -void EasyUnlockPrivatePerformECDHKeyAgreementFunction::OnData( - const std::string& secret_key) { - // TODO(tbarzic): Improve error handling. - if (!secret_key.empty()) { - Respond(ArgumentList( - easy_unlock_private::PerformECDHKeyAgreement::Results::Create( - std::vector<char>(secret_key.begin(), secret_key.end())))); - return; - } - - Respond(NoArguments()); -} - -EasyUnlockPrivateGenerateEcP256KeyPairFunction:: -EasyUnlockPrivateGenerateEcP256KeyPairFunction() {} - -EasyUnlockPrivateGenerateEcP256KeyPairFunction:: -~EasyUnlockPrivateGenerateEcP256KeyPairFunction() {} - -ExtensionFunction::ResponseAction -EasyUnlockPrivateGenerateEcP256KeyPairFunction::Run() { - GetCryptoDelegate(browser_context())->GenerateEcP256KeyPair( - base::Bind(&EasyUnlockPrivateGenerateEcP256KeyPairFunction::OnData, - this)); - // TODO(https://crbug.com/829182): Resolve this. - return did_respond() ? AlreadyResponded() : RespondLater(); -} - -void EasyUnlockPrivateGenerateEcP256KeyPairFunction::OnData( - const std::string& private_key, - const std::string& public_key) { - // TODO(tbarzic): Improve error handling. - if (!public_key.empty() && !private_key.empty()) { - Respond(ArgumentList( - easy_unlock_private::GenerateEcP256KeyPair::Results::Create( - std::vector<char>(public_key.begin(), public_key.end()), - std::vector<char>(private_key.begin(), private_key.end())))); - return; - } - - Respond(NoArguments()); -} - -EasyUnlockPrivateCreateSecureMessageFunction:: -EasyUnlockPrivateCreateSecureMessageFunction() {} - -EasyUnlockPrivateCreateSecureMessageFunction:: -~EasyUnlockPrivateCreateSecureMessageFunction() {} - -ExtensionFunction::ResponseAction -EasyUnlockPrivateCreateSecureMessageFunction::Run() { - std::unique_ptr<easy_unlock_private::CreateSecureMessage::Params> params = - easy_unlock_private::CreateSecureMessage::Params::Create(*args_); - EXTENSION_FUNCTION_VALIDATE(params); - - GetCryptoDelegate(browser_context())->CreateSecureMessage( - *params, - base::Bind(&EasyUnlockPrivateCreateSecureMessageFunction::OnData, - this)); - // TODO(https://crbug.com/829182): Resolve this. - return did_respond() ? AlreadyResponded() : RespondLater(); -} - -void EasyUnlockPrivateCreateSecureMessageFunction::OnData( - const std::string& message) { - // TODO(tbarzic): Improve error handling. - if (!message.empty()) { - Respond( - ArgumentList(easy_unlock_private::CreateSecureMessage::Results::Create( - std::vector<char>(message.begin(), message.end())))); - return; - } - - Respond(NoArguments()); -} - -EasyUnlockPrivateUnwrapSecureMessageFunction:: -EasyUnlockPrivateUnwrapSecureMessageFunction() {} - -EasyUnlockPrivateUnwrapSecureMessageFunction:: -~EasyUnlockPrivateUnwrapSecureMessageFunction() {} - -ExtensionFunction::ResponseAction -EasyUnlockPrivateUnwrapSecureMessageFunction::Run() { - std::unique_ptr<easy_unlock_private::UnwrapSecureMessage::Params> params = - easy_unlock_private::UnwrapSecureMessage::Params::Create(*args_); - EXTENSION_FUNCTION_VALIDATE(params); - - GetCryptoDelegate(browser_context())->UnwrapSecureMessage( - *params, - base::Bind(&EasyUnlockPrivateUnwrapSecureMessageFunction::OnData, - this)); - // TODO(https://crbug.com/829182): Resolve this. - return did_respond() ? AlreadyResponded() : RespondLater(); -} - -void EasyUnlockPrivateUnwrapSecureMessageFunction::OnData( - const std::string& data) { - // TODO(tbarzic): Improve error handling. - if (!data.empty()) { - Respond( - ArgumentList(easy_unlock_private::UnwrapSecureMessage::Results::Create( - std::vector<char>(data.begin(), data.end())))); - return; - } - - Respond(NoArguments()); -} - -EasyUnlockPrivateGetPermitAccessFunction:: - EasyUnlockPrivateGetPermitAccessFunction() { -} - -EasyUnlockPrivateGetPermitAccessFunction:: - ~EasyUnlockPrivateGetPermitAccessFunction() { -} - -ExtensionFunction::ResponseAction -EasyUnlockPrivateGetPermitAccessFunction::Run() { - // Check that we are inside a user session. - Profile* profile = Profile::FromBrowserContext(browser_context()); - chromeos::EasyUnlockService* easy_unlock_service = - chromeos::EasyUnlockService::Get(profile); - if (easy_unlock_service->GetType() != - chromeos::EasyUnlockService::TYPE_REGULAR) { - return RespondNow( - Error("This function must be called inside a user session.")); - } - - std::string b64_public_key, b64_private_key; - GetKeyPairForExperiment(&b64_public_key, &b64_private_key); - - // Fill in the permit access JSON dictionary. - proximity_auth::ProximityAuthClient* client = - easy_unlock_service->proximity_auth_client(); - std::unique_ptr<base::DictionaryValue> permit_access( - new base::DictionaryValue()); - permit_access->SetString("permitId", - "permit://google.com/" + client->GetAccountId()); - permit_access->SetString("id", b64_public_key); - permit_access->SetString("type", "access"); - permit_access->SetString("data", b64_private_key); - - PA_LOG(INFO) << "Returning permit access for " - << "chrome.easyUnlockPrivate.getPermitAccess:\n" - << " id: " << b64_public_key; - - return RespondNow(OneArgument(std::move(permit_access))); -} - -void EasyUnlockPrivateGetPermitAccessFunction::GetKeyPairForExperiment( - std::string* user_public_key, - std::string* user_private_key) { - Profile* profile = Profile::FromBrowserContext(browser_context()); - cryptauth::CryptAuthEnrollmentManager* enrollment_manager = - chromeos::EasyUnlockService::Get(profile) - ->proximity_auth_client() - ->GetCryptAuthEnrollmentManager(); - base::Base64UrlEncode(enrollment_manager->GetUserPublicKey(), - base::Base64UrlEncodePolicy::INCLUDE_PADDING, - user_public_key); - base::Base64UrlEncode(enrollment_manager->GetUserPrivateKey(), - base::Base64UrlEncodePolicy::INCLUDE_PADDING, - user_private_key); -} - -EasyUnlockPrivateClearPermitAccessFunction:: - EasyUnlockPrivateClearPermitAccessFunction() { -} - -EasyUnlockPrivateClearPermitAccessFunction:: - ~EasyUnlockPrivateClearPermitAccessFunction() { -} - -ExtensionFunction::ResponseAction -EasyUnlockPrivateClearPermitAccessFunction::Run() { - Profile* profile = Profile::FromBrowserContext(browser_context()); - chromeos::EasyUnlockService::Get(profile)->ClearPermitAccess(); - return RespondNow(NoArguments()); -} - -EasyUnlockPrivateSetRemoteDevicesFunction:: - EasyUnlockPrivateSetRemoteDevicesFunction() { -} - -EasyUnlockPrivateSetRemoteDevicesFunction:: - ~EasyUnlockPrivateSetRemoteDevicesFunction() { -} - -ExtensionFunction::ResponseAction -EasyUnlockPrivateSetRemoteDevicesFunction::Run() { - std::unique_ptr<easy_unlock_private::SetRemoteDevices::Params> params( - easy_unlock_private::SetRemoteDevices::Params::Create(*args_)); - EXTENSION_FUNCTION_VALIDATE(params.get()); - - Profile* profile = Profile::FromBrowserContext(browser_context()); - base::ListValue devices; - for (const easy_unlock_private::Device& device : params->devices) - devices.Append(device.ToValue()); - - chromeos::EasyUnlockService::Get(profile)->SetRemoteBleDevices(devices); - - return RespondNow(NoArguments()); -} - -EasyUnlockPrivateGetRemoteDevicesFunction:: - EasyUnlockPrivateGetRemoteDevicesFunction() { -} - -EasyUnlockPrivateGetRemoteDevicesFunction:: - ~EasyUnlockPrivateGetRemoteDevicesFunction() { -} - -ExtensionFunction::ResponseAction -EasyUnlockPrivateGetRemoteDevicesFunction::Run() { - // Check that we are inside a user profile. - Profile* profile = Profile::FromBrowserContext(browser_context()); - chromeos::EasyUnlockService* easy_unlock_service = - chromeos::EasyUnlockService::Get(profile); - if (easy_unlock_service->GetType() != - chromeos::EasyUnlockService::TYPE_REGULAR) { - return RespondNow( - Error("This function must be called inside a user session.")); - } - - // Get the synced unlock key data. - proximity_auth::ProximityAuthClient* client = - easy_unlock_service->proximity_auth_client(); - - permit_id_ = "permit://google.com/easyunlock/v1/" + client->GetAccountId(); - secure_message_delegate_ = - cryptauth::SecureMessageDelegateImpl::Factory::NewInstance(); - std::vector<cryptauth::ExternalDeviceInfo> unlock_keys = GetUnlockKeys(); - expected_devices_count_ = unlock_keys.size(); - - remote_devices_.reset(new base::ListValue()); - if (expected_devices_count_ == 0) - return RespondNow(OneArgument(std::move(remote_devices_))); - - // If there is a BLE unlock key, then don't return anything, so the app does - // not try the classic Bluetooth protocol. - for (const auto& unlock_key : unlock_keys) { - if (unlock_key.bluetooth_address().empty()) - return RespondNow(OneArgument(std::move(remote_devices_))); - } - - // Derive the PSKs for the user's unlock keys. - PA_LOG(INFO) << "Deriving PSKs for " - << "chrome.easyUnlockPrivate.getRemoteDevices.\n" - << "Expecting " << expected_devices_count_ << " devices."; - for (const auto& unlock_key : unlock_keys) { - secure_message_delegate_->DeriveKey( - GetUserPrivateKey(), unlock_key.public_key(), - base::Bind( - &EasyUnlockPrivateGetRemoteDevicesFunction::OnPSKDerivedForDevice, - this, unlock_key)); - } - return did_respond() ? AlreadyResponded() : RespondLater(); -} - -std::string EasyUnlockPrivateGetRemoteDevicesFunction::GetUserPrivateKey() { - Profile* profile = Profile::FromBrowserContext(browser_context()); - proximity_auth::ProximityAuthClient* client = - chromeos::EasyUnlockService::Get(profile)->proximity_auth_client(); - cryptauth::CryptAuthEnrollmentManager* enrollment_manager = - client->GetCryptAuthEnrollmentManager(); - return enrollment_manager->GetUserPrivateKey(); -} - -std::vector<cryptauth::ExternalDeviceInfo> -EasyUnlockPrivateGetRemoteDevicesFunction::GetUnlockKeys() { - Profile* profile = Profile::FromBrowserContext(browser_context()); - proximity_auth::ProximityAuthClient* client = - chromeos::EasyUnlockService::Get(profile)->proximity_auth_client(); - cryptauth::CryptAuthDeviceManager* device_manager = - client->GetCryptAuthDeviceManager(); - return device_manager->GetUnlockKeys(); -} - -void EasyUnlockPrivateGetRemoteDevicesFunction::OnPSKDerivedForDevice( - const cryptauth::ExternalDeviceInfo& device, - const std::string& persistent_symmetric_key) { - std::string b64_public_key, b64_psk; - base::Base64UrlEncode(device.public_key(), - base::Base64UrlEncodePolicy::INCLUDE_PADDING, - &b64_public_key); - base::Base64UrlEncode(persistent_symmetric_key, - base::Base64UrlEncodePolicy::INCLUDE_PADDING, - &b64_psk); - - // Fill in the JSON dictionary containing a single unlock key's data. - std::unique_ptr<base::DictionaryValue> device_dictionary( - new base::DictionaryValue()); - device_dictionary->SetString("name", device.friendly_device_name()); - device_dictionary->SetString("bluetoothAddress", device.bluetooth_address()); - device_dictionary->SetString("psk", b64_psk); - - // Fill in the permit license for the unlock key. - std::unique_ptr<base::DictionaryValue> permit_license( - new base::DictionaryValue()); - permit_license->SetString("permitId", permit_id_); - permit_license->SetString("id", b64_public_key); - permit_license->SetString("type", "license"); - permit_license->SetString("data", b64_public_key); - device_dictionary->Set("permitRecord", std::move(permit_license)); - - remote_devices_->Append(std::move(device_dictionary)); - - // If all PSKs are derived, then return from the API call. - PA_LOG(INFO) << "Derived PSK for " << b64_public_key << ": " - << remote_devices_->GetSize() << "/" << expected_devices_count_; - if (remote_devices_->GetSize() == expected_devices_count_) - Respond(OneArgument(std::move(remote_devices_))); -} - -EasyUnlockPrivateGetUserInfoFunction::EasyUnlockPrivateGetUserInfoFunction() { -} - -EasyUnlockPrivateGetUserInfoFunction::~EasyUnlockPrivateGetUserInfoFunction() { -} - -ExtensionFunction::ResponseAction EasyUnlockPrivateGetUserInfoFunction::Run() { - chromeos::EasyUnlockService* service = chromeos::EasyUnlockService::Get( - Profile::FromBrowserContext(browser_context())); - std::vector<easy_unlock_private::UserInfo> users; - const AccountId& account_id = service->GetAccountId(); - if (account_id.is_valid()) { - easy_unlock_private::UserInfo user; - user.user_id = account_id.GetUserEmail(); - user.logged_in = - service->GetType() == chromeos::EasyUnlockService::TYPE_REGULAR; - user.data_ready = user.logged_in || service->GetRemoteDevices() != NULL; - - user.device_user_id = cryptauth::CalculateDeviceUserId( - cryptauth::CryptAuthDeviceIdProviderImpl::GetInstance()->GetDeviceId(), - account_id.GetUserEmail()); - - users.push_back(std::move(user)); - } - return RespondNow( - ArgumentList(easy_unlock_private::GetUserInfo::Results::Create(users))); -} - EasyUnlockPrivateShowErrorBubbleFunction:: EasyUnlockPrivateShowErrorBubbleFunction() { } @@ -691,9 +314,10 @@ EasyUnlockPrivateShowErrorBubbleFunction:: ExtensionFunction::ResponseAction EasyUnlockPrivateShowErrorBubbleFunction::Run() { - content::WebContents* web_contents = GetAssociatedWebContents(); - if (!web_contents) + content::WebContents* web_contents = GetSenderWebContents(); + if (!web_contents || GetViewType(web_contents) != VIEW_TYPE_APP_WINDOW) { return RespondNow(Error("A foreground app window is required.")); + } std::unique_ptr<easy_unlock_private::ShowErrorBubble::Params> params( easy_unlock_private::ShowErrorBubble::Params::Create(*args_)); @@ -757,14 +381,13 @@ void EasyUnlockPrivateFindSetupConnectionFunction:: void EasyUnlockPrivateFindSetupConnectionFunction::OnConnectionFound( std::unique_ptr<cryptauth::Connection> connection) { // Connection are not persistent by default. - std::string device_address = connection->remote_device().bluetooth_address; bool persistent = false; int connection_id = GetConnectionManager(browser_context()) ->AddConnection(extension(), std::move(connection), persistent); Respond( ArgumentList(easy_unlock_private::FindSetupConnection::Results::Create( - connection_id, device_address))); + connection_id))); } ExtensionFunction::ResponseAction @@ -775,21 +398,20 @@ EasyUnlockPrivateFindSetupConnectionFunction::Run() { // Creates a BLE connection finder to look for any device advertising // |params->setup_service_uuid|. - connection_finder_.reset( - new proximity_auth::BluetoothLowEnergySetupConnectionFinder( - params->setup_service_uuid)); + connection_finder_ = + std::make_unique<proximity_auth::BluetoothLowEnergySetupConnectionFinder>( + params->setup_service_uuid); connection_finder_->Find(base::Bind( &EasyUnlockPrivateFindSetupConnectionFunction::OnConnectionFound, this)); - timer_.reset(new base::OneShotTimer()); + timer_ = std::make_unique<base::OneShotTimer>(); timer_->Start(FROM_HERE, base::TimeDelta::FromSeconds(params->time_out), base::Bind(&EasyUnlockPrivateFindSetupConnectionFunction:: OnConnectionFinderTimedOut, this)); - // TODO(https://crbug.com/829182): Resolve this. - return did_respond() ? AlreadyResponded() : RespondLater(); + return RespondLater(); } EasyUnlockPrivateSetupConnectionDisconnectFunction:: diff --git a/chromium/chrome/browser/extensions/api/easy_unlock_private/easy_unlock_private_api.h b/chromium/chrome/browser/extensions/api/easy_unlock_private/easy_unlock_private_api.h index f0f04d2d74f..78046e5347e 100644 --- a/chromium/chrome/browser/extensions/api/easy_unlock_private/easy_unlock_private_api.h +++ b/chromium/chrome/browser/extensions/api/easy_unlock_private/easy_unlock_private_api.h @@ -27,8 +27,6 @@ class BrowserContext; namespace cryptauth { class Connection; -class ExternalDeviceInfo; -class SecureMessageDelegate; } namespace proximity_auth { @@ -38,7 +36,6 @@ class BluetoothLowEnergyConnectionFinder; namespace extensions { class EasyUnlockPrivateConnectionManager; -class EasyUnlockPrivateCryptoDelegate; class EasyUnlockPrivateAPI : public BrowserContextKeyedAPI { public: @@ -50,8 +47,6 @@ class EasyUnlockPrivateAPI : public BrowserContextKeyedAPI { explicit EasyUnlockPrivateAPI(content::BrowserContext* context); ~EasyUnlockPrivateAPI() override; - EasyUnlockPrivateCryptoDelegate* GetCryptoDelegate(); - EasyUnlockPrivateConnectionManager* get_connection_manager() { return connection_manager_.get(); } @@ -65,8 +60,6 @@ class EasyUnlockPrivateAPI : public BrowserContextKeyedAPI { // KeyedService implementation. void Shutdown() override; - std::unique_ptr<EasyUnlockPrivateCryptoDelegate> crypto_delegate_; - std::unique_ptr<EasyUnlockPrivateConnectionManager> connection_manager_; DISALLOW_COPY_AND_ASSIGN(EasyUnlockPrivateAPI); @@ -89,198 +82,6 @@ class EasyUnlockPrivateGetStringsFunction : public UIThreadExtensionFunction { DISALLOW_COPY_AND_ASSIGN(EasyUnlockPrivateGetStringsFunction); }; -class EasyUnlockPrivatePerformECDHKeyAgreementFunction - : public UIThreadExtensionFunction { - public: - EasyUnlockPrivatePerformECDHKeyAgreementFunction(); - - protected: - ~EasyUnlockPrivatePerformECDHKeyAgreementFunction() override; - - // ExtensionFunction: - ResponseAction Run() override; - - private: - void OnData(const std::string& secret_key); - - DECLARE_EXTENSION_FUNCTION("easyUnlockPrivate.performECDHKeyAgreement", - EASYUNLOCKPRIVATE_PERFORMECDHKEYAGREEMENT) - - DISALLOW_COPY_AND_ASSIGN(EasyUnlockPrivatePerformECDHKeyAgreementFunction); -}; - -class EasyUnlockPrivateGenerateEcP256KeyPairFunction - : public UIThreadExtensionFunction { - public: - EasyUnlockPrivateGenerateEcP256KeyPairFunction(); - - protected: - ~EasyUnlockPrivateGenerateEcP256KeyPairFunction() override; - - // ExtensionFunction: - ResponseAction Run() override; - - private: - void OnData(const std::string& public_key, - const std::string& private_key); - - DECLARE_EXTENSION_FUNCTION("easyUnlockPrivate.generateEcP256KeyPair", - EASYUNLOCKPRIVATE_GENERATEECP256KEYPAIR) - - DISALLOW_COPY_AND_ASSIGN(EasyUnlockPrivateGenerateEcP256KeyPairFunction); -}; - -class EasyUnlockPrivateCreateSecureMessageFunction - : public UIThreadExtensionFunction { - public: - EasyUnlockPrivateCreateSecureMessageFunction(); - - protected: - ~EasyUnlockPrivateCreateSecureMessageFunction() override; - - // ExtensionFunction: - ResponseAction Run() override; - - private: - void OnData(const std::string& message); - - DECLARE_EXTENSION_FUNCTION("easyUnlockPrivate.createSecureMessage", - EASYUNLOCKPRIVATE_CREATESECUREMESSAGE) - - DISALLOW_COPY_AND_ASSIGN(EasyUnlockPrivateCreateSecureMessageFunction); -}; - -class EasyUnlockPrivateUnwrapSecureMessageFunction - : public UIThreadExtensionFunction { - public: - EasyUnlockPrivateUnwrapSecureMessageFunction(); - - protected: - ~EasyUnlockPrivateUnwrapSecureMessageFunction() override; - - // ExtensionFunction: - ResponseAction Run() override; - - private: - void OnData(const std::string& data); - - DECLARE_EXTENSION_FUNCTION("easyUnlockPrivate.unwrapSecureMessage", - EASYUNLOCKPRIVATE_UNWRAPSECUREMESSAGE) - - DISALLOW_COPY_AND_ASSIGN(EasyUnlockPrivateUnwrapSecureMessageFunction); -}; - -class EasyUnlockPrivateGetPermitAccessFunction - : public UIThreadExtensionFunction { - public: - DECLARE_EXTENSION_FUNCTION("easyUnlockPrivate.getPermitAccess", - EASYUNLOCKPRIVATE_GETPERMITACCESS) - EasyUnlockPrivateGetPermitAccessFunction(); - - protected: - ~EasyUnlockPrivateGetPermitAccessFunction() override; - - // Writes the user's public and private key in base64 form to the - // |user_public_key| and |user_private_key| fields. Exposed for testing. - virtual void GetKeyPairForExperiment(std::string* user_public_key, - std::string* user_private_key); - - private: - // ExtensionFunction: - ResponseAction Run() override; - - DISALLOW_COPY_AND_ASSIGN(EasyUnlockPrivateGetPermitAccessFunction); -}; - -class EasyUnlockPrivateClearPermitAccessFunction - : public UIThreadExtensionFunction { - public: - DECLARE_EXTENSION_FUNCTION("easyUnlockPrivate.clearPermitAccess", - EASYUNLOCKPRIVATE_CLEARPERMITACCESS) - EasyUnlockPrivateClearPermitAccessFunction(); - - private: - ~EasyUnlockPrivateClearPermitAccessFunction() override; - - // ExtensionFunction: - ResponseAction Run() override; - - DISALLOW_COPY_AND_ASSIGN(EasyUnlockPrivateClearPermitAccessFunction); -}; - -class EasyUnlockPrivateSetRemoteDevicesFunction - : public UIThreadExtensionFunction { - public: - DECLARE_EXTENSION_FUNCTION("easyUnlockPrivate.setRemoteDevices", - EASYUNLOCKPRIVATE_SETREMOTEDEVICES) - EasyUnlockPrivateSetRemoteDevicesFunction(); - - private: - ~EasyUnlockPrivateSetRemoteDevicesFunction() override; - - // ExtensionFunction: - ResponseAction Run() override; - - DISALLOW_COPY_AND_ASSIGN(EasyUnlockPrivateSetRemoteDevicesFunction); -}; - -class EasyUnlockPrivateGetRemoteDevicesFunction - : public UIThreadExtensionFunction { - public: - DECLARE_EXTENSION_FUNCTION("easyUnlockPrivate.getRemoteDevices", - EASYUNLOCKPRIVATE_GETREMOTEDEVICES) - EasyUnlockPrivateGetRemoteDevicesFunction(); - - protected: - ~EasyUnlockPrivateGetRemoteDevicesFunction() override; - - // Returns the user's private key used for the native experiment. - // Exposed for testing. - virtual std::string GetUserPrivateKey(); - - // Returns the user's unlock keys used for the native experiment. - // Exposed for testing. - virtual std::vector<cryptauth::ExternalDeviceInfo> GetUnlockKeys(); - - private: - // ExtensionFunction: - ResponseAction Run() override; - - // Callback when the PSK of a device is derived. - void OnPSKDerivedForDevice(const cryptauth::ExternalDeviceInfo& device, - const std::string& persistent_symmetric_key); - - // The permit id of the user. Used for the native experiment. - std::string permit_id_; - - // The expected number of devices to return. Used for the native experiment. - size_t expected_devices_count_; - - // Working list of the devices to return. Used for the native experiment. - std::unique_ptr<base::ListValue> remote_devices_; - - // Used to derive devices' PSK. Used for the native experiment. - std::unique_ptr<cryptauth::SecureMessageDelegate> - secure_message_delegate_; - - DISALLOW_COPY_AND_ASSIGN(EasyUnlockPrivateGetRemoteDevicesFunction); -}; - -class EasyUnlockPrivateGetUserInfoFunction : public UIThreadExtensionFunction { - public: - DECLARE_EXTENSION_FUNCTION("easyUnlockPrivate.getUserInfo", - EASYUNLOCKPRIVATE_GETUSERINFO) - EasyUnlockPrivateGetUserInfoFunction(); - - private: - ~EasyUnlockPrivateGetUserInfoFunction() override; - - // ExtensionFunction: - ResponseAction Run() override; - - DISALLOW_COPY_AND_ASSIGN(EasyUnlockPrivateGetUserInfoFunction); -}; - class EasyUnlockPrivateShowErrorBubbleFunction : public UIThreadExtensionFunction { public: diff --git a/chromium/chrome/browser/extensions/api/easy_unlock_private/easy_unlock_private_api_chromeos_unittest.cc b/chromium/chrome/browser/extensions/api/easy_unlock_private/easy_unlock_private_api_chromeos_unittest.cc index 009de5e36fd..e23780b47e8 100644 --- a/chromium/chrome/browser/extensions/api/easy_unlock_private/easy_unlock_private_api_chromeos_unittest.cc +++ b/chromium/chrome/browser/extensions/api/easy_unlock_private/easy_unlock_private_api_chromeos_unittest.cc @@ -5,142 +5,30 @@ #include "chrome/browser/extensions/api/easy_unlock_private/easy_unlock_private_api.h" #include <memory> -#include <string> #include <utility> -#include "base/bind.h" -#include "base/command_line.h" -#include "base/files/file_path.h" -#include "base/files/scoped_temp_dir.h" -#include "base/macros.h" -#include "base/memory/scoped_refptr.h" -#include "base/threading/thread_task_runner_handle.h" -#include "base/values.h" -#include "chrome/browser/chromeos/login/easy_unlock/easy_unlock_app_manager.h" -#include "chrome/browser/chromeos/login/easy_unlock/easy_unlock_service_factory.h" -#include "chrome/browser/chromeos/login/easy_unlock/easy_unlock_service_regular.h" #include "chrome/browser/extensions/api/easy_unlock_private/easy_unlock_private_connection_manager.h" #include "chrome/browser/extensions/extension_api_unittest.h" -#include "chrome/browser/extensions/extension_function_test_utils.h" -#include "chrome/browser/extensions/extension_system_factory.h" -#include "chrome/browser/extensions/test_extension_system.h" -#include "chrome/browser/profiles/profile.h" -#include "chrome/common/extensions/api/easy_unlock_private.h" -#include "chrome/common/extensions/extension_constants.h" -#include "chrome/test/base/testing_profile.h" -#include "chromeos/components/proximity_auth/switches.h" -#include "chromeos/dbus/dbus_thread_manager.h" -#include "chromeos/dbus/fake_easy_unlock_client.h" -#include "components/cryptauth/cryptauth_test_util.h" #include "components/cryptauth/fake_connection.h" -#include "components/cryptauth/proto/cryptauth_api.pb.h" -#include "device/bluetooth/dbus/bluez_dbus_manager.h" -#include "extensions/browser/api_test_utils.h" +#include "components/cryptauth/remote_device_test_util.h" +#include "content/public/browser/browser_context.h" #include "extensions/browser/browser_context_keyed_api_factory.h" -#include "extensions/browser/test_event_router.h" #include "extensions/common/extension.h" #include "extensions/common/extension_builder.h" #include "extensions/common/value_builder.h" -#include "testing/gmock/include/gmock/gmock.h" -#include "testing/gtest/include/gtest/gtest.h" -#include "third_party/cros_system_api/dbus/service_constants.h" -#include "ui/aura/env.h" -// TODO(jhawkins): Wrap in extensions namespace. +namespace extensions { namespace { -namespace api = extensions::api::easy_unlock_private; - using cryptauth::FakeConnection; -using cryptauth::CreateLERemoteDeviceForTest; +using cryptauth::CreateRemoteDeviceForTest; using extensions::BrowserContextKeyedAPIFactory; using extensions::DictionaryBuilder; -using extensions::EasyUnlockPrivateAPI; -using extensions::EasyUnlockPrivateCreateSecureMessageFunction; -using extensions::EasyUnlockPrivateConnectionManager; -using extensions::EasyUnlockPrivateGenerateEcP256KeyPairFunction; -using extensions::EasyUnlockPrivatePerformECDHKeyAgreementFunction; -using extensions::EasyUnlockPrivateUnwrapSecureMessageFunction; using extensions::Extension; using extensions::ExtensionBuilder; using extensions::ListBuilder; -class TestableGetRemoteDevicesFunction - : public extensions::EasyUnlockPrivateGetRemoteDevicesFunction { - public: - TestableGetRemoteDevicesFunction() {} - - // EasyUnlockPrivateGetRemoteDevicesFunction: - std::string GetUserPrivateKey() override { return "user private key"; } - - std::vector<cryptauth::ExternalDeviceInfo> GetUnlockKeys() override { - cryptauth::ExternalDeviceInfo unlock_key1; - unlock_key1.set_friendly_device_name("test phone 1"); - unlock_key1.set_public_key("public key 1"); - unlock_key1.set_bluetooth_address("AA:BB:CC:DD:EE:FF"); - unlock_key1.set_unlock_key(true); - - cryptauth::ExternalDeviceInfo unlock_key2; - unlock_key2.set_friendly_device_name("test phone 2"); - unlock_key2.set_public_key("public key 2"); - unlock_key2.set_bluetooth_address("FF:EE:DD:CC:BB:AA"); - unlock_key2.set_unlock_key(true); - - std::vector<cryptauth::ExternalDeviceInfo> unlock_keys; - unlock_keys.push_back(unlock_key1); - unlock_keys.push_back(unlock_key2); - return unlock_keys; - } - - private: - ~TestableGetRemoteDevicesFunction() override {} - - DISALLOW_COPY_AND_ASSIGN(TestableGetRemoteDevicesFunction); -}; - -class TestableGetPermitAccessFunction - : public extensions::EasyUnlockPrivateGetPermitAccessFunction { - public: - TestableGetPermitAccessFunction() {} - - // EasyUnlockPrivateGetPermitAccessFunction: - void GetKeyPairForExperiment(std::string* user_public_key, - std::string* user_private_key) override { - *user_public_key = "user public key"; - *user_private_key = "user private key"; - } - - private: - ~TestableGetPermitAccessFunction() override {} - - DISALLOW_COPY_AND_ASSIGN(TestableGetPermitAccessFunction); -}; - -// Converts a string to a base::Value value whose buffer contains the -// string data without the trailing '\0'. -std::unique_ptr<base::Value> StringToBinaryValue(const std::string& value) { - return base::Value::CreateWithCopiedBuffer(value.data(), value.length()); -} - -// Copies |private_key_source| and |public_key_source| to |private_key_target| -// and |public_key_target|. It is used as a callback for -// |EasyUnlockClient::GenerateEcP256KeyPair| to save the values returned by the -// method. -void CopyKeyPair(std::string* private_key_target, - std::string* public_key_target, - const std::string& private_key_source, - const std::string& public_key_source) { - *private_key_target = private_key_source; - *public_key_target = public_key_source; -} - -// Copies |data_source| to |data_target|. Used as a callback to EasyUnlockClient -// methods to save the data returned by the method. -void CopyData(std::string* data_target, const std::string& data_source) { - *data_target = data_source; -} - EasyUnlockPrivateConnectionManager* GetConnectionManager( content::BrowserContext* context) { return BrowserContextKeyedAPIFactory<EasyUnlockPrivateAPI>::Get(context) @@ -164,357 +52,21 @@ class EasyUnlockPrivateApiTest : public extensions::ExtensionApiUnittest { public: EasyUnlockPrivateApiTest() {} ~EasyUnlockPrivateApiTest() override {} - - protected: - void SetUp() override { - chromeos::DBusThreadManager::Initialize(); - if (aura::Env::GetInstance()->mode() == aura::Env::Mode::LOCAL) { - bluez::BluezDBusManager::Initialize( - chromeos::DBusThreadManager::Get()->GetSystemBus(), - chromeos::DBusThreadManager::Get()->IsUsingFakes()); - } - client_ = chromeos::DBusThreadManager::Get()->GetEasyUnlockClient(); - - extensions::ExtensionApiUnittest::SetUp(); - } - - void TearDown() override { - extensions::ExtensionApiUnittest::TearDown(); - - if (aura::Env::GetInstance()->mode() == aura::Env::Mode::LOCAL) - bluez::BluezDBusManager::Shutdown(); - chromeos::DBusThreadManager::Shutdown(); - } - - // Extracts a single binary value result from a run extension function - // |function| and converts it to string. - // It will fail if the extension doesn't have exactly one binary value result. - // On failure, an empty string is returned. - std::string GetSingleBinaryResultAsString( - UIThreadExtensionFunction* function) { - const base::ListValue* result_list = function->GetResultList(); - if (!result_list) { - LOG(ERROR) << "Function has no result list."; - return std::string(); - } - - if (result_list->GetSize() != 1u) { - LOG(ERROR) << "Invalid number of results."; - return std::string(); - } - - const auto& result_binary_value = result_list->GetList()[0]; - if (!result_binary_value.is_blob()) { - LOG(ERROR) << "Result not a binary value."; - return std::string(); - } - - return std::string(result_binary_value.GetBlob().data(), - result_binary_value.GetBlob().size()); - } - - chromeos::EasyUnlockClient* client_; -}; - -TEST_F(EasyUnlockPrivateApiTest, GenerateEcP256KeyPair) { - scoped_refptr<EasyUnlockPrivateGenerateEcP256KeyPairFunction> function( - new EasyUnlockPrivateGenerateEcP256KeyPairFunction()); - function->set_has_callback(true); - - ASSERT_TRUE(extension_function_test_utils::RunFunction( - function.get(), "[]", browser(), extensions::api_test_utils::NONE)); - - const base::ListValue* result_list = function->GetResultList(); - ASSERT_TRUE(result_list); - ASSERT_EQ(2u, result_list->GetSize()); - - const base::Value& public_key = result_list->GetList()[0]; - const base::Value& private_key = result_list->GetList()[1]; - ASSERT_TRUE(public_key.is_blob()); - ASSERT_TRUE(private_key.is_blob()); - - EXPECT_TRUE(chromeos::FakeEasyUnlockClient::IsEcP256KeyPair( - std::string(private_key.GetBlob().data(), private_key.GetBlob().size()), - std::string(public_key.GetBlob().data(), public_key.GetBlob().size()))); -} - -TEST_F(EasyUnlockPrivateApiTest, PerformECDHKeyAgreement) { - scoped_refptr<EasyUnlockPrivatePerformECDHKeyAgreementFunction> function( - new EasyUnlockPrivatePerformECDHKeyAgreementFunction()); - function->set_has_callback(true); - - std::string private_key_1; - std::string public_key_1_unused; - client_->GenerateEcP256KeyPair( - base::Bind(&CopyKeyPair, &private_key_1, &public_key_1_unused)); - - std::string private_key_2_unused; - std::string public_key_2; - client_->GenerateEcP256KeyPair( - base::Bind(&CopyKeyPair, &private_key_2_unused, &public_key_2)); - - std::string expected_result; - client_->PerformECDHKeyAgreement( - private_key_1, - public_key_2, - base::Bind(&CopyData, &expected_result)); - ASSERT_GT(expected_result.length(), 0u); - - std::unique_ptr<base::ListValue> args(new base::ListValue); - args->Append(StringToBinaryValue(private_key_1)); - args->Append(StringToBinaryValue(public_key_2)); - - ASSERT_TRUE(extension_function_test_utils::RunFunction( - function.get(), std::move(args), browser(), - extensions::api_test_utils::NONE)); - - EXPECT_EQ(expected_result, GetSingleBinaryResultAsString(function.get())); -} - -TEST_F(EasyUnlockPrivateApiTest, CreateSecureMessage) { - scoped_refptr<EasyUnlockPrivateCreateSecureMessageFunction> function( - new EasyUnlockPrivateCreateSecureMessageFunction()); - function->set_has_callback(true); - - chromeos::EasyUnlockClient::CreateSecureMessageOptions create_options; - create_options.key = "KEY"; - create_options.associated_data = "ASSOCIATED_DATA"; - create_options.public_metadata = "PUBLIC_METADATA"; - create_options.verification_key_id = "VERIFICATION_KEY_ID"; - create_options.decryption_key_id = "DECRYPTION_KEY_ID"; - create_options.encryption_type = easy_unlock::kEncryptionTypeAES256CBC; - create_options.signature_type = easy_unlock::kSignatureTypeHMACSHA256; - - std::string expected_result; - client_->CreateSecureMessage( - "PAYLOAD", - create_options, - base::Bind(&CopyData, &expected_result)); - ASSERT_GT(expected_result.length(), 0u); - - std::unique_ptr<base::ListValue> args(new base::ListValue); - args->Append(StringToBinaryValue("PAYLOAD")); - args->Append(StringToBinaryValue("KEY")); - auto options = std::make_unique<base::DictionaryValue>(); - options->Set("associatedData", StringToBinaryValue("ASSOCIATED_DATA")); - options->Set("publicMetadata", StringToBinaryValue("PUBLIC_METADATA")); - options->Set("verificationKeyId", - StringToBinaryValue("VERIFICATION_KEY_ID")); - options->Set("decryptionKeyId", - StringToBinaryValue("DECRYPTION_KEY_ID")); - options->SetString( - "encryptType", - api::ToString(api::ENCRYPTION_TYPE_AES_256_CBC)); - options->SetString( - "signType", - api::ToString(api::SIGNATURE_TYPE_HMAC_SHA256)); - args->Append(std::move(options)); - - ASSERT_TRUE(extension_function_test_utils::RunFunction( - function.get(), std::move(args), browser(), - extensions::api_test_utils::NONE)); - - EXPECT_EQ(expected_result, GetSingleBinaryResultAsString(function.get())); -} - -TEST_F(EasyUnlockPrivateApiTest, CreateSecureMessage_EmptyOptions) { - scoped_refptr<EasyUnlockPrivateCreateSecureMessageFunction> function( - new EasyUnlockPrivateCreateSecureMessageFunction()); - function->set_has_callback(true); - - chromeos::EasyUnlockClient::CreateSecureMessageOptions create_options; - create_options.key = "KEY"; - create_options.encryption_type = easy_unlock::kEncryptionTypeNone; - create_options.signature_type = easy_unlock::kSignatureTypeHMACSHA256; - - std::string expected_result; - client_->CreateSecureMessage( - "PAYLOAD", - create_options, - base::Bind(&CopyData, &expected_result)); - ASSERT_GT(expected_result.length(), 0u); - - std::unique_ptr<base::ListValue> args(new base::ListValue); - args->Append(StringToBinaryValue("PAYLOAD")); - args->Append(StringToBinaryValue("KEY")); - auto options = std::make_unique<base::DictionaryValue>(); - args->Append(std::move(options)); - - ASSERT_TRUE(extension_function_test_utils::RunFunction( - function.get(), std::move(args), browser(), - extensions::api_test_utils::NONE)); - - EXPECT_EQ(expected_result, GetSingleBinaryResultAsString(function.get())); -} - -TEST_F(EasyUnlockPrivateApiTest, CreateSecureMessage_AsymmetricSign) { - scoped_refptr<EasyUnlockPrivateCreateSecureMessageFunction> function( - new EasyUnlockPrivateCreateSecureMessageFunction()); - function->set_has_callback(true); - - chromeos::EasyUnlockClient::CreateSecureMessageOptions create_options; - create_options.key = "KEY"; - create_options.associated_data = "ASSOCIATED_DATA"; - create_options.verification_key_id = "VERIFICATION_KEY_ID"; - create_options.encryption_type = easy_unlock::kEncryptionTypeNone; - create_options.signature_type = easy_unlock::kSignatureTypeECDSAP256SHA256; - - std::string expected_result; - client_->CreateSecureMessage( - "PAYLOAD", - create_options, - base::Bind(&CopyData, &expected_result)); - ASSERT_GT(expected_result.length(), 0u); - - std::unique_ptr<base::ListValue> args(new base::ListValue); - args->Append(StringToBinaryValue("PAYLOAD")); - args->Append(StringToBinaryValue("KEY")); - auto options = std::make_unique<base::DictionaryValue>(); - options->Set("associatedData", - StringToBinaryValue("ASSOCIATED_DATA")); - options->Set("verificationKeyId", - StringToBinaryValue("VERIFICATION_KEY_ID")); - options->SetString( - "signType", - api::ToString(api::SIGNATURE_TYPE_ECDSA_P256_SHA256)); - args->Append(std::move(options)); - - ASSERT_TRUE(extension_function_test_utils::RunFunction( - function.get(), std::move(args), browser(), - extensions::api_test_utils::NONE)); - - EXPECT_EQ(expected_result, GetSingleBinaryResultAsString(function.get())); -} - -TEST_F(EasyUnlockPrivateApiTest, UnwrapSecureMessage) { - scoped_refptr<EasyUnlockPrivateUnwrapSecureMessageFunction> function( - new EasyUnlockPrivateUnwrapSecureMessageFunction()); - function->set_has_callback(true); - - chromeos::EasyUnlockClient::UnwrapSecureMessageOptions unwrap_options; - unwrap_options.key = "KEY"; - unwrap_options.associated_data = "ASSOCIATED_DATA"; - unwrap_options.encryption_type = easy_unlock::kEncryptionTypeAES256CBC; - unwrap_options.signature_type = easy_unlock::kSignatureTypeHMACSHA256; - - std::string expected_result; - client_->UnwrapSecureMessage( - "MESSAGE", - unwrap_options, - base::Bind(&CopyData, &expected_result)); - ASSERT_GT(expected_result.length(), 0u); - - std::unique_ptr<base::ListValue> args(new base::ListValue); - args->Append(StringToBinaryValue("MESSAGE")); - args->Append(StringToBinaryValue("KEY")); - auto options = std::make_unique<base::DictionaryValue>(); - options->Set("associatedData", StringToBinaryValue("ASSOCIATED_DATA")); - options->SetString( - "encryptType", - api::ToString(api::ENCRYPTION_TYPE_AES_256_CBC)); - options->SetString( - "signType", - api::ToString(api::SIGNATURE_TYPE_HMAC_SHA256)); - args->Append(std::move(options)); - - ASSERT_TRUE(extension_function_test_utils::RunFunction( - function.get(), std::move(args), browser(), - extensions::api_test_utils::NONE)); - - EXPECT_EQ(expected_result, GetSingleBinaryResultAsString(function.get())); -} - -TEST_F(EasyUnlockPrivateApiTest, UnwrapSecureMessage_EmptyOptions) { - scoped_refptr<EasyUnlockPrivateUnwrapSecureMessageFunction> function( - new EasyUnlockPrivateUnwrapSecureMessageFunction()); - function->set_has_callback(true); - - chromeos::EasyUnlockClient::UnwrapSecureMessageOptions unwrap_options; - unwrap_options.key = "KEY"; - unwrap_options.encryption_type = easy_unlock::kEncryptionTypeNone; - unwrap_options.signature_type = easy_unlock::kSignatureTypeHMACSHA256; - - std::string expected_result; - client_->UnwrapSecureMessage( - "MESSAGE", - unwrap_options, - base::Bind(&CopyData, &expected_result)); - ASSERT_GT(expected_result.length(), 0u); - - std::unique_ptr<base::ListValue> args(new base::ListValue); - args->Append(StringToBinaryValue("MESSAGE")); - args->Append(StringToBinaryValue("KEY")); - auto options = std::make_unique<base::DictionaryValue>(); - args->Append(std::move(options)); - - ASSERT_TRUE(extension_function_test_utils::RunFunction( - function.get(), std::move(args), browser(), - extensions::api_test_utils::NONE)); - - EXPECT_EQ(expected_result, GetSingleBinaryResultAsString(function.get())); -} - -TEST_F(EasyUnlockPrivateApiTest, UnwrapSecureMessage_AsymmetricSign) { - scoped_refptr<EasyUnlockPrivateUnwrapSecureMessageFunction> function( - new EasyUnlockPrivateUnwrapSecureMessageFunction()); - function->set_has_callback(true); - - chromeos::EasyUnlockClient::UnwrapSecureMessageOptions unwrap_options; - unwrap_options.key = "KEY"; - unwrap_options.associated_data = "ASSOCIATED_DATA"; - unwrap_options.encryption_type = easy_unlock::kEncryptionTypeNone; - unwrap_options.signature_type = easy_unlock::kSignatureTypeECDSAP256SHA256; - - std::string expected_result; - client_->UnwrapSecureMessage( - "MESSAGE", - unwrap_options, - base::Bind(&CopyData, &expected_result)); - ASSERT_GT(expected_result.length(), 0u); - - std::unique_ptr<base::ListValue> args(new base::ListValue); - args->Append(StringToBinaryValue("MESSAGE")); - args->Append(StringToBinaryValue("KEY")); - auto options = std::make_unique<base::DictionaryValue>(); - options->Set("associatedData", - StringToBinaryValue("ASSOCIATED_DATA")); - options->SetString( - "signType", - api::ToString(api::SIGNATURE_TYPE_ECDSA_P256_SHA256)); - args->Append(std::move(options)); - - ASSERT_TRUE(extension_function_test_utils::RunFunction( - function.get(), std::move(args), browser(), - extensions::api_test_utils::NONE)); - - EXPECT_EQ(expected_result, GetSingleBinaryResultAsString(function.get())); -} - -struct AutoPairingResult { - AutoPairingResult() : success(false) {} - - void SetResult(bool success, const std::string& error) { - this->success = success; - this->error = error; - } - - bool success; - std::string error; }; // Tests that no BrowserContext dependencies of EasyUnlockPrivateApi (and its // dependencies) are referenced after the BrowserContext is torn down. The test // fails with a crash if such a condition exists. TEST_F(EasyUnlockPrivateApiTest, BrowserContextTearDown) { - EasyUnlockPrivateConnectionManager* manager = GetConnectionManager(profile()); + auto* manager = GetConnectionManager(profile()); ASSERT_TRUE(!!manager); // Add a Connection. The shutdown path for EasyUnlockPrivateConnectionManager, // a dependency of EasyUnlockPrivateApi, only references BrowserContext // dependencies if it has a Connection to shutdown. auto extension = CreateTestExtension(); - auto connection = - std::make_unique<FakeConnection>(CreateLERemoteDeviceForTest()); + auto connection = std::make_unique<FakeConnection>( + cryptauth::CreateRemoteDeviceRefForTest()); manager->AddConnection(extension.get(), std::move(connection), true); // The Profile is cleaned up at the end of this scope, and BrowserContext @@ -522,3 +74,4 @@ TEST_F(EasyUnlockPrivateApiTest, BrowserContextTearDown) { } } // namespace +} // namespace extensions diff --git a/chromium/chrome/browser/extensions/api/easy_unlock_private/easy_unlock_private_connection_manager.cc b/chromium/chrome/browser/extensions/api/easy_unlock_private/easy_unlock_private_connection_manager.cc index 0ca60a93f09..646cadc7576 100644 --- a/chromium/chrome/browser/extensions/api/easy_unlock_private/easy_unlock_private_connection_manager.cc +++ b/chromium/chrome/browser/extensions/api/easy_unlock_private/easy_unlock_private_connection_manager.cc @@ -24,11 +24,11 @@ const char kEasyUnlockFeatureName[] = "easy_unlock"; api::easy_unlock_private::ConnectionStatus ToApiConnectionStatus( Connection::Status status) { switch (status) { - case Connection::DISCONNECTED: + case Connection::Status::DISCONNECTED: return api::easy_unlock_private::CONNECTION_STATUS_DISCONNECTED; - case Connection::IN_PROGRESS: + case Connection::Status::IN_PROGRESS: return api::easy_unlock_private::CONNECTION_STATUS_IN_PROGRESS; - case Connection::CONNECTED: + case Connection::Status::CONNECTED: return api::easy_unlock_private::CONNECTION_STATUS_CONNECTED; } return api::easy_unlock_private::CONNECTION_STATUS_NONE; diff --git a/chromium/chrome/browser/extensions/api/easy_unlock_private/easy_unlock_private_crypto_delegate.h b/chromium/chrome/browser/extensions/api/easy_unlock_private/easy_unlock_private_crypto_delegate.h deleted file mode 100644 index f03f47041d9..00000000000 --- a/chromium/chrome/browser/extensions/api/easy_unlock_private/easy_unlock_private_crypto_delegate.h +++ /dev/null @@ -1,48 +0,0 @@ -// Copyright 2014 The Chromium Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -#ifndef CHROME_BROWSER_EXTENSIONS_API_EASY_UNLOCK_PRIVATE_EASY_UNLOCK_PRIVATE_CRYPTO_DELEGATE_H_ -#define CHROME_BROWSER_EXTENSIONS_API_EASY_UNLOCK_PRIVATE_EASY_UNLOCK_PRIVATE_CRYPTO_DELEGATE_H_ - -#include <memory> -#include <string> - -#include "base/callback.h" -#include "chrome/common/extensions/api/easy_unlock_private.h" - -namespace extensions { - -// Wrapper around EasyUnlock dbus client on Chrome OS. The methods read -// extension function pearameters and invoke the associated EasyUnlock dbus -// client methods. On non-Chrome OS platforms, the methods are stubbed out. -class EasyUnlockPrivateCryptoDelegate { - public: - typedef base::Callback<void(const std::string& data)> DataCallback; - - typedef base::Callback<void(const std::string& public_key, - const std::string& private_key)> - KeyPairCallback; - - virtual ~EasyUnlockPrivateCryptoDelegate() {} - - // Creates platform specific delegate instance. Non Chrome OS implementations - // currently do nothing but invoke callbacks with empty data. - static std::unique_ptr<EasyUnlockPrivateCryptoDelegate> Create(); - - // See chromeos/dbus/easy_unlock_client.h for info on these methods. - virtual void GenerateEcP256KeyPair(const KeyPairCallback& callback) = 0; - virtual void PerformECDHKeyAgreement( - const api::easy_unlock_private::PerformECDHKeyAgreement::Params& params, - const DataCallback& callback) = 0; - virtual void CreateSecureMessage( - const api::easy_unlock_private::CreateSecureMessage::Params& params, - const DataCallback& callback) = 0; - virtual void UnwrapSecureMessage( - const api::easy_unlock_private::UnwrapSecureMessage::Params& params, - const DataCallback& callback) = 0; -}; - -} // namespace extensions - -#endif // CHROME_BROWSER_EXTENSIONS_API_EASY_UNLOCK_PRIVATE_EASY_UNLOCK_PRIVATE_CRYPTO_DELEGATE_H_ diff --git a/chromium/chrome/browser/extensions/api/easy_unlock_private/easy_unlock_private_crypto_delegate_chromeos.cc b/chromium/chrome/browser/extensions/api/easy_unlock_private/easy_unlock_private_crypto_delegate_chromeos.cc deleted file mode 100644 index 6d2a5b94691..00000000000 --- a/chromium/chrome/browser/extensions/api/easy_unlock_private/easy_unlock_private_crypto_delegate_chromeos.cc +++ /dev/null @@ -1,133 +0,0 @@ -// Copyright 2014 The Chromium Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -#include "chrome/browser/extensions/api/easy_unlock_private/easy_unlock_private_crypto_delegate.h" - -#include "base/macros.h" -#include "chromeos/dbus/dbus_thread_manager.h" -#include "chromeos/dbus/easy_unlock_client.h" -#include "third_party/cros_system_api/dbus/service_constants.h" - -namespace extensions { - -namespace easy_unlock_private = api::easy_unlock_private; - -namespace { - -// Converts encryption type to a string representation used by EasyUnlock dbus -// client. -std::string EncryptionTypeToString(easy_unlock_private::EncryptionType type) { - switch (type) { - case easy_unlock_private::ENCRYPTION_TYPE_AES_256_CBC: - return easy_unlock::kEncryptionTypeAES256CBC; - default: - return easy_unlock::kEncryptionTypeNone; - } -} - -// Converts signature type to a string representation used by EasyUnlock dbus -// client. -std::string SignatureTypeToString(easy_unlock_private::SignatureType type) { - switch (type) { - case easy_unlock_private::SIGNATURE_TYPE_ECDSA_P256_SHA256: - return easy_unlock::kSignatureTypeECDSAP256SHA256; - case easy_unlock_private::SIGNATURE_TYPE_HMAC_SHA256: - // Fall through to default. - default: - return easy_unlock::kSignatureTypeHMACSHA256; - } -} - -// ChromeOS specific EasyUnlockPrivateCryptoDelegate implementation. -class EasyUnlockPrivateCryptoDelegateChromeOS - : public extensions::EasyUnlockPrivateCryptoDelegate { - public: - EasyUnlockPrivateCryptoDelegateChromeOS() - : dbus_client_( - chromeos::DBusThreadManager::Get()->GetEasyUnlockClient()) { - } - - ~EasyUnlockPrivateCryptoDelegateChromeOS() override {} - - void GenerateEcP256KeyPair(const KeyPairCallback& callback) override { - dbus_client_->GenerateEcP256KeyPair(callback); - } - - void PerformECDHKeyAgreement( - const easy_unlock_private::PerformECDHKeyAgreement::Params& params, - const DataCallback& callback) override { - dbus_client_->PerformECDHKeyAgreement( - std::string(params.private_key.begin(), params.private_key.end()), - std::string(params.public_key.begin(), params.public_key.end()), - callback); - } - - void CreateSecureMessage( - const easy_unlock_private::CreateSecureMessage::Params& params, - const DataCallback& callback) override { - chromeos::EasyUnlockClient::CreateSecureMessageOptions options; - options.key.assign(params.key.begin(), params.key.end()); - if (params.options.associated_data) { - options.associated_data.assign(params.options.associated_data->begin(), - params.options.associated_data->end()); - } - if (params.options.public_metadata) { - options.public_metadata.assign(params.options.public_metadata->begin(), - params.options.public_metadata->end()); - } - if (params.options.verification_key_id) { - options.verification_key_id.assign( - params.options.verification_key_id->begin(), - params.options.verification_key_id->end()); - } - if (params.options.decryption_key_id) { - options.decryption_key_id.assign( - params.options.decryption_key_id->begin(), - params.options.decryption_key_id->end()); - } - options.encryption_type = - EncryptionTypeToString(params.options.encrypt_type); - options.signature_type = - SignatureTypeToString(params.options.sign_type); - - dbus_client_->CreateSecureMessage( - std::string(params.payload.begin(), params.payload.end()), options, - callback); - } - - void UnwrapSecureMessage( - const easy_unlock_private::UnwrapSecureMessage::Params& params, - const DataCallback& callback) override { - chromeos::EasyUnlockClient::UnwrapSecureMessageOptions options; - options.key.assign(params.key.begin(), params.key.end()); - if (params.options.associated_data) { - options.associated_data.assign(params.options.associated_data->begin(), - params.options.associated_data->end()); - } - options.encryption_type = - EncryptionTypeToString(params.options.encrypt_type); - options.signature_type = - SignatureTypeToString(params.options.sign_type); - - dbus_client_->UnwrapSecureMessage( - std::string(params.secure_message.begin(), params.secure_message.end()), - options, callback); - } - - private: - chromeos::EasyUnlockClient* dbus_client_; - - DISALLOW_COPY_AND_ASSIGN(EasyUnlockPrivateCryptoDelegateChromeOS); -}; - -} // namespace - -// static -std::unique_ptr<EasyUnlockPrivateCryptoDelegate> -EasyUnlockPrivateCryptoDelegate::Create() { - return std::unique_ptr<EasyUnlockPrivateCryptoDelegate>( - new EasyUnlockPrivateCryptoDelegateChromeOS()); -} - -} // namespace extensions diff --git a/chromium/chrome/browser/extensions/api/easy_unlock_private/easy_unlock_private_crypto_delegate_stub.cc b/chromium/chrome/browser/extensions/api/easy_unlock_private/easy_unlock_private_crypto_delegate_stub.cc deleted file mode 100644 index 5a7161c90c2..00000000000 --- a/chromium/chrome/browser/extensions/api/easy_unlock_private/easy_unlock_private_crypto_delegate_stub.cc +++ /dev/null @@ -1,57 +0,0 @@ -// Copyright 2014 The Chromium Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -#include "base/macros.h" -#include "chrome/browser/extensions/api/easy_unlock_private/easy_unlock_private_crypto_delegate.h" - -namespace extensions { - -namespace easy_unlock_private = api::easy_unlock_private; - -namespace { - -// Stub EasyUnlockPrivateCryptoDelegate implementation. -class EasyUnlockPrivateCryptoDelegateStub - : public extensions::EasyUnlockPrivateCryptoDelegate { - public: - EasyUnlockPrivateCryptoDelegateStub() {} - - ~EasyUnlockPrivateCryptoDelegateStub() override {} - - void GenerateEcP256KeyPair(const KeyPairCallback& callback) override { - callback.Run("", ""); - } - - void PerformECDHKeyAgreement( - const easy_unlock_private::PerformECDHKeyAgreement::Params& params, - const DataCallback& callback) override { - callback.Run(""); - } - - void CreateSecureMessage( - const easy_unlock_private::CreateSecureMessage::Params& params, - const DataCallback& callback) override { - callback.Run(""); - } - - void UnwrapSecureMessage( - const easy_unlock_private::UnwrapSecureMessage::Params& params, - const DataCallback& callback) override { - callback.Run(""); - } - - private: - DISALLOW_COPY_AND_ASSIGN(EasyUnlockPrivateCryptoDelegateStub); -}; - -} // namespace - -// static -std::unique_ptr<EasyUnlockPrivateCryptoDelegate> -EasyUnlockPrivateCryptoDelegate::Create() { - return std::unique_ptr<EasyUnlockPrivateCryptoDelegate>( - new EasyUnlockPrivateCryptoDelegateStub()); -} - -} // namespace extensions diff --git a/chromium/chrome/browser/extensions/api/enterprise_device_attributes/enterprise_device_attributes_apitest.cc b/chromium/chrome/browser/extensions/api/enterprise_device_attributes/enterprise_device_attributes_apitest.cc index 8f2b5a933e6..c923b2d663b 100644 --- a/chromium/chrome/browser/extensions/api/enterprise_device_attributes/enterprise_device_attributes_apitest.cc +++ b/chromium/chrome/browser/extensions/api/enterprise_device_attributes/enterprise_device_attributes_apitest.cc @@ -18,11 +18,11 @@ #include "chromeos/dbus/fake_session_manager_client.h" #include "chromeos/system/fake_statistics_provider.h" #include "chromeos/system/statistics_provider.h" +#include "components/account_id/account_id.h" #include "components/policy/core/common/cloud/device_management_service.h" #include "components/policy/core/common/mock_configuration_policy_provider.h" #include "components/policy/policy_constants.h" #include "components/prefs/pref_service.h" -#include "components/signin/core/account_id/account_id.h" #include "components/user_manager/user_manager.h" #include "content/public/browser/browser_thread.h" #include "content/public/browser/notification_service.h" @@ -84,7 +84,7 @@ class EnterpriseDeviceAttributesTest : public: EnterpriseDeviceAttributesTest() { fake_statistics_provider_.SetMachineStatistic( - chromeos::system::kSerialNumberKey, kSerialNumber); + chromeos::system::kSerialNumberKeyForTest, kSerialNumber); set_exit_when_last_browser_closes(false); set_chromeos_user_ = false; } diff --git a/chromium/chrome/browser/extensions/api/enterprise_platform_keys/enterprise_platform_keys_api_unittest.cc b/chromium/chrome/browser/extensions/api/enterprise_platform_keys/enterprise_platform_keys_api_unittest.cc index d974bf51ac0..7fff815039e 100644 --- a/chromium/chrome/browser/extensions/api/enterprise_platform_keys/enterprise_platform_keys_api_unittest.cc +++ b/chromium/chrome/browser/extensions/api/enterprise_platform_keys/enterprise_platform_keys_api_unittest.cc @@ -28,9 +28,9 @@ #include "chromeos/cryptohome/mock_async_method_caller.h" #include "chromeos/dbus/dbus_method_call_status.h" #include "chromeos/dbus/fake_cryptohome_client.h" +#include "components/account_id/account_id.h" #include "components/policy/core/common/cloud/cloud_policy_constants.h" #include "components/prefs/pref_service.h" -#include "components/signin/core/account_id/account_id.h" #include "components/signin/core/browser/signin_manager.h" #include "components/user_manager/scoped_user_manager.h" #include "extensions/common/extension_builder.h" diff --git a/chromium/chrome/browser/extensions/api/enterprise_platform_keys/enterprise_platform_keys_apitest_nss.cc b/chromium/chrome/browser/extensions/api/enterprise_platform_keys/enterprise_platform_keys_apitest_nss.cc index 5e20545888f..0566fd88cdc 100644 --- a/chromium/chrome/browser/extensions/api/enterprise_platform_keys/enterprise_platform_keys_apitest_nss.cc +++ b/chromium/chrome/browser/extensions/api/enterprise_platform_keys/enterprise_platform_keys_apitest_nss.cc @@ -26,6 +26,8 @@ #include "testing/gmock/include/gmock/gmock.h" #include "testing/gtest/include/gtest/gtest.h" +namespace extensions { + namespace { // The test extension has a certificate referencing this private key which will @@ -191,8 +193,7 @@ class EnterprisePlatformKeysTest policy::POLICY_SOURCE_CLOUD, std::move(forcelist), nullptr); // Set the policy and wait until the extension is installed. - extensions::TestExtensionRegistryObserver observer( - extensions::ExtensionRegistry::Get(profile())); + TestExtensionRegistryObserver observer(ExtensionRegistry::Get(profile())); mock_policy_provider()->UpdateChromePolicy(policy); observer.WaitForExtensionWillBeInstalled(); } @@ -269,9 +270,6 @@ INSTANTIATE_TEST_CASE_P( PlatformKeysTestBase::EnrollmentStatus::ENROLLED, PlatformKeysTestBase::UserStatus::MANAGED_AFFILIATED_DOMAIN))); -class EnterprisePlatformKeysTestNonPolicyInstalledExtension - : public EnterprisePlatformKeysTest {}; - // Ensure that extensions that are not pre-installed by policy throw an install // warning if they request the enterprise.platformKeys permission in the // manifest and that such extensions don't see the @@ -284,9 +282,8 @@ IN_PROC_BROWSER_TEST_F(ExtensionApiTest, base::FilePath extension_path = test_data_dir_.AppendASCII("enterprise_platform_keys"); - extensions::ExtensionRegistry* registry = - extensions::ExtensionRegistry::Get(profile()); - const extensions::Extension* extension = + ExtensionRegistry* registry = ExtensionRegistry::Get(profile()); + const Extension* extension = GetExtensionByPath(registry->enabled_extensions(), extension_path); ASSERT_FALSE(extension->install_warnings().empty()); EXPECT_EQ( @@ -294,3 +291,5 @@ IN_PROC_BROWSER_TEST_F(ExtensionApiTest, "location.", extension->install_warnings()[0].message); } + +} // namespace extensions diff --git a/chromium/chrome/browser/extensions/api/enterprise_platform_keys_private/enterprise_platform_keys_private_api.cc b/chromium/chrome/browser/extensions/api/enterprise_platform_keys_private/enterprise_platform_keys_private_api.cc index e42c29e6c6f..f609d252df9 100644 --- a/chromium/chrome/browser/extensions/api/enterprise_platform_keys_private/enterprise_platform_keys_private_api.cc +++ b/chromium/chrome/browser/extensions/api/enterprise_platform_keys_private/enterprise_platform_keys_private_api.cc @@ -9,7 +9,6 @@ #include "base/base64.h" #include "base/callback.h" -#include "base/message_loop/message_loop.h" #include "base/strings/stringprintf.h" #include "base/values.h" #include "chrome/browser/browser_process.h" @@ -31,9 +30,9 @@ #include "chromeos/dbus/dbus_method_call_status.h" #include "chromeos/dbus/dbus_thread_manager.h" #include "chromeos/settings/cros_settings_names.h" +#include "components/account_id/account_id.h" #include "components/pref_registry/pref_registry_syncable.h" #include "components/prefs/pref_service.h" -#include "components/signin/core/account_id/account_id.h" #include "components/signin/core/browser/signin_manager.h" #include "components/user_manager/known_user.h" #include "components/user_manager/user.h" @@ -148,6 +147,11 @@ bool EPKPChallengeKeyBase::IsExtensionWhitelisted() const { // TODO(drcrash): Use a separate device-wide policy for the API. return Manifest::IsPolicyLocation(extension_->location()); } + if (Manifest::IsComponentLocation(extension_->location())) { + // Note: For this to even be called, the component extension must also be + // whitelisted in chrome/common/extensions/api/_permission_features.json + return true; + } const base::ListValue* list = profile_->GetPrefs()->GetList(prefs::kAttestationExtensionWhitelist); base::Value value(extension_->id()); diff --git a/chromium/chrome/browser/extensions/api/enterprise_platform_keys_private/enterprise_platform_keys_private_api.h b/chromium/chrome/browser/extensions/api/enterprise_platform_keys_private/enterprise_platform_keys_private_api.h index a80e5d5930f..5409d5a735b 100644 --- a/chromium/chrome/browser/extensions/api/enterprise_platform_keys_private/enterprise_platform_keys_private_api.h +++ b/chromium/chrome/browser/extensions/api/enterprise_platform_keys_private/enterprise_platform_keys_private_api.h @@ -18,7 +18,7 @@ #include "chromeos/attestation/attestation_constants.h" #include "chromeos/attestation/attestation_flow.h" #include "chromeos/dbus/cryptohome_client.h" -#include "components/signin/core/account_id/account_id.h" +#include "components/account_id/account_id.h" #include "extensions/browser/extension_function.h" #include "extensions/common/extension.h" #include "third_party/cros_system_api/dbus/service_constants.h" diff --git a/chromium/chrome/browser/extensions/api/enterprise_platform_keys_private/enterprise_platform_keys_private_api_unittest.cc b/chromium/chrome/browser/extensions/api/enterprise_platform_keys_private/enterprise_platform_keys_private_api_unittest.cc index 03541c19880..93064bb1354 100644 --- a/chromium/chrome/browser/extensions/api/enterprise_platform_keys_private/enterprise_platform_keys_private_api_unittest.cc +++ b/chromium/chrome/browser/extensions/api/enterprise_platform_keys_private/enterprise_platform_keys_private_api_unittest.cc @@ -30,9 +30,9 @@ #include "chromeos/cryptohome/cryptohome_parameters.h" #include "chromeos/cryptohome/mock_async_method_caller.h" #include "chromeos/dbus/fake_cryptohome_client.h" +#include "components/account_id/account_id.h" #include "components/policy/core/common/cloud/cloud_policy_constants.h" #include "components/prefs/pref_service.h" -#include "components/signin/core/account_id/account_id.h" #include "components/signin/core/browser/signin_manager.h" #include "components/user_manager/scoped_user_manager.h" #include "extensions/common/extension_builder.h" diff --git a/chromium/chrome/browser/extensions/api/enterprise_reporting_private/chrome_desktop_report_request_helper.cc b/chromium/chrome/browser/extensions/api/enterprise_reporting_private/chrome_desktop_report_request_helper.cc index 05c2b24bb68..4eae3e8ead7 100644 --- a/chromium/chrome/browser/extensions/api/enterprise_reporting_private/chrome_desktop_report_request_helper.cc +++ b/chromium/chrome/browser/extensions/api/enterprise_reporting_private/chrome_desktop_report_request_helper.cc @@ -11,11 +11,17 @@ #include "base/path_service.h" #include "base/strings/utf_string_conversions.h" #include "base/values.h" +#include "chrome/browser/browser_process.h" +#include "chrome/browser/policy/chrome_browser_policy_connector.h" #include "chrome/browser/policy/policy_conversions.h" #include "chrome/browser/profiles/profile.h" #include "chrome/common/channel_info.h" +#include "chrome/common/pref_names.h" +#include "components/policy/core/common/cloud/cloud_policy_client.h" #include "components/policy/core/common/cloud/cloud_policy_util.h" +#include "components/policy/core/common/cloud/machine_level_user_cloud_policy_manager.h" #include "components/policy/proto/device_management_backend.pb.h" +#include "components/prefs/pref_service.h" #include "components/version_info/channel.h" #include "components/version_info/version_info.h" @@ -24,18 +30,19 @@ namespace em = enterprise_management; namespace extensions { namespace { -// JSON key in extension arguments. -const char kMachineName[] = "machineName"; -const char kOSInfo[] = "osInfo"; -const char kOSUser[] = "osUser"; +// JSON keys in the extension arguments. const char kBrowserReport[] = "browserReport"; const char kChromeUserProfileReport[] = "chromeUserProfileReport"; const char kChromeSignInUser[] = "chromeSignInUser"; const char kExtensionData[] = "extensionData"; const char kPlugins[] = "plugins"; +const char kSafeBrowsingWarnings[] = "safeBrowsingWarnings"; +const char kSafeBrowsingWarningsClickThrough[] = + "safeBrowsingWarningsClickThrough"; -// JSON key in the os_info field. +// JSON keys in the os_info field. const char kOS[] = "os"; +const char kOSArch[] = "arch"; const char kOSVersion[] = "os_version"; const char kDefaultDictionary[] = "{}"; @@ -56,6 +63,17 @@ std::string GetProfileId(const Profile* profile) { return profile->GetOriginalProfile()->GetPath().AsUTF8Unsafe(); } +// Returns last policy fetch timestamp of machine level user cloud policy if +// it exists. Otherwise, returns zero. +int64_t GetMachineLevelUserCloudPolicyFetchTimestamp() { + policy::MachineLevelUserCloudPolicyManager* manager = + g_browser_process->browser_policy_connector() + ->GetMachineLevelUserCloudPolicyManager(); + if (!manager || !manager->IsClientRegistered()) + return 0; + return manager->core()->client()->last_policy_timestamp().ToJavaTime(); +} + void AppendAdditionalBrowserInformation(em::ChromeDesktopReportRequest* request, Profile* profile) { // Set Chrome version number @@ -76,11 +94,24 @@ void AppendAdditionalBrowserInformation(em::ChromeDesktopReportRequest* request, request->mutable_browser_report() ->mutable_chrome_user_profile_reports(0) ->set_id(GetProfileId(profile)); + // Set policy data of the first profile. Extension will report this data in // the future. request->mutable_browser_report() ->mutable_chrome_user_profile_reports(0) ->set_policy_data(policy::GetAllPolicyValuesAsJSON(profile, true)); + + int64_t timestamp = GetMachineLevelUserCloudPolicyFetchTimestamp(); + if (timestamp > 0) { + request->mutable_browser_report() + ->mutable_chrome_user_profile_reports(0) + ->set_policy_fetched_timestamp(timestamp); + } + + // Set the profile name + request->mutable_browser_report() + ->mutable_chrome_user_profile_reports(0) + ->set_name(profile->GetPrefs()->GetString(prefs::kProfileName)); } bool UpdateJSONEncodedStringEntry(const base::Value& dict_value, @@ -103,17 +134,23 @@ bool UpdateJSONEncodedStringEntry(const base::Value& dict_value, return true; } -bool UpdateOSInfoEntry(const base::Value& report, std::string* os_info_string) { - base::Value writable_os_info(base::Value::Type::DICTIONARY); - if (const base::Value* os_info = report.FindKey(kOSInfo)) { - if (!os_info->is_dict()) - return false; - writable_os_info = os_info->Clone(); - } - writable_os_info.SetKey(kOS, base::Value(policy::GetOSPlatform())); - writable_os_info.SetKey(kOSVersion, base::Value(policy::GetOSVersion())); - base::JSONWriter::Write(writable_os_info, os_info_string); - return true; +void AppendPlatformInformation(em::ChromeDesktopReportRequest* request) { + const char kComputerName[] = "computername"; + const char kUsername[] = "username"; + + base::Value os_info = base::Value(base::Value::Type::DICTIONARY); + os_info.SetKey(kOS, base::Value(policy::GetOSPlatform())); + os_info.SetKey(kOSVersion, base::Value(policy::GetOSVersion())); + os_info.SetKey(kOSArch, base::Value(policy::GetOSArchitecture())); + base::JSONWriter::Write(os_info, request->mutable_os_info()); + + base::Value machine_name = base::Value(base::Value::Type::DICTIONARY); + machine_name.SetKey(kComputerName, base::Value(policy::GetMachineName())); + base::JSONWriter::Write(machine_name, request->mutable_machine_name()); + + base::Value os_user = base::Value(base::Value::Type::DICTIONARY); + os_user.SetKey(kUsername, base::Value(policy::GetOSUsername())); + base::JSONWriter::Write(os_user, request->mutable_os_user()); } std::unique_ptr<em::ChromeUserProfileReport> @@ -134,6 +171,20 @@ GenerateChromeUserProfileReportRequest(const base::Value& profile_report) { return nullptr; } + if (const base::Value* count = + profile_report.FindKey(kSafeBrowsingWarnings)) { + if (!count->is_int()) + return nullptr; + request->set_safe_browsing_warnings(count->GetInt()); + } + + if (const base::Value* count = + profile_report.FindKey(kSafeBrowsingWarningsClickThrough)) { + if (!count->is_int()) + return nullptr; + request->set_safe_browsing_warnings_click_through(count->GetInt()); + } + return request; } @@ -145,13 +196,7 @@ GenerateChromeDesktopReportRequest(const base::DictionaryValue& report, std::unique_ptr<em::ChromeDesktopReportRequest> request = std::make_unique<em::ChromeDesktopReportRequest>(); - if (!UpdateJSONEncodedStringEntry( - report, kMachineName, request->mutable_machine_name(), DICTIONARY) || - !UpdateJSONEncodedStringEntry(report, kOSUser, request->mutable_os_user(), - DICTIONARY) || - !UpdateOSInfoEntry(report, request->mutable_os_info())) { - return nullptr; - } + AppendPlatformInformation(request.get()); if (const base::Value* browser_report = report.FindKeyOfType(kBrowserReport, base::Value::Type::DICTIONARY)) { diff --git a/chromium/chrome/browser/extensions/api/enterprise_reporting_private/chrome_desktop_report_request_helper_unittest.cc b/chromium/chrome/browser/extensions/api/enterprise_reporting_private/chrome_desktop_report_request_helper_unittest.cc index fe6ef6e2b70..97d58f1c3ac 100644 --- a/chromium/chrome/browser/extensions/api/enterprise_reporting_private/chrome_desktop_report_request_helper_unittest.cc +++ b/chromium/chrome/browser/extensions/api/enterprise_reporting_private/chrome_desktop_report_request_helper_unittest.cc @@ -5,10 +5,13 @@ #include "chrome/browser/extensions/api/enterprise_reporting_private/chrome_desktop_report_request_helper.h" #include "base/json/json_reader.h" +#include "base/json/string_escape.h" #include "base/values.h" +#include "chrome/common/pref_names.h" #include "chrome/test/base/testing_profile.h" #include "components/policy/core/common/cloud/cloud_policy_util.h" #include "components/policy/proto/device_management_backend.pb.h" +#include "components/prefs/pref_service.h" #include "content/public/test/test_browser_thread_bundle.h" #include "testing/gtest/include/gtest/gtest.h" @@ -27,46 +30,57 @@ TEST_F(ChromeDesktopReportRequestGeneratorTest, OSInfo) { std::unique_ptr<em::ChromeDesktopReportRequest> request; std::string expected_os_info; - // Platform and its version will be the |os_info| by default. - expected_os_info = base::StringPrintf("{\"os\":\"%s\",\"os_version\":\"%s\"}", - policy::GetOSPlatform().c_str(), - policy::GetOSVersion().c_str()); + expected_os_info = base::StringPrintf( + "{\"arch\":\"%s\",\"os\":\"%s\",\"os_version\":\"%s\"}", + policy::GetOSArchitecture().c_str(), policy::GetOSPlatform().c_str(), + policy::GetOSVersion().c_str()); request = GenerateChromeDesktopReportRequest(base::DictionaryValue(), &profile_); ASSERT_TRUE(request); EXPECT_EQ(expected_os_info, request->os_info()); - - // Platform and its version will be merged with other |os_info|. - expected_os_info = base::StringPrintf( - "{\"os\":\"%s\",\"os_version\":\"%s\",\"other_info\":\"info\"}", - policy::GetOSPlatform().c_str(), policy::GetOSVersion().c_str()); - std::unique_ptr<base::DictionaryValue> report = base::DictionaryValue::From( - base::JSONReader::Read("{\"osInfo\": {\"other_info\":\"info\"}}")); - ASSERT_TRUE(report); - request = GenerateChromeDesktopReportRequest(*report, &profile_); - ASSERT_TRUE(request); - EXPECT_EQ(expected_os_info, request->os_info()); } TEST_F(ChromeDesktopReportRequestGeneratorTest, MachineName) { std::unique_ptr<em::ChromeDesktopReportRequest> request; std::string expected_machine_name; - // Machine name will be a empty dict by default. - expected_machine_name = "{}"; + expected_machine_name = base::StringPrintf("{\"computername\":\"%s\"}", + policy::GetMachineName().c_str()); request = GenerateChromeDesktopReportRequest(base::DictionaryValue(), &profile_); ASSERT_TRUE(request); EXPECT_EQ(expected_machine_name, request->machine_name()); +} - // Machine name will be copied from the |report|. - expected_machine_name = "{\"computername\":\"name\"}"; - std::unique_ptr<base::DictionaryValue> report = base::DictionaryValue::From( - base::JSONReader::Read("{\"machineName\":{\"computername\":\"name\"}}")); - ASSERT_TRUE(report); - request = GenerateChromeDesktopReportRequest(*report, &profile_); +TEST_F(ChromeDesktopReportRequestGeneratorTest, OSUsername) { + std::unique_ptr<em::ChromeDesktopReportRequest> request; + std::string expected_os_username, os_username_escaped; + + // The username needs to be escaped as the name can contain slashes. + base::EscapeJSONString(policy::GetOSUsername(), false, &os_username_escaped); + expected_os_username = + base::StringPrintf("{\"username\":\"%s\"}", os_username_escaped.c_str()); + + request = + GenerateChromeDesktopReportRequest(base::DictionaryValue(), &profile_); ASSERT_TRUE(request); - EXPECT_EQ(expected_machine_name, request->machine_name()); + EXPECT_EQ(expected_os_username, request->os_user()); +} + +TEST_F(ChromeDesktopReportRequestGeneratorTest, ProfileName) { + // Set the profile name to a known value to compare against. + const std::string test_name("TEST"); + profile_.GetPrefs()->SetString(prefs::kProfileName, test_name); + + // An empty report suffices for this test. The information of interest is + // sourced from the profile + std::unique_ptr<em::ChromeDesktopReportRequest> request = + GenerateChromeDesktopReportRequest(base::DictionaryValue(), &profile_); + ASSERT_TRUE(request); + + // Make sure the user name was set in the proto. + EXPECT_EQ(test_name, + request->browser_report().chrome_user_profile_reports(0).name()); } TEST_F(ChromeDesktopReportRequestGeneratorTest, ExtensionList) { @@ -124,21 +138,49 @@ TEST_F(ChromeDesktopReportRequestGeneratorTest, ProfileID) { TEST_F(ChromeDesktopReportRequestGeneratorTest, InvalidInput) { // |request| will not be generated if the type of input is invalid. std::unique_ptr<base::DictionaryValue> report; - report = base::DictionaryValue::From( - base::JSONReader::Read("{\"osInfo\": \"info\"}")); + report = base::DictionaryValue::From(base::JSONReader::Read( + "{\"browserReport\": " + "{\"chromeUserProfileReport\":[{\"extensionData\":{}}]}}")); ASSERT_TRUE(report); EXPECT_FALSE(GenerateChromeDesktopReportRequest(*report, &profile_)); + report = base::DictionaryValue::From(base::JSONReader::Read( + "{\"browserReport\": " + "{\"chromeUserProfileReport\":[{\"chromeSignInUser\":\"\"}]}}")); + ASSERT_TRUE(report); + EXPECT_FALSE(GenerateChromeDesktopReportRequest(*report, &profile_)); +} + +TEST_F(ChromeDesktopReportRequestGeneratorTest, SafeBrowsing) { + std::unique_ptr<base::DictionaryValue> report; report = base::DictionaryValue::From( - base::JSONReader::Read("{\"machineName\": \"info\"}")); + base::JSONReader::Read("{\"browserReport\": " + "{\"chromeUserProfileReport\":[{" + "\"safeBrowsingWarnings\":\"invalid\"}]}}")); ASSERT_TRUE(report); EXPECT_FALSE(GenerateChromeDesktopReportRequest(*report, &profile_)); report = base::DictionaryValue::From(base::JSONReader::Read( "{\"browserReport\": " - "{\"chromeUserProfileReport\":[{\"extensionData\":{}}]}}")); + "{\"chromeUserProfileReport\":[{\"safeBrowsingWarningsClickThrough\":" + "\"invalid\"}]}}")); ASSERT_TRUE(report); EXPECT_FALSE(GenerateChromeDesktopReportRequest(*report, &profile_)); + + report = base::DictionaryValue::From(base::JSONReader::Read( + "{\"browserReport\": " + "{\"chromeUserProfileReport\":[{\"safeBrowsingWarnings\":3, " + "\"safeBrowsingWarningsClickThrough\":1}]}}")); + ASSERT_TRUE(report); + std::unique_ptr<em::ChromeDesktopReportRequest> request = + GenerateChromeDesktopReportRequest(*report, &profile_); + ASSERT_TRUE(request); + EXPECT_EQ(3u, request->browser_report() + .chrome_user_profile_reports(0) + .safe_browsing_warnings()); + EXPECT_EQ(1u, request->browser_report() + .chrome_user_profile_reports(0) + .safe_browsing_warnings_click_through()); } } // namespace extensions diff --git a/chromium/chrome/browser/extensions/api/enterprise_reporting_private/enterprise_reporting_private_api.cc b/chromium/chrome/browser/extensions/api/enterprise_reporting_private/enterprise_reporting_private_api.cc index de8a865ecb5..0ecdfca701f 100644 --- a/chromium/chrome/browser/extensions/api/enterprise_reporting_private/enterprise_reporting_private_api.cc +++ b/chromium/chrome/browser/extensions/api/enterprise_reporting_private/enterprise_reporting_private_api.cc @@ -40,7 +40,8 @@ EnterpriseReportingPrivateUploadChromeDesktopReportFunction:: if (device_management_service) device_management_service->ScheduleInitialization(0); cloud_policy_client_ = std::make_unique<policy::CloudPolicyClient>( - std::string(), std::string(), device_management_service, + std::string() /* machine_id */, std::string() /* machine_model */, + std::string() /* brand_code */, device_management_service, g_browser_process->system_request_context(), nullptr, policy::CloudPolicyClient::DeviceDMTokenCallback()); dm_token_ = policy::BrowserDMTokenStorage::Get()->RetrieveDMToken(); diff --git a/chromium/chrome/browser/extensions/api/enterprise_reporting_private/enterprise_reporting_private_unittest.cc b/chromium/chrome/browser/extensions/api/enterprise_reporting_private/enterprise_reporting_private_unittest.cc index 72f932d92a3..14c234c68d6 100644 --- a/chromium/chrome/browser/extensions/api/enterprise_reporting_private/enterprise_reporting_private_unittest.cc +++ b/chromium/chrome/browser/extensions/api/enterprise_reporting_private/enterprise_reporting_private_unittest.cc @@ -21,7 +21,6 @@ namespace { const char kFakeDMToken[] = "fake-dm-token"; const char kFakeClientId[] = "fake-client-id"; const char kFakeMachineNameReport[] = "{\"computername\":\"name\"}"; -const char kFakeInvalidMachineNameReport[] = "\"invalid\""; class MockCloudPolicyClient : public policy::MockCloudPolicyClient { public: @@ -30,7 +29,7 @@ class MockCloudPolicyClient : public policy::MockCloudPolicyClient { void UploadChromeDesktopReport( std::unique_ptr<enterprise_management::ChromeDesktopReportRequest> request, - const StatusCallback& callback) { + const StatusCallback& callback) override { UploadChromeDesktopReportProxy(request.get(), callback); } MOCK_METHOD2(UploadChromeDesktopReportProxy, @@ -73,6 +72,14 @@ class EnterpriseReportingPrivateTest : public ExtensionApiUnittest { return base::StringPrintf("[{\"machineName\":%s}]", name); } + std::string GenerateInvalidReport() { + // This report is invalid as the chromeSignInUser dictionary should not be + // wrapped in a list. + return std::string( + "[{\"browserReport\": " + "{\"chromeUserProfileReport\":[{\"chromeSignInUser\":\"Name\"}]}}]"); + } + MockCloudPolicyClient* client_; private: @@ -90,7 +97,7 @@ TEST_F(EnterpriseReportingPrivateTest, ReportIsNotValid) { ASSERT_EQ(enterprise_reporting::kInvalidInputErrorMessage, RunFunctionAndReturnError( CreateChromeDesktopReportingFunction(kFakeDMToken), - GenerateArgs(kFakeInvalidMachineNameReport))); + GenerateInvalidReport())); } TEST_F(EnterpriseReportingPrivateTest, UploadFailed) { diff --git a/chromium/chrome/browser/extensions/api/extension_action/browser_action_browsertest.cc b/chromium/chrome/browser/extensions/api/extension_action/browser_action_browsertest.cc index d474eff3540..fdf5d3c0227 100644 --- a/chromium/chrome/browser/extensions/api/extension_action/browser_action_browsertest.cc +++ b/chromium/chrome/browser/extensions/api/extension_action/browser_action_browsertest.cc @@ -3,7 +3,6 @@ // found in the LICENSE file. #include "base/files/file_path.h" -#include "base/message_loop/message_loop.h" #include "chrome/browser/extensions/extension_action.h" #include "chrome/browser/extensions/extension_action_manager.h" #include "chrome/browser/extensions/extension_browsertest.h" diff --git a/chromium/chrome/browser/extensions/api/extension_action/extension_action_api.cc b/chromium/chrome/browser/extensions/api/extension_action/extension_action_api.cc index 3d48f3a8e6d..0b69a15ff2a 100644 --- a/chromium/chrome/browser/extensions/api/extension_action/extension_action_api.cc +++ b/chromium/chrome/browser/extensions/api/extension_action/extension_action_api.cc @@ -543,13 +543,11 @@ ExtensionActionGetBadgeBackgroundColorFunction::RunExtensionAction() { return RespondNow(OneArgument(std::move(list))); } -BrowserActionOpenPopupFunction::BrowserActionOpenPopupFunction() - : response_sent_(false) { -} +BrowserActionOpenPopupFunction::BrowserActionOpenPopupFunction() = default; -bool BrowserActionOpenPopupFunction::RunAsync() { +ExtensionFunction::ResponseAction BrowserActionOpenPopupFunction::Run() { // We only allow the popup in the active window. - Profile* profile = GetProfile(); + Profile* profile = Profile::FromBrowserContext(browser_context()); Browser* browser = chrome::FindLastActiveWithProfile(profile); // It's possible that the last active browser actually corresponds to the // associated incognito profile, and this won't be returned by @@ -566,13 +564,11 @@ bool BrowserActionOpenPopupFunction::RunAsync() { // Otherwise, try to open a popup in the active browser. // TODO(justinlin): Remove toolbar check when http://crbug.com/308645 is // fixed. - if (!browser || - !browser->window()->IsActive() || + if (!browser || !browser->window()->IsActive() || !browser->window()->IsToolbarVisible() || - !ExtensionActionAPI::Get(GetProfile())->ShowExtensionActionPopup( + !ExtensionActionAPI::Get(profile)->ShowExtensionActionPopup( extension_.get(), browser, false)) { - error_ = kOpenPopupError; - return false; + return RespondNow(Error(kOpenPopupError)); } // Even if this is for an incognito window, we want to use the normal profile. @@ -590,17 +586,15 @@ bool BrowserActionOpenPopupFunction::RunAsync() { FROM_HERE, base::BindOnce(&BrowserActionOpenPopupFunction::OpenPopupTimedOut, this), base::TimeDelta::FromSeconds(10)); - return true; + return RespondLater(); } void BrowserActionOpenPopupFunction::OpenPopupTimedOut() { - if (response_sent_) + if (did_respond()) return; DVLOG(1) << "chrome.browserAction.openPopup did not show a popup."; - error_ = kOpenPopupError; - SendResponse(false); - response_sent_ = true; + Respond(Error(kOpenPopupError)); } void BrowserActionOpenPopupFunction::Observe( @@ -608,7 +602,7 @@ void BrowserActionOpenPopupFunction::Observe( const content::NotificationSource& source, const content::NotificationDetails& details) { DCHECK_EQ(NOTIFICATION_EXTENSION_HOST_DID_STOP_FIRST_LOAD, type); - if (response_sent_) + if (did_respond()) return; ExtensionHost* host = content::Details<ExtensionHost>(details).ptr(); @@ -616,8 +610,7 @@ void BrowserActionOpenPopupFunction::Observe( host->extension()->id() != extension_->id()) return; - SendResponse(true); - response_sent_ = true; + Respond(NoArguments()); registrar_.RemoveAll(); } diff --git a/chromium/chrome/browser/extensions/api/extension_action/extension_action_api.h b/chromium/chrome/browser/extensions/api/extension_action/extension_action_api.h index 6e003ace148..051518beed5 100644 --- a/chromium/chrome/browser/extensions/api/extension_action/extension_action_api.h +++ b/chromium/chrome/browser/extensions/api/extension_action/extension_action_api.h @@ -9,12 +9,12 @@ #include "base/macros.h" #include "base/observer_list.h" -#include "chrome/browser/extensions/chrome_extension_function.h" #include "chrome/browser/extensions/extension_action.h" #include "content/public/browser/notification_observer.h" #include "content/public/browser/notification_registrar.h" #include "extensions/browser/browser_context_keyed_api_factory.h" #include "extensions/browser/extension_event_histogram_value.h" +#include "extensions/browser/extension_function.h" #include "third_party/skia/include/core/SkColor.h" namespace base { @@ -26,6 +26,8 @@ class BrowserContext; class WebContents; } +class Browser; + namespace extensions { class ExtensionPrefs; @@ -358,7 +360,7 @@ class BrowserActionDisableFunction : public ExtensionActionHideFunction { ~BrowserActionDisableFunction() override {} }; -class BrowserActionOpenPopupFunction : public ChromeAsyncExtensionFunction, +class BrowserActionOpenPopupFunction : public UIThreadExtensionFunction, public content::NotificationObserver { public: DECLARE_EXTENSION_FUNCTION("browserAction.openPopup", @@ -369,7 +371,7 @@ class BrowserActionOpenPopupFunction : public ChromeAsyncExtensionFunction, ~BrowserActionOpenPopupFunction() override {} // ExtensionFunction: - bool RunAsync() override; + ResponseAction Run() override; void Observe(int type, const content::NotificationSource& source, @@ -377,7 +379,6 @@ class BrowserActionOpenPopupFunction : public ChromeAsyncExtensionFunction, void OpenPopupTimedOut(); content::NotificationRegistrar registrar_; - bool response_sent_; DISALLOW_COPY_AND_ASSIGN(BrowserActionOpenPopupFunction); }; diff --git a/chromium/chrome/browser/extensions/api/extension_action/extension_action_apitest.cc b/chromium/chrome/browser/extensions/api/extension_action/extension_action_apitest.cc index fb57664c7ca..f12831ad5e7 100644 --- a/chromium/chrome/browser/extensions/api/extension_action/extension_action_apitest.cc +++ b/chromium/chrome/browser/extensions/api/extension_action/extension_action_apitest.cc @@ -9,14 +9,20 @@ #include "base/run_loop.h" #include "base/scoped_observer.h" #include "base/strings/stringprintf.h" +#include "chrome/browser/extensions/extension_action.h" +#include "chrome/browser/extensions/extension_action_manager.h" #include "chrome/browser/extensions/extension_apitest.h" #include "chrome/browser/sessions/session_tab_helper.h" #include "chrome/browser/ui/browser.h" #include "chrome/browser/ui/tabs/tab_strip_model.h" +#include "chrome/test/base/ui_test_utils.h" +#include "content/public/browser/web_contents.h" +#include "content/public/test/test_utils.h" #include "extensions/browser/browsertest_util.h" #include "extensions/browser/state_store.h" #include "extensions/test/extension_test_message_listener.h" #include "extensions/test/test_extension_dir.h" +#include "ui/base/window_open_disposition.h" namespace extensions { namespace { @@ -160,4 +166,59 @@ IN_PROC_BROWSER_TEST_F(ExtensionActionAPITest, TestNoUnnecessaryIO) { } } +// Verify that tab-specific values are cleared on navigation and on tab +// removal. Regression test for https://crbug.com/834033. +IN_PROC_BROWSER_TEST_F(ExtensionActionAPITest, + ValuesAreClearedOnNavigationAndTabRemoval) { + ASSERT_TRUE(StartEmbeddedTestServer()); + + TestExtensionDir test_dir; + test_dir.WriteManifest( + R"({ + "name": "Extension", + "description": "An extension", + "manifest_version": 2, + "version": "0.1", + "browser_action": {} + })"); + const Extension* extension = LoadExtension(test_dir.UnpackedPath()); + ASSERT_TRUE(extension); + + auto* action_manager = ExtensionActionManager::Get(profile()); + ExtensionAction* action = action_manager->GetExtensionAction(*extension); + ASSERT_TRUE(action); + + GURL initial_url = embedded_test_server()->GetURL("/title1.html"); + ui_test_utils::NavigateToURLWithDisposition( + browser(), initial_url, WindowOpenDisposition::NEW_FOREGROUND_TAB, + ui_test_utils::BROWSER_TEST_WAIT_FOR_NAVIGATION); + + TabStripModel* tab_strip_model = browser()->tab_strip_model(); + content::WebContents* web_contents = tab_strip_model->GetActiveWebContents(); + int tab_id = SessionTabHelper::IdForTab(web_contents).id(); + + // There should be no explicit title to start, but should be one if we set + // one. + EXPECT_FALSE(action->HasTitle(tab_id)); + action->SetTitle(tab_id, "alpha"); + EXPECT_TRUE(action->HasTitle(tab_id)); + + // Navigating should clear the title. + GURL second_url = embedded_test_server()->GetURL("/title2.html"); + ui_test_utils::NavigateToURL(browser(), second_url); + + EXPECT_EQ(second_url, web_contents->GetLastCommittedURL()); + EXPECT_FALSE(action->HasTitle(tab_id)); + + action->SetTitle(tab_id, "alpha"); + { + content::WebContentsDestroyedWatcher destroyed_watcher(web_contents); + tab_strip_model->CloseWebContentsAt(tab_strip_model->active_index(), + TabStripModel::CLOSE_NONE); + destroyed_watcher.Wait(); + } + // The title should have been cleared on tab removal as well. + EXPECT_FALSE(action->HasTitle(tab_id)); +} + } // namespace extensions diff --git a/chromium/chrome/browser/extensions/api/feedback_private/feedback_browsertest.cc b/chromium/chrome/browser/extensions/api/feedback_private/feedback_browsertest.cc index 05be2e18013..2087659b39a 100644 --- a/chromium/chrome/browser/extensions/api/feedback_private/feedback_browsertest.cc +++ b/chromium/chrome/browser/extensions/api/feedback_private/feedback_browsertest.cc @@ -3,7 +3,6 @@ // found in the LICENSE file. #include "base/bind.h" -#include "base/message_loop/message_loop.h" #include "base/run_loop.h" #include "chrome/browser/apps/app_browsertest_util.h" #include "chrome/browser/browser_process.h" diff --git a/chromium/chrome/browser/extensions/api/file_system/chrome_file_system_delegate.cc b/chromium/chrome/browser/extensions/api/file_system/chrome_file_system_delegate.cc index 57c2cf505ee..5d0ccc2fed6 100644 --- a/chromium/chrome/browser/extensions/api/file_system/chrome_file_system_delegate.cc +++ b/chromium/chrome/browser/extensions/api/file_system/chrome_file_system_delegate.cc @@ -230,7 +230,7 @@ ChromeFileSystemDelegate::~ChromeFileSystemDelegate() {} base::FilePath ChromeFileSystemDelegate::GetDefaultDirectory() { base::FilePath documents_dir; - PathService::Get(chrome::DIR_USER_DOCUMENTS, &documents_dir); + base::PathService::Get(chrome::DIR_USER_DOCUMENTS, &documents_dir); return documents_dir; } @@ -242,33 +242,28 @@ bool ChromeFileSystemDelegate::ShowSelectFileDialog( FileSystemDelegate::FilesSelectedCallback files_selected_callback, base::OnceClosure file_selection_canceled_callback) { const Extension* extension = extension_function->extension(); - content::WebContents* web_contents = nullptr; + content::WebContents* web_contents = + extension_function->GetSenderWebContents(); + + if (!web_contents) + return false; // TODO(asargent/benwells) - As a short term remediation for // crbug.com/179010 we're adding the ability for a whitelisted extension to // use this API since chrome.fileBrowserHandler.selectFile is ChromeOS-only. // Eventually we'd like a better solution and likely this code will go back // to being platform-app only. - if (extension->is_platform_app()) { - content::WebContents* candidate = content::WebContents::FromRenderFrameHost( - extension_function->render_frame_host()); - // Make sure there is an app window associated with the web contents. - if (AppWindowRegistry::Get(extension_function->browser_context()) - ->GetAppWindowForWebContents(candidate)) { - web_contents = candidate; - } - } else { - // TODO(michaelpg): As a workaround for crbug.com/736930, allow this to work - // from a background page by using the the extended GetAssociatedWebContents - // function provided by ChromeExtensionFunctionDetails. This is safe because - // only whitelisted extensions can access the chrome.fileSystem API; - // platform apps cannot open the file picker from a background page. - web_contents = ChromeExtensionFunctionDetails(extension_function.get()) - .GetAssociatedWebContents(); - } - if (!web_contents) + // Make sure there is an app window associated with the web contents, so that + // platform apps cannot open the file picker from a background page. + // TODO(michaelpg): As a workaround for https://crbug.com/736930, allow this + // to work from a background page for non-platform apps (which, in practice, + // is restricted to whitelisted extensions). + if (extension->is_platform_app() && + !AppWindowRegistry::Get(extension_function->browser_context()) + ->GetAppWindowForWebContents(web_contents)) { return false; + } // The file picker will hold a reference to the UIThreadExtensionFunction // instance, preventing its destruction (and subsequent sending of the diff --git a/chromium/chrome/browser/extensions/api/file_system/consent_provider_unittest.cc b/chromium/chrome/browser/extensions/api/file_system/consent_provider_unittest.cc index cae7ed04cca..2289c0abd82 100644 --- a/chromium/chrome/browser/extensions/api/file_system/consent_provider_unittest.cc +++ b/chromium/chrome/browser/extensions/api/file_system/consent_provider_unittest.cc @@ -181,10 +181,8 @@ TEST_F(FileSystemApiConsentProviderTest, ForKioskApps) { { scoped_refptr<Extension> auto_launch_kiosk_app( ExtensionBuilder("Test", ExtensionBuilder::Type::PLATFORM_APP) - .MergeManifest(DictionaryBuilder() - .SetBoolean("kiosk_enabled", true) - .SetBoolean("kiosk_only", true) - .Build()) + .SetManifestKey("kiosk_enabled", true) + .SetManifestKey("kiosk_only", true) .Build()); user_manager_->AddKioskAppUser( AccountId::FromUserEmail(auto_launch_kiosk_app->id())); @@ -211,10 +209,8 @@ TEST_F(FileSystemApiConsentProviderTest, ForKioskApps) { // receiving approval from the user. scoped_refptr<Extension> manual_launch_kiosk_app( ExtensionBuilder("Test", ExtensionBuilder::Type::PLATFORM_APP) - .MergeManifest(DictionaryBuilder() - .SetBoolean("kiosk_enabled", true) - .SetBoolean("kiosk_only", true) - .Build()) + .SetManifestKey("kiosk_enabled", true) + .SetManifestKey("kiosk_only", true) .Build()); user_manager::User* const manual_kiosk_app_user = user_manager_->AddKioskAppUser( diff --git a/chromium/chrome/browser/extensions/api/file_system/file_system_apitest.cc b/chromium/chrome/browser/extensions/api/file_system/file_system_apitest.cc index 50a2b82e4eb..fe2b33bac09 100644 --- a/chromium/chrome/browser/extensions/api/file_system/file_system_apitest.cc +++ b/chromium/chrome/browser/extensions/api/file_system/file_system_apitest.cc @@ -163,7 +163,7 @@ IN_PROC_BROWSER_TEST_F(FileSystemApiTest, FileSystemApiGetDisplayPath) { IN_PROC_BROWSER_TEST_F(FileSystemApiTest, FileSystemApiGetDisplayPathPrettify) { { base::ScopedAllowBlockingForTesting allow_blocking; - ASSERT_TRUE(PathService::OverrideAndCreateIfNeeded( + ASSERT_TRUE(base::PathService::OverrideAndCreateIfNeeded( base::DIR_HOME, test_root_folder_, false, false)); } @@ -230,7 +230,7 @@ IN_PROC_BROWSER_TEST_F(FileSystemApiTest, ASSERT_FALSE(test_file.empty()); { base::ScopedAllowBlockingForTesting allow_blocking; - ASSERT_TRUE(PathService::OverrideAndCreateIfNeeded( + ASSERT_TRUE(base::PathService::OverrideAndCreateIfNeeded( chrome::DIR_USER_DOCUMENTS, test_file.DirName(), false, false)); } FileSystemChooseEntryFunction:: @@ -254,7 +254,7 @@ IN_PROC_BROWSER_TEST_F(FileSystemApiTest, ASSERT_FALSE(test_file.empty()); { base::ScopedAllowBlockingForTesting allow_blocking; - ASSERT_TRUE(PathService::OverrideAndCreateIfNeeded( + ASSERT_TRUE(base::PathService::OverrideAndCreateIfNeeded( chrome::DIR_USER_DOCUMENTS, test_file.DirName(), false, false)); } FileSystemChooseEntryFunction:: @@ -269,7 +269,7 @@ IN_PROC_BROWSER_TEST_F(FileSystemApiTest, FileSystemApiOpenMultipleSuggested) { ASSERT_FALSE(test_file.empty()); { base::ScopedAllowBlockingForTesting allow_blocking; - ASSERT_TRUE(PathService::OverrideAndCreateIfNeeded( + ASSERT_TRUE(base::PathService::OverrideAndCreateIfNeeded( chrome::DIR_USER_DOCUMENTS, test_file.DirName(), false, false)); } FileSystemChooseEntryFunction::SkipPickerAndSelectSuggestedPathForTest(); @@ -351,7 +351,7 @@ IN_PROC_BROWSER_TEST_F(FileSystemApiTest, base::FilePath test_directory = test_file.DirName(); { base::ScopedAllowBlockingForTesting allow_blocking; - ASSERT_TRUE(PathService::OverrideAndCreateIfNeeded( + ASSERT_TRUE(base::PathService::OverrideAndCreateIfNeeded( kGraylistedPath, test_directory, false, false)); } FileSystemChooseEntryFunction::SkipPickerAndAlwaysSelectPathForTest( @@ -369,7 +369,7 @@ IN_PROC_BROWSER_TEST_F(FileSystemApiTest, base::FilePath test_directory = test_file.DirName(); { base::ScopedAllowBlockingForTesting allow_blocking; - ASSERT_TRUE(PathService::OverrideAndCreateIfNeeded( + ASSERT_TRUE(base::PathService::OverrideAndCreateIfNeeded( kGraylistedPath, test_directory, false, false)); } FileSystemChooseEntryFunction::SkipPickerAndAlwaysSelectPathForTest( @@ -388,7 +388,7 @@ IN_PROC_BROWSER_TEST_F(FileSystemApiTest, base::FilePath parent_directory = test_directory.DirName(); { base::ScopedAllowBlockingForTesting allow_blocking; - ASSERT_TRUE(PathService::OverrideAndCreateIfNeeded( + ASSERT_TRUE(base::PathService::OverrideAndCreateIfNeeded( kGraylistedPath, test_directory, false, false)); } FileSystemChooseEntryFunction::SkipPickerAndAlwaysSelectPathForTest( @@ -410,7 +410,7 @@ IN_PROC_BROWSER_TEST_F(FileSystemApiTest, base::FilePath parent_directory = test_directory.DirName(); { base::ScopedAllowBlockingForTesting allow_blocking; - ASSERT_TRUE(PathService::OverrideAndCreateIfNeeded( + ASSERT_TRUE(base::PathService::OverrideAndCreateIfNeeded( kGraylistedPath, parent_directory, false, false)); } FileSystemChooseEntryFunction::SkipPickerAndAlwaysSelectPathForTest( diff --git a/chromium/chrome/browser/extensions/api/file_system/file_system_apitest_chromeos.cc b/chromium/chrome/browser/extensions/api/file_system/file_system_apitest_chromeos.cc index 9fa91d2ba67..183e3cad0cf 100644 --- a/chromium/chrome/browser/extensions/api/file_system/file_system_apitest_chromeos.cc +++ b/chromium/chrome/browser/extensions/api/file_system/file_system_apitest_chromeos.cc @@ -299,7 +299,7 @@ IN_PROC_BROWSER_TEST_F(FileSystemApiTestForDrive, FileSystemApiOpenMultipleSuggested) { base::FilePath test_file = drive::util::GetDriveMountPointPath( browser()->profile()).AppendASCII("root/open_existing.txt"); - ASSERT_TRUE(PathService::OverrideAndCreateIfNeeded( + ASSERT_TRUE(base::PathService::OverrideAndCreateIfNeeded( chrome::DIR_USER_DOCUMENTS, test_file.DirName(), true, false)); FileSystemChooseEntryFunction::SkipPickerAndSelectSuggestedPathForTest(); ASSERT_TRUE(RunPlatformAppTest( diff --git a/chromium/chrome/browser/extensions/api/font_settings/font_settings_apitest.cc b/chromium/chrome/browser/extensions/api/font_settings/font_settings_apitest.cc index 6e0fc6ff4db..603f84f1610 100644 --- a/chromium/chrome/browser/extensions/api/font_settings/font_settings_apitest.cc +++ b/chromium/chrome/browser/extensions/api/font_settings/font_settings_apitest.cc @@ -11,6 +11,8 @@ #include "chrome/common/pref_names.h" #include "components/prefs/pref_service.h" +namespace extensions { + // Test of extension API on a standard profile. IN_PROC_BROWSER_TEST_F(ExtensionApiTest, FontSettings) { PrefService* prefs = browser()->profile()->GetPrefs(); @@ -36,3 +38,5 @@ IN_PROC_BROWSER_TEST_F(ExtensionApiTest, FontSettingsIncognito) { "launch.html", flags)); } + +} // namespace extensions diff --git a/chromium/chrome/browser/extensions/api/history/history_api.cc b/chromium/chrome/browser/extensions/api/history/history_api.cc index c83fcd8c060..9e23c409306 100644 --- a/chromium/chrome/browser/extensions/api/history/history_api.cc +++ b/chromium/chrome/browser/extensions/api/history/history_api.cc @@ -149,16 +149,14 @@ void HistoryEventRouter::OnURLVisited(history::HistoryService* history_service, api::history::OnVisited::kEventName, std::move(args)); } -void HistoryEventRouter::OnURLsDeleted(history::HistoryService* history_service, - bool all_history, - bool expired, - const history::URLRows& deleted_rows, - const std::set<GURL>& favicon_urls) { +void HistoryEventRouter::OnURLsDeleted( + history::HistoryService* history_service, + const history::DeletionInfo& deletion_info) { OnVisitRemoved::Removed removed; - removed.all_history = all_history; + removed.all_history = deletion_info.IsAllHistory(); std::vector<std::string>* urls = new std::vector<std::string>(); - for (const auto& row : deleted_rows) + for (const auto& row : deletion_info.deleted_rows()) urls->push_back(row.url().spec()); removed.urls.reset(urls); diff --git a/chromium/chrome/browser/extensions/api/history/history_api.h b/chromium/chrome/browser/extensions/api/history/history_api.h index f6b74f78d01..36d12ac0841 100644 --- a/chromium/chrome/browser/extensions/api/history/history_api.h +++ b/chromium/chrome/browser/extensions/api/history/history_api.h @@ -46,10 +46,7 @@ class HistoryEventRouter : public history::HistoryServiceObserver { const history::RedirectList& redirects, base::Time visit_time) override; void OnURLsDeleted(history::HistoryService* history_service, - bool all_history, - bool expired, - const history::URLRows& deleted_rows, - const std::set<GURL>& favicon_urls) override; + const history::DeletionInfo& deletion_info) override; void DispatchEvent(Profile* profile, events::HistogramValue histogram_value, diff --git a/chromium/chrome/browser/extensions/api/i18n/i18n_apitest.cc b/chromium/chrome/browser/extensions/api/i18n/i18n_apitest.cc index 6eda3618fc2..b8d0b5b9e15 100644 --- a/chromium/chrome/browser/extensions/api/i18n/i18n_apitest.cc +++ b/chromium/chrome/browser/extensions/api/i18n/i18n_apitest.cc @@ -14,6 +14,8 @@ #include "extensions/test/result_catcher.h" #include "net/test/embedded_test_server/embedded_test_server.h" +namespace extensions { + IN_PROC_BROWSER_TEST_F(ExtensionApiTest, I18N) { ASSERT_TRUE(StartEmbeddedTestServer()); ASSERT_TRUE(RunExtensionTest("i18n")) << message_; @@ -35,10 +37,9 @@ IN_PROC_BROWSER_TEST_F(ExtensionApiTest, I18NUpdate) { test_data_dir_.AppendASCII("i18nUpdate").AppendASCII("_locales"), extension_dir.GetPath().AppendASCII("_locales"), true); - const extensions::Extension* extension = - LoadExtension(extension_dir.GetPath()); + const Extension* extension = LoadExtension(extension_dir.GetPath()); - extensions::ResultCatcher catcher; + ResultCatcher catcher; // Test that the messages.json file is loaded and the i18n message is loaded. ui_test_utils::NavigateToURL( @@ -65,3 +66,5 @@ IN_PROC_BROWSER_TEST_F(ExtensionApiTest, I18NUpdate) { ui_test_utils::GetCurrentTabTitle(browser(), &title); EXPECT_EQ(std::string("SECONDMESSAGE"), base::UTF16ToUTF8(title)); } + +} // namespace extensions diff --git a/chromium/chrome/browser/extensions/api/identity/gaia_web_auth_flow_unittest.cc b/chromium/chrome/browser/extensions/api/identity/gaia_web_auth_flow_unittest.cc index 57d3f43b709..79752bcfe86 100644 --- a/chromium/chrome/browser/extensions/api/identity/gaia_web_auth_flow_unittest.cc +++ b/chromium/chrome/browser/extensions/api/identity/gaia_web_auth_flow_unittest.cc @@ -64,7 +64,7 @@ class IdentityGaiaWebAuthFlowTest : public testing::Test { IdentityGaiaWebAuthFlowTest() : ubertoken_error_state_(GoogleServiceAuthError::NONE) {} - virtual void TearDown() { + void TearDown() override { testing::Test::TearDown(); base::RunLoop loop; loop.RunUntilIdle(); // Run tasks so FakeWebAuthFlows get deleted. diff --git a/chromium/chrome/browser/extensions/api/identity/identity_apitest.cc b/chromium/chrome/browser/extensions/api/identity/identity_apitest.cc index 2a6261ec2fe..3091e73d086 100644 --- a/chromium/chrome/browser/extensions/api/identity/identity_apitest.cc +++ b/chromium/chrome/browser/extensions/api/identity/identity_apitest.cc @@ -14,16 +14,7 @@ #include "base/strings/string_util.h" #include "base/values.h" #include "build/build_config.h" -#include "chrome/browser/browser_process.h" #include "chrome/browser/chrome_notification_types.h" -#include "components/prefs/pref_service.h" -#if defined(OS_CHROMEOS) -#include "chrome/browser/chromeos/login/users/mock_user_manager.h" -#include "chrome/browser/chromeos/policy/browser_policy_connector_chromeos.h" -#include "chrome/browser/chromeos/settings/stub_install_attributes.h" -#include "components/user_manager/scoped_user_manager.h" -#include "extensions/common/extension_builder.h" -#endif #include "chrome/browser/extensions/api/identity/identity_api.h" #include "chrome/browser/extensions/api/identity/identity_constants.h" #include "chrome/browser/extensions/api/identity/identity_get_accounts_function.h" @@ -43,6 +34,7 @@ #include "chrome/browser/signin/fake_profile_oauth2_token_service_builder.h" #include "chrome/browser/signin/fake_signin_manager_builder.h" #include "chrome/browser/signin/gaia_cookie_manager_service_factory.h" +#include "chrome/browser/signin/identity_manager_factory.h" #include "chrome/browser/signin/profile_oauth2_token_service_factory.h" #include "chrome/browser/signin/signin_manager_factory.h" #include "chrome/browser/ui/browser.h" @@ -52,6 +44,7 @@ #include "chrome/test/base/in_process_browser_test.h" #include "components/crx_file/id_util.h" #include "components/guest_view/browser/guest_view_base.h" +#include "components/prefs/pref_service.h" #include "components/signin/core/browser/account_fetcher_service.h" #include "components/signin/core/browser/account_tracker_service.h" #include "components/signin/core/browser/fake_gaia_cookie_manager_service.h" @@ -70,14 +63,22 @@ #include "google_apis/gaia/oauth2_mint_token_flow.h" #include "google_apis/gaia/oauth2_token_service.h" #include "net/test/embedded_test_server/embedded_test_server.h" +#include "services/identity/public/cpp/identity_manager.h" +#include "services/identity/public/cpp/identity_test_utils.h" #include "testing/gmock/include/gmock/gmock.h" #include "testing/gtest/include/gtest/gtest.h" #include "url/gurl.h" +#if defined(OS_CHROMEOS) +#include "chrome/browser/chromeos/login/users/mock_user_manager.h" +#include "chrome/browser/chromeos/policy/browser_policy_connector_chromeos.h" +#include "chrome/browser/chromeos/settings/stub_install_attributes.h" +#include "components/user_manager/scoped_user_manager.h" +#endif + using guest_view::GuestViewBase; using testing::_; using testing::Return; -using testing::ReturnRef; namespace extensions { @@ -483,37 +484,26 @@ class IdentityTestWithSignin : public AsyncExtensionBrowserTest { } protected: - void SignIn(const std::string& account_key) { - SignIn(account_key, account_key); - } - // Returns the account ID of the created account. - std::string SignIn(const std::string& email, const std::string& gaia) { - AccountTrackerService* account_tracker = - AccountTrackerServiceFactory::GetForProfile(profile()); - std::string account_id = account_tracker->SeedAccountInfo(gaia, email); - -#if defined(OS_CHROMEOS) - signin_manager_->SetAuthenticatedAccountInfo(gaia, email); -#else - signin_manager_->SignIn(gaia, email, "password"); -#endif - token_service_->UpdateCredentials(account_id, "refresh_token"); - - return account_id; + std::string SignIn(const std::string& email) { + identity::IdentityManager* identity_manager = + IdentityManagerFactory::GetForProfile(profile()); + identity::MakePrimaryAccountAvailable(signin_manager_, token_service_, + identity_manager, email); + return identity_manager->GetPrimaryAccountInfo().account_id; } - void AddAccount(const std::string& email, const std::string& gaia) { - AccountTrackerService* account_tracker = - AccountTrackerServiceFactory::GetForProfile(profile()); - std::string account_id = account_tracker->SeedAccountInfo(gaia, email); + std::string AddAccount(const std::string& email) { + std::string account_id = SeedAccountInfo(email); token_service_->UpdateCredentials(account_id, "refresh_token"); + return account_id; } - void SeedAccountInfo(const std::string& account_key) { + std::string SeedAccountInfo(const std::string& email) { + std::string gaia = "gaia_id_for_" + email; AccountTrackerService* account_tracker = AccountTrackerServiceFactory::GetForProfile(profile()); - account_tracker->SeedAccountInfo(account_key, account_key); + return account_tracker->SeedAccountInfo(gaia, email); } FakeSigninManagerForTesting* signin_manager_; @@ -532,59 +522,53 @@ class IdentityGetAccountsFunctionTest : public IdentityTestWithSignin { protected: testing::AssertionResult ExpectGetAccounts( - const std::vector<std::string>& accounts) { + const std::vector<std::string>& gaia_ids) { scoped_refptr<IdentityGetAccountsFunction> func( new IdentityGetAccountsFunction); func->set_extension( ExtensionBuilder("Test").SetID(kExtensionId).Build().get()); if (!utils::RunFunction(func.get(), std::string("[]"), browser(), api_test_utils::NONE)) { - return GenerateFailureResult(accounts, NULL) + return GenerateFailureResult(gaia_ids, NULL) << "getAccounts did not return a result."; } const base::ListValue* callback_arguments = func->GetResultList(); if (!callback_arguments) - return GenerateFailureResult(accounts, NULL) << "NULL result"; + return GenerateFailureResult(gaia_ids, NULL) << "NULL result"; if (callback_arguments->GetSize() != 1) { - return GenerateFailureResult(accounts, NULL) + return GenerateFailureResult(gaia_ids, NULL) << "Expected 1 argument but got " << callback_arguments->GetSize(); } const base::ListValue* results; if (!callback_arguments->GetList(0, &results)) - GenerateFailureResult(accounts, NULL) << "Result was not an array"; + GenerateFailureResult(gaia_ids, NULL) << "Result was not an array"; std::set<std::string> result_ids; - for (base::ListValue::const_iterator it = results->begin(); - it != results->end(); - ++it) { + for (const base::Value& item : *results) { std::unique_ptr<api::identity::AccountInfo> info = - api::identity::AccountInfo::FromValue(*it); + api::identity::AccountInfo::FromValue(item); if (info.get()) result_ids.insert(info->id); else - return GenerateFailureResult(accounts, results); + return GenerateFailureResult(gaia_ids, results); } - for (std::vector<std::string>::const_iterator it = accounts.begin(); - it != accounts.end(); - ++it) { - if (result_ids.find(*it) == result_ids.end()) - return GenerateFailureResult(accounts, results); + for (const std::string& gaia_id : gaia_ids) { + if (result_ids.find(gaia_id) == result_ids.end()) + return GenerateFailureResult(gaia_ids, results); } return testing::AssertionResult(true); } testing::AssertionResult GenerateFailureResult( - const ::std::vector<std::string>& accounts, + const ::std::vector<std::string>& gaia_ids, const base::ListValue* results) { testing::Message msg("Expected: "); - for (std::vector<std::string>::const_iterator it = accounts.begin(); - it != accounts.end(); - ++it) { - msg << *it << " "; + for (const std::string& gaia_id : gaia_ids) { + msg << gaia_id << " "; } msg << "Actual: "; if (!results) { @@ -609,36 +593,32 @@ IN_PROC_BROWSER_TEST_F(IdentityGetAccountsFunctionTest, MultiAccountOn) { } IN_PROC_BROWSER_TEST_F(IdentityGetAccountsFunctionTest, NoneSignedIn) { - EXPECT_TRUE(ExpectGetAccounts(std::vector<std::string>())); + EXPECT_TRUE(ExpectGetAccounts({})); } IN_PROC_BROWSER_TEST_F(IdentityGetAccountsFunctionTest, NoPrimaryAccount) { - AddAccount("secondary@example.com", "2"); - EXPECT_TRUE(ExpectGetAccounts(std::vector<std::string>())); + AddAccount("secondary@example.com"); + EXPECT_TRUE(ExpectGetAccounts({})); } IN_PROC_BROWSER_TEST_F(IdentityGetAccountsFunctionTest, PrimaryAccountHasNoRefreshToken) { - std::string primary_account_id = SignIn("primary@example.com", "1"); + std::string primary_account_id = SignIn("primary@example.com"); token_service_->RevokeCredentials(primary_account_id); - EXPECT_TRUE(ExpectGetAccounts(std::vector<std::string>())); + EXPECT_TRUE(ExpectGetAccounts({})); } IN_PROC_BROWSER_TEST_F(IdentityGetAccountsFunctionTest, PrimaryAccountSignedIn) { - SignIn("primary@example.com", "1"); - std::vector<std::string> primary; - primary.push_back("1"); - EXPECT_TRUE(ExpectGetAccounts(primary)); + SignIn("primary@example.com"); + EXPECT_TRUE(ExpectGetAccounts({"gaia_id_for_primary@example.com"})); } IN_PROC_BROWSER_TEST_F(IdentityGetAccountsFunctionTest, TwoAccountsSignedIn) { - SignIn("primary@example.com", "1"); - AddAccount("secondary@example.com", "2"); - std::vector<std::string> two_accounts; - two_accounts.push_back("1"); - two_accounts.push_back("2"); - EXPECT_TRUE(ExpectGetAccounts(two_accounts)); + SignIn("primary@example.com"); + AddAccount("secondary@example.com"); + EXPECT_TRUE(ExpectGetAccounts({"gaia_id_for_primary@example.com", + "gaia_id_for_secondary@example.com"})); } class IdentityOldProfilesGetAccountsFunctionTest @@ -656,11 +636,9 @@ IN_PROC_BROWSER_TEST_F(IdentityOldProfilesGetAccountsFunctionTest, IN_PROC_BROWSER_TEST_F(IdentityOldProfilesGetAccountsFunctionTest, TwoAccountsSignedIn) { - SignIn("primary@example.com", "1"); - AddAccount("secondary@example.com", "2"); - std::vector<std::string> only_primary; - only_primary.push_back("1"); - EXPECT_TRUE(ExpectGetAccounts(only_primary)); + SignIn("primary@example.com"); + AddAccount("secondary@example.com"); + EXPECT_TRUE(ExpectGetAccounts({"gaia_id_for_primary@example.com"})); } class IdentityGetProfileUserInfoFunctionTest : public IdentityTestWithSignin { @@ -687,11 +665,7 @@ class IdentityGetProfileUserInfoFunctionTest : public IdentityTestWithSignin { private: scoped_refptr<Extension> CreateExtensionWithEmailPermission() { - std::unique_ptr<base::DictionaryValue> test_extension_value( - api_test_utils::ParseDictionary( - "{\"name\": \"Test\", \"version\": \"1.0\", " - "\"permissions\": [\"identity.email\"]}")); - return api_test_utils::CreateExtension(test_extension_value.get()); + return ExtensionBuilder("Test").AddPermission("identity.email").Build(); } }; @@ -703,11 +677,11 @@ IN_PROC_BROWSER_TEST_F(IdentityGetProfileUserInfoFunctionTest, NotSignedIn) { } IN_PROC_BROWSER_TEST_F(IdentityGetProfileUserInfoFunctionTest, SignedIn) { - SignIn("president@example.com", "12345"); + SignIn("president@example.com"); std::unique_ptr<api::identity::ProfileUserInfo> info = RunGetProfileUserInfoWithEmail(); EXPECT_EQ("president@example.com", info->email); - EXPECT_EQ("12345", info->id); + EXPECT_EQ("gaia_id_for_president@example.com", info->id); } IN_PROC_BROWSER_TEST_F(IdentityGetProfileUserInfoFunctionTest, @@ -720,7 +694,7 @@ IN_PROC_BROWSER_TEST_F(IdentityGetProfileUserInfoFunctionTest, IN_PROC_BROWSER_TEST_F(IdentityGetProfileUserInfoFunctionTest, SignedInNoEmail) { - SignIn("president@example.com", "12345"); + SignIn("president@example.com"); std::unique_ptr<api::identity::ProfileUserInfo> info = RunGetProfileUserInfo(); EXPECT_TRUE(info->email.empty()); @@ -736,11 +710,12 @@ class GetAuthTokenFunctionTest command_line->AppendSwitch(switches::kExtensionsMultiAccount); } - void IssueLoginAccessTokenForAccount(const std::string& account_key) { + std::string IssueLoginAccessTokenForAccount(const std::string& account_id) { + std::string access_token = "access_token-" + account_id; token_service_->IssueAllTokensForAccount( - account_key, - "access_token-" + account_key, + account_id, access_token, base::Time::Now() + base::TimeDelta::FromSeconds(3600)); + return access_token; } protected: @@ -1675,7 +1650,7 @@ IN_PROC_BROWSER_TEST_F(GetAuthTokenFunctionTest, } IN_PROC_BROWSER_TEST_F(GetAuthTokenFunctionTest, ManuallyIssueToken) { - SignIn("primary@example.com"); + std::string primary_account_id = SignIn("primary@example.com"); scoped_refptr<FakeGetAuthTokenFunction> func(new FakeGetAuthTokenFunction()); scoped_refptr<const Extension> extension(CreateExtension(CLIENT_ID | SCOPES)); @@ -1690,7 +1665,8 @@ IN_PROC_BROWSER_TEST_F(GetAuthTokenFunctionTest, ManuallyIssueToken) { RunFunctionAsync(func.get(), "[{}]"); run_loop.Run(); - IssueLoginAccessTokenForAccount("primary@example.com"); + std::string primary_account_access_token = + IssueLoginAccessTokenForAccount(primary_account_id); std::unique_ptr<base::Value> value(WaitForSingleResult(func.get())); std::string access_token; @@ -1698,11 +1674,11 @@ IN_PROC_BROWSER_TEST_F(GetAuthTokenFunctionTest, ManuallyIssueToken) { EXPECT_EQ(std::string(kAccessToken), access_token); EXPECT_EQ(IdentityTokenCacheValue::CACHE_STATUS_TOKEN, GetCachedToken(std::string()).status()); - EXPECT_EQ("access_token-primary@example.com", func->login_access_token()); + EXPECT_EQ(primary_account_access_token, func->login_access_token()); } IN_PROC_BROWSER_TEST_F(GetAuthTokenFunctionTest, ManuallyIssueTokenFailure) { - SignIn("primary@example.com"); + std::string primary_account_id = SignIn("primary@example.com"); scoped_refptr<FakeGetAuthTokenFunction> func(new FakeGetAuthTokenFunction()); scoped_refptr<const Extension> extension(CreateExtension(CLIENT_ID | SCOPES)); @@ -1718,7 +1694,7 @@ IN_PROC_BROWSER_TEST_F(GetAuthTokenFunctionTest, ManuallyIssueTokenFailure) { run_loop.Run(); token_service_->IssueErrorForAllPendingRequestsForAccount( - "primary@example.com", + primary_account_id, GoogleServiceAuthError(GoogleServiceAuthError::SERVICE_UNAVAILABLE)); EXPECT_EQ( @@ -1730,7 +1706,7 @@ IN_PROC_BROWSER_TEST_F(GetAuthTokenFunctionTest, ManuallyIssueTokenFailure) { IN_PROC_BROWSER_TEST_F(GetAuthTokenFunctionTest, MultiDefaultUserManuallyIssueToken) { - SignIn("primary@example.com"); + std::string primary_account_id = SignIn("primary@example.com"); SeedAccountInfo("secondary@example.com"); scoped_refptr<FakeGetAuthTokenFunction> func(new FakeGetAuthTokenFunction()); @@ -1744,7 +1720,8 @@ IN_PROC_BROWSER_TEST_F(GetAuthTokenFunctionTest, RunFunctionAsync(func.get(), "[{}]"); run_loop.Run(); - IssueLoginAccessTokenForAccount("primary@example.com"); + std::string primary_account_access_token = + IssueLoginAccessTokenForAccount(primary_account_id); std::unique_ptr<base::Value> value(WaitForSingleResult(func.get())); std::string access_token; @@ -1752,13 +1729,13 @@ IN_PROC_BROWSER_TEST_F(GetAuthTokenFunctionTest, EXPECT_EQ(std::string(kAccessToken), access_token); EXPECT_EQ(IdentityTokenCacheValue::CACHE_STATUS_TOKEN, GetCachedToken(std::string()).status()); - EXPECT_EQ("access_token-primary@example.com", func->login_access_token()); + EXPECT_EQ(primary_account_access_token, func->login_access_token()); } IN_PROC_BROWSER_TEST_F(GetAuthTokenFunctionTest, MultiPrimaryUserManuallyIssueToken) { - SignIn("primary@example.com"); - AddAccount("secondary@example.com", "secondary@example.com"); + std::string primary_account_id = SignIn("primary@example.com"); + AddAccount("secondary@example.com"); scoped_refptr<FakeGetAuthTokenFunction> func(new FakeGetAuthTokenFunction()); scoped_refptr<const Extension> extension(CreateExtension(CLIENT_ID | SCOPES)); @@ -1768,11 +1745,13 @@ IN_PROC_BROWSER_TEST_F(GetAuthTokenFunctionTest, base::RunLoop run_loop; on_access_token_requested_ = run_loop.QuitClosure(); - RunFunctionAsync(func.get(), - "[{\"account\": { \"id\": \"primary@example.com\" } }]"); + RunFunctionAsync( + func.get(), + "[{\"account\": { \"id\": \"gaia_id_for_primary@example.com\" } }]"); run_loop.Run(); - IssueLoginAccessTokenForAccount("primary@example.com"); + std::string primary_account_access_token = + IssueLoginAccessTokenForAccount(primary_account_id); std::unique_ptr<base::Value> value(WaitForSingleResult(func.get())); std::string access_token; @@ -1780,13 +1759,13 @@ IN_PROC_BROWSER_TEST_F(GetAuthTokenFunctionTest, EXPECT_EQ(std::string(kAccessToken), access_token); EXPECT_EQ(IdentityTokenCacheValue::CACHE_STATUS_TOKEN, GetCachedToken(std::string()).status()); - EXPECT_EQ("access_token-primary@example.com", func->login_access_token()); + EXPECT_EQ(primary_account_access_token, func->login_access_token()); } IN_PROC_BROWSER_TEST_F(GetAuthTokenFunctionTest, MultiSecondaryUserManuallyIssueToken) { - SignIn("primary@example.com"); - AddAccount("secondary@example.com", "secondary@example.com"); + std::string primary_account_id = SignIn("primary@example.com"); + std::string secondary_account_id = AddAccount("secondary@example.com"); scoped_refptr<FakeGetAuthTokenFunction> func(new FakeGetAuthTokenFunction()); scoped_refptr<const Extension> extension(CreateExtension(CLIENT_ID | SCOPES)); @@ -1796,25 +1775,27 @@ IN_PROC_BROWSER_TEST_F(GetAuthTokenFunctionTest, base::RunLoop run_loop; on_access_token_requested_ = run_loop.QuitClosure(); - RunFunctionAsync(func.get(), - "[{\"account\": { \"id\": \"secondary@example.com\" } }]"); + RunFunctionAsync( + func.get(), + "[{\"account\": { \"id\": \"gaia_id_for_secondary@example.com\" } }]"); run_loop.Run(); - IssueLoginAccessTokenForAccount("secondary@example.com"); + std::string secondary_account_access_token = + IssueLoginAccessTokenForAccount(secondary_account_id); std::unique_ptr<base::Value> value(WaitForSingleResult(func.get())); std::string access_token; EXPECT_TRUE(value->GetAsString(&access_token)); EXPECT_EQ(std::string(kAccessToken), access_token); EXPECT_EQ(IdentityTokenCacheValue::CACHE_STATUS_TOKEN, - GetCachedToken("secondary@example.com").status()); - EXPECT_EQ("access_token-secondary@example.com", func->login_access_token()); + GetCachedToken(secondary_account_id).status()); + EXPECT_EQ(secondary_account_access_token, func->login_access_token()); } IN_PROC_BROWSER_TEST_F(GetAuthTokenFunctionTest, MultiUnknownUserGetTokenFromTokenServiceFailure) { SignIn("primary@example.com"); - AddAccount("secondary@example.com", "secondary@example.com"); + AddAccount("secondary@example.com"); scoped_refptr<FakeGetAuthTokenFunction> func(new FakeGetAuthTokenFunction()); scoped_refptr<const Extension> extension(CreateExtension(CLIENT_ID | SCOPES)); @@ -1830,13 +1811,14 @@ IN_PROC_BROWSER_TEST_F(GetAuthTokenFunctionTest, IN_PROC_BROWSER_TEST_F(GetAuthTokenFunctionTest, MultiSecondaryNonInteractiveMintFailure) { SignIn("primary@example.com"); - AddAccount("secondary@example.com", "secondary@example.com"); + AddAccount("secondary@example.com"); scoped_refptr<FakeGetAuthTokenFunction> func(new FakeGetAuthTokenFunction()); func->set_extension(CreateExtension(CLIENT_ID | SCOPES)); func->set_mint_token_result(TestOAuth2MintTokenFlow::MINT_TOKEN_FAILURE); std::string error = utils::RunFunctionAndReturnError( - func.get(), "[{\"account\": { \"id\": \"secondary@example.com\" } }]", + func.get(), + "[{\"account\": { \"id\": \"gaia_id_for_secondary@example.com\" } }]", browser()); EXPECT_TRUE(base::StartsWith(error, errors::kAuthFailure, base::CompareCase::INSENSITIVE_ASCII)); @@ -1847,13 +1829,14 @@ IN_PROC_BROWSER_TEST_F(GetAuthTokenFunctionTest, IN_PROC_BROWSER_TEST_F(GetAuthTokenFunctionTest, MultiSecondaryNonInteractiveLoginAccessTokenFailure) { SignIn("primary@example.com"); - AddAccount("secondary@example.com", "secondary@example.com"); + AddAccount("secondary@example.com"); scoped_refptr<FakeGetAuthTokenFunction> func(new FakeGetAuthTokenFunction()); func->set_extension(CreateExtension(CLIENT_ID | SCOPES)); func->set_login_access_token_result(false); std::string error = utils::RunFunctionAndReturnError( - func.get(), "[{\"account\": { \"id\": \"secondary@example.com\" } }]", + func.get(), + "[{\"account\": { \"id\": \"gaia_id_for_secondary@example.com\" } }]", browser()); EXPECT_TRUE(base::StartsWith(error, errors::kAuthFailure, base::CompareCase::INSENSITIVE_ASCII)); @@ -1862,7 +1845,7 @@ IN_PROC_BROWSER_TEST_F(GetAuthTokenFunctionTest, IN_PROC_BROWSER_TEST_F(GetAuthTokenFunctionTest, MultiSecondaryInteractiveApprovalAborted) { SignIn("primary@example.com"); - AddAccount("secondary@example.com", "secondary@example.com"); + AddAccount("secondary@example.com"); scoped_refptr<FakeGetAuthTokenFunction> func(new FakeGetAuthTokenFunction()); func->set_extension(CreateExtension(CLIENT_ID | SCOPES)); @@ -1870,7 +1853,8 @@ IN_PROC_BROWSER_TEST_F(GetAuthTokenFunctionTest, func->set_scope_ui_failure(GaiaWebAuthFlow::WINDOW_CLOSED); std::string error = utils::RunFunctionAndReturnError( func.get(), - "[{\"account\": { \"id\": \"secondary@example.com\" }, \"interactive\": " + "[{\"account\": { \"id\": \"gaia_id_for_secondary@example.com\" }, " + "\"interactive\": " "true}]", browser()); EXPECT_EQ(std::string(errors::kUserRejected), error); @@ -1970,18 +1954,12 @@ class GetAuthTokenFunctionPublicSessionTest : public GetAuthTokenFunctionTest { } scoped_refptr<Extension> CreateTestExtension(const std::string& id) { - return ExtensionBuilder() - .SetManifest( - DictionaryBuilder() - .Set("name", "Test") - .Set("version", "1.0") - .Set("oauth2", - DictionaryBuilder() - .Set("client_id", "clientId") - .Set("scopes", ListBuilder().Append("scope1").Build()) - .Build()) - .Build()) - .SetLocation(Manifest::UNPACKED) + return ExtensionBuilder("Test") + .SetManifestKey( + "oauth2", DictionaryBuilder() + .Set("client_id", "clientId") + .Set("scopes", ListBuilder().Append("scope1").Build()) + .Build()) .SetID(id) .Build(); } @@ -2302,11 +2280,11 @@ class OnSignInChangedEventTest : public IdentityTestWithSignin { // Test that an event is fired when the primary account signs in. IN_PROC_BROWSER_TEST_F(OnSignInChangedEventTest, FireOnPrimaryAccountSignIn) { api::identity::AccountInfo account_info; - account_info.id = "primary"; + account_info.id = "gaia_id_for_primary@example.com"; AddExpectedEvent(api::identity::OnSignInChanged::Create(account_info, true)); // Sign in and verify that the callback fires. - SignIn("primary", "primary"); + SignIn("primary@example.com"); EXPECT_FALSE(HasExpectedEvent()); } @@ -2315,10 +2293,10 @@ IN_PROC_BROWSER_TEST_F(OnSignInChangedEventTest, FireOnPrimaryAccountSignIn) { // Test that an event is fired when the primary account signs out. IN_PROC_BROWSER_TEST_F(OnSignInChangedEventTest, FireOnPrimaryAccountSignOut) { api::identity::AccountInfo account_info; - account_info.id = "primary"; + account_info.id = "gaia_id_for_primary@example.com"; AddExpectedEvent(api::identity::OnSignInChanged::Create(account_info, true)); - SignIn("primary", "primary"); + SignIn("primary@example.com"); AddExpectedEvent(api::identity::OnSignInChanged::Create(account_info, false)); @@ -2334,15 +2312,15 @@ IN_PROC_BROWSER_TEST_F(OnSignInChangedEventTest, FireOnPrimaryAccountSignOut) { IN_PROC_BROWSER_TEST_F(OnSignInChangedEventTest, FireOnPrimaryAccountRefreshTokenRevoked) { api::identity::AccountInfo account_info; - account_info.id = "primary"; + account_info.id = "gaia_id_for_primary@example.com"; AddExpectedEvent(api::identity::OnSignInChanged::Create(account_info, true)); - SignIn("primary", "primary"); + std::string primary_account_id = SignIn("primary@example.com"); AddExpectedEvent(api::identity::OnSignInChanged::Create(account_info, false)); // Revoke the refresh token and verify that the callback fires. - token_service_->RevokeCredentials("primary"); + token_service_->RevokeCredentials(primary_account_id); EXPECT_FALSE(HasExpectedEvent()); } @@ -2352,51 +2330,51 @@ IN_PROC_BROWSER_TEST_F(OnSignInChangedEventTest, IN_PROC_BROWSER_TEST_F(OnSignInChangedEventTest, FireOnPrimaryAccountRefreshTokenAvailable) { api::identity::AccountInfo account_info; - account_info.id = "primary"; + account_info.id = "gaia_id_for_primary@example.com"; AddExpectedEvent(api::identity::OnSignInChanged::Create(account_info, true)); - SignIn("primary", "primary"); + std::string primary_account_id = SignIn("primary@example.com"); AddExpectedEvent(api::identity::OnSignInChanged::Create(account_info, false)); - token_service_->RevokeCredentials("primary"); + token_service_->RevokeCredentials(primary_account_id); - account_info.id = "primary"; + account_info.id = "gaia_id_for_primary@example.com"; AddExpectedEvent(api::identity::OnSignInChanged::Create(account_info, true)); // Make the primary account's refresh token available and check that the // callback fires. Note that we must call AddAccount() here as the account's // information must be present in the AccountTrackerService as well. - AddAccount("primary", "primary"); + AddAccount("primary@example.com"); EXPECT_FALSE(HasExpectedEvent()); } // Test that an event is fired for changes to a secondary account. IN_PROC_BROWSER_TEST_F(OnSignInChangedEventTest, FireForSecondaryAccount) { api::identity::AccountInfo account_info; - account_info.id = "primary"; + account_info.id = "gaia_id_for_primary@example.com"; AddExpectedEvent(api::identity::OnSignInChanged::Create(account_info, true)); - SignIn("primary", "primary"); + SignIn("primary@example.com"); - account_info.id = "secondary"; + account_info.id = "gaia_id_for_secondary@example.com"; AddExpectedEvent(api::identity::OnSignInChanged::Create(account_info, true)); // Make a secondary account's refresh token available and check that the // callback fires. Note that we must call AddAccount() here as the account's // information must be present in the AccountTrackerService as well. - AddAccount("secondary", "secondary"); + std::string secondary_account_id = AddAccount("secondary@example.com"); EXPECT_FALSE(HasExpectedEvent()); // Revoke the secondary account's refresh token and check that the callback // fires. AddExpectedEvent(api::identity::OnSignInChanged::Create(account_info, false)); - token_service_->RevokeCredentials("secondary"); + token_service_->RevokeCredentials(secondary_account_id); EXPECT_FALSE(HasExpectedEvent()); } -} // namespace extensions - // Tests the chrome.identity API implemented by custom JS bindings . IN_PROC_BROWSER_TEST_F(ExtensionApiTest, ChromeIdentityJsBindings) { ASSERT_TRUE(RunExtensionTest("identity/js_bindings")) << message_; } + +} // namespace extensions diff --git a/chromium/chrome/browser/extensions/api/idltest/idltest_apitest.cc b/chromium/chrome/browser/extensions/api/idltest/idltest_apitest.cc index a81cb23da8f..2329c872cb7 100644 --- a/chromium/chrome/browser/extensions/api/idltest/idltest_apitest.cc +++ b/chromium/chrome/browser/extensions/api/idltest/idltest_apitest.cc @@ -7,7 +7,7 @@ #include "extensions/common/features/feature_channel.h" #include "extensions/common/switches.h" -class ExtensionIdltestApiTest : public ExtensionApiTest { +class ExtensionIdltestApiTest : public extensions::ExtensionApiTest { public: // Set the channel to "trunk" since idltest is restricted to trunk. ExtensionIdltestApiTest() : trunk_(version_info::Channel::UNKNOWN) {} diff --git a/chromium/chrome/browser/extensions/api/image_writer_private/image_writer_private_apitest.cc b/chromium/chrome/browser/extensions/api/image_writer_private/image_writer_private_apitest.cc index ddcd1a3b317..ce0e8bbd6bc 100644 --- a/chromium/chrome/browser/extensions/api/image_writer_private/image_writer_private_apitest.cc +++ b/chromium/chrome/browser/extensions/api/image_writer_private/image_writer_private_apitest.cc @@ -2,7 +2,6 @@ // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. -#include "base/message_loop/message_loop.h" #include "build/build_config.h" #include "chrome/browser/extensions/api/image_writer_private/operation.h" #include "chrome/browser/extensions/api/image_writer_private/removable_storage_provider.h" diff --git a/chromium/chrome/browser/extensions/api/image_writer_private/operation_unittest.cc b/chromium/chrome/browser/extensions/api/image_writer_private/operation_unittest.cc index 3f0a8bceef5..2d3d0c32d99 100644 --- a/chromium/chrome/browser/extensions/api/image_writer_private/operation_unittest.cc +++ b/chromium/chrome/browser/extensions/api/image_writer_private/operation_unittest.cc @@ -6,7 +6,6 @@ #include "base/files/file_util.h" #include "base/files/scoped_temp_dir.h" -#include "base/message_loop/message_loop.h" #include "base/run_loop.h" #include "build/build_config.h" #include "chrome/browser/extensions/api/image_writer_private/error_messages.h" diff --git a/chromium/chrome/browser/extensions/api/image_writer_private/test_utils.h b/chromium/chrome/browser/extensions/api/image_writer_private/test_utils.h index 4e3ed443001..1031b57f7fa 100644 --- a/chromium/chrome/browser/extensions/api/image_writer_private/test_utils.h +++ b/chromium/chrome/browser/extensions/api/image_writer_private/test_utils.h @@ -11,7 +11,6 @@ #include "base/files/file_util.h" #include "base/files/scoped_temp_dir.h" -#include "base/message_loop/message_loop.h" #include "base/run_loop.h" #include "base/test/scoped_task_environment.h" #include "build/build_config.h" @@ -46,7 +45,7 @@ const char kTestFileSystemType[] = "vfat"; class MockOperationManager : public OperationManager { public: explicit MockOperationManager(content::BrowserContext* context); - virtual ~MockOperationManager(); + ~MockOperationManager() override; MOCK_METHOD3(OnProgress, void(const ExtensionId& extension_id, image_writer_api::Stage stage, diff --git a/chromium/chrome/browser/extensions/api/inline_install_private/inline_install_private_api.cc b/chromium/chrome/browser/extensions/api/inline_install_private/inline_install_private_api.cc index 870613d80e3..66322d86a48 100644 --- a/chromium/chrome/browser/extensions/api/inline_install_private/inline_install_private_api.cc +++ b/chromium/chrome/browser/extensions/api/inline_install_private/inline_install_private_api.cc @@ -14,6 +14,7 @@ #include "components/crx_file/id_util.h" #include "content/public/browser/browser_thread.h" #include "extensions/browser/extension_registry.h" +#include "extensions/browser/view_type_utils.h" namespace extensions { @@ -106,10 +107,11 @@ InlineInstallPrivateInstallFunction::Run() { return RespondNow(CreateResponse("Must be called with a user gesture", webstore_install::NOT_PERMITTED)); - content::WebContents* web_contents = GetAssociatedWebContents(); - if (!web_contents) + content::WebContents* web_contents = GetSenderWebContents(); + if (!web_contents || GetViewType(web_contents) != VIEW_TYPE_APP_WINDOW) { return RespondNow(CreateResponse("Must be called from a foreground page", webstore_install::NOT_PERMITTED)); + } ExtensionRegistry* registry = ExtensionRegistry::Get(browser_context()); if (registry->GetExtensionById(params->id, ExtensionRegistry::EVERYTHING)) diff --git a/chromium/chrome/browser/extensions/api/input_ime/input_ime_api.cc b/chromium/chrome/browser/extensions/api/input_ime/input_ime_api.cc index fdf6dab9bdd..34b2a987294 100644 --- a/chromium/chrome/browser/extensions/api/input_ime/input_ime_api.cc +++ b/chromium/chrome/browser/extensions/api/input_ime/input_ime_api.cc @@ -59,6 +59,7 @@ void ImeObserver::OnFocus( context_value.auto_correct = ConvertInputContextAutoCorrect(context); context_value.auto_complete = ConvertInputContextAutoComplete(context); context_value.spell_check = ConvertInputContextSpellCheck(context); + context_value.should_do_learning = context.should_do_learning; std::unique_ptr<base::ListValue> args( input_ime::OnFocus::Create(context_value)); diff --git a/chromium/chrome/browser/extensions/api/input_ime/input_ime_api_chromeos.cc b/chromium/chrome/browser/extensions/api/input_ime/input_ime_api_chromeos.cc index 022c1f2d20b..85611abe334 100644 --- a/chromium/chrome/browser/extensions/api/input_ime/input_ime_api_chromeos.cc +++ b/chromium/chrome/browser/extensions/api/input_ime/input_ime_api_chromeos.cc @@ -25,8 +25,10 @@ #include "ui/base/ime/chromeos/input_method_manager.h" #include "ui/base/ime/ime_engine_handler_interface.h" #include "ui/keyboard/keyboard_controller.h" +#include "ui/keyboard/keyboard_util.h" namespace input_ime = extensions::api::input_ime; +namespace input_method_private = extensions::api::input_method_private; namespace DeleteSurroundingText = extensions::api::input_ime::DeleteSurroundingText; namespace UpdateMenuItems = extensions::api::input_ime::UpdateMenuItems; @@ -188,6 +190,39 @@ class ImeObserverChromeOS : public ui::ImeObserver { OnCompositionBoundsChanged::kEventName, std::move(args)); } + void OnFocus( + const IMEEngineHandlerInterface::InputContext& context) override { + if (extension_id_.empty()) + return; + + // There is both a public and private OnFocus event. The private OnFocus + // event is only for ChromeOS and contains additional information about pen + // inputs. We ensure that we only trigger one OnFocus event. + if (HasListener(input_method_private::OnFocus::kEventName) && + keyboard::IsStylusVirtualKeyboardEnabled()) { + input_method_private::InputContext input_context; + input_context.context_id = context.id; + input_context.type = input_method_private::ParseInputContextType( + ConvertInputContextType(context)); + input_context.auto_correct = ConvertInputContextAutoCorrect(context); + input_context.auto_complete = ConvertInputContextAutoComplete(context); + input_context.spell_check = ConvertInputContextSpellCheck(context); + input_context.should_do_learning = context.should_do_learning; + input_context.focus_reason = input_method_private::ParseFocusReason( + ConvertInputContextFocusReason(context)); + + std::unique_ptr<base::ListValue> args( + input_method_private::OnFocus::Create(input_context)); + + DispatchEventToExtension( + extensions::events::INPUT_METHOD_PRIVATE_ON_FOCUS, + input_method_private::OnFocus::kEventName, std::move(args)); + return; + } + + ImeObserver::OnFocus(context); + } + private: // ui::ImeObserver overrides. void DispatchEventToExtension( @@ -251,6 +286,22 @@ class ImeObserverChromeOS : public ui::ImeObserver { return "normal"; } + std::string ConvertInputContextFocusReason( + ui::IMEEngineHandlerInterface::InputContext input_context) { + switch (input_context.focus_reason) { + case ui::TextInputClient::FOCUS_REASON_NONE: + return ""; + case ui::TextInputClient::FOCUS_REASON_MOUSE: + return "mouse"; + case ui::TextInputClient::FOCUS_REASON_TOUCH: + return "touch"; + case ui::TextInputClient::FOCUS_REASON_PEN: + return "pen"; + case ui::TextInputClient::FOCUS_REASON_OTHER: + return "other"; + } + } + DISALLOW_COPY_AND_ASSIGN(ImeObserverChromeOS); }; @@ -619,6 +670,26 @@ InputMethodPrivateNotifyImeMenuItemActivatedFunction::Run() { return RespondNow(NoArguments()); } +ExtensionFunction::ResponseAction +InputMethodPrivateGetCompositionBoundsFunction::Run() { + InputMethodEngine* engine = GetActiveEngine( + Profile::FromBrowserContext(browser_context()), extension_id()); + if (!engine) + return RespondNow(Error(kErrorEngineNotAvailable)); + + auto bounds_list = std::make_unique<base::ListValue>(); + for (const auto& bounds : engine->composition_bounds()) { + auto bounds_value = std::make_unique<base::DictionaryValue>(); + bounds_value->SetInteger("x", bounds.x()); + bounds_value->SetInteger("y", bounds.y()); + bounds_value->SetInteger("w", bounds.width()); + bounds_value->SetInteger("h", bounds.height()); + bounds_list->Append(std::move(bounds_value)); + } + + return RespondNow(OneArgument(std::move(bounds_list))); +} + void InputImeAPI::OnExtensionLoaded(content::BrowserContext* browser_context, const Extension* extension) { const std::vector<InputComponentInfo>* input_components = diff --git a/chromium/chrome/browser/extensions/api/input_ime/input_ime_api_chromeos.h b/chromium/chrome/browser/extensions/api/input_ime/input_ime_api_chromeos.h index c329b90cb88..7356db8c224 100644 --- a/chromium/chrome/browser/extensions/api/input_ime/input_ime_api_chromeos.h +++ b/chromium/chrome/browser/extensions/api/input_ime/input_ime_api_chromeos.h @@ -133,6 +133,19 @@ class InputMethodPrivateNotifyImeMenuItemActivatedFunction InputMethodPrivateNotifyImeMenuItemActivatedFunction); }; +class InputMethodPrivateGetCompositionBoundsFunction + : public UIThreadExtensionFunction { + public: + DECLARE_EXTENSION_FUNCTION("inputMethodPrivate.getCompositionBounds", + INPUTMETHODPRIVATE_GETCOMPOSITIONBOUNDS) + + protected: + ~InputMethodPrivateGetCompositionBoundsFunction() override {} + + // ExtensionFunction: + ResponseAction Run() override; +}; + class InputImeEventRouter : public InputImeEventRouterBase { public: explicit InputImeEventRouter(Profile* profile); diff --git a/chromium/chrome/browser/extensions/api/input_ime/input_ime_apitest_chromeos.cc b/chromium/chrome/browser/extensions/api/input_ime/input_ime_apitest_chromeos.cc index af200cec127..01b8c20f9d3 100644 --- a/chromium/chrome/browser/extensions/api/input_ime/input_ime_apitest_chromeos.cc +++ b/chromium/chrome/browser/extensions/api/input_ime/input_ime_apitest_chromeos.cc @@ -8,8 +8,12 @@ #include "extensions/browser/api/test/test_api.h" #include "testing/gtest/include/gtest/gtest.h" +namespace extensions { + #if defined(OS_CHROMEOS) IN_PROC_BROWSER_TEST_F(ExtensionApiTest, InputImeApiBasic) { ASSERT_TRUE(RunExtensionTest("input_ime")) << message_; } #endif + +} // namespace extensions diff --git a/chromium/chrome/browser/extensions/api/instance_id/instance_id_api.cc b/chromium/chrome/browser/extensions/api/instance_id/instance_id_api.cc index bb844a69c6c..4f1b565131a 100644 --- a/chromium/chrome/browser/extensions/api/instance_id/instance_id_api.cc +++ b/chromium/chrome/browser/extensions/api/instance_id/instance_id_api.cc @@ -8,11 +8,11 @@ #include "base/logging.h" #include "base/metrics/histogram_macros.h" -#include "chrome/browser/gcm/instance_id/instance_id_profile_service.h" #include "chrome/browser/gcm/instance_id/instance_id_profile_service_factory.h" #include "chrome/browser/profiles/profile.h" #include "chrome/common/extensions/api/instance_id.h" #include "components/gcm_driver/instance_id/instance_id_driver.h" +#include "components/gcm_driver/instance_id/instance_id_profile_service.h" #include "extensions/common/extension.h" namespace extensions { @@ -76,7 +76,8 @@ ExtensionFunction::ResponseAction InstanceIDApiFunction::Run() { bool InstanceIDApiFunction::IsEnabled() const { Profile* profile = Profile::FromBrowserContext(browser_context()); - return instance_id::InstanceIDProfileService::IsInstanceIDEnabled(profile); + return instance_id::InstanceIDProfileService::IsInstanceIDEnabled( + profile->GetPrefs()); } instance_id::InstanceID* InstanceIDApiFunction::GetInstanceID() const { diff --git a/chromium/chrome/browser/extensions/api/management/chrome_management_api_delegate.cc b/chromium/chrome/browser/extensions/api/management/chrome_management_api_delegate.cc index c1701dac388..5da7b5d1b97 100644 --- a/chromium/chrome/browser/extensions/api/management/chrome_management_api_delegate.cc +++ b/chromium/chrome/browser/extensions/api/management/chrome_management_api_delegate.cc @@ -316,11 +316,13 @@ void ChromeManagementAPIDelegate::EnableExtension( void ChromeManagementAPIDelegate::DisableExtension( content::BrowserContext* context, + const extensions::Extension* source_extension, const std::string& extension_id, extensions::disable_reason::DisableReason disable_reason) const { extensions::ExtensionSystem::Get(context) ->extension_service() - ->DisableExtension(extension_id, disable_reason); + ->DisableExtensionWithSource(source_extension, extension_id, + disable_reason); } bool ChromeManagementAPIDelegate::UninstallExtension( diff --git a/chromium/chrome/browser/extensions/api/management/chrome_management_api_delegate.h b/chromium/chrome/browser/extensions/api/management/chrome_management_api_delegate.h index fa8e88c5825..eb53b3d9d8a 100644 --- a/chromium/chrome/browser/extensions/api/management/chrome_management_api_delegate.h +++ b/chromium/chrome/browser/extensions/api/management/chrome_management_api_delegate.h @@ -52,6 +52,7 @@ class ChromeManagementAPIDelegate : public extensions::ManagementAPIDelegate { const std::string& extension_id) const override; void DisableExtension( content::BrowserContext* context, + const extensions::Extension* source_extension, const std::string& extension_id, extensions::disable_reason::DisableReason disable_reason) const override; bool UninstallExtension(content::BrowserContext* context, diff --git a/chromium/chrome/browser/extensions/api/management/management_api_browsertest.cc b/chromium/chrome/browser/extensions/api/management/management_api_browsertest.cc index e144c34a723..63f3124ab1a 100644 --- a/chromium/chrome/browser/extensions/api/management/management_api_browsertest.cc +++ b/chromium/chrome/browser/extensions/api/management/management_api_browsertest.cc @@ -4,6 +4,7 @@ #include "base/files/file_path.h" #include "base/files/scoped_temp_dir.h" +#include "base/memory/scoped_refptr.h" #include "base/strings/pattern.h" #include "base/strings/string_util.h" #include "base/strings/stringprintf.h" @@ -26,6 +27,7 @@ #include "extensions/browser/extension_prefs.h" #include "extensions/browser/extension_system.h" #include "extensions/browser/notification_types.h" +#include "extensions/common/extension_builder.h" #include "extensions/test/extension_test_message_listener.h" namespace keys = extension_management_api_constants; @@ -206,10 +208,13 @@ class ExtensionManagementApiEscalationTest : ->DidExtensionEscalatePermissions(kId)); } - void SetEnabled(bool enabled, bool user_gesture, - const std::string& expected_error) { + void SetEnabled(bool enabled, + bool user_gesture, + const std::string& expected_error, + scoped_refptr<const Extension> extension) { scoped_refptr<ManagementSetEnabledFunction> function( new ManagementSetEnabledFunction); + function->set_extension(extension); const char* const enabled_string = enabled ? "true" : "false"; if (user_gesture) function->set_user_gesture(true); @@ -251,14 +256,18 @@ IN_PROC_BROWSER_TEST_F(ExtensionManagementApiEscalationTest, IN_PROC_BROWSER_TEST_F(ExtensionManagementApiEscalationTest, SetEnabled) { + scoped_refptr<const Extension> source_extension = + ExtensionBuilder("test").Build(); + // Expect an error about no gesture. - SetEnabled(true, false, keys::kGestureNeededForEscalationError); + SetEnabled(true, false, keys::kGestureNeededForEscalationError, + source_extension); { // Expect an error that user cancelled the dialog. ScopedTestDialogAutoConfirm auto_confirm( ScopedTestDialogAutoConfirm::CANCEL); - SetEnabled(true, true, keys::kUserDidNotReEnableError); + SetEnabled(true, true, keys::kUserDidNotReEnableError, source_extension); } { @@ -271,7 +280,7 @@ IN_PROC_BROWSER_TEST_F(ExtensionManagementApiEscalationTest, content::NotificationService::AllSources()); ScopedTestDialogAutoConfirm auto_confirm( ScopedTestDialogAutoConfirm::ACCEPT); - SetEnabled(true, true, std::string()); + SetEnabled(true, true, std::string(), source_extension); observer.Wait(); } @@ -281,8 +290,14 @@ IN_PROC_BROWSER_TEST_F(ExtensionManagementApiEscalationTest, ScopedTestDialogAutoConfirm auto_confirm( ScopedTestDialogAutoConfirm::ACCEPT); ASSERT_TRUE(CrashEnabledExtension(kId)); - SetEnabled(false, true, std::string()); - SetEnabled(true, true, std::string()); + // Register the target extension with extension service. + scoped_refptr<const Extension> target_extension = + ExtensionBuilder("TargetExtension").SetID(kId).Build(); + ExtensionService* const service = + ExtensionSystem::Get(browser()->profile())->extension_service(); + service->AddExtension(target_extension.get()); + SetEnabled(false, true, std::string(), source_extension); + SetEnabled(true, true, std::string(), source_extension); const Extension* extension = ExtensionSystem::Get(browser()->profile()) ->extension_service() ->GetExtensionById(kId, false); diff --git a/chromium/chrome/browser/extensions/api/management/management_api_unittest.cc b/chromium/chrome/browser/extensions/api/management/management_api_unittest.cc index d6e125dc86b..44ca34b11fa 100644 --- a/chromium/chrome/browser/extensions/api/management/management_api_unittest.cc +++ b/chromium/chrome/browser/extensions/api/management/management_api_unittest.cc @@ -111,9 +111,13 @@ void ManagementApiUnitTest::TearDown() { TEST_F(ManagementApiUnitTest, ManagementSetEnabled) { scoped_refptr<const Extension> extension = ExtensionBuilder("Test").Build(); service()->AddExtension(extension.get()); + scoped_refptr<const Extension> source_extension = + ExtensionBuilder("Test").Build(); + service()->AddExtension(source_extension.get()); std::string extension_id = extension->id(); scoped_refptr<ManagementSetEnabledFunction> function( new ManagementSetEnabledFunction()); + function->set_extension(source_extension); base::ListValue disable_args; disable_args.AppendString(extension_id); @@ -149,6 +153,107 @@ TEST_F(ManagementApiUnitTest, ManagementSetEnabled) { policy->UnregisterProvider(&provider); } +// Test that component extensions cannot be disabled, and that policy extensions +// can be disabled only by component/policy extensions. +TEST_F(ManagementApiUnitTest, ComponentPolicyDisabling) { + auto component = + ExtensionBuilder("component").SetLocation(Manifest::COMPONENT).Build(); + auto component2 = + ExtensionBuilder("component2").SetLocation(Manifest::COMPONENT).Build(); + auto policy = + ExtensionBuilder("policy").SetLocation(Manifest::EXTERNAL_POLICY).Build(); + auto policy2 = ExtensionBuilder("policy2") + .SetLocation(Manifest::EXTERNAL_POLICY) + .Build(); + auto internal = + ExtensionBuilder("internal").SetLocation(Manifest::INTERNAL).Build(); + + service()->AddExtension(component.get()); + service()->AddExtension(component2.get()); + service()->AddExtension(policy.get()); + service()->AddExtension(policy2.get()); + service()->AddExtension(internal.get()); + + auto extension_can_disable_extension = + [this](scoped_refptr<const Extension> source_extension, + scoped_refptr<const Extension> target_extension) { + std::string id = target_extension->id(); + base::ListValue args; + args.AppendString(id); + args.AppendBoolean(false /* disable the extension */); + auto function = base::MakeRefCounted<ManagementSetEnabledFunction>(); + function->set_extension(source_extension); + bool did_disable = RunFunction(function, args); + // If the extension was disabled, re-enable it. + if (did_disable) { + EXPECT_TRUE(registry()->disabled_extensions().Contains(id)); + service()->EnableExtension(id); + } else { + EXPECT_TRUE(registry()->enabled_extensions().Contains(id)); + } + return did_disable; + }; + + // Component extension cannot be disabled. + EXPECT_FALSE(extension_can_disable_extension(component2, component)); + EXPECT_FALSE(extension_can_disable_extension(policy, component)); + EXPECT_FALSE(extension_can_disable_extension(internal, component)); + + // Policy extension can be disabled by component/policy extensions, but not + // others. + EXPECT_TRUE(extension_can_disable_extension(component, policy)); + EXPECT_TRUE(extension_can_disable_extension(policy2, policy)); + EXPECT_FALSE(extension_can_disable_extension(internal, policy)); +} + +// Test that policy extensions can be enabled only by component/policy +// extensions. +TEST_F(ManagementApiUnitTest, ComponentPolicyEnabling) { + auto component = + ExtensionBuilder("component").SetLocation(Manifest::COMPONENT).Build(); + auto policy = + ExtensionBuilder("policy").SetLocation(Manifest::EXTERNAL_POLICY).Build(); + auto policy2 = ExtensionBuilder("policy2") + .SetLocation(Manifest::EXTERNAL_POLICY) + .Build(); + auto internal = + ExtensionBuilder("internal").SetLocation(Manifest::INTERNAL).Build(); + + service()->AddExtension(component.get()); + service()->AddExtension(policy.get()); + service()->AddExtension(policy2.get()); + service()->AddExtension(internal.get()); + service()->DisableExtensionWithSource( + component.get(), policy->id(), disable_reason::DISABLE_BLOCKED_BY_POLICY); + + auto extension_can_enable_extension = + [this, component](scoped_refptr<const Extension> source_extension, + scoped_refptr<const Extension> target_extension) { + std::string id = target_extension->id(); + base::ListValue args; + args.AppendString(id); + args.AppendBoolean(true /* enable the extension */); + auto function = base::MakeRefCounted<ManagementSetEnabledFunction>(); + function->set_extension(source_extension); + bool did_enable = RunFunction(function, args); + // If the extension was enabled, disable it. + if (did_enable) { + EXPECT_TRUE(registry()->enabled_extensions().Contains(id)); + service()->DisableExtensionWithSource( + component.get(), id, disable_reason::DISABLE_BLOCKED_BY_POLICY); + } else { + EXPECT_TRUE(registry()->disabled_extensions().Contains(id)); + } + return did_enable; + }; + + // Policy extension can be enabled by component/policy extensions, but not + // others. + EXPECT_TRUE(extension_can_enable_extension(component, policy)); + EXPECT_TRUE(extension_can_enable_extension(policy2, policy)); + EXPECT_FALSE(extension_can_enable_extension(internal, policy)); +} + // Tests management.uninstall. TEST_F(ManagementApiUnitTest, ManagementUninstall) { scoped_refptr<const Extension> extension = ExtensionBuilder("Test").Build(); diff --git a/chromium/chrome/browser/extensions/api/management/management_apitest.cc b/chromium/chrome/browser/extensions/api/management/management_apitest.cc index 3a914ec3552..2e470f69593 100644 --- a/chromium/chrome/browser/extensions/api/management/management_apitest.cc +++ b/chromium/chrome/browser/extensions/api/management/management_apitest.cc @@ -42,7 +42,7 @@ Browser* FindOtherBrowser(Browser* browser) { } // namespace -class ExtensionManagementApiTest : public ExtensionApiTest { +class ExtensionManagementApiTest : public extensions::ExtensionApiTest { public: virtual void LoadExtensions() { base::FilePath basedir = test_data_dir_.AppendASCII("management"); diff --git a/chromium/chrome/browser/extensions/api/management/management_browsertest.cc b/chromium/chrome/browser/extensions/api/management/management_browsertest.cc index 60ced21750e..adba1640c02 100644 --- a/chromium/chrome/browser/extensions/api/management/management_browsertest.cc +++ b/chromium/chrome/browser/extensions/api/management/management_browsertest.cc @@ -59,7 +59,7 @@ std::string BuildForceInstallPolicyValue(const char* extension_id, } // namespace -class ExtensionManagementTest : public ExtensionBrowserTest { +class ExtensionManagementTest : public extensions::ExtensionBrowserTest { public: void SetUpInProcessBrowserTestFixture() override { EXPECT_CALL(policy_provider_, IsInitializationComplete(_)) @@ -369,16 +369,14 @@ IN_PROC_BROWSER_TEST_F(ExtensionManagementTest, MAYBE_AutoUpdate) { ASSERT_EQ("ogjcoiohnmldgjemafoockdghcjciccf", extension->id()); ASSERT_EQ("1.0", extension->VersionString()); - extensions::ExtensionUpdater::CheckParams params; - params.callback = - base::Bind(&NotificationListener::OnFinished, - base::Unretained(¬ification_listener)); - // Run autoupdate and make sure version 2 of the extension was installed. ExtensionTestMessageListener listener2("v2 installed", false); extensions::TestExtensionRegistryObserver install_observer(registry); - service->updater()->CheckNow(params); + extensions::ExtensionUpdater::CheckParams params1; + params1.callback = base::BindOnce(&NotificationListener::OnFinished, + base::Unretained(¬ification_listener)); + service->updater()->CheckNow(std::move(params1)); install_observer.WaitForExtensionWillBeInstalled(); EXPECT_TRUE(listener2.WaitUntilSatisfied()); ASSERT_EQ(size_before + 1, registry->enabled_extensions().size()); @@ -400,7 +398,10 @@ IN_PROC_BROWSER_TEST_F(ExtensionManagementTest, MAYBE_AutoUpdate) { interceptor.SetResponseIgnoreQuery(GURL("http://localhost/autoupdate/v3.crx"), basedir.AppendASCII("v3.crx")); - service->updater()->CheckNow(params); + extensions::ExtensionUpdater::CheckParams params2; + params2.callback = base::BindOnce(&NotificationListener::OnFinished, + base::Unretained(¬ification_listener)); + service->updater()->CheckNow(std::move(params2)); ASSERT_TRUE(WaitForExtensionInstallError()); ASSERT_TRUE(notification_listener.started()); ASSERT_TRUE(notification_listener.finished()); @@ -473,16 +474,14 @@ IN_PROC_BROWSER_TEST_F(ExtensionManagementTest, ASSERT_EQ("ogjcoiohnmldgjemafoockdghcjciccf", extension->id()); ASSERT_EQ("1.0", extension->VersionString()); - extensions::ExtensionUpdater::CheckParams params; - params.callback = - base::Bind(&NotificationListener::OnFinished, - base::Unretained(¬ification_listener)); - ExtensionTestMessageListener listener2("v2 installed", false); extensions::TestExtensionRegistryObserver install_observer(registry); // Run autoupdate and make sure version 2 of the extension was installed but // is still disabled. - service->updater()->CheckNow(params); + extensions::ExtensionUpdater::CheckParams params; + params.callback = base::BindOnce(&NotificationListener::OnFinished, + base::Unretained(¬ification_listener)); + service->updater()->CheckNow(std::move(params)); install_observer.WaitForExtensionWillBeInstalled(); ASSERT_EQ(disabled_size_before + 1, registry->disabled_extensions().size()); ASSERT_EQ(enabled_size_before, registry->enabled_extensions().size()); @@ -509,7 +508,6 @@ IN_PROC_BROWSER_TEST_F(ExtensionManagementTest, ExternalUrlUpdate) { ExtensionService* service = extensions::ExtensionSystem::Get( browser()->profile())->extension_service(); const char kExtensionId[] = "ogjcoiohnmldgjemafoockdghcjciccf"; - extensions::ExtensionUpdater::CheckParams params; base::ScopedAllowBlockingForTesting allow_blocking; base::ScopedTempDir temp_dir; @@ -556,7 +554,7 @@ IN_PROC_BROWSER_TEST_F(ExtensionManagementTest, ExternalUrlUpdate) { extensions::TestExtensionRegistryObserver install_observer(registry); // Run autoupdate and make sure version 2 of the extension was installed. - service->updater()->CheckNow(params); + service->updater()->CheckNow(extensions::ExtensionUpdater::CheckParams()); install_observer.WaitForExtensionWillBeInstalled(); ASSERT_EQ(size_before + 1, registry->enabled_extensions().size()); const Extension* extension = service->GetExtensionById(kExtensionId, false); diff --git a/chromium/chrome/browser/extensions/api/mdns/mdns_api_unittest.cc b/chromium/chrome/browser/extensions/api/mdns/mdns_api_unittest.cc index a74ce67ef9f..2b97c24e75d 100644 --- a/chromium/chrome/browser/extensions/api/mdns/mdns_api_unittest.cc +++ b/chromium/chrome/browser/extensions/api/mdns/mdns_api_unittest.cc @@ -98,9 +98,9 @@ class MockEventRouter : public EventRouter { explicit MockEventRouter(content::BrowserContext* browser_context, ExtensionPrefs* extension_prefs) : EventRouter(browser_context, extension_prefs) {} - virtual ~MockEventRouter() {} + ~MockEventRouter() override {} - virtual void BroadcastEvent(std::unique_ptr<Event> event) { + void BroadcastEvent(std::unique_ptr<Event> event) override { BroadcastEventPtr(event.get()); } MOCK_METHOD1(BroadcastEventPtr, void(Event* event)); @@ -220,6 +220,7 @@ class MDnsAPITest : public extensions::ExtensionServiceTestBase { base::DictionaryValue manifest; manifest.SetString(extensions::manifest_keys::kVersion, "1.0.0.0"); manifest.SetString(extensions::manifest_keys::kName, name); + manifest.SetInteger(extensions::manifest_keys::kManifestVersion, 2); if (is_platform_app) { // Setting app.background.page = "background.html" is sufficient to make // the extension type TYPE_PLATFORM_APP. diff --git a/chromium/chrome/browser/extensions/api/mdns/mdns_apitest.cc b/chromium/chrome/browser/extensions/api/mdns/mdns_apitest.cc index 48bcf21aab1..7751cefc276 100644 --- a/chromium/chrome/browser/extensions/api/mdns/mdns_apitest.cc +++ b/chromium/chrome/browser/extensions/api/mdns/mdns_apitest.cc @@ -23,12 +23,12 @@ namespace api = extensions::api; namespace { -class MDnsAPITest : public ExtensionApiTest { +class MDnsAPITest : public extensions::ExtensionApiTest { public: MDnsAPITest() {} void SetUpCommandLine(base::CommandLine* command_line) override { - ExtensionApiTest::SetUpCommandLine(command_line); + extensions::ExtensionApiTest::SetUpCommandLine(command_line); command_line->AppendSwitchASCII( extensions::switches::kWhitelistedExtensionID, "ddchlicdkolnonkihahngkmmmjnjlkkf"); diff --git a/chromium/chrome/browser/extensions/api/media_galleries/blob_data_source_factory.cc b/chromium/chrome/browser/extensions/api/media_galleries/blob_data_source_factory.cc new file mode 100644 index 00000000000..98271a7dd7b --- /dev/null +++ b/chromium/chrome/browser/extensions/api/media_galleries/blob_data_source_factory.cc @@ -0,0 +1,83 @@ +// Copyright 2018 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#include "chrome/browser/extensions/api/media_galleries/blob_data_source_factory.h" +#include "content/public/browser/browser_context.h" +#include "extensions/browser/blob_reader.h" +#include "mojo/public/cpp/bindings/binding.h" + +namespace extensions { +namespace { + +// Media data source that reads data from a blob in browser process. +class BlobMediaDataSource : public chrome::mojom::MediaDataSource { + public: + BlobMediaDataSource(chrome::mojom::MediaDataSourcePtr* interface, + content::BrowserContext* browser_context, + const std::string& blob_uuid, + BlobDataSourceFactory::MediaDataCallback callback) + : binding_(this, mojo::MakeRequest(interface)), + browser_context_(browser_context), + blob_uuid_(blob_uuid), + callback_(callback), + weak_factory_(this) {} + + ~BlobMediaDataSource() override = default; + + private: + // chrome::mojom::MediaDataSource implementation. + void Read(int64_t position, + int64_t length, + chrome::mojom::MediaDataSource::ReadCallback callback) override { + StartBlobRequest(std::move(callback), position, length); + } + + void StartBlobRequest(chrome::mojom::MediaDataSource::ReadCallback callback, + int64_t position, + int64_t length) { + BlobReader* reader = new BlobReader( // BlobReader is self-deleting. + browser_context_, blob_uuid_, + base::BindRepeating(&BlobMediaDataSource::OnBlobReaderDone, + weak_factory_.GetWeakPtr(), + base::Passed(&callback))); + reader->SetByteRange(position, length); + reader->Start(); + } + + void OnBlobReaderDone(chrome::mojom::MediaDataSource::ReadCallback callback, + std::unique_ptr<std::string> data, + int64_t size) { + callback_.Run(std::move(callback), std::move(data)); + } + + mojo::Binding<chrome::mojom::MediaDataSource> binding_; + + content::BrowserContext* const browser_context_; + std::string blob_uuid_; + + BlobDataSourceFactory::MediaDataCallback callback_; + + base::WeakPtrFactory<BlobMediaDataSource> weak_factory_; + + DISALLOW_COPY_AND_ASSIGN(BlobMediaDataSource); +}; + +} // namespace + +BlobDataSourceFactory::BlobDataSourceFactory( + content::BrowserContext* browser_context, + const std::string& blob_uuid) + : browser_context_(browser_context), blob_uuid_(blob_uuid) {} + +BlobDataSourceFactory::~BlobDataSourceFactory() = default; + +std::unique_ptr<chrome::mojom::MediaDataSource> +BlobDataSourceFactory::CreateMediaDataSource( + chrome::mojom::MediaDataSourcePtr* request, + MediaDataCallback media_data_callback) { + return std::make_unique<BlobMediaDataSource>(request, browser_context_, + blob_uuid_, media_data_callback); +} + +} // namespace extensions diff --git a/chromium/chrome/browser/extensions/api/media_galleries/blob_data_source_factory.h b/chromium/chrome/browser/extensions/api/media_galleries/blob_data_source_factory.h new file mode 100644 index 00000000000..c2ed111caf6 --- /dev/null +++ b/chromium/chrome/browser/extensions/api/media_galleries/blob_data_source_factory.h @@ -0,0 +1,45 @@ +// Copyright 2018 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#ifndef CHROME_BROWSER_EXTENSIONS_API_MEDIA_GALLERIES_BLOB_DATA_SOURCE_FACTORY_H_ +#define CHROME_BROWSER_EXTENSIONS_API_MEDIA_GALLERIES_BLOB_DATA_SOURCE_FACTORY_H_ + +#include <memory> +#include <string> + +#include "base/macros.h" +#include "chrome/services/media_gallery_util/public/cpp/safe_media_metadata_parser.h" +#include "chrome/services/media_gallery_util/public/mojom/media_parser.mojom.h" + +namespace content { +class BrowserContext; +} // namespace content + +namespace extensions { + +// Factory to provide media data source for extension media gallery API. +// Internally it will read media data from a blob in browser process. +class BlobDataSourceFactory + : public SafeMediaMetadataParser::MediaDataSourceFactory { + public: + BlobDataSourceFactory(content::BrowserContext* browser_context, + const std::string& blob_uuid); + ~BlobDataSourceFactory() override; + + private: + // SafeMediaMetadataParser::MediaDataSourceFactory implementation. + std::unique_ptr<chrome::mojom::MediaDataSource> CreateMediaDataSource( + chrome::mojom::MediaDataSourcePtr* request, + MediaDataCallback media_data_callback) override; + + content::BrowserContext* browser_context_; + std::string blob_uuid_; + MediaDataCallback callback_; + + DISALLOW_COPY_AND_ASSIGN(BlobDataSourceFactory); +}; + +} // namespace extensions + +#endif // CHROME_BROWSER_EXTENSIONS_API_MEDIA_GALLERIES_BLOB_DATA_SOURCE_FACTORY_H_ diff --git a/chromium/chrome/browser/extensions/api/media_galleries/media_galleries_api.cc b/chromium/chrome/browser/extensions/api/media_galleries/media_galleries_api.cc index d958a3dc130..efe4a6313a2 100644 --- a/chromium/chrome/browser/extensions/api/media_galleries/media_galleries_api.cc +++ b/chromium/chrome/browser/extensions/api/media_galleries/media_galleries_api.cc @@ -24,6 +24,8 @@ #include "base/strings/utf_string_conversions.h" #include "base/values.h" #include "chrome/browser/browser_process.h" +#include "chrome/browser/extensions/api/media_galleries/blob_data_source_factory.h" +#include "chrome/browser/extensions/api/media_galleries/media_galleries_api_util.h" #include "chrome/browser/extensions/chrome_extension_function_details.h" #include "chrome/browser/extensions/extension_tab_util.h" #include "chrome/browser/media_galleries/gallery_watch_manager.h" @@ -674,9 +676,11 @@ void MediaGalleriesGetMetadataFunction::GetMetadata( metadata_type == MediaGalleries::GET_METADATA_TYPE_ALL || metadata_type == MediaGalleries::GET_METADATA_TYPE_NONE; + auto media_data_source_factory = + std::make_unique<BlobDataSourceFactory>(GetProfile(), blob_uuid); auto parser = std::make_unique<SafeMediaMetadataParser>( - GetProfile(), blob_uuid, total_blob_length, mime_type, - get_attached_images); + total_blob_length, mime_type, get_attached_images, + std::move(media_data_source_factory)); SafeMediaMetadataParser* parser_ptr = parser.get(); parser_ptr->Start( content::ServiceManagerConnection::GetForProcess()->GetConnector(), @@ -688,7 +692,7 @@ void MediaGalleriesGetMetadataFunction::GetMetadata( void MediaGalleriesGetMetadataFunction::OnSafeMediaMetadataParserDone( std::unique_ptr<SafeMediaMetadataParser> parser_keep_alive, bool parse_success, - std::unique_ptr<base::DictionaryValue> metadata_dictionary, + chrome::mojom::MediaMetadataPtr metadata, std::unique_ptr<std::vector<metadata::AttachedImage>> attached_images) { DCHECK_CURRENTLY_ON(content::BrowserThread::UI); @@ -697,12 +701,13 @@ void MediaGalleriesGetMetadataFunction::OnSafeMediaMetadataParserDone( return; } - DCHECK(metadata_dictionary.get()); - DCHECK(attached_images.get()); + DCHECK(metadata); + DCHECK(attached_images); std::unique_ptr<base::DictionaryValue> result_dictionary( new base::DictionaryValue); - result_dictionary->Set(kMetadataKey, std::move(metadata_dictionary)); + result_dictionary->Set(kMetadataKey, + SerializeMediaMetadata(std::move(metadata))); if (attached_images->empty()) { SetResult(std::move(result_dictionary)); diff --git a/chromium/chrome/browser/extensions/api/media_galleries/media_galleries_api.h b/chromium/chrome/browser/extensions/api/media_galleries/media_galleries_api.h index 003d60740f6..ebe708aba0f 100644 --- a/chromium/chrome/browser/extensions/api/media_galleries/media_galleries_api.h +++ b/chromium/chrome/browser/extensions/api/media_galleries/media_galleries_api.h @@ -22,6 +22,7 @@ #include "chrome/browser/media_galleries/media_file_system_registry.h" #include "chrome/common/extensions/api/media_galleries.h" #include "chrome/common/media_galleries/metadata_types.h" +#include "chrome/services/media_gallery_util/public/mojom/media_parser.mojom.h" #include "components/storage_monitor/media_storage_util.h" #include "extensions/browser/browser_context_keyed_api_factory.h" #include "extensions/browser/event_router.h" @@ -181,7 +182,7 @@ class MediaGalleriesGetMetadataFunction : public ChromeAsyncExtensionFunction { void OnSafeMediaMetadataParserDone( std::unique_ptr<SafeMediaMetadataParser> parser_keep_alive, bool parse_success, - std::unique_ptr<base::DictionaryValue> result_dictionary, + chrome::mojom::MediaMetadataPtr metadata, std::unique_ptr<std::vector<metadata::AttachedImage>> attached_images); void ConstructNextBlob( diff --git a/chromium/chrome/browser/extensions/api/media_galleries/media_galleries_api_util.cc b/chromium/chrome/browser/extensions/api/media_galleries/media_galleries_api_util.cc new file mode 100644 index 00000000000..9a0eda75700 --- /dev/null +++ b/chromium/chrome/browser/extensions/api/media_galleries/media_galleries_api_util.cc @@ -0,0 +1,63 @@ +// Copyright 2018 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#include "chrome/browser/extensions/api/media_galleries/media_galleries_api_util.h" + +#include "base/logging.h" +#include "chrome/common/extensions/api/media_galleries.h" + +namespace extensions { + +template <class T> +void SetValueScopedPtr(T value, std::unique_ptr<T>* destination) { + DCHECK(destination); + if (value >= 0) + destination->reset(new T(value)); +} + +template <> +void SetValueScopedPtr(std::string value, + std::unique_ptr<std::string>* destination) { + DCHECK(destination); + if (!value.empty()) + destination->reset(new std::string(std::move(value))); +} + +std::unique_ptr<base::DictionaryValue> SerializeMediaMetadata( + chrome::mojom::MediaMetadataPtr metadata) { + DCHECK(metadata); + extensions::api::media_galleries::MediaMetadata extension_metadata; + extension_metadata.mime_type = std::move(metadata->mime_type); + if (metadata->height >= 0 && metadata->width >= 0) { + extension_metadata.height.reset(new int(metadata->height)); + extension_metadata.width.reset(new int(metadata->width)); + } + + SetValueScopedPtr(metadata->duration, &extension_metadata.duration); + SetValueScopedPtr(std::move(metadata->artist), &extension_metadata.artist); + SetValueScopedPtr(std::move(metadata->album), &extension_metadata.album); + SetValueScopedPtr(std::move(metadata->comment), &extension_metadata.comment); + SetValueScopedPtr(std::move(metadata->copyright), + &extension_metadata.copyright); + SetValueScopedPtr(metadata->disc, &extension_metadata.disc); + SetValueScopedPtr(std::move(metadata->genre), &extension_metadata.genre); + SetValueScopedPtr(std::move(metadata->language), + &extension_metadata.language); + SetValueScopedPtr(metadata->rotation, &extension_metadata.rotation); + SetValueScopedPtr(std::move(metadata->title), &extension_metadata.title); + SetValueScopedPtr(metadata->track, &extension_metadata.track); + + for (const chrome::mojom::MediaStreamInfoPtr& info : metadata->raw_tags) { + extensions::api::media_galleries::StreamInfo stream_info; + stream_info.type = std::move(info->type); + base::DictionaryValue* dict_value; + info->additional_properties.GetAsDictionary(&dict_value); + stream_info.tags.additional_properties.Swap(dict_value); + extension_metadata.raw_tags.push_back(std::move(stream_info)); + } + + return extension_metadata.ToValue(); +} + +} // namespace extensions diff --git a/chromium/chrome/browser/extensions/api/media_galleries/media_galleries_api_util.h b/chromium/chrome/browser/extensions/api/media_galleries/media_galleries_api_util.h new file mode 100644 index 00000000000..c768acde0ae --- /dev/null +++ b/chromium/chrome/browser/extensions/api/media_galleries/media_galleries_api_util.h @@ -0,0 +1,25 @@ +// Copyright 2018 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#ifndef CHROME_BROWSER_EXTENSIONS_API_MEDIA_GALLERIES_MEDIA_GALLERIES_API_UTIL_H_ +#define CHROME_BROWSER_EXTENSIONS_API_MEDIA_GALLERIES_MEDIA_GALLERIES_API_UTIL_H_ + +#include <memory> + +#include "chrome/services/media_gallery_util/public/mojom/media_parser.mojom.h" + +namespace base { +class DictionaryValue; +} // namespace base + +namespace extensions { + +// Converts a mojo media metadata struct into a dictionary. Internally uses +// extension's auto generated serializer. +std::unique_ptr<base::DictionaryValue> SerializeMediaMetadata( + chrome::mojom::MediaMetadataPtr metadata); + +} // namespace extensions + +#endif // CHROME_BROWSER_EXTENSIONS_API_MEDIA_GALLERIES_MEDIA_GALLERIES_API_UTIL_H_ diff --git a/chromium/chrome/browser/extensions/api/media_galleries/media_galleries_apitest.cc b/chromium/chrome/browser/extensions/api/media_galleries/media_galleries_apitest.cc index 39bdf5e556f..95796a2c7fb 100644 --- a/chromium/chrome/browser/extensions/api/media_galleries/media_galleries_apitest.cc +++ b/chromium/chrome/browser/extensions/api/media_galleries/media_galleries_apitest.cc @@ -254,7 +254,7 @@ class MediaGalleriesPlatformAppPpapiTest void SetUpOnMainThread() override { MediaGalleriesPlatformAppBrowserTest::SetUpOnMainThread(); - ASSERT_TRUE(PathService::Get(chrome::DIR_GEN_TEST_DATA, &app_dir_)); + ASSERT_TRUE(base::PathService::Get(chrome::DIR_GEN_TEST_DATA, &app_dir_)); app_dir_ = app_dir_.AppendASCII("ppapi") .AppendASCII("tests") .AppendASCII("extensions") diff --git a/chromium/chrome/browser/extensions/api/media_galleries/media_galleries_watch_apitest.cc b/chromium/chrome/browser/extensions/api/media_galleries/media_galleries_watch_apitest.cc index 0e662e59525..f3a7613fbec 100644 --- a/chromium/chrome/browser/extensions/api/media_galleries/media_galleries_watch_apitest.cc +++ b/chromium/chrome/browser/extensions/api/media_galleries/media_galleries_watch_apitest.cc @@ -69,7 +69,7 @@ const char kGalleryChangedEventReceived[] = "gallery_changed_event_received"; // MediaGalleriesGalleryWatchApiTest // /////////////////////////////////////////////////////////////////////////////// -class MediaGalleriesGalleryWatchApiTest : public ExtensionApiTest { +class MediaGalleriesGalleryWatchApiTest : public extensions::ExtensionApiTest { public: MediaGalleriesGalleryWatchApiTest() : extension_(NULL), background_host_(NULL) {} @@ -78,12 +78,12 @@ class MediaGalleriesGalleryWatchApiTest : public ExtensionApiTest { protected: // ExtensionApiTest overrides. void SetUpCommandLine(base::CommandLine* command_line) override { - ExtensionApiTest::SetUpCommandLine(command_line); + extensions::ExtensionApiTest::SetUpCommandLine(command_line); command_line->AppendSwitchASCII( extensions::switches::kWhitelistedExtensionID, kTestExtensionId); } void SetUpOnMainThread() override { - ExtensionApiTest::SetUpOnMainThread(); + extensions::ExtensionApiTest::SetUpOnMainThread(); ensure_media_directories_exists_.reset(new EnsureMediaDirectoriesExists); extension_ = LoadExtension(test_data_dir_.AppendASCII(kTestExtensionPath)); GetBackgroundHostForTestExtension(); @@ -94,7 +94,7 @@ class MediaGalleriesGalleryWatchApiTest : public ExtensionApiTest { extension_ = NULL; background_host_ = NULL; ensure_media_directories_exists_.reset(); - ExtensionApiTest::TearDownOnMainThread(); + extensions::ExtensionApiTest::TearDownOnMainThread(); } bool GalleryWatchesSupported() { diff --git a/chromium/chrome/browser/extensions/api/media_perception_private/media_perception_api_delegate_chromeos.cc b/chromium/chrome/browser/extensions/api/media_perception_private/media_perception_api_delegate_chromeos.cc index 4b96ce3fc8f..902cccf2825 100644 --- a/chromium/chrome/browser/extensions/api/media_perception_private/media_perception_api_delegate_chromeos.cc +++ b/chromium/chrome/browser/extensions/api/media_perception_private/media_perception_api_delegate_chromeos.cc @@ -4,9 +4,12 @@ #include "chrome/browser/extensions/api/media_perception_private/media_perception_api_delegate_chromeos.h" +#include <string> +#include <utility> + #include "base/bind.h" #include "chrome/browser/browser_process.h" -#include "chrome/browser/component_updater/cros_component_installer.h" +#include "chrome/browser/component_updater/cros_component_installer_chromeos.h" namespace media_perception = extensions::api::media_perception_private; @@ -36,7 +39,9 @@ void OnLoadComponent( MediaPerceptionAPIDelegate::LoadCrOSComponentCallback load_callback, component_updater::CrOSComponentManager::Error error, const base::FilePath& mount_point) { - std::move(load_callback).Run(mount_point); + std::move(load_callback) + .Run(error == component_updater::CrOSComponentManager::Error::NONE, + mount_point); } } // namespace diff --git a/chromium/chrome/browser/extensions/api/messaging/native_messaging_apitest.cc b/chromium/chrome/browser/extensions/api/messaging/native_messaging_apitest.cc index eac88e83622..0983cc2ca74 100644 --- a/chromium/chrome/browser/extensions/api/messaging/native_messaging_apitest.cc +++ b/chromium/chrome/browser/extensions/api/messaging/native_messaging_apitest.cc @@ -5,6 +5,8 @@ #include "chrome/browser/extensions/api/messaging/native_messaging_test_util.h" #include "chrome/browser/extensions/extension_apitest.h" +namespace extensions { + IN_PROC_BROWSER_TEST_F(ExtensionApiTest, NativeMessagingBasic) { extensions::ScopedTestNativeMessagingHost test_host; ASSERT_NO_FATAL_FAILURE(test_host.RegisterTestHost(false)); @@ -16,3 +18,5 @@ IN_PROC_BROWSER_TEST_F(ExtensionApiTest, UserLevelNativeMessaging) { ASSERT_NO_FATAL_FAILURE(test_host.RegisterTestHost(true)); ASSERT_TRUE(RunExtensionTest("native_messaging")) << message_; } + +} // namespace extensions diff --git a/chromium/chrome/browser/extensions/api/messaging/native_messaging_test_util.cc b/chromium/chrome/browser/extensions/api/messaging/native_messaging_test_util.cc index 4067196dcaa..1acf4aec153 100644 --- a/chromium/chrome/browser/extensions/api/messaging/native_messaging_test_util.cc +++ b/chromium/chrome/browser/extensions/api/messaging/native_messaging_test_util.cc @@ -74,7 +74,8 @@ void ScopedTestNativeMessagingHost::RegisterTestHost(bool user_level) { ScopedTestNativeMessagingHost test_host; base::FilePath test_user_data_dir; - ASSERT_TRUE(PathService::Get(chrome::DIR_TEST_DATA, &test_user_data_dir)); + ASSERT_TRUE( + base::PathService::Get(chrome::DIR_TEST_DATA, &test_user_data_dir)); test_user_data_dir = test_user_data_dir.AppendASCII("native_messaging") .AppendASCII("native_hosts"); diff --git a/chromium/chrome/browser/extensions/api/messaging/native_process_launcher_posix.cc b/chromium/chrome/browser/extensions/api/messaging/native_process_launcher_posix.cc index 0a5d0166333..c0843625742 100644 --- a/chromium/chrome/browser/extensions/api/messaging/native_process_launcher_posix.cc +++ b/chromium/chrome/browser/extensions/api/messaging/native_process_launcher_posix.cc @@ -22,7 +22,7 @@ namespace { base::FilePath FindManifestInDir(int dir_key, const std::string& host_name) { base::FilePath base_path; - if (PathService::Get(dir_key, &base_path)) { + if (base::PathService::Get(dir_key, &base_path)) { base::FilePath path = base_path.Append(host_name + ".json"); if (base::PathExists(path)) return path; diff --git a/chromium/chrome/browser/extensions/api/metrics_private/metrics_apitest.cc b/chromium/chrome/browser/extensions/api/metrics_private/metrics_apitest.cc index b41a3e14ee3..c9862e8fde7 100644 --- a/chromium/chrome/browser/extensions/api/metrics_private/metrics_apitest.cc +++ b/chromium/chrome/browser/extensions/api/metrics_private/metrics_apitest.cc @@ -14,6 +14,8 @@ #include "chrome/browser/extensions/extension_apitest.h" #include "components/variations/variations_associated_data.h" +namespace extensions { + namespace { // The tests that are run by this extension are expected to record the following @@ -126,7 +128,7 @@ void ValidateHistograms(const RecordedHistogram* recorded, } } -} // anonymous namespace +} // namespace IN_PROC_BROWSER_TEST_F(ExtensionApiTest, Metrics) { base::UserActionTester user_action_tester; @@ -145,3 +147,5 @@ IN_PROC_BROWSER_TEST_F(ExtensionApiTest, Metrics) { arraysize(g_user_actions)); ValidateHistograms(g_histograms, arraysize(g_histograms)); } + +} // namespace extensions diff --git a/chromium/chrome/browser/extensions/api/module/module_apitest.cc b/chromium/chrome/browser/extensions/api/module/module_apitest.cc index 748b13275ea..ca037e4085b 100644 --- a/chromium/chrome/browser/extensions/api/module/module_apitest.cc +++ b/chromium/chrome/browser/extensions/api/module/module_apitest.cc @@ -4,8 +4,7 @@ #include "chrome/browser/extensions/extension_apitest.h" -class ExtensionModuleApiTest : public ExtensionApiTest { -}; +using ExtensionModuleApiTest = extensions::ExtensionApiTest; IN_PROC_BROWSER_TEST_F(ExtensionModuleApiTest, CognitoFile) { ASSERT_TRUE(RunExtensionTest("extension_module/cognito_file")) << message_; diff --git a/chromium/chrome/browser/extensions/api/networking_config_chromeos_apitest_chromeos.cc b/chromium/chrome/browser/extensions/api/networking_config_chromeos_apitest_chromeos.cc index 2dea3a79ffc..4cfa0b91735 100644 --- a/chromium/chrome/browser/extensions/api/networking_config_chromeos_apitest_chromeos.cc +++ b/chromium/chrome/browser/extensions/api/networking_config_chromeos_apitest_chromeos.cc @@ -2,6 +2,7 @@ // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. +#include <memory> #include <string> #include "base/location.h" @@ -12,10 +13,10 @@ #include "base/values.h" #include "chrome/browser/browser_process.h" #include "chrome/browser/chromeos/net/network_portal_detector_impl.h" -#include "chrome/browser/chromeos/net/network_portal_notification_controller.h" #include "chrome/browser/chromeos/profiles/profile_helper.h" #include "chrome/browser/extensions/extension_apitest.h" #include "chrome/browser/notifications/notification_display_service_tester.h" +#include "chrome/browser/ui/ash/network/network_portal_notification_controller.h" #include "chromeos/dbus/dbus_thread_manager.h" #include "chromeos/dbus/shill_device_client.h" #include "chromeos/dbus/shill_profile_client.h" @@ -45,11 +46,14 @@ const char kWifi1ServiceGUID[] = "wifi1_guid"; } // namespace class NetworkingConfigTest - : public ExtensionApiTest, + : public extensions::ExtensionApiTest, public captive_portal::CaptivePortalDetectorTestBase { public: + NetworkingConfigTest() : network_portal_detector_(nullptr) {} + ~NetworkingConfigTest() override = default; + void SetUpOnMainThread() override { - ExtensionApiTest::SetUpOnMainThread(); + extensions::ExtensionApiTest::SetUpOnMainThread(); content::RunAllPendingInMessageLoop(); display_service_ = std::make_unique<NotificationDisplayServiceTester>( @@ -81,12 +85,20 @@ class NetworkingConfigTest content::RunAllPendingInMessageLoop(); - network_portal_detector_ = new NetworkPortalDetectorImpl( - test_loader_factory(), true /* create_notification_controller */); + network_portal_detector_ = + new NetworkPortalDetectorImpl(test_loader_factory()); + // Takes ownership of |network_portal_detector_|: chromeos::network_portal_detector::InitializeForTesting( network_portal_detector_); network_portal_detector_->Enable(false /* start_detection */); set_detector(network_portal_detector_->captive_portal_detector_.get()); + network_portal_notification_controller_ = + std::make_unique<NetworkPortalNotificationController>( + network_portal_detector_); + } + + void TearDownOnMainThread() override { + network_portal_notification_controller_.reset(); } void LoadTestExtension() { @@ -118,7 +130,9 @@ class NetworkingConfigTest } protected: - NetworkPortalDetectorImpl* network_portal_detector_ = nullptr; + NetworkPortalDetectorImpl* network_portal_detector_; + std::unique_ptr<NetworkPortalNotificationController> + network_portal_notification_controller_; const extensions::Extension* extension_ = nullptr; std::unique_ptr<NotificationDisplayServiceTester> display_service_; }; diff --git a/chromium/chrome/browser/extensions/api/networking_private/networking_private_chromeos_apitest.cc b/chromium/chrome/browser/extensions/api/networking_private/networking_private_chromeos_apitest.cc index 4abe0b8919d..475010dec10 100644 --- a/chromium/chrome/browser/extensions/api/networking_private/networking_private_chromeos_apitest.cc +++ b/chromium/chrome/browser/extensions/api/networking_private/networking_private_chromeos_apitest.cc @@ -52,6 +52,7 @@ #include "content/public/browser/notification_service.h" #include "content/public/browser/notification_source.h" #include "content/public/test/test_utils.h" +#include "dbus/object_path.h" #include "extensions/browser/api/networking_private/networking_private_chromeos.h" #include "extensions/browser/api/networking_private/networking_private_delegate_factory.h" #include "extensions/browser/notification_types.h" @@ -186,7 +187,7 @@ class TestListener : public content::NotificationObserver { DISALLOW_COPY_AND_ASSIGN(TestListener); }; -class NetworkingPrivateChromeOSApiTest : public ExtensionApiTest { +class NetworkingPrivateChromeOSApiTest : public extensions::ExtensionApiTest { public: NetworkingPrivateChromeOSApiTest() : detector_(nullptr), @@ -207,11 +208,11 @@ class NetworkingPrivateChromeOSApiTest : public ExtensionApiTest { .WillRepeatedly(Return(true)); policy::BrowserPolicyConnector::SetPolicyProviderForTesting(&provider_); - ExtensionApiTest::SetUpInProcessBrowserTestFixture(); + extensions::ExtensionApiTest::SetUpInProcessBrowserTestFixture(); } void SetUpCommandLine(base::CommandLine* command_line) override { - ExtensionApiTest::SetUpCommandLine(command_line); + extensions::ExtensionApiTest::SetUpCommandLine(command_line); // Whitelist the extension ID of the test extension. command_line->AppendSwitchASCII( extensions::switches::kWhitelistedExtensionID, @@ -252,33 +253,30 @@ class NetworkingPrivateChromeOSApiTest : public ExtensionApiTest { // Add a Cellular GSM Device. device_test_->AddDevice(kCellularDevicePath, shill::kTypeCellular, "stub_cellular_device1"); - device_test_->SetDeviceProperty(kCellularDevicePath, - shill::kCarrierProperty, - base::Value("Cellular1_Carrier")); + SetDeviceProperty(kCellularDevicePath, shill::kCarrierProperty, + base::Value("Cellular1_Carrier")); base::DictionaryValue home_provider; home_provider.SetString("name", "Cellular1_Provider"); home_provider.SetString("code", "000000"); home_provider.SetString("country", "us"); - device_test_->SetDeviceProperty( - kCellularDevicePath, shill::kHomeProviderProperty, home_provider); - device_test_->SetDeviceProperty(kCellularDevicePath, - shill::kTechnologyFamilyProperty, - base::Value(shill::kNetworkTechnologyGsm)); - device_test_->SetDeviceProperty(kCellularDevicePath, shill::kMeidProperty, - base::Value("test_meid")); - device_test_->SetDeviceProperty(kCellularDevicePath, shill::kImeiProperty, - base::Value("test_imei")); - device_test_->SetDeviceProperty(kCellularDevicePath, shill::kIccidProperty, - base::Value("test_iccid")); - device_test_->SetDeviceProperty(kCellularDevicePath, shill::kEsnProperty, - base::Value("test_esn")); - device_test_->SetDeviceProperty(kCellularDevicePath, shill::kMdnProperty, - base::Value("test_mdn")); - device_test_->SetDeviceProperty(kCellularDevicePath, shill::kMinProperty, - base::Value("test_min")); - device_test_->SetDeviceProperty(kCellularDevicePath, - shill::kModelIdProperty, - base::Value("test_model_id")); + SetDeviceProperty(kCellularDevicePath, shill::kHomeProviderProperty, + home_provider); + SetDeviceProperty(kCellularDevicePath, shill::kTechnologyFamilyProperty, + base::Value(shill::kNetworkTechnologyGsm)); + SetDeviceProperty(kCellularDevicePath, shill::kMeidProperty, + base::Value("test_meid")); + SetDeviceProperty(kCellularDevicePath, shill::kImeiProperty, + base::Value("test_imei")); + SetDeviceProperty(kCellularDevicePath, shill::kIccidProperty, + base::Value("test_iccid")); + SetDeviceProperty(kCellularDevicePath, shill::kEsnProperty, + base::Value("test_esn")); + SetDeviceProperty(kCellularDevicePath, shill::kMdnProperty, + base::Value("test_mdn")); + SetDeviceProperty(kCellularDevicePath, shill::kMinProperty, + base::Value("test_min")); + SetDeviceProperty(kCellularDevicePath, shill::kModelIdProperty, + base::Value("test_model_id")); device_test_->SetSimLocked(kCellularDevicePath, false); // Add the Cellular Service. @@ -323,6 +321,13 @@ class NetworkingPrivateChromeOSApiTest : public ExtensionApiTest { state, true /* add_to_visible */); } + void SetDeviceProperty(const std::string& device_path, + const std::string& name, + const base::Value& value) { + device_test_->SetDeviceProperty(device_path, name, value, + /*notify_changed=*/true); + } + static std::unique_ptr<KeyedService> CreateNetworkingPrivateDelegate( content::BrowserContext* context) { std::unique_ptr<NetworkingPrivateDelegate> result( @@ -340,14 +345,14 @@ class NetworkingPrivateChromeOSApiTest : public ExtensionApiTest { ChromeNetworkingCastPrivateDelegate::SetFactoryCallbackForTest( &networking_cast_delegate_factory_); - ExtensionApiTest::SetUp(); + extensions::ExtensionApiTest::SetUp(); } void SetUpOnMainThread() override { detector_ = new NetworkPortalDetectorTestImpl(); chromeos::network_portal_detector::InitializeForTesting(detector_); - ExtensionApiTest::SetUpOnMainThread(); + extensions::ExtensionApiTest::SetUpOnMainThread(); content::RunAllPendingInMessageLoop(); NetworkingPrivateDelegateFactory::GetInstance()->SetTestingFactory( @@ -389,10 +394,10 @@ class NetworkingPrivateChromeOSApiTest : public ExtensionApiTest { "stub_wifi_device1"); base::ListValue wifi_ip_configs; wifi_ip_configs.AppendString(kIPConfigPath); - device_test_->SetDeviceProperty(kWifiDevicePath, shill::kIPConfigsProperty, - wifi_ip_configs); - device_test_->SetDeviceProperty(kWifiDevicePath, shill::kAddressProperty, - base::Value("001122aabbcc")); + SetDeviceProperty(kWifiDevicePath, shill::kIPConfigsProperty, + wifi_ip_configs); + SetDeviceProperty(kWifiDevicePath, shill::kAddressProperty, + base::Value("001122aabbcc")); // Add Services AddService("stub_ethernet", "eth0", shill::kTypeEthernet, @@ -480,7 +485,7 @@ class NetworkingPrivateChromeOSApiTest : public ExtensionApiTest { } void TearDown() override { - ExtensionApiTest::TearDown(); + extensions::ExtensionApiTest::TearDown(); ChromeNetworkingCastPrivateDelegate::SetFactoryCallbackForTest(nullptr); } @@ -543,8 +548,10 @@ IN_PROC_BROWSER_TEST_F(NetworkingPrivateChromeOSApiTest, StartActivate) { IN_PROC_BROWSER_TEST_F(NetworkingPrivateChromeOSApiTest, StartActivateSprint) { SetupCellular(); // Set the carrier to Sprint. - device_test_->SetDeviceProperty(kCellularDevicePath, shill::kCarrierProperty, - base::Value(shill::kCarrierSprint)); + DBusThreadManager::Get()->GetShillDeviceClient()->SetCarrier( + dbus::ObjectPath(kCellularDevicePath), shill::kCarrierSprint, + base::DoNothing(), + base::BindRepeating([](const std::string&, const std::string&) {})); EXPECT_TRUE(RunNetworkingSubtest("startActivateSprint")) << message_; EXPECT_EQ(0, UIDelegateStub::s_show_account_details_called_); } @@ -908,8 +915,8 @@ IN_PROC_BROWSER_TEST_F(NetworkingPrivateChromeOSApiTest, .Set(shill::kStatusProperty, "available") .Build()) .Build(); - device_test_->SetDeviceProperty( - kCellularDevicePath, shill::kFoundNetworksProperty, *found_networks); + SetDeviceProperty(kCellularDevicePath, shill::kFoundNetworksProperty, + *found_networks); EXPECT_TRUE(RunNetworkingSubtest("selectCellularMobileNetwork")) << message_; } diff --git a/chromium/chrome/browser/extensions/api/networking_private/networking_private_service_client_apitest.cc b/chromium/chrome/browser/extensions/api/networking_private/networking_private_service_client_apitest.cc index 6b2b32bdea8..12ca21e5ca4 100644 --- a/chromium/chrome/browser/extensions/api/networking_private/networking_private_service_client_apitest.cc +++ b/chromium/chrome/browser/extensions/api/networking_private/networking_private_service_client_apitest.cc @@ -91,7 +91,8 @@ class TestNetworkingCastPrivateDelegate DISALLOW_COPY_AND_ASSIGN(TestNetworkingCastPrivateDelegate); }; -class NetworkingPrivateServiceClientApiTest : public ExtensionApiTest { +class NetworkingPrivateServiceClientApiTest + : public extensions::ExtensionApiTest { public: NetworkingPrivateServiceClientApiTest() {} @@ -102,7 +103,7 @@ class NetworkingPrivateServiceClientApiTest : public ExtensionApiTest { } void SetUpCommandLine(base::CommandLine* command_line) override { - ExtensionApiTest::SetUpCommandLine(command_line); + extensions::ExtensionApiTest::SetUpCommandLine(command_line); // Whitelist the extension ID of the test extension. command_line->AppendSwitchASCII( extensions::switches::kWhitelistedExtensionID, @@ -124,11 +125,11 @@ class NetworkingPrivateServiceClientApiTest : public ExtensionApiTest { base::Unretained(this)); ChromeNetworkingCastPrivateDelegate::SetFactoryCallbackForTest( &networking_cast_delegate_factory_); - ExtensionApiTest::SetUp(); + extensions::ExtensionApiTest::SetUp(); } void SetUpOnMainThread() override { - ExtensionApiTest::SetUpOnMainThread(); + extensions::ExtensionApiTest::SetUpOnMainThread(); content::RunAllPendingInMessageLoop(); NetworkingPrivateDelegateFactory::GetInstance()->SetTestingFactory( profile(), &CreateNetworkingPrivateServiceClient); @@ -136,11 +137,11 @@ class NetworkingPrivateServiceClientApiTest : public ExtensionApiTest { void TearDownOnMainThread() override { content::RunAllPendingInMessageLoop(); - ExtensionApiTest::TearDownOnMainThread(); + extensions::ExtensionApiTest::TearDownOnMainThread(); } void TearDown() override { - ExtensionApiTest::TearDown(); + extensions::ExtensionApiTest::TearDown(); ChromeNetworkingCastPrivateDelegate::SetFactoryCallbackForTest(nullptr); } diff --git a/chromium/chrome/browser/extensions/api/notifications/notifications_apitest.cc b/chromium/chrome/browser/extensions/api/notifications/notifications_apitest.cc index d999be59789..fbca69edf11 100644 --- a/chromium/chrome/browser/extensions/api/notifications/notifications_apitest.cc +++ b/chromium/chrome/browser/extensions/api/notifications/notifications_apitest.cc @@ -5,7 +5,6 @@ #include <memory> #include "base/containers/circular_deque.h" -#include "base/message_loop/message_loop.h" #include "base/run_loop.h" #include "base/strings/string_number_conversions.h" #include "base/strings/stringprintf.h" @@ -112,7 +111,7 @@ enum class WindowState { NORMAL }; -class NotificationsApiTest : public ExtensionApiTest { +class NotificationsApiTest : public extensions::ExtensionApiTest { public: const Extension* LoadExtensionAndWait( const std::string& test_name) { @@ -173,7 +172,7 @@ class NotificationsApiTest : public ExtensionApiTest { protected: void SetUpOnMainThread() override { - ExtensionApiTest::SetUpOnMainThread(); + extensions::ExtensionApiTest::SetUpOnMainThread(); DCHECK(profile()); display_service_tester_ = @@ -182,7 +181,7 @@ class NotificationsApiTest : public ExtensionApiTest { void TearDownOnMainThread() override { display_service_tester_.reset(); - ExtensionApiTest::TearDownOnMainThread(); + extensions::ExtensionApiTest::TearDownOnMainThread(); } // Returns the notification that's being displayed for |extension|, or nullptr diff --git a/chromium/chrome/browser/extensions/api/omnibox/omnibox_api_interactive_test.cc b/chromium/chrome/browser/extensions/api/omnibox/omnibox_api_interactive_test.cc index 1e70b8a3011..c45a45ca66e 100644 --- a/chromium/chrome/browser/extensions/api/omnibox/omnibox_api_interactive_test.cc +++ b/chromium/chrome/browser/extensions/api/omnibox/omnibox_api_interactive_test.cc @@ -75,7 +75,14 @@ IN_PROC_BROWSER_TEST_F(OmniboxApiTest, PopupStaysClosed) { } // Tests deleting a deletable omnibox extension suggestion result. -IN_PROC_BROWSER_TEST_F(OmniboxApiTest, DeleteOmniboxSuggestionResult) { +// Flaky on Windows. https://crbug.com/801316 +#if defined(OS_WIN) +#define MAYBE_DeleteOmniboxSuggestionResult \ + DISABLED_DeleteOmniboxSuggestionResult +#else +#define MAYBE_DeleteOmniboxSuggestionResult DeleteOmniboxSuggestionResult +#endif +IN_PROC_BROWSER_TEST_F(OmniboxApiTest, MAYBE_DeleteOmniboxSuggestionResult) { ASSERT_TRUE(RunExtensionTest("omnibox")) << message_; // The results depend on the TemplateURLService being loaded. Make sure it is diff --git a/chromium/chrome/browser/extensions/api/omnibox/omnibox_api_testbase.h b/chromium/chrome/browser/extensions/api/omnibox/omnibox_api_testbase.h index 0013aa05f35..c95e2c48834 100644 --- a/chromium/chrome/browser/extensions/api/omnibox/omnibox_api_testbase.h +++ b/chromium/chrome/browser/extensions/api/omnibox/omnibox_api_testbase.h @@ -24,7 +24,7 @@ class AutocompleteController; -class OmniboxApiTest : public ExtensionApiTest { +class OmniboxApiTest : public extensions::ExtensionApiTest { protected: LocationBar* GetLocationBar(Browser* browser) const { return browser->window()->GetLocationBar(); diff --git a/chromium/chrome/browser/extensions/api/page_capture/page_capture_apitest.cc b/chromium/chrome/browser/extensions/api/page_capture/page_capture_apitest.cc index 3e7e9bd2934..96e50f1b94d 100644 --- a/chromium/chrome/browser/extensions/api/page_capture/page_capture_apitest.cc +++ b/chromium/chrome/browser/extensions/api/page_capture/page_capture_apitest.cc @@ -22,14 +22,14 @@ using extensions::PageCaptureSaveAsMHTMLFunction; using extensions::ScopedTestDialogAutoConfirm; -class ExtensionPageCaptureApiTest : public ExtensionApiTest { +class ExtensionPageCaptureApiTest : public extensions::ExtensionApiTest { public: void SetUpCommandLine(base::CommandLine* command_line) override { - ExtensionApiTest::SetUpCommandLine(command_line); + extensions::ExtensionApiTest::SetUpCommandLine(command_line); command_line->AppendSwitchASCII(switches::kJavaScriptFlags, "--expose-gc"); } void SetUpOnMainThread() override { - ExtensionApiTest::SetUpOnMainThread(); + extensions::ExtensionApiTest::SetUpOnMainThread(); host_resolver()->AddRule("*", "127.0.0.1"); } }; diff --git a/chromium/chrome/browser/extensions/api/passwords_private/passwords_private_api.cc b/chromium/chrome/browser/extensions/api/passwords_private/passwords_private_api.cc index f1b79559ce1..2ed573f89bb 100644 --- a/chromium/chrome/browser/extensions/api/passwords_private/passwords_private_api.cc +++ b/chromium/chrome/browser/extensions/api/passwords_private/passwords_private_api.cc @@ -177,7 +177,7 @@ PasswordsPrivateImportPasswordsFunction::Run() { PasswordsPrivateDelegate* delegate = PasswordsPrivateDelegateFactory::GetForBrowserContext(browser_context(), true /* create */); - delegate->ImportPasswords(GetAssociatedWebContents()); + delegate->ImportPasswords(GetSenderWebContents()); return RespondNow(NoArguments()); } @@ -196,7 +196,7 @@ PasswordsPrivateExportPasswordsFunction::Run() { base::BindOnce( &PasswordsPrivateExportPasswordsFunction::ExportRequestCompleted, this), - GetAssociatedWebContents()); + GetSenderWebContents()); return RespondLater(); } diff --git a/chromium/chrome/browser/extensions/api/permissions/permissions_api.cc b/chromium/chrome/browser/extensions/api/permissions/permissions_api.cc index d78cf8f3d83..dcc9fd56b9b 100644 --- a/chromium/chrome/browser/extensions/api/permissions/permissions_api.cc +++ b/chromium/chrome/browser/extensions/api/permissions/permissions_api.cc @@ -8,6 +8,7 @@ #include "chrome/browser/chrome_notification_types.h" #include "chrome/browser/extensions/api/permissions/permissions_api_helpers.h" +#include "chrome/browser/extensions/chrome_extension_function_details.h" #include "chrome/browser/extensions/extension_management.h" #include "chrome/browser/extensions/permissions_updater.h" #include "chrome/browser/profiles/profile.h" @@ -142,63 +143,61 @@ PermissionsRequestFunction::PermissionsRequestFunction() {} PermissionsRequestFunction::~PermissionsRequestFunction() {} -bool PermissionsRequestFunction::RunAsync() { - results_ = Request::Results::Create(false); - +ExtensionFunction::ResponseAction PermissionsRequestFunction::Run() { if (!user_gesture() && !ignore_user_gesture_for_tests && extension_->location() != Manifest::COMPONENT) { - error_ = kUserGestureRequiredError; - return false; + return RespondNow(Error(kUserGestureRequiredError)); } + gfx::NativeWindow native_window = + ChromeExtensionFunctionDetails(this).GetNativeWindowForUI(); + if (!native_window) + return RespondNow(Error("Could not find an active window.")); + std::unique_ptr<Request::Params> params(Request::Params::Create(*args_)); EXTENSION_FUNCTION_VALIDATE(params); + std::string error; requested_permissions_ = helpers::UnpackPermissionSet( params->permissions, - ExtensionPrefs::Get(GetProfile())->AllowFileAccess(extension_->id()), - &error_); + ExtensionPrefs::Get(browser_context())->AllowFileAccess(extension_->id()), + &error); if (!requested_permissions_.get()) - return false; + return RespondNow(Error(error)); // Make sure they're only requesting permissions supported by this API. APIPermissionSet apis = requested_permissions_->apis(); for (APIPermissionSet::const_iterator i = apis.begin(); i != apis.end(); ++i) { if (!i->info()->supports_optional()) { - error_ = ErrorUtils::FormatErrorMessage( - kNotWhitelistedError, i->name()); - return false; + return RespondNow(Error( + ErrorUtils::FormatErrorMessage(kNotWhitelistedError, i->name()))); } } // The requested permissions must be defined as optional in the manifest. if (!PermissionsParser::GetOptionalPermissions(extension()) .Contains(*requested_permissions_)) { - error_ = kNotInOptionalPermissionsError; - return false; + return RespondNow(Error(kNotInOptionalPermissionsError)); } // Automatically declines api permissions requests, which are blocked by // enterprise policy. - if (!ExtensionManagementFactory::GetForBrowserContext(GetProfile()) + if (!ExtensionManagementFactory::GetForBrowserContext(browser_context()) ->IsPermissionSetAllowed(extension(), *requested_permissions_)) { - error_ = kBlockedByEnterprisePolicy; - return false; + return RespondNow(Error(kBlockedByEnterprisePolicy)); } // We don't need to prompt the user if the requested permissions are a subset // of the granted permissions set. std::unique_ptr<const PermissionSet> granted = - ExtensionPrefs::Get(GetProfile()) + ExtensionPrefs::Get(browser_context()) ->GetGrantedPermissions(extension()->id()); if (granted.get() && granted->Contains(*requested_permissions_)) { - PermissionsUpdater perms_updater(GetProfile()); + PermissionsUpdater perms_updater(browser_context()); perms_updater.AddPermissions(extension(), *requested_permissions_); - results_ = Request::Results::Create(true); - SendResponse(true); - return true; + return RespondNow(ArgumentList(Request::Results::Create(true))); } // Filter out the granted permissions so we only prompt for new ones. @@ -225,35 +224,40 @@ bool PermissionsRequestFunction::RunAsync() { if (auto_confirm_for_tests == PROCEED || has_no_warnings || extension_->location() == Manifest::COMPONENT) { OnInstallPromptDone(ExtensionInstallPrompt::Result::ACCEPTED); - } else if (auto_confirm_for_tests == ABORT) { + return AlreadyResponded(); + } + + if (auto_confirm_for_tests == ABORT) { // Pretend the user clicked cancel. OnInstallPromptDone(ExtensionInstallPrompt::Result::USER_CANCELED); - } else { - CHECK_EQ(DO_NOT_SKIP, auto_confirm_for_tests); - install_ui_.reset(new ExtensionInstallPrompt(GetAssociatedWebContents())); - install_ui_->ShowDialog( - base::Bind(&PermissionsRequestFunction::OnInstallPromptDone, this), - extension(), nullptr, - std::make_unique<ExtensionInstallPrompt::Prompt>( - ExtensionInstallPrompt::PERMISSIONS_PROMPT), - requested_permissions_->Clone(), - ExtensionInstallPrompt::GetDefaultShowDialogCallback()); + return AlreadyResponded(); } - return true; + CHECK_EQ(DO_NOT_SKIP, auto_confirm_for_tests); + install_ui_.reset(new ExtensionInstallPrompt( + Profile::FromBrowserContext(browser_context()), native_window)); + install_ui_->ShowDialog( + base::Bind(&PermissionsRequestFunction::OnInstallPromptDone, this), + extension(), nullptr, + std::make_unique<ExtensionInstallPrompt::Prompt>( + ExtensionInstallPrompt::PERMISSIONS_PROMPT), + requested_permissions_->Clone(), + ExtensionInstallPrompt::GetDefaultShowDialogCallback()); + + // ExtensionInstallPrompt::ShowDialog() can call the response synchronously. + return did_respond() ? AlreadyResponded() : RespondLater(); } void PermissionsRequestFunction::OnInstallPromptDone( ExtensionInstallPrompt::Result result) { - if (result == ExtensionInstallPrompt::Result::ACCEPTED) { - PermissionsUpdater perms_updater(GetProfile()); + bool granted = result == ExtensionInstallPrompt::Result::ACCEPTED; + if (granted) { + PermissionsUpdater perms_updater(browser_context()); perms_updater.AddPermissions(extension(), *requested_permissions_); - - results_ = Request::Results::Create(true); } - SendResponse(true); - Release(); // Balanced in RunAsync(). + Respond(ArgumentList(Request::Results::Create(granted))); + Release(); // Balanced in Run(). } } // namespace extensions diff --git a/chromium/chrome/browser/extensions/api/permissions/permissions_api.h b/chromium/chrome/browser/extensions/api/permissions/permissions_api.h index e780a45199d..63e516bf56a 100644 --- a/chromium/chrome/browser/extensions/api/permissions/permissions_api.h +++ b/chromium/chrome/browser/extensions/api/permissions/permissions_api.h @@ -9,8 +9,8 @@ #include "base/compiler_specific.h" #include "base/macros.h" -#include "chrome/browser/extensions/chrome_extension_function.h" #include "chrome/browser/extensions/extension_install_prompt.h" +#include "extensions/browser/extension_function.h" #include "extensions/common/permissions/permission_set.h" namespace extensions { @@ -52,7 +52,7 @@ class PermissionsRemoveFunction : public UIThreadExtensionFunction { }; // chrome.permissions.request -class PermissionsRequestFunction : public ChromeAsyncExtensionFunction { +class PermissionsRequestFunction : public UIThreadExtensionFunction { public: DECLARE_EXTENSION_FUNCTION("permissions.request", PERMISSIONS_REQUEST) @@ -66,7 +66,7 @@ class PermissionsRequestFunction : public ChromeAsyncExtensionFunction { ~PermissionsRequestFunction() override; // ExtensionFunction: - bool RunAsync() override; + ResponseAction Run() override; private: void OnInstallPromptDone(ExtensionInstallPrompt::Result result); diff --git a/chromium/chrome/browser/extensions/api/platform_keys/platform_keys_apitest_nss.cc b/chromium/chrome/browser/extensions/api/platform_keys/platform_keys_apitest_nss.cc index 63971e9f50f..8df8111325f 100644 --- a/chromium/chrome/browser/extensions/api/platform_keys/platform_keys_apitest_nss.cc +++ b/chromium/chrome/browser/extensions/api/platform_keys/platform_keys_apitest_nss.cc @@ -3,6 +3,7 @@ // found in the LICENSE file. #include <cryptohi.h> +#include <pk11pub.h> #include <memory> #include <utility> @@ -20,6 +21,8 @@ #include "chrome/browser/profiles/profile.h" #include "components/policy/policy_constants.h" #include "crypto/nss_util_internal.h" +#include "crypto/scoped_nss_types.h" +#include "crypto/scoped_test_nss_db.h" #include "crypto/scoped_test_system_nss_key_slot.h" #include "net/cert/nss_cert_database.h" #include "net/cert/test_root_certs.h" @@ -30,15 +33,34 @@ namespace { class PlatformKeysTest : public PlatformKeysTestBase { public: + enum class UserClientCertSlot { kPrivateSlot, kPublicSlot }; + PlatformKeysTest(EnrollmentStatus enrollment_status, UserStatus user_status, - bool key_permission_policy) + bool key_permission_policy, + UserClientCertSlot user_client_cert_slot) : PlatformKeysTestBase(SystemTokenStatus::EXISTS, enrollment_status, user_status), - key_permission_policy_(key_permission_policy) {} + key_permission_policy_(key_permission_policy), + user_client_cert_slot_(user_client_cert_slot) {} void SetUpOnMainThread() override { + if (!IsPreTest()) { + // Set up the private slot before + // |PlatformKeysTestBase::SetUpOnMainThread| triggers the user sign-in. + ASSERT_TRUE(user_private_slot_db_.is_open()); + base::RunLoop loop; + content::BrowserThread::PostTaskAndReply( + content::BrowserThread::IO, FROM_HERE, + base::BindOnce(&PlatformKeysTest::SetPrivateSoftwareSlotOnIO, + base::Unretained(this), + crypto::ScopedPK11Slot( + PK11_ReferenceSlot(user_private_slot_db_.slot()))), + loop.QuitClosure()); + loop.Run(); + } + PlatformKeysTestBase::SetUpOnMainThread(); if (IsPreTest()) @@ -128,11 +150,18 @@ class PlatformKeysTest : public PlatformKeysTestBase { } protected: + // Imported into user's private or public slot, depending on the value of + // |user_client_cert_slot_|. scoped_refptr<net::X509Certificate> client_cert1_; + // Imported into system slot. scoped_refptr<net::X509Certificate> client_cert2_; const extensions::Extension* extension_; private: + void SetPrivateSoftwareSlotOnIO(crypto::ScopedPK11Slot slot) { + crypto::SetPrivateSoftwareSlotForChromeOSUserForTesting(std::move(slot)); + } + void GotPermissionsForExtension( const base::Closure& done_callback, std::unique_ptr<chromeos::KeyPermissions::PermissionsForExtension> @@ -152,9 +181,16 @@ class PlatformKeysTest : public PlatformKeysTestBase { } void SetupTestClientCerts(net::NSSCertDatabase* cert_db) { + // Sanity check to ensure that + // SetPrivateSoftwareSlotForChromeOSUserForTesting took effect. + EXPECT_EQ(user_private_slot_db_.slot(), cert_db->GetPrivateSlot().get()); + EXPECT_NE(cert_db->GetPrivateSlot().get(), cert_db->GetPublicSlot().get()); + + auto* slot = user_client_cert_slot_ == UserClientCertSlot::kPrivateSlot + ? cert_db->GetPrivateSlot().get() + : cert_db->GetPublicSlot().get(); client_cert1_ = net::ImportClientCertAndKeyFromFile( - net::GetTestCertsDirectory(), "client_1.pem", "client_1.pk8", - cert_db->GetPrivateSlot().get()); + net::GetTestCertsDirectory(), "client_1.pem", "client_1.pk8", slot); ASSERT_TRUE(client_cert1_.get()); // Import a second client cert signed by another CA than client_1 into the @@ -175,6 +211,8 @@ class PlatformKeysTest : public PlatformKeysTestBase { } const bool key_permission_policy_; + const UserClientCertSlot user_client_cert_slot_; + crypto::ScopedTestNSSDB user_private_slot_db_; DISALLOW_COPY_AND_ASSIGN(PlatformKeysTest); }; @@ -204,7 +242,7 @@ class TestSelectDelegate scoped_refptr<net::X509Certificate> selection; if (certs_to_select_.back()) { for (scoped_refptr<net::X509Certificate> cert : certs) { - if (cert->Equals(certs_to_select_.back().get())) { + if (cert->EqualsExcludingChain(certs_to_select_.back().get())) { selection = cert; break; } @@ -219,19 +257,32 @@ class TestSelectDelegate net::CertificateList certs_to_select_; }; -class UnmanagedPlatformKeysTest : public PlatformKeysTest, - public ::testing::WithParamInterface< - PlatformKeysTestBase::EnrollmentStatus> { +struct UnmanagedPlatformKeysTestParams { + UnmanagedPlatformKeysTestParams( + PlatformKeysTestBase::EnrollmentStatus enrollment_status, + PlatformKeysTest::UserClientCertSlot user_client_cert_slot) + : enrollment_status_(enrollment_status), + user_client_cert_slot_(user_client_cert_slot) {} + + PlatformKeysTestBase::EnrollmentStatus enrollment_status_; + PlatformKeysTest::UserClientCertSlot user_client_cert_slot_; +}; + +class UnmanagedPlatformKeysTest + : public PlatformKeysTest, + public ::testing::WithParamInterface<UnmanagedPlatformKeysTestParams> { public: UnmanagedPlatformKeysTest() - : PlatformKeysTest(GetParam(), + : PlatformKeysTest(GetParam().enrollment_status_, UserStatus::UNMANAGED, - false /* unused */) {} + false /* unused */, + GetParam().user_client_cert_slot_) {} }; -struct Params { - Params(PlatformKeysTestBase::EnrollmentStatus enrollment_status, - PlatformKeysTestBase::UserStatus user_status) +struct ManagedPlatformKeysTestParams { + ManagedPlatformKeysTestParams( + PlatformKeysTestBase::EnrollmentStatus enrollment_status, + PlatformKeysTestBase::UserStatus user_status) : enrollment_status_(enrollment_status), user_status_(user_status) {} PlatformKeysTestBase::EnrollmentStatus enrollment_status_; @@ -240,22 +291,24 @@ struct Params { class ManagedWithPermissionPlatformKeysTest : public PlatformKeysTest, - public ::testing::WithParamInterface<Params> { + public ::testing::WithParamInterface<ManagedPlatformKeysTestParams> { public: ManagedWithPermissionPlatformKeysTest() : PlatformKeysTest(GetParam().enrollment_status_, GetParam().user_status_, - true /* grant the extension key permission */) {} + true /* grant the extension key permission */, + UserClientCertSlot::kPrivateSlot) {} }; class ManagedWithoutPermissionPlatformKeysTest : public PlatformKeysTest, - public ::testing::WithParamInterface<Params> { + public ::testing::WithParamInterface<ManagedPlatformKeysTestParams> { public: ManagedWithoutPermissionPlatformKeysTest() : PlatformKeysTest(GetParam().enrollment_status_, GetParam().user_status_, - false /* do not grant key permission */) {} + false /* do not grant key permission */, + UserClientCertSlot::kPrivateSlot) {} }; } // namespace @@ -299,8 +352,18 @@ IN_PROC_BROWSER_TEST_P(UnmanagedPlatformKeysTest, Permissions) { INSTANTIATE_TEST_CASE_P( Unmanaged, UnmanagedPlatformKeysTest, - ::testing::Values(PlatformKeysTestBase::EnrollmentStatus::ENROLLED, - PlatformKeysTestBase::EnrollmentStatus::NOT_ENROLLED)); + ::testing::Values(UnmanagedPlatformKeysTestParams( + PlatformKeysTestBase::EnrollmentStatus::ENROLLED, + PlatformKeysTest::UserClientCertSlot::kPrivateSlot), + UnmanagedPlatformKeysTestParams( + PlatformKeysTestBase::EnrollmentStatus::NOT_ENROLLED, + PlatformKeysTest::UserClientCertSlot::kPrivateSlot), + UnmanagedPlatformKeysTestParams( + PlatformKeysTestBase::EnrollmentStatus::ENROLLED, + PlatformKeysTest::UserClientCertSlot::kPublicSlot), + UnmanagedPlatformKeysTestParams( + PlatformKeysTestBase::EnrollmentStatus::NOT_ENROLLED, + PlatformKeysTest::UserClientCertSlot::kPublicSlot))); IN_PROC_BROWSER_TEST_P(ManagedWithoutPermissionPlatformKeysTest, PRE_UserPermissionsBlocked) { @@ -340,12 +403,15 @@ INSTANTIATE_TEST_CASE_P( ManagedWithoutPermission, ManagedWithoutPermissionPlatformKeysTest, ::testing::Values( - Params(PlatformKeysTestBase::EnrollmentStatus::ENROLLED, - PlatformKeysTestBase::UserStatus::MANAGED_AFFILIATED_DOMAIN), - Params(PlatformKeysTestBase::EnrollmentStatus::ENROLLED, - PlatformKeysTestBase::UserStatus::MANAGED_OTHER_DOMAIN), - Params(PlatformKeysTestBase::EnrollmentStatus::NOT_ENROLLED, - PlatformKeysTestBase::UserStatus::MANAGED_OTHER_DOMAIN))); + ManagedPlatformKeysTestParams( + PlatformKeysTestBase::EnrollmentStatus::ENROLLED, + PlatformKeysTestBase::UserStatus::MANAGED_AFFILIATED_DOMAIN), + ManagedPlatformKeysTestParams( + PlatformKeysTestBase::EnrollmentStatus::ENROLLED, + PlatformKeysTestBase::UserStatus::MANAGED_OTHER_DOMAIN), + ManagedPlatformKeysTestParams( + PlatformKeysTestBase::EnrollmentStatus::NOT_ENROLLED, + PlatformKeysTestBase::UserStatus::MANAGED_OTHER_DOMAIN))); IN_PROC_BROWSER_TEST_P(ManagedWithPermissionPlatformKeysTest, PRE_PolicyGrantsAccessToCorporateKey) { @@ -396,9 +462,12 @@ INSTANTIATE_TEST_CASE_P( ManagedWithPermission, ManagedWithPermissionPlatformKeysTest, ::testing::Values( - Params(PlatformKeysTestBase::EnrollmentStatus::ENROLLED, - PlatformKeysTestBase::UserStatus::MANAGED_AFFILIATED_DOMAIN), - Params(PlatformKeysTestBase::EnrollmentStatus::ENROLLED, - PlatformKeysTestBase::UserStatus::MANAGED_OTHER_DOMAIN), - Params(PlatformKeysTestBase::EnrollmentStatus::NOT_ENROLLED, - PlatformKeysTestBase::UserStatus::MANAGED_OTHER_DOMAIN))); + ManagedPlatformKeysTestParams( + PlatformKeysTestBase::EnrollmentStatus::ENROLLED, + PlatformKeysTestBase::UserStatus::MANAGED_AFFILIATED_DOMAIN), + ManagedPlatformKeysTestParams( + PlatformKeysTestBase::EnrollmentStatus::ENROLLED, + PlatformKeysTestBase::UserStatus::MANAGED_OTHER_DOMAIN), + ManagedPlatformKeysTestParams( + PlatformKeysTestBase::EnrollmentStatus::NOT_ENROLLED, + PlatformKeysTestBase::UserStatus::MANAGED_OTHER_DOMAIN))); diff --git a/chromium/chrome/browser/extensions/api/platform_keys/platform_keys_test_base.cc b/chromium/chrome/browser/extensions/api/platform_keys/platform_keys_test_base.cc index 74e8911e005..24934f6a747 100644 --- a/chromium/chrome/browser/extensions/api/platform_keys/platform_keys_test_base.cc +++ b/chromium/chrome/browser/extensions/api/platform_keys/platform_keys_test_base.cc @@ -56,7 +56,7 @@ PlatformKeysTestBase::~PlatformKeysTestBase() {} void PlatformKeysTestBase::SetUp() { base::FilePath test_data_dir; - PathService::Get(chrome::DIR_TEST_DATA, &test_data_dir); + base::PathService::Get(chrome::DIR_TEST_DATA, &test_data_dir); embedded_test_server()->ServeFilesFromDirectory(test_data_dir); embedded_test_server()->RegisterRequestHandler(base::BindRepeating( @@ -72,11 +72,11 @@ void PlatformKeysTestBase::SetUp() { GaiaUrls::GetInstance()->gaia_url().host(), embedded_test_server()->base_url())); - ExtensionApiTest::SetUp(); + extensions::ExtensionApiTest::SetUp(); } void PlatformKeysTestBase::SetUpCommandLine(base::CommandLine* command_line) { - ExtensionApiTest::SetUpCommandLine(command_line); + extensions::ExtensionApiTest::SetUpCommandLine(command_line); policy::affiliation_test_helper::AppendCommandLineSwitchesForLoginManager( command_line); @@ -91,7 +91,7 @@ void PlatformKeysTestBase::SetUpCommandLine(base::CommandLine* command_line) { } void PlatformKeysTestBase::SetUpInProcessBrowserTestFixture() { - ExtensionApiTest::SetUpInProcessBrowserTestFixture(); + extensions::ExtensionApiTest::SetUpInProcessBrowserTestFixture(); chromeos::FakeSessionManagerClient* fake_session_manager_client = new chromeos::FakeSessionManagerClient; @@ -162,11 +162,11 @@ void PlatformKeysTestBase::SetUpOnMainThread() { loop.Run(); } - ExtensionApiTest::SetUpOnMainThread(); + extensions::ExtensionApiTest::SetUpOnMainThread(); } void PlatformKeysTestBase::TearDownOnMainThread() { - ExtensionApiTest::TearDownOnMainThread(); + extensions::ExtensionApiTest::TearDownOnMainThread(); if (system_token_status() == SystemTokenStatus::EXISTS) { base::RunLoop loop; diff --git a/chromium/chrome/browser/extensions/api/platform_keys/platform_keys_test_base.h b/chromium/chrome/browser/extensions/api/platform_keys/platform_keys_test_base.h index 01f5ff06467..75f525973bd 100644 --- a/chromium/chrome/browser/extensions/api/platform_keys/platform_keys_test_base.h +++ b/chromium/chrome/browser/extensions/api/platform_keys/platform_keys_test_base.h @@ -11,8 +11,8 @@ #include "chrome/browser/chromeos/login/test/https_forwarder.h" #include "chrome/browser/chromeos/policy/device_policy_cros_browser_test.h" #include "chrome/browser/extensions/extension_apitest.h" +#include "components/account_id/account_id.h" #include "components/policy/core/common/mock_configuration_policy_provider.h" -#include "components/signin/core/account_id/account_id.h" #include "google_apis/gaia/fake_gaia.h" namespace crypto { @@ -23,7 +23,7 @@ class ScopedTestSystemNSSKeySlot; // availability, device enrollment status, user affiliation and user policy. // Every test case is supposed to have a PRE_ test case which must call // PlatformKeysTestBase::RunPreTest. -class PlatformKeysTestBase : public ExtensionApiTest { +class PlatformKeysTestBase : public extensions::ExtensionApiTest { public: enum class SystemTokenStatus { EXISTS, DOES_NOT_EXIST }; diff --git a/chromium/chrome/browser/extensions/api/preference/preference_api.cc b/chromium/chrome/browser/extensions/api/preference/preference_api.cc index fe98bbb17a7..8eba4e71b44 100644 --- a/chromium/chrome/browser/extensions/api/preference/preference_api.cc +++ b/chromium/chrome/browser/extensions/api/preference/preference_api.cc @@ -127,7 +127,6 @@ const PrefMappingEntry kPrefMapping[] = { APIPermission::kPrivacy, APIPermission::kPrivacy}, {"translationServiceEnabled", prefs::kOfferTranslateEnabled, APIPermission::kPrivacy, APIPermission::kPrivacy}, -#if BUILDFLAG(ENABLE_WEBRTC) // webRTCMultipleRoutesEnabled and webRTCNonProxiedUdpEnabled have been // replaced by webRTCIPHandlingPolicy. Leaving it for backward // compatibility. TODO(guoweis): Remove this in M50. @@ -139,7 +138,6 @@ const PrefMappingEntry kPrefMapping[] = { APIPermission::kPrivacy, APIPermission::kPrivacy}, {"webRTCUDPPortRange", prefs::kWebRTCUDPPortRange, APIPermission::kPrivacy, APIPermission::kPrivacy}, -#endif // accessibilityFeatures.animationPolicy is available for // all platforms but the others from accessibilityFeatures // is only available for OS_CHROMEOS. diff --git a/chromium/chrome/browser/extensions/api/preference/preference_apitest.cc b/chromium/chrome/browser/extensions/api/preference/preference_apitest.cc index 17b0bfde383..1c25420c612 100644 --- a/chromium/chrome/browser/extensions/api/preference/preference_apitest.cc +++ b/chromium/chrome/browser/extensions/api/preference/preference_apitest.cc @@ -35,7 +35,7 @@ #include "extensions/test/result_catcher.h" #include "media/media_buildflags.h" -class ExtensionPreferenceApiTest : public ExtensionApiTest { +class ExtensionPreferenceApiTest : public extensions::ExtensionApiTest { protected: ExtensionPreferenceApiTest() : profile_(NULL) {} @@ -80,7 +80,7 @@ class ExtensionPreferenceApiTest : public ExtensionApiTest { } void SetUpOnMainThread() override { - ExtensionApiTest::SetUpOnMainThread(); + extensions::ExtensionApiTest::SetUpOnMainThread(); // The browser might get closed later (and therefore be destroyed), so we // save the profile. @@ -101,7 +101,7 @@ class ExtensionPreferenceApiTest : public ExtensionApiTest { base::Unretained(&keep_alive_), nullptr)); content::RunAllPendingInMessageLoop(); - ExtensionApiTest::TearDownOnMainThread(); + extensions::ExtensionApiTest::TearDownOnMainThread(); } Profile* profile_; @@ -127,12 +127,10 @@ IN_PROC_BROWSER_TEST_F(ExtensionPreferenceApiTest, MAYBE_Standard) { prefs->SetBoolean(password_manager::prefs::kCredentialsEnableService, false); prefs->SetBoolean(prefs::kSafeBrowsingEnabled, false); prefs->SetBoolean(prefs::kSearchSuggestEnabled, false); -#if BUILDFLAG(ENABLE_WEBRTC) prefs->SetBoolean(prefs::kWebRTCMultipleRoutesEnabled, false); prefs->SetBoolean(prefs::kWebRTCNonProxiedUdpEnabled, false); prefs->SetString(prefs::kWebRTCIPHandlingPolicy, content::kWebRTCIPHandlingDefaultPublicInterfaceOnly); -#endif const char kExtensionPath[] = "preference/standard"; diff --git a/chromium/chrome/browser/extensions/api/processes/processes_api.cc b/chromium/chrome/browser/extensions/api/processes/processes_api.cc index 6aa8242a882..84d72154ca7 100644 --- a/chromium/chrome/browser/extensions/api/processes/processes_api.cc +++ b/chromium/chrome/browser/extensions/api/processes/processes_api.cc @@ -500,7 +500,8 @@ ExtensionFunction::ResponseAction ProcessesTerminateFunction::Run() { auto* render_process_host = content::RenderProcessHost::FromID(child_process_host_id_); if (render_process_host) - return RespondNow(TerminateIfAllowed(render_process_host->GetHandle())); + return RespondNow( + TerminateIfAllowed(render_process_host->GetProcess().Handle())); // This could be a non-renderer child process like a plugin or a nacl // process. Try to get its handle from the BrowserChildProcessHost on the diff --git a/chromium/chrome/browser/extensions/api/processes/processes_apitest.cc b/chromium/chrome/browser/extensions/api/processes/processes_apitest.cc index da8e064fa21..c470ed46677 100644 --- a/chromium/chrome/browser/extensions/api/processes/processes_apitest.cc +++ b/chromium/chrome/browser/extensions/api/processes/processes_apitest.cc @@ -13,7 +13,7 @@ #include "extensions/common/switches.h" #include "extensions/test/extension_test_message_listener.h" -class ProcessesApiTest : public ExtensionApiTest { +class ProcessesApiTest : public extensions::ExtensionApiTest { public: ProcessesApiTest() {} ~ProcessesApiTest() override {} diff --git a/chromium/chrome/browser/extensions/api/resources_private/resources_private_apitest.cc b/chromium/chrome/browser/extensions/api/resources_private/resources_private_apitest.cc index 9b8b16c18f6..bddf8cd1419 100644 --- a/chromium/chrome/browser/extensions/api/resources_private/resources_private_apitest.cc +++ b/chromium/chrome/browser/extensions/api/resources_private/resources_private_apitest.cc @@ -5,13 +5,7 @@ #include "base/macros.h" #include "chrome/browser/extensions/extension_apitest.h" -class ResourcesPrivateApiTest : public ExtensionApiTest { - public: - ResourcesPrivateApiTest() {} - - private: - DISALLOW_COPY_AND_ASSIGN(ResourcesPrivateApiTest); -}; +using ResourcesPrivateApiTest = extensions::ExtensionApiTest; IN_PROC_BROWSER_TEST_F(ResourcesPrivateApiTest, GetStrings) { ASSERT_TRUE(RunComponentExtensionTest("resources_private/get_strings")); diff --git a/chromium/chrome/browser/extensions/api/runtime/chrome_runtime_api_delegate.cc b/chromium/chrome/browser/extensions/api/runtime/chrome_runtime_api_delegate.cc index 40364179f40..b30736cadbe 100644 --- a/chromium/chrome/browser/extensions/api/runtime/chrome_runtime_api_delegate.cc +++ b/chromium/chrome/browser/extensions/api/runtime/chrome_runtime_api_delegate.cc @@ -283,6 +283,10 @@ bool ChromeRuntimeAPIDelegate::GetPlatformInfo(PlatformInfo* info) { info->arch = extensions::api::runtime::PLATFORM_ARCH_X86_32; } else if (strcmp(arch, "x64") == 0) { info->arch = extensions::api::runtime::PLATFORM_ARCH_X86_64; + } else if (strcmp(arch, "mipsel") == 0) { + info->arch = extensions::api::runtime::PLATFORM_ARCH_MIPS; + } else if (strcmp(arch, "mips64el") == 0) { + info->arch = extensions::api::runtime::PLATFORM_ARCH_MIPS64; } else { NOTREACHED(); return false; @@ -295,6 +299,10 @@ bool ChromeRuntimeAPIDelegate::GetPlatformInfo(PlatformInfo* info) { info->nacl_arch = extensions::api::runtime::PLATFORM_NACL_ARCH_X86_32; } else if (strcmp(nacl_arch, "x86-64") == 0) { info->nacl_arch = extensions::api::runtime::PLATFORM_NACL_ARCH_X86_64; + } else if (strcmp(nacl_arch, "mips32") == 0) { + info->nacl_arch = extensions::api::runtime::PLATFORM_NACL_ARCH_MIPS; + } else if (strcmp(nacl_arch, "mips64") == 0) { + info->nacl_arch = extensions::api::runtime::PLATFORM_NACL_ARCH_MIPS64; } else { NOTREACHED(); return false; diff --git a/chromium/chrome/browser/extensions/api/runtime/runtime_apitest.cc b/chromium/chrome/browser/extensions/api/runtime/runtime_apitest.cc index a1f7840198a..b26ef11c2df 100644 --- a/chromium/chrome/browser/extensions/api/runtime/runtime_apitest.cc +++ b/chromium/chrome/browser/extensions/api/runtime/runtime_apitest.cc @@ -20,6 +20,8 @@ #include "net/test/embedded_test_server/embedded_test_server.h" #include "url/url_constants.h" +namespace extensions { + // Tests the privileged components of chrome.runtime. IN_PROC_BROWSER_TEST_F(ExtensionApiTest, ChromeRuntimePrivileged) { ASSERT_TRUE(RunExtensionTest("runtime/privileged")) << message_; @@ -48,8 +50,6 @@ IN_PROC_BROWSER_TEST_F(ExtensionApiTest, ChromeRuntimeUninstallURL) { ASSERT_TRUE(RunExtensionTest("runtime/uninstall_url")) << message_; } -namespace extensions { - namespace { const char kUninstallUrl[] = "http://www.google.com/"; diff --git a/chromium/chrome/browser/extensions/api/safe_browsing_private/OWNERS b/chromium/chrome/browser/extensions/api/safe_browsing_private/OWNERS new file mode 100644 index 00000000000..50851251692 --- /dev/null +++ b/chromium/chrome/browser/extensions/api/safe_browsing_private/OWNERS @@ -0,0 +1,3 @@ +jialiul@chromium.org +nparker@chromium.org +vakh@chromium.org diff --git a/chromium/chrome/browser/extensions/api/safe_browsing_private/safe_browsing_private_event_router.cc b/chromium/chrome/browser/extensions/api/safe_browsing_private/safe_browsing_private_event_router.cc new file mode 100644 index 00000000000..6ffd453df0d --- /dev/null +++ b/chromium/chrome/browser/extensions/api/safe_browsing_private/safe_browsing_private_event_router.cc @@ -0,0 +1,143 @@ +// Copyright 2018 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#include "chrome/browser/extensions/api/safe_browsing_private/safe_browsing_private_event_router.h" + +#include "base/strings/string_number_conversions.h" +#include "chrome/browser/profiles/profile.h" +#include "chrome/common/extensions/api/safe_browsing_private.h" +#include "content/public/browser/browser_context.h" +#include "extensions/browser/event_router.h" +#include "url/gurl.h" + +namespace extensions { + +SafeBrowsingPrivateEventRouter::SafeBrowsingPrivateEventRouter( + content::BrowserContext* context) + : context_(context), event_router_(nullptr) { + event_router_ = EventRouter::Get(context_); +} + +SafeBrowsingPrivateEventRouter::~SafeBrowsingPrivateEventRouter() {} + +void SafeBrowsingPrivateEventRouter::OnPolicySpecifiedPasswordReuseDetected( + const GURL& url, + const std::string& user_name, + bool is_phishing_url) { + // |event_router_| can be null in tests. + if (!event_router_) + return; + + api::safe_browsing_private::PolicySpecifiedPasswordReuse params; + params.url = url.spec(); + params.user_name = user_name; + params.is_phishing_url = is_phishing_url; + + auto event_value = std::make_unique<base::ListValue>(); + event_value->Append(params.ToValue()); + + auto extension_event = std::make_unique<Event>( + events::SAFE_BROWSING_PRIVATE_ON_POLICY_SPECIFIED_PASSWORD_REUSE_DETECTED, + api::safe_browsing_private::OnPolicySpecifiedPasswordReuseDetected:: + kEventName, + std::move(event_value)); + event_router_->BroadcastEvent(std::move(extension_event)); +} + +void SafeBrowsingPrivateEventRouter::OnPolicySpecifiedPasswordChanged( + const std::string& user_name) { + // |event_router_| can be null in tests. + if (!event_router_) + return; + + auto event_value = std::make_unique<base::ListValue>(); + event_value->Append(std::make_unique<base::Value>(user_name)); + auto extension_event = std::make_unique<Event>( + events::SAFE_BROWSING_PRIVATE_ON_POLICY_SPECIFIED_PASSWORD_CHANGED, + api::safe_browsing_private::OnPolicySpecifiedPasswordChanged::kEventName, + std::move(event_value)); + event_router_->BroadcastEvent(std::move(extension_event)); +} + +void SafeBrowsingPrivateEventRouter::OnDangerousDownloadOpened( + const GURL& url, + const std::string& file_name, + const std::string& download_digest_sha256, + const std::string& user_name) { + // |event_router_| can be null in tests. + if (!event_router_) + return; + + api::safe_browsing_private::DangerousDownloadInfo params; + params.url = url.spec(); + params.file_name = file_name; + params.download_digest_sha256 = download_digest_sha256; + params.user_name = user_name; + auto event_value = std::make_unique<base::ListValue>(); + event_value->Append(params.ToValue()); + + auto extension_event = std::make_unique<Event>( + events::SAFE_BROWSING_PRIVATE_ON_DANGEROUS_DOWNLOAD_OPENED, + api::safe_browsing_private::OnDangerousDownloadOpened::kEventName, + std::move(event_value)); + event_router_->BroadcastEvent(std::move(extension_event)); +} + +void SafeBrowsingPrivateEventRouter::OnSecurityInterstitialShown( + const GURL& url, + const std::string& reason, + int net_error_code, + const std::string& user_name) { + // |event_router_| can be null in tests. + if (!event_router_) + return; + + api::safe_browsing_private::InterstitialInfo params; + params.url = url.spec(); + params.reason = reason; + if (net_error_code < 0) { + params.net_error_code = + std::make_unique<std::string>(base::NumberToString(net_error_code)); + } + params.user_name = user_name; + + auto event_value = std::make_unique<base::ListValue>(); + event_value->Append(params.ToValue()); + + auto extension_event = std::make_unique<Event>( + events::SAFE_BROWSING_PRIVATE_ON_SECURITY_INTERSTITIAL_SHOWN, + api::safe_browsing_private::OnSecurityInterstitialShown::kEventName, + std::move(event_value)); + event_router_->BroadcastEvent(std::move(extension_event)); +} + +void SafeBrowsingPrivateEventRouter::OnSecurityInterstitialProceeded( + const GURL& url, + const std::string& reason, + int net_error_code, + const std::string& user_name) { + // |event_router_| can be null in tests. + if (!event_router_) + return; + + api::safe_browsing_private::InterstitialInfo params; + params.url = url.spec(); + params.reason = reason; + if (net_error_code < 0) { + params.net_error_code = + std::make_unique<std::string>(base::NumberToString(net_error_code)); + } + params.user_name = user_name; + + auto event_value = std::make_unique<base::ListValue>(); + event_value->Append(params.ToValue()); + + auto extension_event = std::make_unique<Event>( + events::SAFE_BROWSING_PRIVATE_ON_SECURITY_INTERSTITIAL_PROCEEDED, + api::safe_browsing_private::OnSecurityInterstitialProceeded::kEventName, + std::move(event_value)); + event_router_->BroadcastEvent(std::move(extension_event)); +} + +} // namespace extensions diff --git a/chromium/chrome/browser/extensions/api/safe_browsing_private/safe_browsing_private_event_router.h b/chromium/chrome/browser/extensions/api/safe_browsing_private/safe_browsing_private_event_router.h new file mode 100644 index 00000000000..e5267e9dce4 --- /dev/null +++ b/chromium/chrome/browser/extensions/api/safe_browsing_private/safe_browsing_private_event_router.h @@ -0,0 +1,68 @@ +// Copyright 2018 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#ifndef CHROME_BROWSER_EXTENSIONS_API_SAFE_BROWSING_PRIVATE_SAFE_BROWSING_PRIVATE_EVENT_ROUTER_H_ +#define CHROME_BROWSER_EXTENSIONS_API_SAFE_BROWSING_PRIVATE_SAFE_BROWSING_PRIVATE_EVENT_ROUTER_H_ + +#include <string> + +#include "base/macros.h" +#include "components/keyed_service/core/keyed_service.h" + +namespace content { +class BrowserContext; +} + +namespace extensions { +class EventRouter; +} + +class GURL; + +namespace extensions { + +// An event router that observes Safe Browsing events and notifies listeners. +class SafeBrowsingPrivateEventRouter : public KeyedService { + public: + explicit SafeBrowsingPrivateEventRouter(content::BrowserContext* context); + + ~SafeBrowsingPrivateEventRouter() override; + + // Notifies listeners that the user reused a protected password. + void OnPolicySpecifiedPasswordReuseDetected(const GURL& url, + const std::string& user_name, + bool is_phishing_url); + + // Notifies listeners that the user changed the password associated with + // |user_name|. + void OnPolicySpecifiedPasswordChanged(const std::string& user_name); + + // Notifies listeners that the user just opened a dangerous download. + void OnDangerousDownloadOpened(const GURL& url, + const std::string& file_name, + const std::string& download_digest_sha256, + const std::string& user_name); + + // Notifies listeners that the user saw a security interstitial. + void OnSecurityInterstitialShown(const GURL& url, + const std::string& reason, + int net_error_code, + const std::string& user_name); + + // Notifies listeners that the user clicked-through a security interstitial. + void OnSecurityInterstitialProceeded(const GURL& url, + const std::string& reason, + int net_error_code, + const std::string& user_name); + + private: + content::BrowserContext* context_; + EventRouter* event_router_; + + DISALLOW_COPY_AND_ASSIGN(SafeBrowsingPrivateEventRouter); +}; + +} // namespace extensions + +#endif // CHROME_BROWSER_EXTENSIONS_API_SAFE_BROWSING_PRIVATE_SAFE_BROWSING_PRIVATE_EVENT_ROUTER_H_ diff --git a/chromium/chrome/browser/extensions/api/safe_browsing_private/safe_browsing_private_event_router_factory.cc b/chromium/chrome/browser/extensions/api/safe_browsing_private/safe_browsing_private_event_router_factory.cc new file mode 100644 index 00000000000..f9cc8435642 --- /dev/null +++ b/chromium/chrome/browser/extensions/api/safe_browsing_private/safe_browsing_private_event_router_factory.cc @@ -0,0 +1,59 @@ +// Copyright 2018 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#include "chrome/browser/extensions/api/safe_browsing_private/safe_browsing_private_event_router_factory.h" + +#include "chrome/browser/extensions/api/safe_browsing_private/safe_browsing_private_event_router.h" +#include "components/keyed_service/content/browser_context_dependency_manager.h" +#include "content/public/browser/browser_context.h" +#include "extensions/browser/extension_system_provider.h" +#include "extensions/browser/extensions_browser_client.h" + +namespace extensions { + +// static +SafeBrowsingPrivateEventRouter* +SafeBrowsingPrivateEventRouterFactory::GetForProfile( + content::BrowserContext* context) { + return static_cast<SafeBrowsingPrivateEventRouter*>( + GetInstance()->GetServiceForBrowserContext(context, true)); +} + +// static +SafeBrowsingPrivateEventRouterFactory* +SafeBrowsingPrivateEventRouterFactory::GetInstance() { + return base::Singleton<SafeBrowsingPrivateEventRouterFactory>::get(); +} + +SafeBrowsingPrivateEventRouterFactory::SafeBrowsingPrivateEventRouterFactory() + : BrowserContextKeyedServiceFactory( + "SafeBrowsingPrivateEventRouter", + BrowserContextDependencyManager::GetInstance()) { + DependsOn(ExtensionsBrowserClient::Get()->GetExtensionSystemFactory()); +} + +SafeBrowsingPrivateEventRouterFactory:: + ~SafeBrowsingPrivateEventRouterFactory() {} + +KeyedService* SafeBrowsingPrivateEventRouterFactory::BuildServiceInstanceFor( + content::BrowserContext* context) const { + return new SafeBrowsingPrivateEventRouter(context); +} + +content::BrowserContext* +SafeBrowsingPrivateEventRouterFactory::GetBrowserContextToUse( + content::BrowserContext* context) const { + return ExtensionsBrowserClient::Get()->GetOriginalContext(context); +} + +bool SafeBrowsingPrivateEventRouterFactory::ServiceIsCreatedWithBrowserContext() + const { + return true; +} + +bool SafeBrowsingPrivateEventRouterFactory::ServiceIsNULLWhileTesting() const { + return true; +} + +} // namespace extensions diff --git a/chromium/chrome/browser/extensions/api/safe_browsing_private/safe_browsing_private_event_router_factory.h b/chromium/chrome/browser/extensions/api/safe_browsing_private/safe_browsing_private_event_router_factory.h new file mode 100644 index 00000000000..670735961dc --- /dev/null +++ b/chromium/chrome/browser/extensions/api/safe_browsing_private/safe_browsing_private_event_router_factory.h @@ -0,0 +1,53 @@ +// Copyright 2018 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#ifndef CHROME_BROWSER_EXTENSIONS_API_SAFE_BROWSING_PRIVATE_SAFE_BROWSING_PRIVATE_EVENT_ROUTER_FACTORY_H_ +#define CHROME_BROWSER_EXTENSIONS_API_SAFE_BROWSING_PRIVATE_SAFE_BROWSING_PRIVATE_EVENT_ROUTER_FACTORY_H_ + +#include "base/macros.h" +#include "base/memory/singleton.h" +#include "components/keyed_service/content/browser_context_keyed_service_factory.h" + +namespace extensions { + +class SafeBrowsingPrivateEventRouter; + +// This is a factory class used by the BrowserContextDependencyManager +// to instantiate the safeBrowsingPrivate event router per profile (since the +// extension event router is per profile). +class SafeBrowsingPrivateEventRouterFactory + : public BrowserContextKeyedServiceFactory { + public: + // Returns the SafeBrowsingPrivateEventRouter for |profile|, creating it if + // it is not yet created. + static SafeBrowsingPrivateEventRouter* GetForProfile( + content::BrowserContext* context); + + // Returns the SafeBrowsingPrivateEventRouterFactory instance. + static SafeBrowsingPrivateEventRouterFactory* GetInstance(); + + protected: + // BrowserContextKeyedBaseFactory overrides: + content::BrowserContext* GetBrowserContextToUse( + content::BrowserContext* context) const override; + bool ServiceIsCreatedWithBrowserContext() const override; + bool ServiceIsNULLWhileTesting() const override; + + private: + friend struct base::DefaultSingletonTraits< + SafeBrowsingPrivateEventRouterFactory>; + + SafeBrowsingPrivateEventRouterFactory(); + ~SafeBrowsingPrivateEventRouterFactory() override; + + // BrowserContextKeyedServiceFactory: + KeyedService* BuildServiceInstanceFor( + content::BrowserContext* profile) const override; + + DISALLOW_COPY_AND_ASSIGN(SafeBrowsingPrivateEventRouterFactory); +}; + +} // namespace extensions + +#endif // CHROME_BROWSER_EXTENSIONS_API_SAFE_BROWSING_PRIVATE_SAFE_BROWSING_PRIVATE_EVENT_ROUTER_FACTORY_H_ diff --git a/chromium/chrome/browser/extensions/api/safe_browsing_private/safe_browsing_private_event_router_unittest.cc b/chromium/chrome/browser/extensions/api/safe_browsing_private/safe_browsing_private_event_router_unittest.cc new file mode 100644 index 00000000000..e8dff26b8fa --- /dev/null +++ b/chromium/chrome/browser/extensions/api/safe_browsing_private/safe_browsing_private_event_router_unittest.cc @@ -0,0 +1,182 @@ +// Copyright 2018 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. +#include "chrome/browser/extensions/api/safe_browsing_private/safe_browsing_private_event_router.h" + +#include "base/strings/utf_string_conversions.h" +#include "base/test/mock_callback.h" +#include "base/values.h" +#include "chrome/browser/extensions/api/safe_browsing_private/safe_browsing_private_event_router_factory.h" +#include "chrome/common/extensions/api/safe_browsing_private.h" +#include "chrome/test/base/testing_profile.h" +#include "content/public/test/test_browser_thread_bundle.h" +#include "extensions/browser/test_event_router.h" +#include "testing/gtest/include/gtest/gtest.h" + +namespace extensions { + +class SafeBrowsingEventObserver : public TestEventRouter::EventObserver { + public: + // The observer will only listen to events with the |event_name|. + explicit SafeBrowsingEventObserver(const std::string& event_name) + : event_name_(event_name) {} + + ~SafeBrowsingEventObserver() override = default; + + // Removes |event_args_| from |*this| and returns them. + base::Value PassEventArgs() { return std::move(event_args_); } + + // extensions::TestEventRouter::EventObserver: + void OnBroadcastEvent(const extensions::Event& event) override { + if (event.event_name == event_name_) { + event_args_ = event.event_args->Clone(); + } + } + + private: + // The name of the observed event. + const std::string event_name_; + + // The arguments passed for the last observed event. + base::Value event_args_; + + DISALLOW_COPY_AND_ASSIGN(SafeBrowsingEventObserver); +}; + +std::unique_ptr<KeyedService> BuildSafeBrowsingPrivateEventRouter( + content::BrowserContext* context) { + return std::unique_ptr<KeyedService>( + new SafeBrowsingPrivateEventRouter(context)); +} + +class SafeBrowsingPrivateEventRouterTest : public testing::Test { + public: + SafeBrowsingPrivateEventRouterTest() = default; + ~SafeBrowsingPrivateEventRouterTest() override = default; + + void TriggerOnPolicySpecifiedPasswordReuseDetectedEvent() { + SafeBrowsingPrivateEventRouterFactory::GetForProfile(&profile_) + ->OnPolicySpecifiedPasswordReuseDetected(GURL("https://phishing.com/"), + "user_name_1", + /*is_phishing_url*/ true); + } + + void TriggerOnPolicySpecifiedPasswordChangedEvent() { + SafeBrowsingPrivateEventRouterFactory::GetForProfile(&profile_) + ->OnPolicySpecifiedPasswordChanged("user_name_2"); + } + + void TriggerOnDangerousDownloadOpenedEvent() { + SafeBrowsingPrivateEventRouterFactory::GetForProfile(&profile_) + ->OnDangerousDownloadOpened(GURL("https://evil.com/malware.exe"), + "/path/to/malware.exe", + "sha256_or_malware_exe", "user_name"); + } + + void TriggerOnSecurityInterstitialShownEvent() { + SafeBrowsingPrivateEventRouterFactory::GetForProfile(&profile_) + ->OnSecurityInterstitialShown(GURL("https://phishing.com/"), "PHISHING", + 0, "user_name"); + } + + void TriggerOnSecurityInterstitialProceededEvent() { + SafeBrowsingPrivateEventRouterFactory::GetForProfile(&profile_) + ->OnSecurityInterstitialProceeded(GURL("https://phishing.com/"), + "PHISHING", -201, "user_name"); + } + + void SetUpRouters() { + event_router_ = extensions::CreateAndUseTestEventRouter(&profile_); + SafeBrowsingPrivateEventRouterFactory::GetInstance()->SetTestingFactory( + &profile_, BuildSafeBrowsingPrivateEventRouter); + } + + protected: + content::TestBrowserThreadBundle thread_bundle_; + TestingProfile profile_; + extensions::TestEventRouter* event_router_ = nullptr; + + private: + DISALLOW_COPY_AND_ASSIGN(SafeBrowsingPrivateEventRouterTest); +}; + +TEST_F(SafeBrowsingPrivateEventRouterTest, TestOnReuseDetected) { + SetUpRouters(); + SafeBrowsingEventObserver event_observer( + api::safe_browsing_private::OnPolicySpecifiedPasswordReuseDetected:: + kEventName); + event_router_->AddEventObserver(&event_observer); + + TriggerOnPolicySpecifiedPasswordReuseDetectedEvent(); + base::RunLoop().RunUntilIdle(); + + auto captured_args = event_observer.PassEventArgs().GetList()[0].Clone(); + EXPECT_EQ("https://phishing.com/", captured_args.FindKey("url")->GetString()); + EXPECT_EQ("user_name_1", captured_args.FindKey("userName")->GetString()); +} + +TEST_F(SafeBrowsingPrivateEventRouterTest, TestOnPasswordChanged) { + SetUpRouters(); + SafeBrowsingEventObserver event_observer( + api::safe_browsing_private::OnPolicySpecifiedPasswordChanged::kEventName); + event_router_->AddEventObserver(&event_observer); + + TriggerOnPolicySpecifiedPasswordChangedEvent(); + base::RunLoop().RunUntilIdle(); + + auto captured_args = event_observer.PassEventArgs().GetList()[0].Clone(); + EXPECT_EQ("user_name_2", captured_args.GetString()); +} + +TEST_F(SafeBrowsingPrivateEventRouterTest, TestOnDangerousDownloadOpened) { + SetUpRouters(); + SafeBrowsingEventObserver event_observer( + api::safe_browsing_private::OnDangerousDownloadOpened::kEventName); + event_router_->AddEventObserver(&event_observer); + + TriggerOnDangerousDownloadOpenedEvent(); + base::RunLoop().RunUntilIdle(); + + auto captured_args = event_observer.PassEventArgs().GetList()[0].Clone(); + EXPECT_EQ("https://evil.com/malware.exe", + captured_args.FindKey("url")->GetString()); + EXPECT_EQ("/path/to/malware.exe", + captured_args.FindKey("fileName")->GetString()); + EXPECT_EQ("user_name", captured_args.FindKey("userName")->GetString()); + EXPECT_EQ("sha256_or_malware_exe", + captured_args.FindKey("downloadDigestSha256")->GetString()); +} + +TEST_F(SafeBrowsingPrivateEventRouterTest, + TestOnSecurityInterstitialProceeded) { + SetUpRouters(); + SafeBrowsingEventObserver event_observer( + api::safe_browsing_private::OnSecurityInterstitialProceeded::kEventName); + event_router_->AddEventObserver(&event_observer); + + TriggerOnSecurityInterstitialProceededEvent(); + base::RunLoop().RunUntilIdle(); + + auto captured_args = event_observer.PassEventArgs().GetList()[0].Clone(); + EXPECT_EQ("https://phishing.com/", captured_args.FindKey("url")->GetString()); + EXPECT_EQ("PHISHING", captured_args.FindKey("reason")->GetString()); + EXPECT_EQ("-201", captured_args.FindKey("netErrorCode")->GetString()); + EXPECT_EQ("user_name", captured_args.FindKey("userName")->GetString()); +} + +TEST_F(SafeBrowsingPrivateEventRouterTest, TestOnSecurityInterstitialShown) { + SetUpRouters(); + SafeBrowsingEventObserver event_observer( + api::safe_browsing_private::OnSecurityInterstitialShown::kEventName); + event_router_->AddEventObserver(&event_observer); + + TriggerOnSecurityInterstitialShownEvent(); + base::RunLoop().RunUntilIdle(); + + auto captured_args = event_observer.PassEventArgs().GetList()[0].Clone(); + EXPECT_EQ("https://phishing.com/", captured_args.FindKey("url")->GetString()); + EXPECT_EQ("PHISHING", captured_args.FindKey("reason")->GetString()); + EXPECT_FALSE(captured_args.FindKey("netErrorCode")); + EXPECT_EQ("user_name", captured_args.FindKey("userName")->GetString()); +} +} // namespace extensions diff --git a/chromium/chrome/browser/extensions/api/screenlock_private/screenlock_private_apitest.cc b/chromium/chrome/browser/extensions/api/screenlock_private/screenlock_private_apitest.cc index 01f98441b18..8b1f3765e78 100644 --- a/chromium/chrome/browser/extensions/api/screenlock_private/screenlock_private_apitest.cc +++ b/chromium/chrome/browser/extensions/api/screenlock_private/screenlock_private_apitest.cc @@ -15,19 +15,21 @@ #include "chrome/browser/profiles/profile_attributes_entry.h" #include "chrome/browser/profiles/profile_attributes_storage.h" #include "chrome/browser/profiles/profile_manager.h" +#include "chrome/browser/signin/identity_manager_factory.h" +#include "chrome/browser/signin/profile_oauth2_token_service_factory.h" #include "chrome/browser/signin/signin_manager_factory.h" #include "chromeos/components/proximity_auth/screenlock_bridge.h" -#include "components/signin/core/browser/signin_manager.h" #include "content/public/browser/notification_service.h" #include "extensions/browser/api/test/test_api.h" #include "extensions/browser/notification_types.h" #include "extensions/common/switches.h" +#include "services/identity/public/cpp/identity_manager.h" +#include "services/identity/public/cpp/identity_test_utils.h" namespace extensions { namespace { -const char kTestGaiaId[] = "gaia-id-testuser@gmail.com"; const char kAttemptClickAuthMessage[] = "attemptClickAuth"; const char kTestExtensionId[] = "lkegkdgachcnekllcdfkijonogckdnjo"; const char kTestUser[] = "testuser@gmail.com"; @@ -50,14 +52,14 @@ class ScreenlockPrivateApiTest : public ExtensionApiTest, } void SetUpOnMainThread() override { - SigninManagerFactory::GetForProfile(profile()) - ->SetAuthenticatedAccountInfo(kTestGaiaId, kTestUser); - ProfileAttributesEntry* entry; - ASSERT_TRUE(g_browser_process->profile_manager()-> - GetProfileAttributesStorage(). - GetProfileAttributesWithPath(profile()->GetPath(), &entry)); - entry->SetAuthInfo( - kTestGaiaId, base::UTF8ToUTF16(test_account_id_.GetUserEmail())); + identity::IdentityManager* identity_manager = + IdentityManagerFactory::GetForProfile(profile()); + identity::MakePrimaryAccountAvailable( + SigninManagerFactory::GetForProfile(profile()), + ProfileOAuth2TokenServiceFactory::GetForProfile(profile()), + identity_manager, kTestUser); + test_account_id_ = AccountId::FromUserEmailGaiaId( + kTestUser, identity_manager->GetPrimaryAccountInfo().gaia); registrar_.Add(this, extensions::NOTIFICATION_EXTENSION_TEST_MESSAGE, content::NotificationService::AllSources()); @@ -91,8 +93,7 @@ class ScreenlockPrivateApiTest : public ExtensionApiTest, } private: - const AccountId test_account_id_ = - AccountId::FromUserEmailGaiaId(kTestUser, kTestGaiaId); + AccountId test_account_id_; content::NotificationRegistrar registrar_; DISALLOW_COPY_AND_ASSIGN(ScreenlockPrivateApiTest); diff --git a/chromium/chrome/browser/extensions/api/sessions/sessions_apitest.cc b/chromium/chrome/browser/extensions/api/sessions/sessions_apitest.cc index 1cc32e82a62..22bbf3acca1 100644 --- a/chromium/chrome/browser/extensions/api/sessions/sessions_apitest.cc +++ b/chromium/chrome/browser/extensions/api/sessions/sessions_apitest.cc @@ -205,7 +205,7 @@ std::unique_ptr<KeyedService> ExtensionSessionsTest::BuildProfileSyncService( void ExtensionSessionsTest::CreateTestProfileSyncService() { ProfileManager* profile_manager = g_browser_process->profile_manager(); base::FilePath path; - PathService::Get(chrome::DIR_USER_DATA, &path); + base::PathService::Get(chrome::DIR_USER_DATA, &path); path = path.AppendASCII("test_profile"); if (!base::PathExists(path)) CHECK(base::CreateDirectory(path)); diff --git a/chromium/chrome/browser/extensions/api/settings_private/prefs_util.cc b/chromium/chrome/browser/extensions/api/settings_private/prefs_util.cc index 47413054d45..70c8081978e 100644 --- a/chromium/chrome/browser/extensions/api/settings_private/prefs_util.cc +++ b/chromium/chrome/browser/extensions/api/settings_private/prefs_util.cc @@ -17,9 +17,11 @@ #include "components/autofill/core/common/autofill_pref_names.h" #include "components/bookmarks/common/bookmark_pref_names.h" #include "components/browsing_data/core/pref_names.h" +#include "components/component_updater/pref_names.h" #include "components/content_settings/core/common/pref_names.h" #include "components/drive/drive_pref_names.h" #include "components/password_manager/core/common/password_manager_pref_names.h" +#include "components/payments/core/payment_prefs.h" #include "components/prefs/pref_service.h" #include "components/proxy_config/proxy_config_pref_names.h" #include "components/safe_browsing/common/safe_browsing_prefs.h" @@ -37,6 +39,7 @@ #if defined(OS_CHROMEOS) #include "ash/public/cpp/ash_pref_names.h" // nogncheck +#include "chrome/browser/chromeos/crostini/crostini_pref_names.h" #include "chrome/browser/chromeos/ownership/owner_settings_service_chromeos.h" #include "chrome/browser/chromeos/ownership/owner_settings_service_chromeos_factory.h" #include "chrome/browser/chromeos/policy/browser_policy_connector_chromeos.h" @@ -80,6 +83,11 @@ bool IsSettingReadOnly(const std::string& pref_name) { if (pref_name == ash::prefs::kEnableAutoScreenLock) return true; #endif +#if defined(OS_WIN) + // Don't allow user to change sw_reporter preferences. + if (pref_name == prefs::kSwReporterEnabled) + return true; +#endif return false; } @@ -110,6 +118,8 @@ const PrefsUtil::TypedPrefMap& PrefsUtil::GetWhitelistedKeys() { settings_api::PrefType::PREF_TYPE_BOOLEAN; (*s_whitelist)[autofill::prefs::kAutofillCreditCardEnabled] = settings_api::PrefType::PREF_TYPE_BOOLEAN; + (*s_whitelist)[payments::kCanMakePaymentEnabled] = + settings_api::PrefType::PREF_TYPE_BOOLEAN; (*s_whitelist)[bookmarks::prefs::kShowBookmarkBar] = settings_api::PrefType::PREF_TYPE_BOOLEAN; #if defined(OS_LINUX) && !defined(OS_CHROMEOS) @@ -204,6 +214,8 @@ const PrefsUtil::TypedPrefMap& PrefsUtil::GetWhitelistedKeys() { #if defined(OS_CHROMEOS) (*s_whitelist)[::prefs::kLanguageImeMenuActivated] = settings_api::PrefType::PREF_TYPE_BOOLEAN; + (*s_whitelist)[::prefs::kAllowedLocales] = + settings_api::PrefType::PREF_TYPE_LIST; #endif // Search page. @@ -285,6 +297,8 @@ const PrefsUtil::TypedPrefMap& PrefsUtil::GetWhitelistedKeys() { settings_api::PrefType::PREF_TYPE_BOOLEAN; (*s_whitelist)[ash::prefs::kShouldAlwaysShowAccessibilityMenu] = settings_api::PrefType::PREF_TYPE_BOOLEAN; + (*s_whitelist)[ash::prefs::kAccessibilityDictationEnabled] = + settings_api::PrefType::PREF_TYPE_BOOLEAN; (*s_whitelist)[ash::prefs::kAccessibilityFocusHighlightEnabled] = settings_api::PrefType::PREF_TYPE_BOOLEAN; (*s_whitelist)[ash::prefs::kAccessibilityHighContrastEnabled] = @@ -308,6 +322,20 @@ const PrefsUtil::TypedPrefMap& PrefsUtil::GetWhitelistedKeys() { (*s_whitelist)[ash::prefs::kAccessibilityMonoAudioEnabled] = settings_api::PrefType::PREF_TYPE_BOOLEAN; + // Text to Speech. + (*s_whitelist)[::prefs::kTextToSpeechLangToVoiceName] = + settings_api::PrefType::PREF_TYPE_DICTIONARY; + (*s_whitelist)[::prefs::kTextToSpeechRate] = + settings_api::PrefType::PREF_TYPE_NUMBER; + (*s_whitelist)[::prefs::kTextToSpeechPitch] = + settings_api::PrefType::PREF_TYPE_NUMBER; + (*s_whitelist)[::prefs::kTextToSpeechVolume] = + settings_api::PrefType::PREF_TYPE_NUMBER; + + // Crostini + (*s_whitelist)[crostini::prefs::kCrostiniEnabled] = + settings_api::PrefType::PREF_TYPE_BOOLEAN; + // Android Apps. (*s_whitelist)[arc::prefs::kArcEnabled] = settings_api::PrefType::PREF_TYPE_BOOLEAN; @@ -428,6 +456,10 @@ const PrefsUtil::TypedPrefMap& PrefsUtil::GetWhitelistedKeys() { (*s_whitelist)[arc::prefs::kSmsConnectEnabled] = settings_api::PrefType::PREF_TYPE_BOOLEAN; + // Native Printing settings. + (*s_whitelist)[::prefs::kUserNativePrintersAllowed] = + settings_api::PrefType::PREF_TYPE_BOOLEAN; + #else (*s_whitelist)[::prefs::kAcceptLanguages] = settings_api::PrefType::PREF_TYPE_STRING; @@ -464,6 +496,12 @@ const PrefsUtil::TypedPrefMap& PrefsUtil::GetWhitelistedKeys() { (*s_whitelist)[::prefs::kMediaRouterMediaRemotingEnabled] = settings_api::PrefType::PREF_TYPE_BOOLEAN; +#if defined(OS_WIN) + // SwReporter settings. + (*s_whitelist)[::prefs::kSwReporterEnabled] = + settings_api::PrefType::PREF_TYPE_BOOLEAN; +#endif + return *s_whitelist; } diff --git a/chromium/chrome/browser/extensions/api/settings_private/settings_private_apitest.cc b/chromium/chrome/browser/extensions/api/settings_private/settings_private_apitest.cc index 8ebc9f6f06b..0f7d3c5e9f3 100644 --- a/chromium/chrome/browser/extensions/api/settings_private/settings_private_apitest.cc +++ b/chromium/chrome/browser/extensions/api/settings_private/settings_private_apitest.cc @@ -6,7 +6,7 @@ #include "base/command_line.h" #include "base/macros.h" -#include "base/message_loop/message_loop.h" +#include "base/message_loop/message_loop_current.h" #include "base/run_loop.h" #include "base/values.h" #include "build/build_config.h" @@ -69,7 +69,7 @@ class SettingsPrivateApiTest : public ExtensionApiTest { policy::POLICY_SOURCE_CLOUD, base::WrapUnique(new base::Value(true)), nullptr); provider_.UpdateChromePolicy(policies); - DCHECK(base::MessageLoop::current()); + DCHECK(base::MessageLoopCurrent::Get()); base::RunLoop loop; loop.RunUntilIdle(); } diff --git a/chromium/chrome/browser/extensions/api/signed_in_devices/signed_in_devices_api_unittest.cc b/chromium/chrome/browser/extensions/api/signed_in_devices/signed_in_devices_api_unittest.cc index 32d5acdee69..aaff0a6bbc8 100644 --- a/chromium/chrome/browser/extensions/api/signed_in_devices/signed_in_devices_api_unittest.cc +++ b/chromium/chrome/browser/extensions/api/signed_in_devices/signed_in_devices_api_unittest.cc @@ -141,7 +141,7 @@ class ProfileSyncServiceMockForExtensionTests public: explicit ProfileSyncServiceMockForExtensionTests(Profile* p) : ProfileSyncServiceMock(CreateProfileSyncServiceParamsForTest(p)) {} - ~ProfileSyncServiceMockForExtensionTests() {} + ~ProfileSyncServiceMockForExtensionTests() override {} MOCK_METHOD0(Shutdown, void()); MOCK_CONST_METHOD0(GetDeviceInfoTracker, DeviceInfoTracker*()); diff --git a/chromium/chrome/browser/extensions/api/socket/mock_tcp_client_socket.h b/chromium/chrome/browser/extensions/api/socket/mock_tcp_client_socket.h index 9dd6af53b29..fddad102ac6 100644 --- a/chromium/chrome/browser/extensions/api/socket/mock_tcp_client_socket.h +++ b/chromium/chrome/browser/extensions/api/socket/mock_tcp_client_socket.h @@ -5,6 +5,7 @@ #ifndef CHROME_BROWSER_EXTENSIONS_API_SOCKET_MOCK_TCP_CLIENT_SOCKET_H_ #define CHROME_BROWSER_EXTENSIONS_API_SOCKET_MOCK_TCP_CLIENT_SOCKET_H_ +#include "base/callback_helpers.h" #include "net/log/net_log_source.h" #include "net/log/net_log_with_source.h" #include "net/socket/tcp_client_socket.h" @@ -12,11 +13,29 @@ #include "testing/gmock/include/gmock/gmock.h" namespace extensions { - class MockTCPClientSocket : public net::TCPClientSocket { public: MockTCPClientSocket(); - virtual ~MockTCPClientSocket(); + ~MockTCPClientSocket() override; + + int Read(net::IOBuffer* buffer, + int bytes, + net::CompletionOnceCallback callback) override { + return Read(buffer, bytes, + base::AdaptCallbackForRepeating(std::move(callback))); + } + + int Write(net::IOBuffer* buffer, + int bytes, + net::CompletionOnceCallback callback, + const net::NetworkTrafficAnnotationTag& tag) override { + return Write(buffer, bytes, + base::AdaptCallbackForRepeating(std::move(callback)), tag); + } + + int Connect(net::CompletionOnceCallback callback) override { + return Connect(base::AdaptCallbackForRepeating(std::move(callback))); + } MOCK_METHOD3(Read, int(net::IOBuffer*, int, const net::CompletionCallback&)); MOCK_METHOD4(Write, @@ -33,8 +52,6 @@ class MockTCPClientSocket : public net::TCPClientSocket { MOCK_CONST_METHOD1(GetPeerAddress, int(net::IPEndPoint*)); MOCK_CONST_METHOD1(GetLocalAddress, int(net::IPEndPoint*)); MOCK_CONST_METHOD0(NetLog, const net::NetLogWithSource&()); - MOCK_METHOD0(SetSubresourceSpeculation, void()); - MOCK_METHOD0(SetOmniboxSpeculation, void()); MOCK_CONST_METHOD0(WasEverUsed, bool()); MOCK_CONST_METHOD0(UsingTCPFastOpen, bool()); MOCK_CONST_METHOD0(NumBytesRead, int64_t()); diff --git a/chromium/chrome/browser/extensions/api/socket/socket_apitest.cc b/chromium/chrome/browser/extensions/api/socket/socket_apitest.cc index b1710494d53..ae11686ed95 100644 --- a/chromium/chrome/browser/extensions/api/socket/socket_apitest.cc +++ b/chromium/chrome/browser/extensions/api/socket/socket_apitest.cc @@ -25,7 +25,7 @@ namespace { const char kHostname[] = "127.0.0.1"; const int kPort = 8888; -class SocketApiTest : public ExtensionApiTest { +class SocketApiTest : public extensions::ExtensionApiTest { public: SocketApiTest() : resolver_event_(base::WaitableEvent::ResetPolicy::MANUAL, @@ -33,7 +33,7 @@ class SocketApiTest : public ExtensionApiTest { resolver_creator_(new extensions::MockHostResolverCreator()) {} void SetUpOnMainThread() override { - ExtensionApiTest::SetUpOnMainThread(); + extensions::ExtensionApiTest::SetUpOnMainThread(); extensions::HostResolverWrapper::GetInstance()->SetHostResolverForTesting( resolver_creator_->CreateMockHostResolver()); } diff --git a/chromium/chrome/browser/extensions/api/socket/tcp_socket_unittest.cc b/chromium/chrome/browser/extensions/api/socket/tcp_socket_unittest.cc index 902970df9ff..6351e3d6ca2 100644 --- a/chromium/chrome/browser/extensions/api/socket/tcp_socket_unittest.cc +++ b/chromium/chrome/browser/extensions/api/socket/tcp_socket_unittest.cc @@ -4,6 +4,7 @@ #include <memory> +#include "base/callback_helpers.h" #include "base/macros.h" #include "extensions/browser/api/socket/tcp_socket.h" #include "net/base/address_list.h" @@ -29,6 +30,21 @@ class MockTCPSocket : public net::TCPClientSocket { explicit MockTCPSocket(const net::AddressList& address_list) : net::TCPClientSocket(address_list, NULL, NULL, net::NetLogSource()) {} + int Read(net::IOBuffer* buffer, + int bytes, + net::CompletionOnceCallback callback) override { + return Read(buffer, bytes, + base::AdaptCallbackForRepeating(std::move(callback))); + } + + int Write(net::IOBuffer* buffer, + int bytes, + net::CompletionOnceCallback callback, + const net::NetworkTrafficAnnotationTag& tag) override { + return Write(buffer, bytes, + base::AdaptCallbackForRepeating(std::move(callback)), tag); + } + MOCK_METHOD3(Read, int(net::IOBuffer* buf, int buf_len, const net::CompletionCallback& callback)); MOCK_METHOD4(Write, @@ -77,7 +93,7 @@ class CompleteHandler { DISALLOW_COPY_AND_ASSIGN(CompleteHandler); }; -const std::string FAKE_ID = "abcdefghijklmnopqrst"; +const char FAKE_ID[] = "abcdefghijklmnopqrst"; TEST(SocketTest, TestTCPSocketRead) { net::AddressList address_list; diff --git a/chromium/chrome/browser/extensions/api/socket/tls_socket_unittest.cc b/chromium/chrome/browser/extensions/api/socket/tls_socket_unittest.cc index d89d7300d9b..678b630744e 100644 --- a/chromium/chrome/browser/extensions/api/socket/tls_socket_unittest.cc +++ b/chromium/chrome/browser/extensions/api/socket/tls_socket_unittest.cc @@ -8,6 +8,7 @@ #include <memory> #include <utility> +#include "base/callback_helpers.h" #include "base/containers/circular_deque.h" #include "base/macros.h" #include "base/strings/string_piece.h" @@ -40,6 +41,25 @@ namespace extensions { class MockSSLClientSocket : public net::SSLClientSocket { public: MockSSLClientSocket() {} + int Read(net::IOBuffer* buffer, + int bytes, + net::CompletionOnceCallback callback) override { + return Read(buffer, bytes, + base::AdaptCallbackForRepeating(std::move(callback))); + } + + int Write(net::IOBuffer* buffer, + int bytes, + net::CompletionOnceCallback callback, + const net::NetworkTrafficAnnotationTag& tag) override { + return Write(buffer, bytes, + base::AdaptCallbackForRepeating(std::move(callback)), tag); + } + + int Connect(net::CompletionOnceCallback callback) override { + return Connect(base::AdaptCallbackForRepeating(std::move(callback))); + } + MOCK_METHOD0(Disconnect, void()); MOCK_METHOD3(Read, int(net::IOBuffer* buf, @@ -57,8 +77,6 @@ class MockSSLClientSocket : public net::SSLClientSocket { MOCK_CONST_METHOD1(GetPeerAddress, int(net::IPEndPoint*)); MOCK_CONST_METHOD1(GetLocalAddress, int(net::IPEndPoint*)); MOCK_CONST_METHOD0(NetLog, const net::NetLogWithSource&()); - MOCK_METHOD0(SetSubresourceSpeculation, void()); - MOCK_METHOD0(SetOmniboxSpeculation, void()); MOCK_CONST_METHOD0(WasEverUsed, bool()); MOCK_CONST_METHOD0(UsingTCPFastOpen, bool()); MOCK_CONST_METHOD0(WasAlpnNegotiated, bool()); @@ -75,7 +93,7 @@ class MockSSLClientSocket : public net::SSLClientSocket { const StringPiece&, unsigned char*, unsigned int)); - MOCK_METHOD1(GetSSLCertRequestInfo, void(net::SSLCertRequestInfo*)); + MOCK_CONST_METHOD1(GetSSLCertRequestInfo, void(net::SSLCertRequestInfo*)); MOCK_CONST_METHOD0(GetUnverifiedServerCertificateChain, scoped_refptr<net::X509Certificate>()); MOCK_CONST_METHOD0(GetChannelIDService, net::ChannelIDService*()); @@ -95,6 +113,21 @@ class MockTCPSocket : public net::TCPClientSocket { explicit MockTCPSocket(const net::AddressList& address_list) : net::TCPClientSocket(address_list, NULL, NULL, net::NetLogSource()) {} + int Read(net::IOBuffer* buffer, + int bytes, + net::CompletionOnceCallback callback) override { + return Read(buffer, bytes, + base::AdaptCallbackForRepeating(std::move(callback))); + } + + int Write(net::IOBuffer* buffer, + int bytes, + net::CompletionOnceCallback callback, + const net::NetworkTrafficAnnotationTag& tag) override { + return Write(buffer, bytes, + base::AdaptCallbackForRepeating(std::move(callback)), tag); + } + MOCK_METHOD3(Read, int(net::IOBuffer* buf, int buf_len, diff --git a/chromium/chrome/browser/extensions/api/socket/udp_socket_unittest.cc b/chromium/chrome/browser/extensions/api/socket/udp_socket_unittest.cc index 68b294cade7..033809d16f5 100644 --- a/chromium/chrome/browser/extensions/api/socket/udp_socket_unittest.cc +++ b/chromium/chrome/browser/extensions/api/socket/udp_socket_unittest.cc @@ -10,7 +10,6 @@ #include "base/location.h" #include "base/macros.h" -#include "base/message_loop/message_loop.h" #include "base/run_loop.h" #include "base/single_thread_task_runner.h" #include "base/test/test_timeouts.h" diff --git a/chromium/chrome/browser/extensions/api/storage/settings_apitest.cc b/chromium/chrome/browser/extensions/api/storage/settings_apitest.cc index e0c56008abf..207804b001b 100644 --- a/chromium/chrome/browser/extensions/api/storage/settings_apitest.cc +++ b/chromium/chrome/browser/extensions/api/storage/settings_apitest.cc @@ -64,7 +64,7 @@ const char kManagedStorageExtensionId[] = "kjmkgkdkpedkejedfhmfcenooemhbpbo"; class MockSchemaRegistryObserver : public policy::SchemaRegistry::Observer { public: MockSchemaRegistryObserver() {} - virtual ~MockSchemaRegistryObserver() {} + ~MockSchemaRegistryObserver() override {} MOCK_METHOD1(OnSchemaRegistryUpdated, void(bool)); }; @@ -482,7 +482,7 @@ IN_PROC_BROWSER_TEST_F(ExtensionSettingsApiTest, ManagedStorage) { .Set("string-policy", "value") .Set("int-policy", -123) .Set("double-policy", 456e7) - .SetBoolean("boolean-policy", true) + .Set("boolean-policy", true) .Set("list-policy", extensions::ListBuilder() .Append("one") .Append("two") diff --git a/chromium/chrome/browser/extensions/api/streams_private/streams_private_apitest.cc b/chromium/chrome/browser/extensions/api/streams_private/streams_private_apitest.cc index 3ab92a0545c..dc5725100f5 100644 --- a/chromium/chrome/browser/extensions/api/streams_private/streams_private_apitest.cc +++ b/chromium/chrome/browser/extensions/api/streams_private/streams_private_apitest.cc @@ -32,6 +32,7 @@ #include "net/test/embedded_test_server/http_request.h" #include "net/test/embedded_test_server/http_response.h" #include "net/traffic_annotation/network_traffic_annotation_test_helper.h" +#include "services/network/public/cpp/features.h" #include "testing/gmock/include/gmock/gmock.h" using content::BrowserContext; @@ -130,7 +131,7 @@ std::unique_ptr<HttpResponse> HandleRequest(const HttpRequest& request) { // The test extension expects the resources that should be handed to the // extension to have MIME type 'application/msword' and the resources that // should be downloaded by the browser to have MIME type 'text/plain'. -class StreamsPrivateApiTest : public ExtensionApiTest { +class StreamsPrivateApiTest : public extensions::ExtensionApiTest { public: StreamsPrivateApiTest() {} @@ -142,14 +143,14 @@ class StreamsPrivateApiTest : public ExtensionApiTest { test_server_->RegisterRequestHandler(base::Bind(&HandleRequest)); ASSERT_TRUE(test_server_->Start()); host_resolver()->AddRule("*", "127.0.0.1"); - ExtensionApiTest::SetUpOnMainThread(); + extensions::ExtensionApiTest::SetUpOnMainThread(); } void TearDownOnMainThread() override { // Tear down the test server. EXPECT_TRUE(test_server_->ShutdownAndWaitUntilComplete()); test_server_.reset(); - ExtensionApiTest::TearDownOnMainThread(); + extensions::ExtensionApiTest::TearDownOnMainThread(); } void InitializeDownloadSettings() { @@ -237,6 +238,9 @@ class StreamsPrivateApiTest : public ExtensionApiTest { // installed, white-listed extension invokes the extension's // onExecuteContentHandler event (and does not start a download). IN_PROC_BROWSER_TEST_F(StreamsPrivateApiTest, Navigate) { + if (base::FeatureList::IsEnabled(network::features::kNetworkService)) + return; // Streams not used with network service. + ASSERT_TRUE(LoadTestExtension()) << message_; ResultCatcher catcher; @@ -261,6 +265,9 @@ IN_PROC_BROWSER_TEST_F(StreamsPrivateApiTest, Navigate) { // Tests that navigating to a file URL also intercepts despite there being no // HTTP headers. This is a regression test for https://crbug.com/416433. IN_PROC_BROWSER_TEST_F(StreamsPrivateApiTest, FileURL) { + if (base::FeatureList::IsEnabled(network::features::kNetworkService)) + return; // Streams not used with network service. + ASSERT_TRUE(LoadTestExtension()) << message_; ResultCatcher catcher; @@ -285,6 +292,9 @@ IN_PROC_BROWSER_TEST_F(StreamsPrivateApiTest, FileURL) { // onExecuteContentHandler event (and does not start a download). // Regression test for http://crbug.com/342999. IN_PROC_BROWSER_TEST_F(StreamsPrivateApiTest, NavigateCrossSite) { + if (base::FeatureList::IsEnabled(network::features::kNetworkService)) + return; // Streams not used with network service. + ASSERT_TRUE(LoadTestExtension()) << message_; ResultCatcher catcher; @@ -326,6 +336,9 @@ IN_PROC_BROWSER_TEST_F(StreamsPrivateApiTest, NavigateCrossSite) { // extension with a file browser handler that can handle the attachment's MIME // type. IN_PROC_BROWSER_TEST_F(StreamsPrivateApiTest, MAYBE_NavigateToAnAttachment) { + if (base::FeatureList::IsEnabled(network::features::kNetworkService)) + return; // Streams not used with network service. + InitializeDownloadSettings(); ASSERT_TRUE(LoadTestExtension()) << message_; @@ -371,6 +384,9 @@ IN_PROC_BROWSER_TEST_F(StreamsPrivateApiTest, MAYBE_NavigateToAnAttachment) { // StreamsResourceThrottle, even if there is an extension with a file // browser handler that can handle the download's MIME type. IN_PROC_BROWSER_TEST_F(StreamsPrivateApiTest, MAYBE_DirectDownload) { + if (base::FeatureList::IsEnabled(network::features::kNetworkService)) + return; // Streams not used with network service. + InitializeDownloadSettings(); ASSERT_TRUE(LoadTestExtension()) << message_; @@ -426,6 +442,9 @@ IN_PROC_BROWSER_TEST_F(StreamsPrivateApiTest, MAYBE_DirectDownload) { // Tests that response headers are correctly passed to the API and that multiple // repsonse headers with the same name are merged correctly. IN_PROC_BROWSER_TEST_F(StreamsPrivateApiTest, Headers) { + if (base::FeatureList::IsEnabled(network::features::kNetworkService)) + return; // Streams not used with network service. + ASSERT_TRUE(LoadTestExtension()) << message_; ResultCatcher catcher; @@ -449,6 +468,9 @@ IN_PROC_BROWSER_TEST_F(StreamsPrivateApiTest, Headers) { // Tests that chrome.streamsPrivate.abort() works correctly. IN_PROC_BROWSER_TEST_F(StreamsPrivateApiTest, Abort) { + if (base::FeatureList::IsEnabled(network::features::kNetworkService)) + return; // Streams not used with network service. + ASSERT_TRUE(LoadTestExtension()) << message_; ResultCatcher catcher; diff --git a/chromium/chrome/browser/extensions/api/sync_file_system/sync_file_system_apitest.cc b/chromium/chrome/browser/extensions/api/sync_file_system/sync_file_system_apitest.cc index b8f1c6b90c4..7117b068dfa 100644 --- a/chromium/chrome/browser/extensions/api/sync_file_system/sync_file_system_apitest.cc +++ b/chromium/chrome/browser/extensions/api/sync_file_system/sync_file_system_apitest.cc @@ -37,14 +37,14 @@ using sync_file_system::SyncFileSystemServiceFactory; namespace { -class SyncFileSystemApiTest : public ExtensionApiTest { +class SyncFileSystemApiTest : public extensions::ExtensionApiTest { public: SyncFileSystemApiTest() : mock_remote_service_(NULL), real_default_quota_(0) {} void SetUpInProcessBrowserTestFixture() override { - ExtensionApiTest::SetUpInProcessBrowserTestFixture(); + extensions::ExtensionApiTest::SetUpInProcessBrowserTestFixture(); // TODO(calvinlo): Update test code after default quota is made const // (http://crbug.com/155488). @@ -56,7 +56,7 @@ class SyncFileSystemApiTest : public ExtensionApiTest { void TearDownInProcessBrowserTestFixture() override { storage::QuotaManager::kSyncableStorageDefaultHostQuota = real_default_quota_; - ExtensionApiTest::TearDownInProcessBrowserTestFixture(); + extensions::ExtensionApiTest::TearDownInProcessBrowserTestFixture(); } void SetUpOnMainThread() override { @@ -66,7 +66,7 @@ class SyncFileSystemApiTest : public ExtensionApiTest { mock_remote_service_ = new ::testing::NiceMock<MockRemoteFileSyncService>; SyncFileSystemServiceFactory::GetInstance()->set_mock_remote_file_service( std::unique_ptr<RemoteFileSyncService>(mock_remote_service_)); - ExtensionApiTest::SetUpOnMainThread(); + extensions::ExtensionApiTest::SetUpOnMainThread(); } ::testing::NiceMock<MockRemoteFileSyncService>* mock_remote_service() { diff --git a/chromium/chrome/browser/extensions/api/sync_file_system/sync_file_system_browsertest.cc b/chromium/chrome/browser/extensions/api/sync_file_system/sync_file_system_browsertest.cc index 2ff9bc7e96f..1c8beebfe77 100644 --- a/chromium/chrome/browser/extensions/api/sync_file_system/sync_file_system_browsertest.cc +++ b/chromium/chrome/browser/extensions/api/sync_file_system/sync_file_system_browsertest.cc @@ -69,7 +69,7 @@ class SyncFileSystemTest : public extensions::PlatformAppBrowserTest, } void SetUpOnMainThread() override { - in_memory_env_.reset(leveldb_chrome::NewMemEnv(leveldb::Env::Default())); + in_memory_env_ = leveldb_chrome::NewMemEnv("SyncFileSystemTest"); extensions::PlatformAppBrowserTest::SetUpOnMainThread(); ASSERT_TRUE(base_dir_.CreateUniqueTempDir()); diff --git a/chromium/chrome/browser/extensions/api/system_indicator/system_indicator_apitest.cc b/chromium/chrome/browser/extensions/api/system_indicator/system_indicator_apitest.cc index a903caf6b17..2313974b371 100644 --- a/chromium/chrome/browser/extensions/api/system_indicator/system_indicator_apitest.cc +++ b/chromium/chrome/browser/extensions/api/system_indicator/system_indicator_apitest.cc @@ -13,6 +13,8 @@ #include "extensions/common/extension.h" #include "extensions/test/result_catcher.h" +namespace extensions { + class SystemIndicatorApiTest : public ExtensionApiTest { public: void SetUpOnMainThread() override { @@ -65,3 +67,5 @@ IN_PROC_BROWSER_TEST_F(SystemIndicatorApiTest, DISABLED_SystemIndicator) { EXPECT_TRUE(catcher.GetNextResult()) << catcher.message(); } } + +} // namespace extensions diff --git a/chromium/chrome/browser/extensions/api/system_indicator/system_indicator_manager.h b/chromium/chrome/browser/extensions/api/system_indicator/system_indicator_manager.h index 76045111189..a16d5f37f2d 100644 --- a/chromium/chrome/browser/extensions/api/system_indicator/system_indicator_manager.h +++ b/chromium/chrome/browser/extensions/api/system_indicator/system_indicator_manager.h @@ -21,9 +21,9 @@ class ExtensionAction; class Profile; class StatusTray; +namespace extensions { FORWARD_DECLARE_TEST(SystemIndicatorApiTest, SystemIndicator); -namespace extensions { class ExtensionIndicatorIcon; class ExtensionRegistry; @@ -41,7 +41,7 @@ class SystemIndicatorManager : public ExtensionRegistryObserver, void Shutdown() override; private: - FRIEND_TEST_ALL_PREFIXES(::SystemIndicatorApiTest, SystemIndicator); + FRIEND_TEST_ALL_PREFIXES(SystemIndicatorApiTest, SystemIndicator); // ExtensionRegistryObserver implementation. void OnExtensionUnloaded(content::BrowserContext* browser_context, diff --git a/chromium/chrome/browser/extensions/api/system_private/system_private_api.cc b/chromium/chrome/browser/extensions/api/system_private/system_private_api.cc index e6f5f4d803b..132abe1537a 100644 --- a/chromium/chrome/browser/extensions/api/system_private/system_private_api.cc +++ b/chromium/chrome/browser/extensions/api/system_private/system_private_api.cc @@ -36,12 +36,8 @@ const char* const kIncognitoModeAvailabilityStrings[] = { }; // Property keys. -const char kBrightnessKey[] = "brightness"; const char kDownloadProgressKey[] = "downloadProgress"; -const char kIsVolumeMutedKey[] = "isVolumeMuted"; const char kStateKey[] = "state"; -const char kUserInitiatedKey[] = "userInitiated"; -const char kVolumeKey[] = "volume"; // System update states. const char kNotAvailableState[] = "NotAvailable"; @@ -51,19 +47,6 @@ const char kNeedRestartState[] = "NeedRestart"; const char kUpdatingState[] = "Updating"; #endif // defined(OS_CHROMEOS) -// Dispatches an extension event with |argument| -void DispatchEvent(extensions::events::HistogramValue histogram_value, - const std::string& event_name, - std::unique_ptr<base::Value> argument) { - std::unique_ptr<base::ListValue> list_args(new base::ListValue()); - if (argument) { - list_args->Append(std::move(argument)); - } - g_browser_process->extension_event_router_forwarder() - ->BroadcastEventToRenderers(histogram_value, event_name, - std::move(list_args), GURL()); -} - } // namespace namespace extensions { @@ -149,31 +132,4 @@ ExtensionFunction::ResponseAction SystemPrivateGetApiKeyFunction::Run() { OneArgument(std::make_unique<base::Value>(google_apis::GetAPIKey()))); } -void DispatchVolumeChangedEvent(double volume, bool is_volume_muted) { - std::unique_ptr<base::DictionaryValue> dict(new base::DictionaryValue()); - dict->SetDouble(kVolumeKey, volume); - dict->SetBoolean(kIsVolumeMutedKey, is_volume_muted); - DispatchEvent(extensions::events::SYSTEM_PRIVATE_ON_VOLUME_CHANGED, - system_private::OnVolumeChanged::kEventName, std::move(dict)); -} - -void DispatchBrightnessChangedEvent(int brightness, bool user_initiated) { - std::unique_ptr<base::DictionaryValue> dict(new base::DictionaryValue()); - dict->SetInteger(kBrightnessKey, brightness); - dict->SetBoolean(kUserInitiatedKey, user_initiated); - DispatchEvent(extensions::events::SYSTEM_PRIVATE_ON_BRIGHTNESS_CHANGED, - system_private::OnBrightnessChanged::kEventName, - std::move(dict)); -} - -void DispatchScreenUnlockedEvent() { - DispatchEvent(extensions::events::SYSTEM_PRIVATE_ON_SCREEN_UNLOCKED, - system_private::OnScreenUnlocked::kEventName, nullptr); -} - -void DispatchWokeUpEvent() { - DispatchEvent(extensions::events::SYSTEM_PRIVATE_ON_WOKE_UP, - system_private::OnWokeUp::kEventName, nullptr); -} - } // namespace extensions diff --git a/chromium/chrome/browser/extensions/api/system_private/system_private_api.h b/chromium/chrome/browser/extensions/api/system_private/system_private_api.h index 27e7265233a..5d6fb2bcc71 100644 --- a/chromium/chrome/browser/extensions/api/system_private/system_private_api.h +++ b/chromium/chrome/browser/extensions/api/system_private/system_private_api.h @@ -50,18 +50,6 @@ class SystemPrivateGetApiKeyFunction : public UIThreadExtensionFunction { ResponseAction Run() override; }; -// Dispatches systemPrivate.onBrightnessChanged event for extensions. -void DispatchBrightnessChangedEvent(int brightness, bool user_initiated); - -// Dispatches systemPrivate.onVolumeChanged event for extensions. -void DispatchVolumeChangedEvent(double volume, bool is_volume_muted); - -// Dispatches systemPrivate.onScreenChanged event for extensions. -void DispatchScreenUnlockedEvent(); - -// Dispatches systemPrivate.onWokeUp event for extensions. -void DispatchWokeUpEvent(); - } // namespace extensions #endif // CHROME_BROWSER_EXTENSIONS_API_SYSTEM_PRIVATE_SYSTEM_PRIVATE_API_H_ diff --git a/chromium/chrome/browser/extensions/api/system_private/system_private_apitest.cc b/chromium/chrome/browser/extensions/api/system_private/system_private_apitest.cc index 6b47168db23..6f14af16ebc 100644 --- a/chromium/chrome/browser/extensions/api/system_private/system_private_apitest.cc +++ b/chromium/chrome/browser/extensions/api/system_private/system_private_apitest.cc @@ -17,6 +17,8 @@ using chromeos::UpdateEngineClient; #endif +namespace extensions { + IN_PROC_BROWSER_TEST_F(ExtensionApiTest, GetIncognitoModeAvailability) { PrefService* pref_service = browser()->profile()->GetPrefs(); pref_service->SetInteger(prefs::kIncognitoModeAvailability, 1); @@ -69,3 +71,5 @@ IN_PROC_BROWSER_TEST_F(GetUpdateStatusApiTest, Progress) { } #endif + +} // namespace extensions diff --git a/chromium/chrome/browser/extensions/api/tab_capture/OWNERS b/chromium/chrome/browser/extensions/api/tab_capture/OWNERS index 100b4d0879a..ef6851eb466 100644 --- a/chromium/chrome/browser/extensions/api/tab_capture/OWNERS +++ b/chromium/chrome/browser/extensions/api/tab_capture/OWNERS @@ -1,5 +1,3 @@ -hubbe@chromium.org -justinlin@chromium.org miu@chromium.org -# COMPONENT: UI>Browser>TabCapture +# COMPONENT: Blink>GetUserMedia>Tab diff --git a/chromium/chrome/browser/extensions/api/tab_capture/offscreen_tab.cc b/chromium/chrome/browser/extensions/api/tab_capture/offscreen_tab.cc index 61a9d2ef326..12dc3bbd4e0 100644 --- a/chromium/chrome/browser/extensions/api/tab_capture/offscreen_tab.cc +++ b/chromium/chrome/browser/extensions/api/tab_capture/offscreen_tab.cc @@ -118,7 +118,7 @@ void OffscreenTab::Start(const GURL& start_url, if (!optional_presentation_id.empty()) params.starting_sandbox_flags = blink::kPresentationReceiverSandboxFlags; - offscreen_tab_web_contents_.reset(WebContents::Create(params)); + offscreen_tab_web_contents_ = WebContents::Create(params); offscreen_tab_web_contents_->SetDelegate(this); WebContentsObserver::Observe(offscreen_tab_web_contents_.get()); @@ -262,8 +262,10 @@ bool OffscreenTab::EmbedsFullscreenWidget() const { return true; } -void OffscreenTab::EnterFullscreenModeForTab(WebContents* contents, - const GURL& origin) { +void OffscreenTab::EnterFullscreenModeForTab( + WebContents* contents, + const GURL& origin, + const blink::WebFullscreenOptions& options) { DCHECK_EQ(offscreen_tab_web_contents_.get(), contents); if (in_fullscreen_mode()) diff --git a/chromium/chrome/browser/extensions/api/tab_capture/offscreen_tab.h b/chromium/chrome/browser/extensions/api/tab_capture/offscreen_tab.h index 3f866f04566..71bd01da3fe 100644 --- a/chromium/chrome/browser/extensions/api/tab_capture/offscreen_tab.h +++ b/chromium/chrome/browser/extensions/api/tab_capture/offscreen_tab.h @@ -159,8 +159,10 @@ class OffscreenTab : protected content::WebContentsDelegate, const std::string& partition_id, content::SessionStorageNamespace* session_storage_namespace) final; bool EmbedsFullscreenWidget() const final; - void EnterFullscreenModeForTab(content::WebContents* contents, - const GURL& origin) final; + void EnterFullscreenModeForTab( + content::WebContents* contents, + const GURL& origin, + const blink::WebFullscreenOptions& options) final; void ExitFullscreenModeForTab(content::WebContents* contents) final; bool IsFullscreenForTabOrPending( const content::WebContents* contents) const final; diff --git a/chromium/chrome/browser/extensions/api/tab_capture/tab_capture_apitest.cc b/chromium/chrome/browser/extensions/api/tab_capture/tab_capture_apitest.cc index 520f0c136d0..ed7082bce77 100644 --- a/chromium/chrome/browser/extensions/api/tab_capture/tab_capture_apitest.cc +++ b/chromium/chrome/browser/extensions/api/tab_capture/tab_capture_apitest.cc @@ -3,8 +3,10 @@ // found in the LICENSE file. #include "base/command_line.h" +#include "base/feature_list.h" #include "base/location.h" #include "base/message_loop/message_loop.h" +#include "base/run_loop.h" #include "base/single_thread_task_runner.h" #include "base/strings/stringprintf.h" #include "base/test/test_timeouts.h" @@ -21,6 +23,7 @@ #include "chrome/common/chrome_switches.h" #include "content/public/browser/render_frame_host.h" #include "content/public/browser/render_process_host.h" +#include "content/public/common/content_features.h" #include "content/public/test/browser_test_utils.h" #include "content/public/test/test_utils.h" #include "extensions/browser/extension_registry.h" @@ -155,7 +158,13 @@ TEST(TabCaptureCaptureOffscreenTabTest, DetermineInitialSize) { // Tests API behaviors, including info queries, and constraints violations. IN_PROC_BROWSER_TEST_F(TabCaptureApiTest, MAYBE_ApiTests) { AddExtensionToCommandLineWhitelist(); - ASSERT_TRUE(RunExtensionSubtest("tab_capture", "api_tests.html")) << message_; + ASSERT_TRUE(RunExtensionSubtest( + "tab_capture", base::StringPrintf("api_tests.html%s", + base::FeatureList::IsEnabled( + features::kAudioServiceAudioStreams) + ? "" + : "?includeLegacyUnmuteTest=true"))) + << message_; } #if defined(OS_MACOSX) && defined(ADDRESS_SANITIZER) @@ -259,15 +268,10 @@ IN_PROC_BROWSER_TEST_F(TabCaptureApiTest, MAYBE_GetUserMediaTest) { EXPECT_TRUE(catcher.GetNextResult()) << catcher.message(); } -// http://crbug.com/177163 -#if defined(OS_WIN) && !defined(NDEBUG) -#define MAYBE_ActiveTabPermission DISABLED_ActiveTabPermission -#else -#define MAYBE_ActiveTabPermission ActiveTabPermission -#endif +// http://crbug.com/177163, http://crbug.com/427730 // Make sure tabCapture.capture only works if the tab has been granted // permission via an extension icon click or the extension is whitelisted. -IN_PROC_BROWSER_TEST_F(TabCaptureApiTest, MAYBE_ActiveTabPermission) { +IN_PROC_BROWSER_TEST_F(TabCaptureApiTest, DISABLED_ActiveTabPermission) { ExtensionTestMessageListener before_open_tab("ready1", true); ExtensionTestMessageListener before_grant_permission("ready2", true); ExtensionTestMessageListener before_open_new_tab("ready3", true); @@ -338,15 +342,11 @@ IN_PROC_BROWSER_TEST_F(TabCaptureApiTest, DISABLED_FullscreenEvents) { EXPECT_TRUE(catcher.GetNextResult()) << catcher.message(); } -// Times out on Win dbg bots: http://crbug.com/177163 -// Flaky on MSan bots: http://crbug.com/294431 -#if (defined(OS_WIN) && !defined(NDEBUG)) || defined(MEMORY_SANITIZER) -#define MAYBE_GrantForChromePages DISABLED_GrantForChromePages -#else -#define MAYBE_GrantForChromePages GrantForChromePages -#endif +// Times out on Win dbg bots: https://crbug.com/177163 +// Flaky on MSan bots: https://crbug.com/294431 +// But really, just flaky everywhere. http://crbug.com/294431#c33 // Make sure tabCapture API can be granted for Chrome:// pages. -IN_PROC_BROWSER_TEST_F(TabCaptureApiTest, MAYBE_GrantForChromePages) { +IN_PROC_BROWSER_TEST_F(TabCaptureApiTest, DISABLED_GrantForChromePages) { ExtensionTestMessageListener before_open_tab("ready1", true); ASSERT_TRUE(RunExtensionSubtest("tab_capture", "active_tab_chrome_pages.html")) @@ -436,7 +436,7 @@ IN_PROC_BROWSER_TEST_F(TabCaptureApiTest, MAYBE_TabIndicator) { if (alert_state != last_alert_state_) { last_alert_state_ = alert_state; base::ThreadTaskRunnerHandle::Get()->PostTask( - FROM_HERE, base::MessageLoop::QuitWhenIdleClosure()); + FROM_HERE, base::RunLoop::QuitCurrentWhenIdleClosureDeprecated()); } } diff --git a/chromium/chrome/browser/extensions/api/tab_capture/tab_capture_performancetest.cc b/chromium/chrome/browser/extensions/api/tab_capture/tab_capture_performancetest.cc index 38e56a88a20..9aadd4d918e 100644 --- a/chromium/chrome/browser/extensions/api/tab_capture/tab_capture_performancetest.cc +++ b/chromium/chrome/browser/extensions/api/tab_capture/tab_capture_performancetest.cc @@ -49,9 +49,8 @@ enum TestFlags { kSmallWindow = 1 << 4, // Window size: 1 = 800x600, 0 = 2000x1000 }; -class TabCapturePerformanceTest - : public ExtensionApiTest, - public testing::WithParamInterface<int> { +class TabCapturePerformanceTest : public extensions::ExtensionApiTest, + public testing::WithParamInterface<int> { public: TabCapturePerformanceTest() {} @@ -78,7 +77,7 @@ class TabCapturePerformanceTest EnablePixelOutput(); if (!HasFlag(kUseGpu)) UseSoftwareCompositing(); - ExtensionApiTest::SetUp(); + extensions::ExtensionApiTest::SetUp(); } void SetUpCommandLine(base::CommandLine* command_line) override { @@ -101,7 +100,7 @@ class TabCapturePerformanceTest extensions::switches::kWhitelistedExtensionID, kExtensionId); - ExtensionApiTest::SetUpCommandLine(command_line); + extensions::ExtensionApiTest::SetUpCommandLine(command_line); } void FindEvents(trace_analyzer::TraceAnalyzer* analyzer, diff --git a/chromium/chrome/browser/extensions/api/tabs/tabs_api.cc b/chromium/chrome/browser/extensions/api/tabs/tabs_api.cc index 9a275120a54..a753fd57760 100644 --- a/chromium/chrome/browser/extensions/api/tabs/tabs_api.cc +++ b/chromium/chrome/browser/extensions/api/tabs/tabs_api.cc @@ -640,12 +640,13 @@ ExtensionFunction::ResponseAction WindowsCreateFunction::Run() { // a tabbed window. if ((window_type == Browser::TYPE_POPUP && urls.empty()) || window_type == Browser::TYPE_TABBED) { - if (source_tab_strip) - contents = source_tab_strip->DetachWebContentsAt(tab_index); - if (contents) { + if (source_tab_strip) { + std::unique_ptr<content::WebContents> detached_tab = + source_tab_strip->DetachWebContentsAt(tab_index); + contents = detached_tab.get(); TabStripModel* target_tab_strip = new_window->tab_strip_model(); - target_tab_strip->InsertWebContentsAt(urls.size(), contents, - TabStripModel::ADD_NONE); + target_tab_strip->InsertWebContentsAt( + urls.size(), std::move(detached_tab), TabStripModel::ADD_NONE); } } // Create a new tab if the created window is still empty. Don't create a new @@ -655,20 +656,21 @@ ExtensionFunction::ResponseAction WindowsCreateFunction::Run() { } chrome::SelectNumberedTab(new_window, 0); + if (focused) + new_window->window()->Show(); + else + new_window->window()->ShowInactive(); + #if defined(OS_CHROMEOS) // Lock the window fullscreen only after the new tab has been created - // (otherwise the tabstrip is empty). + // (otherwise the tabstrip is empty), and window()->show() has been called + // (otherwise that resets the locked mode for devices in tablet mode). if (create_data && create_data->state == windows::WINDOW_STATE_LOCKED_FULLSCREEN) { SetLockedFullscreenState(new_window, true); } #endif - if (focused) - new_window->window()->Show(); - else - new_window->window()->ShowInactive(); - std::unique_ptr<base::Value> result; if (new_window->profile()->IsOffTheRecord() && !browser_context()->IsOffTheRecord() && !include_incognito()) { @@ -1366,8 +1368,9 @@ bool TabsUpdateFunction::RunAsync() { if (params->update_properties.auto_discardable.get()) { bool state = *params->update_properties.auto_discardable; - g_browser_process->GetTabManager()->SetTabAutoDiscardableState(contents, - state); + resource_coordinator::TabLifecycleUnitExternal::FromWebContents( + web_contents_) + ->SetAutoDiscardable(state); } if (!is_async) { @@ -1395,11 +1398,13 @@ bool TabsUpdateFunction::UpdateURL(const std::string &url_string, return false; } + const bool is_javascript_scheme = url.SchemeIs(url::kJavaScriptScheme); + UMA_HISTOGRAM_BOOLEAN("Extensions.ApiTabUpdateJavascript", + is_javascript_scheme); // JavaScript URLs can do the same kinds of things as cross-origin XHR, so // we need to check host permissions before allowing them. - if (url.SchemeIs(url::kJavaScriptScheme)) { + if (is_javascript_scheme) { if (!extension()->permissions_data()->CanAccessPage( - extension(), web_contents_->GetURL(), tab_id, &error_)) { @@ -1564,7 +1569,7 @@ bool TabsMoveFunction::MoveTab(int tab_id, if (ExtensionTabUtil::GetWindowId(target_browser) != ExtensionTabUtil::GetWindowId(source_browser)) { TabStripModel* target_tab_strip = target_browser->tab_strip_model(); - WebContents* web_contents = + std::unique_ptr<content::WebContents> web_contents = source_tab_strip->DetachWebContentsAt(tab_index); if (!web_contents) { *error = ErrorUtils::FormatErrorMessage(keys::kTabNotFoundError, @@ -1578,12 +1583,13 @@ bool TabsMoveFunction::MoveTab(int tab_id, if (*new_index > target_tab_strip->count() || *new_index < 0) *new_index = target_tab_strip->count(); - target_tab_strip->InsertWebContentsAt( - *new_index, web_contents, TabStripModel::ADD_NONE); + content::WebContents* web_contents_raw = web_contents.get(); + target_tab_strip->InsertWebContentsAt(*new_index, std::move(web_contents), + TabStripModel::ADD_NONE); if (has_callback()) { tab_values->Append(ExtensionTabUtil::CreateTabObject( - web_contents, ExtensionTabUtil::kScrubTab, + web_contents_raw, ExtensionTabUtil::kScrubTab, extension(), target_tab_strip, *new_index) ->ToValue()); } @@ -1739,7 +1745,7 @@ WebContents* TabsCaptureVisibleTabFunction::GetWebContentsForID( } if (!extension()->permissions_data()->CanCaptureVisiblePage( - contents->GetLastCommittedURL(), extension(), + contents->GetLastCommittedURL(), SessionTabHelper::IdForTab(contents).id(), error)) { return nullptr; } @@ -2007,8 +2013,8 @@ bool ExecuteCodeInTabFunction::CanExecuteScriptOnPage(std::string* error) { // NOTE: This can give the wrong answer due to race conditions, but it is OK, // we check again in the renderer. - if (!extension()->permissions_data()->CanAccessPage( - extension(), effective_document_url, execute_tab_id_, error)) { + if (!extension()->permissions_data()->CanAccessPage(effective_document_url, + execute_tab_id_, error)) { if (is_about_url && extension()->permissions_data()->active_permissions().HasAPIPermission( APIPermission::kTab)) { @@ -2084,7 +2090,7 @@ bool TabsSetZoomFunction::RunAsync() { return false; GURL url(web_contents->GetVisibleURL()); - if (PermissionsData::IsRestrictedUrl(url, extension(), &error_)) + if (extension()->permissions_data()->IsRestrictedUrl(url, &error_)) return false; ZoomController* zoom_controller = @@ -2136,7 +2142,7 @@ bool TabsSetZoomSettingsFunction::RunAsync() { return false; GURL url(web_contents->GetVisibleURL()); - if (PermissionsData::IsRestrictedUrl(url, extension(), &error_)) + if (extension()->permissions_data()->IsRestrictedUrl(url, &error_)) return false; // "per-origin" scope is only available in "automatic" mode. diff --git a/chromium/chrome/browser/extensions/api/tabs/tabs_api_unittest.cc b/chromium/chrome/browser/extensions/api/tabs/tabs_api_unittest.cc index 89c2d712616..90c6838376a 100644 --- a/chromium/chrome/browser/extensions/api/tabs/tabs_api_unittest.cc +++ b/chromium/chrome/browser/extensions/api/tabs/tabs_api_unittest.cc @@ -94,18 +94,20 @@ TEST_F(TabsApiUnitTest, QueryWithoutTabsPermission) { std::string tab_titles[] = {"", "Sample title", "Sample title"}; // Add 3 web contentses to the browser. - std::unique_ptr<content::WebContents> web_contentses[arraysize(tab_urls)]; + content::WebContents* web_contentses[arraysize(tab_urls)]; for (size_t i = 0; i < arraysize(tab_urls); ++i) { - content::WebContents* web_contents = + std::unique_ptr<content::WebContents> web_contents = content::WebContentsTester::CreateTestWebContents(profile(), nullptr); - web_contentses[i].reset(web_contents); - browser()->tab_strip_model()->AppendWebContents(web_contents, true); + content::WebContents* raw_web_contents = web_contents.get(); + web_contentses[i] = raw_web_contents; + browser()->tab_strip_model()->AppendWebContents(std::move(web_contents), + true); EXPECT_EQ(browser()->tab_strip_model()->GetActiveWebContents(), - web_contents); + raw_web_contents); content::WebContentsTester* web_contents_tester = - content::WebContentsTester::For(web_contents); + content::WebContentsTester::For(raw_web_contents); web_contents_tester->NavigateAndCommit(tab_urls[i]); - web_contents->GetController().GetVisibleEntry()->SetTitle( + raw_web_contents->GetController().GetVisibleEntry()->SetTitle( base::ASCIIToUTF16(tab_titles[i])); } @@ -140,7 +142,10 @@ TEST_F(TabsApiUnitTest, QueryWithoutTabsPermission) { ASSERT_TRUE(tabs_list_with_permission->GetDictionary(0, &third_tab_info)); int third_tab_id = -1; ASSERT_TRUE(third_tab_info->GetInteger("id", &third_tab_id)); - EXPECT_EQ(ExtensionTabUtil::GetTabId(web_contentses[2].get()), third_tab_id); + EXPECT_EQ(ExtensionTabUtil::GetTabId(web_contentses[2]), third_tab_id); + + while (!browser()->tab_strip_model()->empty()) + browser()->tab_strip_model()->DetachWebContentsAt(0); } TEST_F(TabsApiUnitTest, QueryWithHostPermission) { @@ -150,18 +155,20 @@ TEST_F(TabsApiUnitTest, QueryWithHostPermission) { std::string tab_titles[] = {"", "Sample title", "Sample title"}; // Add 3 web contentses to the browser. - std::unique_ptr<content::WebContents> web_contentses[arraysize(tab_urls)]; + content::WebContents* web_contentses[arraysize(tab_urls)]; for (size_t i = 0; i < arraysize(tab_urls); ++i) { - content::WebContents* web_contents = + std::unique_ptr<content::WebContents> web_contents = content::WebContentsTester::CreateTestWebContents(profile(), nullptr); - web_contentses[i].reset(web_contents); - browser()->tab_strip_model()->AppendWebContents(web_contents, true); + content::WebContents* raw_web_contents = web_contents.get(); + web_contentses[i] = raw_web_contents; + browser()->tab_strip_model()->AppendWebContents(std::move(web_contents), + true); EXPECT_EQ(browser()->tab_strip_model()->GetActiveWebContents(), - web_contents); + raw_web_contents); content::WebContentsTester* web_contents_tester = - content::WebContentsTester::For(web_contents); + content::WebContentsTester::For(raw_web_contents); web_contents_tester->NavigateAndCommit(tab_urls[i]); - web_contents->GetController().GetVisibleEntry()->SetTitle( + raw_web_contents->GetController().GetVisibleEntry()->SetTitle( base::ASCIIToUTF16(tab_titles[i])); } @@ -192,8 +199,7 @@ TEST_F(TabsApiUnitTest, QueryWithHostPermission) { ASSERT_TRUE(tabs_list_with_permission->GetDictionary(0, &third_tab_info)); int third_tab_id = -1; ASSERT_TRUE(third_tab_info->GetInteger("id", &third_tab_id)); - EXPECT_EQ(ExtensionTabUtil::GetTabId(web_contentses[2].get()), - third_tab_id); + EXPECT_EQ(ExtensionTabUtil::GetTabId(web_contentses[2]), third_tab_id); } // Try the same without title, first and third tabs will match. @@ -211,10 +217,8 @@ TEST_F(TabsApiUnitTest, QueryWithHostPermission) { ASSERT_TRUE(tabs_list_with_permission->GetDictionary(1, &third_tab_info)); std::vector<int> expected_tabs_ids; - expected_tabs_ids.push_back( - ExtensionTabUtil::GetTabId(web_contentses[0].get())); - expected_tabs_ids.push_back( - ExtensionTabUtil::GetTabId(web_contentses[2].get())); + expected_tabs_ids.push_back(ExtensionTabUtil::GetTabId(web_contentses[0])); + expected_tabs_ids.push_back(ExtensionTabUtil::GetTabId(web_contentses[2])); int first_tab_id = -1; ASSERT_TRUE(first_tab_info->GetInteger("id", &first_tab_id)); @@ -224,6 +228,8 @@ TEST_F(TabsApiUnitTest, QueryWithHostPermission) { ASSERT_TRUE(third_tab_info->GetInteger("id", &third_tab_id)); EXPECT_TRUE(base::ContainsValue(expected_tabs_ids, third_tab_id)); } + while (!browser()->tab_strip_model()->empty()) + browser()->tab_strip_model()->DetachWebContentsAt(0); } // Test that using the PDF extension for tab updates is treated as a @@ -242,19 +248,21 @@ TEST_F(TabsApiUnitTest, PDFExtensionNavigation) { .Build(); ASSERT_TRUE(extension); - content::WebContents* web_contents = + std::unique_ptr<content::WebContents> web_contents = content::WebContentsTester::CreateTestWebContents(profile(), nullptr); - ASSERT_TRUE(web_contents); + content::WebContents* raw_web_contents = web_contents.get(); + ASSERT_TRUE(raw_web_contents); content::WebContentsTester* web_contents_tester = - content::WebContentsTester::For(web_contents); + content::WebContentsTester::For(raw_web_contents); const GURL kGoogle("http://www.google.com"); web_contents_tester->NavigateAndCommit(kGoogle); - EXPECT_EQ(kGoogle, web_contents->GetLastCommittedURL()); - EXPECT_EQ(kGoogle, web_contents->GetVisibleURL()); + EXPECT_EQ(kGoogle, raw_web_contents->GetLastCommittedURL()); + EXPECT_EQ(kGoogle, raw_web_contents->GetVisibleURL()); - SessionTabHelper::CreateForWebContents(web_contents); - int tab_id = SessionTabHelper::IdForTab(web_contents).id(); - browser()->tab_strip_model()->AppendWebContents(web_contents, true); + SessionTabHelper::CreateForWebContents(raw_web_contents); + int tab_id = SessionTabHelper::IdForTab(raw_web_contents).id(); + browser()->tab_strip_model()->AppendWebContents(std::move(web_contents), + true); scoped_refptr<TabsUpdateFunction> function = new TabsUpdateFunction(); function->set_extension(extension.get()); @@ -266,8 +274,8 @@ TEST_F(TabsApiUnitTest, PDFExtensionNavigation) { api_test_utils::SendResponseHelper response_helper(function.get()); function->RunWithValidation()->Execute(); - EXPECT_EQ(kGoogle, web_contents->GetLastCommittedURL()); - EXPECT_EQ(kGoogle, web_contents->GetVisibleURL()); + EXPECT_EQ(kGoogle, raw_web_contents->GetLastCommittedURL()); + EXPECT_EQ(kGoogle, raw_web_contents->GetVisibleURL()); // Clean up. response_helper.WaitForResponse(); diff --git a/chromium/chrome/browser/extensions/api/tabs/tabs_event_router.cc b/chromium/chrome/browser/extensions/api/tabs/tabs_event_router.cc index af63faf2661..05f4274c974 100644 --- a/chromium/chrome/browser/extensions/api/tabs/tabs_event_router.cc +++ b/chromium/chrome/browser/extensions/api/tabs/tabs_event_router.cc @@ -248,7 +248,9 @@ void TabsEventRouter::TabInsertedAt(TabStripModel* tab_strip_model, std::move(args), EventRouter::USER_GESTURE_UNKNOWN); } -void TabsEventRouter::TabDetachedAt(WebContents* contents, int index) { +void TabsEventRouter::TabDetachedAt(WebContents* contents, + int index, + bool was_active) { if (!GetTabEntry(contents)) { // The tab was removed. Don't send detach event. return; diff --git a/chromium/chrome/browser/extensions/api/tabs/tabs_event_router.h b/chromium/chrome/browser/extensions/api/tabs/tabs_event_router.h index 7f0ac1eec90..d0b11d82c81 100644 --- a/chromium/chrome/browser/extensions/api/tabs/tabs_event_router.h +++ b/chromium/chrome/browser/extensions/api/tabs/tabs_event_router.h @@ -61,7 +61,9 @@ class TabsEventRouter : public TabStripModelObserver, void TabClosingAt(TabStripModel* tab_strip_model, content::WebContents* contents, int index) override; - void TabDetachedAt(content::WebContents* contents, int index) override; + void TabDetachedAt(content::WebContents* contents, + int index, + bool was_active) override; void ActiveTabChanged(content::WebContents* old_contents, content::WebContents* new_contents, int index, diff --git a/chromium/chrome/browser/extensions/api/tabs/tabs_test.cc b/chromium/chrome/browser/extensions/api/tabs/tabs_test.cc index b711fb4d26e..0dc983f83c5 100644 --- a/chromium/chrome/browser/extensions/api/tabs/tabs_test.cc +++ b/chromium/chrome/browser/extensions/api/tabs/tabs_test.cc @@ -11,7 +11,6 @@ #include "apps/test/app_window_waiter.h" #include "base/memory/ref_counted.h" -#include "base/message_loop/message_loop.h" #include "base/run_loop.h" #include "base/strings/pattern.h" #include "base/strings/string_split.h" @@ -889,12 +888,8 @@ base::Value* ExtensionWindowLastFocusedTest::RunFunction( IN_PROC_BROWSER_TEST_F(ExtensionWindowLastFocusedTest, ExtensionAPICannotNavigateDevtools) { - std::unique_ptr<base::DictionaryValue> test_extension_value( - api_test_utils::ParseDictionary( - "{\"name\": \"Test\", \"version\": \"1.0\", \"permissions\": " - "[\"tabs\"]}")); - scoped_refptr<Extension> extension( - api_test_utils::CreateExtension(test_extension_value.get())); + scoped_refptr<const Extension> extension = + ExtensionBuilder("Test").AddPermission("tabs").Build(); DevToolsWindow* devtools = DevToolsWindowTesting::OpenDevToolsWindowSync( browser()->tab_strip_model()->GetWebContentsAt(0), false /* is_docked */); @@ -1033,7 +1028,13 @@ IN_PROC_BROWSER_TEST_F(ExtensionWindowLastFocusedTest, } #endif // !defined(OS_MACOSX) -IN_PROC_BROWSER_TEST_F(ExtensionWindowCreateTest, AcceptState) { +#if defined(OS_MACOSX) +// https://crbug.com/836327 +#define MAYBE_AcceptState DISABLED_AcceptState +#else +#define MAYBE_AcceptState AcceptState +#endif +IN_PROC_BROWSER_TEST_F(ExtensionWindowCreateTest, MAYBE_AcceptState) { #if defined(OS_MACOSX) if (base::mac::IsOS10_10()) return; // Fails when swarmed. http://crbug.com/660582 @@ -1125,12 +1126,8 @@ IN_PROC_BROWSER_TEST_F(ExtensionTabsTest, DuplicateTab) { scoped_refptr<TabsDuplicateFunction> duplicate_tab_function( new TabsDuplicateFunction()); - std::unique_ptr<base::DictionaryValue> test_extension_value( - api_test_utils::ParseDictionary( - "{\"name\": \"Test\", \"version\": \"1.0\", \"permissions\": " - "[\"tabs\"]}")); - scoped_refptr<Extension> empty_tab_extension( - api_test_utils::CreateExtension(test_extension_value.get())); + scoped_refptr<const Extension> empty_tab_extension = + ExtensionBuilder("Test").AddPermission("tabs").Build(); duplicate_tab_function->set_extension(empty_tab_extension.get()); duplicate_tab_function->set_has_callback(true); @@ -1273,12 +1270,8 @@ IN_PROC_BROWSER_TEST_F(ExtensionTabsTest, MAYBE_FilteredEvents) { } IN_PROC_BROWSER_TEST_F(ExtensionTabsTest, ExecuteScriptOnDevTools) { - std::unique_ptr<base::DictionaryValue> test_extension_value( - api_test_utils::ParseDictionary( - "{\"name\": \"Test\", \"version\": \"1.0\", \"permissions\": " - "[\"tabs\"]}")); - scoped_refptr<Extension> extension( - api_test_utils::CreateExtension(test_extension_value.get())); + scoped_refptr<const Extension> extension = + ExtensionBuilder("Test").AddPermission("tabs").Build(); DevToolsWindow* devtools = DevToolsWindowTesting::OpenDevToolsWindowSync( browser()->tab_strip_model()->GetWebContentsAt(0), false /* is_docked */); diff --git a/chromium/chrome/browser/extensions/api/terminal/terminal_private_apitest.cc b/chromium/chrome/browser/extensions/api/terminal/terminal_private_apitest.cc index 7069e3d2a57..f14022f64a0 100644 --- a/chromium/chrome/browser/extensions/api/terminal/terminal_private_apitest.cc +++ b/chromium/chrome/browser/extensions/api/terminal/terminal_private_apitest.cc @@ -6,9 +6,9 @@ #include "chrome/browser/extensions/extension_apitest.h" #include "extensions/common/switches.h" -class ExtensionTerminalPrivateApiTest : public ExtensionApiTest { +class ExtensionTerminalPrivateApiTest : public extensions::ExtensionApiTest { void SetUpCommandLine(base::CommandLine* command_line) override { - ExtensionApiTest::SetUpCommandLine(command_line); + extensions::ExtensionApiTest::SetUpCommandLine(command_line); command_line->AppendSwitchASCII( extensions::switches::kWhitelistedExtensionID, "kidcpjlbjdmcnmccjhjdckhbngnhnepk"); diff --git a/chromium/chrome/browser/extensions/api/top_sites/top_sites_api.cc b/chromium/chrome/browser/extensions/api/top_sites/top_sites_api.cc index 0df2d28cbc4..3f9ef2b5060 100644 --- a/chromium/chrome/browser/extensions/api/top_sites/top_sites_api.cc +++ b/chromium/chrome/browser/extensions/api/top_sites/top_sites_api.cc @@ -18,21 +18,22 @@ namespace extensions { -TopSitesGetFunction::TopSitesGetFunction() - : weak_ptr_factory_(this) {} +TopSitesGetFunction::TopSitesGetFunction() = default; +TopSitesGetFunction::~TopSitesGetFunction() = default; -TopSitesGetFunction::~TopSitesGetFunction() {} - -bool TopSitesGetFunction::RunAsync() { - scoped_refptr<history::TopSites> ts = - TopSitesFactory::GetForProfile(GetProfile()); +ExtensionFunction::ResponseAction TopSitesGetFunction::Run() { + scoped_refptr<history::TopSites> ts = TopSitesFactory::GetForProfile( + Profile::FromBrowserContext(browser_context())); if (!ts) - return false; + return RespondNow(Error(kUnknownErrorDoNotUse)); ts->GetMostVisitedURLs( - base::Bind(&TopSitesGetFunction::OnMostVisitedURLsAvailable, - weak_ptr_factory_.GetWeakPtr()), false); - return true; + base::Bind(&TopSitesGetFunction::OnMostVisitedURLsAvailable, this), + false); + + // GetMostVisitedURLs() will invoke the callback synchronously if the URLs are + // already populated. + return did_respond() ? AlreadyResponded() : RespondLater(); } void TopSitesGetFunction::OnMostVisitedURLsAvailable( @@ -52,8 +53,7 @@ void TopSitesGetFunction::OnMostVisitedURLsAvailable( } } - SetResult(std::move(pages_value)); - SendResponse(true); + Respond(OneArgument(std::move(pages_value))); } } // namespace extensions diff --git a/chromium/chrome/browser/extensions/api/top_sites/top_sites_api.h b/chromium/chrome/browser/extensions/api/top_sites/top_sites_api.h index 41b93efd86f..1b8689303ef 100644 --- a/chromium/chrome/browser/extensions/api/top_sites/top_sites_api.h +++ b/chromium/chrome/browser/extensions/api/top_sites/top_sites_api.h @@ -5,13 +5,12 @@ #ifndef CHROME_BROWSER_EXTENSIONS_API_TOP_SITES_TOP_SITES_API_H_ #define CHROME_BROWSER_EXTENSIONS_API_TOP_SITES_TOP_SITES_API_H_ -#include "base/memory/weak_ptr.h" -#include "chrome/browser/extensions/chrome_extension_function.h" #include "components/history/core/browser/history_types.h" +#include "extensions/browser/extension_function.h" namespace extensions { -class TopSitesGetFunction : public ChromeAsyncExtensionFunction { +class TopSitesGetFunction : public UIThreadExtensionFunction { public: DECLARE_EXTENSION_FUNCTION("topSites.get", TOPSITES_GET) @@ -21,13 +20,10 @@ class TopSitesGetFunction : public ChromeAsyncExtensionFunction { ~TopSitesGetFunction() override; // ExtensionFunction: - bool RunAsync() override; + ResponseAction Run() override; private: void OnMostVisitedURLsAvailable(const history::MostVisitedURLList& data); - - // For callbacks may be run after destruction. - base::WeakPtrFactory<TopSitesGetFunction> weak_ptr_factory_; }; } // namespace extensions diff --git a/chromium/chrome/browser/extensions/api/virtual_keyboard_private/chrome_virtual_keyboard_delegate.cc b/chromium/chrome/browser/extensions/api/virtual_keyboard_private/chrome_virtual_keyboard_delegate.cc index bb04d9671bd..82ffe51c0ef 100644 --- a/chromium/chrome/browser/extensions/api/virtual_keyboard_private/chrome_virtual_keyboard_delegate.cc +++ b/chromium/chrome/browser/extensions/api/virtual_keyboard_private/chrome_virtual_keyboard_delegate.cc @@ -182,6 +182,8 @@ ChromeVirtualKeyboardDelegate::ConvertKeyboardModeToContainerType( return keyboard::ContainerType::FULL_WIDTH; case keyboard_api::KEYBOARD_MODE_FLOATING: return keyboard::ContainerType::FLOATING; + case keyboard_api::KEYBOARD_MODE_FULLSCREEN: + return keyboard::ContainerType::FULLSCREEN; } NOTREACHED(); @@ -251,6 +253,9 @@ void ChromeVirtualKeyboardDelegate::OnHasInputDevices( "gestureediting", keyboard::IsGestureEditingEnabled())); features->AppendString(GenerateFeatureFlag( "experimental", keyboard::IsExperimentalInputViewEnabled())); + features->AppendString(GenerateFeatureFlag( + "fullscreenhandwriting", + keyboard::IsFullscreenHandwritingVirtualKeyboardEnabled())); const keyboard::KeyboardConfig config = keyboard::GetKeyboardConfig(); // TODO(oka): Change this to use config.voice_input. diff --git a/chromium/chrome/browser/extensions/api/vpn_provider/vpn_provider_apitest.cc b/chromium/chrome/browser/extensions/api/vpn_provider/vpn_provider_apitest.cc index cd090aab65c..000c2d54fee 100644 --- a/chromium/chrome/browser/extensions/api/vpn_provider/vpn_provider_apitest.cc +++ b/chromium/chrome/browser/extensions/api/vpn_provider/vpn_provider_apitest.cc @@ -114,25 +114,25 @@ class TestShillThirdPartyVpnDriverClient std::vector<char> ip_packet_; }; -class VpnProviderApiTest : public ExtensionApiTest, +class VpnProviderApiTest : public extensions::ExtensionApiTest, public NetworkConfigurationObserver { public: VpnProviderApiTest() {} ~VpnProviderApiTest() override {} void SetUpOnMainThread() override { - ExtensionApiTest::SetUpOnMainThread(); + extensions::ExtensionApiTest::SetUpOnMainThread(); NetworkHandler::Get()->network_configuration_handler()->AddObserver(this); } void TearDownOnMainThread() override { - ExtensionApiTest::TearDownOnMainThread(); + extensions::ExtensionApiTest::TearDownOnMainThread(); NetworkHandler::Get()->network_configuration_handler()->RemoveObserver( this); } void SetUpInProcessBrowserTestFixture() override { - ExtensionApiTest::SetUpInProcessBrowserTestFixture(); + extensions::ExtensionApiTest::SetUpInProcessBrowserTestFixture(); test_client_ = new TestShillThirdPartyVpnDriverClient(); DBusThreadManager::GetSetterForTesting()->SetShillThirdPartyVpnDriverClient( base::WrapUnique(test_client_)); diff --git a/chromium/chrome/browser/extensions/api/web_navigation/web_navigation_apitest.cc b/chromium/chrome/browser/extensions/api/web_navigation/web_navigation_apitest.cc index e75618d49cb..56f264506ca 100644 --- a/chromium/chrome/browser/extensions/api/web_navigation/web_navigation_apitest.cc +++ b/chromium/chrome/browser/extensions/api/web_navigation/web_navigation_apitest.cc @@ -40,6 +40,7 @@ #include "content/public/common/resource_type.h" #include "content/public/common/url_constants.h" #include "content/public/test/browser_test_utils.h" +#include "content/public/test/download_test_observer.h" #include "content/public/test/test_utils.h" #include "extensions/browser/extension_system.h" #include "extensions/common/switches.h" @@ -206,9 +207,6 @@ class WebNavigationApiTest : public ExtensionApiTest { FrameNavigationState::set_allow_extension_scheme(true); - base::CommandLine::ForCurrentProcess()->AppendSwitch( - switches::kAllowLegacyExtensionManifests); - host_resolver()->AddRule("*", "127.0.0.1"); } @@ -236,10 +234,17 @@ IN_PROC_BROWSER_TEST_F(WebNavigationApiTest, DISABLED_ServerRedirect) { << message_; } -IN_PROC_BROWSER_TEST_F(WebNavigationApiTest, Download) { +// https://crbug.com/660288 +IN_PROC_BROWSER_TEST_F(WebNavigationApiTest, DISABLED_Download) { ASSERT_TRUE(StartEmbeddedTestServer()); - ASSERT_TRUE(RunExtensionTest("webnavigation/download")) - << message_; + content::DownloadManager* download_manager = + content::BrowserContext::GetDownloadManager(browser()->profile()); + content::DownloadTestObserverTerminal observer( + download_manager, 1, + content::DownloadTestObserver::ON_DANGEROUS_DOWNLOAD_FAIL); + bool result = RunExtensionTest("webnavigation/download"); + observer.WaitForFinished(); + ASSERT_TRUE(result) << message_; } IN_PROC_BROWSER_TEST_F(WebNavigationApiTest, ServerRedirectSingleProcess) { diff --git a/chromium/chrome/browser/extensions/api/web_request/web_request_apitest.cc b/chromium/chrome/browser/extensions/api/web_request/web_request_apitest.cc index 216f8755d93..28eaeffb94b 100644 --- a/chromium/chrome/browser/extensions/api/web_request/web_request_apitest.cc +++ b/chromium/chrome/browser/extensions/api/web_request/web_request_apitest.cc @@ -3,13 +3,18 @@ // found in the LICENSE file. #include <memory> +#include <utility> #include "base/command_line.h" +#include "base/feature_list.h" #include "base/macros.h" #include "base/memory/ptr_util.h" #include "base/optional.h" #include "base/run_loop.h" #include "base/strings/stringprintf.h" +#include "base/synchronization/lock.h" +#include "base/test/bind_test_util.h" +#include "base/test/scoped_feature_list.h" #include "base/values.h" #include "build/build_config.h" #include "chrome/browser/browser_process.h" @@ -20,19 +25,29 @@ #include "chrome/browser/extensions/extension_apitest.h" #include "chrome/browser/extensions/extension_service.h" #include "chrome/browser/extensions/extension_with_management_policy_apitest.h" +#include "chrome/browser/extensions/scripting_permissions_modifier.h" #include "chrome/browser/extensions/tab_helper.h" #include "chrome/browser/net/profile_network_context_service.h" #include "chrome/browser/net/profile_network_context_service_factory.h" +#include "chrome/browser/net/system_network_context_manager.h" #include "chrome/browser/profiles/profile.h" +#include "chrome/browser/search/one_google_bar/one_google_bar_loader.h" +#include "chrome/browser/search/one_google_bar/one_google_bar_service.h" +#include "chrome/browser/search/one_google_bar/one_google_bar_service_factory.h" +#include "chrome/browser/search/search.h" #include "chrome/browser/search_engines/template_url_service_factory.h" #include "chrome/browser/ui/browser.h" #include "chrome/browser/ui/browser_navigator_params.h" #include "chrome/browser/ui/login/login_handler.h" +#include "chrome/browser/ui/search/local_ntp_test_utils.h" #include "chrome/browser/ui/tabs/tab_strip_model.h" +#include "chrome/common/chrome_features.h" #include "chrome/common/chrome_switches.h" +#include "chrome/common/url_constants.h" #include "chrome/test/base/search_test_utils.h" #include "chrome/test/base/ui_test_utils.h" #include "chromeos/login/scoped_test_public_session_login_state.h" +#include "components/google/core/browser/google_switches.h" #include "components/prefs/pref_service.h" #include "components/proxy_config/proxy_config_dictionary.h" #include "components/proxy_config/proxy_config_pref_names.h" @@ -55,6 +70,7 @@ #include "extensions/browser/blocked_action_type.h" #include "extensions/browser/extension_system.h" #include "extensions/common/extension_builder.h" +#include "extensions/common/extension_features.h" #include "extensions/common/features/feature.h" #include "extensions/test/extension_test_message_listener.h" #include "extensions/test/result_catcher.h" @@ -64,13 +80,10 @@ #include "net/http/http_util.h" #include "net/test/embedded_test_server/embedded_test_server.h" #include "net/test/embedded_test_server/http_request.h" +#include "net/test/embedded_test_server/http_response.h" #include "net/test/test_data_directory.h" #include "net/test/url_request/url_request_mock_http_job.h" #include "net/traffic_annotation/network_traffic_annotation_test_helper.h" -#include "net/url_request/test_url_fetcher_factory.h" -#include "net/url_request/url_fetcher.h" -#include "net/url_request/url_fetcher_delegate.h" -#include "net/url_request/url_request_context_getter.h" #include "net/url_request/url_request_filter.h" #include "net/url_request/url_request_interceptor.h" #include "services/network/public/cpp/features.h" @@ -171,56 +184,6 @@ int GetWebRequestCountFromBackgroundPage(const Extension* extension, "window.webRequestCount"); } -// A test delegate to wait allow waiting for responses to complete with an -// expected status and given content. -// TODO(devlin): Other similar classes exist elsewhere. Pull this into a common -// test class. -class TestURLFetcherDelegate : public net::URLFetcherDelegate { - public: - // Creating the TestURLFetcherDelegate automatically creates and starts a - // URLFetcher. - TestURLFetcherDelegate( - scoped_refptr<net::URLRequestContextGetter> context_getter, - const GURL& url, - net::URLRequestStatus expected_request_status) - : expected_request_status_(expected_request_status), - fetcher_(net::URLFetcher::Create(url, - net::URLFetcher::GET, - this, - TRAFFIC_ANNOTATION_FOR_TESTS)) { - fetcher_->SetRequestContext(context_getter.get()); - fetcher_->Start(); - } - ~TestURLFetcherDelegate() override {} - - void SetExpectedResponse(const std::string& expected_response) { - expected_response_ = expected_response; - } - - void WaitForCompletion() { run_loop_.Run(); } - - // net::URLFetcherDelegate: - void OnURLFetchComplete(const net::URLFetcher* source) override { - EXPECT_EQ(expected_request_status_.status(), source->GetStatus().status()); - EXPECT_EQ(expected_request_status_.error(), source->GetStatus().error()); - if (expected_response_) { - std::string response; - ASSERT_TRUE(fetcher_->GetResponseAsString(&response)); - EXPECT_EQ(*expected_response_, response); - } - - run_loop_.Quit(); - } - - private: - const net::URLRequestStatus expected_request_status_; - base::Optional<std::string> expected_response_; - std::unique_ptr<net::URLFetcher> fetcher_; - base::RunLoop run_loop_; - - DISALLOW_COPY_AND_ASSIGN(TestURLFetcherDelegate); -}; - // The DevTool's remote front-end is hardcoded to a URL with a fixed port. // Redirect all responses to a URL with port. class DevToolsFrontendInterceptor : public net::URLRequestInterceptor { @@ -807,11 +770,11 @@ IN_PROC_BROWSER_TEST_F(ExtensionWebRequestApiTest, HostedAppRequest) { EXPECT_TRUE(listener2.WaitUntilSatisfied()); } -// Tests that webRequest works with the --scripts-require-action feature. +// Tests that webRequest works with features::kRuntimeHostPermissions. IN_PROC_BROWSER_TEST_F(ExtensionWebRequestApiTest, WebRequestWithWithheldPermissions) { - FeatureSwitch::ScopedOverride enable_scripts_require_action( - FeatureSwitch::scripts_require_action(), true); + base::test::ScopedFeatureList scoped_feature_list; + scoped_feature_list.InitAndEnableFeature(features::kRuntimeHostPermissions); content::SetupCrossSiteRedirector(embedded_test_server()); ASSERT_TRUE(embedded_test_server()->Start()); @@ -822,6 +785,8 @@ IN_PROC_BROWSER_TEST_F(ExtensionWebRequestApiTest, const Extension* extension = LoadExtension(test_data_dir_.AppendASCII("webrequest_activetab")); ASSERT_TRUE(extension) << message_; + ScriptingPermissionsModifier(profile(), base::WrapRefCounted(extension)) + .SetAllowedOnAllUrls(false); EXPECT_TRUE(listener.WaitUntilSatisfied()); // Navigate the browser to a page in a new tab. @@ -926,14 +891,25 @@ IN_PROC_BROWSER_TEST_F(ExtensionWebRequestApiTest, ASSERT_TRUE(extension) << message_; EXPECT_TRUE(listener.WaitUntilSatisfied()); - EXPECT_EQ(0, GetWebRequestCountFromBackgroundPage(extension, profile())); + auto get_clients_google_request_count = [this, extension]() { + return GetCountFromBackgroundPage(extension, profile(), + "window.clientsGoogleWebRequestCount"); + }; + auto get_yahoo_request_count = [this, extension]() { + return GetCountFromBackgroundPage(extension, profile(), + "window.yahooWebRequestCount"); + }; + + EXPECT_EQ(0, get_clients_google_request_count()); + EXPECT_EQ(0, get_yahoo_request_count()); GURL main_frame_url = embedded_test_server()->GetURL("www.example.com", "/simple.html"); NavigateParams params(browser(), main_frame_url, ui::PAGE_TRANSITION_TYPED); ui_test_utils::NavigateToURL(¶ms); - EXPECT_EQ(0, GetWebRequestCountFromBackgroundPage(extension, profile())); + EXPECT_EQ(0, get_clients_google_request_count()); + EXPECT_EQ(0, get_yahoo_request_count()); content::WebContents* web_contents = browser()->tab_strip_model()->GetActiveWebContents(); @@ -953,33 +929,42 @@ IN_PROC_BROWSER_TEST_F(ExtensionWebRequestApiTest, // Requests always fail due to cross origin nature. EXPECT_FALSE(success); - EXPECT_EQ(1, GetWebRequestCountFromBackgroundPage(extension, profile())); - - // Now perform a request to client1.google.com from the browser process. This - // should *not* be visible to the WebRequest API. - - auto request = std::make_unique<network::ResourceRequest>(); - request->url = - embedded_test_server()->GetURL("clients1.google.com", "/simple.html"); + EXPECT_EQ(1, get_clients_google_request_count()); + EXPECT_EQ(0, get_yahoo_request_count()); + + auto make_browser_request = [this](const GURL& url) { + auto request = std::make_unique<network::ResourceRequest>(); + request->url = url; + + auto* url_loader_factory = + content::BrowserContext::GetDefaultStoragePartition(profile()) + ->GetURLLoaderFactoryForBrowserProcess() + .get(); + content::SimpleURLLoaderTestHelper loader_helper; + auto loader = network::SimpleURLLoader::Create( + std::move(request), TRAFFIC_ANNOTATION_FOR_TESTS); + loader->DownloadToStringOfUnboundedSizeUntilCrashAndDie( + url_loader_factory, loader_helper.GetCallback()); + + // Wait for the response to complete. + loader_helper.WaitForCallback(); + EXPECT_TRUE(loader_helper.response_body()); + EXPECT_EQ(200, loader->ResponseInfo()->headers->response_code()); + }; - auto* url_loader_factory = - content::BrowserContext::GetDefaultStoragePartition(profile()) - ->GetURLLoaderFactoryForBrowserProcess() - .get(); - content::SimpleURLLoaderTestHelper loader_helper; - auto loader = network::SimpleURLLoader::Create(std::move(request), - TRAFFIC_ANNOTATION_FOR_TESTS); - loader->DownloadToStringOfUnboundedSizeUntilCrashAndDie( - url_loader_factory, loader_helper.GetCallback()); - - // Wait for the response to complete. - loader_helper.WaitForCallback(); - EXPECT_TRUE(loader_helper.response_body()); - EXPECT_EQ(200, loader->ResponseInfo()->headers->response_code()); - - // We should still have only seen the single render-initiated request from the - // first half of the test. - EXPECT_EQ(1, GetWebRequestCountFromBackgroundPage(extension, profile())); + // Now perform a request to "client1.google.com" from the browser process. + // This should *not* be visible to the WebRequest API. We should still have + // only seen the single render-initiated request from the first half of the + // test. + make_browser_request( + embedded_test_server()->GetURL("clients1.google.com", "/simple.html")); + EXPECT_EQ(1, get_clients_google_request_count()); + + // Sanity check that other requests made by the browser can still be + // intercepted by the extension. + make_browser_request( + embedded_test_server()->GetURL("yahoo.com", "/simple.html")); + EXPECT_EQ(1, get_yahoo_request_count()); } // Verify that requests for PAC scripts are protected properly. @@ -1156,7 +1141,7 @@ IN_PROC_BROWSER_TEST_F(ExtensionWebRequestApiTest, // Test behavior when intercepting requests from a browser-initiated url fetch. IN_PROC_BROWSER_TEST_F(ExtensionWebRequestApiTest, - WebRequestURLFetcherInterception) { + WebRequestURLLoaderInterception) { // Create an extension that intercepts (and blocks) requests to example.com. TestExtensionDir test_dir; test_dir.WriteManifest( @@ -1177,7 +1162,6 @@ IN_PROC_BROWSER_TEST_F(ExtensionWebRequestApiTest, ["blocking"]); chrome.test.sendMessage('ready');)"); - ASSERT_TRUE(StartEmbeddedTestServer()); const Extension* extension = nullptr; { ExtensionTestMessageListener listener("ready", false); @@ -1186,12 +1170,36 @@ IN_PROC_BROWSER_TEST_F(ExtensionWebRequestApiTest, EXPECT_TRUE(listener.WaitUntilSatisfied()); } - GURL google_url = - embedded_test_server()->GetURL("google.com", "/extensions/body1.html"); // Taken from test/data/extensions/body1.html. const char kGoogleBodyContent[] = "dog"; const char kGoogleFullContent[] = "<html>\n<body>dog</body>\n</html>\n"; + // Taken from test/data/extensions/body2.html. + const char kExampleBodyContent[] = "cat"; + const char kExampleFullContent[] = "<html>\n<body>cat</body>\n</html>\n"; + + embedded_test_server()->RegisterRequestHandler(base::BindLambdaForTesting( + [&](const net::test_server::HttpRequest& request) + -> std::unique_ptr<net::test_server::HttpResponse> { + std::unique_ptr<net::test_server::BasicHttpResponse> response( + new net::test_server::BasicHttpResponse); + if (request.relative_url == "/extensions/body1.html") { + response->set_code(net::HTTP_OK); + response->set_content(kGoogleFullContent); + return std::move(response); + } else if (request.relative_url == "/extensions/body2.html") { + response->set_code(net::HTTP_OK); + response->set_content(kExampleFullContent); + return std::move(response); + } + + return nullptr; + })); + ASSERT_TRUE(StartEmbeddedTestServer()); + + GURL google_url = + embedded_test_server()->GetURL("google.com", "/extensions/body1.html"); + // First, check normal requets (e.g., navigations) to verify the extension // is working correctly. content::WebContents* web_contents = @@ -1210,9 +1218,6 @@ IN_PROC_BROWSER_TEST_F(ExtensionWebRequestApiTest, GURL example_url = embedded_test_server()->GetURL("example.com", "/extensions/body2.html"); - // Taken from test/data/extensions/body2.html. - const char kExampleBodyContent[] = "cat"; - const char kExampleFullContent[] = "<html>\n<body>cat</body>\n</html>\n"; ui_test_utils::NavigateToURL(browser(), example_url); { @@ -1229,47 +1234,74 @@ IN_PROC_BROWSER_TEST_F(ExtensionWebRequestApiTest, EXPECT_NE(kExampleBodyContent, content); } + // A callback allow waiting for responses to complete with an expected status + // and given content. + auto make_browser_request = + [this](network::mojom::URLLoaderFactory* url_loader_factory, + const GURL& url, + const base::Optional<std::string>& expected_response, + int expected_net_code) { + auto request = std::make_unique<network::ResourceRequest>(); + request->url = url; + + content::SimpleURLLoaderTestHelper simple_loader_helper; + auto simple_loader = network::SimpleURLLoader::Create( + std::move(request), TRAFFIC_ANNOTATION_FOR_TESTS); + simple_loader->DownloadToStringOfUnboundedSizeUntilCrashAndDie( + url_loader_factory, simple_loader_helper.GetCallback()); + + simple_loader_helper.WaitForCallback(); + + if (expected_response.has_value()) { + EXPECT_TRUE(!!simple_loader_helper.response_body()); + EXPECT_EQ(*simple_loader_helper.response_body(), *expected_response); + EXPECT_EQ(200, + simple_loader->ResponseInfo()->headers->response_code()); + } else { + EXPECT_FALSE(!!simple_loader_helper.response_body()); + EXPECT_EQ(simple_loader->NetError(), expected_net_code); + } + }; + // Next, try a series of requests through URLRequestFetchers (rather than a // renderer). - net::URLRequestContextGetter* profile_context = - browser()->profile()->GetRequestContext(); + auto* url_loader_factory = + content::BrowserContext::GetDefaultStoragePartition(profile()) + ->GetURLLoaderFactoryForBrowserProcess() + .get(); + { // google.com should be unaffected by the extension and should succeed. - SCOPED_TRACE("google.com with Profile's request context"); - TestURLFetcherDelegate url_fetcher(profile_context, google_url, - net::URLRequestStatus()); - url_fetcher.SetExpectedResponse(kGoogleFullContent); - url_fetcher.WaitForCompletion(); + SCOPED_TRACE("google.com with Profile's url loader"); + make_browser_request(url_loader_factory, google_url, kGoogleFullContent, + net::OK); } + { // example.com should fail. - SCOPED_TRACE("example.com with Profile's request context"); - TestURLFetcherDelegate url_fetcher( - profile_context, example_url, - net::URLRequestStatus(net::URLRequestStatus::FAILED, - net::ERR_BLOCKED_BY_CLIENT)); - url_fetcher.WaitForCompletion(); + SCOPED_TRACE("example.com with Profile's url loader"); + make_browser_request(url_loader_factory, example_url, base::nullopt, + net::ERR_BLOCKED_BY_CLIENT); } - // Requests going through the system request context should always succeed. - net::URLRequestContextGetter* system_context = - g_browser_process->system_request_context(); + // Requests going through the system network context manager should always + // succeed. + SystemNetworkContextManager* system_network_context_manager = + g_browser_process->system_network_context_manager(); + network::mojom::URLLoaderFactory* system_url_loader_factory = + system_network_context_manager->GetURLLoaderFactory(); { // google.com should succeed (again). - SCOPED_TRACE("google.com with System's request context"); - TestURLFetcherDelegate url_fetcher(system_context, google_url, - net::URLRequestStatus()); - url_fetcher.SetExpectedResponse(kGoogleFullContent); - url_fetcher.WaitForCompletion(); + SCOPED_TRACE("google.com with System's network context manager"); + make_browser_request(system_url_loader_factory, google_url, + kGoogleFullContent, net::OK); } { // example.com should also succeed, since it's not through the profile's // request context. - SCOPED_TRACE("example.com with System's request context"); - TestURLFetcherDelegate url_fetcher(system_context, example_url, - net::URLRequestStatus()); - url_fetcher.SetExpectedResponse(kExampleFullContent); - url_fetcher.WaitForCompletion(); + SCOPED_TRACE("example.com with System's network context manager"); + make_browser_request(system_url_loader_factory, example_url, + kExampleFullContent, net::OK); } } @@ -1318,6 +1350,222 @@ IN_PROC_BROWSER_TEST_F(ExtensionWebRequestApiTest, MinimumAccessInitiator) { } } +// Test fixture which sets a custom NTP Page. +class NTPInterceptionWebRequestAPITest : public ExtensionApiTest { + public: + NTPInterceptionWebRequestAPITest() + : https_test_server_(net::EmbeddedTestServer::TYPE_HTTPS) {} + + // ExtensionApiTest override: + void SetUpOnMainThread() override { + ExtensionApiTest::SetUpOnMainThread(); + test_data_dir_ = test_data_dir_.AppendASCII("webrequest") + .AppendASCII("ntp_request_interception"); + https_test_server_.ServeFilesFromDirectory(test_data_dir_); + ASSERT_TRUE(https_test_server_.Start()); + + GURL ntp_url = https_test_server_.GetURL("/fake_ntp.html"); + local_ntp_test_utils::SetUserSelectedDefaultSearchProvider( + profile(), https_test_server_.base_url().spec(), ntp_url.spec()); + } + + const net::EmbeddedTestServer* https_test_server() const { + return &https_test_server_; + } + + private: + net::EmbeddedTestServer https_test_server_; + DISALLOW_COPY_AND_ASSIGN(NTPInterceptionWebRequestAPITest); +}; + +// Ensures that requests made by the NTP Instant renderer are hidden from the +// Web Request API. Regression test for crbug.com/797461. +IN_PROC_BROWSER_TEST_F(NTPInterceptionWebRequestAPITest, + NTPRendererRequestsHidden) { + // Loads an extension which tries to intercept requests to + // "fake_ntp_script.js", which will be loaded as part of the NTP renderer. + ExtensionTestMessageListener listener("ready", true /*will_reply*/); + const Extension* extension = + LoadExtension(test_data_dir_.AppendASCII("extension")); + ASSERT_TRUE(extension); + EXPECT_TRUE(listener.WaitUntilSatisfied()); + + // Have the extension listen for requests to |fake_ntp_script.js|. + listener.Reply(https_test_server()->GetURL("/fake_ntp_script.js").spec()); + + // Returns true if the given extension was able to intercept the request to + // "fake_ntp_script.js". + auto was_script_request_intercepted = + [this](const std::string& extension_id) { + const std::string result = ExecuteScriptInBackgroundPage( + extension_id, "getAndResetRequestIntercepted();"); + EXPECT_TRUE(result == "true" || result == "false") + << "Unexpected result " << result; + return result == "true"; + }; + + // Returns true if the given |web_contents| has window.scriptExecuted set to + // true; + auto was_ntp_script_loaded = [](content::WebContents* web_contents) { + bool was_ntp_script_loaded = false; + EXPECT_TRUE(content::ExecuteScriptAndExtractBool( + web_contents, "domAutomationController.send(!!window.scriptExecuted);", + &was_ntp_script_loaded)); + return was_ntp_script_loaded; + }; + + WebContents* web_contents = + browser()->tab_strip_model()->GetActiveWebContents(); + + // Navigate to the NTP. The request for "fake_ntp_script.js" should not have + // reached the extension, since it was made by the instant NTP renderer, which + // is semi-privileged. + ui_test_utils::NavigateToURL(browser(), GURL(chrome::kChromeUINewTabURL)); + EXPECT_TRUE(was_ntp_script_loaded(web_contents)); + ASSERT_TRUE(search::IsInstantNTP(web_contents)); + EXPECT_FALSE(was_script_request_intercepted(extension->id())); + + // However, when a normal webpage requests the same script, the request should + // be seen by the extension. + ui_test_utils::NavigateToURL( + browser(), https_test_server()->GetURL("/page_with_ntp_script.html")); + EXPECT_TRUE(was_ntp_script_loaded(web_contents)); + ASSERT_FALSE(search::IsInstantNTP(web_contents)); + EXPECT_TRUE(was_script_request_intercepted(extension->id())); +} + +// Test fixture testing that requests made for the OneGoogleBar on behalf of +// the local NTP can't be intercepted by extensions. +class LocalNTPInterceptionWebRequestAPITest + : public ExtensionApiTest, + public OneGoogleBarServiceObserver { + public: + LocalNTPInterceptionWebRequestAPITest() + : https_test_server_(net::EmbeddedTestServer::TYPE_HTTPS) {} + + // ExtensionApiTest override: + void SetUp() override { + https_test_server_.RegisterRequestMonitor(base::BindRepeating( + &LocalNTPInterceptionWebRequestAPITest::MonitorRequest, + base::Unretained(this))); + ASSERT_TRUE(https_test_server_.InitializeAndListen()); + ExtensionApiTest::SetUp(); + feature_list_.InitWithFeatures( + {::features::kUseGoogleLocalNtp, ::features::kOneGoogleBarOnLocalNtp}, + {}); + } + void SetUpCommandLine(base::CommandLine* command_line) override { + ExtensionApiTest::SetUpCommandLine(command_line); + command_line->AppendSwitchASCII(switches::kGoogleBaseURL, + https_test_server_.base_url().spec()); + } + void SetUpOnMainThread() override { + ExtensionApiTest::SetUpOnMainThread(); + + https_test_server_.StartAcceptingConnections(); + + one_google_bar_url_ = + one_google_bar_service()->loader_for_testing()->GetLoadURLForTesting(); + + // Can't declare |runloop_| as a data member on the stack since it needs to + // be be constructed from a single-threaded context. + runloop_ = std::make_unique<base::RunLoop>(); + one_google_bar_service()->AddObserver(this); + } + + // OneGoogleBarServiceObserver overrides: + void OnOneGoogleBarDataUpdated() override { runloop_->Quit(); } + void OnOneGoogleBarServiceShuttingDown() override { + one_google_bar_service()->RemoveObserver(this); + } + + GURL one_google_bar_url() const { return one_google_bar_url_; } + + // Waits for OneGoogleBar data to be updated. Should only be used once. + void WaitForOneGoogleBarDataUpdate() { runloop_->Run(); } + + bool GetAndResetOneGoogleBarRequestSeen() { + base::AutoLock lock(lock_); + bool result = one_google_bar_request_seen_; + one_google_bar_request_seen_ = false; + return result; + } + + private: + OneGoogleBarService* one_google_bar_service() { + return OneGoogleBarServiceFactory::GetForProfile(profile()); + } + + void MonitorRequest(const net::test_server::HttpRequest& request) { + if (request.GetURL() == one_google_bar_url_) { + base::AutoLock lock(lock_); + one_google_bar_request_seen_ = true; + } + } + + net::EmbeddedTestServer https_test_server_; + base::test::ScopedFeatureList feature_list_; + std::unique_ptr<base::RunLoop> runloop_; + + // Initialized on the UI thread in SetUpOnMainThread. Read on UI and Embedded + // Test Server IO thread thereafter. + GURL one_google_bar_url_; + + // Accessed on multiple threads- UI and Embedded Test Server IO thread. Access + // requires acquiring |lock_|. + bool one_google_bar_request_seen_ = false; + + base::Lock lock_; + + DISALLOW_COPY_AND_ASSIGN(LocalNTPInterceptionWebRequestAPITest); +}; + +IN_PROC_BROWSER_TEST_F(LocalNTPInterceptionWebRequestAPITest, + OneGoogleBarRequestsHidden) { + // Loads an extension which tries to intercept requests to the OneGoogleBar. + ExtensionTestMessageListener listener("ready", true /*will_reply*/); + const Extension* extension = + LoadExtension(test_data_dir_.AppendASCII("webrequest") + .AppendASCII("ntp_request_interception") + .AppendASCII("extension")); + ASSERT_TRUE(extension); + EXPECT_TRUE(listener.WaitUntilSatisfied()); + + // Have the extension listen for requests to |one_google_bar_url()|. + listener.Reply(one_google_bar_url().spec()); + + // Returns true if the given extension was able to intercept the request to + // |one_google_bar_url()|. + auto was_script_request_intercepted = + [this](const std::string& extension_id) { + const std::string result = ExecuteScriptInBackgroundPage( + extension_id, "getAndResetRequestIntercepted();"); + EXPECT_TRUE(result == "true" || result == "false") + << "Unexpected result " << result; + return result == "true"; + }; + + WebContents* web_contents = + browser()->tab_strip_model()->GetActiveWebContents(); + + ASSERT_FALSE(GetAndResetOneGoogleBarRequestSeen()); + ui_test_utils::NavigateToURL(browser(), GURL(chrome::kChromeUINewTabURL)); + ASSERT_TRUE(search::IsInstantNTP(web_contents)); + ASSERT_EQ(GURL(chrome::kChromeSearchLocalNtpUrl), + web_contents->GetController().GetVisibleEntry()->GetURL()); + WaitForOneGoogleBarDataUpdate(); + ASSERT_TRUE(GetAndResetOneGoogleBarRequestSeen()); + + // Ensure that the extension wasn't able to intercept the request. + EXPECT_FALSE(was_script_request_intercepted(extension->id())); + + // A normal request to |one_google_bar_url()| (i.e. not made by + // OneGoogleBarFetcher) should be intercepted by extensions. + ui_test_utils::NavigateToURL(browser(), one_google_bar_url()); + EXPECT_TRUE(was_script_request_intercepted(extension->id())); + ASSERT_TRUE(GetAndResetOneGoogleBarRequestSeen()); +} + // Ensure that devtools frontend requests are hidden from the webRequest API. IN_PROC_BROWSER_TEST_F(DevToolsFrontendInWebRequestApiTest, HiddenRequests) { // Test expectations differ with the Network Service because of the way @@ -1346,7 +1594,7 @@ IN_PROC_BROWSER_TEST_F(ExtensionApiTestWithManagementPolicy, // means that the request to example.com will be seen by the extension. { ExtensionManagementPolicyUpdater pref(&policy_provider_); - pref.AddRuntimeBlockedHost("*", "*://notexample.com"); + pref.AddPolicyBlockedHost("*", "*://notexample.com"); } ASSERT_TRUE(StartEmbeddedTestServer()); @@ -1401,7 +1649,7 @@ IN_PROC_BROWSER_TEST_F(ExtensionApiTestWithManagementPolicy, // will not be seen by the extension. { ExtensionManagementPolicyUpdater pref(&policy_provider_); - pref.AddRuntimeBlockedHost("*", "*://" + example_com); + pref.AddPolicyBlockedHost("*", "*://" + example_com); } // Wait until all remote Javascript files have been pulled down. @@ -1419,14 +1667,15 @@ IN_PROC_BROWSER_TEST_F(ExtensionApiTestWithManagementPolicy, // Tests that the webRequest events aren't dispatched when the URL of the // request is protected by policy. +// Disabled because it is flaky. See https://crbug.com/835155 IN_PROC_BROWSER_TEST_F(ExtensionApiTestWithManagementPolicy, - UrlProtectedByPolicy) { + DISABLED_UrlProtectedByPolicy) { // Host protected by policy. const std::string protected_domain = "example.com"; { ExtensionManagementPolicyUpdater pref(&policy_provider_); - pref.AddRuntimeBlockedHost("*", "*://" + protected_domain); + pref.AddPolicyBlockedHost("*", "*://" + protected_domain); } ASSERT_TRUE(StartEmbeddedTestServer()); @@ -1474,15 +1723,15 @@ IN_PROC_BROWSER_TEST_F(ExtensionApiTestWithManagementPolicy, // specific permission shouldn't bypass our policy. IN_PROC_BROWSER_TEST_F(ExtensionApiTestWithManagementPolicy, WebRequestProtectedByPolicy) { - FeatureSwitch::ScopedOverride enable_scripts_require_action( - FeatureSwitch::scripts_require_action(), true); + base::test::ScopedFeatureList scoped_feature_list; + scoped_feature_list.InitAndEnableFeature(features::kRuntimeHostPermissions); // Host protected by policy. const std::string protected_domain = "example.com"; { ExtensionManagementPolicyUpdater pref(&policy_provider_); - pref.AddRuntimeBlockedHost("*", "*://" + protected_domain); + pref.AddPolicyBlockedHost("*", "*://" + protected_domain); } ASSERT_TRUE(StartEmbeddedTestServer()); @@ -1491,6 +1740,8 @@ IN_PROC_BROWSER_TEST_F(ExtensionApiTestWithManagementPolicy, const Extension* extension = LoadExtension(test_data_dir_.AppendASCII("webrequest_activetab")); ASSERT_TRUE(extension) << message_; + ScriptingPermissionsModifier(profile(), base::WrapRefCounted(extension)) + .SetAllowedOnAllUrls(false); EXPECT_TRUE(listener.WaitUntilSatisfied()); // Navigate the browser to a page in a new tab. diff --git a/chromium/chrome/browser/extensions/api/web_request/web_request_permissions_unittest.cc b/chromium/chrome/browser/extensions/api/web_request/web_request_permissions_unittest.cc index b2723a15ed6..ab284e6b1d8 100644 --- a/chromium/chrome/browser/extensions/api/web_request/web_request_permissions_unittest.cc +++ b/chromium/chrome/browser/extensions/api/web_request/web_request_permissions_unittest.cc @@ -7,7 +7,6 @@ #include <memory> #include "base/macros.h" -#include "base/message_loop/message_loop.h" #include "chrome/common/extensions/extension_test_util.h" #include "chromeos/login/scoped_test_public_session_login_state.h" #include "content/public/browser/resource_request_info.h" @@ -199,14 +198,14 @@ TEST_F(ExtensionWebRequestHelpersTestWithThreadsTest, NULL, TRAFFIC_ANNOTATION_FOR_TESTS)); EXPECT_EQ( - PermissionsData::ACCESS_ALLOWED, + PermissionsData::PageAccess::kAllowed, WebRequestPermissions::CanExtensionAccessURL( extension_info_map_.get(), permissionless_extension_->id(), request->url(), -1, // No tab id. false, // crosses_incognito WebRequestPermissions::DO_NOT_CHECK_HOST, request->initiator())); - EXPECT_EQ(PermissionsData::ACCESS_DENIED, + EXPECT_EQ(PermissionsData::PageAccess::kDenied, WebRequestPermissions::CanExtensionAccessURL( extension_info_map_.get(), permissionless_extension_->id(), request->url(), @@ -214,7 +213,7 @@ TEST_F(ExtensionWebRequestHelpersTestWithThreadsTest, false, // crosses_incognito WebRequestPermissions::REQUIRE_HOST_PERMISSION_FOR_URL, request->initiator())); - EXPECT_EQ(PermissionsData::ACCESS_ALLOWED, + EXPECT_EQ(PermissionsData::PageAccess::kAllowed, WebRequestPermissions::CanExtensionAccessURL( extension_info_map_.get(), com_extension_->id(), request->url(), -1, // No tab id. @@ -222,14 +221,14 @@ TEST_F(ExtensionWebRequestHelpersTestWithThreadsTest, WebRequestPermissions::REQUIRE_HOST_PERMISSION_FOR_URL, request->initiator())); EXPECT_EQ( - PermissionsData::ACCESS_ALLOWED, + PermissionsData::PageAccess::kAllowed, WebRequestPermissions::CanExtensionAccessURL( extension_info_map_.get(), com_extension_->id(), request->url(), -1, // No tab id. false, // crosses_incognito WebRequestPermissions::REQUIRE_HOST_PERMISSION_FOR_URL_AND_INITIATOR, request->initiator())); - EXPECT_EQ(PermissionsData::ACCESS_DENIED, + EXPECT_EQ(PermissionsData::PageAccess::kDenied, WebRequestPermissions::CanExtensionAccessURL( extension_info_map_.get(), com_extension_->id(), request->url(), -1, // No tab id. @@ -242,7 +241,7 @@ TEST_F(ExtensionWebRequestHelpersTestWithThreadsTest, request_with_initiator->set_initiator( url::Origin::Create(GURL("http://www.example.org"))); - EXPECT_EQ(PermissionsData::ACCESS_ALLOWED, + EXPECT_EQ(PermissionsData::PageAccess::kAllowed, WebRequestPermissions::CanExtensionAccessURL( extension_info_map_.get(), permissionless_extension_->id(), request_with_initiator->url(), @@ -250,7 +249,7 @@ TEST_F(ExtensionWebRequestHelpersTestWithThreadsTest, false, // crosses_incognito WebRequestPermissions::DO_NOT_CHECK_HOST, request_with_initiator->initiator())); - EXPECT_EQ(PermissionsData::ACCESS_DENIED, + EXPECT_EQ(PermissionsData::PageAccess::kDenied, WebRequestPermissions::CanExtensionAccessURL( extension_info_map_.get(), permissionless_extension_->id(), request_with_initiator->url(), @@ -258,7 +257,7 @@ TEST_F(ExtensionWebRequestHelpersTestWithThreadsTest, false, // crosses_incognito WebRequestPermissions::REQUIRE_HOST_PERMISSION_FOR_URL, request_with_initiator->initiator())); - EXPECT_EQ(PermissionsData::ACCESS_ALLOWED, + EXPECT_EQ(PermissionsData::PageAccess::kAllowed, WebRequestPermissions::CanExtensionAccessURL( extension_info_map_.get(), com_extension_->id(), request_with_initiator->url(), @@ -267,7 +266,7 @@ TEST_F(ExtensionWebRequestHelpersTestWithThreadsTest, WebRequestPermissions::REQUIRE_HOST_PERMISSION_FOR_URL, request_with_initiator->initiator())); EXPECT_EQ( - PermissionsData::ACCESS_DENIED, + PermissionsData::PageAccess::kDenied, WebRequestPermissions::CanExtensionAccessURL( extension_info_map_.get(), com_extension_->id(), request_with_initiator->url(), @@ -275,7 +274,7 @@ TEST_F(ExtensionWebRequestHelpersTestWithThreadsTest, false, // crosses_incognito WebRequestPermissions::REQUIRE_HOST_PERMISSION_FOR_URL_AND_INITIATOR, request_with_initiator->initiator())); - EXPECT_EQ(PermissionsData::ACCESS_DENIED, + EXPECT_EQ(PermissionsData::PageAccess::kDenied, WebRequestPermissions::CanExtensionAccessURL( extension_info_map_.get(), com_extension_->id(), request_with_initiator->url(), @@ -290,7 +289,7 @@ TEST_F(ExtensionWebRequestHelpersTestWithThreadsTest, GURL("http://example.org"), net::DEFAULT_PRIORITY, nullptr)); // com_extension_ doesn't have host permission for .org URLs. - EXPECT_EQ(PermissionsData::ACCESS_DENIED, + EXPECT_EQ(PermissionsData::PageAccess::kDenied, WebRequestPermissions::CanExtensionAccessURL( extension_info_map_.get(), com_policy_extension_->id(), org_request->url(), @@ -303,7 +302,7 @@ TEST_F(ExtensionWebRequestHelpersTestWithThreadsTest, // Host permission checks are disabled in Public Sessions, instead all URLs // are whitelisted. - EXPECT_EQ(PermissionsData::ACCESS_ALLOWED, + EXPECT_EQ(PermissionsData::PageAccess::kAllowed, WebRequestPermissions::CanExtensionAccessURL( extension_info_map_.get(), com_policy_extension_->id(), org_request->url(), @@ -313,7 +312,7 @@ TEST_F(ExtensionWebRequestHelpersTestWithThreadsTest, org_request->initiator())); EXPECT_EQ( - PermissionsData::ACCESS_ALLOWED, + PermissionsData::PageAccess::kAllowed, WebRequestPermissions::CanExtensionAccessURL( extension_info_map_.get(), com_policy_extension_->id(), org_request->url(), @@ -326,7 +325,7 @@ TEST_F(ExtensionWebRequestHelpersTestWithThreadsTest, context.CreateRequest(GURL("chrome://version/"), net::DEFAULT_PRIORITY, nullptr, TRAFFIC_ANNOTATION_FOR_TESTS)); - EXPECT_EQ(PermissionsData::ACCESS_DENIED, + EXPECT_EQ(PermissionsData::PageAccess::kDenied, WebRequestPermissions::CanExtensionAccessURL( extension_info_map_.get(), com_policy_extension_->id(), chrome_request->url(), diff --git a/chromium/chrome/browser/extensions/api/webrtc_audio_private/webrtc_audio_private_api.cc b/chromium/chrome/browser/extensions/api/webrtc_audio_private/webrtc_audio_private_api.cc index 910c324ba2e..3f29daeb4db 100644 --- a/chromium/chrome/browser/extensions/api/webrtc_audio_private/webrtc_audio_private_api.cc +++ b/chromium/chrome/browser/extensions/api/webrtc_audio_private/webrtc_audio_private_api.cc @@ -284,7 +284,6 @@ WebrtcAudioPrivateSetAudioExperimentsFunction:: ~WebrtcAudioPrivateSetAudioExperimentsFunction() {} bool WebrtcAudioPrivateSetAudioExperimentsFunction::RunAsync() { -#if BUILDFLAG(ENABLE_WEBRTC) DCHECK_CURRENTLY_ON(BrowserThread::UI); std::unique_ptr<wap::SetAudioExperiments::Params> params( wap::SetAudioExperiments::Params::Create(*args_)); @@ -312,11 +311,6 @@ bool WebrtcAudioPrivateSetAudioExperimentsFunction::RunAsync() { &WebrtcAudioPrivateSetAudioExperimentsFunction::FireCallback, this)); return true; -#else - SetError("Not supported"); - SendResponse(false); - return false; -#endif } void WebrtcAudioPrivateSetAudioExperimentsFunction::FireCallback( diff --git a/chromium/chrome/browser/extensions/api/webrtc_logging_private/webrtc_logging_private_api.h b/chromium/chrome/browser/extensions/api/webrtc_logging_private/webrtc_logging_private_api.h index 157ed003914..6ab73874ae1 100644 --- a/chromium/chrome/browser/extensions/api/webrtc_logging_private/webrtc_logging_private_api.h +++ b/chromium/chrome/browser/extensions/api/webrtc_logging_private/webrtc_logging_private_api.h @@ -8,13 +8,10 @@ #include <string> #include "chrome/browser/extensions/chrome_extension_function.h" -#include "chrome/common/extensions/api/webrtc_logging_private.h" -#include "media/media_buildflags.h" - -#if BUILDFLAG(ENABLE_WEBRTC) #include "chrome/browser/media/webrtc/audio_debug_recordings_handler.h" #include "chrome/browser/media/webrtc/webrtc_logging_handler_host.h" -#endif +#include "chrome/common/extensions/api/webrtc_logging_private.h" +#include "media/media_buildflags.h" namespace content { @@ -28,7 +25,6 @@ class WebrtcLoggingPrivateFunction : public ChromeAsyncExtensionFunction { protected: ~WebrtcLoggingPrivateFunction() override {} -#if BUILDFLAG(ENABLE_WEBRTC) // Returns the RenderProcessHost associated with the given |request| // authorized by the |security_origin|. Returns null if unauthorized or // the RPH does not exist. @@ -39,7 +35,6 @@ class WebrtcLoggingPrivateFunction : public ChromeAsyncExtensionFunction { scoped_refptr<WebRtcLoggingHandlerHost> LoggingHandlerFromRequest( const api::webrtc_logging_private::RequestInfo& request, const std::string& security_origin); -#endif }; class WebrtcLoggingPrivateFunctionWithGenericCallback @@ -47,7 +42,6 @@ class WebrtcLoggingPrivateFunctionWithGenericCallback protected: ~WebrtcLoggingPrivateFunctionWithGenericCallback() override {} -#if BUILDFLAG(ENABLE_WEBRTC) // Finds the appropriate logging handler for performing the task and prepares // a generic callback object for when the task is completed. // If the logging handler can't be found for the given request+origin, the @@ -59,7 +53,6 @@ class WebrtcLoggingPrivateFunctionWithGenericCallback // Must be called on UI thread. void FireCallback(bool success, const std::string& error_message); -#endif }; class WebrtcLoggingPrivateFunctionWithUploadCallback @@ -67,11 +60,9 @@ class WebrtcLoggingPrivateFunctionWithUploadCallback protected: ~WebrtcLoggingPrivateFunctionWithUploadCallback() override {} -#if BUILDFLAG(ENABLE_WEBRTC) // Must be called on UI thread. void FireCallback(bool success, const std::string& report_id, const std::string& error_message); -#endif }; class WebrtcLoggingPrivateFunctionWithRecordingDoneCallback @@ -79,13 +70,11 @@ class WebrtcLoggingPrivateFunctionWithRecordingDoneCallback protected: ~WebrtcLoggingPrivateFunctionWithRecordingDoneCallback() override {} -#if BUILDFLAG(ENABLE_WEBRTC) // Must be called on UI thread. void FireErrorCallback(const std::string& error_message); void FireCallback(const std::string& prefix_path, bool did_stop, bool did_manual_stop); -#endif }; class WebrtcLoggingPrivateSetMetaDataFunction @@ -287,12 +276,10 @@ class WebrtcLoggingPrivateGetLogsDirectoryFunction // ExtensionFunction overrides. bool RunAsync() override; -#if BUILDFLAG(ENABLE_WEBRTC) // Must be called on UI thread. void FireErrorCallback(const std::string& error_message); void FireCallback(const std::string& filesystem_id, const std::string& base_name); -#endif }; } // namespace extensions diff --git a/chromium/chrome/browser/extensions/api/webrtc_logging_private/webrtc_logging_private_api_stub.cc b/chromium/chrome/browser/extensions/api/webrtc_logging_private/webrtc_logging_private_api_stub.cc deleted file mode 100644 index a47726a9a25..00000000000 --- a/chromium/chrome/browser/extensions/api/webrtc_logging_private/webrtc_logging_private_api_stub.cc +++ /dev/null @@ -1,95 +0,0 @@ -// Copyright 2013 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. -// -// Stub implementation used when WebRTC is not enabled. - -#include "chrome/browser/extensions/api/webrtc_logging_private/webrtc_logging_private_api.h" - -namespace extensions { - -namespace { - -const char kErrorNotSupported[] = "Not supported"; - -} // namespace - -bool WebrtcLoggingPrivateSetMetaDataFunction::RunAsync() { - SetError(kErrorNotSupported); - SendResponse(false); - return false; -} - -bool WebrtcLoggingPrivateStartFunction::RunAsync() { - SetError(kErrorNotSupported); - SendResponse(false); - return false; -} - -bool WebrtcLoggingPrivateSetUploadOnRenderCloseFunction::RunAsync() { - SetError(kErrorNotSupported); - SendResponse(false); - return false; -} - -bool WebrtcLoggingPrivateStopFunction::RunAsync() { - SetError(kErrorNotSupported); - SendResponse(false); - return false; -} - -bool WebrtcLoggingPrivateStoreFunction::RunAsync() { - SetError(kErrorNotSupported); - SendResponse(false); - return false; -} - -bool WebrtcLoggingPrivateUploadStoredFunction::RunAsync() { - SetError(kErrorNotSupported); - SendResponse(false); - return false; -} - -bool WebrtcLoggingPrivateUploadFunction::RunAsync() { - SetError(kErrorNotSupported); - SendResponse(false); - return false; -} - -bool WebrtcLoggingPrivateDiscardFunction::RunAsync() { - SetError(kErrorNotSupported); - SendResponse(false); - return false; -} - -bool WebrtcLoggingPrivateStartRtpDumpFunction::RunAsync() { - SetError(kErrorNotSupported); - SendResponse(false); - return false; -} - -bool WebrtcLoggingPrivateStopRtpDumpFunction::RunAsync() { - SetError(kErrorNotSupported); - SendResponse(false); - return false; -} - -bool WebrtcLoggingPrivateStartAudioDebugRecordingsFunction::RunAsync() { - SetError(kErrorNotSupported); - SendResponse(false); - return false; -} - -bool WebrtcLoggingPrivateStopAudioDebugRecordingsFunction::RunAsync() { - SetError(kErrorNotSupported); - SendResponse(false); - return false; -} - -bool WebrtcLoggingPrivateGetLogsDirectoryFunction::RunAsync() { - SetError(kErrorNotSupported); - SendResponse(false); - return false; -} - -} // namespace extensions diff --git a/chromium/chrome/browser/extensions/api/webrtc_logging_private/webrtc_logging_private_apitest.cc b/chromium/chrome/browser/extensions/api/webrtc_logging_private/webrtc_logging_private_apitest.cc index 3eb34990543..c878060ff8f 100644 --- a/chromium/chrome/browser/extensions/api/webrtc_logging_private/webrtc_logging_private_apitest.cc +++ b/chromium/chrome/browser/extensions/api/webrtc_logging_private/webrtc_logging_private_apitest.cc @@ -71,12 +71,12 @@ void InitializeTestMetaData(base::ListValue* parameters) { parameters->Append(std::move(meta_data)); } -class WebrtcLoggingPrivateApiTest : public ExtensionApiTest { +class WebrtcLoggingPrivateApiTest : public extensions::ExtensionApiTest { protected: void SetUp() override { auto* cl = scoped_command_line_.GetProcessCommandLine(); cl->AppendSwitchASCII(::switches::kWebRtcRemoteEventLog, "enabled"); - ExtensionApiTest::SetUp(); + extensions::ExtensionApiTest::SetUp(); extension_ = extensions::ExtensionBuilder("Test").Build(); } @@ -347,7 +347,7 @@ class WebrtcLoggingPrivateApiTestDisabledRemoteLogging void SetUp() override { auto* cl = scoped_command_line_.GetProcessCommandLine(); cl->AppendSwitchASCII(::switches::kWebRtcRemoteEventLog, "disabled"); - ExtensionApiTest::SetUp(); + extensions::ExtensionApiTest::SetUp(); extension_ = extensions::ExtensionBuilder("Test").Build(); } }; diff --git a/chromium/chrome/browser/extensions/api/webstore_private/webstore_private_api.cc b/chromium/chrome/browser/extensions/api/webstore_private/webstore_private_api.cc index 3a33fe8e797..6d06524c940 100644 --- a/chromium/chrome/browser/extensions/api/webstore_private/webstore_private_api.cc +++ b/chromium/chrome/browser/extensions/api/webstore_private/webstore_private_api.cc @@ -8,6 +8,7 @@ #include <utility> #include <vector> +#include "base/base64.h" #include "base/bind.h" #include "base/lazy_instance.h" #include "base/macros.h" @@ -17,11 +18,14 @@ #include "base/values.h" #include "base/version.h" #include "chrome/browser/bitmap_fetcher/bitmap_fetcher.h" +#include "chrome/browser/browser_process.h" #include "chrome/browser/extensions/crx_installer.h" #include "chrome/browser/extensions/extension_service.h" #include "chrome/browser/extensions/extension_util.h" #include "chrome/browser/extensions/install_tracker.h" #include "chrome/browser/profiles/profile.h" +#include "chrome/browser/safe_browsing/safe_browsing_navigation_observer_manager.h" +#include "chrome/browser/safe_browsing/safe_browsing_service.h" #include "chrome/browser/signin/signin_manager_factory.h" #include "chrome/browser/ui/app_list/app_list_util.h" #include "chrome/common/extensions/extension_constants.h" @@ -32,6 +36,7 @@ #include "content/public/browser/gpu_feature_checker.h" #include "content/public/browser/storage_partition.h" #include "content/public/browser/web_contents.h" +#include "extensions/browser/extension_function_constants.h" #include "extensions/browser/extension_registry.h" #include "extensions/browser/extension_system.h" #include "extensions/common/extension.h" @@ -44,6 +49,8 @@ #include "chrome/browser/supervised_user/supervised_user_service_factory.h" #endif +using safe_browsing::SafeBrowsingNavigationObserverManager; + namespace extensions { namespace BeginInstallWithManifest3 = @@ -60,6 +67,7 @@ namespace IsPendingCustodianApproval = namespace IsInIncognitoMode = api::webstore_private::IsInIncognitoMode; namespace LaunchEphemeralApp = api::webstore_private::LaunchEphemeralApp; namespace SetStoreLogin = api::webstore_private::SetStoreLogin; +namespace GetReferrerChain = api::webstore_private::GetReferrerChain; namespace { @@ -140,6 +148,9 @@ const char kIncognitoError[] = const char kEphemeralAppLaunchingNotSupported[] = "Ephemeral launching of apps is no longer supported."; +// The number of user gestures to trace back for the referrer chain. +const int kExtensionReferrerUserGestureLimit = 2; + WebstoreInstaller::Delegate* test_webstore_installer_delegate = nullptr; // We allow the web store to set a string containing login information when a @@ -299,7 +310,7 @@ void WebstorePrivateBeginInstallWithManifest3Function::OnWebstoreParseSuccess( return; } - content::WebContents* web_contents = GetAssociatedWebContents(); + content::WebContents* web_contents = GetSenderWebContents(); if (!web_contents) { // The browser window has gone away. Respond(BuildResponse(api::webstore_private::RESULT_USER_CANCELLED, @@ -435,6 +446,12 @@ WebstorePrivateCompleteInstallFunction::Run() { params->expected_id)); } + content::WebContents* web_contents = GetSenderWebContents(); + if (!web_contents) { + return RespondNow( + Error(function_constants::kCouldNotFindSenderWebContents)); + } + scoped_active_install_.reset(new ScopedActiveInstall( InstallTracker::Get(browser_context()), params->expected_id)); @@ -444,8 +461,7 @@ WebstorePrivateCompleteInstallFunction::Run() { // The extension will install through the normal extension install flow, but // the whitelist entry will bypass the normal permissions install dialog. scoped_refptr<WebstoreInstaller> installer = new WebstoreInstaller( - chrome_details_.GetProfile(), this, - chrome_details_.GetAssociatedWebContents(), params->expected_id, + chrome_details_.GetProfile(), this, web_contents, params->expected_id, std::move(approval_), WebstoreInstaller::INSTALL_SOURCE_OTHER); installer->Start(); @@ -657,4 +673,57 @@ WebstorePrivateIsPendingCustodianApprovalFunction::BuildResponse(bool result) { return OneArgument(std::make_unique<base::Value>(result)); } +WebstorePrivateGetReferrerChainFunction:: + WebstorePrivateGetReferrerChainFunction() + : chrome_details_(this) {} + +WebstorePrivateGetReferrerChainFunction:: + ~WebstorePrivateGetReferrerChainFunction() {} + +ExtensionFunction::ResponseAction +WebstorePrivateGetReferrerChainFunction::Run() { + Profile* profile = chrome_details_.GetProfile(); + if (!SafeBrowsingNavigationObserverManager::IsEnabledAndReady(profile)) + return RespondNow(ArgumentList(GetReferrerChain::Results::Create(""))); + + content::WebContents* web_contents = GetSenderWebContents(); + if (!web_contents) { + return RespondNow(ErrorWithArguments(GetReferrerChain::Results::Create(""), + kUserCancelledError)); + } + + scoped_refptr<SafeBrowsingNavigationObserverManager> + navigation_observer_manager = g_browser_process->safe_browsing_service() + ->navigation_observer_manager(); + + safe_browsing::ReferrerChain referrer_chain; + SafeBrowsingNavigationObserverManager::AttributionResult result = + navigation_observer_manager->IdentifyReferrerChainByWebContents( + web_contents, kExtensionReferrerUserGestureLimit, &referrer_chain); + + // If the referrer chain is incomplete we'll append the most recent + // navigations to referrer chain for diagnostic purposes. This only happens if + // the user is not in incognito mode and has opted into extended reporting or + // Scout reporting. Otherwise, |CountOfRecentNavigationsToAppend| returns 0. + int recent_navigations_to_collect = + SafeBrowsingNavigationObserverManager::CountOfRecentNavigationsToAppend( + *profile, result); + if (recent_navigations_to_collect > 0) { + navigation_observer_manager->AppendRecentNavigations( + recent_navigations_to_collect, &referrer_chain); + } + + safe_browsing::ExtensionWebStoreInstallRequest request; + request.mutable_referrer_chain()->Swap(&referrer_chain); + request.mutable_referrer_chain_options()->set_recent_navigations_to_collect( + recent_navigations_to_collect); + + std::string serialized_referrer_proto = request.SerializeAsString(); + // Base64 encode the proto to avoid issues with base::Value rejecting strings + // which are not valid UTF8. + base::Base64Encode(serialized_referrer_proto, &serialized_referrer_proto); + return RespondNow(ArgumentList( + GetReferrerChain::Results::Create(serialized_referrer_proto))); +} + } // namespace extensions diff --git a/chromium/chrome/browser/extensions/api/webstore_private/webstore_private_api.h b/chromium/chrome/browser/extensions/api/webstore_private/webstore_private_api.h index 8af8ccc53a6..c131838423e 100644 --- a/chromium/chrome/browser/extensions/api/webstore_private/webstore_private_api.h +++ b/chromium/chrome/browser/extensions/api/webstore_private/webstore_private_api.h @@ -304,6 +304,25 @@ class WebstorePrivateIsPendingCustodianApprovalFunction ChromeExtensionFunctionDetails chrome_details_; }; +class WebstorePrivateGetReferrerChainFunction + : public UIThreadExtensionFunction { + public: + DECLARE_EXTENSION_FUNCTION("webstorePrivate.getReferrerChain", + WEBSTOREPRIVATE_GETREFERRERCHAIN) + + WebstorePrivateGetReferrerChainFunction(); + + private: + ~WebstorePrivateGetReferrerChainFunction() override; + + // ExtensionFunction: + ExtensionFunction::ResponseAction Run() override; + + ChromeExtensionFunctionDetails chrome_details_; + + DISALLOW_COPY_AND_ASSIGN(WebstorePrivateGetReferrerChainFunction); +}; + } // namespace extensions #endif // CHROME_BROWSER_EXTENSIONS_API_WEBSTORE_PRIVATE_WEBSTORE_PRIVATE_API_H_ diff --git a/chromium/chrome/browser/extensions/api/webstore_private/webstore_private_apitest.cc b/chromium/chrome/browser/extensions/api/webstore_private/webstore_private_apitest.cc index f33655acf2d..4819cef550e 100644 --- a/chromium/chrome/browser/extensions/api/webstore_private/webstore_private_apitest.cc +++ b/chromium/chrome/browser/extensions/api/webstore_private/webstore_private_apitest.cc @@ -7,7 +7,6 @@ #include "base/files/file_path.h" #include "base/files/file_util.h" #include "base/macros.h" -#include "base/message_loop/message_loop.h" #include "base/run_loop.h" #include "base/strings/utf_string_conversions.h" #include "base/threading/thread_restrictions.h" @@ -432,4 +431,50 @@ IN_PROC_BROWSER_TEST_F(ExtensionWebstoreGetWebGLStatusTest, Blocked) { RunTest(webgl_allowed); } +class ExtensionWebstorePrivateGetReferrerChainApiTest + : public ExtensionWebstorePrivateApiTest { + public: + void SetUpOnMainThread() override { + host_resolver()->AddRule("redirect1.com", "127.0.0.1"); + host_resolver()->AddRule("redirect2.com", "127.0.0.1"); + + ExtensionWebstorePrivateApiTest::SetUpOnMainThread(); + } + + GURL GetTestServerURLWithReferrers(const std::string& path) { + // Hand craft a url that will cause the test server to issue redirects. + const std::vector<std::string> redirects = {"redirect1.com", + "redirect2.com"}; + net::HostPortPair host_port = embedded_test_server()->host_port_pair(); + std::string redirect_chain; + for (const auto& redirect : redirects) { + std::string redirect_url = base::StringPrintf( + "http://%s:%d/server-redirect?", redirect.c_str(), host_port.port()); + redirect_chain += redirect_url; + } + + return GURL(redirect_chain + GetTestServerURL(path).spec()); + } +}; + +// Tests that the GetReferrerChain API returns the redirect information. +IN_PROC_BROWSER_TEST_F(ExtensionWebstorePrivateGetReferrerChainApiTest, + GetReferrerChain) { + GURL page_url = GetTestServerURLWithReferrers("referrer_chain.html"); + ASSERT_TRUE(RunPageTest(page_url.spec())); +} + +// Tests that the GetReferrerChain API returns an empty string for profiles +// opted out of SafeBrowsing. +IN_PROC_BROWSER_TEST_F(ExtensionWebstorePrivateGetReferrerChainApiTest, + GetReferrerChainForNonSafeBrowsingUser) { + PrefService* pref_service = browser()->profile()->GetPrefs(); + EXPECT_TRUE(pref_service->GetBoolean(prefs::kSafeBrowsingEnabled)); + // Disable SafeBrowsing. + pref_service->SetBoolean(prefs::kSafeBrowsingEnabled, false); + + GURL page_url = GetTestServerURLWithReferrers("empty_referrer_chain.html"); + ASSERT_TRUE(RunPageTest(page_url.spec())); +} + } // namespace extensions diff --git a/chromium/chrome/browser/extensions/api/webstore_widget_private/app_installer.cc b/chromium/chrome/browser/extensions/api/webstore_widget_private/app_installer.cc index 3c1af8493f7..003dc82da45 100644 --- a/chromium/chrome/browser/extensions/api/webstore_widget_private/app_installer.cc +++ b/chromium/chrome/browser/extensions/api/webstore_widget_private/app_installer.cc @@ -42,6 +42,7 @@ AppInstaller::AppInstaller(content::WebContents* web_contents, callback_(callback), web_contents_(web_contents), web_contents_observer_(new WebContentsObserver(web_contents, this)) { + DCHECK(web_contents_); } AppInstaller::~AppInstaller() { diff --git a/chromium/chrome/browser/extensions/api/webstore_widget_private/webstore_widget_private_api.cc b/chromium/chrome/browser/extensions/api/webstore_widget_private/webstore_widget_private_api.cc index 50ea3fc8820..f8f5aa30cb9 100644 --- a/chromium/chrome/browser/extensions/api/webstore_widget_private/webstore_widget_private_api.cc +++ b/chromium/chrome/browser/extensions/api/webstore_widget_private/webstore_widget_private_api.cc @@ -14,6 +14,7 @@ #include "chrome/browser/profiles/profile.h" #include "chrome/common/extensions/api/webstore_widget_private.h" #include "chrome/grit/generated_resources.h" +#include "extensions/browser/extension_function_constants.h" #include "ui/base/l10n/l10n_util.h" #include "ui/base/webui/web_ui_util.h" @@ -90,9 +91,14 @@ WebstoreWidgetPrivateInstallWebstoreItemFunction::Run() { &WebstoreWidgetPrivateInstallWebstoreItemFunction::OnInstallComplete, this); + content::WebContents* web_contents = GetSenderWebContents(); + if (!web_contents) { + return RespondNow( + Error(function_constants::kCouldNotFindSenderWebContents)); + } scoped_refptr<webstore_widget::AppInstaller> installer( new webstore_widget::AppInstaller( - GetAssociatedWebContents(), params->item_id, + web_contents, params->item_id, Profile::FromBrowserContext(browser_context()), params->silent_installation, callback)); // installer will be AddRef()'d in BeginInstall(). |