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_login_dialog.h" 6 7 #import <Cocoa/Cocoa.h> 8 9 #include "base/logging.h" 10 #include "base/mac/bundle_locations.h" 11 #import "base/mac/scoped_nsobject.h" 12 #include "base/strings/sys_string_conversions.h" 13 #include "content/public/browser/browser_thread.h" 14 #import "ui/base/cocoa/nib_loading.h" 15 16 namespace { 17 18 const int kUsernameFieldTag = 1; 19 const int kPasswordFieldTag = 2; 20 21 } // namespace 22 23 // Helper object that receives the notification that the dialog/sheet is 24 // going away. 25 @interface ShellLoginDialogHelper : NSObject<NSAlertDelegate> { 26 @private 27 base::scoped_nsobject<NSAlert> alert_; 28 NSTextField* usernameField_; // WEAK; owned by alert_ 29 NSSecureTextField* passwordField_; // WEAK; owned by alert_ 30 } 31 32 - (NSAlert*)alert; 33 - (NSView*)accessoryView; 34 - (void)focus; 35 - (void)alertDidEnd:(NSAlert*)alert 36 returnCode:(int)returnCode 37 contextInfo:(void*)contextInfo; 38 - (void)cancel; 39 40 @end 41 42 @implementation ShellLoginDialogHelper 43 44 - (NSAlert*)alert { 45 alert_.reset([[NSAlert alloc] init]); 46 [alert_ setAccessoryView:[self accessoryView]]; 47 return alert_; 48 } 49 50 - (NSView*)accessoryView { 51 NSView* accessory_view = ui::GetViewFromNib(@"HttpAuth"); 52 if (!accessory_view) 53 return nil; 54 55 usernameField_ = [accessory_view viewWithTag:kUsernameFieldTag]; 56 passwordField_ = [accessory_view viewWithTag:kPasswordFieldTag]; 57 return accessory_view; 58 } 59 60 - (void)focus { 61 [[alert_ window] makeFirstResponder:usernameField_]; 62 } 63 64 - (void)alertDidEnd:(NSAlert*)alert 65 returnCode:(int)returnCode 66 contextInfo:(void*)contextInfo { 67 if (returnCode == NSRunStoppedResponse) 68 return; 69 70 content::ShellLoginDialog* this_dialog = 71 reinterpret_cast<content::ShellLoginDialog*>(contextInfo); 72 if (returnCode == NSAlertFirstButtonReturn) { 73 this_dialog->UserAcceptedAuth( 74 base::SysNSStringToUTF16([usernameField_ stringValue]), 75 base::SysNSStringToUTF16([passwordField_ stringValue])); 76 } else { 77 this_dialog->UserCancelledAuth(); 78 } 79 } 80 81 - (void)cancel { 82 [NSApp endSheet:[alert_ window]]; 83 alert_.reset(); 84 } 85 86 @end 87 88 namespace content { 89 90 void ShellLoginDialog::PlatformCreateDialog(const base::string16& message) { 91 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); 92 helper_ = [[ShellLoginDialogHelper alloc] init]; 93 94 // Show the modal dialog. 95 NSAlert* alert = [helper_ alert]; 96 [alert setDelegate:helper_]; 97 [alert setInformativeText:base::SysUTF16ToNSString(message)]; 98 [alert setMessageText:@"Please log in."]; 99 [alert addButtonWithTitle:@"OK"]; 100 NSButton* other = [alert addButtonWithTitle:@"Cancel"]; 101 [other setKeyEquivalent:@"\e"]; 102 [alert 103 beginSheetModalForWindow:nil // nil here makes it app-modal 104 modalDelegate:helper_ 105 didEndSelector:@selector(alertDidEnd:returnCode:contextInfo:) 106 contextInfo:this]; 107 108 [helper_ focus]; 109 } 110 111 void ShellLoginDialog::PlatformCleanUp() { 112 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); 113 [helper_ release]; 114 helper_ = nil; 115 } 116 117 void ShellLoginDialog::PlatformRequestCancelled() { 118 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); 119 [helper_ cancel]; 120 } 121 122 } // namespace content 123