Fix random lint warnings in chrome/android/shell
[chromium-blink-merge.git] / chrome / browser / renderer_context_menu / spelling_menu_observer_browsertest.cc
blob7c68b41e2a3290ea032a1547d666c1a948b25c45
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/spelling_menu_observer.h"
7 #include <vector>
9 #include "base/prefs/pref_service.h"
10 #include "base/strings/utf_string_conversions.h"
11 #include "chrome/app/chrome_command_ids.h"
12 #include "chrome/browser/renderer_context_menu/render_view_context_menu.h"
13 #include "chrome/browser/spellchecker/spelling_service_client.h"
14 #include "chrome/common/pref_names.h"
15 #include "chrome/test/base/in_process_browser_test.h"
16 #include "chrome/test/base/testing_profile.h"
17 #include "components/renderer_context_menu/render_view_context_menu_observer.h"
19 using content::RenderViewHost;
20 using content::WebContents;
22 namespace {
24 // A mock context menu used in this test. This class overrides virtual methods
25 // derived from the RenderViewContextMenuProxy class to monitor calls from the
26 // SpellingMenuObserver class.
27 class MockRenderViewContextMenu : public RenderViewContextMenuProxy {
28 public:
29 // A menu item used in this test. This test uses a vector of this struct to
30 // hold menu items added by this test.
31 struct MockMenuItem {
32 MockMenuItem()
33 : command_id(0),
34 enabled(false),
35 checked(false),
36 hidden(true) {
38 int command_id;
39 bool enabled;
40 bool checked;
41 bool hidden;
42 base::string16 title;
45 explicit MockRenderViewContextMenu(bool incognito);
46 virtual ~MockRenderViewContextMenu();
48 // RenderViewContextMenuProxy implementation.
49 void AddMenuItem(int command_id, const base::string16& title) override;
50 void AddCheckItem(int command_id, const base::string16& title) override;
51 void AddSeparator() override;
52 void AddSubMenu(int command_id,
53 const base::string16& label,
54 ui::MenuModel* model) override;
55 void UpdateMenuItem(int command_id,
56 bool enabled,
57 bool hidden,
58 const base::string16& title) override;
59 RenderViewHost* GetRenderViewHost() const override;
60 WebContents* GetWebContents() const override;
61 content::BrowserContext* GetBrowserContext() const override;
63 // Attaches a RenderViewContextMenuObserver to be tested.
64 void SetObserver(RenderViewContextMenuObserver* observer);
66 // Returns the number of items added by the test.
67 size_t GetMenuSize() const;
69 // Returns the i-th item.
70 bool GetMenuItem(size_t i, MockMenuItem* item) const;
72 // Returns the writable profile used in this test.
73 PrefService* GetPrefs();
75 private:
76 // An observer used for initializing the status of menu items added in this
77 // test. A test should delete this RenderViewContextMenuObserver object.
78 RenderViewContextMenuObserver* observer_;
80 // A dummy profile used in this test. Call GetPrefs() when a test needs to
81 // change this profile and use PrefService methods.
82 scoped_ptr<TestingProfile> original_profile_;
84 // Either |original_profile_| or its incognito profile.
85 Profile* profile_;
87 // A list of menu items added by the SpellingMenuObserver class.
88 std::vector<MockMenuItem> items_;
90 DISALLOW_COPY_AND_ASSIGN(MockRenderViewContextMenu);
93 MockRenderViewContextMenu::MockRenderViewContextMenu(bool incognito)
94 : observer_(NULL) {
95 original_profile_ = TestingProfile::Builder().Build();
96 profile_ = incognito ? original_profile_->GetOffTheRecordProfile()
97 : original_profile_.get();
100 MockRenderViewContextMenu::~MockRenderViewContextMenu() {
103 void MockRenderViewContextMenu::AddMenuItem(int command_id,
104 const base::string16& title) {
105 MockMenuItem item;
106 item.command_id = command_id;
107 item.enabled = observer_->IsCommandIdEnabled(command_id);
108 item.checked = false;
109 item.hidden = false;
110 item.title = title;
111 items_.push_back(item);
114 void MockRenderViewContextMenu::AddCheckItem(int command_id,
115 const base::string16& title) {
116 MockMenuItem item;
117 item.command_id = command_id;
118 item.enabled = observer_->IsCommandIdEnabled(command_id);
119 item.checked = observer_->IsCommandIdChecked(command_id);
120 item.hidden = false;
121 item.title = title;
122 items_.push_back(item);
125 void MockRenderViewContextMenu::AddSeparator() {
126 MockMenuItem item;
127 item.command_id = -1;
128 item.enabled = false;
129 item.checked = false;
130 item.hidden = false;
131 items_.push_back(item);
134 void MockRenderViewContextMenu::AddSubMenu(int command_id,
135 const base::string16& label,
136 ui::MenuModel* model) {
137 MockMenuItem item;
138 item.command_id = -1;
139 item.enabled = false;
140 item.checked = false;
141 item.hidden = false;
142 items_.push_back(item);
145 void MockRenderViewContextMenu::UpdateMenuItem(int command_id,
146 bool enabled,
147 bool hidden,
148 const base::string16& title) {
149 for (std::vector<MockMenuItem>::iterator it = items_.begin();
150 it != items_.end(); ++it) {
151 if (it->command_id == command_id) {
152 it->enabled = enabled;
153 it->hidden = hidden;
154 it->title = title;
155 return;
159 // The SpellingMenuObserver class tries to change a menu item not added by the
160 // class. This is an unexpected behavior and we should stop now.
161 FAIL();
164 RenderViewHost* MockRenderViewContextMenu::GetRenderViewHost() const {
165 return NULL;
168 WebContents* MockRenderViewContextMenu::GetWebContents() const {
169 return NULL;
172 content::BrowserContext* MockRenderViewContextMenu::GetBrowserContext() const {
173 return profile_;
176 size_t MockRenderViewContextMenu::GetMenuSize() const {
177 return items_.size();
180 bool MockRenderViewContextMenu::GetMenuItem(size_t i,
181 MockMenuItem* item) const {
182 if (i >= items_.size())
183 return false;
184 item->command_id = items_[i].command_id;
185 item->enabled = items_[i].enabled;
186 item->checked = items_[i].checked;
187 item->hidden = items_[i].hidden;
188 item->title = items_[i].title;
189 return true;
192 void MockRenderViewContextMenu::SetObserver(
193 RenderViewContextMenuObserver* observer) {
194 observer_ = observer;
197 PrefService* MockRenderViewContextMenu::GetPrefs() {
198 return profile_->GetPrefs();
201 // A test class used in this file. This test should be a browser test because it
202 // accesses resources.
203 class SpellingMenuObserverTest : public InProcessBrowserTest {
204 public:
205 SpellingMenuObserverTest();
207 void SetUpOnMainThread() override { Reset(false); }
209 void TearDownOnMainThread() override {
210 observer_.reset();
211 menu_.reset();
214 void Reset(bool incognito) {
215 observer_.reset();
216 menu_.reset(new MockRenderViewContextMenu(incognito));
217 observer_.reset(new SpellingMenuObserver(menu_.get()));
218 menu_->SetObserver(observer_.get());
221 void InitMenu(const char* word, const char* suggestion) {
222 content::ContextMenuParams params;
223 params.is_editable = true;
224 params.misspelled_word = base::ASCIIToUTF16(word);
225 params.dictionary_suggestions.clear();
226 if (suggestion)
227 params.dictionary_suggestions.push_back(base::ASCIIToUTF16(suggestion));
228 observer_->InitMenu(params);
231 void ForceSuggestMode() {
232 menu()->GetPrefs()->SetBoolean(prefs::kSpellCheckUseSpellingService, true);
233 // Force a non-empty and non-"en" locale so SUGGEST is available.
234 menu()->GetPrefs()->SetString(prefs::kSpellCheckDictionary, "fr");
235 ASSERT_TRUE(SpellingServiceClient::IsAvailable(
236 menu()->GetBrowserContext(), SpellingServiceClient::SUGGEST));
237 ASSERT_FALSE(SpellingServiceClient::IsAvailable(
238 menu()->GetBrowserContext(), SpellingServiceClient::SPELLCHECK));
241 ~SpellingMenuObserverTest() override;
242 MockRenderViewContextMenu* menu() { return menu_.get(); }
243 SpellingMenuObserver* observer() { return observer_.get(); }
244 private:
245 scoped_ptr<SpellingMenuObserver> observer_;
246 scoped_ptr<MockRenderViewContextMenu> menu_;
247 DISALLOW_COPY_AND_ASSIGN(SpellingMenuObserverTest);
250 SpellingMenuObserverTest::SpellingMenuObserverTest() {
253 SpellingMenuObserverTest::~SpellingMenuObserverTest() {
256 } // namespace
258 // Tests that right-clicking a correct word does not add any items.
259 IN_PROC_BROWSER_TEST_F(SpellingMenuObserverTest, InitMenuWithCorrectWord) {
260 InitMenu("", NULL);
261 EXPECT_EQ(static_cast<size_t>(0), menu()->GetMenuSize());
264 // Tests that right-clicking a misspelled word adds four items:
265 // "No spelling suggestions", "Add to dictionary", "Ask Google for suggestions",
266 // and a separator.
267 IN_PROC_BROWSER_TEST_F(SpellingMenuObserverTest, InitMenuWithMisspelledWord) {
268 InitMenu("wiimode", NULL);
269 EXPECT_EQ(static_cast<size_t>(4), menu()->GetMenuSize());
271 // Read all the context-menu items added by this test and verify they are
272 // expected ones. We do not check the item titles to prevent resource changes
273 // from breaking this test. (I think it is not expected by those who change
274 // resources.)
275 MockRenderViewContextMenu::MockMenuItem item;
276 menu()->GetMenuItem(0, &item);
277 EXPECT_EQ(IDC_CONTENT_CONTEXT_NO_SPELLING_SUGGESTIONS, item.command_id);
278 EXPECT_FALSE(item.enabled);
279 EXPECT_FALSE(item.hidden);
280 menu()->GetMenuItem(1, &item);
281 EXPECT_EQ(IDC_SPELLCHECK_ADD_TO_DICTIONARY, item.command_id);
282 EXPECT_TRUE(item.enabled);
283 EXPECT_FALSE(item.hidden);
284 menu()->GetMenuItem(2, &item);
285 EXPECT_EQ(IDC_CONTENT_CONTEXT_SPELLING_TOGGLE, item.command_id);
286 EXPECT_TRUE(item.enabled);
287 EXPECT_FALSE(item.checked);
288 EXPECT_FALSE(item.hidden);
289 menu()->GetMenuItem(3, &item);
290 EXPECT_EQ(-1, item.command_id);
291 EXPECT_FALSE(item.enabled);
292 EXPECT_FALSE(item.hidden);
295 // Tests that right-clicking a correct word when we enable spelling-service
296 // integration to verify an item "Ask Google for suggestions" is checked. Even
297 // though this meanu itself does not add this item, its sub-menu adds the item
298 // and calls SpellingMenuObserver::IsChecked() to check it.
299 IN_PROC_BROWSER_TEST_F(SpellingMenuObserverTest,
300 EnableSpellingServiceWithCorrectWord) {
301 menu()->GetPrefs()->SetBoolean(prefs::kSpellCheckUseSpellingService, true);
302 InitMenu("", NULL);
304 EXPECT_TRUE(
305 observer()->IsCommandIdChecked(IDC_CONTENT_CONTEXT_SPELLING_TOGGLE));
308 // Tests that right-clicking a misspelled word when we enable spelling-service
309 // integration to verify an item "Ask Google for suggestions" is checked. (This
310 // test does not actually send JSON-RPC requests to the service because it makes
311 // this test flaky.)
312 IN_PROC_BROWSER_TEST_F(SpellingMenuObserverTest, EnableSpellingService) {
313 menu()->GetPrefs()->SetBoolean(prefs::kSpellCheckUseSpellingService, true);
314 menu()->GetPrefs()->SetString(prefs::kSpellCheckDictionary, std::string());
316 InitMenu("wiimode", NULL);
317 EXPECT_EQ(static_cast<size_t>(4), menu()->GetMenuSize());
319 // To avoid duplicates, this test reads only the "Ask Google for suggestions"
320 // item and verifies it is enabled and checked.
321 MockRenderViewContextMenu::MockMenuItem item;
322 menu()->GetMenuItem(2, &item);
323 EXPECT_EQ(IDC_CONTENT_CONTEXT_SPELLING_TOGGLE, item.command_id);
324 EXPECT_TRUE(item.enabled);
325 EXPECT_TRUE(item.checked);
326 EXPECT_FALSE(item.hidden);
329 // Test that there will be a separator after "no suggestions" if
330 // SpellingServiceClient::SUGGEST is on.
331 IN_PROC_BROWSER_TEST_F(SpellingMenuObserverTest, SeparatorAfterSuggestions) {
332 ForceSuggestMode();
333 InitMenu("jhhj", NULL);
335 // The test should see a top separator, "No spelling suggestions",
336 // "No more Google suggestions" (from SpellingService) and a separator
337 // as the first four items, then possibly more (not relevant here).
338 EXPECT_LT(4U, menu()->GetMenuSize());
340 MockRenderViewContextMenu::MockMenuItem item;
341 menu()->GetMenuItem(0, &item);
342 EXPECT_EQ(-1, item.command_id);
343 EXPECT_FALSE(item.enabled);
344 EXPECT_FALSE(item.hidden);
346 menu()->GetMenuItem(1, &item);
347 EXPECT_EQ(IDC_CONTENT_CONTEXT_SPELLING_SUGGESTION, item.command_id);
348 EXPECT_FALSE(item.enabled);
349 EXPECT_FALSE(item.hidden);
351 menu()->GetMenuItem(2, &item);
352 EXPECT_EQ(IDC_CONTENT_CONTEXT_NO_SPELLING_SUGGESTIONS, item.command_id);
353 EXPECT_FALSE(item.enabled);
354 EXPECT_FALSE(item.hidden);
356 menu()->GetMenuItem(3, &item);
357 EXPECT_EQ(-1, item.command_id);
358 EXPECT_FALSE(item.enabled);
359 EXPECT_FALSE(item.hidden);
362 // Test that we don't show "No more suggestions from Google" if the spelling
363 // service is enabled and that there is only one suggestion.
364 IN_PROC_BROWSER_TEST_F(SpellingMenuObserverTest,
365 NoMoreSuggestionsNotDisplayed) {
366 menu()->GetPrefs()->SetBoolean(prefs::kSpellCheckUseSpellingService, true);
368 // Force a non-empty locale so SPELLCHECK is available.
369 menu()->GetPrefs()->SetString(prefs::kSpellCheckDictionary, "en");
370 EXPECT_TRUE(SpellingServiceClient::IsAvailable(
371 menu()->GetBrowserContext(), SpellingServiceClient::SPELLCHECK));
372 InitMenu("asdfkj", "asdf");
374 // The test should see a separator, a suggestion and another separator
375 // as the first two items, then possibly more (not relevant here).
376 EXPECT_LT(3U, menu()->GetMenuSize());
378 MockRenderViewContextMenu::MockMenuItem item;
379 menu()->GetMenuItem(0, &item);
380 EXPECT_EQ(-1, item.command_id);
381 EXPECT_FALSE(item.enabled);
382 EXPECT_FALSE(item.hidden);
384 menu()->GetMenuItem(1, &item);
385 EXPECT_EQ(IDC_SPELLCHECK_SUGGESTION_0, item.command_id);
386 EXPECT_TRUE(item.enabled);
387 EXPECT_FALSE(item.hidden);
389 menu()->GetMenuItem(2, &item);
390 EXPECT_EQ(-1, item.command_id);
391 EXPECT_FALSE(item.enabled);
392 EXPECT_FALSE(item.hidden);
395 // Test that "Ask Google For Suggestions" is grayed out when using an
396 // off the record profile.
397 // TODO(rlp): Include graying out of autocorrect in this test when autocorrect
398 // is functional.
399 IN_PROC_BROWSER_TEST_F(SpellingMenuObserverTest,
400 NoSpellingServiceWhenOffTheRecord) {
401 // Create a menu in an incognito profile.
402 Reset(true);
404 // This means spellchecking is allowed. Default is that the service is
405 // contacted but this test makes sure that if profile is incognito, that
406 // is not an option.
407 menu()->GetPrefs()->SetBoolean(prefs::kSpellCheckUseSpellingService, true);
409 // Force a non-empty locale so SUGGEST normally would be available.
410 menu()->GetPrefs()->SetString(prefs::kSpellCheckDictionary, "en");
411 EXPECT_FALSE(SpellingServiceClient::IsAvailable(
412 menu()->GetBrowserContext(), SpellingServiceClient::SUGGEST));
413 EXPECT_FALSE(SpellingServiceClient::IsAvailable(
414 menu()->GetBrowserContext(), SpellingServiceClient::SPELLCHECK));
416 InitMenu("sjxdjiiiiii", NULL);
418 // The test should see "No spelling suggestions" (from system checker).
419 // They should not see "No more Google suggestions" (from SpellingService) or
420 // a separator. The next 2 items should be "Add to Dictionary" followed
421 // by "Ask Google for suggestions" which should be disabled.
422 // TODO(rlp): add autocorrect here when it is functional.
423 EXPECT_LT(3U, menu()->GetMenuSize());
425 MockRenderViewContextMenu::MockMenuItem item;
426 menu()->GetMenuItem(0, &item);
427 EXPECT_EQ(IDC_CONTENT_CONTEXT_NO_SPELLING_SUGGESTIONS, item.command_id);
428 EXPECT_FALSE(item.enabled);
429 EXPECT_FALSE(item.hidden);
431 menu()->GetMenuItem(1, &item);
432 EXPECT_EQ(IDC_SPELLCHECK_ADD_TO_DICTIONARY, item.command_id);
433 EXPECT_TRUE(item.enabled);
434 EXPECT_FALSE(item.hidden);
436 menu()->GetMenuItem(2, &item);
437 EXPECT_EQ(IDC_CONTENT_CONTEXT_SPELLING_TOGGLE, item.command_id);
438 EXPECT_FALSE(item.enabled);
439 EXPECT_FALSE(item.hidden);
442 // Test that the menu is preceeded by a separator if there are any suggestions,
443 // or if the SpellingServiceClient is available
444 IN_PROC_BROWSER_TEST_F(SpellingMenuObserverTest, SuggestionsForceTopSeparator) {
445 menu()->GetPrefs()->SetBoolean(prefs::kSpellCheckUseSpellingService, false);
447 // First case: Misspelled word, no suggestions, no spellcheck service.
448 InitMenu("asdfkj", NULL);
449 // See SpellingMenuObserverTest.InitMenuWithMisspelledWord on why 4 items.
450 EXPECT_EQ(static_cast<size_t>(4), menu()->GetMenuSize());
451 MockRenderViewContextMenu::MockMenuItem item;
452 menu()->GetMenuItem(0, &item);
453 EXPECT_NE(-1, item.command_id);
455 // Case #2. Misspelled word, suggestions, no spellcheck service.
456 Reset(false);
457 menu()->GetPrefs()->SetBoolean(prefs::kSpellCheckUseSpellingService, false);
458 InitMenu("asdfkj", "asdf");
460 // Expect at least separator and 4 default entries.
461 EXPECT_LT(static_cast<size_t>(5), menu()->GetMenuSize());
462 // This test only cares that the first one is a separator.
463 menu()->GetMenuItem(0, &item);
464 EXPECT_EQ(-1, item.command_id);
466 // Case #3. Misspelled word, suggestion service is on.
467 Reset(false);
468 ForceSuggestMode();
469 InitMenu("asdfkj", NULL);
471 // Should have at least 2 entries. Separator, suggestion.
472 EXPECT_LT(2U, menu()->GetMenuSize());
473 menu()->GetMenuItem(0, &item);
474 EXPECT_EQ(-1, item.command_id);
475 menu()->GetMenuItem(1, &item);
476 EXPECT_EQ(IDC_CONTENT_CONTEXT_SPELLING_SUGGESTION, item.command_id);