1 // Copyright (c) 2012 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 "content/shell/shell_javascript_dialog.h" 6 7 #import <Cocoa/Cocoa.h> 8 9 #import "base/mac/scoped_nsobject.h" 10 #include "base/strings/sys_string_conversions.h" 11 #include "content/shell/shell_javascript_dialog_manager.h" 12 13 // Helper object that receives the notification that the dialog/sheet is 14 // going away. Is responsible for cleaning itself up. 15 @interface ShellJavaScriptDialogHelper : NSObject<NSAlertDelegate> { 16 @private 17 base::scoped_nsobject<NSAlert> alert_; 18 NSTextField* textField_; // WEAK; owned by alert_ 19 20 // Copies of the fields in ShellJavaScriptDialog because they're private. 21 content::ShellJavaScriptDialogManager* manager_; 22 content::JavaScriptDialogManager::DialogClosedCallback callback_; 23 } 24 25 - (id)initHelperWithManager:(content::ShellJavaScriptDialogManager*)manager 26 andCallback:(content::JavaScriptDialogManager::DialogClosedCallback)callback; 27 - (NSAlert*)alert; 28 - (NSTextField*)textField; 29 - (void)alertDidEnd:(NSAlert*)alert 30 returnCode:(int)returnCode 31 contextInfo:(void*)contextInfo; 32 - (void)cancel; 33 34 @end 35 36 @implementation ShellJavaScriptDialogHelper 37 38 - (id)initHelperWithManager:(content::ShellJavaScriptDialogManager*)manager 39 andCallback:(content::JavaScriptDialogManager::DialogClosedCallback)callback { 40 if (self = [super init]) { 41 manager_ = manager; 42 callback_ = callback; 43 } 44 45 return self; 46 } 47 48 - (NSAlert*)alert { 49 alert_.reset([[NSAlert alloc] init]); 50 return alert_; 51 } 52 53 - (NSTextField*)textField { 54 textField_ = [[NSTextField alloc] initWithFrame:NSMakeRect(0, 0, 300, 22)]; 55 [[textField_ cell] setLineBreakMode:NSLineBreakByTruncatingTail]; 56 [alert_ setAccessoryView:textField_]; 57 [textField_ release]; 58 59 return textField_; 60 } 61 62 - (void)alertDidEnd:(NSAlert*)alert 63 returnCode:(int)returnCode 64 contextInfo:(void*)contextInfo { 65 if (returnCode == NSRunStoppedResponse) 66 return; 67 68 bool success = returnCode == NSAlertFirstButtonReturn; 69 string16 input; 70 if (textField_) 71 input = base::SysNSStringToUTF16([textField_ stringValue]); 72 73 content::ShellJavaScriptDialog* native_dialog = 74 reinterpret_cast<content::ShellJavaScriptDialog*>(contextInfo); 75 callback_.Run(success, input); 76 manager_->DialogClosed(native_dialog); 77 } 78 79 - (void)cancel { 80 [NSApp endSheet:[alert_ window]]; 81 alert_.reset(); 82 } 83 84 @end 85 86 namespace content { 87 88 ShellJavaScriptDialog::ShellJavaScriptDialog( 89 ShellJavaScriptDialogManager* manager, 90 gfx::NativeWindow parent_window, 91 JavaScriptMessageType message_type, 92 const string16& message_text, 93 const string16& default_prompt_text, 94 const JavaScriptDialogManager::DialogClosedCallback& callback) 95 : manager_(manager), 96 callback_(callback) { 97 bool text_field = message_type == JAVASCRIPT_MESSAGE_TYPE_PROMPT; 98 bool one_button = message_type == JAVASCRIPT_MESSAGE_TYPE_ALERT; 99 100 helper_ = 101 [[ShellJavaScriptDialogHelper alloc] initHelperWithManager:manager 102 andCallback:callback]; 103 104 // Show the modal dialog. 105 NSAlert* alert = [helper_ alert]; 106 NSTextField* field = nil; 107 if (text_field) { 108 field = [helper_ textField]; 109 [field setStringValue:base::SysUTF16ToNSString(default_prompt_text)]; 110 } 111 [alert setDelegate:helper_]; 112 [alert setInformativeText:base::SysUTF16ToNSString(message_text)]; 113 [alert setMessageText:@"Javascript alert"]; 114 [alert addButtonWithTitle:@"OK"]; 115 if (!one_button) { 116 NSButton* other = [alert addButtonWithTitle:@"Cancel"]; 117 [other setKeyEquivalent:@"\e"]; 118 } 119 120 [alert 121 beginSheetModalForWindow:nil // nil here makes it app-modal 122 modalDelegate:helper_ 123 didEndSelector:@selector(alertDidEnd:returnCode:contextInfo:) 124 contextInfo:this]; 125 126 if ([alert accessoryView]) 127 [[alert window] makeFirstResponder:[alert accessoryView]]; 128 } 129 130 ShellJavaScriptDialog::~ShellJavaScriptDialog() { 131 [helper_ release]; 132 } 133 134 void ShellJavaScriptDialog::Cancel() { 135 [helper_ cancel]; 136 } 137 138 } // namespace content 139