• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 // Copyright (c) 2011 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 "chrome/browser/ui/login/login_prompt.h"
6 
7 #include <string>
8 
9 #include "base/json/json_reader.h"
10 #include "base/utf_string_conversions.h"
11 #include "base/values.h"
12 #include "chrome/browser/profiles/profile.h"
13 #include "chrome/browser/ui/webui/chrome_url_data_manager.h"
14 #include "chrome/browser/ui/webui/constrained_html_ui.h"
15 #include "chrome/browser/ui/webui/html_dialog_ui.h"
16 #include "chrome/common/jstemplate_builder.h"
17 #include "chrome/common/url_constants.h"
18 #include "content/browser/tab_contents/tab_contents.h"
19 #include "grit/browser_resources.h"
20 #include "grit/generated_resources.h"
21 #include "ui/base/l10n/l10n_util.h"
22 #include "ui/base/resource/resource_bundle.h"
23 #include "ui/gfx/size.h"
24 
25 class LoginHandlerSource : public ChromeURLDataManager::DataSource {
26  public:
LoginHandlerSource()27   LoginHandlerSource()
28       : DataSource(chrome::kChromeUIHttpAuthHost, MessageLoop::current()) {}
29 
StartDataRequest(const std::string & path,bool is_off_the_record,int request_id)30   virtual void StartDataRequest(const std::string& path,
31                                 bool is_off_the_record,
32                                 int request_id) {
33     DictionaryValue dict;
34     dict.SetString("username",
35                    l10n_util::GetStringUTF16(IDS_LOGIN_DIALOG_USERNAME_FIELD));
36     dict.SetString("password",
37                    l10n_util::GetStringUTF16(IDS_LOGIN_DIALOG_PASSWORD_FIELD));
38     dict.SetString("signin",
39                    l10n_util::GetStringUTF16(IDS_LOGIN_DIALOG_OK_BUTTON_LABEL));
40     dict.SetString("cancel", l10n_util::GetStringUTF16(IDS_CANCEL));
41 
42     SetFontAndTextDirection(&dict);
43 
44     const base::StringPiece html(
45         ResourceBundle::GetSharedInstance().GetRawDataResource(
46             IDR_HTTP_AUTH_HTML));
47     std::string response = jstemplate_builder::GetI18nTemplateHtml(html, &dict);
48 
49     // Send the response.
50     scoped_refptr<RefCountedBytes> html_bytes(new RefCountedBytes);
51     html_bytes->data.resize(response.size());
52     std::copy(response.begin(), response.end(), html_bytes->data.begin());
53     SendResponse(request_id, html_bytes);
54   }
55 
GetMimeType(const std::string & path) const56   virtual std::string GetMimeType(const std::string& path) const {
57     return "text/html";
58   }
59 
RegisterDataSource(Profile * profile)60   static void RegisterDataSource(Profile *profile) {
61     ChromeURLDataManager* url_manager = profile->GetChromeURLDataManager();
62     LoginHandlerSource *source = new LoginHandlerSource();
63     url_manager->AddDataSource(source);
64   }
65 
66  private:
~LoginHandlerSource()67   virtual ~LoginHandlerSource() {}
68 
69   DISALLOW_COPY_AND_ASSIGN(LoginHandlerSource);
70 };
71 
72 class LoginHandlerHtml;
73 
74 class LoginHandlerHtmlDelegate : public HtmlDialogUIDelegate,
75                                  public WebUIMessageHandler {
76  public:
LoginHandlerHtmlDelegate(LoginHandlerHtml * login_handler,TabContents * tab_contents,const string16 explanation)77   LoginHandlerHtmlDelegate(LoginHandlerHtml *login_handler,
78                            TabContents *tab_contents,
79                            const string16 explanation)
80       : login_handler_(login_handler),
81         tab_contents_(tab_contents),
82         explanation_(UTF16ToUTF8(explanation)),
83         closed_(false),
84         has_autofill_(false),
85         ready_for_autofill_(false) {
86   }
87 
88   // HtmlDialogUIDelegate methods:
IsDialogModal() const89   virtual bool IsDialogModal() const {
90     return true;
91   }
92 
GetDialogTitle() const93   virtual std::wstring GetDialogTitle() const {
94     return UTF16ToWide(l10n_util::GetStringUTF16(IDS_LOGIN_DIALOG_TITLE));
95   }
96 
GetDialogContentURL() const97   virtual GURL GetDialogContentURL() const {
98     return GURL(chrome::kChromeUIHttpAuthURL);
99   }
100 
GetWebUIMessageHandlers(std::vector<WebUIMessageHandler * > * handlers) const101   virtual void GetWebUIMessageHandlers(
102       std::vector<WebUIMessageHandler*>* handlers) const {
103     const WebUIMessageHandler* handler = this;
104     handlers->push_back(const_cast<WebUIMessageHandler*>(handler));
105   }
106 
GetDialogSize(gfx::Size * size) const107   virtual void GetDialogSize(gfx::Size* size) const {
108     size->set_width(kDialogWidth);
109     size->set_height(kDialogHeight);
110   }
111 
GetDialogArgs() const112   virtual std::string GetDialogArgs() const {
113     return explanation_;
114   }
115 
116   virtual void OnDialogClosed(const std::string& json_retval);
117 
OnCloseContents(TabContents * source,bool * out_close_dialog)118   virtual void OnCloseContents(TabContents* source, bool* out_close_dialog) {}
119 
ShouldShowDialogTitle() const120   virtual bool ShouldShowDialogTitle() const {
121     return true;
122   }
123 
124   // WebUIMessageHandler method:
RegisterMessages()125   virtual void RegisterMessages() {
126     web_ui_->RegisterMessageCallback(
127         "GetAutofill",
128         NewCallback(this, &LoginHandlerHtmlDelegate::GetAutofill));
129   }
130 
131   void ShowAutofillData(const std::wstring& username,
132                         const std::wstring& password);
133 
134  private:
135   // Send autofill data to HTML once the dialog is ready and the data is
136   // available.
137   void SendAutofillData();
138 
139   // Handle the request for autofill data from HTML.
GetAutofill(const ListValue * args)140   void GetAutofill(const ListValue* args) {
141     ready_for_autofill_ = true;
142     SendAutofillData();
143   }
144 
145   LoginHandlerHtml *login_handler_;
146   TabContents *tab_contents_;
147   std::string explanation_;
148   bool closed_;
149 
150   bool has_autofill_;
151   bool ready_for_autofill_;
152   std::string autofill_username_;
153   std::string autofill_password_;
154 
155   static const int kDialogWidth = 400;
156   static const int kDialogHeight = 130;
157 
158   DISALLOW_COPY_AND_ASSIGN(LoginHandlerHtmlDelegate);
159 };
160 
161 class LoginHandlerHtml : public LoginHandler {
162  public:
LoginHandlerHtml(net::AuthChallengeInfo * auth_info,net::URLRequest * request)163   LoginHandlerHtml(net::AuthChallengeInfo* auth_info, net::URLRequest* request)
164       : LoginHandler(auth_info, request),
165         delegate_(NULL) {
166   }
167 
168   // LoginModelObserver method:
OnAutofillDataAvailable(const std::wstring & username,const std::wstring & password)169   virtual void OnAutofillDataAvailable(const std::wstring& username,
170                                        const std::wstring& password) {
171     if (delegate_)
172       delegate_->ShowAutofillData(username, password);
173   }
174 
175   // LoginHandler method:
176   virtual void BuildViewForPasswordManager(PasswordManager* manager,
177                                            const string16& explanation);
178 
179   friend class LoginHandlerHtmlDelegate;
180 
181  protected:
~LoginHandlerHtml()182   virtual ~LoginHandlerHtml() {}
183 
184  private:
185   LoginHandlerHtmlDelegate *delegate_;
186 
FreeAndRelease()187   void FreeAndRelease() {
188     SetDialog(NULL);
189     SetModel(NULL);
190     ReleaseSoon();
191   }
192 
193   DISALLOW_COPY_AND_ASSIGN(LoginHandlerHtml);
194 };
195 
OnDialogClosed(const std::string & json_retval)196 void LoginHandlerHtmlDelegate::OnDialogClosed(const std::string& json_retval) {
197   if (closed_)
198     return;
199   closed_ = true;
200 
201   scoped_ptr<Value> parsed_value(base::JSONReader::Read(json_retval, false));
202 
203   if (!parsed_value.get() || !parsed_value->IsType(Value::TYPE_DICTIONARY)) {
204     login_handler_->CancelAuth();
205   } else {
206     DictionaryValue* res = static_cast<DictionaryValue*>(parsed_value.get());
207     string16 username;
208     string16 password;
209 
210     if (!res->GetString("username", &username) ||
211         !res->GetString("password", &password)) {
212       login_handler_->CancelAuth();
213     } else {
214       login_handler_->SetAuth(username, password);
215     }
216   }
217 
218   login_handler_->FreeAndRelease();
219 }
220 
ShowAutofillData(const std::wstring & username,const std::wstring & password)221 void LoginHandlerHtmlDelegate::ShowAutofillData(const std::wstring& username,
222                                                 const std::wstring& password) {
223   autofill_username_ = WideToUTF8(username);
224   autofill_password_ = WideToUTF8(password);
225   has_autofill_ = true;
226   SendAutofillData();
227 }
228 
SendAutofillData()229 void LoginHandlerHtmlDelegate::SendAutofillData() {
230   if (!closed_ && web_ui_ && has_autofill_ && ready_for_autofill_) {
231     StringValue username_v(autofill_username_);
232     StringValue password_v(autofill_password_);
233     web_ui_->CallJavascriptFunction("setAutofillCredentials",
234                                     username_v, password_v);
235   }
236 }
237 
BuildViewForPasswordManager(PasswordManager * manager,const string16 & explanation)238 void LoginHandlerHtml::BuildViewForPasswordManager(
239     PasswordManager* manager, const string16& explanation) {
240   DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
241 
242   LOG(INFO) << "BuildViewForPasswordManager";
243 
244   TabContents* tab_contents = GetTabContentsForLogin();
245   LoginHandlerSource::RegisterDataSource(tab_contents->profile());
246   delegate_ = new LoginHandlerHtmlDelegate(this, tab_contents, explanation);
247   ConstrainedWindow* dialog = ConstrainedHtmlUI::CreateConstrainedHtmlDialog(
248       tab_contents->profile(), delegate_, tab_contents);
249 
250   SetModel(manager);
251   SetDialog(dialog);
252 
253   NotifyAuthNeeded();
254 }
255 
256 // static
Create(net::AuthChallengeInfo * auth_info,net::URLRequest * request)257 LoginHandler* LoginHandler::Create(net::AuthChallengeInfo* auth_info,
258                                    net::URLRequest* request) {
259   return new LoginHandlerHtml(auth_info, request);
260 }
261