OLD | NEW |
(Empty) | |
| 1 // Copyright (c) 2009 The Chromium Authors. All rights reserved. |
| 2 // Use of this source code is governed by a BSD-style license that can be |
| 3 // found in the LICENSE file. |
| 4 |
| 5 #import "chrome/browser/cocoa/html_dialog_window_controller.h" |
| 6 |
| 7 #include "base/gfx/size.h" |
| 8 #include "base/logging.h" |
| 9 #include "base/scoped_nsobject.h" |
| 10 #include "base/sys_string_conversions.h" |
| 11 #include "chrome/browser/browser.h" |
| 12 #import "chrome/browser/cocoa/browser_command_executor.h" |
| 13 #import "chrome/browser/cocoa/chrome_event_processing_window.h" |
| 14 #include "chrome/browser/dom_ui/html_dialog_ui.h" |
| 15 #include "chrome/browser/tab_contents/tab_contents.h" |
| 16 #include "googleurl/src/gurl.h" |
| 17 |
| 18 HtmlDialogWindowDelegateBridge::HtmlDialogWindowDelegateBridge( |
| 19 HtmlDialogUIDelegate* delegate, NSWindowController* controller, |
| 20 NSWindow* window, Browser* browser) |
| 21 : delegate_(delegate), controller_(controller), window_(window), |
| 22 browser_(browser) { |
| 23 DCHECK(delegate_); |
| 24 DCHECK(controller_); |
| 25 DCHECK(window_); |
| 26 DCHECK(browser_); |
| 27 } |
| 28 |
| 29 HtmlDialogWindowDelegateBridge::~HtmlDialogWindowDelegateBridge() {} |
| 30 |
| 31 void HtmlDialogWindowDelegateBridge::WindowControllerClosed() { |
| 32 DelegateOnDialogClosed(""); |
| 33 } |
| 34 |
| 35 bool HtmlDialogWindowDelegateBridge::DelegateOnDialogClosed( |
| 36 const std::string& json_retval) { |
| 37 if (delegate_) { |
| 38 HtmlDialogUIDelegate* real_delegate = delegate_; |
| 39 delegate_ = NULL; |
| 40 real_delegate->OnDialogClosed(json_retval); |
| 41 return true; |
| 42 } |
| 43 return false; |
| 44 } |
| 45 |
| 46 // HtmlDialogUIDelegate definitions. |
| 47 |
| 48 // All of these functions check for NULL first since delegate_ is set |
| 49 // to NULL when the window is closed. |
| 50 |
| 51 bool HtmlDialogWindowDelegateBridge::IsDialogModal() const { |
| 52 // TODO(akalin): Support modal dialog boxes. |
| 53 if (delegate_ && delegate_->IsDialogModal()) { |
| 54 LOG(WARNING) << "Modal HTML dialogs are not supported yet"; |
| 55 } |
| 56 return false; |
| 57 } |
| 58 |
| 59 std::wstring HtmlDialogWindowDelegateBridge::GetDialogTitle() const { |
| 60 return delegate_ ? delegate_->GetDialogTitle() : L""; |
| 61 } |
| 62 |
| 63 GURL HtmlDialogWindowDelegateBridge::GetDialogContentURL() const { |
| 64 return delegate_ ? delegate_->GetDialogContentURL() : GURL(); |
| 65 } |
| 66 |
| 67 void HtmlDialogWindowDelegateBridge::GetDOMMessageHandlers( |
| 68 std::vector<DOMMessageHandler*>* handlers) const { |
| 69 if (delegate_) { |
| 70 delegate_->GetDOMMessageHandlers(handlers); |
| 71 } else { |
| 72 // TODO(akalin): Add this clause in the windows version. Also |
| 73 // make sure that everything expects handlers to be non-NULL and |
| 74 // document it. |
| 75 handlers->clear(); |
| 76 } |
| 77 } |
| 78 |
| 79 void HtmlDialogWindowDelegateBridge::GetDialogSize(gfx::Size* size) const { |
| 80 if (delegate_) { |
| 81 delegate_->GetDialogSize(size); |
| 82 } else { |
| 83 *size = gfx::Size(); |
| 84 } |
| 85 } |
| 86 |
| 87 std::string HtmlDialogWindowDelegateBridge::GetDialogArgs() const { |
| 88 return delegate_ ? delegate_->GetDialogArgs() : ""; |
| 89 } |
| 90 |
| 91 void HtmlDialogWindowDelegateBridge::OnDialogClosed( |
| 92 const std::string& json_retval) { |
| 93 // [controller_ close] should be called at most once, too. |
| 94 if (DelegateOnDialogClosed(json_retval)) { |
| 95 [controller_ close]; |
| 96 } |
| 97 } |
| 98 |
| 99 // TabContentsDelegate definitions. Most of this logic is copied from |
| 100 // chrome/browser/views/html_dialog_view.cc . All functions with empty |
| 101 // bodies are notifications we don't care about. |
| 102 |
| 103 void HtmlDialogWindowDelegateBridge::OpenURLFromTab( |
| 104 TabContents* source, const GURL& url, const GURL& referrer, |
| 105 WindowOpenDisposition disposition, PageTransition::Type transition) { |
| 106 // Force all links to open in a new window. |
| 107 static_cast<TabContentsDelegate*>(browser_)-> |
| 108 OpenURLFromTab(source, url, referrer, NEW_WINDOW, transition); |
| 109 } |
| 110 |
| 111 void HtmlDialogWindowDelegateBridge::NavigationStateChanged( |
| 112 const TabContents* source, unsigned changed_flags) { |
| 113 } |
| 114 |
| 115 void HtmlDialogWindowDelegateBridge::AddNewContents( |
| 116 TabContents* source, TabContents* new_contents, |
| 117 WindowOpenDisposition disposition, const gfx::Rect& initial_pos, |
| 118 bool user_gesture) { |
| 119 // Force this to open in a new window, too. |
| 120 static_cast<TabContentsDelegate*>(browser_)-> |
| 121 AddNewContents(source, new_contents, NEW_WINDOW, |
| 122 initial_pos, user_gesture); |
| 123 } |
| 124 |
| 125 void HtmlDialogWindowDelegateBridge::ActivateContents(TabContents* contents) {} |
| 126 |
| 127 void HtmlDialogWindowDelegateBridge::LoadingStateChanged(TabContents* source) {} |
| 128 |
| 129 void HtmlDialogWindowDelegateBridge::CloseContents(TabContents* source) {} |
| 130 |
| 131 void HtmlDialogWindowDelegateBridge::MoveContents(TabContents* source, |
| 132 const gfx::Rect& pos) { |
| 133 // TODO(akalin): Actually set the window bounds. |
| 134 } |
| 135 |
| 136 bool HtmlDialogWindowDelegateBridge::IsPopup(TabContents* source) { |
| 137 // This needs to return true so that we are allowed to be resized by |
| 138 // our contents. |
| 139 return true; |
| 140 } |
| 141 |
| 142 void HtmlDialogWindowDelegateBridge::ToolbarSizeChanged( |
| 143 TabContents* source, bool is_animating) { |
| 144 // TODO(akalin): Figure out what to do here. |
| 145 } |
| 146 |
| 147 void HtmlDialogWindowDelegateBridge::URLStarredChanged( |
| 148 TabContents* source, bool starred) { |
| 149 // We don't have a visible star to click in the window. |
| 150 NOTREACHED(); |
| 151 } |
| 152 |
| 153 void HtmlDialogWindowDelegateBridge::UpdateTargetURL( |
| 154 TabContents* source, const GURL& url) {} |
| 155 |
| 156 // ChromeEventProcessingWindow expect its controller to implement this |
| 157 // protocol. |
| 158 |
| 159 @interface HtmlDialogWindowController (InternalAPI) <BrowserCommandExecutor> |
| 160 |
| 161 - (void)executeCommand:(int)command; |
| 162 |
| 163 @end |
| 164 |
| 165 @implementation HtmlDialogWindowController (InternalAPI) |
| 166 |
| 167 - (void)executeCommand:(int)command { |
| 168 if (browser_->command_updater()->IsCommandEnabled(command)) { |
| 169 browser_->ExecuteCommand(command); |
| 170 } |
| 171 } |
| 172 |
| 173 @end |
| 174 |
| 175 @implementation HtmlDialogWindowController |
| 176 |
| 177 + (void)showHtmlDialog:(HtmlDialogUIDelegate*)delegate |
| 178 parentWindow:(gfx::NativeWindow)parent_window |
| 179 browser:(Browser*)browser { |
| 180 HtmlDialogWindowController* html_dialog_window_controller = |
| 181 [[HtmlDialogWindowController alloc] initWithDelegate:delegate |
| 182 parentWindow:parent_window |
| 183 browser:browser]; |
| 184 [html_dialog_window_controller loadDialogContents]; |
| 185 [html_dialog_window_controller showWindow:nil]; |
| 186 } |
| 187 |
| 188 - (id)initWithDelegate:(HtmlDialogUIDelegate*)delegate |
| 189 parentWindow:(gfx::NativeWindow)parent_window |
| 190 browser:(Browser*)browser { |
| 191 DCHECK(delegate); |
| 192 DCHECK(parent_window); |
| 193 DCHECK(browser); |
| 194 |
| 195 // Put the dialog box in the center of the window. |
| 196 // |
| 197 // TODO(akalin): Surely there must be a cleaner way to do this. |
| 198 // |
| 199 // TODO(akalin): Perhaps use [window center] instead, which centers |
| 200 // the dialog to the screen, although it doesn't match the Windows |
| 201 // behavior. |
| 202 NSRect parent_window_frame = [parent_window frame]; |
| 203 NSPoint parent_window_origin = parent_window_frame.origin; |
| 204 NSSize parent_window_size = parent_window_frame.size; |
| 205 gfx::Size dialog_size; |
| 206 delegate->GetDialogSize(&dialog_size); |
| 207 NSRect dialog_rect = |
| 208 NSMakeRect(parent_window_origin.x + |
| 209 (parent_window_size.width - dialog_size.width()) / 2, |
| 210 parent_window_origin.y + |
| 211 (parent_window_size.height - dialog_size.height()) / 2, |
| 212 dialog_size.width(), |
| 213 dialog_size.height()); |
| 214 // TODO(akalin): Make the window resizable (but with the minimum size being |
| 215 // dialog_size and always on top (but not modal) to match the Windows |
| 216 // behavior. |
| 217 NSUInteger style = NSTitledWindowMask | NSClosableWindowMask; |
| 218 scoped_nsobject<ChromeEventProcessingWindow> window( |
| 219 [[ChromeEventProcessingWindow alloc] |
| 220 initWithContentRect:dialog_rect |
| 221 styleMask:style |
| 222 backing:NSBackingStoreBuffered |
| 223 defer:YES]); |
| 224 if (!window.get()) { |
| 225 return nil; |
| 226 } |
| 227 self = [super initWithWindow:window]; |
| 228 if (!self) { |
| 229 return nil; |
| 230 } |
| 231 [window setWindowController:self]; |
| 232 [window setDelegate:self]; |
| 233 [window setTitle:base::SysWideToNSString(delegate->GetDialogTitle())]; |
| 234 browser_ = browser; |
| 235 delegate_.reset( |
| 236 new HtmlDialogWindowDelegateBridge(delegate, self, window, browser)); |
| 237 return self; |
| 238 } |
| 239 |
| 240 - (void)loadDialogContents { |
| 241 // TODO(akalin): Figure out if this can be an incognito profile. |
| 242 Profile* profile = browser_->profile(); |
| 243 tab_contents_.reset(new TabContents(profile, NULL, MSG_ROUTING_NONE, NULL)); |
| 244 [[self window] setContentView:tab_contents_->GetNativeView()]; |
| 245 tab_contents_->set_delegate(delegate_.get()); |
| 246 |
| 247 // This must be done before loading the page; see the comments in |
| 248 // HtmlDialogUI. |
| 249 HtmlDialogUI::GetPropertyAccessor().SetProperty(tab_contents_->property_bag(), |
| 250 delegate_.get()); |
| 251 |
| 252 tab_contents_->controller().LoadURL(delegate_->GetDialogContentURL(), |
| 253 GURL(), PageTransition::START_PAGE); |
| 254 |
| 255 // TODO(akalin): add accelerator for ESC to close the dialog box. |
| 256 // |
| 257 // TODO(akalin): Figure out why implementing (void)cancel:(id)sender |
| 258 // to do the above doesn't work. |
| 259 } |
| 260 |
| 261 - (void)windowWillClose:(NSNotification*)notification { |
| 262 delegate_->WindowControllerClosed(); |
| 263 [self autorelease]; |
| 264 } |
| 265 |
| 266 @end |
| 267 |
OLD | NEW |