summaryrefslogtreecommitdiffstats
path: root/chrome/browser
diff options
context:
space:
mode:
Diffstat (limited to 'chrome/browser')
-rw-r--r--chrome/browser/cocoa/browser_window_controller.h3
-rw-r--r--chrome/browser/cocoa/browser_window_controller.mm39
-rw-r--r--chrome/browser/cocoa/extension_shelf_controller.h49
-rw-r--r--chrome/browser/cocoa/extension_shelf_controller.mm356
-rw-r--r--chrome/browser/cocoa/extension_shelf_controller_unittest.mm56
-rw-r--r--chrome/browser/cocoa/extension_view_mac.h65
-rw-r--r--chrome/browser/cocoa/extension_view_mac.mm68
-rw-r--r--chrome/browser/cocoa/status_bubble_mac.h3
-rw-r--r--chrome/browser/cocoa/status_bubble_mac.mm12
-rw-r--r--chrome/browser/extensions/extension_host.cc18
-rw-r--r--chrome/browser/extensions/extension_host.h6
-rw-r--r--chrome/browser/renderer_host/render_widget_host_view_mac.h3
-rw-r--r--chrome/browser/renderer_host/render_widget_host_view_mac.mm10
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 ---------------------------------------------------