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 "base/command_line.h"
6#include "chrome/browser/extensions/api/extension_action/extension_action_api.h"
7#include "chrome/browser/extensions/browser_action_test_util.h"
8#include "chrome/browser/extensions/extension_action.h"
9#include "chrome/browser/extensions/extension_action_icon_factory.h"
10#include "chrome/browser/extensions/extension_action_manager.h"
11#include "chrome/browser/extensions/extension_apitest.h"
12#include "chrome/browser/extensions/extension_prefs.h"
13#include "chrome/browser/extensions/extension_service.h"
14#include "chrome/browser/extensions/extension_system.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/browser_window.h"
19#include "chrome/browser/ui/omnibox/location_bar.h"
20#include "chrome/browser/ui/tabs/tab_strip_model.h"
21#include "chrome/common/chrome_switches.h"
22#include "chrome/common/extensions/extension.h"
23#include "chrome/test/base/ui_test_utils.h"
24#include "content/public/browser/web_contents.h"
25
26// These are a mash-up of the tests from from page_actions_apitest.cc and
27// browser_actions_apitest.cc.
28
29namespace extensions {
30namespace {
31
32class PageAsBrowserActionApiTest : public ExtensionApiTest {
33 public:
34  PageAsBrowserActionApiTest() {}
35  virtual ~PageAsBrowserActionApiTest() {}
36
37  virtual void SetUpCommandLine(CommandLine* command_line) OVERRIDE {
38    ExtensionApiTest::SetUpCommandLine(command_line);
39    command_line->AppendSwitchASCII(switches::kScriptBadges, "1");
40  }
41
42 protected:
43  BrowserActionTestUtil GetBrowserActionsBar() {
44    return BrowserActionTestUtil(browser());
45  }
46
47  ExtensionActionManager* extension_action_manager() {
48    return ExtensionActionManager::Get(browser()->profile());
49  }
50};
51
52IN_PROC_BROWSER_TEST_F(PageAsBrowserActionApiTest, Basic) {
53  ASSERT_TRUE(test_server()->Start());
54  ASSERT_TRUE(RunExtensionTest("page_action/basics")) << message_;
55  const Extension* extension = GetSingleLoadedExtension();
56  ASSERT_TRUE(extension) << message_;
57
58  // The extension declares a page action, but it should have gotten a browser
59  // action instead.
60  ASSERT_TRUE(extension_action_manager()->GetBrowserAction(*extension));
61  ASSERT_FALSE(extension_action_manager()->GetPageAction(*extension));
62
63  // With the "action box" there won't be browser actions unless they're pinned.
64  ExtensionActionAPI::SetBrowserActionVisibility(
65      extensions::ExtensionSystem::Get(browser()->profile())->
66          extension_service()->extension_prefs(),
67      extension->id(),
68      true);
69
70  // Test that there is a browser action in the toolbar.
71  ASSERT_EQ(1, GetBrowserActionsBar().NumberOfBrowserActions());
72
73  {
74    // Tell the extension to update the page action state.
75    ResultCatcher catcher;
76    ui_test_utils::NavigateToURL(browser(),
77        GURL(extension->GetResourceURL("update.html")));
78    ASSERT_TRUE(catcher.GetNextResult());
79  }
80
81  // Test that we received the changes.
82  int tab_id = ExtensionTabUtil::GetTabId(
83      browser()->tab_strip_model()->GetActiveWebContents());
84  ExtensionAction* action =
85      extension_action_manager()->GetBrowserAction(*extension);
86  ASSERT_TRUE(action);
87  EXPECT_EQ("Modified", action->GetTitle(tab_id));
88
89  {
90    // Simulate the page action being clicked.
91    ResultCatcher catcher;
92    ExtensionService* service = extensions::ExtensionSystem::Get(
93        browser()->profile())->extension_service();
94    service->toolbar_model()->ExecuteBrowserAction(extension, browser(), NULL);
95    EXPECT_TRUE(catcher.GetNextResult());
96  }
97
98  {
99    // Tell the extension to update the page action state again.
100    ResultCatcher catcher;
101    ui_test_utils::NavigateToURL(browser(),
102        GURL(extension->GetResourceURL("update2.html")));
103    ASSERT_TRUE(catcher.GetNextResult());
104  }
105
106  // We should not be creating icons asynchronously, so we don't need an
107  // observer.
108  ExtensionActionIconFactory icon_factory(
109      profile(), extension, action, NULL);
110
111  // Test that we received the changes.
112  EXPECT_FALSE(icon_factory.GetIcon(tab_id).IsEmpty());
113}
114
115// Test that calling chrome.pageAction.setPopup() can enable a popup.
116IN_PROC_BROWSER_TEST_F(PageAsBrowserActionApiTest, AddPopup) {
117  // Load the extension, which has no default popup.
118  ASSERT_TRUE(RunExtensionTest("page_action/add_popup")) << message_;
119  const Extension* extension = GetSingleLoadedExtension();
120  ASSERT_TRUE(extension) << message_;
121
122  int tab_id = ExtensionTabUtil::GetTabId(
123      browser()->tab_strip_model()->GetActiveWebContents());
124
125  ExtensionAction* page_action =
126      extension_action_manager()->GetBrowserAction(*extension);
127  ASSERT_TRUE(page_action)
128      << "Page action test extension should have a page action.";
129
130  ASSERT_FALSE(page_action->HasPopup(tab_id));
131
132  // Simulate the page action being clicked.  The resulting event should
133  // install a page action popup.
134  {
135    ResultCatcher catcher;
136    ExtensionService* service = extensions::ExtensionSystem::Get(
137        browser()->profile())->extension_service();
138    service->toolbar_model()->ExecuteBrowserAction(extension, browser(), NULL);
139    ASSERT_TRUE(catcher.GetNextResult());
140  }
141
142  ASSERT_TRUE(page_action->HasPopup(tab_id))
143      << "Clicking on the page action should have caused a popup to be added.";
144
145  ASSERT_STREQ("/a_popup.html",
146               page_action->GetPopupUrl(tab_id).path().c_str());
147
148  // Now change the popup from a_popup.html to a_second_popup.html .
149  // Load a page which removes the popup using chrome.pageAction.setPopup().
150  {
151    ResultCatcher catcher;
152    ui_test_utils::NavigateToURL(
153        browser(),
154        GURL(extension->GetResourceURL("change_popup.html")));
155    ASSERT_TRUE(catcher.GetNextResult());
156  }
157
158  ASSERT_TRUE(page_action->HasPopup(tab_id));
159  ASSERT_STREQ("/another_popup.html",
160               page_action->GetPopupUrl(tab_id).path().c_str());
161}
162
163// Test that calling chrome.pageAction.setPopup() can remove a popup.
164IN_PROC_BROWSER_TEST_F(PageAsBrowserActionApiTest, RemovePopup) {
165  // Load the extension, which has a page action with a default popup.
166  ASSERT_TRUE(RunExtensionTest("page_action/remove_popup")) << message_;
167  const Extension* extension = GetSingleLoadedExtension();
168  ASSERT_TRUE(extension) << message_;
169
170  int tab_id = ExtensionTabUtil::GetTabId(
171      browser()->tab_strip_model()->GetActiveWebContents());
172
173  ExtensionAction* page_action =
174      extension_action_manager()->GetBrowserAction(*extension);
175  ASSERT_TRUE(page_action)
176      << "Page action test extension should have a page action.";
177
178  ASSERT_TRUE(page_action->HasPopup(tab_id))
179      << "Expect a page action popup before the test removes it.";
180
181  // Load a page which removes the popup using chrome.pageAction.setPopup().
182  {
183    ResultCatcher catcher;
184    ui_test_utils::NavigateToURL(
185        browser(),
186        GURL(extension->GetResourceURL("remove_popup.html")));
187    ASSERT_TRUE(catcher.GetNextResult());
188  }
189
190  ASSERT_FALSE(page_action->HasPopup(tab_id))
191      << "Page action popup should have been removed.";
192}
193
194IN_PROC_BROWSER_TEST_F(PageAsBrowserActionApiTest, Getters) {
195  ASSERT_TRUE(RunExtensionTest("page_action/getters")) << message_;
196  const Extension* extension = GetSingleLoadedExtension();
197  ASSERT_TRUE(extension) << message_;
198
199  ResultCatcher catcher;
200  ui_test_utils::NavigateToURL(browser(),
201      GURL(extension->GetResourceURL("update.html")));
202  ASSERT_TRUE(catcher.GetNextResult());
203}
204
205}
206}  // namespace extensions
207