| Index: chrome/browser/ui/cocoa/extension_installed_bubble_controller.mm
|
| ===================================================================
|
| --- chrome/browser/ui/cocoa/extension_installed_bubble_controller.mm (revision 71534)
|
| +++ chrome/browser/ui/cocoa/extension_installed_bubble_controller.mm (working copy)
|
| @@ -1,378 +0,0 @@
|
| -// Copyright (c) 2010 The Chromium Authors. All rights reserved.
|
| -// Use of this source code is governed by a BSD-style license that can be
|
| -// found in the LICENSE file.
|
| -
|
| -#import "extension_installed_bubble_controller.h"
|
| -
|
| -#include "app/l10n_util.h"
|
| -#include "base/i18n/rtl.h"
|
| -#include "base/mac/mac_util.h"
|
| -#include "base/sys_string_conversions.h"
|
| -#include "base/utf_string_conversions.h"
|
| -#include "chrome/browser/ui/cocoa/browser_window_cocoa.h"
|
| -#include "chrome/browser/ui/cocoa/browser_window_controller.h"
|
| -#include "chrome/browser/ui/cocoa/extensions/browser_actions_controller.h"
|
| -#include "chrome/browser/ui/cocoa/hover_close_button.h"
|
| -#include "chrome/browser/ui/cocoa/info_bubble_view.h"
|
| -#include "chrome/browser/ui/cocoa/location_bar/location_bar_view_mac.h"
|
| -#include "chrome/browser/ui/cocoa/toolbar_controller.h"
|
| -#include "chrome/browser/ui/browser.h"
|
| -#include "chrome/browser/ui/browser_window.h"
|
| -#include "chrome/common/extensions/extension.h"
|
| -#include "chrome/common/extensions/extension_action.h"
|
| -#include "chrome/common/notification_details.h"
|
| -#include "chrome/common/notification_registrar.h"
|
| -#include "chrome/common/notification_source.h"
|
| -#include "grit/generated_resources.h"
|
| -#import "skia/ext/skia_utils_mac.h"
|
| -#import "third_party/GTM/AppKit/GTMUILocalizerAndLayoutTweaker.h"
|
| -
|
| -
|
| -// C++ class that receives EXTENSION_LOADED notifications and proxies them back
|
| -// to |controller|.
|
| -class ExtensionLoadedNotificationObserver : public NotificationObserver {
|
| - public:
|
| - ExtensionLoadedNotificationObserver(
|
| - ExtensionInstalledBubbleController* controller, Profile* profile)
|
| - : controller_(controller) {
|
| - registrar_.Add(this, NotificationType::EXTENSION_LOADED,
|
| - Source<Profile>(profile));
|
| - registrar_.Add(this, NotificationType::EXTENSION_UNLOADED,
|
| - Source<Profile>(profile));
|
| - }
|
| -
|
| - private:
|
| - // NotificationObserver implementation. Tells the controller to start showing
|
| - // its window on the main thread when the extension has finished loading.
|
| - void Observe(NotificationType type,
|
| - const NotificationSource& source,
|
| - const NotificationDetails& details) {
|
| - if (type == NotificationType::EXTENSION_LOADED) {
|
| - const Extension* extension = Details<const Extension>(details).ptr();
|
| - if (extension == [controller_ extension]) {
|
| - [controller_ performSelectorOnMainThread:@selector(showWindow:)
|
| - withObject:controller_
|
| - waitUntilDone:NO];
|
| - }
|
| - } else if (type == NotificationType::EXTENSION_UNLOADED) {
|
| - const Extension* extension = Details<const Extension>(details).ptr();
|
| - if (extension == [controller_ extension]) {
|
| - [controller_ performSelectorOnMainThread:@selector(extensionUnloaded:)
|
| - withObject:controller_
|
| - waitUntilDone:NO];
|
| - }
|
| - } else {
|
| - NOTREACHED() << "Received unexpected notification.";
|
| - }
|
| - }
|
| -
|
| - NotificationRegistrar registrar_;
|
| - ExtensionInstalledBubbleController* controller_; // weak, owns us
|
| -};
|
| -
|
| -@implementation ExtensionInstalledBubbleController
|
| -
|
| -@synthesize extension = extension_;
|
| -@synthesize pageActionRemoved = pageActionRemoved_; // Exposed for unit test.
|
| -
|
| -- (id)initWithParentWindow:(NSWindow*)parentWindow
|
| - extension:(const Extension*)extension
|
| - browser:(Browser*)browser
|
| - icon:(SkBitmap)icon {
|
| - NSString* nibPath =
|
| - [base::mac::MainAppBundle() pathForResource:@"ExtensionInstalledBubble"
|
| - ofType:@"nib"];
|
| - if ((self = [super initWithWindowNibPath:nibPath owner:self])) {
|
| - DCHECK(parentWindow);
|
| - parentWindow_ = parentWindow;
|
| - DCHECK(extension);
|
| - extension_ = extension;
|
| - DCHECK(browser);
|
| - browser_ = browser;
|
| - icon_.reset([gfx::SkBitmapToNSImage(icon) retain]);
|
| - pageActionRemoved_ = NO;
|
| -
|
| - if (!extension->omnibox_keyword().empty()) {
|
| - type_ = extension_installed_bubble::kOmniboxKeyword;
|
| - } else if (extension->browser_action()) {
|
| - type_ = extension_installed_bubble::kBrowserAction;
|
| - } else if (extension->page_action() &&
|
| - !extension->page_action()->default_icon_path().empty()) {
|
| - type_ = extension_installed_bubble::kPageAction;
|
| - } else {
|
| - NOTREACHED(); // kGeneric installs handled in the extension_install_ui.
|
| - }
|
| -
|
| - // Start showing window only after extension has fully loaded.
|
| - extensionObserver_.reset(new ExtensionLoadedNotificationObserver(
|
| - self, browser->profile()));
|
| - }
|
| - return self;
|
| -}
|
| -
|
| -- (void)dealloc {
|
| - [[NSNotificationCenter defaultCenter] removeObserver:self];
|
| - [super dealloc];
|
| -}
|
| -
|
| -- (void)close {
|
| - [parentWindow_ removeChildWindow:[self window]];
|
| - [super close];
|
| -}
|
| -
|
| -- (void)windowWillClose:(NSNotification*)notification {
|
| - // Turn off page action icon preview when the window closes, unless we
|
| - // already removed it when the window resigned key status.
|
| - [self removePageActionPreviewIfNecessary];
|
| - extension_ = NULL;
|
| - browser_ = NULL;
|
| - parentWindow_ = nil;
|
| - // We caught a close so we don't need to watch for the parent closing.
|
| - [[NSNotificationCenter defaultCenter] removeObserver:self];
|
| - [self autorelease];
|
| -}
|
| -
|
| -// The controller is the delegate of the window, so it receives "did resign
|
| -// key" notifications. When key is resigned, close the window.
|
| -- (void)windowDidResignKey:(NSNotification*)notification {
|
| - NSWindow* window = [self window];
|
| - DCHECK_EQ([notification object], window);
|
| - DCHECK([window isVisible]);
|
| -
|
| - // If the browser window is closing, we need to remove the page action
|
| - // immediately, otherwise the closing animation may overlap with
|
| - // browser destruction.
|
| - [self removePageActionPreviewIfNecessary];
|
| - [self close];
|
| -}
|
| -
|
| -- (IBAction)closeWindow:(id)sender {
|
| - DCHECK([[self window] isVisible]);
|
| - [self close];
|
| -}
|
| -
|
| -// Extracted to a function here so that it can be overwritten for unit
|
| -// testing.
|
| -- (void)removePageActionPreviewIfNecessary {
|
| - if (!extension_ || !extension_->page_action() || pageActionRemoved_)
|
| - return;
|
| - pageActionRemoved_ = YES;
|
| -
|
| - BrowserWindowCocoa* window =
|
| - static_cast<BrowserWindowCocoa*>(browser_->window());
|
| - LocationBarViewMac* locationBarView =
|
| - [window->cocoa_controller() locationBarBridge];
|
| - locationBarView->SetPreviewEnabledPageAction(extension_->page_action(),
|
| - false); // disables preview.
|
| -}
|
| -
|
| -// The extension installed bubble points at the browser action icon or the
|
| -// page action icon (shown as a preview), depending on the extension type.
|
| -// We need to calculate the location of these icons and the size of the
|
| -// message itself (which varies with the title of the extension) in order
|
| -// to figure out the origin point for the extension installed bubble.
|
| -// TODO(mirandac): add framework to easily test extension UI components!
|
| -- (NSPoint)calculateArrowPoint {
|
| - BrowserWindowCocoa* window =
|
| - static_cast<BrowserWindowCocoa*>(browser_->window());
|
| - NSPoint arrowPoint = NSZeroPoint;
|
| -
|
| - switch(type_) {
|
| - case extension_installed_bubble::kOmniboxKeyword: {
|
| - LocationBarViewMac* locationBarView =
|
| - [window->cocoa_controller() locationBarBridge];
|
| - arrowPoint = locationBarView->GetPageInfoBubblePoint();
|
| - break;
|
| - }
|
| - case extension_installed_bubble::kBrowserAction: {
|
| - BrowserActionsController* controller =
|
| - [[window->cocoa_controller() toolbarController]
|
| - browserActionsController];
|
| - arrowPoint = [controller popupPointForBrowserAction:extension_];
|
| - break;
|
| - }
|
| - case extension_installed_bubble::kPageAction: {
|
| - LocationBarViewMac* locationBarView =
|
| - [window->cocoa_controller() locationBarBridge];
|
| -
|
| - // Tell the location bar to show a preview of the page action icon, which
|
| - // would ordinarily only be displayed on a page of the appropriate type.
|
| - // We remove this preview when the extension installed bubble closes.
|
| - locationBarView->SetPreviewEnabledPageAction(extension_->page_action(),
|
| - true);
|
| -
|
| - // Find the center of the bottom of the page action icon.
|
| - arrowPoint =
|
| - locationBarView->GetPageActionBubblePoint(extension_->page_action());
|
| - break;
|
| - }
|
| - default: {
|
| - NOTREACHED() << "Generic extension type not allowed in install bubble.";
|
| - }
|
| - }
|
| - return arrowPoint;
|
| -}
|
| -
|
| -// We want this to be a child of a browser window. addChildWindow:
|
| -// (called from this function) will bring the window on-screen;
|
| -// unfortunately, [NSWindowController showWindow:] will also bring it
|
| -// on-screen (but will cause unexpected changes to the window's
|
| -// position). We cannot have an addChildWindow: and a subsequent
|
| -// showWindow:. Thus, we have our own version.
|
| -- (void)showWindow:(id)sender {
|
| - // Generic extensions get an infobar rather than a bubble.
|
| - DCHECK(type_ != extension_installed_bubble::kGeneric);
|
| - DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
|
| -
|
| - // Load nib and calculate height based on messages to be shown.
|
| - NSWindow* window = [self initializeWindow];
|
| - int newWindowHeight = [self calculateWindowHeight];
|
| - [infoBubbleView_ setFrameSize:NSMakeSize(
|
| - NSWidth([[window contentView] bounds]), newWindowHeight)];
|
| - NSSize windowDelta = NSMakeSize(
|
| - 0, newWindowHeight - NSHeight([[window contentView] bounds]));
|
| - windowDelta = [[window contentView] convertSize:windowDelta toView:nil];
|
| - NSRect newFrame = [window frame];
|
| - newFrame.size.height += windowDelta.height;
|
| - [window setFrame:newFrame display:NO];
|
| -
|
| - // Now that we have resized the window, adjust y pos of the messages.
|
| - [self setMessageFrames:newWindowHeight];
|
| -
|
| - // Find window origin, taking into account bubble size and arrow location.
|
| - NSPoint origin =
|
| - [parentWindow_ convertBaseToScreen:[self calculateArrowPoint]];
|
| - NSSize offsets = NSMakeSize(info_bubble::kBubbleArrowXOffset +
|
| - info_bubble::kBubbleArrowWidth / 2.0, 0);
|
| - offsets = [[window contentView] convertSize:offsets toView:nil];
|
| - if ([infoBubbleView_ arrowLocation] == info_bubble::kTopRight)
|
| - origin.x -= NSWidth([window frame]) - offsets.width;
|
| - origin.y -= NSHeight([window frame]);
|
| - [window setFrameOrigin:origin];
|
| -
|
| - [parentWindow_ addChildWindow:window
|
| - ordered:NSWindowAbove];
|
| - [window makeKeyAndOrderFront:self];
|
| -}
|
| -
|
| -// Finish nib loading, set arrow location and load icon into window. This
|
| -// function is exposed for unit testing.
|
| -- (NSWindow*)initializeWindow {
|
| - NSWindow* window = [self window]; // completes nib load
|
| -
|
| - if (type_ == extension_installed_bubble::kOmniboxKeyword) {
|
| - [infoBubbleView_ setArrowLocation:info_bubble::kTopLeft];
|
| - } else {
|
| - [infoBubbleView_ setArrowLocation:info_bubble::kTopRight];
|
| - }
|
| -
|
| - // Set appropriate icon, resizing if necessary.
|
| - if ([icon_ size].width > extension_installed_bubble::kIconSize) {
|
| - [icon_ setSize:NSMakeSize(extension_installed_bubble::kIconSize,
|
| - extension_installed_bubble::kIconSize)];
|
| - }
|
| - [iconImage_ setImage:icon_];
|
| - [iconImage_ setNeedsDisplay:YES];
|
| - return window;
|
| - }
|
| -
|
| -// Calculate the height of each install message, resizing messages in their
|
| -// frames to fit window width. Return the new window height, based on the
|
| -// total of all message heights.
|
| -- (int)calculateWindowHeight {
|
| - // Adjust the window height to reflect the sum height of all messages
|
| - // and vertical padding.
|
| - int newWindowHeight = 2 * extension_installed_bubble::kOuterVerticalMargin;
|
| -
|
| - // First part of extension installed message.
|
| - string16 extension_name = UTF8ToUTF16(extension_->name().c_str());
|
| - base::i18n::AdjustStringForLocaleDirection(&extension_name);
|
| - [extensionInstalledMsg_ setStringValue:l10n_util::GetNSStringF(
|
| - IDS_EXTENSION_INSTALLED_HEADING, extension_name)];
|
| - [GTMUILocalizerAndLayoutTweaker
|
| - sizeToFitFixedWidthTextField:extensionInstalledMsg_];
|
| - newWindowHeight += [extensionInstalledMsg_ frame].size.height +
|
| - extension_installed_bubble::kInnerVerticalMargin;
|
| -
|
| - // If type is page action, include a special message about page actions.
|
| - if (type_ == extension_installed_bubble::kPageAction) {
|
| - [extraInfoMsg_ setHidden:NO];
|
| - [[extraInfoMsg_ cell]
|
| - setFont:[NSFont systemFontOfSize:[NSFont smallSystemFontSize]]];
|
| - [GTMUILocalizerAndLayoutTweaker
|
| - sizeToFitFixedWidthTextField:extraInfoMsg_];
|
| - newWindowHeight += [extraInfoMsg_ frame].size.height +
|
| - extension_installed_bubble::kInnerVerticalMargin;
|
| - }
|
| -
|
| - // If type is omnibox keyword, include a special message about the keyword.
|
| - if (type_ == extension_installed_bubble::kOmniboxKeyword) {
|
| - [extraInfoMsg_ setStringValue:l10n_util::GetNSStringF(
|
| - IDS_EXTENSION_INSTALLED_OMNIBOX_KEYWORD_INFO,
|
| - UTF8ToUTF16(extension_->omnibox_keyword()))];
|
| - [extraInfoMsg_ setHidden:NO];
|
| - [[extraInfoMsg_ cell]
|
| - setFont:[NSFont systemFontOfSize:[NSFont smallSystemFontSize]]];
|
| - [GTMUILocalizerAndLayoutTweaker
|
| - sizeToFitFixedWidthTextField:extraInfoMsg_];
|
| - newWindowHeight += [extraInfoMsg_ frame].size.height +
|
| - extension_installed_bubble::kInnerVerticalMargin;
|
| - }
|
| -
|
| - // Second part of extension installed message.
|
| - [[extensionInstalledInfoMsg_ cell]
|
| - setFont:[NSFont systemFontOfSize:[NSFont smallSystemFontSize]]];
|
| - [GTMUILocalizerAndLayoutTweaker
|
| - sizeToFitFixedWidthTextField:extensionInstalledInfoMsg_];
|
| - newWindowHeight += [extensionInstalledInfoMsg_ frame].size.height;
|
| -
|
| - return newWindowHeight;
|
| -}
|
| -
|
| -// Adjust y-position of messages to sit properly in new window height.
|
| -- (void)setMessageFrames:(int)newWindowHeight {
|
| - // The extension messages will always be shown.
|
| - NSRect extensionMessageFrame1 = [extensionInstalledMsg_ frame];
|
| - NSRect extensionMessageFrame2 = [extensionInstalledInfoMsg_ frame];
|
| -
|
| - extensionMessageFrame1.origin.y = newWindowHeight - (
|
| - extensionMessageFrame1.size.height +
|
| - extension_installed_bubble::kOuterVerticalMargin);
|
| - [extensionInstalledMsg_ setFrame:extensionMessageFrame1];
|
| - if (type_ == extension_installed_bubble::kPageAction ||
|
| - type_ == extension_installed_bubble::kOmniboxKeyword) {
|
| - // The extra message is only shown when appropriate.
|
| - NSRect extraMessageFrame = [extraInfoMsg_ frame];
|
| - extraMessageFrame.origin.y = extensionMessageFrame1.origin.y - (
|
| - extraMessageFrame.size.height +
|
| - extension_installed_bubble::kInnerVerticalMargin);
|
| - [extraInfoMsg_ setFrame:extraMessageFrame];
|
| - extensionMessageFrame2.origin.y = extraMessageFrame.origin.y - (
|
| - extensionMessageFrame2.size.height +
|
| - extension_installed_bubble::kInnerVerticalMargin);
|
| - } else {
|
| - extensionMessageFrame2.origin.y = extensionMessageFrame1.origin.y - (
|
| - extensionMessageFrame2.size.height +
|
| - extension_installed_bubble::kInnerVerticalMargin);
|
| - }
|
| - [extensionInstalledInfoMsg_ setFrame:extensionMessageFrame2];
|
| -}
|
| -
|
| -// Exposed for unit testing.
|
| -- (NSRect)getExtensionInstalledMsgFrame {
|
| - return [extensionInstalledMsg_ frame];
|
| -}
|
| -
|
| -- (NSRect)getExtraInfoMsgFrame {
|
| - return [extraInfoMsg_ frame];
|
| -}
|
| -
|
| -- (NSRect)getExtensionInstalledInfoMsgFrame {
|
| - return [extensionInstalledInfoMsg_ frame];
|
| -}
|
| -
|
| -- (void)extensionUnloaded:(id)sender {
|
| - extension_ = NULL;
|
| -}
|
| -
|
| -@end
|
|
|