diff options
author | andybons@chromium.org <andybons@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98> | 2010-06-28 19:58:54 +0000 |
---|---|---|
committer | andybons@chromium.org <andybons@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98> | 2010-06-28 19:58:54 +0000 |
commit | beeb134984c5dd8cae93de8fc135384789c253ad (patch) | |
tree | a9f088f9c8d617f89b4cb4879fd0afb4731966d0 | |
parent | 5a80586e9d98cf8b4ead40e181b310f6cb518ee5 (diff) | |
download | chromium_src-beeb134984c5dd8cae93de8fc135384789c253ad.zip chromium_src-beeb134984c5dd8cae93de8fc135384789c253ad.tar.gz chromium_src-beeb134984c5dd8cae93de8fc135384789c253ad.tar.bz2 |
[Mac] Base implementation of extension infobars on the mac.
BUG=43168
TEST=install an extension that has an infobar. see if one shows up.
Review URL: http://codereview.chromium.org/2858028
git-svn-id: svn://svn.chromium.org/chrome/trunk/src@51031 0039d316-1c4b-4281-b951-d872f2087c98
10 files changed, 173 insertions, 38 deletions
diff --git a/chrome/browser/cocoa/extension_view_mac.mm b/chrome/browser/cocoa/extension_view_mac.mm index 6134fcf..feab70c 100644 --- a/chrome/browser/cocoa/extension_view_mac.mm +++ b/chrome/browser/cocoa/extension_view_mac.mm @@ -63,7 +63,7 @@ void ExtensionViewMac::UpdatePreferredSize(const gfx::Size& new_size) { // On first display of some extensions, this function is called with zero // width after the correct size has been set. Bail if zero is seen, assuming - // that an extension popup view doesn't want any dimensions to ever be zero. + // that an extension's view doesn't want any dimensions to ever be zero. // TODO(andybons): Verify this assumption and look into WebCore's // |contentesPreferredWidth| to see why this is occurring. if (NSIsEmptyRect(frame)) @@ -74,7 +74,7 @@ void ExtensionViewMac::UpdatePreferredSize(const gfx::Size& new_size) { // RenderWidgetHostViewCocoa overrides setFrame but not setFrameSize. // We need to defer the update back to the RenderWidgetHost so we don't - // get the flickering effect on 10.5 of http://crbug.com/31970. + // get the flickering effect on 10.5 of http://crbug.com/31970 [hostView setFrameWithDeferredUpdate:frame]; [hostView setNeedsDisplay:YES]; } diff --git a/chrome/browser/cocoa/extensions/extension_infobar_controller.h b/chrome/browser/cocoa/extensions/extension_infobar_controller.h new file mode 100644 index 0000000..93b7e57 --- /dev/null +++ b/chrome/browser/cocoa/extensions/extension_infobar_controller.h @@ -0,0 +1,22 @@ +// 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. + +#ifndef CHROME_BROWSER_COCOA_EXTENSIONS_EXTENSION_INFOBAR_CONTROLLER_H_ +#define CHROME_BROWSER_COCOA_EXTENSIONS_EXTENSION_INFOBAR_CONTROLLER_H_ + +#import "chrome/browser/cocoa/infobar_controller.h" + +#import <Cocoa/Cocoa.h> + +@interface ExtensionInfoBarController : InfoBarController { + // The native extension view retrieved from the extension host. Weak. + NSView* extensionView_; + + // The window containing this InfoBar. Weak. + NSWindow* window_; +} + +@end + +#endif // CHROME_BROWSER_COCOA_EXTENSIONS_EXTENSION_INFOBAR_CONTROLLER_H_ diff --git a/chrome/browser/cocoa/extensions/extension_infobar_controller.mm b/chrome/browser/cocoa/extensions/extension_infobar_controller.mm new file mode 100644 index 0000000..1a65161 --- /dev/null +++ b/chrome/browser/cocoa/extensions/extension_infobar_controller.mm @@ -0,0 +1,118 @@ +// 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 "chrome/browser/cocoa/extensions/extension_infobar_controller.h" + +#import "chrome/browser/cocoa/animatable_view.h" +#include "chrome/browser/cocoa/infobar.h" +#include "chrome/browser/extensions/extension_host.h" +#include "chrome/browser/extensions/extension_infobar_delegate.h" +#include "chrome/browser/tab_contents/tab_contents.h" + +namespace { +const CGFloat kAnimationDuration = 0.12; +const CGFloat kBottomBorderHeightPx = 1.0; +} // namepsace + +@interface ExtensionInfoBarController(Private) +// Called when the extension's hosted NSView has been resized. +- (void)extensionViewFrameChanged; +// Adjusts the width of the extension's hosted view to match the window's width. +- (void)adjustWidthToFitWindow; +@end + +@implementation ExtensionInfoBarController + +- (id)initWithDelegate:(InfoBarDelegate*)delegate + window:(NSWindow*)window { + if ((self = [super initWithDelegate:delegate])) { + window_ = window; + } + return self; +} + +- (void)dealloc { + [[NSNotificationCenter defaultCenter] removeObserver:self]; + [super dealloc]; +} + +- (void)addAdditionalControls { + [self removeButtons]; + + extensionView_ = delegate_->AsExtensionInfoBarDelegate()-> + extension_host()->view()->native_view(); + + // Add the extension's RenderWidgetHostViewMac to the view hierarchy of the + // InfoBar and make sure to place it below the Close button. + [infoBarView_ addSubview:extensionView_ + positioned:NSWindowBelow + relativeTo:(NSView*)closeButton_]; + + // Because the parent view has a bottom border, account for it during + // positioning. + NSRect extensionFrame = [extensionView_ frame]; + extensionFrame.origin.y = kBottomBorderHeightPx; + + [extensionView_ setFrame:extensionFrame]; + // The extension's native view will only have a height that is non-zero if it + // already has been loaded and rendered, which is the case when you switch + // back to a tab with an extension infobar within it. The reason this is + // needed is because the extension view's frame will not have changed in the + // above case, so the NSViewFrameDidChangeNotification registered below will + // never fire. + if (extensionFrame.size.height > 0.0) { + NSSize infoBarSize = [[self view] frame].size; + infoBarSize.height = extensionFrame.size.height + kBottomBorderHeightPx; + [[self view] setFrameSize:infoBarSize]; + [infoBarView_ setFrameSize:infoBarSize]; + } + + [self adjustWidthToFitWindow]; + + // These two notification handlers are here to ensure the width of the + // native extension view is the same as the browser window's width and that + // the parent infobar view matches the height of the extension's native view. + [[NSNotificationCenter defaultCenter] + addObserver:self + selector:@selector(extensionViewFrameChanged) + name:NSViewFrameDidChangeNotification + object:extensionView_]; + + [[NSNotificationCenter defaultCenter] + addObserver:self + selector:@selector(adjustWidthToFitWindow) + name:NSWindowDidResizeNotification + object:window_]; +} + +- (void)extensionViewFrameChanged { + [self adjustWidthToFitWindow]; + + AnimatableView* view = [self animatableView]; + NSRect infoBarFrame = [view frame]; + CGFloat newHeight = NSHeight([extensionView_ frame]) + kBottomBorderHeightPx; + [infoBarView_ setPostsFrameChangedNotifications:NO]; + infoBarFrame.size.height = newHeight; + [infoBarView_ setFrame:infoBarFrame]; + [infoBarView_ setPostsFrameChangedNotifications:YES]; + [view animateToNewHeight:newHeight duration:kAnimationDuration]; +} + +- (void)adjustWidthToFitWindow { + [extensionView_ setPostsFrameChangedNotifications:NO]; + NSSize extensionViewSize = [extensionView_ frame].size; + extensionViewSize.width = NSWidth([window_ frame]); + [extensionView_ setFrameSize:extensionViewSize]; + [extensionView_ setPostsFrameChangedNotifications:YES]; +} + +@end + +InfoBar* ExtensionInfoBarDelegate::CreateInfoBar() { + NSWindow* window = [(NSView*)tab_contents_->GetContentNativeView() window]; + ExtensionInfoBarController* controller = + [[ExtensionInfoBarController alloc] initWithDelegate:this + window:window]; + return new InfoBar(controller); +} diff --git a/chrome/browser/cocoa/extensions/extension_popup_controller.h b/chrome/browser/cocoa/extensions/extension_popup_controller.h index ec31816..d7042ea 100644 --- a/chrome/browser/cocoa/extensions/extension_popup_controller.h +++ b/chrome/browser/cocoa/extensions/extension_popup_controller.h @@ -50,7 +50,7 @@ class NotificationRegistrar; scoped_ptr<DevtoolsNotificationBridge> notificationBridge_; // Whether the popup has a devtools window attached to it. - bool beingInspected_; + BOOL beingInspected_; } // Returns the ExtensionHost object associated with this popup. diff --git a/chrome/browser/cocoa/extensions/extension_popup_controller.mm b/chrome/browser/cocoa/extensions/extension_popup_controller.mm index d7a4a66..b2647da 100644 --- a/chrome/browser/cocoa/extensions/extension_popup_controller.mm +++ b/chrome/browser/cocoa/extensions/extension_popup_controller.mm @@ -42,14 +42,12 @@ class DevtoolsNotificationBridge : public NotificationObserver { const NotificationDetails& details) { switch (type.value) { case NotificationType::EXTENSION_HOST_DID_STOP_LOADING: { - if (Details<ExtensionHost>([controller_ extensionHost]) == - details) + if (Details<ExtensionHost>([controller_ extensionHost]) == details) [controller_ showDevTools]; break; } case NotificationType::DEVTOOLS_WINDOW_CLOSING: { - RenderViewHost* rvh = - [controller_ extensionHost]->render_view_host(); + RenderViewHost* rvh = [controller_ extensionHost]->render_view_host(); if (Details<RenderViewHost>(rvh) == details) // Allow the devtools to finish detaching before we close the popup [controller_ performSelector:@selector(close) @@ -92,6 +90,7 @@ class DevtoolsNotificationBridge : public NotificationObserver { parentWindow_ = parentWindow; anchor_ = [parentWindow convertBaseToScreen:anchoredAt]; host_.reset(host); + beingInspected_ = devMode; scoped_nsobject<InfoBubbleView> view([[InfoBubbleView alloc] init]); if (!view.get()) @@ -127,8 +126,7 @@ class DevtoolsNotificationBridge : public NotificationObserver { [window setDelegate:self]; [window setContentView:view]; self = [super initWithWindow:window]; - if (devMode) { - beingInspected_ = true; + if (beingInspected_) { // Listen for the the devtools window closing. notificationBridge_.reset(new DevtoolsNotificationBridge(self)); registrar_.reset(new NotificationRegistrar); @@ -138,15 +136,12 @@ class DevtoolsNotificationBridge : public NotificationObserver { registrar_->Add(notificationBridge_.get(), NotificationType::EXTENSION_HOST_DID_STOP_LOADING, Source<Profile>(host->profile())); - } else { - beingInspected_ = false; } return self; } - (void)showDevTools { - DevToolsManager::GetInstance()->OpenDevToolsWindow( - host_->render_view_host()); + DevToolsManager::GetInstance()->OpenDevToolsWindow(host_->render_view_host()); } - (void)dealloc { diff --git a/chrome/browser/cocoa/infobar_controller.h b/chrome/browser/cocoa/infobar_controller.h index 9d557cf..265700c 100644 --- a/chrome/browser/cocoa/infobar_controller.h +++ b/chrome/browser/cocoa/infobar_controller.h @@ -1,4 +1,4 @@ -// Copyright (c) 2009 The Chromium Authors. All rights reserved. +// 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. @@ -45,7 +45,7 @@ class InfoBarDelegate; // Initializes a new InfoBarController. - (id)initWithDelegate:(InfoBarDelegate*)delegate; -// Called when someone clicks on the ok or cancel buttons. Subclasses +// Called when someone clicks on the OK or Cancel buttons. Subclasses // must override if they do not hide the buttons. - (void)ok:(id)sender; - (void)cancel:(id)sender; @@ -73,6 +73,10 @@ class InfoBarDelegate; // Sets the info bar message to the specified |message|. - (void)setLabelToMessage:(NSString*)message; +// Removes the OK and Cancel buttons and resizes the textfield to use the +// space. +- (void)removeButtons; + @property(nonatomic, assign) id<InfoBarContainer> containerController; @property(nonatomic, readonly) InfoBarDelegate* delegate; @@ -94,7 +98,7 @@ class InfoBarDelegate; @interface ConfirmInfoBarController : InfoBarController -// Called when the ok and cancel buttons are clicked. +// Called when the OK and Cancel buttons are clicked. - (IBAction)ok:(id)sender; - (IBAction)cancel:(id)sender; // Called when there is a click on the link in the infobar. diff --git a/chrome/browser/cocoa/infobar_controller.mm b/chrome/browser/cocoa/infobar_controller.mm index 6f743f51..c6f42a4 100644 --- a/chrome/browser/cocoa/infobar_controller.mm +++ b/chrome/browser/cocoa/infobar_controller.mm @@ -1,4 +1,4 @@ -// Copyright (c) 2009 The Chromium Authors. All rights reserved. +// 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. @@ -86,10 +86,6 @@ const float kAnimateCloseDuration = 0.12; // infobar from its container, if necessary. - (void)cleanUpAfterAnimation:(BOOL)finished; -// Removes the ok and cancel buttons, and resizes the textfield to use the -// space. -- (void)removeButtons; - // Sets the info bar message to the specified |message|, with a hypertext // style link. |link| will be inserted into message at |linkOffset|. - (void)setLabelToMessage:(NSString*)message @@ -215,6 +211,15 @@ const float kAnimateCloseDuration = 0.12; [[label_.get() textStorage] setAttributedString:attributedString]; } +- (void)removeButtons { + // Extend the label all the way across. + NSRect labelFrame = [label_.get() frame]; + labelFrame.size.width = NSMaxX([cancelButton_ frame]) - NSMinX(labelFrame); + [okButton_ removeFromSuperview]; + [cancelButton_ removeFromSuperview]; + [label_.get() setFrame:labelFrame]; +} + @end @implementation InfoBarController (PrivateMethods) @@ -242,16 +247,6 @@ const float kAnimateCloseDuration = 0.12; [containerController_ removeDelegate:delegate_]; } -- (void)removeButtons { - // Extend the label all the way across. - // Remove the ok and cancel buttons, since they are not needed. - NSRect labelFrame = [label_.get() frame]; - labelFrame.size.width = NSMaxX([cancelButton_ frame]) - NSMinX(labelFrame); - [okButton_ removeFromSuperview]; - [cancelButton_ removeFromSuperview]; - [label_.get() setFrame:labelFrame]; -} - - (void)cleanUpAfterAnimation:(BOOL)finished { // Don't need to do any cleanup if the bar was animating open. if (!infoBarClosing_) diff --git a/chrome/browser/extensions/extension_infobar_delegate.cc b/chrome/browser/extensions/extension_infobar_delegate.cc index 7bbc79b..33e16dd 100644 --- a/chrome/browser/extensions/extension_infobar_delegate.cc +++ b/chrome/browser/extensions/extension_infobar_delegate.cc @@ -57,13 +57,6 @@ void ExtensionInfoBarDelegate::InfoBarClosed() { delete this; } -#if defined(OS_MACOSX) -InfoBar* ExtensionInfoBarDelegate::CreateInfoBar() { - NOTIMPLEMENTED(); - return NULL; -} -#endif // OS_MACOSX - void ExtensionInfoBarDelegate::Observe(NotificationType type, const NotificationSource& source, const NotificationDetails& details) { diff --git a/chrome/browser/renderer_host/render_widget_host_view_mac.mm b/chrome/browser/renderer_host/render_widget_host_view_mac.mm index ff68b86..3f9a85f 100644 --- a/chrome/browser/renderer_host/render_widget_host_view_mac.mm +++ b/chrome/browser/renderer_host/render_widget_host_view_mac.mm @@ -1106,6 +1106,12 @@ void RenderWidgetHostViewMac::SetTextInputActive(bool active) { } } +- (void)setFrameSize:(NSSize)newSize { + [super setFrameSize:newSize]; + if (renderWidgetHostView_->render_widget_host_) + renderWidgetHostView_->render_widget_host_->WasResized(); +} + - (void)setFrame:(NSRect)frameRect { [super setFrame:frameRect]; if (renderWidgetHostView_->render_widget_host_) diff --git a/chrome/chrome_browser.gypi b/chrome/chrome_browser.gypi index a7eedfd..96cecccc8 100644 --- a/chrome/chrome_browser.gypi +++ b/chrome/chrome_browser.gypi @@ -725,6 +725,8 @@ 'browser/cocoa/extensions/browser_actions_controller.mm', 'browser/cocoa/extensions/extension_action_context_menu.h', 'browser/cocoa/extensions/extension_action_context_menu.mm', + 'browser/cocoa/extensions/extension_infobar_controller.h', + 'browser/cocoa/extensions/extension_infobar_controller.mm', 'browser/cocoa/extensions/extension_install_prompt_controller.h', 'browser/cocoa/extensions/extension_install_prompt_controller.mm', 'browser/cocoa/extensions/extension_popup_controller.h', |