Home | History | Annotate | Download | only in extensions
      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 
     40 namespace keys = extension_manifest_keys;
     41 
     42 class 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.
    124 TEST_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 
    167 TEST_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