diff options
Diffstat (limited to 'chrome/browser')
-rw-r--r-- | chrome/browser/cocoa/browser_window_controller.h | 3 | ||||
-rw-r--r-- | chrome/browser/cocoa/browser_window_controller.mm | 39 | ||||
-rw-r--r-- | chrome/browser/cocoa/extension_shelf_controller.h | 49 | ||||
-rw-r--r-- | chrome/browser/cocoa/extension_shelf_controller.mm | 356 | ||||
-rw-r--r-- | chrome/browser/cocoa/extension_shelf_controller_unittest.mm | 56 | ||||
-rw-r--r-- | chrome/browser/cocoa/extension_view_mac.h | 65 | ||||
-rw-r--r-- | chrome/browser/cocoa/extension_view_mac.mm | 68 | ||||
-rw-r--r-- | chrome/browser/cocoa/status_bubble_mac.h | 3 | ||||
-rw-r--r-- | chrome/browser/cocoa/status_bubble_mac.mm | 12 | ||||
-rw-r--r-- | chrome/browser/extensions/extension_host.cc | 18 | ||||
-rw-r--r-- | chrome/browser/extensions/extension_host.h | 6 | ||||
-rw-r--r-- | chrome/browser/renderer_host/render_widget_host_view_mac.h | 3 | ||||
-rw-r--r-- | chrome/browser/renderer_host/render_widget_host_view_mac.mm | 10 |
13 files changed, 658 insertions, 30 deletions
diff --git a/chrome/browser/cocoa/browser_window_controller.h b/chrome/browser/cocoa/browser_window_controller.h index e7d9471..339aa61 100644 --- a/chrome/browser/cocoa/browser_window_controller.h +++ b/chrome/browser/cocoa/browser_window_controller.h @@ -25,6 +25,7 @@ class BrowserWindow; class BrowserWindowCocoa; class ConstrainedWindowMac; @class DownloadShelfController; +@class ExtensionShelfController; @class FindBarCocoaController; @class GTMWindowSheetController; @class InfoBarContainerController; @@ -65,10 +66,12 @@ class TabStripModelObserverBridge; scoped_nsobject<InfoBarContainerController> infoBarContainerController_; scoped_ptr<StatusBubble> statusBubble_; scoped_nsobject<DownloadShelfController> downloadShelfController_; + scoped_nsobject<ExtensionShelfController> extensionShelfController_; scoped_nsobject<BookmarkBubbleController> bookmarkBubbleController_; scoped_nsobject<GTMTheme> theme_; BOOL ownsBrowser_; // Only ever NO when testing BOOL fullscreen_; + CGFloat verticalOffsetForStatusBubble_; } // Load the browser window nib and do any Cocoa-specific initialization. diff --git a/chrome/browser/cocoa/browser_window_controller.mm b/chrome/browser/cocoa/browser_window_controller.mm index 2e98d78..38c5b4c 100644 --- a/chrome/browser/cocoa/browser_window_controller.mm +++ b/chrome/browser/cocoa/browser_window_controller.mm @@ -25,6 +25,7 @@ #import "chrome/browser/cocoa/browser_window_cocoa.h" #import "chrome/browser/cocoa/browser_window_controller.h" #import "chrome/browser/cocoa/download_shelf_controller.h" +#import "chrome/browser/cocoa/extension_shelf_controller.h" #import "chrome/browser/cocoa/find_bar_cocoa_controller.h" #include "chrome/browser/cocoa/find_bar_bridge.h" #import "chrome/browser/cocoa/fullscreen_window.h" @@ -189,6 +190,16 @@ willPositionSheet:(NSWindow*)sheet } [[[self window] contentView] addSubview:[toolbarController_ view]]; + if (browser_->SupportsWindowFeature(Browser::FEATURE_EXTENSIONSHELF)) { + // Create the extension shelf. + extensionShelfController_.reset([[ExtensionShelfController alloc] + initWithBrowser:browser_.get() + resizeDelegate:self]); + [[[self window] contentView] addSubview:[extensionShelfController_ view]]; + [extensionShelfController_ wasInsertedIntoWindow]; + [extensionShelfController_ show:nil]; + } + [self fixWindowGradient]; // Force a relayout of all the various bars. @@ -466,12 +477,13 @@ willPositionSheet:(NSWindow*)sheet // directly. If the view is already the correct height, does not force a // relayout. - (void)resizeView:(NSView*)view newHeight:(float)height { - // We should only ever be called for one of the following three views. + // We should only ever be called for one of the following four views. // |downloadShelfController_| may be nil. DCHECK(view); DCHECK(view == [toolbarController_ view] || view == [infoBarContainerController_ view] || - view == [downloadShelfController_ view]); + view == [downloadShelfController_ view] || + view == [extensionShelfController_ view]); // Change the height of the view and call layoutViews. We set the height here // without regard to where the view is on the screen or whether it needs to @@ -615,13 +627,7 @@ willPositionSheet:(NSWindow*)sheet // StatusBubble delegate method: tell the status bubble how far above the bottom // of the window it should position itself. - (float)verticalOffsetForStatusBubble { - float offset = 0.0; - - // Don't create a download shelf if there isn't one. - if (downloadShelfController_.get() && [[self downloadShelf] isVisible]) - offset += [[self downloadShelf] height]; - - return offset; + return verticalOffsetForStatusBubble_; } - (GTMWindowSheetController*)sheetController { @@ -827,7 +833,6 @@ willPositionSheet:(NSWindow*)sheet - (BOOL)isBookmarkBarVisible { return [[toolbarController_ bookmarkBarController] isBookmarkBarVisible]; - } - (void)toggleBookmarkBar { @@ -1242,7 +1247,17 @@ willPositionSheet:(NSWindow*)sheet [infoBarView setFrame:infoBarFrame]; maxY -= NSHeight(infoBarFrame); - // Place the download shelf at the bottom of the view, if it exists. + // Place the extension shelf at the bottom of the view, if it exists. + if (extensionShelfController_.get()) { + NSView* extensionView = [extensionShelfController_ view]; + NSRect extensionFrame = [extensionView frame]; + extensionFrame.origin.y = minY; + extensionFrame.size.width = NSWidth(contentFrame); + [extensionView setFrame:extensionFrame]; + minY += NSHeight(extensionFrame); + } + + // Place the download shelf above the extension shelf, if it exists. if (downloadShelfController_.get()) { NSView* downloadView = [downloadShelfController_ view]; NSRect downloadFrame = [downloadView frame]; @@ -1263,6 +1278,8 @@ willPositionSheet:(NSWindow*)sheet // Position the find bar relative to the infobar container. [findBarCocoaController_ positionFindBarView:[infoBarContainerController_ view]]; + + verticalOffsetForStatusBubble_ = minY; } @end diff --git a/chrome/browser/cocoa/extension_shelf_controller.h b/chrome/browser/cocoa/extension_shelf_controller.h new file mode 100644 index 0000000..a533c7a --- /dev/null +++ b/chrome/browser/cocoa/extension_shelf_controller.h @@ -0,0 +1,49 @@ +// Copyright (c) 2009 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 <Cocoa/Cocoa.h> + +#include "base/scoped_ptr.h" +#import "chrome/browser/cocoa/view_resizer.h" + +class Browser; +class ExtensionShelfMac; + +// A controller for the extension shelf. After creating on object of this class, +// insert its |view| into a superview and call |wasInsertedIntoWindow|. After +// that, the controller automatically registers itself in the extensions +// subsystem and manages displaying toolstrips in the extension shelf. +@interface ExtensionShelfController : NSViewController { + @private + CGFloat shelfHeight_; + + scoped_ptr<ExtensionShelfMac> bridge_; + + // Delegate that handles resizing our view. + id<ViewResizer> resizeDelegate_; + + Browser* browser_; +} + +// Initializes a new ExtensionShelfController. +- (id)initWithBrowser:(Browser*)browser + resizeDelegate:(id<ViewResizer>)resizeDelegate; + +// Makes the extension shelf view managed by this class visible. +- (IBAction)show:(id)sender; + +// Makes the extension shelf view managed by this class invisible. +- (IBAction)hide:(id)sender; + +// Returns the height this shelf has when it's visible (which is different from +// the frame's height if the shelf is hidden). +- (CGFloat)height; + +// Call this once this shelf's view has been inserted into a superview. It will +// create the internal bridge object to chrome's extension system and call +// cacheDisplayInRect:toBitmapImageRep: on the |view|, which requires that it is +// in a superview. +- (void)wasInsertedIntoWindow; + +@end diff --git a/chrome/browser/cocoa/extension_shelf_controller.mm b/chrome/browser/cocoa/extension_shelf_controller.mm new file mode 100644 index 0000000..ec7a40b --- /dev/null +++ b/chrome/browser/cocoa/extension_shelf_controller.mm @@ -0,0 +1,356 @@ +// Copyright (c) 2009 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_shelf_controller.h" + +#include "base/mac_util.h" +#include "chrome/browser/browser.h" +#include "chrome/browser/extensions/extension_shelf_model.h" +#include "skia/ext/skia_utils_mac.h" + +namespace { + +const int kExtensionShelfPaddingTop = 1; +const int kToolstripPadding = 2; + +} + +// This class manages the extensions ("toolstrips") on the shelf. It listens to +// events sent by the extension system, and acts as a bridge between that and +// the cocoa world. +class ExtensionShelfMac : public ExtensionShelfModelObserver { + public: + ExtensionShelfMac(Browser* browser, ExtensionShelfController* controller); + virtual ~ExtensionShelfMac(); + + // ExtensionShelfModelObserver + virtual void ToolstripInsertedAt(ExtensionHost* toolstrip, int index); + virtual void ToolstripRemovingAt(ExtensionHost* toolstrip, int index); + virtual void ToolstripMoved(ExtensionHost* toolstrip, + int from_index, + int to_index); + virtual void ToolstripChangedAt(ExtensionHost* toolstrip, int index); + virtual void ExtensionShelfEmpty(); + virtual void ShelfModelReloaded(); + virtual void ShelfModelDeleting(); + + // Determines what is our target height and sets it. + void AdjustHeight(); + + private: + class Toolstrip; + + void Show(); + void Hide(); + + // Create the contents of the extension shelf. + void Init(Profile* profile); + + // Loads the background image into memory, or does nothing if already loaded. + void InitBackground(); + + // Re-inserts all toolstrips from the model. Must be called when the shelf + // contains no toolstrips. + void LoadFromModel(); + + void DeleteToolstrips(); + + Toolstrip* ToolstripAtIndex(int index); + + ExtensionShelfController* controller_; // weak, owns us + + Browser* browser_; // weak + + // Lazily-initialized background for toolstrips. + scoped_ptr<SkBitmap> background_; + + // The model representing the toolstrips on the shelf. + ExtensionShelfModel* model_; // weak + + // Set of toolstrip views which are really on the shelf. + std::set<Toolstrip*> toolstrips_; + + // Stores if we are currently layouting items. + bool is_adjusting_height_; + + DISALLOW_COPY_AND_ASSIGN(ExtensionShelfMac); +}; + +// This class represents a single extension ("toolstrip") on the extension +// shelf. +class ExtensionShelfMac::Toolstrip { + public: + explicit Toolstrip(ExtensionHost* host) + : host_(host) { + DCHECK(host_->view()); + Init(); + } + + // Inserts the native NSView belonging to this extension into the view that + // belongs to |controller|. Makes sure the controller is notified when the + // extension's |frame| changes. + void AddToolstripToController(ExtensionShelfController* controller); + + // Removes the native NSView belonging to this extension from the view that + // belongs to |controller|. Removes |controller| as a frame size observer. + void RemoveToolstripFromController(ExtensionShelfController* controller); + + // Sets the image that is used by the extension. + void SetBackground(const SkBitmap& background) { + host_->view()->SetBackground(background); + } + + // Returns the native NSView belonging to this extension. + gfx::NativeView native_view() { + return host_->view()->native_view(); + } + + private: + void Init(); + + ExtensionHost* host_; // weak + + const std::string extension_name_; + + private: + DISALLOW_COPY_AND_ASSIGN(Toolstrip); +}; + +void ExtensionShelfMac::Toolstrip::AddToolstripToController( + ExtensionShelfController* controller) { + NSView* toolstrip_view = host_->view()->native_view(); + [[controller view] addSubview:toolstrip_view]; + + [[NSNotificationCenter defaultCenter] + addObserver:controller + selector:@selector(updateVisibility:) + name:NSViewFrameDidChangeNotification + object:toolstrip_view]; +} + +void ExtensionShelfMac::Toolstrip::RemoveToolstripFromController( + ExtensionShelfController* controller) { + [host_->view()->native_view() removeFromSuperview]; + + [[NSNotificationCenter defaultCenter] + removeObserver:controller + name:NSViewFrameDidChangeNotification + object:host_->view()->native_view()]; +} + +void ExtensionShelfMac::Toolstrip::Init() { + host_->view()->set_is_toolstrip(true); +} + +ExtensionShelfMac::ExtensionShelfMac(Browser* browser, + ExtensionShelfController* controller) + : controller_(controller), + browser_(browser), + model_(browser->extension_shelf_model()), + is_adjusting_height_(false) { + if (model_) // Can be NULL in tests. + Init(browser_->profile()); +} + +ExtensionShelfMac::~ExtensionShelfMac() { + DeleteToolstrips(); + if (model_) + model_->RemoveObserver(this); +} + +void ExtensionShelfMac::Show() { + [controller_ show:nil]; +} + +void ExtensionShelfMac::Hide() { + [controller_ hide:nil]; +} + +void ExtensionShelfMac::ToolstripInsertedAt(ExtensionHost* host, + int index) { + InitBackground(); + Toolstrip* toolstrip = new Toolstrip(host); + toolstrip->SetBackground(*background_.get()); + toolstrip->AddToolstripToController(controller_); + toolstrips_.insert(toolstrip); + model_->SetToolstripDataAt(index, toolstrip); + + AdjustHeight(); +} + +void ExtensionShelfMac::ToolstripRemovingAt(ExtensionHost* host, + int index) { + Toolstrip* toolstrip = ToolstripAtIndex(index); + toolstrip->RemoveToolstripFromController(controller_); + toolstrips_.erase(toolstrip); + model_->SetToolstripDataAt(index, NULL); + delete toolstrip; + + AdjustHeight(); +} + +void ExtensionShelfMac::ToolstripMoved(ExtensionHost* host, + int from_index, + int to_index) { + // TODO(thakis): Implement reordering toolstrips. + AdjustHeight(); +} + +void ExtensionShelfMac::ToolstripChangedAt( + ExtensionHost* toolstrip, int index) { + // TODO(thakis): Implement changing toolstrips. + AdjustHeight(); +} + +void ExtensionShelfMac::ExtensionShelfEmpty() { + AdjustHeight(); +} + +void ExtensionShelfMac::ShelfModelReloaded() { + DeleteToolstrips(); + LoadFromModel(); +} + +void ExtensionShelfMac::ShelfModelDeleting() { + DeleteToolstrips(); + model_->RemoveObserver(this); + model_ = NULL; +} + +void ExtensionShelfMac::Init(Profile* profile) { + LoadFromModel(); + model_->AddObserver(this); +} + +void ExtensionShelfMac::InitBackground() { + if (background_.get()) + return; + + // If this is called while the shelf is invisible, shortly resize the shelf so + // that it can paint itself. + NSRect current_frame = [[controller_ view] frame]; + if (current_frame.size.height < [controller_ height]) { + NSRect new_frame = current_frame; + new_frame.size.height = [controller_ height]; + [[controller_ view] setFrame:new_frame]; + } + + // The background is tiled horizontally in the toolstrip. Hence, its width + // should not be too small so that tiling is fast, and not too large, so that + // not too much memory is needed -- but the exact width doesn't really matter. + const CGFloat kBackgroundTileWidth = 100; + + // Paint shelf background into an SkBitmap. If we decide to keep the shelf, we + // need to do this for both the "main window" and "not main window" shadings. + NSRect background_rect = NSMakeRect( + 0, 0, + kBackgroundTileWidth, [controller_ height] - kExtensionShelfPaddingTop); + NSBitmapImageRep* bitmap_rep = [[controller_ view] + bitmapImageRepForCachingDisplayInRect:background_rect]; + + [[controller_ view] cacheDisplayInRect:background_rect + toBitmapImageRep:bitmap_rep]; + background_.reset(new SkBitmap(gfx::CGImageToSkBitmap([bitmap_rep CGImage]))); + + // Restore old frame. + [[controller_ view] setFrame:current_frame]; +} + +void ExtensionShelfMac::AdjustHeight() { + if (model_->empty() || toolstrips_.empty()) { + // It's possible that |model_| is not empty, but |toolstrips_| are empty + // when removing the last toolstrip. + DCHECK(toolstrips_.empty()); + Hide(); + return; + } + + if (is_adjusting_height_) + return; + is_adjusting_height_ = true; + + Show(); + + // Lay out items horizontally from left to right. This method's name is + // misleading, but matches linux and windows for now. + CGFloat x = 0; + for (std::set<Toolstrip*>::iterator iter = toolstrips_.begin(); + iter != toolstrips_.end(); ++iter) { + NSView* view = (*iter)->native_view(); + NSRect frame = [view frame]; + frame.origin.x = x; + frame.origin.y = 0; + frame.size.height = [controller_ height] - kExtensionShelfPaddingTop; + [view setFrame:frame]; + x += frame.size.width + kToolstripPadding; + } + + is_adjusting_height_ = false; +} + +void ExtensionShelfMac::LoadFromModel() { + DCHECK(toolstrips_.empty()); + int count = model_->count(); + for (int i = 0; i < count; ++i) + ToolstripInsertedAt(model_->ToolstripAt(i).host, i); + AdjustHeight(); +} + +void ExtensionShelfMac::DeleteToolstrips() { + for (std::set<Toolstrip*>::iterator iter = toolstrips_.begin(); + iter != toolstrips_.end(); ++iter) { + (*iter)->RemoveToolstripFromController(controller_); + delete *iter; + } + toolstrips_.clear(); +} + +ExtensionShelfMac::Toolstrip* ExtensionShelfMac::ToolstripAtIndex(int index) { + return static_cast<Toolstrip*>(model_->ToolstripAt(index).data); +} + + +@implementation ExtensionShelfController + +- (id)initWithBrowser:(Browser*)browser + resizeDelegate:(id<ViewResizer>)resizeDelegate { + if ((self = [super initWithNibName:@"ExtensionShelf" + bundle:mac_util::MainAppBundle()])) { + resizeDelegate_ = resizeDelegate; + browser_ = browser; + shelfHeight_ = [[self view] bounds].size.height; + + NSRect frame = [[self view] frame]; + frame.size.height = 0; + [[self view] setFrame:frame]; + } + return self; +} + +- (void)wasInsertedIntoWindow { + // The bridge_ calls cacheDisplayInRect:toBitmapImageRep:, which requires that + // the view is in a superview to work. Hence, create the bridge object no + // sooner. + DCHECK(bridge_.get() == NULL); + bridge_.reset(new ExtensionShelfMac(browser_, self)); +} + +- (IBAction)show:(id)sender { + [resizeDelegate_ resizeView:[self view] newHeight:shelfHeight_]; +} + +- (IBAction)hide:(id)sender { + [resizeDelegate_ resizeView:[self view] newHeight:0]; +} + +- (CGFloat)height { + return shelfHeight_; +} + +- (void)updateVisibility:(id)sender { + if(bridge_.get()) + bridge_->AdjustHeight(); +} + +@end diff --git a/chrome/browser/cocoa/extension_shelf_controller_unittest.mm b/chrome/browser/cocoa/extension_shelf_controller_unittest.mm new file mode 100644 index 0000000..ddbca2a --- /dev/null +++ b/chrome/browser/cocoa/extension_shelf_controller_unittest.mm @@ -0,0 +1,56 @@ +// Copyright (c) 2009 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 <Cocoa/Cocoa.h> + +#include "base/scoped_nsobject.h" +#include "chrome/browser/cocoa/browser_test_helper.h" +#import "chrome/browser/cocoa/cocoa_test_helper.h" +#import "chrome/browser/cocoa/extension_shelf_controller.h" +#import "chrome/browser/cocoa/view_resizer_pong.h" +#include "testing/gtest/include/gtest/gtest.h" +#include "testing/platform_test.h" + +namespace { + +class ExtensionShelfControllerTest : public PlatformTest { + public: + ExtensionShelfControllerTest() { + resizeDelegate_.reset([[ViewResizerPong alloc] init]); + + NSRect frame = NSMakeRect(0, 0, 100, 30); + controller_.reset([[ExtensionShelfController alloc] + initWithBrowser:helper_.browser() + resizeDelegate:resizeDelegate_.get()]); + } + + CocoaTestHelper cocoa_helper_; // Inits Cocoa, creates window, etc... + BrowserTestHelper helper_; + scoped_nsobject<ExtensionShelfController> controller_; + scoped_nsobject<ViewResizerPong> resizeDelegate_; +}; + +// Check that |hide:| tells the delegate to set the shelf's height to zero. +TEST_F(ExtensionShelfControllerTest, HideSetsHeightToZero) { + [resizeDelegate_ setHeight:10]; + [controller_ hide:nil]; + EXPECT_EQ(0, [resizeDelegate_ height]); +} + +// Check that |show:| tells the delegate to set the shelf's height to the +// shelf's desired height. +TEST_F(ExtensionShelfControllerTest, ShowSetsHeightToHeight) { + [resizeDelegate_ setHeight:0]; + [controller_ show:nil]; + EXPECT_GT([controller_ height], 0); + EXPECT_EQ([controller_ height], [resizeDelegate_ height]); +} + +// Test adding to the view hierarchy, mostly to ensure nothing leaks or crashes. +TEST_F(ExtensionShelfControllerTest, Add) { + [cocoa_helper_.contentView() addSubview:[controller_ view]]; + [controller_ wasInsertedIntoWindow]; +} + +} // namespace diff --git a/chrome/browser/cocoa/extension_view_mac.h b/chrome/browser/cocoa/extension_view_mac.h new file mode 100644 index 0000000..e358d1b --- /dev/null +++ b/chrome/browser/cocoa/extension_view_mac.h @@ -0,0 +1,65 @@ +// Copyright (c) 2009 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_EXTENSION_VIEW_MAC_H_ +#define CHROME_BROWSER_COCOA_EXTENSION_VIEW_MAC_H_ + +#include "base/basictypes.h" +#include "base/gfx/native_widget_types.h" + +class Browser; +class ExtensionHost; +class RenderViewHost; +class RenderWidgetHostViewMac; +class SkBitmap; + +// This class represents extension views. An extension view internally contains +// a bridge to an extension process, which draws to the extension view's +// native view object through IPC. +class ExtensionViewMac { + public: + ExtensionViewMac(ExtensionHost* extension_host, Browser* browser); + ~ExtensionViewMac(); + + // Starts the extension process and creates the native view. You must call + // this method before calling any of this class's other methods. + void Init(); + + // Returns the extension's native view. + gfx::NativeView native_view(); + + // Returns the browser the extension belongs to. + Browser* browser() const { return browser_; } + + // Does this extension live as a toolstrip in an extension shelf? + bool is_toolstrip() const { return is_toolstrip_; } + void set_is_toolstrip(bool is_toolstrip) { is_toolstrip_ = is_toolstrip; } + + // Sets the extensions's background image. + void SetBackground(const SkBitmap& background); + + // Method for the ExtensionHost to notify us about the correct width for + // extension contents. + void UpdatePreferredWidth(int pref_width); + + private: + RenderViewHost* render_view_host() const; + + void CreateWidgetHostView(); + + // True if the contents are being displayed inside the extension shelf. + bool is_toolstrip_; + + Browser* browser_; // weak + + ExtensionHost* extension_host_; // weak + + // Created by us, but owned by its |native_view()|. We |release| the + // rwhv's native view in our destructor, effectively freeing this. + RenderWidgetHostViewMac* render_widget_host_view_; + + DISALLOW_COPY_AND_ASSIGN(ExtensionViewMac); +}; + +#endif // CHROME_BROWSER_COCOA_EXTENSION_VIEW_MAC_H_ diff --git a/chrome/browser/cocoa/extension_view_mac.mm b/chrome/browser/cocoa/extension_view_mac.mm new file mode 100644 index 0000000..a64eee8 --- /dev/null +++ b/chrome/browser/cocoa/extension_view_mac.mm @@ -0,0 +1,68 @@ +// Copyright (c) 2009 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. + +#include "chrome/browser/cocoa/extension_view_mac.h" + +#include "chrome/browser/extensions/extension_host.h" +#include "chrome/browser/renderer_host/render_view_host.h" +#include "chrome/browser/renderer_host/render_widget_host_view_mac.h" + +ExtensionViewMac::ExtensionViewMac(ExtensionHost* extension_host, + Browser* browser) + : is_toolstrip_(true), + browser_(browser), + extension_host_(extension_host), + render_widget_host_view_(NULL) { + DCHECK(extension_host_); +} + +ExtensionViewMac::~ExtensionViewMac() { + if (render_widget_host_view_) + [render_widget_host_view_->native_view() release]; +} + +void ExtensionViewMac::Init() { + CreateWidgetHostView(); +} + +gfx::NativeView ExtensionViewMac::native_view() { + DCHECK(render_widget_host_view_); + return render_widget_host_view_->native_view(); +} + +RenderViewHost* ExtensionViewMac::render_view_host() const { + return extension_host_->render_view_host(); +} + +void ExtensionViewMac::SetBackground(const SkBitmap& background) { + DCHECK(render_widget_host_view_); + render_widget_host_view_->SetBackground(background); +} + +void ExtensionViewMac::UpdatePreferredWidth(int pref_width) { + // TODO(thakis, erikkay): Windows does some tricks to resize the extension + // view not before it's visible. Do something similar here. + + // No need to use CA here, our caller calls us repeatedly to animate the + // resizing. + NSView* view = native_view(); + NSRect frame = [view frame]; + frame.size.width = pref_width; + + // RenderWidgetHostViewCocoa overrides setFrame but not setFrameSize. + [view setFrame:frame]; + [view setNeedsDisplay:YES]; +} + +void ExtensionViewMac::CreateWidgetHostView() { + DCHECK(!render_widget_host_view_); + render_widget_host_view_ = new RenderWidgetHostViewMac(render_view_host()); + + // The RenderWidgetHostViewMac is owned by its native view, which is created + // in an autoreleased state. retain it, so that it doesn't immediately + // disappear. + [render_widget_host_view_->native_view() retain]; + + extension_host_->CreateRenderView(render_widget_host_view_); +} diff --git a/chrome/browser/cocoa/status_bubble_mac.h b/chrome/browser/cocoa/status_bubble_mac.h index 54899c2..de305de 100644 --- a/chrome/browser/cocoa/status_bubble_mac.h +++ b/chrome/browser/cocoa/status_bubble_mac.h @@ -55,9 +55,6 @@ class StatusBubbleMac : public StatusBubble { // How vertically offset the bubble is from its root position. int offset_; - - // Is the download shelf visible. - bool is_download_shelf_visible_; }; // Delegate interface that allows the StatusBubble to query its delegate about diff --git a/chrome/browser/cocoa/status_bubble_mac.mm b/chrome/browser/cocoa/status_bubble_mac.mm index 1f2ecfa..7b592c6 100644 --- a/chrome/browser/cocoa/status_bubble_mac.mm +++ b/chrome/browser/cocoa/status_bubble_mac.mm @@ -39,8 +39,7 @@ StatusBubbleMac::StatusBubbleMac(NSWindow* parent, id delegate) delegate_(delegate), window_(nil), status_text_(nil), - url_text_(nil), - is_download_shelf_visible_(false) { + url_text_(nil) { } StatusBubbleMac::~StatusBubbleMac() { @@ -127,12 +126,10 @@ void StatusBubbleMac::MouseMoved() { NSRect window_frame = [window_ frame]; window_frame.origin = [parent_ frame].origin; - // Adjust the position to sit on top of download shelf. + // Adjust the position to sit on top of download and extension shelves. // |delegate_| can be nil during unit tests. - if (is_download_shelf_visible_) { - if ([delegate_ respondsToSelector:@selector(verticalOffsetForStatusBubble)]) - window_frame.origin.y += [delegate_ verticalOffsetForStatusBubble]; - } + if ([delegate_ respondsToSelector:@selector(verticalOffsetForStatusBubble)]) + window_frame.origin.y += [delegate_ verticalOffsetForStatusBubble]; // Get the cursor position relative to the popup. cursor_location.x -= NSMaxX(window_frame); @@ -179,7 +176,6 @@ void StatusBubbleMac::MouseMoved() { } void StatusBubbleMac::UpdateDownloadShelfVisibility(bool visible) { - is_download_shelf_visible_ = visible; } void StatusBubbleMac::Create() { diff --git a/chrome/browser/extensions/extension_host.cc b/chrome/browser/extensions/extension_host.cc index 0bafeec..f8503f3 100644 --- a/chrome/browser/extensions/extension_host.cc +++ b/chrome/browser/extensions/extension_host.cc @@ -71,6 +71,9 @@ void ExtensionHost::CreateView(Browser* browser) { #elif defined(OS_LINUX) view_.reset(new ExtensionViewGtk(this, browser)); view_->Init(); +#elif defined(OS_MACOSX) + view_.reset(new ExtensionViewMac(this, browser)); + view_->Init(); #else // TODO(port) NOTREACHED(); @@ -130,10 +133,8 @@ void ExtensionHost::Observe(NotificationType type, } void ExtensionHost::UpdatePreferredWidth(int pref_width) { -#if defined(TOOLKIT_VIEWS) || defined(OS_LINUX) if (view_.get()) view_->UpdatePreferredWidth(pref_width); -#endif } void ExtensionHost::RenderViewGone(RenderViewHost* render_view_host) { @@ -180,6 +181,8 @@ void ExtensionHost::DidNavigate(RenderViewHost* render_view_host, } void ExtensionHost::InsertCssIfToolstrip() { + + // TODO(erikkay): Make these ifdefs go away -- http://crbug.com/21939 #if defined(TOOLKIT_VIEWS) ExtensionView* view = view_.get(); if (!view) @@ -190,8 +193,12 @@ void ExtensionHost::InsertCssIfToolstrip() { view->SetDidInsertCSS(true); return; } -#elif defined(OS_LINUX) +#elif defined(OS_LINUX) || defined(OS_MACOSX) +#if defined(OS_LINUX) ExtensionViewGtk* view = view_.get(); +#else + ExtensionViewMac* view = view_.get(); +#endif if (!view || !view->is_toolstrip()) return; #endif @@ -218,14 +225,12 @@ void ExtensionHost::InsertCssIfToolstrip() { pos = css.find(kToolstripTextColorSubstitution); } -#if defined(TOOLKIT_VIEWS) || defined(OS_LINUX) // TODO(erikkay) this injection should really happen in the renderer. // When the Jerry's view type change lands, investigate moving this there. // As a toolstrip, inject our toolstrip CSS to make it easier for toolstrips // to blend in with the chrome UI. render_view_host()->InsertCSSInWebFrame(L"", css, "ToolstripDefaultCss"); -#endif } void ExtensionHost::DidStopLoading(RenderViewHost* render_view_host) { @@ -362,10 +367,9 @@ void ExtensionHost::HandleMouseLeave() { } Browser* ExtensionHost::GetBrowser() { -#if defined(OS_WIN) || defined(OS_LINUX) if (view_.get()) return view_->browser(); -#endif + Profile* profile = render_view_host()->process()->profile(); Browser* browser = BrowserList::GetLastActiveWithProfile(profile); diff --git a/chrome/browser/extensions/extension_host.h b/chrome/browser/extensions/extension_host.h index b6e25e5..49a75f1 100644 --- a/chrome/browser/extensions/extension_host.h +++ b/chrome/browser/extensions/extension_host.h @@ -15,6 +15,8 @@ #include "chrome/browser/views/extensions/extension_view.h" #elif defined(OS_LINUX) #include "chrome/browser/gtk/extension_view_gtk.h" +#elif defined(OS_MACOSX) +#include "chrome/browser/cocoa/extension_view_mac.h" #endif #include "chrome/common/notification_registrar.h" @@ -48,6 +50,8 @@ class ExtensionHost : public RenderViewHostDelegate, ExtensionView* view() const { return view_.get(); } #elif defined(OS_LINUX) ExtensionViewGtk* view() const { return view_.get(); } +#elif defined(OS_MACOSX) + ExtensionViewMac* view() const { return view_.get(); } #else // TODO(port): implement void* view() const { return NULL; } @@ -158,6 +162,8 @@ class ExtensionHost : public RenderViewHostDelegate, scoped_ptr<ExtensionView> view_; #elif defined(OS_LINUX) scoped_ptr<ExtensionViewGtk> view_; +#elif defined(OS_MACOSX) + scoped_ptr<ExtensionViewMac> view_; #endif // The host for our HTML content. diff --git a/chrome/browser/renderer_host/render_widget_host_view_mac.h b/chrome/browser/renderer_host/render_widget_host_view_mac.h index b8f4146..0e76e95 100644 --- a/chrome/browser/renderer_host/render_widget_host_view_mac.h +++ b/chrome/browser/renderer_host/render_widget_host_view_mac.h @@ -32,7 +32,7 @@ class RWHVMEditCommandHelper; @interface RenderWidgetHostViewCocoa : BaseView <RenderWidgetHostViewMacOwner, NSTextInput, NSChangeSpelling> { @private - RenderWidgetHostViewMac* renderWidgetHostView_; + RenderWidgetHostViewMac* renderWidgetHostView_; // Owned by us. BOOL canBeKeyView_; BOOL closeOnDeactivate_; scoped_ptr<RWHVMEditCommandHelper> editCommand_helper_; @@ -107,6 +107,7 @@ class RenderWidgetHostViewMac : public RenderWidgetHostView { virtual gfx::Rect GetWindowRect(); virtual gfx::Rect GetRootWindowRect(); virtual void SetActive(bool active); + virtual void SetBackground(const SkBitmap& background); void KillSelf(); 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 3587616..21fce5f 100644 --- a/chrome/browser/renderer_host/render_widget_host_view_mac.mm +++ b/chrome/browser/renderer_host/render_widget_host_view_mac.mm @@ -14,6 +14,7 @@ #include "chrome/browser/renderer_host/render_widget_host.h" #include "chrome/browser/spellchecker_platform_engine.h" #include "chrome/common/native_web_keyboard_event.h" +#include "chrome/common/render_messages.h" #include "skia/ext/platform_canvas.h" #include "webkit/api/public/mac/WebInputEventFactory.h" #include "webkit/api/public/WebInputEvent.h" @@ -56,6 +57,9 @@ RenderWidgetHostViewMac::RenderWidgetHostViewMac(RenderWidgetHost* widget) is_hidden_(false), shutdown_factory_(this), parent_view_(NULL) { + // |cocoa_view_| owns us and we will be deleted when |cocoa_view_| goes away. + // Since we autorelease it, our caller must put |native_view()| into the view + // hierarchy right after calling us. cocoa_view_ = [[[RenderWidgetHostViewCocoa alloc] initWithRenderWidgetHostViewMac:this] autorelease]; render_widget_host_->set_view(this); @@ -419,6 +423,12 @@ void RenderWidgetHostViewMac::SetActive(bool active) { render_widget_host_->SetActive(active); } +void RenderWidgetHostViewMac::SetBackground(const SkBitmap& background) { + RenderWidgetHostView::SetBackground(background); + if (render_widget_host_) + render_widget_host_->Send(new ViewMsg_SetBackground( + render_widget_host_->routing_id(), background)); +} // RenderWidgetHostViewCocoa --------------------------------------------------- |