Home | History | Annotate | Download | only in browser
      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)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   base::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 base::string16& message_text,
     93     const base::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