| // 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/renderer_context_menu/render_view_context_menu.h" |
| |
| #include "base/bind.h" |
| #include "base/run_loop.h" |
| #include "base/strings/utf_string_conversions.h" |
| #include "base/test/scoped_feature_list.h" |
| #include "base/threading/thread_task_runner_handle.h" |
| #include "chrome/app/chrome_command_ids.h" |
| #include "chrome/browser/custom_handlers/protocol_handler_registry.h" |
| #include "chrome/browser/data_reduction_proxy/data_reduction_proxy_chrome_settings.h" |
| #include "chrome/browser/data_reduction_proxy/data_reduction_proxy_chrome_settings_factory.h" |
| #include "chrome/browser/extensions/menu_manager.h" |
| #include "chrome/browser/extensions/menu_manager_factory.h" |
| #include "chrome/browser/extensions/test_extension_environment.h" |
| #include "chrome/browser/extensions/test_extension_prefs.h" |
| #include "chrome/browser/password_manager/chrome_password_manager_client.h" |
| #include "chrome/browser/prefs/incognito_mode_prefs.h" |
| #include "chrome/browser/renderer_context_menu/render_view_context_menu_test_util.h" |
| #include "chrome/common/chrome_features.h" |
| #include "chrome/common/pref_names.h" |
| #include "chrome/test/base/chrome_render_view_host_test_harness.h" |
| #include "chrome/test/base/testing_profile.h" |
| #include "components/data_reduction_proxy/core/browser/data_reduction_proxy_test_utils.h" |
| #include "components/data_reduction_proxy/core/browser/data_store.h" |
| #include "components/data_reduction_proxy/core/common/data_reduction_proxy_headers.h" |
| #include "components/data_reduction_proxy/core/common/data_reduction_proxy_params.h" |
| #include "components/password_manager/content/browser/content_password_manager_driver_factory.h" |
| #include "components/prefs/pref_registry_simple.h" |
| #include "components/prefs/pref_service.h" |
| #include "components/proxy_config/proxy_config_pref_names.h" |
| #include "content/public/browser/web_contents.h" |
| #include "content/public/test/test_renderer_host.h" |
| #include "content/public/test/web_contents_tester.h" |
| #include "extensions/browser/extension_prefs.h" |
| #include "extensions/common/url_pattern.h" |
| #include "services/network/test/test_shared_url_loader_factory.h" |
| #include "testing/gtest/include/gtest/gtest.h" |
| #include "third_party/blink/public/web/web_context_menu_data.h" |
| #include "ui/base/clipboard/clipboard.h" |
| #include "url/gurl.h" |
| |
| using extensions::Extension; |
| using extensions::MenuItem; |
| using extensions::MenuManager; |
| using extensions::MenuManagerFactory; |
| using extensions::URLPatternSet; |
| |
| namespace { |
| |
| // Generates a ContextMenuParams that matches the specified contexts. |
| static content::ContextMenuParams CreateParams(int contexts) { |
| content::ContextMenuParams rv; |
| rv.is_editable = false; |
| rv.media_type = blink::WebContextMenuData::kMediaTypeNone; |
| rv.page_url = GURL("http://test.page/"); |
| |
| static const base::char16 selected_text[] = { 's', 'e', 'l', 0 }; |
| if (contexts & MenuItem::SELECTION) |
| rv.selection_text = selected_text; |
| |
| if (contexts & MenuItem::LINK) |
| rv.link_url = GURL("http://test.link/"); |
| |
| if (contexts & MenuItem::EDITABLE) |
| rv.is_editable = true; |
| |
| if (contexts & MenuItem::IMAGE) { |
| rv.src_url = GURL("http://test.image/"); |
| rv.media_type = blink::WebContextMenuData::kMediaTypeImage; |
| } |
| |
| if (contexts & MenuItem::VIDEO) { |
| rv.src_url = GURL("http://test.video/"); |
| rv.media_type = blink::WebContextMenuData::kMediaTypeVideo; |
| } |
| |
| if (contexts & MenuItem::AUDIO) { |
| rv.src_url = GURL("http://test.audio/"); |
| rv.media_type = blink::WebContextMenuData::kMediaTypeAudio; |
| } |
| |
| if (contexts & MenuItem::FRAME) |
| rv.frame_url = GURL("http://test.frame/"); |
| |
| return rv; |
| } |
| |
| // Returns a test context menu. |
| std::unique_ptr<TestRenderViewContextMenu> CreateContextMenu( |
| content::WebContents* web_contents, |
| ProtocolHandlerRegistry* registry) { |
| content::ContextMenuParams params = CreateParams(MenuItem::LINK); |
| params.unfiltered_link_url = params.link_url; |
| auto menu = std::make_unique<TestRenderViewContextMenu>( |
| web_contents->GetMainFrame(), params); |
| menu->set_protocol_handler_registry(registry); |
| menu->Init(); |
| return menu; |
| } |
| |
| } // namespace |
| |
| class RenderViewContextMenuTest : public testing::Test { |
| protected: |
| RenderViewContextMenuTest() |
| : RenderViewContextMenuTest( |
| std::unique_ptr<extensions::TestExtensionEnvironment>()) {} |
| |
| // If the test uses a TestExtensionEnvironment, which provides a MessageLoop, |
| // it needs to be passed to the constructor so that it exists before the |
| // RenderViewHostTestEnabler which needs to use the MessageLoop. |
| explicit RenderViewContextMenuTest( |
| std::unique_ptr<extensions::TestExtensionEnvironment> env) |
| : environment_(std::move(env)) { |
| // TODO(mgiuca): Add tests with DesktopPWAs enabled. |
| feature_list_.InitAndDisableFeature(features::kDesktopPWAWindowing); |
| } |
| |
| // Proxy defined here to minimize friend classes in RenderViewContextMenu |
| static bool ExtensionContextAndPatternMatch( |
| const content::ContextMenuParams& params, |
| MenuItem::ContextList contexts, |
| const URLPatternSet& patterns) { |
| return RenderViewContextMenu::ExtensionContextAndPatternMatch( |
| params, contexts, patterns); |
| } |
| |
| // Returns a test item. |
| std::unique_ptr<MenuItem> CreateTestItem(const Extension* extension, |
| int uid) { |
| MenuItem::Type type = MenuItem::NORMAL; |
| MenuItem::ContextList contexts(MenuItem::ALL); |
| const MenuItem::ExtensionKey key(extension->id()); |
| bool incognito = false; |
| MenuItem::Id id(incognito, key); |
| id.uid = uid; |
| return std::make_unique<MenuItem>(id, "Added by an extension", false, true, |
| true, type, contexts); |
| } |
| |
| protected: |
| std::unique_ptr<extensions::TestExtensionEnvironment> environment_; |
| |
| private: |
| content::RenderViewHostTestEnabler rvh_test_enabler_; |
| base::test::ScopedFeatureList feature_list_; |
| |
| DISALLOW_COPY_AND_ASSIGN(RenderViewContextMenuTest); |
| }; |
| |
| // Generates a URLPatternSet with a single pattern |
| static URLPatternSet CreatePatternSet(const std::string& pattern) { |
| URLPattern target(URLPattern::SCHEME_HTTP); |
| target.Parse(pattern); |
| |
| URLPatternSet rv; |
| rv.AddPattern(target); |
| |
| return rv; |
| } |
| |
| TEST_F(RenderViewContextMenuTest, TargetIgnoredForPage) { |
| content::ContextMenuParams params = CreateParams(0); |
| |
| MenuItem::ContextList contexts; |
| contexts.Add(MenuItem::PAGE); |
| |
| URLPatternSet patterns = CreatePatternSet("*://test.none/*"); |
| |
| EXPECT_TRUE(ExtensionContextAndPatternMatch(params, contexts, patterns)); |
| } |
| |
| TEST_F(RenderViewContextMenuTest, TargetCheckedForLink) { |
| content::ContextMenuParams params = CreateParams(MenuItem::LINK); |
| |
| MenuItem::ContextList contexts; |
| contexts.Add(MenuItem::PAGE); |
| contexts.Add(MenuItem::LINK); |
| |
| URLPatternSet patterns = CreatePatternSet("*://test.none/*"); |
| |
| EXPECT_FALSE(ExtensionContextAndPatternMatch(params, contexts, patterns)); |
| } |
| |
| TEST_F(RenderViewContextMenuTest, TargetCheckedForImage) { |
| content::ContextMenuParams params = CreateParams(MenuItem::IMAGE); |
| |
| MenuItem::ContextList contexts; |
| contexts.Add(MenuItem::PAGE); |
| contexts.Add(MenuItem::IMAGE); |
| |
| URLPatternSet patterns = CreatePatternSet("*://test.none/*"); |
| |
| EXPECT_FALSE(ExtensionContextAndPatternMatch(params, contexts, patterns)); |
| } |
| |
| TEST_F(RenderViewContextMenuTest, TargetCheckedForVideo) { |
| content::ContextMenuParams params = CreateParams(MenuItem::VIDEO); |
| |
| MenuItem::ContextList contexts; |
| contexts.Add(MenuItem::PAGE); |
| contexts.Add(MenuItem::VIDEO); |
| |
| URLPatternSet patterns = CreatePatternSet("*://test.none/*"); |
| |
| EXPECT_FALSE(ExtensionContextAndPatternMatch(params, contexts, patterns)); |
| } |
| |
| TEST_F(RenderViewContextMenuTest, TargetCheckedForAudio) { |
| content::ContextMenuParams params = CreateParams(MenuItem::AUDIO); |
| |
| MenuItem::ContextList contexts; |
| contexts.Add(MenuItem::PAGE); |
| contexts.Add(MenuItem::AUDIO); |
| |
| URLPatternSet patterns = CreatePatternSet("*://test.none/*"); |
| |
| EXPECT_FALSE(ExtensionContextAndPatternMatch(params, contexts, patterns)); |
| } |
| |
| TEST_F(RenderViewContextMenuTest, MatchWhenLinkedImageMatchesTarget) { |
| content::ContextMenuParams params = CreateParams(MenuItem::IMAGE | |
| MenuItem::LINK); |
| |
| MenuItem::ContextList contexts; |
| contexts.Add(MenuItem::LINK); |
| contexts.Add(MenuItem::IMAGE); |
| |
| URLPatternSet patterns = CreatePatternSet("*://test.link/*"); |
| |
| EXPECT_TRUE(ExtensionContextAndPatternMatch(params, contexts, patterns)); |
| } |
| |
| TEST_F(RenderViewContextMenuTest, MatchWhenLinkedImageMatchesSource) { |
| content::ContextMenuParams params = CreateParams(MenuItem::IMAGE | |
| MenuItem::LINK); |
| |
| MenuItem::ContextList contexts; |
| contexts.Add(MenuItem::LINK); |
| contexts.Add(MenuItem::IMAGE); |
| |
| URLPatternSet patterns = CreatePatternSet("*://test.image/*"); |
| |
| EXPECT_TRUE(ExtensionContextAndPatternMatch(params, contexts, patterns)); |
| } |
| |
| TEST_F(RenderViewContextMenuTest, NoMatchWhenLinkedImageMatchesNeither) { |
| content::ContextMenuParams params = CreateParams(MenuItem::IMAGE | |
| MenuItem::LINK); |
| |
| MenuItem::ContextList contexts; |
| contexts.Add(MenuItem::LINK); |
| contexts.Add(MenuItem::IMAGE); |
| |
| URLPatternSet patterns = CreatePatternSet("*://test.none/*"); |
| |
| EXPECT_FALSE(ExtensionContextAndPatternMatch(params, contexts, patterns)); |
| } |
| |
| TEST_F(RenderViewContextMenuTest, TargetIgnoredForFrame) { |
| content::ContextMenuParams params = CreateParams(MenuItem::FRAME); |
| |
| MenuItem::ContextList contexts; |
| contexts.Add(MenuItem::FRAME); |
| |
| URLPatternSet patterns = CreatePatternSet("*://test.none/*"); |
| |
| EXPECT_TRUE(ExtensionContextAndPatternMatch(params, contexts, patterns)); |
| } |
| |
| TEST_F(RenderViewContextMenuTest, TargetIgnoredForEditable) { |
| content::ContextMenuParams params = CreateParams(MenuItem::EDITABLE); |
| |
| MenuItem::ContextList contexts; |
| contexts.Add(MenuItem::EDITABLE); |
| |
| URLPatternSet patterns = CreatePatternSet("*://test.none/*"); |
| |
| EXPECT_TRUE(ExtensionContextAndPatternMatch(params, contexts, patterns)); |
| } |
| |
| TEST_F(RenderViewContextMenuTest, TargetIgnoredForSelection) { |
| content::ContextMenuParams params = |
| CreateParams(MenuItem::SELECTION); |
| |
| MenuItem::ContextList contexts; |
| contexts.Add(MenuItem::SELECTION); |
| |
| URLPatternSet patterns = CreatePatternSet("*://test.none/*"); |
| |
| EXPECT_TRUE(ExtensionContextAndPatternMatch(params, contexts, patterns)); |
| } |
| |
| TEST_F(RenderViewContextMenuTest, TargetIgnoredForSelectionOnLink) { |
| content::ContextMenuParams params = CreateParams( |
| MenuItem::SELECTION | MenuItem::LINK); |
| |
| MenuItem::ContextList contexts; |
| contexts.Add(MenuItem::SELECTION); |
| contexts.Add(MenuItem::LINK); |
| |
| URLPatternSet patterns = CreatePatternSet("*://test.none/*"); |
| |
| EXPECT_TRUE(ExtensionContextAndPatternMatch(params, contexts, patterns)); |
| } |
| |
| TEST_F(RenderViewContextMenuTest, TargetIgnoredForSelectionOnImage) { |
| content::ContextMenuParams params = CreateParams( |
| MenuItem::SELECTION | MenuItem::IMAGE); |
| |
| MenuItem::ContextList contexts; |
| contexts.Add(MenuItem::SELECTION); |
| contexts.Add(MenuItem::IMAGE); |
| |
| URLPatternSet patterns = CreatePatternSet("*://test.none/*"); |
| |
| EXPECT_TRUE(ExtensionContextAndPatternMatch(params, contexts, patterns)); |
| } |
| |
| class RenderViewContextMenuExtensionsTest : public RenderViewContextMenuTest { |
| protected: |
| RenderViewContextMenuExtensionsTest() |
| : RenderViewContextMenuTest( |
| std::make_unique<extensions::TestExtensionEnvironment>()) {} |
| |
| void SetUp() override { |
| RenderViewContextMenuTest::SetUp(); |
| // TestingProfile does not provide a protocol registry. |
| registry_ = std::make_unique<ProtocolHandlerRegistry>(profile(), nullptr); |
| } |
| |
| void TearDown() override { |
| registry_.reset(); |
| RenderViewContextMenuTest::TearDown(); |
| } |
| |
| TestingProfile* profile() const { return environment_->profile(); } |
| |
| extensions::TestExtensionEnvironment& environment() { return *environment_; } |
| |
| protected: |
| std::unique_ptr<ProtocolHandlerRegistry> registry_; |
| |
| DISALLOW_COPY_AND_ASSIGN(RenderViewContextMenuExtensionsTest); |
| }; |
| |
| TEST_F(RenderViewContextMenuExtensionsTest, |
| ItemWithSameTitleFromTwoExtensions) { |
| MenuManager* menu_manager = // Owned by profile(). |
| static_cast<MenuManager*>( |
| (MenuManagerFactory::GetInstance()->SetTestingFactoryAndUse( |
| profile(), |
| base::BindRepeating( |
| &MenuManagerFactory::BuildServiceInstanceForTesting)))); |
| |
| const Extension* extension1 = environment().MakeExtension( |
| base::DictionaryValue(), "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa"); |
| const Extension* extension2 = environment().MakeExtension( |
| base::DictionaryValue(), "bbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb"); |
| |
| // Create two items in two extensions with same title. |
| ASSERT_TRUE( |
| menu_manager->AddContextItem(extension1, CreateTestItem(extension1, 1))); |
| ASSERT_TRUE( |
| menu_manager->AddContextItem(extension2, CreateTestItem(extension2, 2))); |
| |
| std::unique_ptr<content::WebContents> web_contents = environment().MakeTab(); |
| std::unique_ptr<TestRenderViewContextMenu> menu( |
| CreateContextMenu(web_contents.get(), registry_.get())); |
| |
| const ui::MenuModel& model = menu->menu_model(); |
| base::string16 expected_title = base::ASCIIToUTF16("Added by an extension"); |
| int num_items_found = 0; |
| for (int i = 0; i < model.GetItemCount(); ++i) { |
| if (expected_title == model.GetLabelAt(i)) |
| ++num_items_found; |
| } |
| |
| // Expect both items to be found. |
| ASSERT_EQ(2, num_items_found); |
| } |
| |
| class RenderViewContextMenuPrefsTest : public ChromeRenderViewHostTestHarness { |
| public: |
| RenderViewContextMenuPrefsTest() = default; |
| |
| void SetUp() override { |
| // TODO(mgiuca): Add tests with DesktopPWAs enabled. |
| feature_list_.InitAndDisableFeature(features::kDesktopPWAWindowing); |
| ChromeRenderViewHostTestHarness::SetUp(); |
| registry_ = std::make_unique<ProtocolHandlerRegistry>(profile(), nullptr); |
| } |
| |
| void TearDown() override { |
| registry_.reset(); |
| ChromeRenderViewHostTestHarness::TearDown(); |
| } |
| |
| std::unique_ptr<TestRenderViewContextMenu> CreateContextMenu() { |
| return ::CreateContextMenu(web_contents(), registry_.get()); |
| } |
| |
| // Returns a test context menu for a chrome:// url not permitted to open in |
| // incognito mode. |
| std::unique_ptr<TestRenderViewContextMenu> CreateContextMenuOnChromeLink() { |
| content::ContextMenuParams params = CreateParams(MenuItem::LINK); |
| params.unfiltered_link_url = params.link_url = GURL("chrome://settings"); |
| auto menu = std::make_unique<TestRenderViewContextMenu>( |
| web_contents()->GetMainFrame(), params); |
| menu->set_protocol_handler_registry(registry_.get()); |
| menu->Init(); |
| return menu; |
| } |
| |
| void AppendImageItems(TestRenderViewContextMenu* menu) { |
| menu->AppendImageItems(); |
| } |
| |
| void SetupDataReductionProxy(bool enable_data_reduction_proxy) { |
| drp_test_context_ = |
| data_reduction_proxy::DataReductionProxyTestContext::Builder() |
| .WithMockConfig() |
| .SkipSettingsInitialization() |
| .Build(); |
| |
| DataReductionProxyChromeSettings* settings = |
| DataReductionProxyChromeSettingsFactory::GetForBrowserContext( |
| profile()); |
| |
| // TODO(bengr): Remove proxy_config::prefs::kProxy registration after M46. |
| // See http://crbug.com/445599. |
| PrefRegistrySimple* registry = |
| drp_test_context_->pref_service()->registry(); |
| registry->RegisterDictionaryPref(proxy_config::prefs::kProxy); |
| drp_test_context_->SetDataReductionProxyEnabled( |
| enable_data_reduction_proxy); |
| settings->InitDataReductionProxySettings( |
| drp_test_context_->io_data(), drp_test_context_->pref_service(), |
| drp_test_context_->request_context_getter(), profile(), |
| base::MakeRefCounted<network::TestSharedURLLoaderFactory>(), |
| std::make_unique<data_reduction_proxy::DataStore>(), |
| base::ThreadTaskRunnerHandle::Get(), |
| base::ThreadTaskRunnerHandle::Get()); |
| } |
| |
| // Force destruction of |DataReductionProxySettings| so that objects on DB |
| // task runner can be destroyed before test threads are destroyed. This method |
| // must be called by tests that call |SetupDataReductionProxy|. We cannot |
| // destroy |drp_test_context_| until browser context keyed services are |
| // destroyed since |DataReductionProxyChromeSettings| holds a pointer to the |
| // |PrefService|, which is owned by |drp_test_context_|. |
| void DestroyDataReductionProxySettings() { |
| drp_test_context_->DestroySettings(); |
| } |
| |
| protected: |
| std::unique_ptr<data_reduction_proxy::DataReductionProxyTestContext> |
| drp_test_context_; |
| |
| private: |
| std::unique_ptr<ProtocolHandlerRegistry> registry_; |
| base::test::ScopedFeatureList feature_list_; |
| |
| DISALLOW_COPY_AND_ASSIGN(RenderViewContextMenuPrefsTest); |
| }; |
| |
| // Verifies when Incognito Mode is not available (disabled by policy), |
| // Open Link in Incognito Window link in the context menu is disabled. |
| TEST_F(RenderViewContextMenuPrefsTest, |
| DisableOpenInIncognitoWindowWhenIncognitoIsDisabled) { |
| std::unique_ptr<TestRenderViewContextMenu> menu(CreateContextMenu()); |
| |
| // Initially the Incognito mode is be enabled. So is the Open Link in |
| // Incognito Window link. |
| ASSERT_TRUE(menu->IsItemPresent(IDC_CONTENT_CONTEXT_OPENLINKOFFTHERECORD)); |
| EXPECT_TRUE( |
| menu->IsCommandIdEnabled(IDC_CONTENT_CONTEXT_OPENLINKOFFTHERECORD)); |
| |
| // Disable Incognito mode. |
| IncognitoModePrefs::SetAvailability(profile()->GetPrefs(), |
| IncognitoModePrefs::DISABLED); |
| menu = CreateContextMenu(); |
| ASSERT_TRUE(menu->IsItemPresent(IDC_CONTENT_CONTEXT_OPENLINKOFFTHERECORD)); |
| EXPECT_FALSE( |
| menu->IsCommandIdEnabled(IDC_CONTENT_CONTEXT_OPENLINKOFFTHERECORD)); |
| } |
| |
| // Verifies Incognito Mode is not enabled for links disallowed in Incognito. |
| TEST_F(RenderViewContextMenuPrefsTest, |
| DisableOpenInIncognitoWindowForDisallowedUrls) { |
| std::unique_ptr<TestRenderViewContextMenu> menu( |
| CreateContextMenuOnChromeLink()); |
| |
| ASSERT_TRUE(menu->IsItemPresent(IDC_CONTENT_CONTEXT_OPENLINKOFFTHERECORD)); |
| EXPECT_FALSE( |
| menu->IsCommandIdEnabled(IDC_CONTENT_CONTEXT_OPENLINKOFFTHERECORD)); |
| } |
| |
| // Make sure the checking custom command id that is not enabled will not |
| // cause DCHECK failure. |
| TEST_F(RenderViewContextMenuPrefsTest, |
| IsCustomCommandIdEnabled) { |
| std::unique_ptr<TestRenderViewContextMenu> menu(CreateContextMenu()); |
| |
| EXPECT_FALSE(menu->IsCommandIdEnabled(IDC_CONTENT_CONTEXT_CUSTOM_FIRST)); |
| } |
| |
| // Verify that request headers specify that data reduction proxy should return |
| // the original non compressed resource when "Save Image As..." is used with |
| // Data Saver enabled. |
| TEST_F(RenderViewContextMenuPrefsTest, DataSaverEnabledSaveImageAs) { |
| SetupDataReductionProxy(true); |
| |
| content::ContextMenuParams params = CreateParams(MenuItem::IMAGE); |
| params.unfiltered_link_url = params.link_url; |
| auto menu = std::make_unique<TestRenderViewContextMenu>( |
| web_contents()->GetMainFrame(), params); |
| |
| menu->ExecuteCommand(IDC_CONTENT_CONTEXT_SAVEIMAGEAS, 0); |
| |
| const std::string& headers = |
| content::WebContentsTester::For(web_contents())->GetSaveFrameHeaders(); |
| EXPECT_TRUE(headers.find( |
| "Chrome-Proxy-Accept-Transform: identity") != std::string::npos); |
| EXPECT_TRUE(headers.find("Cache-Control: no-cache") != std::string::npos); |
| |
| DestroyDataReductionProxySettings(); |
| } |
| |
| // Verify that request headers do not specify pass through when "Save Image |
| // As..." is used with Data Saver disabled. |
| TEST_F(RenderViewContextMenuPrefsTest, DataSaverDisabledSaveImageAs) { |
| SetupDataReductionProxy(false); |
| |
| content::ContextMenuParams params = CreateParams(MenuItem::IMAGE); |
| params.unfiltered_link_url = params.link_url; |
| auto menu = std::make_unique<TestRenderViewContextMenu>( |
| web_contents()->GetMainFrame(), params); |
| |
| menu->ExecuteCommand(IDC_CONTENT_CONTEXT_SAVEIMAGEAS, 0); |
| |
| const std::string& headers = |
| content::WebContentsTester::For(web_contents())->GetSaveFrameHeaders(); |
| EXPECT_TRUE(headers.find( |
| "Chrome-Proxy-Accept-Transform: identity") == std::string::npos); |
| EXPECT_TRUE(headers.find("Cache-Control: no-cache") == std::string::npos); |
| |
| DestroyDataReductionProxySettings(); |
| } |
| |
| // Verify that the Chrome-Proxy Lo-Fi directive causes the context menu to |
| // display the "Load Image" menu item. |
| TEST_F(RenderViewContextMenuPrefsTest, DataSaverLoadImage) { |
| SetupDataReductionProxy(true); |
| content::ContextMenuParams params = CreateParams(MenuItem::IMAGE); |
| params.properties[ |
| data_reduction_proxy::chrome_proxy_content_transform_header()] = |
| data_reduction_proxy::empty_image_directive(); |
| params.unfiltered_link_url = params.link_url; |
| auto menu = std::make_unique<TestRenderViewContextMenu>( |
| web_contents()->GetMainFrame(), params); |
| AppendImageItems(menu.get()); |
| |
| ASSERT_TRUE(menu->IsItemPresent(IDC_CONTENT_CONTEXT_LOAD_IMAGE)); |
| |
| DestroyDataReductionProxySettings(); |
| } |
| |
| // Check that if image is broken "Load image" menu item is present. |
| TEST_F(RenderViewContextMenuPrefsTest, LoadBrokenImage) { |
| base::test::ScopedFeatureList scoped_feature_list; |
| scoped_feature_list.InitAndEnableFeature( |
| features::kLoadBrokenImagesFromContextMenu); |
| content::ContextMenuParams params = CreateParams(MenuItem::IMAGE); |
| params.unfiltered_link_url = params.link_url; |
| params.has_image_contents = false; |
| auto menu = std::make_unique<TestRenderViewContextMenu>( |
| web_contents()->GetMainFrame(), params); |
| AppendImageItems(menu.get()); |
| |
| ASSERT_TRUE(menu->IsItemPresent(IDC_CONTENT_CONTEXT_LOAD_IMAGE)); |
| } |
| |
| // Verify that the suggested file name is propagated to web contents when save a |
| // media file in context menu. |
| TEST_F(RenderViewContextMenuPrefsTest, SaveMediaSuggestedFileName) { |
| const base::string16 kTestSuggestedFileName = base::ASCIIToUTF16("test_file"); |
| content::ContextMenuParams params = CreateParams(MenuItem::VIDEO); |
| params.suggested_filename = kTestSuggestedFileName; |
| auto menu = std::make_unique<TestRenderViewContextMenu>( |
| web_contents()->GetMainFrame(), params); |
| menu->ExecuteCommand(IDC_CONTENT_CONTEXT_SAVEAVAS, 0 /* event_flags */); |
| |
| // Video item should have suggested file name. |
| base::string16 suggested_filename = |
| content::WebContentsTester::For(web_contents())->GetSuggestedFileName(); |
| EXPECT_EQ(kTestSuggestedFileName, suggested_filename); |
| |
| params = CreateParams(MenuItem::AUDIO); |
| params.suggested_filename = kTestSuggestedFileName; |
| menu = std::make_unique<TestRenderViewContextMenu>( |
| web_contents()->GetMainFrame(), params); |
| menu->ExecuteCommand(IDC_CONTENT_CONTEXT_SAVEAVAS, 0 /* event_flags */); |
| |
| // Audio item should have suggested file name. |
| suggested_filename = |
| content::WebContentsTester::For(web_contents())->GetSuggestedFileName(); |
| EXPECT_EQ(kTestSuggestedFileName, suggested_filename); |
| } |
| |
| // Verify that "Show all passwords" is displayed on a password field. |
| TEST_F(RenderViewContextMenuPrefsTest, ShowAllPasswords) { |
| // Set up password manager stuff. |
| ChromePasswordManagerClient::CreateForWebContentsWithAutofillClient( |
| web_contents(), nullptr); |
| password_manager::ContentPasswordManagerDriverFactory::FromWebContents( |
| web_contents()) |
| ->RenderFrameCreated(web_contents()->GetMainFrame()); |
| |
| NavigateAndCommit(GURL("http://www.foo.com/")); |
| content::ContextMenuParams params = CreateParams(MenuItem::EDITABLE); |
| params.input_field_type = blink::WebContextMenuData::kInputFieldTypePassword; |
| auto menu = std::make_unique<TestRenderViewContextMenu>( |
| web_contents()->GetMainFrame(), params); |
| menu->Init(); |
| |
| EXPECT_TRUE(menu->IsItemPresent(IDC_CONTENT_CONTEXT_SHOWALLSAVEDPASSWORDS)); |
| } |
| |
| // Verify that "Show all passwords" is displayed on a password field in |
| // Incognito. |
| TEST_F(RenderViewContextMenuPrefsTest, ShowAllPasswordsIncognito) { |
| std::unique_ptr<content::WebContents> incognito_web_contents( |
| content::WebContentsTester::CreateTestWebContents( |
| profile()->GetOffTheRecordProfile(), nullptr)); |
| |
| // Set up password manager stuff. |
| ChromePasswordManagerClient::CreateForWebContentsWithAutofillClient( |
| incognito_web_contents.get(), nullptr); |
| password_manager::ContentPasswordManagerDriverFactory::FromWebContents( |
| incognito_web_contents.get()) |
| ->RenderFrameCreated(incognito_web_contents->GetMainFrame()); |
| |
| content::WebContentsTester::For(incognito_web_contents.get()) |
| ->NavigateAndCommit(GURL("http://www.foo.com/")); |
| content::ContextMenuParams params = CreateParams(MenuItem::EDITABLE); |
| params.input_field_type = blink::WebContextMenuData::kInputFieldTypePassword; |
| auto menu = std::make_unique<TestRenderViewContextMenu>( |
| incognito_web_contents->GetMainFrame(), params); |
| menu->Init(); |
| |
| EXPECT_TRUE(menu->IsItemPresent(IDC_CONTENT_CONTEXT_SHOWALLSAVEDPASSWORDS)); |
| } |
| |
| // Test FormatUrlForClipboard behavior |
| // ------------------------------------------- |
| |
| struct FormatUrlForClipboardTestData { |
| const char* const input; |
| const char* const output; |
| const char* const name; |
| }; |
| |
| class FormatUrlForClipboardTest |
| : public testing::TestWithParam<FormatUrlForClipboardTestData> { |
| public: |
| static base::string16 FormatUrl(const GURL& url) { |
| return RenderViewContextMenu::FormatURLForClipboard(url); |
| } |
| }; |
| |
| const FormatUrlForClipboardTestData kFormatUrlForClipboardTestData[]{ |
| {"http://www.foo.com/", "http://www.foo.com/", "HttpNoEscapes"}, |
| {"http://www.foo.com/%61%62%63", "http://www.foo.com/abc", |
| "HttpSafeUnescapes"}, |
| {"https://www.foo.com/abc%20def", "https://www.foo.com/abc%20def", |
| "HttpsEscapedSpecialCharacters"}, |
| {"https://www.foo.com/%CE%B1%CE%B2%CE%B3", |
| "https://www.foo.com/%CE%B1%CE%B2%CE%B3", "HttpsEscapedUnicodeCharacters"}, |
| {"file:///etc/%CE%B1%CE%B2%CE%B3", "file:///etc/%CE%B1%CE%B2%CE%B3", |
| "FileEscapedUnicodeCharacters"}, |
| {"file://stuff.host.co/my%2Bshare/foo.txt", |
| "file://stuff.host.co/my%2Bshare/foo.txt", "FileEscapedSpecialCharacters"}, |
| {"file://stuff.host.co/my%2Dshare/foo.txt", |
| "file://stuff.host.co/my-share/foo.txt", "FileSafeUnescapes"}, |
| {"mailto:me@foo.com", "me@foo.com", "MailToNoEscapes"}, |
| {"mailto:me@foo.com,you@bar.com?subject=Hello%20world", |
| "me@foo.com,you@bar.com", "MailToWithQuery"}, |
| {"mailto:me@%66%6F%6F.com", "me@foo.com", "MailToSafeEscapes"}, |
| {"mailto:me%2Bsorting-tag@foo.com", "me+sorting-tag@foo.com", |
| "MailToEscapedSpecialCharacters"}, |
| {"mailto:%CE%B1%CE%B2%CE%B3@foo.gr", "αβγ@foo.gr", |
| "MailToEscapedUnicodeCharacters"}, |
| }; |
| |
| INSTANTIATE_TEST_SUITE_P( |
| , |
| FormatUrlForClipboardTest, |
| testing::ValuesIn(kFormatUrlForClipboardTestData), |
| [](const testing::TestParamInfo<FormatUrlForClipboardTestData>& |
| param_info) { return param_info.param.name; }); |
| |
| TEST_P(FormatUrlForClipboardTest, FormatUrlForClipboard) { |
| auto param = GetParam(); |
| GURL url(param.input); |
| const base::string16 result = FormatUrl(url); |
| DCHECK_EQ(base::UTF8ToUTF16(param.output), result); |
| } |