summaryrefslogtreecommitdiffstats
path: root/chrome/browser/cocoa
diff options
context:
space:
mode:
Diffstat (limited to 'chrome/browser/cocoa')
-rw-r--r--chrome/browser/cocoa/browser_command_executor.h15
-rw-r--r--chrome/browser/cocoa/browser_window_cocoa.mm8
-rw-r--r--chrome/browser/cocoa/browser_window_controller.h2
-rw-r--r--chrome/browser/cocoa/chrome_event_processing_window.mm14
-rw-r--r--chrome/browser/cocoa/chrome_event_processing_window_unittest.mm25
-rw-r--r--chrome/browser/cocoa/html_dialog_window_controller.h121
-rw-r--r--chrome/browser/cocoa/html_dialog_window_controller.mm267
-rw-r--r--chrome/browser/cocoa/html_dialog_window_controller_unittest.mm93
8 files changed, 526 insertions, 19 deletions
diff --git a/chrome/browser/cocoa/browser_command_executor.h b/chrome/browser/cocoa/browser_command_executor.h
new file mode 100644
index 0000000..4a76ff1
--- /dev/null
+++ b/chrome/browser/cocoa/browser_command_executor.h
@@ -0,0 +1,15 @@
+// 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_BROWSER_COMMAND_EXECUTOR_H_
+#define CHROME_BROWSER_BROWSER_COMMAND_EXECUTOR_H_
+
+// Defines a protocol for any object that can execute commands in the
+// context of some underlying browser object.
+@protocol BrowserCommandExecutor
+- (void)executeCommand:(int)command;
+@end
+
+#endif // CHROME_BROWSER_BROWSER_COMMAND_EXECUTOR_H_
+
diff --git a/chrome/browser/cocoa/browser_window_cocoa.mm b/chrome/browser/cocoa/browser_window_cocoa.mm
index f16c524..e00f73d 100644
--- a/chrome/browser/cocoa/browser_window_cocoa.mm
+++ b/chrome/browser/cocoa/browser_window_cocoa.mm
@@ -11,6 +11,7 @@
#import "chrome/browser/cocoa/browser_window_controller.h"
#import "chrome/browser/cocoa/clear_browsing_data_controller.h"
#import "chrome/browser/cocoa/download_shelf_controller.h"
+#import "chrome/browser/cocoa/html_dialog_window_controller.h"
#import "chrome/browser/cocoa/keyword_editor_cocoa_controller.h"
#import "chrome/browser/cocoa/nsmenuitem_additions.h"
#include "chrome/browser/cocoa/page_info_window_mac.h"
@@ -296,7 +297,12 @@ void BrowserWindowCocoa::ConfirmBrowserCloseWithPendingDownloads() {
void BrowserWindowCocoa::ShowHTMLDialog(HtmlDialogUIDelegate* delegate,
gfx::NativeWindow parent_window) {
- NOTIMPLEMENTED();
+ if (!parent_window) {
+ parent_window = GetNativeHandle();
+ }
+ [HtmlDialogWindowController showHtmlDialog:delegate
+ parentWindow:parent_window
+ browser:browser_];
}
void BrowserWindowCocoa::UserChangedTheme() {
diff --git a/chrome/browser/cocoa/browser_window_controller.h b/chrome/browser/cocoa/browser_window_controller.h
index d74e3a8..49ebe34 100644
--- a/chrome/browser/cocoa/browser_window_controller.h
+++ b/chrome/browser/cocoa/browser_window_controller.h
@@ -17,6 +17,7 @@
#import "chrome/browser/cocoa/tab_window_controller.h"
#import "chrome/browser/cocoa/bookmark_bar_controller.h"
#import "chrome/browser/cocoa/bookmark_bubble_controller.h"
+#import "chrome/browser/cocoa/browser_command_executor.h"
#import "chrome/browser/cocoa/view_resizer.h"
#import "third_party/GTM/AppKit/GTMTheme.h"
@@ -44,6 +45,7 @@ class TabStripModelObserverBridge;
TabWindowController<NSUserInterfaceValidations,
BookmarkURLOpener,
BookmarkBubbleControllerDelegate,
+ BrowserCommandExecutor,
ViewResizer,
GTMThemeDelegate> {
@private
diff --git a/chrome/browser/cocoa/chrome_event_processing_window.mm b/chrome/browser/cocoa/chrome_event_processing_window.mm
index 3170012..e70113a 100644
--- a/chrome/browser/cocoa/chrome_event_processing_window.mm
+++ b/chrome/browser/cocoa/chrome_event_processing_window.mm
@@ -5,7 +5,7 @@
#import "chrome/browser/cocoa/chrome_event_processing_window.h"
#include "base/logging.h"
-#import "chrome/browser/cocoa/browser_window_controller.h"
+#import "chrome/browser/cocoa/browser_command_executor.h"
#import "chrome/browser/cocoa/browser_frame_view.h"
#import "chrome/browser/cocoa/tab_strip_controller.h"
#import "chrome/browser/renderer_host/render_widget_host_view_mac.h"
@@ -28,14 +28,12 @@ typedef int (*KeyToCommandMapper)(bool, bool, bool, bool, int);
int cmdNum = commandForKeyboardShortcut(cmdKey, shiftKey, cntrlKey, optKey,
keyCode);
- BrowserWindowController* controller =
- (BrowserWindowController*)[self delegate];
- // A bit of sanity.
- DCHECK([controller isKindOfClass:[BrowserWindowController class]]);
- DCHECK([controller respondsToSelector:@selector(executeCommand:)]);
-
if (cmdNum != -1) {
- [controller executeCommand:cmdNum];
+ id executor = [self delegate];
+ // A bit of sanity.
+ DCHECK([executor conformsToProtocol:@protocol(BrowserCommandExecutor)]);
+ DCHECK([executor respondsToSelector:@selector(executeCommand:)]);
+ [executor executeCommand:cmdNum];
return YES;
}
return NO;
diff --git a/chrome/browser/cocoa/chrome_event_processing_window_unittest.mm b/chrome/browser/cocoa/chrome_event_processing_window_unittest.mm
index 48c8d23..05b99f5 100644
--- a/chrome/browser/cocoa/chrome_event_processing_window_unittest.mm
+++ b/chrome/browser/cocoa/chrome_event_processing_window_unittest.mm
@@ -66,6 +66,19 @@ class ChromeEventProcessingWindowTest : public CocoaTest {
ChromeEventProcessingWindow* window_;
};
+id CreateBrowserWindowControllerMock() {
+ id delegate = [OCMockObject mockForClass:[BrowserWindowController class]];
+ // Make conformsToProtocol return YES for @protocol(BrowserCommandExecutor)
+ // to satisfy the DCHECK() in handleExtraKeyboardShortcut.
+ //
+ // TODO(akalin): Figure out how to replace OCMOCK_ANY below with
+ // @protocol(BrowserCommandExecutor) and have it work.
+ BOOL yes = YES;
+ [[[delegate stub] andReturnValue:OCMOCK_VALUE(yes)]
+ conformsToProtocol:OCMOCK_ANY];
+ return delegate;
+}
+
// Verify that the window intercepts a particular key event and
// forwards it to [delegate executeCommand:]. Assume that other
// CommandForKeyboardShortcut() will work the same for the rest.
@@ -73,11 +86,7 @@ TEST_F(ChromeEventProcessingWindowTest,
PerformKeyEquivalentForwardToExecuteCommand) {
NSEvent* event = KeyEvent(NSCommandKeyMask, kVK_ANSI_1);
- id delegate = [OCMockObject mockForClass:[BrowserWindowController class]];
- // -stub to satisfy the DCHECK.
- BOOL yes = YES;
- [[[delegate stub] andReturnValue:OCMOCK_VALUE(yes)]
- isKindOfClass:[BrowserWindowController class]];
+ id delegate = CreateBrowserWindowControllerMock();
[[delegate expect] executeCommand:IDC_SELECT_TAB_0];
[window_ setDelegate:delegate];
@@ -95,11 +104,7 @@ TEST_F(ChromeEventProcessingWindowTest,
TEST_F(ChromeEventProcessingWindowTest, PerformKeyEquivalentNoForward) {
NSEvent* event = KeyEvent(0, 0);
- id delegate = [OCMockObject mockForClass:[BrowserWindowController class]];
- // -stub to satisfy the DCHECK.
- BOOL yes = YES;
- [[[delegate stub] andReturnValue:OCMOCK_VALUE(yes)]
- isKindOfClass:[BrowserWindowController class]];
+ id delegate = CreateBrowserWindowControllerMock();
[window_ setDelegate:delegate];
[window_ performKeyEquivalent:event];
diff --git a/chrome/browser/cocoa/html_dialog_window_controller.h b/chrome/browser/cocoa/html_dialog_window_controller.h
new file mode 100644
index 0000000..e5a9297
--- /dev/null
+++ b/chrome/browser/cocoa/html_dialog_window_controller.h
@@ -0,0 +1,121 @@
+// 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_HTML_DIALOG_WINDOW_CONTROLLER_H_
+#define CHROME_BROWSER_COCOA_HTML_DIALOG_WINDOW_CONTROLLER_H_
+
+#include <string>
+#include <vector>
+
+#import <Cocoa/Cocoa.h>
+
+#include "app/gfx/native_widget_types.h"
+#include "base/basictypes.h"
+#include "base/scoped_ptr.h"
+#include "chrome/browser/dom_ui/html_dialog_ui.h"
+#include "chrome/browser/tab_contents/tab_contents_delegate.h"
+#include "googleurl/src/gurl.h"
+
+class Browser;
+
+// Thin bridge that routes notifications to
+// HtmlDialogWindowController's member variables.
+class HtmlDialogWindowDelegateBridge : public HtmlDialogUIDelegate,
+ public TabContentsDelegate {
+ public:
+ // All parameters must be non-NULL/non-nil.
+ HtmlDialogWindowDelegateBridge(HtmlDialogUIDelegate* delegate,
+ NSWindowController* controller,
+ NSWindow* window,
+ Browser* browser);
+
+ virtual ~HtmlDialogWindowDelegateBridge();
+
+ // Called when the window is directly closed, e.g. from the close
+ // button or from an accelerator.
+ void WindowControllerClosed();
+
+ // HtmlDialogUIDelegate declarations.
+ virtual bool IsDialogModal() const;
+ virtual std::wstring GetDialogTitle() const;
+ virtual GURL GetDialogContentURL() const;
+ virtual void GetDOMMessageHandlers(
+ std::vector<DOMMessageHandler*>* handlers) const;
+ virtual void GetDialogSize(gfx::Size* size) const;
+ virtual std::string GetDialogArgs() const;
+ virtual void OnDialogClosed(const std::string& json_retval);
+
+ // TabContentsDelegate declarations.
+ virtual void OpenURLFromTab(TabContents* source,
+ const GURL& url, const GURL& referrer,
+ WindowOpenDisposition disposition,
+ PageTransition::Type transition);
+ virtual void NavigationStateChanged(const TabContents* source,
+ unsigned changed_flags);
+ virtual void AddNewContents(TabContents* source,
+ TabContents* new_contents,
+ WindowOpenDisposition disposition,
+ const gfx::Rect& initial_pos,
+ bool user_gesture);
+ virtual void ActivateContents(TabContents* contents);
+ virtual void LoadingStateChanged(TabContents* source);
+ virtual void CloseContents(TabContents* source);
+ virtual void MoveContents(TabContents* source, const gfx::Rect& pos);
+ virtual bool IsPopup(TabContents* source);
+ virtual void ToolbarSizeChanged(TabContents* source, bool is_animating);
+ virtual void URLStarredChanged(TabContents* source, bool starred);
+ virtual void UpdateTargetURL(TabContents* source, const GURL& url);
+
+ private:
+ HtmlDialogUIDelegate* delegate_; // weak
+ NSWindowController* controller_; // weak
+ NSWindow* window_; // weak
+ Browser* browser_; // weak
+
+ // Calls delegate_'s OnDialogClosed() exactly once, nulling it out
+ // afterwards so that no other HtmlDialogUIDelegate calls are sent
+ // to it. Returns whether or not the OnDialogClosed() was actually
+ // called on the delegate.
+ bool DelegateOnDialogClosed(const std::string& json_retval);
+
+ DISALLOW_COPY_AND_ASSIGN(HtmlDialogWindowDelegateBridge);
+};
+
+// This controller manages a dialog box with properties and HTML content taken
+// from a HTMLDialogUIDelegate object.
+@interface HtmlDialogWindowController : NSWindowController {
+ @private
+ Browser* browser_; // weak
+ // Order here is important, as tab_contents_ may send messages to
+ // delegate_ when it gets destroyed.
+ scoped_ptr<HtmlDialogWindowDelegateBridge> delegate_;
+ scoped_ptr<TabContents> tab_contents_;
+}
+
+// Creates and shows an HtmlDialogWindowController with the given
+// delegate, parent window, and browser, none of which may be NULL.
+// The window is automatically destroyed when it is closed.
++ (void)showHtmlDialog:(HtmlDialogUIDelegate*)delegate
+ parentWindow:(gfx::NativeWindow)parent_window
+ browser:(Browser*)browser;
+
+@end
+
+@interface HtmlDialogWindowController (TestingAPI)
+
+// This is the designated initializer. However, this is exposed only
+// for testing; use showHtmlDialog instead.
+- (id)initWithDelegate:(HtmlDialogUIDelegate*)delegate
+ parentWindow:(gfx::NativeWindow)parent_window
+ browser:(Browser*)browser;
+
+// Loads the HTML content from the delegate; this is not a lightweight
+// process which is why it is not part of the constructor. Must be
+// called before showWindow.
+- (void)loadDialogContents;
+
+@end
+
+#endif // CHROME_BROWSER_COCOA_HTML_DIALOG_WINDOW_CONTROLLER_H_
+
diff --git a/chrome/browser/cocoa/html_dialog_window_controller.mm b/chrome/browser/cocoa/html_dialog_window_controller.mm
new file mode 100644
index 0000000..0e01e499
--- /dev/null
+++ b/chrome/browser/cocoa/html_dialog_window_controller.mm
@@ -0,0 +1,267 @@
+// 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 "chrome/browser/cocoa/html_dialog_window_controller.h"
+
+#include "base/gfx/size.h"
+#include "base/logging.h"
+#include "base/scoped_nsobject.h"
+#include "base/sys_string_conversions.h"
+#include "chrome/browser/browser.h"
+#import "chrome/browser/cocoa/browser_command_executor.h"
+#import "chrome/browser/cocoa/chrome_event_processing_window.h"
+#include "chrome/browser/dom_ui/html_dialog_ui.h"
+#include "chrome/browser/tab_contents/tab_contents.h"
+#include "googleurl/src/gurl.h"
+
+HtmlDialogWindowDelegateBridge::HtmlDialogWindowDelegateBridge(
+ HtmlDialogUIDelegate* delegate, NSWindowController* controller,
+ NSWindow* window, Browser* browser)
+ : delegate_(delegate), controller_(controller), window_(window),
+ browser_(browser) {
+ DCHECK(delegate_);
+ DCHECK(controller_);
+ DCHECK(window_);
+ DCHECK(browser_);
+}
+
+HtmlDialogWindowDelegateBridge::~HtmlDialogWindowDelegateBridge() {}
+
+void HtmlDialogWindowDelegateBridge::WindowControllerClosed() {
+ DelegateOnDialogClosed("");
+}
+
+bool HtmlDialogWindowDelegateBridge::DelegateOnDialogClosed(
+ const std::string& json_retval) {
+ if (delegate_) {
+ HtmlDialogUIDelegate* real_delegate = delegate_;
+ delegate_ = NULL;
+ real_delegate->OnDialogClosed(json_retval);
+ return true;
+ }
+ return false;
+}
+
+// HtmlDialogUIDelegate definitions.
+
+// All of these functions check for NULL first since delegate_ is set
+// to NULL when the window is closed.
+
+bool HtmlDialogWindowDelegateBridge::IsDialogModal() const {
+ // TODO(akalin): Support modal dialog boxes.
+ if (delegate_ && delegate_->IsDialogModal()) {
+ LOG(WARNING) << "Modal HTML dialogs are not supported yet";
+ }
+ return false;
+}
+
+std::wstring HtmlDialogWindowDelegateBridge::GetDialogTitle() const {
+ return delegate_ ? delegate_->GetDialogTitle() : L"";
+}
+
+GURL HtmlDialogWindowDelegateBridge::GetDialogContentURL() const {
+ return delegate_ ? delegate_->GetDialogContentURL() : GURL();
+}
+
+void HtmlDialogWindowDelegateBridge::GetDOMMessageHandlers(
+ std::vector<DOMMessageHandler*>* handlers) const {
+ if (delegate_) {
+ delegate_->GetDOMMessageHandlers(handlers);
+ } else {
+ // TODO(akalin): Add this clause in the windows version. Also
+ // make sure that everything expects handlers to be non-NULL and
+ // document it.
+ handlers->clear();
+ }
+}
+
+void HtmlDialogWindowDelegateBridge::GetDialogSize(gfx::Size* size) const {
+ if (delegate_) {
+ delegate_->GetDialogSize(size);
+ } else {
+ *size = gfx::Size();
+ }
+}
+
+std::string HtmlDialogWindowDelegateBridge::GetDialogArgs() const {
+ return delegate_ ? delegate_->GetDialogArgs() : "";
+}
+
+void HtmlDialogWindowDelegateBridge::OnDialogClosed(
+ const std::string& json_retval) {
+ // [controller_ close] should be called at most once, too.
+ if (DelegateOnDialogClosed(json_retval)) {
+ [controller_ close];
+ }
+}
+
+// TabContentsDelegate definitions. Most of this logic is copied from
+// chrome/browser/views/html_dialog_view.cc . All functions with empty
+// bodies are notifications we don't care about.
+
+void HtmlDialogWindowDelegateBridge::OpenURLFromTab(
+ TabContents* source, const GURL& url, const GURL& referrer,
+ WindowOpenDisposition disposition, PageTransition::Type transition) {
+ // Force all links to open in a new window.
+ static_cast<TabContentsDelegate*>(browser_)->
+ OpenURLFromTab(source, url, referrer, NEW_WINDOW, transition);
+}
+
+void HtmlDialogWindowDelegateBridge::NavigationStateChanged(
+ const TabContents* source, unsigned changed_flags) {
+}
+
+void HtmlDialogWindowDelegateBridge::AddNewContents(
+ TabContents* source, TabContents* new_contents,
+ WindowOpenDisposition disposition, const gfx::Rect& initial_pos,
+ bool user_gesture) {
+ // Force this to open in a new window, too.
+ static_cast<TabContentsDelegate*>(browser_)->
+ AddNewContents(source, new_contents, NEW_WINDOW,
+ initial_pos, user_gesture);
+}
+
+void HtmlDialogWindowDelegateBridge::ActivateContents(TabContents* contents) {}
+
+void HtmlDialogWindowDelegateBridge::LoadingStateChanged(TabContents* source) {}
+
+void HtmlDialogWindowDelegateBridge::CloseContents(TabContents* source) {}
+
+void HtmlDialogWindowDelegateBridge::MoveContents(TabContents* source,
+ const gfx::Rect& pos) {
+ // TODO(akalin): Actually set the window bounds.
+}
+
+bool HtmlDialogWindowDelegateBridge::IsPopup(TabContents* source) {
+ // This needs to return true so that we are allowed to be resized by
+ // our contents.
+ return true;
+}
+
+void HtmlDialogWindowDelegateBridge::ToolbarSizeChanged(
+ TabContents* source, bool is_animating) {
+ // TODO(akalin): Figure out what to do here.
+}
+
+void HtmlDialogWindowDelegateBridge::URLStarredChanged(
+ TabContents* source, bool starred) {
+ // We don't have a visible star to click in the window.
+ NOTREACHED();
+}
+
+void HtmlDialogWindowDelegateBridge::UpdateTargetURL(
+ TabContents* source, const GURL& url) {}
+
+// ChromeEventProcessingWindow expect its controller to implement this
+// protocol.
+
+@interface HtmlDialogWindowController (InternalAPI) <BrowserCommandExecutor>
+
+- (void)executeCommand:(int)command;
+
+@end
+
+@implementation HtmlDialogWindowController (InternalAPI)
+
+- (void)executeCommand:(int)command {
+ if (browser_->command_updater()->IsCommandEnabled(command)) {
+ browser_->ExecuteCommand(command);
+ }
+}
+
+@end
+
+@implementation HtmlDialogWindowController
+
++ (void)showHtmlDialog:(HtmlDialogUIDelegate*)delegate
+ parentWindow:(gfx::NativeWindow)parent_window
+ browser:(Browser*)browser {
+ HtmlDialogWindowController* html_dialog_window_controller =
+ [[HtmlDialogWindowController alloc] initWithDelegate:delegate
+ parentWindow:parent_window
+ browser:browser];
+ [html_dialog_window_controller loadDialogContents];
+ [html_dialog_window_controller showWindow:nil];
+}
+
+- (id)initWithDelegate:(HtmlDialogUIDelegate*)delegate
+ parentWindow:(gfx::NativeWindow)parent_window
+ browser:(Browser*)browser {
+ DCHECK(delegate);
+ DCHECK(parent_window);
+ DCHECK(browser);
+
+ // Put the dialog box in the center of the window.
+ //
+ // TODO(akalin): Surely there must be a cleaner way to do this.
+ //
+ // TODO(akalin): Perhaps use [window center] instead, which centers
+ // the dialog to the screen, although it doesn't match the Windows
+ // behavior.
+ NSRect parent_window_frame = [parent_window frame];
+ NSPoint parent_window_origin = parent_window_frame.origin;
+ NSSize parent_window_size = parent_window_frame.size;
+ gfx::Size dialog_size;
+ delegate->GetDialogSize(&dialog_size);
+ NSRect dialog_rect =
+ NSMakeRect(parent_window_origin.x +
+ (parent_window_size.width - dialog_size.width()) / 2,
+ parent_window_origin.y +
+ (parent_window_size.height - dialog_size.height()) / 2,
+ dialog_size.width(),
+ dialog_size.height());
+ // TODO(akalin): Make the window resizable (but with the minimum size being
+ // dialog_size and always on top (but not modal) to match the Windows
+ // behavior.
+ NSUInteger style = NSTitledWindowMask | NSClosableWindowMask;
+ scoped_nsobject<ChromeEventProcessingWindow> window(
+ [[ChromeEventProcessingWindow alloc]
+ initWithContentRect:dialog_rect
+ styleMask:style
+ backing:NSBackingStoreBuffered
+ defer:YES]);
+ if (!window.get()) {
+ return nil;
+ }
+ self = [super initWithWindow:window];
+ if (!self) {
+ return nil;
+ }
+ [window setWindowController:self];
+ [window setDelegate:self];
+ [window setTitle:base::SysWideToNSString(delegate->GetDialogTitle())];
+ browser_ = browser;
+ delegate_.reset(
+ new HtmlDialogWindowDelegateBridge(delegate, self, window, browser));
+ return self;
+}
+
+- (void)loadDialogContents {
+ // TODO(akalin): Figure out if this can be an incognito profile.
+ Profile* profile = browser_->profile();
+ tab_contents_.reset(new TabContents(profile, NULL, MSG_ROUTING_NONE, NULL));
+ [[self window] setContentView:tab_contents_->GetNativeView()];
+ tab_contents_->set_delegate(delegate_.get());
+
+ // This must be done before loading the page; see the comments in
+ // HtmlDialogUI.
+ HtmlDialogUI::GetPropertyAccessor().SetProperty(tab_contents_->property_bag(),
+ delegate_.get());
+
+ tab_contents_->controller().LoadURL(delegate_->GetDialogContentURL(),
+ GURL(), PageTransition::START_PAGE);
+
+ // TODO(akalin): add accelerator for ESC to close the dialog box.
+ //
+ // TODO(akalin): Figure out why implementing (void)cancel:(id)sender
+ // to do the above doesn't work.
+}
+
+- (void)windowWillClose:(NSNotification*)notification {
+ delegate_->WindowControllerClosed();
+ [self autorelease];
+}
+
+@end
+
diff --git a/chrome/browser/cocoa/html_dialog_window_controller_unittest.mm b/chrome/browser/cocoa/html_dialog_window_controller_unittest.mm
new file mode 100644
index 0000000..de6ec22
--- /dev/null
+++ b/chrome/browser/cocoa/html_dialog_window_controller_unittest.mm
@@ -0,0 +1,93 @@
+// 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 "chrome/browser/cocoa/html_dialog_window_controller.h"
+
+#include <string>
+#include <vector>
+
+#import <Cocoa/Cocoa.h>
+
+#include "base/gfx/size.h"
+#import "base/scoped_nsautorelease_pool.h"
+#include "base/sys_string_conversions.h"
+#include "chrome/browser/cocoa/cocoa_test_helper.h"
+#include "chrome/browser/dom_ui/dom_ui.h"
+#include "chrome/browser/dom_ui/html_dialog_ui.h"
+#include "chrome/test/browser_with_test_window_test.h"
+#include "googleurl/src/gurl.h"
+#include "testing/gmock/include/gmock/gmock.h"
+#include "testing/gtest/include/gtest/gtest.h"
+
+namespace {
+
+class MockDelegate : public HtmlDialogUIDelegate {
+public:
+ MOCK_CONST_METHOD0(IsDialogModal, bool());
+ MOCK_CONST_METHOD0(GetDialogTitle, std::wstring());
+ MOCK_CONST_METHOD0(GetDialogContentURL, GURL());
+ MOCK_CONST_METHOD1(GetDOMMessageHandlers,
+ void(std::vector<DOMMessageHandler*>*));
+ MOCK_CONST_METHOD1(GetDialogSize, void(gfx::Size*));
+ MOCK_CONST_METHOD0(GetDialogArgs, std::string());
+ MOCK_METHOD1(OnDialogClosed, void(const std::string& json_retval));
+};
+
+class HtmlDialogWindowControllerTest : public BrowserWithTestWindowTest {
+ public:
+ virtual void SetUp() {
+ BrowserWithTestWindowTest::SetUp();
+ title_ = L"Mock Title";
+ size_ = gfx::Size(50, 100);
+ gurl_ = GURL("");
+ }
+
+ protected:
+ std::wstring title_;
+ gfx::Size size_;
+ GURL gurl_;
+
+ // Order here is important.
+ CocoaTestHelper cocoa_helper_;
+ MockDelegate delegate_;
+};
+
+using ::testing::_;
+using ::testing::Return;
+using ::testing::SetArgumentPointee;
+
+// TODO(akalin): We can't test much more than the below without a real browser.
+// In particular, GetDOMMessageHandlers() and GetDialogArgs() are never called.
+// This should be fixed.
+
+TEST_F(HtmlDialogWindowControllerTest, showDialog) {
+ // We want to make sure html_dialog_window_controller below gets
+ // destroyed before cocoa_helper_ and delegate_, so we specify our
+ // own autorelease pool.
+ //
+ // TODO(dmaclach): Remove this once
+ // http://code.google.com/p/chromium/issues/detail?id=26133 is fixed.
+ base::ScopedNSAutoreleasePool release_pool;
+
+ EXPECT_CALL(delegate_, GetDialogTitle())
+ .WillOnce(Return(title_));
+ EXPECT_CALL(delegate_, GetDialogSize(_))
+ .WillOnce(SetArgumentPointee<0>(size_));
+ EXPECT_CALL(delegate_, GetDialogContentURL())
+ .WillOnce(Return(gurl_));
+ EXPECT_CALL(delegate_, OnDialogClosed(_))
+ .Times(1);
+
+ NSWindow* parent_window = cocoa_helper_.window();
+ HtmlDialogWindowController* html_dialog_window_controller =
+ [[HtmlDialogWindowController alloc] initWithDelegate:&delegate_
+ parentWindow:parent_window
+ browser:browser()];
+
+ [html_dialog_window_controller loadDialogContents];
+ [html_dialog_window_controller showWindow:nil];
+ [html_dialog_window_controller close];
+}
+
+} // namespace