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