| Index: chrome/browser/cocoa/html_dialog_window_controller.mm
|
| 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 0000000000000000000000000000000000000000..0e01e49918f28b9bbc04cc9a979938030963e9ba
|
| --- /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
|
| +
|
|
|