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