1a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)// Copyright 2014 The Chromium Authors. All rights reserved.
25821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Use of this source code is governed by a BSD-style license that can be
35821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// found in the LICENSE file.
45821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
5a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)#include "chrome/browser/renderer_context_menu/spellchecker_submenu_observer.h"
65821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
72a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)#include "base/prefs/pref_service.h"
8868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)#include "base/strings/utf_string_conversions.h"
95821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "chrome/app/chrome_command_ids.h"
10a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)#include "chrome/browser/renderer_context_menu/render_view_context_menu.h"
115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "chrome/common/pref_names.h"
125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "chrome/test/base/in_process_browser_test.h"
135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "chrome/test/base/testing_profile.h"
145f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)#include "components/renderer_context_menu/render_view_context_menu_observer.h"
155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)using content::RenderViewHost;
175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)using content::WebContents;
185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)namespace {
205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// A mock context menu used in this test. This class overrides virtual methods
225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// derived from the RenderViewContextMenuProxy class to monitor calls from the
235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// SpellingMenuObserver class.
245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)class MockRenderViewContextMenu : public ui::SimpleMenuModel::Delegate,
255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                                  public RenderViewContextMenuProxy {
265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) public:
275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // A menu item used in this test.
285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  struct MockMenuItem {
295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    MockMenuItem()
305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        : command_id(0),
315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)          enabled(false),
325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)          checked(false),
335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)          hidden(true) {}
345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    int command_id;
355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    bool enabled;
365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    bool checked;
375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    bool hidden;
38a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)    base::string16 title;
395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  };
405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  MockRenderViewContextMenu() : observer_(NULL), profile_(new TestingProfile) {}
425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  virtual ~MockRenderViewContextMenu() {}
435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // SimpleMenuModel::Delegate implementation.
455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  virtual bool IsCommandIdChecked(int command_id) const OVERRIDE {
465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return observer_->IsCommandIdChecked(command_id);
475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  virtual bool IsCommandIdEnabled(int command_id) const OVERRIDE {
495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return observer_->IsCommandIdEnabled(command_id);
505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
512a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  virtual void ExecuteCommand(int command_id, int event_flags) OVERRIDE {
525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    observer_->ExecuteCommand(command_id);
535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  virtual void MenuWillShow(ui::SimpleMenuModel* source) OVERRIDE {}
555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  virtual void MenuClosed(ui::SimpleMenuModel* source) OVERRIDE {}
565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  virtual bool GetAcceleratorForCommandId(
575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      int command_id,
585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      ui::Accelerator* accelerator) OVERRIDE {
595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return false;
605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // RenderViewContextMenuProxy implementation.
63a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)  virtual void AddMenuItem(int command_id,
64a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)                           const base::string16& title) OVERRIDE {}
65a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)  virtual void AddCheckItem(int command_id,
66a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)                            const base::string16& title) OVERRIDE {}
675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  virtual void AddSeparator() OVERRIDE {}
685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  virtual void AddSubMenu(int command_id,
69a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)                          const base::string16& label,
705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                          ui::MenuModel* model) OVERRIDE {}
715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  virtual void UpdateMenuItem(int command_id,
725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                              bool enabled,
735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                              bool hidden,
74a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)                              const base::string16& title) OVERRIDE {}
755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  virtual RenderViewHost* GetRenderViewHost() const OVERRIDE {
765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return NULL;
775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
785f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)  virtual content::BrowserContext* GetBrowserContext() const OVERRIDE {
795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return profile_.get();
805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  virtual content::WebContents* GetWebContents() const OVERRIDE {
825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return NULL;
835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Attaches a RenderViewContextMenuObserver to be tested.
865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  void SetObserver(RenderViewContextMenuObserver* observer) {
875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    observer_ = observer;
885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Returns the number of items added by the test.
915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  size_t GetMenuSize() const {
925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return 0;
935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Returns the i-th item.
965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  bool GetMenuItem(size_t i, MockMenuItem* item) const {
975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return false;
985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Returns the writable profile used in this test.
1015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  PrefService* GetPrefs() {
1025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return profile_->GetPrefs();
1035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
1045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) private:
1065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // An observer used for initializing the status of menu items added in this
1075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // test. This is a weak pointer, the test is responsible for deleting this
1085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // object.
1095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  RenderViewContextMenuObserver* observer_;
1105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // A dummy profile used in this test. Call GetPrefs() when a test needs to
1125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // change this profile and use PrefService methods.
1135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  scoped_ptr<TestingProfile> profile_;
1145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  DISALLOW_COPY_AND_ASSIGN(MockRenderViewContextMenu);
1165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)};
1175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// A test class used in this file. This test should be a browser test because it
1195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// accesses resources.
1205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)class SpellCheckerSubMenuObserverTest : public InProcessBrowserTest {
1215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) public:
1225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  SpellCheckerSubMenuObserverTest() {}
1235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  virtual ~SpellCheckerSubMenuObserverTest() {}
1245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) private:
1265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  DISALLOW_COPY_AND_ASSIGN(SpellCheckerSubMenuObserverTest);
1275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)};
1285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}  // namespace
1305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Tests that selecting the "Check Spelling While Typing" item toggles the value
1325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// of the "browser.enable_spellchecking" profile.
1335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)IN_PROC_BROWSER_TEST_F(SpellCheckerSubMenuObserverTest, ToggleSpelling) {
1345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Initialize a menu consisting only of a "Spell-checker Options" submenu.
1355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  scoped_ptr<MockRenderViewContextMenu> menu(new MockRenderViewContextMenu);
1365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  scoped_ptr<SpellCheckerSubMenuObserver> observer(
1375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      new SpellCheckerSubMenuObserver(menu.get(), menu.get(), 1));
1385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  menu->SetObserver(observer.get());
1395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  menu->GetPrefs()->SetString(prefs::kAcceptLanguages, "en-US");
1405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  menu->GetPrefs()->SetString(prefs::kSpellCheckDictionary, "en-US");
1412a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  menu->GetPrefs()->SetBoolean(prefs::kEnableContinuousSpellcheck, true);
1425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  content::ContextMenuParams params;
1435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  observer->InitMenu(params);
1445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Verify this menu has the "Check Spelling While Typing" item and this item
1465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // is checked.
1475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  EXPECT_TRUE(menu->IsCommandIdEnabled(IDC_CHECK_SPELLING_WHILE_TYPING));
1485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  EXPECT_TRUE(menu->IsCommandIdChecked(IDC_CHECK_SPELLING_WHILE_TYPING));
1495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Select this item and verify that the "Check Spelling While Typing" item is
1515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // not checked. Also, verify that the value of "browser.enable_spellchecking"
1525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // is now false.
1532a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  menu->ExecuteCommand(IDC_CHECK_SPELLING_WHILE_TYPING, 0);
1542a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  EXPECT_FALSE(
1552a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      menu->GetPrefs()->GetBoolean(prefs::kEnableContinuousSpellcheck));
1565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  EXPECT_FALSE(menu->IsCommandIdChecked(IDC_CHECK_SPELLING_WHILE_TYPING));
1575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
158