Update To 11.40.268.0
[platform/framework/web/crosswalk.git] / src / chrome / browser / password_manager / chrome_password_manager_client.cc
1 // Copyright 2014 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/password_manager/chrome_password_manager_client.h"
6
7 #include "base/bind_helpers.h"
8 #include "base/command_line.h"
9 #include "base/memory/singleton.h"
10 #include "base/metrics/histogram.h"
11 #include "base/strings/string16.h"
12 #include "base/strings/utf_string_conversions.h"
13 #include "chrome/browser/browsing_data/browsing_data_helper.h"
14 #include "chrome/browser/password_manager/password_manager_util.h"
15 #include "chrome/browser/password_manager/password_store_factory.h"
16 #include "chrome/browser/password_manager/save_password_infobar_delegate.h"
17 #include "chrome/browser/password_manager/sync_metrics.h"
18 #include "chrome/browser/profiles/profile.h"
19 #include "chrome/browser/sync/profile_sync_service.h"
20 #include "chrome/browser/sync/profile_sync_service_factory.h"
21 #include "chrome/browser/ui/autofill/password_generation_popup_controller_impl.h"
22 #include "chrome/browser/ui/passwords/manage_passwords_ui_controller.h"
23 #include "chrome/common/chrome_switches.h"
24 #include "chrome/common/chrome_version_info.h"
25 #include "chrome/common/url_constants.h"
26 #include "components/autofill/content/common/autofill_messages.h"
27 #include "components/autofill/core/browser/password_generator.h"
28 #include "components/autofill/core/common/password_form.h"
29 #include "components/password_manager/content/browser/password_manager_internals_service_factory.h"
30 #include "components/password_manager/content/common/credential_manager_messages.h"
31 #include "components/password_manager/content/common/credential_manager_types.h"
32 #include "components/password_manager/core/browser/log_receiver.h"
33 #include "components/password_manager/core/browser/password_form_manager.h"
34 #include "components/password_manager/core/browser/password_manager.h"
35 #include "components/password_manager/core/browser/password_manager_internals_service.h"
36 #include "components/password_manager/core/browser/password_manager_metrics_util.h"
37 #include "components/password_manager/core/common/password_manager_switches.h"
38 #include "content/public/browser/navigation_entry.h"
39 #include "content/public/browser/render_view_host.h"
40 #include "content/public/browser/web_contents.h"
41 #include "google_apis/gaia/gaia_urls.h"
42 #include "net/base/url_util.h"
43 #include "third_party/re2/re2/re2.h"
44
45 #if defined(OS_ANDROID)
46 #include "chrome/browser/password_manager/generated_password_saved_infobar_delegate_android.h"
47 #endif
48
49 using password_manager::PasswordManagerInternalsService;
50 using password_manager::PasswordManagerInternalsServiceFactory;
51
52 DEFINE_WEB_CONTENTS_USER_DATA_KEY(ChromePasswordManagerClient);
53
54 // static
55 void ChromePasswordManagerClient::CreateForWebContentsWithAutofillClient(
56     content::WebContents* contents,
57     autofill::AutofillClient* autofill_client) {
58   if (FromWebContents(contents))
59     return;
60
61   contents->SetUserData(
62       UserDataKey(),
63       new ChromePasswordManagerClient(contents, autofill_client));
64 }
65
66 ChromePasswordManagerClient::ChromePasswordManagerClient(
67     content::WebContents* web_contents,
68     autofill::AutofillClient* autofill_client)
69     : content::WebContentsObserver(web_contents),
70       profile_(Profile::FromBrowserContext(web_contents->GetBrowserContext())),
71       driver_(web_contents, this, autofill_client),
72       credential_manager_dispatcher_(web_contents, this),
73       observer_(NULL),
74       can_use_log_router_(false),
75       autofill_sync_state_(ALLOW_SYNC_CREDENTIALS),
76       sync_credential_was_filtered_(false) {
77   PasswordManagerInternalsService* service =
78       PasswordManagerInternalsServiceFactory::GetForBrowserContext(profile_);
79   if (service)
80     can_use_log_router_ = service->RegisterClient(this);
81   SetUpAutofillSyncState();
82 }
83
84 ChromePasswordManagerClient::~ChromePasswordManagerClient() {
85   PasswordManagerInternalsService* service =
86       PasswordManagerInternalsServiceFactory::GetForBrowserContext(profile_);
87   if (service)
88     service->UnregisterClient(this);
89 }
90
91 bool ChromePasswordManagerClient::IsAutomaticPasswordSavingEnabled() const {
92   return CommandLine::ForCurrentProcess()->HasSwitch(
93       password_manager::switches::kEnableAutomaticPasswordSaving) &&
94          chrome::VersionInfo::GetChannel() ==
95              chrome::VersionInfo::CHANNEL_UNKNOWN;
96 }
97
98 bool ChromePasswordManagerClient::IsPasswordManagerEnabledForCurrentPage()
99     const {
100   DCHECK(web_contents());
101   content::NavigationEntry* entry =
102       web_contents()->GetController().GetLastCommittedEntry();
103   if (!entry) {
104     // TODO(gcasto): Determine if fix for crbug.com/388246 is relevant here.
105     return true;
106   }
107
108   // Disable the password manager for online password management.
109   if (IsURLPasswordWebsiteReauth(entry->GetURL()))
110     return false;
111
112   if (EnabledForSyncSignin())
113     return true;
114
115   // Do not fill nor save password when a user is signing in for sync. This
116   // is because users need to remember their password if they are syncing as
117   // this is effectively their master password.
118   return entry->GetURL().host() != chrome::kChromeUIChromeSigninHost;
119 }
120
121 bool ChromePasswordManagerClient::ShouldFilterAutofillResult(
122     const autofill::PasswordForm& form) {
123   if (!IsSyncAccountCredential(base::UTF16ToUTF8(form.username_value),
124                                form.signon_realm))
125     return false;
126
127   if (autofill_sync_state_ == DISALLOW_SYNC_CREDENTIALS) {
128     sync_credential_was_filtered_ = true;
129     return true;
130   }
131
132   if (autofill_sync_state_ == DISALLOW_SYNC_CREDENTIALS_FOR_REAUTH &&
133       LastLoadWasTransactionalReauthPage()) {
134     sync_credential_was_filtered_ = true;
135     return true;
136   }
137
138   return false;
139 }
140
141 std::string ChromePasswordManagerClient::GetSyncUsername() const {
142   return password_manager_sync_metrics::GetSyncUsername(profile_);
143 }
144
145 bool ChromePasswordManagerClient::IsSyncAccountCredential(
146     const std::string& username, const std::string& origin) const {
147   return password_manager_sync_metrics::IsSyncAccountCredential(
148       profile_, username, origin);
149 }
150
151 void ChromePasswordManagerClient::AutofillResultsComputed() {
152   UMA_HISTOGRAM_BOOLEAN("PasswordManager.SyncCredentialFiltered",
153                         sync_credential_was_filtered_);
154   sync_credential_was_filtered_ = false;
155 }
156
157 bool ChromePasswordManagerClient::PromptUserToSavePassword(
158     scoped_ptr<password_manager::PasswordFormManager> form_to_save) {
159   // Save password infobar and the password bubble prompts in case of
160   // "webby" URLs and do not prompt in case of "non-webby" URLS (e.g. file://).
161   if (!BrowsingDataHelper::IsWebScheme(
162       web_contents()->GetLastCommittedURL().scheme())) {
163     return false;
164   }
165
166   if (IsTheHotNewBubbleUIEnabled()) {
167     ManagePasswordsUIController* manage_passwords_ui_controller =
168         ManagePasswordsUIController::FromWebContents(web_contents());
169     manage_passwords_ui_controller->OnPasswordSubmitted(form_to_save.Pass());
170   } else {
171     std::string uma_histogram_suffix(
172         password_manager::metrics_util::GroupIdToString(
173             password_manager::metrics_util::MonitoredDomainGroupId(
174                 form_to_save->realm(), GetPrefs())));
175     SavePasswordInfoBarDelegate::Create(
176         web_contents(), form_to_save.Pass(), uma_histogram_suffix);
177   }
178   return true;
179 }
180
181 void ChromePasswordManagerClient::AutomaticPasswordSave(
182     scoped_ptr<password_manager::PasswordFormManager> saved_form) {
183 #if defined(OS_ANDROID)
184   GeneratedPasswordSavedInfoBarDelegateAndroid::Create(web_contents());
185 #else
186   if (IsTheHotNewBubbleUIEnabled()) {
187     ManagePasswordsUIController* manage_passwords_ui_controller =
188         ManagePasswordsUIController::FromWebContents(web_contents());
189     manage_passwords_ui_controller->OnAutomaticPasswordSave(
190         saved_form.Pass());
191   }
192 #endif
193 }
194
195 void ChromePasswordManagerClient::PasswordWasAutofilled(
196     const autofill::PasswordFormMap& best_matches) const {
197   ManagePasswordsUIController* manage_passwords_ui_controller =
198       ManagePasswordsUIController::FromWebContents(web_contents());
199   if (manage_passwords_ui_controller && IsTheHotNewBubbleUIEnabled())
200     manage_passwords_ui_controller->OnPasswordAutofilled(best_matches);
201 }
202
203 void ChromePasswordManagerClient::PasswordAutofillWasBlocked(
204     const autofill::PasswordFormMap& best_matches) const {
205   ManagePasswordsUIController* controller =
206       ManagePasswordsUIController::FromWebContents(web_contents());
207   if (controller && IsTheHotNewBubbleUIEnabled())
208     controller->OnBlacklistBlockedAutofill(best_matches);
209 }
210
211 void ChromePasswordManagerClient::HidePasswordGenerationPopup() {
212   if (popup_controller_)
213     popup_controller_->HideAndDestroy();
214 }
215
216 PrefService* ChromePasswordManagerClient::GetPrefs() {
217   return profile_->GetPrefs();
218 }
219
220 password_manager::PasswordStore*
221 ChromePasswordManagerClient::GetPasswordStore() {
222   // Always use EXPLICIT_ACCESS as the password manager checks IsOffTheRecord
223   // itself when it shouldn't access the PasswordStore.
224   // TODO(gcasto): Is is safe to change this to Profile::IMPLICIT_ACCESS?
225   return PasswordStoreFactory::GetForProfile(profile_, Profile::EXPLICIT_ACCESS)
226       .get();
227 }
228
229 password_manager::PasswordManagerDriver*
230 ChromePasswordManagerClient::GetDriver() {
231   return &driver_;
232 }
233
234 base::FieldTrial::Probability
235 ChromePasswordManagerClient::GetProbabilityForExperiment(
236     const std::string& experiment_name) {
237   base::FieldTrial::Probability enabled_probability = 0;
238   if (experiment_name ==
239       password_manager::PasswordManager::kOtherPossibleUsernamesExperiment) {
240     switch (chrome::VersionInfo::GetChannel()) {
241       case chrome::VersionInfo::CHANNEL_DEV:
242       case chrome::VersionInfo::CHANNEL_BETA:
243         enabled_probability = 50;
244         break;
245       default:
246         break;
247     }
248   }
249   return enabled_probability;
250 }
251
252 bool ChromePasswordManagerClient::IsPasswordSyncEnabled(
253     password_manager::CustomPassphraseState state) {
254   ProfileSyncService* sync_service =
255       ProfileSyncServiceFactory::GetForProfile(profile_);
256   if (sync_service && sync_service->HasSyncSetupCompleted() &&
257       sync_service->SyncActive() &&
258       sync_service->GetActiveDataTypes().Has(syncer::PASSWORDS)) {
259     if (sync_service->IsUsingSecondaryPassphrase()) {
260       return state == password_manager::ONLY_CUSTOM_PASSPHRASE;
261     } else {
262       return state == password_manager::WITHOUT_CUSTOM_PASSPHRASE;
263     }
264   }
265   return false;
266 }
267
268 void ChromePasswordManagerClient::OnLogRouterAvailabilityChanged(
269     bool router_can_be_used) {
270   if (can_use_log_router_ == router_can_be_used)
271     return;
272   can_use_log_router_ = router_can_be_used;
273
274   NotifyRendererOfLoggingAvailability();
275 }
276
277 void ChromePasswordManagerClient::LogSavePasswordProgress(
278     const std::string& text) {
279   if (!IsLoggingActive())
280     return;
281   PasswordManagerInternalsService* service =
282       PasswordManagerInternalsServiceFactory::GetForBrowserContext(profile_);
283   if (service)
284     service->ProcessLog(text);
285 }
286
287 bool ChromePasswordManagerClient::IsLoggingActive() const {
288   // WebUI tabs do not need to log password saving progress. In particular, the
289   // internals page itself should not send any logs.
290   return can_use_log_router_ && !web_contents()->GetWebUI();
291 }
292
293 // static
294 password_manager::PasswordGenerationManager*
295 ChromePasswordManagerClient::GetGenerationManagerFromWebContents(
296     content::WebContents* contents) {
297   ChromePasswordManagerClient* client =
298       ChromePasswordManagerClient::FromWebContents(contents);
299   if (!client)
300     return NULL;
301   return client->GetDriver()->GetPasswordGenerationManager();
302 }
303
304 // static
305 password_manager::PasswordManager*
306 ChromePasswordManagerClient::GetManagerFromWebContents(
307     content::WebContents* contents) {
308   ChromePasswordManagerClient* client =
309       ChromePasswordManagerClient::FromWebContents(contents);
310   if (!client)
311     return NULL;
312   return client->GetDriver()->GetPasswordManager();
313 }
314
315 void ChromePasswordManagerClient::SetTestObserver(
316     autofill::PasswordGenerationPopupObserver* observer) {
317   observer_ = observer;
318 }
319
320 bool ChromePasswordManagerClient::OnMessageReceived(
321     const IPC::Message& message) {
322   bool handled = true;
323   IPC_BEGIN_MESSAGE_MAP(ChromePasswordManagerClient, message)
324     // Autofill messages:
325     IPC_MESSAGE_HANDLER(AutofillHostMsg_ShowPasswordGenerationPopup,
326                         ShowPasswordGenerationPopup)
327     IPC_MESSAGE_HANDLER(AutofillHostMsg_ShowPasswordEditingPopup,
328                         ShowPasswordEditingPopup)
329     IPC_MESSAGE_HANDLER(AutofillHostMsg_HidePasswordGenerationPopup,
330                         HidePasswordGenerationPopup)
331     IPC_MESSAGE_HANDLER(AutofillHostMsg_PasswordAutofillAgentConstructed,
332                         NotifyRendererOfLoggingAvailability)
333
334     // Default:
335     IPC_MESSAGE_UNHANDLED(handled = false)
336   IPC_END_MESSAGE_MAP()
337   return handled;
338 }
339
340 gfx::RectF ChromePasswordManagerClient::GetBoundsInScreenSpace(
341     const gfx::RectF& bounds) {
342   gfx::Rect client_area = web_contents()->GetContainerBounds();
343   return bounds + client_area.OffsetFromOrigin();
344 }
345
346 void ChromePasswordManagerClient::ShowPasswordGenerationPopup(
347     const gfx::RectF& bounds,
348     int max_length,
349     const autofill::PasswordForm& form) {
350   // TODO(gcasto): Validate data in PasswordForm.
351
352   gfx::RectF element_bounds_in_screen_space = GetBoundsInScreenSpace(bounds);
353
354   popup_controller_ =
355       autofill::PasswordGenerationPopupControllerImpl::GetOrCreate(
356           popup_controller_,
357           element_bounds_in_screen_space,
358           form,
359           max_length,
360           driver_.GetPasswordManager(),
361           observer_,
362           web_contents(),
363           web_contents()->GetNativeView());
364   popup_controller_->Show(true /* display_password */);
365 }
366
367 void ChromePasswordManagerClient::ShowPasswordEditingPopup(
368     const gfx::RectF& bounds,
369     const autofill::PasswordForm& form) {
370   gfx::RectF element_bounds_in_screen_space = GetBoundsInScreenSpace(bounds);
371   popup_controller_ =
372       autofill::PasswordGenerationPopupControllerImpl::GetOrCreate(
373           popup_controller_,
374           element_bounds_in_screen_space,
375           form,
376           0,  // Unspecified max length.
377           driver_.GetPasswordManager(),
378           observer_,
379           web_contents(),
380           web_contents()->GetNativeView());
381   popup_controller_->Show(false /* display_password */);
382 }
383
384 void ChromePasswordManagerClient::NotifyRendererOfLoggingAvailability() {
385   if (!web_contents())
386     return;
387
388   web_contents()->GetRenderViewHost()->Send(new AutofillMsg_SetLoggingState(
389       web_contents()->GetRenderViewHost()->GetRoutingID(),
390       can_use_log_router_));
391 }
392
393 bool ChromePasswordManagerClient::LastLoadWasTransactionalReauthPage() const {
394   DCHECK(web_contents());
395   content::NavigationEntry* entry =
396       web_contents()->GetController().GetLastCommittedEntry();
397   if (!entry)
398     return false;
399
400   if (entry->GetURL().GetOrigin() !=
401       GaiaUrls::GetInstance()->gaia_url().GetOrigin())
402     return false;
403
404   // "rart" is the transactional reauth paramter.
405   std::string ignored_value;
406   return net::GetValueForKeyInQuery(entry->GetURL(),
407                                     "rart",
408                                     &ignored_value);
409 }
410
411 bool ChromePasswordManagerClient::IsURLPasswordWebsiteReauth(
412     const GURL& url) const {
413   if (url.GetOrigin() != GaiaUrls::GetInstance()->gaia_url().GetOrigin())
414     return false;
415
416   // "rart" param signals this page is for transactional reauth.
417   std::string param_value;
418   if (!net::GetValueForKeyInQuery(url, "rart", &param_value))
419     return false;
420
421   // Check the "continue" param to see if this reauth page is for the passwords
422   // website.
423   param_value.clear();
424   if (!net::GetValueForKeyInQuery(url, "continue", &param_value))
425     return false;
426
427   // All password sites, including test sites, have autofilling disabled.
428   CR_DEFINE_STATIC_LOCAL(RE2, account_dashboard_pattern,
429                          ("passwords(-([a-z-]+\\.corp))?\\.google\\.com"));
430
431   return RE2::FullMatch(GURL(param_value).host(), account_dashboard_pattern);
432 }
433
434 bool ChromePasswordManagerClient::IsTheHotNewBubbleUIEnabled() {
435 #if !defined(USE_AURA) && !defined(OS_MACOSX)
436   return false;
437 #endif
438   CommandLine* command_line = CommandLine::ForCurrentProcess();
439   if (command_line->HasSwitch(switches::kDisableSavePasswordBubble))
440     return false;
441
442   if (command_line->HasSwitch(switches::kEnableSavePasswordBubble))
443     return true;
444
445   std::string group_name =
446       base::FieldTrialList::FindFullName("PasswordManagerUI");
447
448   // The bubble should be the default case that runs on the bots.
449   return group_name != "Infobar";
450 }
451
452 bool ChromePasswordManagerClient::EnabledForSyncSignin() {
453   CommandLine* command_line = CommandLine::ForCurrentProcess();
454   if (command_line->HasSwitch(
455           password_manager::switches::kDisableManagerForSyncSignin))
456     return false;
457
458   if (command_line->HasSwitch(
459           password_manager::switches::kEnableManagerForSyncSignin))
460     return true;
461
462   // Default is enabled.
463   std::string group_name =
464       base::FieldTrialList::FindFullName("PasswordManagerStateForSyncSignin");
465   return group_name != "Disabled";
466 }
467
468 void ChromePasswordManagerClient::SetUpAutofillSyncState() {
469   std::string group_name =
470       base::FieldTrialList::FindFullName("AutofillSyncCredential");
471
472   CommandLine* command_line = CommandLine::ForCurrentProcess();
473   if (command_line->HasSwitch(
474           password_manager::switches::kAllowAutofillSyncCredential)) {
475     autofill_sync_state_ = ALLOW_SYNC_CREDENTIALS;
476     return;
477   }
478   if (command_line->HasSwitch(
479           password_manager::switches::
480           kDisallowAutofillSyncCredentialForReauth)) {
481     autofill_sync_state_ = DISALLOW_SYNC_CREDENTIALS_FOR_REAUTH;
482     return;
483   }
484   if (command_line->HasSwitch(
485           password_manager::switches::kDisallowAutofillSyncCredential)) {
486     autofill_sync_state_ = DISALLOW_SYNC_CREDENTIALS;
487     return;
488   }
489
490   if (group_name == "DisallowSyncCredentialsForReauth") {
491     autofill_sync_state_ = DISALLOW_SYNC_CREDENTIALS_FOR_REAUTH;
492   } else if (group_name == "DisallowSyncCredentials") {
493       autofill_sync_state_ = DISALLOW_SYNC_CREDENTIALS;
494   } else {
495     // Allow by default.
496     autofill_sync_state_ = ALLOW_SYNC_CREDENTIALS;
497   }
498 }