Only grant permissions to new extensions from sync if they have the expected version
[chromium-blink-merge.git] / chrome / browser / renderer_context_menu / render_view_context_menu_unittest.cc
blobafcfcc4b092274566cfb4f451771f67c6bf67aaf
1 // Copyright 2014 The Chromium Authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file.
5 #include "chrome/browser/renderer_context_menu/render_view_context_menu.h"
7 #include "base/prefs/pref_registry_simple.h"
8 #include "base/prefs/pref_service.h"
9 #include "base/run_loop.h"
10 #include "base/strings/utf_string_conversions.h"
11 #include "base/thread_task_runner_handle.h"
12 #include "chrome/app/chrome_command_ids.h"
13 #include "chrome/browser/custom_handlers/protocol_handler_registry.h"
14 #include "chrome/browser/extensions/menu_manager.h"
15 #include "chrome/browser/extensions/menu_manager_factory.h"
16 #include "chrome/browser/extensions/test_extension_environment.h"
17 #include "chrome/browser/extensions/test_extension_prefs.h"
18 #include "chrome/browser/net/spdyproxy/data_reduction_proxy_chrome_settings.h"
19 #include "chrome/browser/net/spdyproxy/data_reduction_proxy_chrome_settings_factory.h"
20 #include "chrome/browser/prefs/incognito_mode_prefs.h"
21 #include "chrome/browser/renderer_context_menu/render_view_context_menu_test_util.h"
22 #include "chrome/test/base/chrome_render_view_host_test_harness.h"
23 #include "chrome/test/base/testing_profile.h"
24 #include "components/data_reduction_proxy/core/browser/data_reduction_proxy_test_utils.h"
25 #include "components/data_reduction_proxy/core/browser/data_store.h"
26 #include "components/data_reduction_proxy/core/common/data_reduction_proxy_headers.h"
27 #include "components/data_reduction_proxy/core/common/data_reduction_proxy_params.h"
28 #include "components/data_reduction_proxy/core/common/data_reduction_proxy_pref_names.h"
29 #include "components/proxy_config/proxy_config_pref_names.h"
30 #include "content/public/browser/web_contents.h"
31 #include "content/public/test/test_renderer_host.h"
32 #include "content/public/test/web_contents_tester.h"
34 #include "extensions/browser/extension_prefs.h"
35 #include "extensions/common/url_pattern.h"
36 #include "testing/gtest/include/gtest/gtest.h"
37 #include "third_party/WebKit/public/web/WebContextMenuData.h"
38 #include "url/gurl.h"
40 using extensions::Extension;
41 using extensions::MenuItem;
42 using extensions::MenuManager;
43 using extensions::MenuManagerFactory;
44 using extensions::URLPatternSet;
46 namespace {
48 // Generates a ContextMenuParams that matches the specified contexts.
49 static content::ContextMenuParams CreateParams(int contexts) {
50 content::ContextMenuParams rv;
51 rv.is_editable = false;
52 rv.media_type = blink::WebContextMenuData::MediaTypeNone;
53 rv.page_url = GURL("http://test.page/");
55 static const base::char16 selected_text[] = { 's', 'e', 'l', 0 };
56 if (contexts & MenuItem::SELECTION)
57 rv.selection_text = selected_text;
59 if (contexts & MenuItem::LINK)
60 rv.link_url = GURL("http://test.link/");
62 if (contexts & MenuItem::EDITABLE)
63 rv.is_editable = true;
65 if (contexts & MenuItem::IMAGE) {
66 rv.src_url = GURL("http://test.image/");
67 rv.media_type = blink::WebContextMenuData::MediaTypeImage;
70 if (contexts & MenuItem::VIDEO) {
71 rv.src_url = GURL("http://test.video/");
72 rv.media_type = blink::WebContextMenuData::MediaTypeVideo;
75 if (contexts & MenuItem::AUDIO) {
76 rv.src_url = GURL("http://test.audio/");
77 rv.media_type = blink::WebContextMenuData::MediaTypeAudio;
80 if (contexts & MenuItem::FRAME)
81 rv.frame_url = GURL("http://test.frame/");
83 return rv;
86 } // namespace
88 class RenderViewContextMenuTest : public testing::Test {
89 protected:
90 // Proxy defined here to minimize friend classes in RenderViewContextMenu
91 static bool ExtensionContextAndPatternMatch(
92 const content::ContextMenuParams& params,
93 MenuItem::ContextList contexts,
94 const URLPatternSet& patterns) {
95 return RenderViewContextMenu::ExtensionContextAndPatternMatch(
96 params, contexts, patterns);
99 // Returns a test item.
100 MenuItem* CreateTestItem(const Extension* extension, int uid) {
101 MenuItem::Type type = MenuItem::NORMAL;
102 MenuItem::ContextList contexts(MenuItem::ALL);
103 const MenuItem::ExtensionKey key(extension->id());
104 bool incognito = false;
105 MenuItem::Id id(incognito, key);
106 id.uid = uid;
107 return new MenuItem(id, "Added by an extension", false, true, type,
108 contexts);
111 // Returns a test context menu.
112 TestRenderViewContextMenu* CreateContextMenu(
113 TestingProfile* profile,
114 content::WebContents* web_contents) {
115 content::ContextMenuParams params = CreateParams(MenuItem::LINK);
116 params.unfiltered_link_url = params.link_url;
117 TestRenderViewContextMenu* menu =
118 new TestRenderViewContextMenu(web_contents->GetMainFrame(), params);
119 // TestingProfile (returned by profile()) does not provide a protocol
120 // registry.
121 scoped_ptr<ProtocolHandlerRegistry> registry_(
122 new ProtocolHandlerRegistry(profile, NULL));
123 menu->protocol_handler_registry_ = registry_.get();
124 menu->Init();
125 return menu;
127 private:
128 content::RenderViewHostTestEnabler rvh_test_enabler_;
131 // Generates a URLPatternSet with a single pattern
132 static URLPatternSet CreatePatternSet(const std::string& pattern) {
133 URLPattern target(URLPattern::SCHEME_HTTP);
134 target.Parse(pattern);
136 URLPatternSet rv;
137 rv.AddPattern(target);
139 return rv;
142 TEST_F(RenderViewContextMenuTest, TargetIgnoredForPage) {
143 content::ContextMenuParams params = CreateParams(0);
145 MenuItem::ContextList contexts;
146 contexts.Add(MenuItem::PAGE);
148 URLPatternSet patterns = CreatePatternSet("*://test.none/*");
150 EXPECT_TRUE(ExtensionContextAndPatternMatch(params, contexts, patterns));
153 TEST_F(RenderViewContextMenuTest, TargetCheckedForLink) {
154 content::ContextMenuParams params = CreateParams(MenuItem::LINK);
156 MenuItem::ContextList contexts;
157 contexts.Add(MenuItem::PAGE);
158 contexts.Add(MenuItem::LINK);
160 URLPatternSet patterns = CreatePatternSet("*://test.none/*");
162 EXPECT_FALSE(ExtensionContextAndPatternMatch(params, contexts, patterns));
165 TEST_F(RenderViewContextMenuTest, TargetCheckedForImage) {
166 content::ContextMenuParams params = CreateParams(MenuItem::IMAGE);
168 MenuItem::ContextList contexts;
169 contexts.Add(MenuItem::PAGE);
170 contexts.Add(MenuItem::IMAGE);
172 URLPatternSet patterns = CreatePatternSet("*://test.none/*");
174 EXPECT_FALSE(ExtensionContextAndPatternMatch(params, contexts, patterns));
177 TEST_F(RenderViewContextMenuTest, TargetCheckedForVideo) {
178 content::ContextMenuParams params = CreateParams(MenuItem::VIDEO);
180 MenuItem::ContextList contexts;
181 contexts.Add(MenuItem::PAGE);
182 contexts.Add(MenuItem::VIDEO);
184 URLPatternSet patterns = CreatePatternSet("*://test.none/*");
186 EXPECT_FALSE(ExtensionContextAndPatternMatch(params, contexts, patterns));
189 TEST_F(RenderViewContextMenuTest, TargetCheckedForAudio) {
190 content::ContextMenuParams params = CreateParams(MenuItem::AUDIO);
192 MenuItem::ContextList contexts;
193 contexts.Add(MenuItem::PAGE);
194 contexts.Add(MenuItem::AUDIO);
196 URLPatternSet patterns = CreatePatternSet("*://test.none/*");
198 EXPECT_FALSE(ExtensionContextAndPatternMatch(params, contexts, patterns));
201 TEST_F(RenderViewContextMenuTest, MatchWhenLinkedImageMatchesTarget) {
202 content::ContextMenuParams params = CreateParams(MenuItem::IMAGE |
203 MenuItem::LINK);
205 MenuItem::ContextList contexts;
206 contexts.Add(MenuItem::LINK);
207 contexts.Add(MenuItem::IMAGE);
209 URLPatternSet patterns = CreatePatternSet("*://test.link/*");
211 EXPECT_TRUE(ExtensionContextAndPatternMatch(params, contexts, patterns));
214 TEST_F(RenderViewContextMenuTest, MatchWhenLinkedImageMatchesSource) {
215 content::ContextMenuParams params = CreateParams(MenuItem::IMAGE |
216 MenuItem::LINK);
218 MenuItem::ContextList contexts;
219 contexts.Add(MenuItem::LINK);
220 contexts.Add(MenuItem::IMAGE);
222 URLPatternSet patterns = CreatePatternSet("*://test.image/*");
224 EXPECT_TRUE(ExtensionContextAndPatternMatch(params, contexts, patterns));
227 TEST_F(RenderViewContextMenuTest, NoMatchWhenLinkedImageMatchesNeither) {
228 content::ContextMenuParams params = CreateParams(MenuItem::IMAGE |
229 MenuItem::LINK);
231 MenuItem::ContextList contexts;
232 contexts.Add(MenuItem::LINK);
233 contexts.Add(MenuItem::IMAGE);
235 URLPatternSet patterns = CreatePatternSet("*://test.none/*");
237 EXPECT_FALSE(ExtensionContextAndPatternMatch(params, contexts, patterns));
240 TEST_F(RenderViewContextMenuTest, TargetIgnoredForFrame) {
241 content::ContextMenuParams params = CreateParams(MenuItem::FRAME);
243 MenuItem::ContextList contexts;
244 contexts.Add(MenuItem::FRAME);
246 URLPatternSet patterns = CreatePatternSet("*://test.none/*");
248 EXPECT_TRUE(ExtensionContextAndPatternMatch(params, contexts, patterns));
251 TEST_F(RenderViewContextMenuTest, TargetIgnoredForEditable) {
252 content::ContextMenuParams params = CreateParams(MenuItem::EDITABLE);
254 MenuItem::ContextList contexts;
255 contexts.Add(MenuItem::EDITABLE);
257 URLPatternSet patterns = CreatePatternSet("*://test.none/*");
259 EXPECT_TRUE(ExtensionContextAndPatternMatch(params, contexts, patterns));
262 TEST_F(RenderViewContextMenuTest, TargetIgnoredForSelection) {
263 content::ContextMenuParams params =
264 CreateParams(MenuItem::SELECTION);
266 MenuItem::ContextList contexts;
267 contexts.Add(MenuItem::SELECTION);
269 URLPatternSet patterns = CreatePatternSet("*://test.none/*");
271 EXPECT_TRUE(ExtensionContextAndPatternMatch(params, contexts, patterns));
274 TEST_F(RenderViewContextMenuTest, TargetIgnoredForSelectionOnLink) {
275 content::ContextMenuParams params = CreateParams(
276 MenuItem::SELECTION | MenuItem::LINK);
278 MenuItem::ContextList contexts;
279 contexts.Add(MenuItem::SELECTION);
280 contexts.Add(MenuItem::LINK);
282 URLPatternSet patterns = CreatePatternSet("*://test.none/*");
284 EXPECT_TRUE(ExtensionContextAndPatternMatch(params, contexts, patterns));
287 TEST_F(RenderViewContextMenuTest, TargetIgnoredForSelectionOnImage) {
288 content::ContextMenuParams params = CreateParams(
289 MenuItem::SELECTION | MenuItem::IMAGE);
291 MenuItem::ContextList contexts;
292 contexts.Add(MenuItem::SELECTION);
293 contexts.Add(MenuItem::IMAGE);
295 URLPatternSet patterns = CreatePatternSet("*://test.none/*");
297 EXPECT_TRUE(ExtensionContextAndPatternMatch(params, contexts, patterns));
300 TEST_F(RenderViewContextMenuTest, ItemWithSameTitleFromTwoExtensions) {
301 extensions::TestExtensionEnvironment env;
303 MenuManager* menu_manager = // Owned by env.profile().
304 static_cast<MenuManager*>(
305 (MenuManagerFactory::GetInstance()->SetTestingFactoryAndUse(
306 env.profile(),
307 &MenuManagerFactory::BuildServiceInstanceForTesting)));
309 const Extension* extension1 =
310 env.MakeExtension(base::DictionaryValue(),
311 "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa");
312 const Extension* extension2 =
313 env.MakeExtension(base::DictionaryValue(),
314 "bbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb");
316 // Create two items in two extensions with same title.
317 MenuItem* item1 = CreateTestItem(extension1, 1);
318 ASSERT_TRUE(menu_manager->AddContextItem(extension1, item1));
319 MenuItem* item2 = CreateTestItem(extension2, 2);
320 ASSERT_TRUE(menu_manager->AddContextItem(extension2, item2));
322 scoped_ptr<content::WebContents> web_contents = env.MakeTab();
323 scoped_ptr<TestRenderViewContextMenu> menu(
324 CreateContextMenu(env.profile(), web_contents.get()));
326 const ui::MenuModel& model = menu->menu_model();
327 base::string16 expected_title = base::ASCIIToUTF16("Added by an extension");
328 int num_items_found = 0;
329 for (int i = 0; i < model.GetItemCount(); ++i) {
330 if (expected_title == model.GetLabelAt(i))
331 ++num_items_found;
334 // Expect both items to be found.
335 ASSERT_EQ(2, num_items_found);
338 class RenderViewContextMenuPrefsTest : public ChromeRenderViewHostTestHarness {
339 public:
340 void SetUp() override {
341 ChromeRenderViewHostTestHarness::SetUp();
342 registry_.reset(new ProtocolHandlerRegistry(profile(), NULL));
345 void TearDown() override {
346 registry_.reset();
347 ChromeRenderViewHostTestHarness::TearDown();
350 TestRenderViewContextMenu* CreateContextMenu() {
351 content::ContextMenuParams params = CreateParams(MenuItem::LINK);
352 params.unfiltered_link_url = params.link_url;
353 content::WebContents* wc = web_contents();
354 TestRenderViewContextMenu* menu = new TestRenderViewContextMenu(
355 wc->GetMainFrame(), params);
356 // TestingProfile (returned by profile()) does not provide a protocol
357 // registry.
358 menu->protocol_handler_registry_ = registry_.get();
359 menu->Init();
360 return menu;
363 void AppendImageItems(TestRenderViewContextMenu* menu) {
364 menu->AppendImageItems();
367 void SetupDataReductionProxy(bool enable_data_reduction_proxy) {
368 drp_test_context_ =
369 data_reduction_proxy::DataReductionProxyTestContext::Builder()
370 .WithParamsFlags(
371 data_reduction_proxy::DataReductionProxyParams::kAllowed |
372 data_reduction_proxy::DataReductionProxyParams::
373 kFallbackAllowed |
374 data_reduction_proxy::DataReductionProxyParams::kPromoAllowed)
375 .WithMockConfig()
376 .SkipSettingsInitialization()
377 .Build();
379 DataReductionProxyChromeSettings* settings =
380 DataReductionProxyChromeSettingsFactory::GetForBrowserContext(
381 profile());
383 // TODO(bengr): Remove proxy_config::prefs::kProxy registration after M46.
384 // See http://crbug.com/445599.
385 PrefRegistrySimple* registry =
386 drp_test_context_->pref_service()->registry();
387 registry->RegisterDictionaryPref(proxy_config::prefs::kProxy);
389 drp_test_context_->pref_service()->SetBoolean(
390 data_reduction_proxy::prefs::kDataReductionProxyEnabled,
391 enable_data_reduction_proxy);
392 drp_test_context_->InitSettings();
394 settings->InitDataReductionProxySettings(
395 drp_test_context_->io_data(), drp_test_context_->pref_service(),
396 drp_test_context_->request_context_getter(),
397 make_scoped_ptr(new data_reduction_proxy::DataStore()),
398 base::ThreadTaskRunnerHandle::Get(),
399 base::ThreadTaskRunnerHandle::Get());
402 // Force destruction of |DataReductionProxySettings| so that objects on DB
403 // task runner can be destroyed before test threads are destroyed. This method
404 // must be called by tests that call |SetupDataReductionProxy|. We cannot
405 // destroy |drp_test_context_| until browser context keyed services are
406 // destroyed since |DataReductionProxyChromeSettings| holds a pointer to the
407 // |PrefService|, which is owned by |drp_test_context_|.
408 void DestroyDataReductionProxySettings() {
409 drp_test_context_->DestroySettings();
412 protected:
413 scoped_ptr<data_reduction_proxy::DataReductionProxyTestContext>
414 drp_test_context_;
416 private:
417 scoped_ptr<ProtocolHandlerRegistry> registry_;
420 // Verifies when Incognito Mode is not available (disabled by policy),
421 // Open Link in Incognito Window link in the context menu is disabled.
422 TEST_F(RenderViewContextMenuPrefsTest,
423 DisableOpenInIncognitoWindowWhenIncognitoIsDisabled) {
424 scoped_ptr<TestRenderViewContextMenu> menu(CreateContextMenu());
426 // Initially the Incognito mode is be enabled. So is the Open Link in
427 // Incognito Window link.
428 ASSERT_TRUE(menu->IsItemPresent(IDC_CONTENT_CONTEXT_OPENLINKOFFTHERECORD));
429 EXPECT_TRUE(
430 menu->IsCommandIdEnabled(IDC_CONTENT_CONTEXT_OPENLINKOFFTHERECORD));
432 // Disable Incognito mode.
433 IncognitoModePrefs::SetAvailability(profile()->GetPrefs(),
434 IncognitoModePrefs::DISABLED);
435 menu.reset(CreateContextMenu());
436 ASSERT_TRUE(menu->IsItemPresent(IDC_CONTENT_CONTEXT_OPENLINKOFFTHERECORD));
437 EXPECT_FALSE(
438 menu->IsCommandIdEnabled(IDC_CONTENT_CONTEXT_OPENLINKOFFTHERECORD));
441 // Make sure the checking custom command id that is not enabled will not
442 // cause DCHECK failure.
443 TEST_F(RenderViewContextMenuPrefsTest,
444 IsCustomCommandIdEnabled) {
445 scoped_ptr<TestRenderViewContextMenu> menu(CreateContextMenu());
447 EXPECT_FALSE(menu->IsCommandIdEnabled(IDC_CONTENT_CONTEXT_CUSTOM_FIRST));
450 // Verify that request headers specify that data reduction proxy should return
451 // the original non compressed resource when "Save Image As..." is used with
452 // Data Saver enabled.
453 TEST_F(RenderViewContextMenuPrefsTest, DataSaverEnabledSaveImageAs) {
454 SetupDataReductionProxy(true);
456 content::ContextMenuParams params = CreateParams(MenuItem::IMAGE);
457 params.unfiltered_link_url = params.link_url;
458 content::WebContents* wc = web_contents();
459 scoped_ptr<TestRenderViewContextMenu> menu(
460 new TestRenderViewContextMenu(wc->GetMainFrame(), params));
462 menu->ExecuteCommand(IDC_CONTENT_CONTEXT_SAVEIMAGEAS, 0);
464 const std::string& headers =
465 content::WebContentsTester::For(web_contents())->GetSaveFrameHeaders();
466 EXPECT_TRUE(headers.find("Chrome-Proxy: pass-through") != std::string::npos);
467 EXPECT_TRUE(headers.find("Cache-Control: no-cache") != std::string::npos);
469 DestroyDataReductionProxySettings();
472 // Verify that request headers do not specify pass through when "Save Image
473 // As..." is used with Data Saver disabled.
474 TEST_F(RenderViewContextMenuPrefsTest, DataSaverDisabledSaveImageAs) {
475 SetupDataReductionProxy(false);
477 content::ContextMenuParams params = CreateParams(MenuItem::IMAGE);
478 params.unfiltered_link_url = params.link_url;
479 content::WebContents* wc = web_contents();
480 scoped_ptr<TestRenderViewContextMenu> menu(
481 new TestRenderViewContextMenu(wc->GetMainFrame(), params));
483 menu->ExecuteCommand(IDC_CONTENT_CONTEXT_SAVEIMAGEAS, 0);
485 const std::string& headers =
486 content::WebContentsTester::For(web_contents())->GetSaveFrameHeaders();
487 EXPECT_TRUE(headers.find("Chrome-Proxy: pass-through") == std::string::npos);
488 EXPECT_TRUE(headers.find("Cache-Control: no-cache") == std::string::npos);
490 DestroyDataReductionProxySettings();
493 // Verify that the Chrome-Proxy Lo-Fi directive causes the context menu to
494 // display the "Load Image" menu item.
495 TEST_F(RenderViewContextMenuPrefsTest, DataSaverLoadImage) {
496 SetupDataReductionProxy(true);
497 content::ContextMenuParams params = CreateParams(MenuItem::IMAGE);
498 params.properties[data_reduction_proxy::chrome_proxy_header()] =
499 data_reduction_proxy::chrome_proxy_lo_fi_directive();
500 params.unfiltered_link_url = params.link_url;
501 content::WebContents* wc = web_contents();
502 scoped_ptr<TestRenderViewContextMenu> menu(
503 new TestRenderViewContextMenu(wc->GetMainFrame(), params));
504 AppendImageItems(menu.get());
506 ASSERT_TRUE(menu->IsItemPresent(IDC_CONTENT_CONTEXT_LOAD_ORIGINAL_IMAGE));
508 DestroyDataReductionProxySettings();