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

Side by Side Diff: chrome/browser/ui/login/login_prompt.cc

Issue 1395473003: Follow-up clean-up in LoginHandler (Closed) Base URL: https://chromium.googlesource.com/chromium/src.git@master
Patch Set: Created 5 years, 2 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
« no previous file with comments | « chrome/browser/ui/login/login_prompt.h ('k') | chrome/browser/ui/views/login_prompt_views.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) 2012 The Chromium Authors. All rights reserved. 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 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/ui/login/login_prompt.h" 5 #include "chrome/browser/ui/login/login_prompt.h"
6 6
7 #include <string> 7 #include <string>
8 #include <vector> 8 #include <vector>
9 9
10 #include "base/bind.h" 10 #include "base/bind.h"
(...skipping 37 matching lines...) Expand 10 before | Expand all | Expand 10 after
48 using content::BrowserThread; 48 using content::BrowserThread;
49 using content::NavigationController; 49 using content::NavigationController;
50 using content::RenderViewHost; 50 using content::RenderViewHost;
51 using content::RenderViewHostDelegate; 51 using content::RenderViewHostDelegate;
52 using content::ResourceDispatcherHost; 52 using content::ResourceDispatcherHost;
53 using content::ResourceRequestInfo; 53 using content::ResourceRequestInfo;
54 using content::WebContents; 54 using content::WebContents;
55 55
56 class LoginHandlerImpl; 56 class LoginHandlerImpl;
57 57
58 namespace {
59
58 // Helper to remove the ref from an net::URLRequest to the LoginHandler. 60 // Helper to remove the ref from an net::URLRequest to the LoginHandler.
59 // Should only be called from the IO thread, since it accesses an 61 // Should only be called from the IO thread, since it accesses an
60 // net::URLRequest. 62 // net::URLRequest.
61 void ResetLoginHandlerForRequest(net::URLRequest* request) { 63 void ResetLoginHandlerForRequest(net::URLRequest* request) {
62 ResourceDispatcherHost::Get()->ClearLoginDelegateForRequest(request); 64 ResourceDispatcherHost::Get()->ClearLoginDelegateForRequest(request);
63 } 65 }
64 66
65 // Get the signon_realm under which this auth info should be stored. 67 // Helper to create a PasswordForm for PasswordManager to start looking for
66 // 68 // saved credentials.
67 // The format of the signon_realm for proxy auth is: 69 PasswordForm MakeInputForPasswordManager(const GURL& request_url,
vabr (Chromium) 2015/10/08 10:23:34 This and the following methods have just been move
68 // proxy-host/auth-realm 70 net::AuthChallengeInfo* auth_info) {
69 // The format of the signon_realm for server auth is: 71 PasswordForm dialog_form;
70 // url-scheme://url-host[:url-port]/auth-realm 72 if (base::LowerCaseEqualsASCII(auth_info->scheme, "basic")) {
71 // 73 dialog_form.scheme = PasswordForm::SCHEME_BASIC;
72 // Be careful when changing this function, since you could make existing 74 } else if (base::LowerCaseEqualsASCII(auth_info->scheme, "digest")) {
73 // saved logins un-retrievable. 75 dialog_form.scheme = PasswordForm::SCHEME_DIGEST;
74 std::string GetSignonRealm(const GURL& url,
vabr (Chromium) 2015/10/08 10:23:34 This whole method just got moved without changes t
75 const net::AuthChallengeInfo& auth_info) {
76 std::string signon_realm;
77 if (auth_info.is_proxy) {
78 signon_realm = auth_info.challenger.ToString();
79 signon_realm.append("/");
80 } else { 76 } else {
81 // Take scheme, host, and port from the url. 77 dialog_form.scheme = PasswordForm::SCHEME_OTHER;
82 signon_realm = url.GetOrigin().spec();
83 // This ends with a "/".
84 } 78 }
85 signon_realm.append(auth_info.realm); 79 std::string host_and_port(auth_info->challenger.ToString());
86 return signon_realm; 80 if (auth_info->is_proxy) {
81 std::string origin = host_and_port;
82 // We don't expect this to already start with http:// or https://.
83 DCHECK(origin.find("http://") != 0 && origin.find("https://") != 0);
84 origin = std::string("http://") + origin;
85 dialog_form.origin = GURL(origin);
86 } else if (!auth_info->challenger.Equals(
87 net::HostPortPair::FromURL(request_url))) {
88 dialog_form.origin = GURL();
89 NOTREACHED(); // crbug.com/32718
90 } else {
91 dialog_form.origin = GURL(request_url.scheme() + "://" + host_and_port);
92 }
93 dialog_form.signon_realm = GetSignonRealm(dialog_form.origin, *auth_info);
94 return dialog_form;
vabr (Chromium) 2015/10/08 10:23:34 The handler->SetPasswordForm(dialog_form); call be
87 } 95 }
88 96
97 void ShowLoginPrompt(const GURL& request_url,
98 net::AuthChallengeInfo* auth_info,
99 LoginHandler* handler) {
100 DCHECK_CURRENTLY_ON(BrowserThread::UI);
101 WebContents* parent_contents = handler->GetWebContentsForLogin();
102 if (!parent_contents)
103 return;
104 prerender::PrerenderContents* prerender_contents =
105 prerender::PrerenderContents::FromWebContents(parent_contents);
106 if (prerender_contents) {
107 prerender_contents->Destroy(prerender::FINAL_STATUS_AUTH_NEEDED);
108 return;
109 }
110
111 // The realm is controlled by the remote server, so there is no reason
112 // to believe it is of a reasonable length.
113 base::string16 elided_realm;
114 gfx::ElideString(base::UTF8ToUTF16(auth_info->realm), 120, &elided_realm);
115
116 std::string languages;
117 content::WebContents* web_contents = handler->GetWebContentsForLogin();
118 if (web_contents) {
119 Profile* profile =
120 Profile::FromBrowserContext(web_contents->GetBrowserContext());
121 if (profile)
122 languages = profile->GetPrefs()->GetString(prefs::kAcceptLanguages);
123 }
124
125 base::string16 authority =
126 url_formatter::FormatUrlForSecurityDisplay(request_url, languages);
127 base::string16 explanation =
128 elided_realm.empty()
129 ? l10n_util::GetStringFUTF16(IDS_LOGIN_DIALOG_DESCRIPTION_NO_REALM,
130 authority)
131 : l10n_util::GetStringFUTF16(IDS_LOGIN_DIALOG_DESCRIPTION, authority,
132 elided_realm);
133
134 password_manager::PasswordManager* password_manager =
135 handler->GetPasswordManagerForLogin();
136
137 if (!password_manager) {
138 #if defined(ENABLE_EXTENSIONS)
139 // A WebContents in a <webview> (a GuestView type) does not have a password
140 // manager, but still needs to be able to show login prompts.
141 if (guest_view::GuestViewBase::FromWebContents(parent_contents)) {
142 handler->BuildViewWithoutPasswordManager(explanation);
143 return;
144 }
145 #endif
146 handler->CancelAuth();
147 return;
148 }
149
150 if (password_manager && password_manager->client()->IsLoggingActive()) {
151 password_manager::BrowserSavePasswordProgressLogger logger(
152 password_manager->client());
153 logger.LogMessage(
154 autofill::SavePasswordProgressLogger::STRING_SHOW_LOGIN_PROMPT_METHOD);
155 }
156
157 PasswordForm observed_form(
158 MakeInputForPasswordManager(request_url, auth_info));
159 handler->BuildViewWithPasswordManager(explanation, password_manager,
160 observed_form);
161 }
162
163 } // namespace
164
89 // ---------------------------------------------------------------------------- 165 // ----------------------------------------------------------------------------
90 // LoginHandler 166 // LoginHandler
91 167
92 LoginHandler::LoginModelData::LoginModelData( 168 LoginHandler::LoginModelData::LoginModelData(
93 password_manager::LoginModel* login_model, 169 password_manager::LoginModel* login_model,
94 const autofill::PasswordForm& observed_form) 170 const autofill::PasswordForm& observed_form)
95 : model(login_model), form(observed_form) { 171 : model(login_model), form(observed_form) {
96 DCHECK(model); 172 DCHECK(model);
97 } 173 }
98 174
99 LoginHandler::LoginHandler(net::AuthChallengeInfo* auth_info, 175 LoginHandler::LoginHandler(net::AuthChallengeInfo* auth_info,
100 net::URLRequest* request) 176 net::URLRequest* request)
101 : handled_auth_(false), 177 : handled_auth_(false),
102 auth_info_(auth_info), 178 auth_info_(auth_info),
103 request_(request), 179 request_(request),
104 http_network_session_( 180 http_network_session_(
105 request_->context()->http_transaction_factory()->GetSession()), 181 request_->context()->http_transaction_factory()->GetSession()),
106 password_manager_(NULL), 182 password_manager_(NULL),
107 login_model_(NULL) { 183 login_model_(NULL) {
108 // This constructor is called on the I/O thread, so we cannot load the nib 184 // This constructor is called on the I/O thread, so we cannot load the nib
109 // here. BuildView() will be invoked on the UI thread later, so wait with 185 // here. BuildViewImpl() will be invoked on the UI thread later, so wait with
110 // loading the nib until then. 186 // loading the nib until then.
111 DCHECK(request_) << "LoginHandler constructed with NULL request"; 187 DCHECK(request_) << "LoginHandler constructed with NULL request";
112 DCHECK(auth_info_.get()) << "LoginHandler constructed with NULL auth info"; 188 DCHECK(auth_info_.get()) << "LoginHandler constructed with NULL auth info";
113 189
114 AddRef(); // matched by LoginHandler::ReleaseSoon(). 190 AddRef(); // matched by LoginHandler::ReleaseSoon().
115 191
116 BrowserThread::PostTask( 192 BrowserThread::PostTask(
117 BrowserThread::UI, FROM_HERE, 193 BrowserThread::UI, FROM_HERE,
118 base::Bind(&LoginHandler::AddObservers, this)); 194 base::Bind(&LoginHandler::AddObservers, this));
119 195
120 if (!ResourceRequestInfo::ForRequest(request_)->GetAssociatedRenderFrame( 196 if (!ResourceRequestInfo::ForRequest(request_)->GetAssociatedRenderFrame(
121 &render_process_host_id_, &render_frame_id_)) { 197 &render_process_host_id_, &render_frame_id_)) {
122 NOTREACHED(); 198 NOTREACHED();
123 } 199 }
124 } 200 }
125 201
126 void LoginHandler::OnRequestCancelled() { 202 void LoginHandler::OnRequestCancelled() {
127 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO)) << 203 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO)) <<
128 "Why is OnRequestCancelled called from the UI thread?"; 204 "Why is OnRequestCancelled called from the UI thread?";
129 205
130 // Reference is no longer valid. 206 // Reference is no longer valid.
131 request_ = NULL; 207 request_ = NULL;
132 208
133 // Give up on auth if the request was cancelled. 209 // Give up on auth if the request was cancelled.
134 CancelAuth(); 210 CancelAuth();
135 } 211 }
136 212
213 void LoginHandler::BuildViewWithPasswordManager(
214 const base::string16& explanation,
215 password_manager::PasswordManager* password_manager,
216 const autofill::PasswordForm& observed_form) {
217 SetPasswordManager(password_manager);
218 SetPasswordForm(observed_form);
davidben 2015/10/08 15:33:51 These two methods no longer need to be public and
vabr (Chromium) 2015/10/08 15:56:40 Good call! Done.
219 LoginHandler::LoginModelData model_data(password_manager, observed_form);
220 BuildViewImpl(explanation, &model_data);
221 }
222
223 void LoginHandler::BuildViewWithoutPasswordManager(
224 const base::string16& explanation) {
225 BuildViewImpl(explanation, nullptr);
226 }
227
137 void LoginHandler::SetPasswordForm(const autofill::PasswordForm& form) { 228 void LoginHandler::SetPasswordForm(const autofill::PasswordForm& form) {
138 password_form_ = form; 229 password_form_ = form;
139 } 230 }
140 231
141 void LoginHandler::SetPasswordManager( 232 void LoginHandler::SetPasswordManager(
142 password_manager::PasswordManager* password_manager) { 233 password_manager::PasswordManager* password_manager) {
143 password_manager_ = password_manager; 234 password_manager_ = password_manager;
144 } 235 }
145 236
146 WebContents* LoginHandler::GetWebContentsForLogin() const { 237 WebContents* LoginHandler::GetWebContentsForLogin() const {
(...skipping 128 matching lines...) Expand 10 before | Expand all | Expand 10 after
275 base::AutoLock lock(handled_auth_lock_); 366 base::AutoLock lock(handled_auth_lock_);
276 bool was_handled = handled_auth_; 367 bool was_handled = handled_auth_;
277 return was_handled; 368 return was_handled;
278 } 369 }
279 370
280 LoginHandler::~LoginHandler() { 371 LoginHandler::~LoginHandler() {
281 ResetModel(); 372 ResetModel();
282 } 373 }
283 374
284 void LoginHandler::SetModel(LoginModelData model_data) { 375 void LoginHandler::SetModel(LoginModelData model_data) {
285 if (login_model_) 376 ResetModel();
286 login_model_->RemoveObserver(this);
287 login_model_ = model_data.model; 377 login_model_ = model_data.model;
288 login_model_->AddObserverAndDeliverCredentials(this, model_data.form); 378 login_model_->AddObserverAndDeliverCredentials(this, model_data.form);
289 } 379 }
290 380
291 void LoginHandler::ResetModel() { 381 void LoginHandler::ResetModel() {
292 if (login_model_) 382 if (login_model_)
293 login_model_->RemoveObserver(this); 383 login_model_->RemoveObserver(this);
294 login_model_ = nullptr; 384 login_model_ = nullptr;
295 } 385 }
296 386
(...skipping 134 matching lines...) Expand 10 before | Expand all | Expand 10 after
431 if (!requesting_contents) 521 if (!requesting_contents)
432 return; 522 return;
433 // If a (blank) login interstitial was displayed, proceed so that the 523 // If a (blank) login interstitial was displayed, proceed so that the
434 // navigation is committed. 524 // navigation is committed.
435 content::InterstitialPage* interstitial_page = 525 content::InterstitialPage* interstitial_page =
436 requesting_contents->GetInterstitialPage(); 526 requesting_contents->GetInterstitialPage();
437 if (interstitial_page) 527 if (interstitial_page)
438 interstitial_page->Proceed(); 528 interstitial_page->Proceed();
439 } 529 }
440 530
441 // Helper to create a PasswordForm for PasswordManager to start looking for
442 // saved credentials.
443 PasswordForm MakeInputForPasswordManager(const GURL& request_url,
444 net::AuthChallengeInfo* auth_info,
445 LoginHandler* handler) {
446 PasswordForm dialog_form;
447 if (base::LowerCaseEqualsASCII(auth_info->scheme, "basic")) {
448 dialog_form.scheme = PasswordForm::SCHEME_BASIC;
449 } else if (base::LowerCaseEqualsASCII(auth_info->scheme, "digest")) {
450 dialog_form.scheme = PasswordForm::SCHEME_DIGEST;
451 } else {
452 dialog_form.scheme = PasswordForm::SCHEME_OTHER;
453 }
454 std::string host_and_port(auth_info->challenger.ToString());
455 if (auth_info->is_proxy) {
456 std::string origin = host_and_port;
457 // We don't expect this to already start with http:// or https://.
458 DCHECK(origin.find("http://") != 0 && origin.find("https://") != 0);
459 origin = std::string("http://") + origin;
460 dialog_form.origin = GURL(origin);
461 } else if (!auth_info->challenger.Equals(
462 net::HostPortPair::FromURL(request_url))) {
463 dialog_form.origin = GURL();
464 NOTREACHED(); // crbug.com/32718
465 } else {
466 dialog_form.origin = GURL(request_url.scheme() + "://" + host_and_port);
467 }
468 dialog_form.signon_realm = GetSignonRealm(dialog_form.origin, *auth_info);
469 // Set the password form for the handler (by copy).
470 handler->SetPasswordForm(dialog_form);
471 return dialog_form;
472 }
473
474 void ShowLoginPrompt(const GURL& request_url,
475 net::AuthChallengeInfo* auth_info,
476 LoginHandler* handler) {
477 DCHECK_CURRENTLY_ON(BrowserThread::UI);
478 WebContents* parent_contents = handler->GetWebContentsForLogin();
479 if (!parent_contents)
480 return;
481 prerender::PrerenderContents* prerender_contents =
482 prerender::PrerenderContents::FromWebContents(parent_contents);
483 if (prerender_contents) {
484 prerender_contents->Destroy(prerender::FINAL_STATUS_AUTH_NEEDED);
485 return;
486 }
487
488 // The realm is controlled by the remote server, so there is no reason
489 // to believe it is of a reasonable length.
490 base::string16 elided_realm;
491 gfx::ElideString(base::UTF8ToUTF16(auth_info->realm), 120, &elided_realm);
492
493 std::string languages;
494 content::WebContents* web_contents = handler->GetWebContentsForLogin();
495 if (web_contents) {
496 Profile* profile =
497 Profile::FromBrowserContext(web_contents->GetBrowserContext());
498 if (profile)
499 languages = profile->GetPrefs()->GetString(prefs::kAcceptLanguages);
500 }
501
502 base::string16 authority =
503 url_formatter::FormatUrlForSecurityDisplay(request_url, languages);
504 base::string16 explanation =
505 elided_realm.empty()
506 ? l10n_util::GetStringFUTF16(IDS_LOGIN_DIALOG_DESCRIPTION_NO_REALM,
507 authority)
508 : l10n_util::GetStringFUTF16(IDS_LOGIN_DIALOG_DESCRIPTION, authority,
509 elided_realm);
510
511 password_manager::PasswordManager* password_manager =
512 handler->GetPasswordManagerForLogin();
513
514 if (!password_manager) {
515 #if defined(ENABLE_EXTENSIONS)
516 // A WebContents in a <webview> (a GuestView type) does not have a password
517 // manager, but still needs to be able to show login prompts.
518 if (guest_view::GuestViewBase::FromWebContents(parent_contents)) {
519 handler->BuildView(explanation, nullptr);
520 return;
521 }
522 #endif
523 handler->CancelAuth();
524 return;
525 }
526
527 if (password_manager && password_manager->client()->IsLoggingActive()) {
528 password_manager::BrowserSavePasswordProgressLogger logger(
529 password_manager->client());
530 logger.LogMessage(
531 autofill::SavePasswordProgressLogger::STRING_SHOW_LOGIN_PROMPT_METHOD);
532 }
533
534 handler->SetPasswordManager(password_manager);
535
536 PasswordForm observed_form(
537 MakeInputForPasswordManager(request_url, auth_info, handler));
538 LoginHandler::LoginModelData model_data(password_manager, observed_form);
539 handler->BuildView(explanation, &model_data);
540 }
541
542 // This callback is run on the UI thread and creates a constrained window with 531 // This callback is run on the UI thread and creates a constrained window with
543 // a LoginView to prompt the user. If the prompt is triggered because of 532 // a LoginView to prompt the user. If the prompt is triggered because of
544 // a cross origin navigation in the main frame, a blank interstitial is first 533 // a cross origin navigation in the main frame, a blank interstitial is first
545 // created which in turn creates the LoginView. Otherwise, a LoginView is 534 // created which in turn creates the LoginView. Otherwise, a LoginView is
546 // directly in this callback. In both cases, the response will be sent to 535 // directly in this callback. In both cases, the response will be sent to
547 // LoginHandler, which then routes it to the net::URLRequest on the I/O thread. 536 // LoginHandler, which then routes it to the net::URLRequest on the I/O thread.
548 void LoginDialogCallback(const GURL& request_url, 537 void LoginDialogCallback(const GURL& request_url,
549 net::AuthChallengeInfo* auth_info, 538 net::AuthChallengeInfo* auth_info,
550 LoginHandler* handler, 539 LoginHandler* handler,
551 bool is_main_frame) { 540 bool is_main_frame) {
(...skipping 51 matching lines...) Expand 10 before | Expand all | Expand 10 after
603 net::URLRequest* request) { 592 net::URLRequest* request) {
604 bool is_main_frame = (request->load_flags() & net::LOAD_MAIN_FRAME) != 0; 593 bool is_main_frame = (request->load_flags() & net::LOAD_MAIN_FRAME) != 0;
605 LoginHandler* handler = LoginHandler::Create(auth_info, request); 594 LoginHandler* handler = LoginHandler::Create(auth_info, request);
606 BrowserThread::PostTask( 595 BrowserThread::PostTask(
607 BrowserThread::UI, FROM_HERE, 596 BrowserThread::UI, FROM_HERE,
608 base::Bind(&LoginDialogCallback, request->url(), 597 base::Bind(&LoginDialogCallback, request->url(),
609 make_scoped_refptr(auth_info), make_scoped_refptr(handler), 598 make_scoped_refptr(auth_info), make_scoped_refptr(handler),
610 is_main_frame)); 599 is_main_frame));
611 return handler; 600 return handler;
612 } 601 }
602
603 // Get the signon_realm under which this auth info should be stored.
604 //
605 // The format of the signon_realm for proxy auth is:
606 // proxy-host/auth-realm
607 // The format of the signon_realm for server auth is:
608 // url-scheme://url-host[:url-port]/auth-realm
609 //
610 // Be careful when changing this function, since you could make existing
611 // saved logins un-retrievable.
612 std::string GetSignonRealm(const GURL& url,
613 const net::AuthChallengeInfo& auth_info) {
614 std::string signon_realm;
615 if (auth_info.is_proxy) {
616 signon_realm = auth_info.challenger.ToString();
617 signon_realm.append("/");
618 } else {
619 // Take scheme, host, and port from the url.
620 signon_realm = url.GetOrigin().spec();
621 // This ends with a "/".
622 }
623 signon_realm.append(auth_info.realm);
624 return signon_realm;
625 }
OLDNEW
« no previous file with comments | « chrome/browser/ui/login/login_prompt.h ('k') | chrome/browser/ui/views/login_prompt_views.cc » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698