• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 // Copyright (c) 2011 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 "chrome/browser/extensions/browser_action_test_util.h"
6 #include "chrome/browser/extensions/extension_browsertest.h"
7 #include "chrome/browser/extensions/extension_service.h"
8 #include "chrome/browser/profiles/profile.h"
9 #include "chrome/browser/ui/browser.h"
10 #include "chrome/browser/ui/views/browser_actions_container.h"
11 #include "chrome/common/extensions/extension_action.h"
12 #include "chrome/common/extensions/extension_resource.h"
13 
14 class BrowserActionsContainerTest : public ExtensionBrowserTest {
15  public:
BrowserActionsContainerTest()16   BrowserActionsContainerTest() : browser_(NULL) {
17   }
~BrowserActionsContainerTest()18   virtual ~BrowserActionsContainerTest() {}
19 
CreateBrowser(Profile * profile)20   virtual Browser* CreateBrowser(Profile* profile) {
21     browser_ = InProcessBrowserTest::CreateBrowser(profile);
22     browser_actions_bar_.reset(new BrowserActionTestUtil(browser_));
23     return browser_;
24   }
25 
browser()26   Browser* browser() { return browser_; }
27 
browser_actions_bar()28   BrowserActionTestUtil* browser_actions_bar() {
29     return browser_actions_bar_.get();
30   }
31 
32   // Make sure extension with index |extension_index| has an icon.
EnsureExtensionHasIcon(int extension_index)33   void EnsureExtensionHasIcon(int extension_index) {
34     if (!browser_actions_bar_->HasIcon(extension_index)) {
35       // The icon is loaded asynchronously and a notification is then sent to
36       // observers. So we wait on it.
37       browser_actions_bar_->WaitForBrowserActionUpdated(extension_index);
38     }
39     EXPECT_TRUE(browser_actions_bar()->HasIcon(extension_index));
40   }
41 
42  private:
43   scoped_ptr<BrowserActionTestUtil> browser_actions_bar_;
44 
45   Browser* browser_;  // Weak.
46 };
47 
48 // Test the basic functionality.
IN_PROC_BROWSER_TEST_F(BrowserActionsContainerTest,Basic)49 IN_PROC_BROWSER_TEST_F(BrowserActionsContainerTest, Basic) {
50   BrowserActionsContainer::disable_animations_during_testing_ = true;
51 
52   // Load an extension with no browser action.
53   ASSERT_TRUE(LoadExtension(test_data_dir_.AppendASCII("api_test")
54                                           .AppendASCII("browser_action")
55                                           .AppendASCII("none")));
56   // This extension should not be in the model (has no browser action).
57   EXPECT_EQ(0, browser_actions_bar()->NumberOfBrowserActions());
58 
59   // Load an extension with a browser action.
60   ASSERT_TRUE(LoadExtension(test_data_dir_.AppendASCII("api_test")
61                                           .AppendASCII("browser_action")
62                                           .AppendASCII("basics")));
63   EXPECT_EQ(1, browser_actions_bar()->NumberOfBrowserActions());
64   EnsureExtensionHasIcon(0);
65 
66   // Unload the extension.
67   std::string id = browser_actions_bar()->GetExtensionId(0);
68   UnloadExtension(id);
69   EXPECT_EQ(0, browser_actions_bar()->NumberOfBrowserActions());
70 }
71 
72 // TODO(mpcomplete): http://code.google.com/p/chromium/issues/detail?id=38992
IN_PROC_BROWSER_TEST_F(BrowserActionsContainerTest,Visibility)73 IN_PROC_BROWSER_TEST_F(BrowserActionsContainerTest, Visibility) {
74   BrowserActionsContainer::disable_animations_during_testing_ = true;
75 
76   base::TimeTicks start_time = base::TimeTicks::Now();
77 
78   // Load extension A (contains browser action).
79   ASSERT_TRUE(LoadExtension(test_data_dir_.AppendASCII("api_test")
80                                           .AppendASCII("browser_action")
81                                           .AppendASCII("basics")));
82   EXPECT_EQ(1, browser_actions_bar()->NumberOfBrowserActions());
83   EnsureExtensionHasIcon(0);
84   EXPECT_EQ(1, browser_actions_bar()->VisibleBrowserActions());
85   std::string idA = browser_actions_bar()->GetExtensionId(0);
86 
87   LOG(INFO) << "Load extension A done  : "
88             << (base::TimeTicks::Now() - start_time).InMilliseconds()
89             << " ms" << std::flush;
90 
91   // Load extension B (contains browser action).
92   ASSERT_TRUE(LoadExtension(test_data_dir_.AppendASCII("api_test")
93                                           .AppendASCII("browser_action")
94                                           .AppendASCII("add_popup")));
95   EXPECT_EQ(2, browser_actions_bar()->NumberOfBrowserActions());
96   EnsureExtensionHasIcon(0);
97   EXPECT_EQ(2, browser_actions_bar()->VisibleBrowserActions());
98   std::string idB = browser_actions_bar()->GetExtensionId(1);
99 
100   LOG(INFO) << "Load extension B done  : "
101             << (base::TimeTicks::Now() - start_time).InMilliseconds()
102             << " ms" << std::flush;
103 
104   EXPECT_NE(idA, idB);
105 
106   // Load extension C (contains browser action).
107   ASSERT_TRUE(LoadExtension(test_data_dir_.AppendASCII("api_test")
108                                           .AppendASCII("browser_action")
109                                           .AppendASCII("remove_popup")));
110   EXPECT_EQ(3, browser_actions_bar()->NumberOfBrowserActions());
111   EnsureExtensionHasIcon(2);
112   EXPECT_EQ(3, browser_actions_bar()->VisibleBrowserActions());
113   std::string idC = browser_actions_bar()->GetExtensionId(2);
114 
115   LOG(INFO) << "Load extension C done  : "
116             << (base::TimeTicks::Now() - start_time).InMilliseconds()
117             << " ms" << std::flush;
118 
119   // Change container to show only one action, rest in overflow: A, [B, C].
120   browser_actions_bar()->SetIconVisibilityCount(1);
121   EXPECT_EQ(1, browser_actions_bar()->VisibleBrowserActions());
122 
123   LOG(INFO) << "Icon visibility count 1: "
124             << (base::TimeTicks::Now() - start_time).InMilliseconds()
125             << " ms" << std::flush;
126 
127   // Disable extension A (should disappear). State becomes: B [C].
128   DisableExtension(idA);
129   EXPECT_EQ(2, browser_actions_bar()->NumberOfBrowserActions());
130   EXPECT_EQ(1, browser_actions_bar()->VisibleBrowserActions());
131   EXPECT_EQ(idB, browser_actions_bar()->GetExtensionId(0));
132 
133   LOG(INFO) << "Disable extension A    : "
134             << (base::TimeTicks::Now() - start_time).InMilliseconds()
135             << " ms" << std::flush;
136 
137   // Enable A again. A should get its spot in the same location and the bar
138   // should not grow (chevron is showing). For details: http://crbug.com/35349.
139   // State becomes: A, [B, C].
140   EnableExtension(idA);
141   EXPECT_EQ(3, browser_actions_bar()->NumberOfBrowserActions());
142   EXPECT_EQ(1, browser_actions_bar()->VisibleBrowserActions());
143   EXPECT_EQ(idA, browser_actions_bar()->GetExtensionId(0));
144 
145   LOG(INFO) << "Enable extension A     : "
146             << (base::TimeTicks::Now() - start_time).InMilliseconds()
147             << " ms" << std::flush;
148 
149   // Disable C (in overflow). State becomes: A, [B].
150   DisableExtension(idC);
151   EXPECT_EQ(2, browser_actions_bar()->NumberOfBrowserActions());
152   EXPECT_EQ(1, browser_actions_bar()->VisibleBrowserActions());
153   EXPECT_EQ(idA, browser_actions_bar()->GetExtensionId(0));
154 
155   LOG(INFO) << "Disable extension C    : "
156             << (base::TimeTicks::Now() - start_time).InMilliseconds()
157             << " ms" << std::flush;
158 
159   // Enable C again. State becomes: A, [B, C].
160   EnableExtension(idC);
161   EXPECT_EQ(3, browser_actions_bar()->NumberOfBrowserActions());
162   EXPECT_EQ(1, browser_actions_bar()->VisibleBrowserActions());
163   EXPECT_EQ(idA, browser_actions_bar()->GetExtensionId(0));
164 
165   LOG(INFO) << "Enable extension C     : "
166             << (base::TimeTicks::Now() - start_time).InMilliseconds()
167             << " ms" << std::flush;
168 
169   // Now we have 3 extensions. Make sure they are all visible. State: A, B, C.
170   browser_actions_bar()->SetIconVisibilityCount(3);
171   EXPECT_EQ(3, browser_actions_bar()->VisibleBrowserActions());
172 
173   LOG(INFO) << "Checkpoint             : "
174             << (base::TimeTicks::Now() - start_time).InMilliseconds()
175             << " ms" << std::flush;
176 
177   // Disable extension A (should disappear). State becomes: B, C.
178   DisableExtension(idA);
179   EXPECT_EQ(2, browser_actions_bar()->NumberOfBrowserActions());
180   EXPECT_EQ(2, browser_actions_bar()->VisibleBrowserActions());
181   EXPECT_EQ(idB, browser_actions_bar()->GetExtensionId(0));
182 
183   LOG(INFO) << "Disable extension A    : "
184             << (base::TimeTicks::Now() - start_time).InMilliseconds()
185             << " ms" << std::flush;
186 
187   // Disable extension B (should disappear). State becomes: C.
188   DisableExtension(idB);
189   EXPECT_EQ(1, browser_actions_bar()->NumberOfBrowserActions());
190   EXPECT_EQ(1, browser_actions_bar()->VisibleBrowserActions());
191   EXPECT_EQ(idC, browser_actions_bar()->GetExtensionId(0));
192 
193   LOG(INFO) << "Disable extension B    : "
194             << (base::TimeTicks::Now() - start_time).InMilliseconds()
195             << " ms" << std::flush;
196 
197   // Enable B (makes B and C showing now). State becomes: B, C.
198   EnableExtension(idB);
199   EXPECT_EQ(2, browser_actions_bar()->NumberOfBrowserActions());
200   EXPECT_EQ(2, browser_actions_bar()->VisibleBrowserActions());
201   EXPECT_EQ(idB, browser_actions_bar()->GetExtensionId(0));
202 
203   LOG(INFO) << "Enable extension B     : "
204             << (base::TimeTicks::Now() - start_time).InMilliseconds()
205             << " ms" << std::flush;
206 
207   // Enable A (makes A, B and C showing now). State becomes: B, C, A.
208   EnableExtension(idA);
209   EXPECT_EQ(3, browser_actions_bar()->NumberOfBrowserActions());
210   EXPECT_EQ(3, browser_actions_bar()->VisibleBrowserActions());
211   EXPECT_EQ(idA, browser_actions_bar()->GetExtensionId(2));
212 
213   LOG(INFO) << "Test complete          : "
214             << (base::TimeTicks::Now() - start_time).InMilliseconds()
215             << " ms" << std::flush;
216 }
217 
IN_PROC_BROWSER_TEST_F(BrowserActionsContainerTest,ForceHide)218 IN_PROC_BROWSER_TEST_F(BrowserActionsContainerTest, ForceHide) {
219   BrowserActionsContainer::disable_animations_during_testing_ = true;
220 
221   // Load extension A (contains browser action).
222   ASSERT_TRUE(LoadExtension(test_data_dir_.AppendASCII("api_test")
223                                           .AppendASCII("browser_action")
224                                           .AppendASCII("basics")));
225   EXPECT_EQ(1, browser_actions_bar()->NumberOfBrowserActions());
226   EnsureExtensionHasIcon(0);
227   EXPECT_EQ(1, browser_actions_bar()->VisibleBrowserActions());
228   std::string idA = browser_actions_bar()->GetExtensionId(0);
229 
230   // Force hide this browser action.
231   ExtensionService* service = browser()->profile()->GetExtensionService();
232   service->SetBrowserActionVisibility(service->GetExtensionById(idA, false),
233                                       false);
234   EXPECT_EQ(0, browser_actions_bar()->VisibleBrowserActions());
235 
236   ReloadExtension(idA);
237 
238   // The browser action should become visible again.
239   EXPECT_EQ(1, browser_actions_bar()->VisibleBrowserActions());
240 }
241 
IN_PROC_BROWSER_TEST_F(BrowserActionsContainerTest,TestCrash57536)242 IN_PROC_BROWSER_TEST_F(BrowserActionsContainerTest, TestCrash57536) {
243   LOG(INFO) << "Test starting\n" << std::flush;
244 
245   ExtensionService* service = browser()->profile()->GetExtensionService();
246   const size_t size_before = service->extensions()->size();
247 
248   LOG(INFO) << "Loading extension\n" << std::flush;
249 
250   // Load extension A (contains browser action).
251   ASSERT_TRUE(LoadExtension(test_data_dir_.AppendASCII("api_test")
252                                           .AppendASCII("browser_action")
253                                           .AppendASCII("crash_57536")));
254 
255   const Extension* extension = service->extensions()->at(size_before);
256 
257   LOG(INFO) << "Creating bitmap\n" << std::flush;
258 
259   // Create and cache and empty bitmap.
260   SkBitmap bitmap;
261   bitmap.setConfig(SkBitmap::kARGB_8888_Config,
262                     Extension::kBrowserActionIconMaxSize,
263                     Extension::kBrowserActionIconMaxSize);
264   bitmap.allocPixels();
265 
266   LOG(INFO) << "Set as cached image\n" << std::flush;
267 
268   gfx::Size size(Extension::kBrowserActionIconMaxSize,
269                  Extension::kBrowserActionIconMaxSize);
270   extension->SetCachedImage(
271       extension->GetResource(extension->browser_action()->default_icon_path()),
272       bitmap,
273       size);
274 
275   LOG(INFO) << "Disabling extension\n" << std::flush;
276   DisableExtension(extension->id());
277   LOG(INFO) << "Enabling extension\n" << std::flush;
278   EnableExtension(extension->id());
279   LOG(INFO) << "Test ending\n" << std::flush;
280 }
281