Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(40)

Side by Side Diff: chrome/browser/login_prompt_mac.mm

Issue 995004: Factoring duplicate code from platform-specific LoginHandlers into a base ... (Closed) Base URL: http://src.chromium.org/svn/trunk/src/
Patch Set: '' Created 10 years, 9 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch | Annotate | Revision Log
« no previous file with comments | « chrome/browser/login_prompt_gtk.cc ('k') | chrome/browser/login_prompt_win.cc » ('j') | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
1 // Copyright (c) 2009 The Chromium Authors. All rights reserved. 1 // Copyright (c) 2009 The Chromium Authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be 2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file. 3 // found in the LICENSE file.
4 4
5 #include "chrome/browser/login_prompt.h" 5 #include "chrome/browser/login_prompt.h"
6 #import "chrome/browser/login_prompt_mac.h" 6 #import "chrome/browser/login_prompt_mac.h"
7 7
8 #include "app/l10n_util.h" 8 #include "app/l10n_util.h"
9 #include "base/mac_util.h" 9 #include "base/mac_util.h"
10 #include "base/string_util.h" 10 #include "base/string_util.h"
(...skipping 15 matching lines...) Expand all
26 using webkit_glue::PasswordForm; 26 using webkit_glue::PasswordForm;
27 27
28 // ---------------------------------------------------------------------------- 28 // ----------------------------------------------------------------------------
29 // LoginHandlerMac 29 // LoginHandlerMac
30 30
31 // This class simply forwards the authentication from the LoginView (on 31 // This class simply forwards the authentication from the LoginView (on
32 // the UI thread) to the URLRequest (on the I/O thread). 32 // the UI thread) to the URLRequest (on the I/O thread).
33 // This class uses ref counting to ensure that it lives until all InvokeLaters 33 // This class uses ref counting to ensure that it lives until all InvokeLaters
34 // have been called. 34 // have been called.
35 class LoginHandlerMac : public LoginHandler, 35 class LoginHandlerMac : public LoginHandler,
36 public base::RefCountedThreadSafe<LoginHandlerMac>, 36 public ConstrainedWindowMacDelegateCustomSheet {
37 public ConstrainedWindowMacDelegateCustomSheet,
38 public LoginModelObserver {
39 public: 37 public:
40 LoginHandlerMac(URLRequest* request) 38 explicit LoginHandlerMac(URLRequest* request)
41 : handled_auth_(false), 39 : LoginHandler(request),
42 dialog_(NULL), 40 sheet_controller_(nil) {
43 request_(request),
44 password_manager_(NULL),
45 sheet_controller_(nil),
46 login_model_(NULL) {
47 // This constructor is called on the I/O thread, so we cannot load the nib
48 // here. BuildViewForPasswordManager() will be invoked on the UI thread
49 // later, so wait with loading the nib until then.
50 DCHECK(request_) << "LoginHandlerMac constructed with NULL request";
51
52 AddRef(); // matched by ReleaseLater.
53 if (!ResourceDispatcherHost::RenderViewForRequest(request_,
54 &render_process_host_id_,
55 &tab_contents_id_)) {
56 NOTREACHED();
57 }
58 } 41 }
59 42
60 virtual ~LoginHandlerMac() { 43 virtual ~LoginHandlerMac() {
61 if (login_model_)
62 login_model_->SetObserver(NULL);
63 }
64
65 void SetModel(LoginModel* model) {
66 if (login_model_)
67 login_model_->SetObserver(NULL);
68 login_model_ = model;
69 if (login_model_)
70 login_model_->SetObserver(this);
71 } 44 }
72 45
73 // LoginModelObserver implementation. 46 // LoginModelObserver implementation.
74 virtual void OnAutofillDataAvailable(const std::wstring& username, 47 virtual void OnAutofillDataAvailable(const std::wstring& username,
75 const std::wstring& password) { 48 const std::wstring& password) {
49 DCHECK(ChromeThread::CurrentlyOn(ChromeThread::UI));
50
76 [sheet_controller_ autofillLogin:base::SysWideToNSString(username) 51 [sheet_controller_ autofillLogin:base::SysWideToNSString(username)
77 password:base::SysWideToNSString(password)]; 52 password:base::SysWideToNSString(password)];
78 } 53 }
79 54
80 // LoginHandler: 55 // LoginHandler:
81 virtual void BuildViewForPasswordManager(PasswordManager* manager, 56 virtual void BuildViewForPasswordManager(PasswordManager* manager,
82 std::wstring explanation) { 57 std::wstring explanation) {
83 DCHECK(ChromeThread::CurrentlyOn(ChromeThread::UI)); 58 DCHECK(ChromeThread::CurrentlyOn(ChromeThread::UI));
84 59
85 // Load nib here instead of in constructor. 60 // Load nib here instead of in constructor.
86 sheet_controller_ = [[[LoginHandlerSheet alloc] 61 sheet_controller_ = [[[LoginHandlerSheet alloc]
87 initWithLoginHandler:this] autorelease]; 62 initWithLoginHandler:this] autorelease];
88 init([sheet_controller_ window], sheet_controller_, 63 init([sheet_controller_ window], sheet_controller_,
89 @selector(sheetDidEnd:returnCode:contextInfo:)); 64 @selector(sheetDidEnd:returnCode:contextInfo:));
90 65
91 SetModel(manager); 66 SetModel(manager);
92 67
93 [sheet_controller_ setExplanation:base::SysWideToNSString(explanation)]; 68 [sheet_controller_ setExplanation:base::SysWideToNSString(explanation)];
94 69
95 // Scary thread safety note: This can potentially be called *after* SetAuth 70 // Scary thread safety note: This can potentially be called *after* SetAuth
96 // or CancelAuth (say, if the request was cancelled before the UI thread got 71 // or CancelAuth (say, if the request was cancelled before the UI thread got
97 // control). However, that's OK since any UI interaction in those functions 72 // control). However, that's OK since any UI interaction in those functions
98 // will occur via an InvokeLater on the UI thread, which is guaranteed 73 // will occur via an InvokeLater on the UI thread, which is guaranteed
99 // to happen after this is called (since this was InvokeLater'd first). 74 // to happen after this is called (since this was InvokeLater'd first).
100 dialog_ = GetTabContentsForLogin()->CreateConstrainedDialog(this); 75 SetDialog(GetTabContentsForLogin()->CreateConstrainedDialog(this));
101 76
102 SendNotifications(); 77 SendNotifications();
103 } 78 }
104 79
105 virtual void SetPasswordForm(const webkit_glue::PasswordForm& form) { 80 // Overridden from ConstrainedWindowMacDelegate:
106 password_form_ = form; 81 virtual void DeleteDelegate() {
107 }
108
109 virtual void SetPasswordManager(PasswordManager* password_manager) {
110 password_manager_ = password_manager;
111 }
112
113 virtual TabContents* GetTabContentsForLogin() {
114 DCHECK(ChromeThread::CurrentlyOn(ChromeThread::UI)); 82 DCHECK(ChromeThread::CurrentlyOn(ChromeThread::UI));
115 83
116 return tab_util::GetTabContentsByID(render_process_host_id_, 84 // The constrained window is going to delete itself; clear our pointer.
117 tab_contents_id_); 85 SetDialog(NULL);
118 } 86 SetModel(NULL);
119
120 virtual void SetAuth(const std::wstring& username,
121 const std::wstring& password) {
122 if (WasAuthHandled(true))
123 return;
124
125 // Tell the password manager the credentials were submitted / accepted.
126 if (password_manager_) {
127 password_form_.username_value = WideToUTF16Hack(username);
128 password_form_.password_value = WideToUTF16Hack(password);
129 password_manager_->ProvisionallySavePassword(password_form_);
130 }
131
132 ChromeThread::PostTask(
133 ChromeThread::UI, FROM_HERE,
134 NewRunnableMethod(this, &LoginHandlerMac::CloseContentsDeferred));
135 ChromeThread::PostTask(
136 ChromeThread::UI, FROM_HERE,
137 NewRunnableMethod(this, &LoginHandlerMac::SendNotifications));
138 ChromeThread::PostTask(
139 ChromeThread::IO, FROM_HERE,
140 NewRunnableMethod(
141 this, &LoginHandlerMac::SetAuthDeferred, username, password));
142 }
143
144 virtual void CancelAuth() {
145 if (WasAuthHandled(true))
146 return;
147
148 ChromeThread::PostTask(
149 ChromeThread::UI, FROM_HERE,
150 NewRunnableMethod(this, &LoginHandlerMac::CloseContentsDeferred));
151 ChromeThread::PostTask(
152 ChromeThread::UI, FROM_HERE,
153 NewRunnableMethod(this, &LoginHandlerMac::SendNotifications));
154 ChromeThread::PostTask(
155 ChromeThread::IO, FROM_HERE,
156 NewRunnableMethod(this, &LoginHandlerMac::CancelAuthDeferred));
157 }
158
159 virtual void OnRequestCancelled() {
160 DCHECK(ChromeThread::CurrentlyOn(ChromeThread::IO)) <<
161 "Why is OnRequestCancelled called from the UI thread?";
162
163 // Reference is no longer valid.
164 request_ = NULL;
165
166 // Give up on auth if the request was cancelled.
167 CancelAuth();
168 }
169
170 // Overridden from ConstrainedWindowMacDelegate:
171 virtual void DeleteDelegate() {
172 if (!WasAuthHandled(true)) {
173 ChromeThread::PostTask(
174 ChromeThread::IO, FROM_HERE,
175 NewRunnableMethod(this, &LoginHandlerMac::CancelAuthDeferred));
176 ChromeThread::PostTask(
177 ChromeThread::UI, FROM_HERE,
178 NewRunnableMethod(this, &LoginHandlerMac::SendNotifications));
179 }
180 87
181 // Close sheet if it's still open, as required by 88 // Close sheet if it's still open, as required by
182 // ConstrainedWindowMacDelegate. 89 // ConstrainedWindowMacDelegate.
183 DCHECK(ChromeThread::CurrentlyOn(ChromeThread::UI));
184 if (is_sheet_open()) 90 if (is_sheet_open())
185 [NSApp endSheet:sheet()]; 91 [NSApp endSheet:sheet()];
186 92
187 SetModel(NULL); 93 ReleaseSoon();
188
189 // Delete this object once all InvokeLaters have been called.
190 ChromeThread::ReleaseSoon(ChromeThread::IO, FROM_HERE, this);
191 } 94 }
192 95
193 void OnLoginPressed(const std::wstring& username, 96 void OnLoginPressed(const std::wstring& username,
194 const std::wstring& password) { 97 const std::wstring& password) {
195 DCHECK(ChromeThread::CurrentlyOn(ChromeThread::UI)); 98 DCHECK(ChromeThread::CurrentlyOn(ChromeThread::UI));
99
196 SetAuth(username, password); 100 SetAuth(username, password);
197 } 101 }
198 102
199 void OnCancelPressed() { 103 void OnCancelPressed() {
200 DCHECK(ChromeThread::CurrentlyOn(ChromeThread::UI)); 104 DCHECK(ChromeThread::CurrentlyOn(ChromeThread::UI));
105
201 CancelAuth(); 106 CancelAuth();
202 } 107 }
203 108
204 private: 109 private:
205 friend class LoginPrompt; 110 friend class LoginPrompt;
206 111
207 // Calls SetAuth from the IO loop.
208 void SetAuthDeferred(const std::wstring& username,
209 const std::wstring& password) {
210 DCHECK(ChromeThread::CurrentlyOn(ChromeThread::IO));
211
212 if (request_) {
213 request_->SetAuth(username, password);
214 ResetLoginHandlerForRequest(request_);
215 }
216 }
217
218 // Calls CancelAuth from the IO loop.
219 void CancelAuthDeferred() {
220 DCHECK(ChromeThread::CurrentlyOn(ChromeThread::IO));
221
222 if (request_) {
223 request_->CancelAuth();
224 // Verify that CancelAuth does destroy the request via our delegate.
225 DCHECK(request_ != NULL);
226 ResetLoginHandlerForRequest(request_);
227 }
228 }
229
230 // Closes the view_contents from the UI loop.
231 void CloseContentsDeferred() {
232 DCHECK(ChromeThread::CurrentlyOn(ChromeThread::UI));
233
234 // The hosting ConstrainedWindow may have been freed.
235 if (dialog_)
236 dialog_->CloseConstrainedWindow();
237 }
238
239 // Returns whether authentication had been handled (SetAuth or CancelAuth).
240 // If |set_handled| is true, it will mark authentication as handled.
241 bool WasAuthHandled(bool set_handled) {
242 AutoLock lock(handled_auth_lock_);
243 bool was_handled = handled_auth_;
244 if (set_handled)
245 handled_auth_ = true;
246 return was_handled;
247 }
248
249 // Notify observers that authentication is needed or received. The automation
250 // proxy uses this for testing.
251 void SendNotifications() {
252 DCHECK(ChromeThread::CurrentlyOn(ChromeThread::UI));
253
254 NotificationService* service = NotificationService::current();
255 TabContents* requesting_contents = GetTabContentsForLogin();
256 if (!requesting_contents)
257 return;
258
259 NavigationController* controller = &requesting_contents->controller();
260
261 if (!WasAuthHandled(false)) {
262 LoginNotificationDetails details(this);
263 service->Notify(NotificationType::AUTH_NEEDED,
264 Source<NavigationController>(controller),
265 Details<LoginNotificationDetails>(&details));
266 } else {
267 service->Notify(NotificationType::AUTH_SUPPLIED,
268 Source<NavigationController>(controller),
269 NotificationService::NoDetails());
270 }
271 }
272
273 // True if we've handled auth (SetAuth or CancelAuth has been called).
274 bool handled_auth_;
275 Lock handled_auth_lock_;
276
277 // The ConstrainedWindow that is hosting our LoginView.
278 // This should only be accessed on the UI loop.
279 ConstrainedWindow* dialog_;
280
281 // The request that wants login data.
282 // This should only be accessed on the IO loop.
283 URLRequest* request_;
284
285 // The PasswordForm sent to the PasswordManager. This is so we can refer to it
286 // when later notifying the password manager if the credentials were accepted
287 // or rejected.
288 // This should only be accessed on the UI loop.
289 PasswordForm password_form_;
290
291 // Points to the password manager owned by the TabContents requesting auth.
292 // Can be null if the TabContents is not a TabContents.
293 // This should only be accessed on the UI loop.
294 PasswordManager* password_manager_;
295
296 // Cached from the URLRequest, in case it goes NULL on us.
297 int render_process_host_id_;
298 int tab_contents_id_;
299
300 // The Cocoa controller of the GUI. 112 // The Cocoa controller of the GUI.
301 LoginHandlerSheet* sheet_controller_; 113 LoginHandlerSheet* sheet_controller_;
302 114
303 // If not null, points to a model we need to notify of our own destruction
304 // so it doesn't try and access this when its too late.
305 LoginModel* login_model_;
306
307 DISALLOW_COPY_AND_ASSIGN(LoginHandlerMac); 115 DISALLOW_COPY_AND_ASSIGN(LoginHandlerMac);
308 }; 116 };
309 117
310 // static 118 // static
311 LoginHandler* LoginHandler::Create(URLRequest* request) { 119 LoginHandler* LoginHandler::Create(URLRequest* request) {
312 return new LoginHandlerMac(request); 120 return new LoginHandlerMac(request);
313 } 121 }
314 122
315 // ---------------------------------------------------------------------------- 123 // ----------------------------------------------------------------------------
316 // LoginHandlerSheet 124 // LoginHandlerSheet
(...skipping 48 matching lines...) Expand 10 before | Expand all | Expand 10 after
365 sizeToFitFixedWidthTextField:explanationField_]; 173 sizeToFitFixedWidthTextField:explanationField_];
366 174
367 // Resize the window (no shifting needed due to window layout). 175 // Resize the window (no shifting needed due to window layout).
368 NSSize windowDelta = NSMakeSize(0, explanationShift); 176 NSSize windowDelta = NSMakeSize(0, explanationShift);
369 [GTMUILocalizerAndLayoutTweaker 177 [GTMUILocalizerAndLayoutTweaker
370 resizeWindowWithoutAutoResizingSubViews:[self window] 178 resizeWindowWithoutAutoResizingSubViews:[self window]
371 delta:windowDelta]; 179 delta:windowDelta];
372 } 180 }
373 181
374 @end 182 @end
OLDNEW
« no previous file with comments | « chrome/browser/login_prompt_gtk.cc ('k') | chrome/browser/login_prompt_win.cc » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698