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/strings/utf_string_conversions.h"
6#include "chrome/browser/extensions/extension_action.h"
7#include "chrome/browser/extensions/extension_action_manager.h"
8#include "chrome/browser/extensions/extension_action_test_util.h"
9#include "chrome/browser/extensions/extension_browsertest.h"
10#include "chrome/browser/extensions/extension_service.h"
11#include "chrome/browser/extensions/extension_tab_util.h"
12#include "chrome/browser/ui/browser.h"
13#include "chrome/browser/ui/browser_window.h"
14#include "chrome/browser/ui/tabs/tab_strip_model.h"
15#include "chrome/test/base/ui_test_utils.h"
16#include "extensions/browser/extension_system.h"
17#include "extensions/common/extension.h"
18#include "extensions/common/switches.h"
19
20namespace extensions {
21namespace {
22
23const std::string kFeedPage = "files/feeds/feed.html";
24const std::string kNoFeedPage = "files/feeds/no_feed.html";
25const std::string kLocalization =
26    "files/extensions/browsertest/title_localized_pa/simple.html";
27
28const std::string kHashPageA =
29    "files/extensions/api_test/page_action/hash_change/test_page_A.html";
30const std::string kHashPageAHash = kHashPageA + "#asdf";
31const std::string kHashPageB =
32    "files/extensions/api_test/page_action/hash_change/test_page_B.html";
33
34IN_PROC_BROWSER_TEST_F(ExtensionBrowserTest, PageActionCrash25562) {
35  ASSERT_TRUE(test_server()->Start());
36
37  CommandLine::ForCurrentProcess()->AppendSwitch(
38      switches::kAllowLegacyExtensionManifests);
39
40  // This page action will not show an icon, since it doesn't specify one but
41  // is included here to test for a crash (http://crbug.com/25562).
42  ASSERT_TRUE(LoadExtension(
43      test_data_dir_.AppendASCII("browsertest")
44                    .AppendASCII("crash_25562")));
45
46  // Navigate to the feed page.
47  GURL feed_url = test_server()->GetURL(kFeedPage);
48  ui_test_utils::NavigateToURL(browser(), feed_url);
49  // We should now have one page action ready to go in the LocationBar.
50  ASSERT_TRUE(WaitForPageActionVisibilityChangeTo(1));
51}
52
53// Tests that we can load page actions in the Omnibox.
54IN_PROC_BROWSER_TEST_F(ExtensionBrowserTest, PageAction) {
55  ASSERT_TRUE(test_server()->Start());
56
57  ASSERT_TRUE(LoadExtension(
58      test_data_dir_.AppendASCII("subscribe_page_action")));
59
60  ASSERT_TRUE(WaitForPageActionVisibilityChangeTo(0));
61
62  // Navigate to the feed page.
63  GURL feed_url = test_server()->GetURL(kFeedPage);
64  ui_test_utils::NavigateToURL(browser(), feed_url);
65  // We should now have one page action ready to go in the LocationBar.
66  ASSERT_TRUE(WaitForPageActionVisibilityChangeTo(1));
67
68  // Navigate to a page with no feed.
69  GURL no_feed = test_server()->GetURL(kNoFeedPage);
70  ui_test_utils::NavigateToURL(browser(), no_feed);
71  // Make sure the page action goes away.
72  ASSERT_TRUE(WaitForPageActionVisibilityChangeTo(0));
73}
74
75// Tests that we don't lose the page action icon on in-page navigations.
76IN_PROC_BROWSER_TEST_F(ExtensionBrowserTest, PageActionInPageNavigation) {
77  ASSERT_TRUE(test_server()->Start());
78
79  base::FilePath extension_path(test_data_dir_.AppendASCII("api_test")
80                                        .AppendASCII("page_action")
81                                        .AppendASCII("hash_change"));
82  ASSERT_TRUE(LoadExtension(extension_path));
83
84  // Page action should become visible when we navigate here.
85  GURL feed_url = test_server()->GetURL(kHashPageA);
86  ui_test_utils::NavigateToURL(browser(), feed_url);
87  ASSERT_TRUE(WaitForPageActionVisibilityChangeTo(1));
88
89  // In-page navigation, page action should remain.
90  feed_url = test_server()->GetURL(kHashPageAHash);
91  ui_test_utils::NavigateToURL(browser(), feed_url);
92  ASSERT_TRUE(WaitForPageActionVisibilityChangeTo(1));
93
94  // Not an in-page navigation, page action should go away.
95  feed_url = test_server()->GetURL(kHashPageB);
96  ui_test_utils::NavigateToURL(browser(), feed_url);
97  ASSERT_TRUE(WaitForPageActionVisibilityChangeTo(0));
98}
99
100// Tests that the location bar forgets about unloaded page actions.
101IN_PROC_BROWSER_TEST_F(ExtensionBrowserTest, UnloadPageAction) {
102  ASSERT_TRUE(test_server()->Start());
103
104  base::FilePath extension_path(
105      test_data_dir_.AppendASCII("subscribe_page_action"));
106  ASSERT_TRUE(LoadExtension(extension_path));
107
108  // Navigation prompts the location bar to load page actions.
109  GURL feed_url = test_server()->GetURL(kFeedPage);
110  ui_test_utils::NavigateToURL(browser(), feed_url);
111  content::WebContents* tab =
112      browser()->tab_strip_model()->GetActiveWebContents();
113  EXPECT_EQ(1u, extension_action_test_util::GetTotalPageActionCount(tab));
114
115  UnloadExtension(last_loaded_extension_id());
116
117  // Make sure the page action goes away when it's unloaded.
118  EXPECT_EQ(0u, extension_action_test_util::GetTotalPageActionCount(tab));
119}
120
121// Tests that we can load page actions in the Omnibox.
122IN_PROC_BROWSER_TEST_F(ExtensionBrowserTest, PageActionRefreshCrash) {
123  base::TimeTicks start_time = base::TimeTicks::Now();
124
125  ExtensionService* service = extensions::ExtensionSystem::Get(
126      browser()->profile())->extension_service();
127
128  size_t size_before = service->extensions()->size();
129
130  base::FilePath base_path = test_data_dir_.AppendASCII("browsertest")
131                                     .AppendASCII("crash_44415");
132  // Load extension A.
133  const Extension* extensionA = LoadExtension(base_path.AppendASCII("ExtA"));
134  ASSERT_TRUE(extensionA);
135  ASSERT_TRUE(WaitForPageActionVisibilityChangeTo(1));
136  ASSERT_EQ(size_before + 1, service->extensions()->size());
137
138  LOG(INFO) << "Load extension A done  : "
139            << (base::TimeTicks::Now() - start_time).InMilliseconds()
140            << " ms" << std::flush;
141
142  // Load extension B.
143  const Extension* extensionB = LoadExtension(base_path.AppendASCII("ExtB"));
144  ASSERT_TRUE(extensionB);
145  ASSERT_TRUE(WaitForPageActionVisibilityChangeTo(2));
146  ASSERT_EQ(size_before + 2, service->extensions()->size());
147
148  LOG(INFO) << "Load extension B done  : "
149            << (base::TimeTicks::Now() - start_time).InMilliseconds()
150            << " ms" << std::flush;
151
152  std::string idA = extensionA->id();
153  ReloadExtension(extensionA->id());
154  // ExtensionA has changed, so refetch it.
155  ASSERT_EQ(size_before + 2, service->extensions()->size());
156  extensionA = service->extensions()->GetByID(idA);
157
158  LOG(INFO) << "Reload extension A done: "
159            << (base::TimeTicks::Now() - start_time).InMilliseconds()
160            << " ms" << std::flush;
161
162  ReloadExtension(extensionB->id());
163
164  LOG(INFO) << "Reload extension B done: "
165            << (base::TimeTicks::Now() - start_time).InMilliseconds()
166            << " ms" << std::flush;
167
168  // This is where it would crash, before http://crbug.com/44415 was fixed.
169  ReloadExtension(extensionA->id());
170
171  LOG(INFO) << "Test completed         : "
172            << (base::TimeTicks::Now() - start_time).InMilliseconds()
173            << " ms" << std::flush;
174}
175
176// Tests that tooltips of a page action icon can be specified using UTF8.
177// See http://crbug.com/25349.
178IN_PROC_BROWSER_TEST_F(ExtensionBrowserTest, TitleLocalizationPageAction) {
179  ASSERT_TRUE(test_server()->Start());
180
181  ExtensionService* service = extensions::ExtensionSystem::Get(
182      browser()->profile())->extension_service();
183  const size_t size_before = service->extensions()->size();
184
185  base::FilePath extension_path(test_data_dir_.AppendASCII("browsertest")
186                                        .AppendASCII("title_localized_pa"));
187  const Extension* extension = LoadExtension(extension_path);
188  ASSERT_TRUE(extension);
189
190  // Any navigation prompts the location bar to load the page action.
191  GURL url = test_server()->GetURL(kLocalization);
192  ui_test_utils::NavigateToURL(browser(), url);
193  ASSERT_TRUE(WaitForPageActionVisibilityChangeTo(1));
194
195  ASSERT_EQ(size_before + 1, service->extensions()->size());
196
197  EXPECT_STREQ(base::WideToUTF8(L"Hreggvi\u00F0ur: l10n page action").c_str(),
198               extension->description().c_str());
199  EXPECT_STREQ(base::WideToUTF8(L"Hreggvi\u00F0ur is my name").c_str(),
200               extension->name().c_str());
201  int tab_id = ExtensionTabUtil::GetTabId(
202      browser()->tab_strip_model()->GetActiveWebContents());
203  EXPECT_STREQ(base::WideToUTF8(L"Hreggvi\u00F0ur").c_str(),
204               ExtensionActionManager::Get(browser()->profile())->
205               GetPageAction(*extension)->
206               GetTitle(tab_id).c_str());
207}
208
209}  // namespace
210}  // namespace extensions
211