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
16namespace {
17
18const int kUsernameFieldTag = 1;
19const 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
88namespace content {
89
90void 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
111void ShellLoginDialog::PlatformCleanUp() {
112  DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
113  [helper_ release];
114  helper_ = nil;
115}
116
117void ShellLoginDialog::PlatformRequestCancelled() {
118  DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
119  [helper_ cancel];
120}
121
122}  // namespace content
123