Update To 11.40.268.0
[platform/framework/web/crosswalk.git] / src / chrome / browser / ui / cocoa / login_prompt_cocoa.mm
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 #import "chrome/browser/ui/cocoa/login_prompt_cocoa.h"
6
7 #include "base/mac/bundle_locations.h"
8 #include "base/mac/mac_util.h"
9 #include "base/mac/scoped_nsobject.h"
10 #include "base/strings/string16.h"
11 #include "base/strings/string_util.h"
12 #include "base/strings/sys_string_conversions.h"
13 #include "base/strings/utf_string_conversions.h"
14 #include "chrome/browser/tab_contents/tab_util.h"
15 #import "chrome/browser/ui/cocoa/constrained_window/constrained_window_custom_sheet.h"
16 #include "chrome/browser/ui/cocoa/constrained_window/constrained_window_mac.h"
17 #include "chrome/browser/ui/login/login_prompt.h"
18 #include "components/password_manager/core/browser/login_model.h"
19 #include "components/password_manager/core/browser/password_manager.h"
20 #include "content/public/browser/browser_thread.h"
21 #include "content/public/browser/web_contents.h"
22 #include "net/url_request/url_request.h"
23 #include "third_party/google_toolbox_for_mac/src/AppKit/GTMUILocalizerAndLayoutTweaker.h"
24
25 using autofill::PasswordForm;
26 using content::BrowserThread;
27 using content::WebContents;
28
29 // ----------------------------------------------------------------------------
30 // LoginHandlerMac
31
32 // This class simply forwards the authentication from the LoginView (on
33 // the UI thread) to the net::URLRequest (on the I/O thread).
34 // This class uses ref counting to ensure that it lives until all InvokeLaters
35 // have been called.
36 class LoginHandlerMac : public LoginHandler,
37                         public ConstrainedWindowMacDelegate {
38  public:
39   LoginHandlerMac(net::AuthChallengeInfo* auth_info, net::URLRequest* request)
40       : LoginHandler(auth_info, request) {
41   }
42
43   // LoginModelObserver implementation.
44   void OnAutofillDataAvailable(const base::string16& username,
45                                const base::string16& password) override {
46     DCHECK_CURRENTLY_ON(BrowserThread::UI);
47
48     [sheet_controller_ autofillLogin:base::SysUTF16ToNSString(username)
49                             password:base::SysUTF16ToNSString(password)];
50   }
51   void OnLoginModelDestroying() override {}
52
53   // LoginHandler:
54   void BuildViewForPasswordManager(password_manager::PasswordManager* manager,
55                                    const base::string16& explanation) override {
56     DCHECK_CURRENTLY_ON(BrowserThread::UI);
57
58     sheet_controller_.reset(
59         [[LoginHandlerSheet alloc] initWithLoginHandler:this]);
60
61     SetModel(manager);
62
63     [sheet_controller_ setExplanation:base::SysUTF16ToNSString(explanation)];
64
65     // Scary thread safety note: This can potentially be called *after* SetAuth
66     // or CancelAuth (say, if the request was cancelled before the UI thread got
67     // control).  However, that's OK since any UI interaction in those functions
68     // will occur via an InvokeLater on the UI thread, which is guaranteed
69     // to happen after this is called (since this was InvokeLater'd first).
70     WebContents* requesting_contents = GetWebContentsForLogin();
71     DCHECK(requesting_contents);
72
73     base::scoped_nsobject<CustomConstrainedWindowSheet> sheet(
74         [[CustomConstrainedWindowSheet alloc]
75             initWithCustomWindow:[sheet_controller_ window]]);
76     constrained_window_.reset(new ConstrainedWindowMac(
77         this, requesting_contents, sheet));
78
79     NotifyAuthNeeded();
80   }
81
82   void CloseDialog() override {
83     // The hosting dialog may have been freed.
84     if (constrained_window_)
85       constrained_window_->CloseWebContentsModalDialog();
86   }
87
88   // Overridden from ConstrainedWindowMacDelegate:
89   void OnConstrainedWindowClosed(ConstrainedWindowMac* window) override {
90     DCHECK_CURRENTLY_ON(BrowserThread::UI);
91     SetModel(NULL);
92     ReleaseSoon();
93
94     constrained_window_.reset();
95     sheet_controller_.reset();
96   }
97
98   void OnLoginPressed(const base::string16& username,
99                       const base::string16& password) {
100     DCHECK_CURRENTLY_ON(BrowserThread::UI);
101     SetAuth(username, password);
102   }
103
104   void OnCancelPressed() {
105     DCHECK_CURRENTLY_ON(BrowserThread::UI);
106     CancelAuth();
107   }
108
109  private:
110   friend class LoginPrompt;
111
112   ~LoginHandlerMac() override {
113     // This class will be deleted on a non UI thread. Ensure that the UI members
114     // have already been deleted.
115     CHECK(!constrained_window_.get());
116     CHECK(!sheet_controller_.get());
117   }
118
119   // The Cocoa controller of the GUI.
120   base::scoped_nsobject<LoginHandlerSheet> sheet_controller_;
121
122   scoped_ptr<ConstrainedWindowMac> constrained_window_;
123
124   DISALLOW_COPY_AND_ASSIGN(LoginHandlerMac);
125 };
126
127 // static
128 LoginHandler* LoginHandler::Create(net::AuthChallengeInfo* auth_info,
129                                    net::URLRequest* request) {
130   return new LoginHandlerMac(auth_info, request);
131 }
132
133 // ----------------------------------------------------------------------------
134 // LoginHandlerSheet
135
136 @implementation LoginHandlerSheet
137
138 - (id)initWithLoginHandler:(LoginHandlerMac*)handler {
139   NSString* nibPath =
140       [base::mac::FrameworkBundle() pathForResource:@"HttpAuthLoginSheet"
141                                              ofType:@"nib"];
142   if ((self = [super initWithWindowNibPath:nibPath
143                                      owner:self])) {
144     handler_ = handler;
145     // Force the nib to load so that all outlets are initialized.
146     [self window];
147   }
148   return self;
149 }
150
151 - (void)dealloc {
152   // The buttons could be in a modal loop, so disconnect them so they cannot
153   // call back to us after we're dead.
154   [loginButton_ setTarget:nil];
155   [cancelButton_ setTarget:nil];
156   [super dealloc];
157 }
158
159 - (IBAction)loginPressed:(id)sender {
160   handler_->OnLoginPressed(
161       base::SysNSStringToUTF16([nameField_ stringValue]),
162       base::SysNSStringToUTF16([passwordField_ stringValue]));
163 }
164
165 - (IBAction)cancelPressed:(id)sender {
166   handler_->OnCancelPressed();
167 }
168
169 - (void)autofillLogin:(NSString*)login password:(NSString*)password {
170   if ([[nameField_ stringValue] length] == 0) {
171     [nameField_ setStringValue:login];
172     [passwordField_ setStringValue:password];
173     [nameField_ selectText:self];
174   }
175 }
176
177 - (void)setExplanation:(NSString*)explanation {
178   // Put in the text.
179   [explanationField_ setStringValue:explanation];
180
181   // Resize the text field.
182   CGFloat windowDelta = [GTMUILocalizerAndLayoutTweaker
183        sizeToFitFixedWidthTextField:explanationField_];
184
185   NSRect newFrame = [[self window] frame];
186   newFrame.size.height += windowDelta;
187   [[self window] setFrame:newFrame display:NO];
188 }
189
190 @end