- add sources.
[platform/framework/web/crosswalk.git] / src / chrome / browser / ui / cocoa / extensions / extension_installed_bubble_controller_unittest.mm
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 #import <Cocoa/Cocoa.h>
6
7 #include "base/basictypes.h"
8 #include "base/command_line.h"
9 #include "base/file_util.h"
10 #include "base/files/file_path.h"
11 #include "base/memory/scoped_ptr.h"
12 #include "base/path_service.h"
13 #include "base/values.h"
14 #include "chrome/browser/extensions/extension_service.h"
15 #include "chrome/browser/extensions/test_extension_system.h"
16 #import "chrome/browser/ui/browser_window.h"
17 #include "chrome/browser/ui/cocoa/cocoa_profile_test.h"
18 #import "chrome/browser/ui/cocoa/extensions/extension_installed_bubble_controller.h"
19 #import "chrome/browser/ui/cocoa/info_bubble_window.h"
20 #include "chrome/common/chrome_paths.h"
21 #include "chrome/common/extensions/extension.h"
22 #include "chrome/test/base/testing_profile.h"
23 #include "extensions/common/manifest_constants.h"
24 #include "third_party/ocmock/gtest_support.h"
25 #import "third_party/ocmock/OCMock/OCMock.h"
26 #include "ui/gfx/codec/png_codec.h"
27
28 using extensions::Extension;
29
30 // ExtensionInstalledBubbleController with removePageActionPreview overridden
31 // to a no-op, because pageActions are not yet hooked up in the test browser.
32 @interface ExtensionInstalledBubbleControllerForTest :
33     ExtensionInstalledBubbleController {
34 }
35
36 // Do nothing, because browser window is not set up with page actions
37 // for unit testing.
38 - (void)removePageActionPreview;
39
40 @end
41
42 @implementation ExtensionInstalledBubbleControllerForTest
43
44 - (void)removePageActionPreview { }
45
46 @end
47
48 namespace keys = extensions::manifest_keys;
49
50 class ExtensionInstalledBubbleControllerTest : public CocoaProfileTest {
51
52  public:
53   virtual void SetUp() {
54     CocoaProfileTest::SetUp();
55     ASSERT_TRUE(browser());
56     window_ = browser()->window()->GetNativeWindow();
57     icon_ = LoadTestIcon();
58     CommandLine command_line(CommandLine::NO_PROGRAM);
59     extension_service_ = static_cast<extensions::TestExtensionSystem*>(
60         extensions::ExtensionSystem::Get(profile()))->CreateExtensionService(
61             &command_line, base::FilePath(), false);
62   }
63
64   // Load test icon from extension test directory.
65   SkBitmap LoadTestIcon() {
66     base::FilePath path;
67     PathService::Get(chrome::DIR_TEST_DATA, &path);
68     path = path.AppendASCII("extensions").AppendASCII("icon1.png");
69
70     std::string file_contents;
71     base::ReadFileToString(path, &file_contents);
72     const unsigned char* data =
73         reinterpret_cast<const unsigned char*>(file_contents.data());
74
75     SkBitmap bitmap;
76     gfx::PNGCodec::Decode(data, file_contents.length(), &bitmap);
77     return bitmap;
78   }
79
80   // Create a skeletal framework of either page action or browser action
81   // type.  This extension only needs to have a type and a name to initialize
82   // the ExtensionInstalledBubble for unit testing.
83   scoped_refptr<Extension> CreateExtension(
84         extension_installed_bubble::ExtensionType type) {
85     base::FilePath path;
86     PathService::Get(chrome::DIR_TEST_DATA, &path);
87     path = path.AppendASCII("extensions").AppendASCII("dummy");
88
89     DictionaryValue extension_input_value;
90     extension_input_value.SetString(keys::kVersion, "1.0.0.0");
91     if (type == extension_installed_bubble::kPageAction) {
92       extension_input_value.SetString(keys::kName, "page action extension");
93       DictionaryValue* action = new DictionaryValue;
94       action->SetString(keys::kPageActionId, "ExtensionActionId");
95       action->SetString(keys::kPageActionDefaultTitle, "ExtensionActionTitle");
96       action->SetString(keys::kPageActionDefaultIcon, "image1.png");
97       ListValue* action_list = new ListValue;
98       action_list->Append(action);
99       extension_input_value.Set(keys::kPageActions, action_list);
100     } else if (type == extension_installed_bubble::kBrowserAction) {
101       extension_input_value.SetString(keys::kName, "browser action extension");
102       DictionaryValue* browser_action = new DictionaryValue;
103       // An empty dictionary is enough to create a Browser Action.
104       extension_input_value.Set(keys::kBrowserAction, browser_action);
105     } else if (type == extension_installed_bubble::kApp) {
106       extension_input_value.SetString(keys::kName, "test app");
107       extension_input_value.SetString(keys::kLaunchWebURL,
108                                       "http://www.example.com");
109     }
110
111     std::string error;
112     scoped_refptr<Extension> extension =
113         Extension::Create(path, extensions::Manifest::INVALID_LOCATION,
114                           extension_input_value, Extension::NO_FLAGS, &error);
115     extension_service_->AddExtension(extension.get());
116     return extension;
117   }
118
119   // Required to initialize the extension installed bubble.
120   NSWindow* window_;  // weak, owned by CocoaProfileTest.
121
122   ExtensionService* extension_service_;
123
124   // Skeleton extension to be tested; reinitialized for each test.
125   scoped_refptr<Extension> extension_;
126
127   // The icon_ to be loaded into the bubble window.
128   SkBitmap icon_;
129 };
130
131 // Confirm that window sizes are set correctly for a page action extension.
132 TEST_F(ExtensionInstalledBubbleControllerTest, PageActionTest) {
133   extension_ = CreateExtension(extension_installed_bubble::kPageAction);
134   ExtensionInstalledBubbleControllerForTest* controller =
135       [[ExtensionInstalledBubbleControllerForTest alloc]
136           initWithParentWindow:window_
137                      extension:extension_.get()
138                         bundle:NULL
139                        browser:browser()
140                           icon:icon_];
141   EXPECT_TRUE(controller);
142
143   // Initialize window without having to calculate tabstrip locations.
144   [controller initializeWindow];
145   EXPECT_TRUE([controller window]);
146
147   int height = [controller calculateWindowHeight];
148   // Height should equal the vertical padding + height of all messages.
149   int correctHeight = 2 * extension_installed_bubble::kOuterVerticalMargin +
150       2 * extension_installed_bubble::kInnerVerticalMargin +
151       NSHeight([controller headingFrame]) +
152       NSHeight([controller frameOfHowToUse]) +
153       NSHeight([controller frameOfHowToManage]);
154   if ([controller showSyncPromo]) {
155     correctHeight += NSHeight([controller frameOfSigninPromo]) +
156                      extension_installed_bubble::kInnerVerticalMargin;
157   }
158   EXPECT_EQ(height, correctHeight);
159   [controller setMessageFrames:height];
160
161   NSRect msg1Frame = [controller headingFrame];
162   NSRect msg2Frame = [controller frameOfHowToUse];
163   NSRect msg3Frame = [controller frameOfHowToManage];
164   NSRect msg4Frame = [controller frameOfSigninPromo];
165
166   int next_y = extension_installed_bubble::kOuterVerticalMargin;
167   if ([controller showSyncPromo]) {
168     // Bottom message should be kOuterVerticalMargin pixels above window edge.
169     EXPECT_EQ(next_y, NSMinY(msg4Frame));
170     next_y = NSMinY(msg4Frame) + NSHeight(msg4Frame) +
171             extension_installed_bubble::kInnerVerticalMargin;
172   }
173
174   // HowToManage frame should be kInnerVerticalMargin pixels above sync promo,
175   // unless sync promo is hidden, then kOuterVerticalMargin pixels above.
176   EXPECT_EQ(next_y, NSMinY(msg3Frame));
177
178   // Page action message should be kInnerVerticalMargin pixels above bottom msg.
179   EXPECT_EQ(NSMinY(msg3Frame) + NSHeight(msg3Frame) +
180                 extension_installed_bubble::kInnerVerticalMargin,
181             NSMinY(msg2Frame));
182
183   // Top message should be kInnerVerticalMargin pixels above Page action msg.
184   EXPECT_EQ(NSMinY(msg2Frame) + NSHeight(msg2Frame) +
185                 extension_installed_bubble::kInnerVerticalMargin,
186             NSMinY(msg1Frame));
187
188   [controller setPageActionPreviewShowing:NO];
189   [controller close];
190 }
191
192 TEST_F(ExtensionInstalledBubbleControllerTest, BrowserActionTest) {
193   extension_ = CreateExtension(extension_installed_bubble::kBrowserAction);
194   ExtensionInstalledBubbleControllerForTest* controller =
195       [[ExtensionInstalledBubbleControllerForTest alloc]
196           initWithParentWindow:window_
197                      extension:extension_.get()
198                         bundle:NULL
199                        browser:browser()
200                           icon:icon_];
201   EXPECT_TRUE(controller);
202
203   // Initialize window without having to calculate tabstrip locations.
204   [controller initializeWindow];
205   EXPECT_TRUE([controller window]);
206
207   int height = [controller calculateWindowHeight];
208   // Height should equal the vertical padding + height of all messages.
209   int correctHeight = 2 * extension_installed_bubble::kOuterVerticalMargin +
210       2 * extension_installed_bubble::kInnerVerticalMargin +
211       NSHeight([controller headingFrame]) +
212       NSHeight([controller frameOfHowToUse]) +
213       NSHeight([controller frameOfHowToManage]);
214   if ([controller showSyncPromo]) {
215     correctHeight += NSHeight([controller frameOfSigninPromo]) +
216                      extension_installed_bubble::kInnerVerticalMargin;
217   }
218   EXPECT_EQ(height, correctHeight);
219   [controller setMessageFrames:height];
220
221   NSRect msg1Frame = [controller headingFrame];
222   NSRect msg2Frame = [controller frameOfHowToUse];
223   NSRect msg3Frame = [controller frameOfHowToManage];
224   NSRect msg4Frame = [controller frameOfSigninPromo];
225
226   int next_y = extension_installed_bubble::kOuterVerticalMargin;
227   if ([controller showSyncPromo]) {
228     // Bottom message should be kOuterVerticalMargin pixels above window edge.
229     EXPECT_EQ(next_y, NSMinY(msg4Frame));
230     next_y = NSMinY(msg4Frame) + NSHeight(msg4Frame) +
231             extension_installed_bubble::kInnerVerticalMargin;
232   }
233
234   // HowToManage frame should be kInnerVerticalMargin pixels above sync promo,
235   // unless sync promo is hidden, then kOuterVerticalMargin pixels above.
236   EXPECT_EQ(next_y, NSMinY(msg3Frame));
237
238   // Browser action message should be kInnerVerticalMargin pixels above bottom
239   // msg.
240   EXPECT_EQ(NSMinY(msg3Frame) + NSHeight(msg3Frame) +
241                 extension_installed_bubble::kInnerVerticalMargin,
242             NSMinY(msg2Frame));
243
244   // Top message should be kInnerVerticalMargin pixels above Browser action msg.
245   EXPECT_EQ(NSMinY(msg2Frame) + NSHeight(msg2Frame) +
246                 extension_installed_bubble::kInnerVerticalMargin,
247             NSMinY(msg1Frame));
248
249   [controller close];
250 }
251
252 TEST_F(ExtensionInstalledBubbleControllerTest, ParentClose) {
253   extension_ = CreateExtension(extension_installed_bubble::kBrowserAction);
254   ExtensionInstalledBubbleControllerForTest* controller =
255       [[ExtensionInstalledBubbleControllerForTest alloc]
256           initWithParentWindow:window_
257                      extension:extension_.get()
258                         bundle:NULL
259                        browser:browser()
260                           icon:icon_];
261   EXPECT_TRUE(controller);
262
263   // Bring up the window and disable close animation.
264   [controller showWindow:nil];
265   NSWindow* bubbleWindow = [controller window];
266   ASSERT_TRUE([bubbleWindow isKindOfClass:[InfoBubbleWindow class]]);
267   [static_cast<InfoBubbleWindow*>(bubbleWindow)
268       setAllowedAnimations:info_bubble::kAnimateNone];
269
270   // Observe whether the bubble window closes.
271   NSString* notification = NSWindowWillCloseNotification;
272   id observer = [OCMockObject observerMock];
273   [[observer expect] notificationWithName:notification object:bubbleWindow];
274   [[NSNotificationCenter defaultCenter]
275     addMockObserver:observer name:notification object:bubbleWindow];
276
277   // The bubble window goes from visible to not-visible.
278   EXPECT_TRUE([bubbleWindow isVisible]);
279   [window_ close];
280   EXPECT_FALSE([bubbleWindow isVisible]);
281
282   [[NSNotificationCenter defaultCenter] removeObserver:observer];
283
284   // Check that the appropriate notification was received.
285   EXPECT_OCMOCK_VERIFY(observer);
286 }
287
288 TEST_F(ExtensionInstalledBubbleControllerTest, AppTest) {
289   extension_ = CreateExtension(extension_installed_bubble::kApp);
290   ExtensionInstalledBubbleControllerForTest* controller =
291       [[ExtensionInstalledBubbleControllerForTest alloc]
292           initWithParentWindow:window_
293                      extension:extension_.get()
294                         bundle:NULL
295                        browser:browser()
296                           icon:icon_];
297   EXPECT_TRUE(controller);
298   [controller initializeWindow];
299   EXPECT_TRUE([controller window]);
300
301   int height = [controller calculateWindowHeight];
302
303   // Make sure there is always enough room for the icon and margin.
304   int minHeight = extension_installed_bubble::kIconSize +
305     (2 * extension_installed_bubble::kOuterVerticalMargin);
306   EXPECT_GT(height, minHeight);
307
308   // Make sure the "show me" link is visible.
309   EXPECT_FALSE([[controller appInstalledShortcutLink] isHidden]);
310
311   [controller close];
312 }
313