1// Copyright 2013 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/browser/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/browser/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)alertDidEndWithResult:(NSModalResponse)returnCode 30 dialog:(content::ShellJavaScriptDialog*)dialog; 31- (void)cancel; 32 33@end 34 35@implementation ShellJavaScriptDialogHelper 36 37- (id)initHelperWithManager:(content::ShellJavaScriptDialogManager*)manager 38 andCallback:(content::JavaScriptDialogManager::DialogClosedCallback)callback { 39 if (self = [super init]) { 40 _manager = manager; 41 _callback = std::move(callback); 42 } 43 44 return self; 45} 46 47- (NSAlert*)alert { 48 _alert.reset([[NSAlert alloc] init]); 49 return _alert; 50} 51 52- (NSTextField*)textField { 53 _textField = [[NSTextField alloc] initWithFrame:NSMakeRect(0, 0, 300, 22)]; 54 [[_textField cell] setLineBreakMode:NSLineBreakByTruncatingTail]; 55 [_alert setAccessoryView:_textField]; 56 [[_alert window] setInitialFirstResponder:_textField]; 57 [_textField release]; 58 59 return _textField; 60} 61 62- (void)alertDidEndWithResult:(NSModalResponse)returnCode 63 dialog:(content::ShellJavaScriptDialog*)dialog { 64 if (returnCode == NSModalResponseStop) 65 return; 66 67 bool success = returnCode == NSAlertFirstButtonReturn; 68 base::string16 input; 69 if (_textField) 70 input = base::SysNSStringToUTF16([_textField stringValue]); 71 72 std::move(_callback).Run(success, input); 73 _manager->DialogClosed(dialog); 74} 75 76- (void)cancel { 77 [NSApp endSheet:[_alert window]]; 78 _alert.reset(); 79 if (_callback) 80 std::move(_callback).Run(false, base::string16()); 81} 82 83@end 84 85namespace content { 86 87ShellJavaScriptDialog::ShellJavaScriptDialog( 88 ShellJavaScriptDialogManager* manager, 89 gfx::NativeWindow parent_window, 90 JavaScriptDialogType dialog_type, 91 const base::string16& message_text, 92 const base::string16& default_prompt_text, 93 JavaScriptDialogManager::DialogClosedCallback callback) { 94 bool text_field = dialog_type == JAVASCRIPT_DIALOG_TYPE_PROMPT; 95 bool one_button = dialog_type == JAVASCRIPT_DIALOG_TYPE_ALERT; 96 97 helper_ = [[ShellJavaScriptDialogHelper alloc] 98 initHelperWithManager:manager 99 andCallback:std::move(callback)]; 100 101 // Show the modal dialog. 102 NSAlert* alert = [helper_ alert]; 103 NSTextField* field = nil; 104 if (text_field) { 105 field = [helper_ textField]; 106 [field setStringValue:base::SysUTF16ToNSString(default_prompt_text)]; 107 } 108 [alert setDelegate:helper_]; 109 [alert setInformativeText:base::SysUTF16ToNSString(message_text)]; 110 [alert setMessageText:@"Javascript alert"]; 111 [alert addButtonWithTitle:@"OK"]; 112 if (!one_button) { 113 NSButton* other = [alert addButtonWithTitle:@"Cancel"]; 114 [other setKeyEquivalent:@"\e"]; 115 } 116 117 [alert beginSheetModalForWindow:nil // nil here makes it app-modal 118 completionHandler:^void(NSModalResponse returnCode) { 119 [helper_ alertDidEndWithResult:returnCode dialog:this]; 120 }]; 121} 122 123ShellJavaScriptDialog::~ShellJavaScriptDialog() { 124 [helper_ release]; 125} 126 127void ShellJavaScriptDialog::Cancel() { 128 [helper_ cancel]; 129} 130 131} // namespace content 132