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#include "base/bind.h"
8#include "base/logging.h"
9#include "base/strings/utf_string_conversions.h"
10#include "content/public/browser/browser_thread.h"
11#include "content/public/browser/resource_dispatcher_host.h"
12#include "net/base/auth.h"
13#include "net/url_request/url_request.h"
14#include "ui/gfx/text_elider.h"
15
16namespace content {
17
18ShellLoginDialog::ShellLoginDialog(
19    net::AuthChallengeInfo* auth_info,
20    net::URLRequest* request) : auth_info_(auth_info),
21                                request_(request) {
22  DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO));
23  BrowserThread::PostTask(
24      BrowserThread::UI, FROM_HERE,
25      base::Bind(&ShellLoginDialog::PrepDialog, this,
26                 base::ASCIIToUTF16(auth_info->challenger.ToString()),
27                 base::UTF8ToUTF16(auth_info->realm)));
28}
29
30void ShellLoginDialog::OnRequestCancelled() {
31  DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO));
32  BrowserThread::PostTask(
33      BrowserThread::UI, FROM_HERE,
34      base::Bind(&ShellLoginDialog::PlatformRequestCancelled, this));
35}
36
37void ShellLoginDialog::UserAcceptedAuth(const base::string16& username,
38                                        const base::string16& password) {
39  DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
40  BrowserThread::PostTask(
41      BrowserThread::IO, FROM_HERE,
42      base::Bind(&ShellLoginDialog::SendAuthToRequester, this,
43                 true, username, password));
44}
45
46void ShellLoginDialog::UserCancelledAuth() {
47  DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
48  BrowserThread::PostTask(
49      BrowserThread::IO, FROM_HERE,
50      base::Bind(&ShellLoginDialog::SendAuthToRequester, this,
51                 false, base::string16(), base::string16()));
52  BrowserThread::PostTask(
53      BrowserThread::UI, FROM_HERE,
54      base::Bind(&ShellLoginDialog::PlatformCleanUp, this));
55}
56
57ShellLoginDialog::~ShellLoginDialog() {
58  // Cannot post any tasks here; this object is going away and cannot be
59  // referenced/dereferenced.
60}
61
62#if !defined(OS_MACOSX)
63// Bogus implementations for linking. They are never called because
64// ResourceDispatcherHostDelegate::CreateLoginDelegate returns NULL.
65// TODO: implement ShellLoginDialog for other platforms, drop this #if
66void ShellLoginDialog::PlatformCreateDialog(const base::string16& message) {}
67void ShellLoginDialog::PlatformCleanUp() {}
68void ShellLoginDialog::PlatformRequestCancelled() {}
69#endif
70
71void ShellLoginDialog::PrepDialog(const base::string16& host,
72                                  const base::string16& realm) {
73  DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
74  // The realm is controlled by the remote server, so there is no reason to
75  // believe it is of a reasonable length.
76  base::string16 elided_realm;
77  gfx::ElideString(realm, 120, &elided_realm);
78
79  base::string16 explanation =
80      base::ASCIIToUTF16("The server ") + host +
81      base::ASCIIToUTF16(" requires a username and password.");
82
83  if (!elided_realm.empty()) {
84    explanation += base::ASCIIToUTF16(" The server says: ");
85    explanation += elided_realm;
86    explanation += base::ASCIIToUTF16(".");
87  }
88
89  PlatformCreateDialog(explanation);
90}
91
92void ShellLoginDialog::SendAuthToRequester(bool success,
93                                           const base::string16& username,
94                                           const base::string16& password) {
95  DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO));
96  if (success)
97    request_->SetAuth(net::AuthCredentials(username, password));
98  else
99    request_->CancelAuth();
100  ResourceDispatcherHost::Get()->ClearLoginDelegateForRequest(request_);
101
102  BrowserThread::PostTask(
103      BrowserThread::UI, FROM_HERE,
104      base::Bind(&ShellLoginDialog::PlatformCleanUp, this));
105}
106
107}  // namespace content
108