• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1// Copyright 2013 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#import "chrome/browser/ui/cocoa/extensions/extension_action_context_menu_controller.h"
6
7#include "base/files/file_path.h"
8#include "base/json/json_file_value_serializer.h"
9#include "base/path_service.h"
10#include "base/prefs/pref_service.h"
11#include "chrome/browser/extensions/browser_action_test_util.h"
12#include "chrome/browser/extensions/extension_action.h"
13#include "chrome/browser/extensions/extension_action_manager.h"
14#include "chrome/browser/extensions/extension_browsertest.h"
15#include "chrome/browser/extensions/extension_tab_util.h"
16#include "chrome/browser/profiles/profile.h"
17#include "chrome/browser/ui/browser.h"
18#include "chrome/browser/ui/cocoa/browser_window_cocoa.h"
19#include "chrome/browser/ui/cocoa/browser_window_controller.h"
20#import "chrome/browser/ui/cocoa/location_bar/location_bar_view_mac.h"
21#include "chrome/browser/ui/cocoa/toolbar/toolbar_controller.h"
22#include "chrome/browser/ui/tabs/tab_strip_model.h"
23#include "chrome/common/chrome_paths.h"
24#include "chrome/common/pref_names.h"
25#include "content/public/browser/devtools_manager.h"
26#include "content/public/test/test_utils.h"
27#include "extensions/common/extension.h"
28#include "grit/generated_resources.h"
29#include "ui/base/l10n/l10n_util_mac.h"
30
31using extensions::Extension;
32
33namespace {
34
35NSMenuItem* GetInspectItem(NSMenu* menu) {
36  return [menu itemWithTitle:
37      l10n_util::GetNSStringWithFixup(IDS_EXTENSION_ACTION_INSPECT_POPUP)];
38}
39
40}  // namespace
41
42class ExtensionActionContextMenuControllerTest : public ExtensionBrowserTest {
43 public:
44  ExtensionActionContextMenuControllerTest() : extension_(NULL), action_(NULL) {
45  }
46
47 protected:
48  void SetupPageAction() {
49    extension_ = InstallExtension(
50        test_data_dir_.AppendASCII("browsertest")
51                      .AppendASCII("page_action_popup"),
52        1);
53    EXPECT_TRUE(extension_);
54    extensions::ExtensionActionManager* action_manager =
55        extensions::ExtensionActionManager::Get(browser()->profile());
56    action_ = action_manager->GetPageAction(*extension_);
57    EXPECT_TRUE(action_);
58
59    content::WebContents* contents =
60        browser()->tab_strip_model()->GetActiveWebContents();
61    action_->SetIsVisible(extensions::ExtensionTabUtil::GetTabId(contents),
62                          true);
63
64    BrowserWindowCocoa* window =
65        static_cast<BrowserWindowCocoa*>(browser()->window());
66    ToolbarController* toolbarController =
67        [window->cocoa_controller() toolbarController];
68    LocationBarViewMac* locationBarView =
69        [toolbarController locationBarBridge];
70    locationBarView->Update(NULL);
71  }
72
73  const Extension* extension_;
74  ExtensionAction* action_;
75};
76
77IN_PROC_BROWSER_TEST_F(ExtensionActionContextMenuControllerTest, BasicTest) {
78  SetupPageAction();
79  base::scoped_nsobject<ExtensionActionContextMenuController> controller(
80      [[ExtensionActionContextMenuController alloc] initWithExtension:extension_
81                                                              browser:browser()
82                                                      extensionAction:action_]);
83
84
85  PrefService* service = browser()->profile()->GetPrefs();
86  bool original = service->GetBoolean(prefs::kExtensionsUIDeveloperMode);
87
88  service->SetBoolean(prefs::kExtensionsUIDeveloperMode, true);
89  base::scoped_nsobject<NSMenu> menu([[NSMenu alloc] initWithTitle:@""]);
90  [controller populateMenu:menu];
91  EXPECT_GT([menu numberOfItems], 0);
92  EXPECT_TRUE(GetInspectItem(menu));
93
94  service->SetBoolean(prefs::kExtensionsUIDeveloperMode, false);
95  [menu removeAllItems];
96  [controller populateMenu:menu];
97  EXPECT_GT([menu numberOfItems], 0);
98  EXPECT_FALSE(GetInspectItem(menu));
99
100  service->SetBoolean(prefs::kExtensionsUIDeveloperMode, original);
101}
102
103// Test that browser action context menus work. Browser actions have their
104// menus created during browser initialization, when there is no tab. This
105// test simulates that and checks the menu is operational.
106IN_PROC_BROWSER_TEST_F(ExtensionActionContextMenuControllerTest,
107                       BrowserAction) {
108  extension_ =
109      InstallExtension(test_data_dir_.AppendASCII("browsertest").AppendASCII(
110                           "browser_action_popup"),
111                       1);
112  EXPECT_TRUE(extension_);
113  extensions::ExtensionActionManager* action_manager =
114      extensions::ExtensionActionManager::Get(browser()->profile());
115  action_ = action_manager->GetBrowserAction(*extension_);
116  EXPECT_TRUE(action_);
117
118  Browser* empty_browser(
119       new Browser(Browser::CreateParams(browser()->profile(),
120                                         browser()->host_desktop_type())));
121
122  base::scoped_nsobject<ExtensionActionContextMenuController> controller(
123      [[ExtensionActionContextMenuController alloc]
124          initWithExtension:extension_
125                    browser:empty_browser
126            extensionAction:action_]);
127  base::scoped_nsobject<NSMenu> menu([[NSMenu alloc] initWithTitle:@""]);
128  [controller populateMenu:menu];
129  EXPECT_GT([menu numberOfItems], 0);
130
131  // Close the empty browser. Can't just free it directly because there are
132  // dangling references in the various native controllers that must be
133  // cleaned up first.
134  NSWindow* window = empty_browser->window()->GetNativeWindow();
135  BrowserWindowController* wc =
136    [BrowserWindowController browserWindowControllerForWindow:window];
137  ASSERT_TRUE(wc != NULL);
138  [wc destroyBrowser];
139}
140
141namespace {
142
143class DevToolsAttachedObserver {
144 public:
145  DevToolsAttachedObserver(const base::Closure& callback)
146      : callback_(callback),
147        devtools_callback_(base::Bind(
148            &DevToolsAttachedObserver::OnDevToolsStateChanged,
149            base::Unretained(this))) {
150    content::DevToolsManager::GetInstance()->AddAgentStateCallback(
151        devtools_callback_);
152  }
153
154  ~DevToolsAttachedObserver() {
155    content::DevToolsManager::GetInstance()->RemoveAgentStateCallback(
156        devtools_callback_);
157  }
158
159  void OnDevToolsStateChanged(content::DevToolsAgentHost*, bool attached) {
160    if (attached)
161      callback_.Run();
162  }
163
164 private:
165  base::Closure callback_;
166  base::Callback<void(content::DevToolsAgentHost*, bool)> devtools_callback_;
167
168  DISALLOW_COPY_AND_ASSIGN(DevToolsAttachedObserver);
169};
170
171}  // namespace
172
173IN_PROC_BROWSER_TEST_F(
174    ExtensionActionContextMenuControllerTest, DISABLED_RunInspectPopup) {
175  SetupPageAction();
176  base::scoped_nsobject<ExtensionActionContextMenuController> controller(
177      [[ExtensionActionContextMenuController alloc] initWithExtension:extension_
178                                                              browser:browser()
179                                                      extensionAction:action_]);
180
181  PrefService* service = browser()->profile()->GetPrefs();
182  bool original = service->GetBoolean(prefs::kExtensionsUIDeveloperMode);
183
184  service->SetBoolean(prefs::kExtensionsUIDeveloperMode, true);
185
186  base::scoped_nsobject<NSMenu> menu([[NSMenu alloc] initWithTitle:@""]);
187  [controller populateMenu:menu];
188  EXPECT_GT([menu numberOfItems], 0);
189  NSMenuItem* inspectItem = GetInspectItem(menu);
190  EXPECT_TRUE(inspectItem);
191
192  scoped_refptr<content::MessageLoopRunner> loop_runner(
193      new content::MessageLoopRunner);
194  DevToolsAttachedObserver observer(loop_runner->QuitClosure());
195  [NSApp sendAction:[inspectItem action]
196                 to:[inspectItem target]
197               from:inspectItem];
198  loop_runner->Run();
199
200  service->SetBoolean(prefs::kExtensionsUIDeveloperMode, original);
201}
202