1// Copyright (c) 2012 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.
4
5#include "chrome/browser/tab_contents/render_view_context_menu.h"
6
7#include "base/prefs/pref_service.h"
8#include "chrome/app/chrome_command_ids.h"
9#include "chrome/browser/custom_handlers/protocol_handler_registry.h"
10#include "chrome/browser/extensions/extension_prefs.h"
11#include "chrome/browser/prefs/incognito_mode_prefs.h"
12#include "chrome/browser/tab_contents/render_view_context_menu_test_util.h"
13#include "chrome/test/base/chrome_render_view_host_test_harness.h"
14#include "chrome/test/base/testing_profile.h"
15#include "content/public/browser/web_contents.h"
16#include "extensions/common/url_pattern.h"
17#include "testing/gtest/include/gtest/gtest.h"
18#include "third_party/WebKit/public/web/WebContextMenuData.h"
19#include "url/gurl.h"
20
21using extensions::MenuItem;
22using extensions::URLPatternSet;
23
24class RenderViewContextMenuTest : public testing::Test {
25 protected:
26  // Proxy defined here to minimize friend classes in RenderViewContextMenu
27  static bool ExtensionContextAndPatternMatch(
28      const content::ContextMenuParams& params,
29      MenuItem::ContextList contexts,
30      const URLPatternSet& patterns) {
31    return RenderViewContextMenu::ExtensionContextAndPatternMatch(params,
32        contexts, patterns);
33  }
34};
35
36// Generates a ContextMenuParams that matches the specified contexts.
37static content::ContextMenuParams CreateParams(int contexts) {
38  content::ContextMenuParams rv;
39  rv.is_editable = false;
40  rv.media_type = WebKit::WebContextMenuData::MediaTypeNone;
41  rv.page_url = GURL("http://test.page/");
42
43  static const char16 selected_text[] = { 's', 'e', 'l', 0 };
44  if (contexts & MenuItem::SELECTION)
45    rv.selection_text = selected_text;
46
47  if (contexts & MenuItem::LINK)
48    rv.link_url = GURL("http://test.link/");
49
50  if (contexts & MenuItem::EDITABLE)
51    rv.is_editable = true;
52
53  if (contexts & MenuItem::IMAGE) {
54    rv.src_url = GURL("http://test.image/");
55    rv.media_type = WebKit::WebContextMenuData::MediaTypeImage;
56  }
57
58  if (contexts & MenuItem::VIDEO) {
59    rv.src_url = GURL("http://test.video/");
60    rv.media_type = WebKit::WebContextMenuData::MediaTypeVideo;
61  }
62
63  if (contexts & MenuItem::AUDIO) {
64    rv.src_url = GURL("http://test.audio/");
65    rv.media_type = WebKit::WebContextMenuData::MediaTypeAudio;
66  }
67
68  if (contexts & MenuItem::FRAME)
69    rv.frame_url = GURL("http://test.frame/");
70
71  return rv;
72}
73
74// Generates a URLPatternSet with a single pattern
75static URLPatternSet CreatePatternSet(const std::string& pattern) {
76  URLPattern target(URLPattern::SCHEME_HTTP);
77  target.Parse(pattern);
78
79  URLPatternSet rv;
80  rv.AddPattern(target);
81
82  return rv;
83}
84
85TEST_F(RenderViewContextMenuTest, TargetIgnoredForPage) {
86  content::ContextMenuParams params = CreateParams(0);
87
88  MenuItem::ContextList contexts;
89  contexts.Add(MenuItem::PAGE);
90
91  URLPatternSet patterns = CreatePatternSet("*://test.none/*");
92
93  EXPECT_TRUE(ExtensionContextAndPatternMatch(params, contexts, patterns));
94}
95
96TEST_F(RenderViewContextMenuTest, TargetCheckedForLink) {
97  content::ContextMenuParams params = CreateParams(MenuItem::LINK);
98
99  MenuItem::ContextList contexts;
100  contexts.Add(MenuItem::PAGE);
101  contexts.Add(MenuItem::LINK);
102
103  URLPatternSet patterns = CreatePatternSet("*://test.none/*");
104
105  EXPECT_FALSE(ExtensionContextAndPatternMatch(params, contexts, patterns));
106}
107
108TEST_F(RenderViewContextMenuTest, TargetCheckedForImage) {
109  content::ContextMenuParams params = CreateParams(MenuItem::IMAGE);
110
111  MenuItem::ContextList contexts;
112  contexts.Add(MenuItem::PAGE);
113  contexts.Add(MenuItem::IMAGE);
114
115  URLPatternSet patterns = CreatePatternSet("*://test.none/*");
116
117  EXPECT_FALSE(ExtensionContextAndPatternMatch(params, contexts, patterns));
118}
119
120TEST_F(RenderViewContextMenuTest, TargetCheckedForVideo) {
121  content::ContextMenuParams params = CreateParams(MenuItem::VIDEO);
122
123  MenuItem::ContextList contexts;
124  contexts.Add(MenuItem::PAGE);
125  contexts.Add(MenuItem::VIDEO);
126
127  URLPatternSet patterns = CreatePatternSet("*://test.none/*");
128
129  EXPECT_FALSE(ExtensionContextAndPatternMatch(params, contexts, patterns));
130}
131
132TEST_F(RenderViewContextMenuTest, TargetCheckedForAudio) {
133  content::ContextMenuParams params = CreateParams(MenuItem::AUDIO);
134
135  MenuItem::ContextList contexts;
136  contexts.Add(MenuItem::PAGE);
137  contexts.Add(MenuItem::AUDIO);
138
139  URLPatternSet patterns = CreatePatternSet("*://test.none/*");
140
141  EXPECT_FALSE(ExtensionContextAndPatternMatch(params, contexts, patterns));
142}
143
144TEST_F(RenderViewContextMenuTest, MatchWhenLinkedImageMatchesTarget) {
145  content::ContextMenuParams params = CreateParams(MenuItem::IMAGE |
146                                                   MenuItem::LINK);
147
148  MenuItem::ContextList contexts;
149  contexts.Add(MenuItem::LINK);
150  contexts.Add(MenuItem::IMAGE);
151
152  URLPatternSet patterns = CreatePatternSet("*://test.link/*");
153
154  EXPECT_TRUE(ExtensionContextAndPatternMatch(params, contexts, patterns));
155}
156
157TEST_F(RenderViewContextMenuTest, MatchWhenLinkedImageMatchesSource) {
158  content::ContextMenuParams params = CreateParams(MenuItem::IMAGE |
159                                                   MenuItem::LINK);
160
161  MenuItem::ContextList contexts;
162  contexts.Add(MenuItem::LINK);
163  contexts.Add(MenuItem::IMAGE);
164
165  URLPatternSet patterns = CreatePatternSet("*://test.image/*");
166
167  EXPECT_TRUE(ExtensionContextAndPatternMatch(params, contexts, patterns));
168}
169
170TEST_F(RenderViewContextMenuTest, NoMatchWhenLinkedImageMatchesNeither) {
171  content::ContextMenuParams params = CreateParams(MenuItem::IMAGE |
172                                                   MenuItem::LINK);
173
174  MenuItem::ContextList contexts;
175  contexts.Add(MenuItem::LINK);
176  contexts.Add(MenuItem::IMAGE);
177
178  URLPatternSet patterns = CreatePatternSet("*://test.none/*");
179
180  EXPECT_FALSE(ExtensionContextAndPatternMatch(params, contexts, patterns));
181}
182
183TEST_F(RenderViewContextMenuTest, TargetIgnoredForFrame) {
184  content::ContextMenuParams params = CreateParams(MenuItem::FRAME);
185
186  MenuItem::ContextList contexts;
187  contexts.Add(MenuItem::FRAME);
188
189  URLPatternSet patterns = CreatePatternSet("*://test.none/*");
190
191  EXPECT_TRUE(ExtensionContextAndPatternMatch(params, contexts, patterns));
192}
193
194TEST_F(RenderViewContextMenuTest, TargetIgnoredForEditable) {
195  content::ContextMenuParams params = CreateParams(MenuItem::EDITABLE);
196
197  MenuItem::ContextList contexts;
198  contexts.Add(MenuItem::EDITABLE);
199
200  URLPatternSet patterns = CreatePatternSet("*://test.none/*");
201
202  EXPECT_TRUE(ExtensionContextAndPatternMatch(params, contexts, patterns));
203}
204
205TEST_F(RenderViewContextMenuTest, TargetIgnoredForSelection) {
206  content::ContextMenuParams params =
207      CreateParams(MenuItem::SELECTION);
208
209  MenuItem::ContextList contexts;
210  contexts.Add(MenuItem::SELECTION);
211
212  URLPatternSet patterns = CreatePatternSet("*://test.none/*");
213
214  EXPECT_TRUE(ExtensionContextAndPatternMatch(params, contexts, patterns));
215}
216
217TEST_F(RenderViewContextMenuTest, TargetIgnoredForSelectionOnLink) {
218  content::ContextMenuParams params = CreateParams(
219      MenuItem::SELECTION | MenuItem::LINK);
220
221  MenuItem::ContextList contexts;
222  contexts.Add(MenuItem::SELECTION);
223  contexts.Add(MenuItem::LINK);
224
225  URLPatternSet patterns = CreatePatternSet("*://test.none/*");
226
227  EXPECT_TRUE(ExtensionContextAndPatternMatch(params, contexts, patterns));
228}
229
230TEST_F(RenderViewContextMenuTest, TargetIgnoredForSelectionOnImage) {
231  content::ContextMenuParams params = CreateParams(
232      MenuItem::SELECTION | MenuItem::IMAGE);
233
234  MenuItem::ContextList contexts;
235  contexts.Add(MenuItem::SELECTION);
236  contexts.Add(MenuItem::IMAGE);
237
238  URLPatternSet patterns = CreatePatternSet("*://test.none/*");
239
240  EXPECT_TRUE(ExtensionContextAndPatternMatch(params, contexts, patterns));
241}
242
243class RenderViewContextMenuPrefsTest : public ChromeRenderViewHostTestHarness {
244 public:
245  virtual void SetUp() OVERRIDE {
246    ChromeRenderViewHostTestHarness::SetUp();
247    registry_.reset(new ProtocolHandlerRegistry(profile(), NULL));
248  }
249
250  virtual void TearDown() OVERRIDE {
251    registry_.reset();
252    ChromeRenderViewHostTestHarness::TearDown();
253  }
254
255  TestRenderViewContextMenu* CreateContextMenu() {
256    content::ContextMenuParams params = CreateParams(MenuItem::LINK);
257    params.unfiltered_link_url = params.link_url;
258    content::WebContents* wc = web_contents();
259    TestRenderViewContextMenu* menu = new TestRenderViewContextMenu(
260        wc, params);
261    // TestingProfile (returned by profile()) does not provide a protocol
262    // registry.
263    menu->protocol_handler_registry_ = registry_.get();
264    menu->Init();
265    return menu;
266  }
267
268 private:
269  scoped_ptr<ProtocolHandlerRegistry> registry_;
270};
271
272// Verifies when Incognito Mode is not available (disabled by policy),
273// Open Link in Incognito Window link in the context menu is disabled.
274TEST_F(RenderViewContextMenuPrefsTest,
275       DisableOpenInIncognitoWindowWhenIncognitoIsDisabled) {
276  scoped_ptr<TestRenderViewContextMenu> menu(CreateContextMenu());
277
278  // Initially the Incognito mode is be enabled. So is the Open Link in
279  // Incognito Window link.
280  ASSERT_TRUE(menu->IsItemPresent(IDC_CONTENT_CONTEXT_OPENLINKOFFTHERECORD));
281  EXPECT_TRUE(
282      menu->IsCommandIdEnabled(IDC_CONTENT_CONTEXT_OPENLINKOFFTHERECORD));
283
284  // Disable Incognito mode.
285  IncognitoModePrefs::SetAvailability(profile()->GetPrefs(),
286                                      IncognitoModePrefs::DISABLED);
287  menu.reset(CreateContextMenu());
288  ASSERT_TRUE(menu->IsItemPresent(IDC_CONTENT_CONTEXT_OPENLINKOFFTHERECORD));
289  EXPECT_FALSE(
290      menu->IsCommandIdEnabled(IDC_CONTENT_CONTEXT_OPENLINKOFFTHERECORD));
291}
292