1 // Copyright (c) 2011 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 #include "chrome/browser/ui/webui/constrained_html_ui.h" 6 7 #import <Cocoa/Cocoa.h> 8 9 #include "base/memory/scoped_nsobject.h" 10 #include "chrome/browser/profiles/profile.h" 11 #include "chrome/browser/ui/cocoa/constrained_window_mac.h" 12 #include "chrome/browser/ui/webui/html_dialog_ui.h" 13 #include "chrome/browser/ui/webui/html_dialog_tab_contents_delegate.h" 14 #include "content/browser/tab_contents/tab_contents.h" 15 #include "ui/gfx/size.h" 16 17 class ConstrainedHtmlDelegateMac : 18 public ConstrainedWindowMacDelegateCustomSheet, 19 public HtmlDialogTabContentsDelegate, 20 public ConstrainedHtmlUIDelegate { 21 22 public: 23 ConstrainedHtmlDelegateMac(Profile* profile, 24 HtmlDialogUIDelegate* delegate); 25 ~ConstrainedHtmlDelegateMac() {} 26 27 // ConstrainedWindowMacDelegateCustomSheet ----------------------------------- 28 virtual void DeleteDelegate() { 29 // From ConstrainedWindowMacDelegate: "you MUST close the sheet belonging to 30 // your delegate in this method." 31 if (is_sheet_open()) 32 [NSApp endSheet:sheet()]; 33 html_delegate_->OnDialogClosed(""); 34 delete this; 35 } 36 37 // ConstrainedHtmlDelegate --------------------------------------------------- 38 virtual HtmlDialogUIDelegate* GetHtmlDialogUIDelegate(); 39 virtual void OnDialogClose(); 40 41 // HtmlDialogTabContentsDelegate --------------------------------------------- 42 void MoveContents(TabContents* source, const gfx::Rect& pos) {} 43 void HandleKeyboardEvent(const NativeWebKeyboardEvent& event) {} 44 45 void set_window(ConstrainedWindow* window) { 46 constrained_window_ = window; 47 } 48 49 private: 50 TabContents tab_contents_; // Holds the HTML to be displayed in the sheet. 51 HtmlDialogUIDelegate* html_delegate_; // weak. 52 53 // The constrained window that owns |this|. Saved here because it needs to be 54 // closed in response to the WebUI OnDialogClose callback. 55 ConstrainedWindow* constrained_window_; 56 57 DISALLOW_COPY_AND_ASSIGN(ConstrainedHtmlDelegateMac); 58 }; 59 60 // The delegate used to forward events from the sheet to the constrained 61 // window delegate. This bridge needs to be passed into the customsheet 62 // to allow the HtmlDialog to know when the sheet closes. 63 @interface ConstrainedHtmlDialogSheetCocoa : NSObject { 64 ConstrainedHtmlDelegateMac* constrainedHtmlDelegate_; // weak 65 } 66 - (id)initWithConstrainedHtmlDelegateMac: 67 (ConstrainedHtmlDelegateMac*)ConstrainedHtmlDelegateMac; 68 - (void)sheetDidEnd:(NSWindow*)sheet 69 returnCode:(int)returnCode 70 contextInfo:(void*)contextInfo; 71 @end 72 73 ConstrainedHtmlDelegateMac::ConstrainedHtmlDelegateMac( 74 Profile* profile, 75 HtmlDialogUIDelegate* delegate) 76 : HtmlDialogTabContentsDelegate(profile), 77 tab_contents_(profile, NULL, MSG_ROUTING_NONE, NULL, NULL), 78 html_delegate_(delegate), 79 constrained_window_(NULL) { 80 tab_contents_.set_delegate(this); 81 82 // Set |this| as a property on the tab contents so that the ConstrainedHtmlUI 83 // can get a reference to |this|. 84 ConstrainedHtmlUI::GetPropertyAccessor().SetProperty( 85 tab_contents_.property_bag(), this); 86 87 tab_contents_.controller().LoadURL(delegate->GetDialogContentURL(), 88 GURL(), PageTransition::START_PAGE); 89 90 // Create NSWindow to hold tab_contents in the constrained sheet: 91 gfx::Size size; 92 delegate->GetDialogSize(&size); 93 NSRect frame = NSMakeRect(0, 0, size.width(), size.height()); 94 95 // |window| is retained by the ConstrainedWindowMacDelegateCustomSheet when 96 // the sheet is initialized. 97 scoped_nsobject<NSWindow> window; 98 window.reset( 99 [[NSWindow alloc] initWithContentRect:frame 100 styleMask:NSTitledWindowMask 101 backing:NSBackingStoreBuffered 102 defer:YES]); 103 104 [window.get() setContentView:tab_contents_.GetNativeView()]; 105 106 // Set the custom sheet to point to the new window. 107 ConstrainedWindowMacDelegateCustomSheet::init( 108 window.get(), 109 [[[ConstrainedHtmlDialogSheetCocoa alloc] 110 initWithConstrainedHtmlDelegateMac:this] autorelease], 111 @selector(sheetDidEnd:returnCode:contextInfo:)); 112 } 113 114 HtmlDialogUIDelegate* ConstrainedHtmlDelegateMac::GetHtmlDialogUIDelegate() { 115 return html_delegate_; 116 } 117 118 void ConstrainedHtmlDelegateMac::OnDialogClose() { 119 DCHECK(constrained_window_); 120 if (constrained_window_) 121 constrained_window_->CloseConstrainedWindow(); 122 } 123 124 // static 125 ConstrainedWindow* ConstrainedHtmlUI::CreateConstrainedHtmlDialog( 126 Profile* profile, 127 HtmlDialogUIDelegate* delegate, 128 TabContents* overshadowed) { 129 // Deleted when ConstrainedHtmlDelegateMac::DeleteDelegate() runs. 130 ConstrainedHtmlDelegateMac* constrained_delegate = 131 new ConstrainedHtmlDelegateMac(profile, delegate); 132 // Deleted when ConstrainedHtmlDelegateMac::OnDialogClose() runs. 133 ConstrainedWindow* constrained_window = 134 overshadowed->CreateConstrainedDialog(constrained_delegate); 135 constrained_delegate->set_window(constrained_window); 136 return constrained_window; 137 } 138 139 @implementation ConstrainedHtmlDialogSheetCocoa 140 141 - (id)initWithConstrainedHtmlDelegateMac: 142 (ConstrainedHtmlDelegateMac*)ConstrainedHtmlDelegateMac { 143 if ((self = [super init])) 144 constrainedHtmlDelegate_ = ConstrainedHtmlDelegateMac; 145 return self; 146 } 147 148 - (void)sheetDidEnd:(NSWindow*)sheet 149 returnCode:(int)returnCode 150 contextInfo:(void *)contextInfo { 151 [sheet orderOut:self]; 152 } 153 154 @end 155