extension_installed_bubble_controller_unittest.mm revision ddb351dbec246cf1fab5ec20d2d5520909041de1
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#import <Cocoa/Cocoa.h>
6
7#include "base/basictypes.h"
8#include "base/file_path.h"
9#include "base/file_util.h"
10#include "base/memory/scoped_ptr.h"
11#include "base/path_service.h"
12#include "base/values.h"
13#import "chrome/browser/ui/browser_window.h"
14#import "chrome/browser/ui/cocoa/browser_test_helper.h"
15#import "chrome/browser/ui/cocoa/cocoa_test_helper.h"
16#import "chrome/browser/ui/cocoa/extensions/extension_installed_bubble_controller.h"
17#include "chrome/common/chrome_paths.h"
18#include "chrome/common/extensions/extension.h"
19#include "chrome/common/extensions/extension_constants.h"
20#include "webkit/glue/image_decoder.h"
21
22// ExtensionInstalledBubbleController with removePageActionPreview overridden
23// to a no-op, because pageActions are not yet hooked up in the test browser.
24@interface ExtensionInstalledBubbleControllerForTest :
25    ExtensionInstalledBubbleController {
26}
27
28// Do nothing, because browser window is not set up with page actions
29// for unit testing.
30- (void)removePageActionPreview;
31
32@end
33
34@implementation ExtensionInstalledBubbleControllerForTest
35
36- (void)removePageActionPreview { }
37
38@end
39
40namespace keys = extension_manifest_keys;
41
42class ExtensionInstalledBubbleControllerTest : public CocoaTest {
43
44 public:
45  virtual void SetUp() {
46    CocoaTest::SetUp();
47    browser_ = helper_.browser();
48    window_ = helper_.CreateBrowserWindow()->GetNativeHandle();
49    icon_ = LoadTestIcon();
50  }
51
52  virtual void TearDown() {
53    helper_.CloseBrowserWindow();
54    CocoaTest::TearDown();
55  }
56
57  // Load test icon from extension test directory.
58  SkBitmap LoadTestIcon() {
59    FilePath path;
60    PathService::Get(chrome::DIR_TEST_DATA, &path);
61    path = path.AppendASCII("extensions").AppendASCII("icon1.png");
62
63    std::string file_contents;
64    file_util::ReadFileToString(path, &file_contents);
65    const unsigned char* data =
66        reinterpret_cast<const unsigned char*>(file_contents.data());
67
68    SkBitmap bitmap;
69    webkit_glue::ImageDecoder decoder;
70    bitmap = decoder.Decode(data, file_contents.length());
71
72    return bitmap;
73  }
74
75  // Create a skeletal framework of either page action or browser action
76  // type.  This extension only needs to have a type and a name to initialize
77  // the ExtensionInstalledBubble for unit testing.
78  scoped_refptr<Extension> CreateExtension(
79        extension_installed_bubble::ExtensionType type) {
80    FilePath path;
81    PathService::Get(chrome::DIR_TEST_DATA, &path);
82    path = path.AppendASCII("extensions").AppendASCII("dummy");
83
84    DictionaryValue extension_input_value;
85    extension_input_value.SetString(keys::kVersion, "1.0.0.0");
86    if (type == extension_installed_bubble::kPageAction) {
87      extension_input_value.SetString(keys::kName, "page action extension");
88      DictionaryValue* action = new DictionaryValue;
89      action->SetString(keys::kPageActionId, "ExtensionActionId");
90      action->SetString(keys::kPageActionDefaultTitle, "ExtensionActionTitle");
91      action->SetString(keys::kPageActionDefaultIcon, "image1.png");
92      ListValue* action_list = new ListValue;
93      action_list->Append(action);
94      extension_input_value.Set(keys::kPageActions, action_list);
95    } else {
96      extension_input_value.SetString(keys::kName, "browser action extension");
97      DictionaryValue* browser_action = new DictionaryValue;
98      // An empty dictionary is enough to create a Browser Action.
99      extension_input_value.Set(keys::kBrowserAction, browser_action);
100    }
101
102    std::string error;
103    return Extension::Create(path, Extension::INVALID, extension_input_value,
104                             Extension::STRICT_ERROR_CHECKS, &error);
105  }
106
107  // Allows us to create the window and browser for testing.
108  BrowserTestHelper helper_;
109
110  // Required to initialize the extension installed bubble.
111  NSWindow* window_;  // weak, owned by BrowserTestHelper.
112
113  // Required to initialize the extension installed bubble.
114  Browser* browser_;  // weak, owned by BrowserTestHelper.
115
116  // Skeleton extension to be tested; reinitialized for each test.
117  scoped_refptr<Extension> extension_;
118
119  // The icon_ to be loaded into the bubble window.
120  SkBitmap icon_;
121};
122
123// Confirm that window sizes are set correctly for a page action extension.
124TEST_F(ExtensionInstalledBubbleControllerTest, PageActionTest) {
125  extension_ = CreateExtension(extension_installed_bubble::kPageAction);
126  ExtensionInstalledBubbleControllerForTest* controller =
127      [[ExtensionInstalledBubbleControllerForTest alloc]
128          initWithParentWindow:window_
129                     extension:extension_.get()
130                       browser:browser_
131                          icon:icon_];
132  EXPECT_TRUE(controller);
133
134  // Initialize window without having to calculate tabstrip locations.
135  [controller initializeWindow];
136  EXPECT_TRUE([controller window]);
137
138  int height = [controller calculateWindowHeight];
139  // Height should equal the vertical padding + height of all messages.
140  int correctHeight = 2 * extension_installed_bubble::kOuterVerticalMargin +
141      2 * extension_installed_bubble::kInnerVerticalMargin +
142      [controller getExtensionInstalledMsgFrame].size.height +
143      [controller getExtensionInstalledInfoMsgFrame].size.height +
144      [controller getExtraInfoMsgFrame].size.height;
145  EXPECT_EQ(height, correctHeight);
146
147  [controller setMessageFrames:height];
148  NSRect msg3Frame = [controller getExtensionInstalledInfoMsgFrame];
149  // Bottom message should be kOuterVerticalMargin pixels above window edge.
150  EXPECT_EQ(msg3Frame.origin.y,
151      extension_installed_bubble::kOuterVerticalMargin);
152  NSRect msg2Frame = [controller getExtraInfoMsgFrame];
153  // Pageaction message should be kInnerVerticalMargin pixels above bottom msg.
154  EXPECT_EQ(msg2Frame.origin.y,
155            msg3Frame.origin.y + msg3Frame.size.height +
156            extension_installed_bubble::kInnerVerticalMargin);
157  NSRect msg1Frame = [controller getExtensionInstalledMsgFrame];
158  // Top message should be kInnerVerticalMargin pixels above Pageaction msg.
159  EXPECT_EQ(msg1Frame.origin.y,
160            msg2Frame.origin.y + msg2Frame.size.height +
161            extension_installed_bubble::kInnerVerticalMargin);
162
163  [controller setPageActionRemoved:YES];
164  [controller close];
165}
166
167TEST_F(ExtensionInstalledBubbleControllerTest, BrowserActionTest) {
168  extension_ = CreateExtension(extension_installed_bubble::kBrowserAction);
169  ExtensionInstalledBubbleControllerForTest* controller =
170      [[ExtensionInstalledBubbleControllerForTest alloc]
171          initWithParentWindow:window_
172                     extension:extension_.get()
173                       browser:browser_
174                          icon:icon_];
175  EXPECT_TRUE(controller);
176
177  // Initialize window without having to calculate tabstrip locations.
178  [controller initializeWindow];
179  EXPECT_TRUE([controller window]);
180
181  int height = [controller calculateWindowHeight];
182  // Height should equal the vertical padding + height of all messages.
183  int correctHeight = 2 * extension_installed_bubble::kOuterVerticalMargin +
184      extension_installed_bubble::kInnerVerticalMargin +
185      [controller getExtensionInstalledMsgFrame].size.height +
186      [controller getExtensionInstalledInfoMsgFrame].size.height;
187  EXPECT_EQ(height, correctHeight);
188
189  [controller setMessageFrames:height];
190  NSRect msg3Frame = [controller getExtensionInstalledInfoMsgFrame];
191  // Bottom message should start kOuterVerticalMargin pixels above window edge.
192  EXPECT_EQ(msg3Frame.origin.y,
193      extension_installed_bubble::kOuterVerticalMargin);
194  NSRect msg1Frame = [controller getExtensionInstalledMsgFrame];
195  // Top message should start kInnerVerticalMargin pixels above top of
196  //  extensionInstalled message, because page action message is hidden.
197  EXPECT_EQ(msg1Frame.origin.y,
198            msg3Frame.origin.y + msg3Frame.size.height +
199                extension_installed_bubble::kInnerVerticalMargin);
200
201  [controller close];
202}
203