Home | History | Annotate | Download | only in password_manager
      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 "chrome/browser/password_manager/password_manager_util.h"
     12 #include "chrome/browser/password_manager/password_store_factory.h"
     13 #include "chrome/browser/password_manager/save_password_infobar_delegate.h"
     14 #include "chrome/browser/profiles/profile.h"
     15 #include "chrome/browser/sync/profile_sync_service.h"
     16 #include "chrome/browser/sync/profile_sync_service_factory.h"
     17 #include "chrome/browser/ui/autofill/password_generation_popup_controller_impl.h"
     18 #include "chrome/browser/ui/passwords/manage_passwords_ui_controller.h"
     19 #include "chrome/common/chrome_switches.h"
     20 #include "chrome/common/chrome_version_info.h"
     21 #include "components/autofill/content/common/autofill_messages.h"
     22 #include "components/autofill/core/browser/password_generator.h"
     23 #include "components/autofill/core/common/password_form.h"
     24 #include "components/password_manager/content/browser/password_manager_internals_service_factory.h"
     25 #include "components/password_manager/core/browser/log_receiver.h"
     26 #include "components/password_manager/core/browser/password_form_manager.h"
     27 #include "components/password_manager/core/browser/password_manager.h"
     28 #include "components/password_manager/core/browser/password_manager_internals_service.h"
     29 #include "components/password_manager/core/browser/password_manager_metrics_util.h"
     30 #include "components/password_manager/core/common/password_manager_switches.h"
     31 #include "content/public/browser/render_view_host.h"
     32 #include "content/public/browser/web_contents.h"
     33 
     34 #if defined(OS_ANDROID)
     35 #include "chrome/browser/android/password_authentication_manager.h"
     36 #endif  // OS_ANDROID
     37 
     38 using password_manager::PasswordManagerInternalsService;
     39 using password_manager::PasswordManagerInternalsServiceFactory;
     40 
     41 DEFINE_WEB_CONTENTS_USER_DATA_KEY(ChromePasswordManagerClient);
     42 
     43 // static
     44 void ChromePasswordManagerClient::CreateForWebContentsWithAutofillClient(
     45     content::WebContents* contents,
     46     autofill::AutofillClient* autofill_client) {
     47   if (FromWebContents(contents))
     48     return;
     49 
     50   contents->SetUserData(
     51       UserDataKey(),
     52       new ChromePasswordManagerClient(contents, autofill_client));
     53 }
     54 
     55 ChromePasswordManagerClient::ChromePasswordManagerClient(
     56     content::WebContents* web_contents,
     57     autofill::AutofillClient* autofill_client)
     58     : content::WebContentsObserver(web_contents),
     59       profile_(Profile::FromBrowserContext(web_contents->GetBrowserContext())),
     60       driver_(web_contents, this, autofill_client),
     61       observer_(NULL),
     62       weak_factory_(this),
     63       can_use_log_router_(false) {
     64   PasswordManagerInternalsService* service =
     65       PasswordManagerInternalsServiceFactory::GetForBrowserContext(profile_);
     66   if (service)
     67     can_use_log_router_ = service->RegisterClient(this);
     68 }
     69 
     70 ChromePasswordManagerClient::~ChromePasswordManagerClient() {
     71   PasswordManagerInternalsService* service =
     72       PasswordManagerInternalsServiceFactory::GetForBrowserContext(profile_);
     73   if (service)
     74     service->UnregisterClient(this);
     75 }
     76 
     77 bool ChromePasswordManagerClient::IsAutomaticPasswordSavingEnabled() const {
     78   return CommandLine::ForCurrentProcess()->HasSwitch(
     79              password_manager::switches::kEnableAutomaticPasswordSaving) &&
     80          chrome::VersionInfo::GetChannel() ==
     81              chrome::VersionInfo::CHANNEL_UNKNOWN;
     82 }
     83 
     84 void ChromePasswordManagerClient::PromptUserToSavePassword(
     85     password_manager::PasswordFormManager* form_to_save) {
     86   if (IsTheHotNewBubbleUIEnabled()) {
     87     ManagePasswordsUIController* manage_passwords_ui_controller =
     88         ManagePasswordsUIController::FromWebContents(web_contents());
     89     manage_passwords_ui_controller->OnPasswordSubmitted(form_to_save);
     90   } else {
     91     std::string uma_histogram_suffix(
     92         password_manager::metrics_util::GroupIdToString(
     93             password_manager::metrics_util::MonitoredDomainGroupId(
     94                 form_to_save->realm(), GetPrefs())));
     95     SavePasswordInfoBarDelegate::Create(
     96         web_contents(), form_to_save, uma_histogram_suffix);
     97   }
     98 }
     99 
    100 void ChromePasswordManagerClient::PasswordWasAutofilled(
    101     const autofill::PasswordFormMap& best_matches) const {
    102   ManagePasswordsUIController* manage_passwords_ui_controller =
    103       ManagePasswordsUIController::FromWebContents(web_contents());
    104   if (manage_passwords_ui_controller && IsTheHotNewBubbleUIEnabled())
    105     manage_passwords_ui_controller->OnPasswordAutofilled(best_matches);
    106 }
    107 
    108 void ChromePasswordManagerClient::PasswordAutofillWasBlocked(
    109     const autofill::PasswordFormMap& best_matches) const {
    110   ManagePasswordsUIController* controller =
    111       ManagePasswordsUIController::FromWebContents(web_contents());
    112   if (controller && IsTheHotNewBubbleUIEnabled())
    113     controller->OnBlacklistBlockedAutofill(best_matches);
    114 }
    115 
    116 void ChromePasswordManagerClient::AuthenticateAutofillAndFillForm(
    117       scoped_ptr<autofill::PasswordFormFillData> fill_data) {
    118 #if defined(OS_ANDROID)
    119   PasswordAuthenticationManager::AuthenticatePasswordAutofill(
    120       web_contents(),
    121       base::Bind(&ChromePasswordManagerClient::CommitFillPasswordForm,
    122                  weak_factory_.GetWeakPtr(),
    123                  base::Owned(fill_data.release())));
    124 #else
    125   // Additional authentication is currently only available for Android, so all
    126   // other plaftorms should just fill the password form directly.
    127   CommitFillPasswordForm(fill_data.get());
    128 #endif  // OS_ANDROID
    129 }
    130 
    131 void ChromePasswordManagerClient::HidePasswordGenerationPopup() {
    132   if (popup_controller_)
    133     popup_controller_->HideAndDestroy();
    134 }
    135 
    136 PrefService* ChromePasswordManagerClient::GetPrefs() {
    137   return profile_->GetPrefs();
    138 }
    139 
    140 password_manager::PasswordStore*
    141 ChromePasswordManagerClient::GetPasswordStore() {
    142   // Always use EXPLICIT_ACCESS as the password manager checks IsOffTheRecord
    143   // itself when it shouldn't access the PasswordStore.
    144   // TODO(gcasto): Is is safe to change this to Profile::IMPLICIT_ACCESS?
    145   return PasswordStoreFactory::GetForProfile(profile_, Profile::EXPLICIT_ACCESS)
    146       .get();
    147 }
    148 
    149 password_manager::PasswordManagerDriver*
    150 ChromePasswordManagerClient::GetDriver() {
    151   return &driver_;
    152 }
    153 
    154 base::FieldTrial::Probability
    155 ChromePasswordManagerClient::GetProbabilityForExperiment(
    156     const std::string& experiment_name) {
    157   base::FieldTrial::Probability enabled_probability = 0;
    158   if (experiment_name ==
    159       password_manager::PasswordManager::kOtherPossibleUsernamesExperiment) {
    160     switch (chrome::VersionInfo::GetChannel()) {
    161       case chrome::VersionInfo::CHANNEL_DEV:
    162       case chrome::VersionInfo::CHANNEL_BETA:
    163         enabled_probability = 50;
    164         break;
    165       default:
    166         break;
    167     }
    168   }
    169   return enabled_probability;
    170 }
    171 
    172 bool ChromePasswordManagerClient::IsPasswordSyncEnabled() {
    173   ProfileSyncService* sync_service =
    174       ProfileSyncServiceFactory::GetForProfile(profile_);
    175   // Don't consider sync enabled if the user has a custom passphrase. See
    176   // crbug.com/358998 for more details.
    177   if (sync_service &&
    178       sync_service->HasSyncSetupCompleted() &&
    179       sync_service->sync_initialized() &&
    180       !sync_service->IsUsingSecondaryPassphrase()) {
    181     return sync_service->GetActiveDataTypes().Has(syncer::PASSWORDS);
    182   }
    183   return false;
    184 }
    185 
    186 void ChromePasswordManagerClient::OnLogRouterAvailabilityChanged(
    187     bool router_can_be_used) {
    188   if (can_use_log_router_ == router_can_be_used)
    189     return;
    190   can_use_log_router_ = router_can_be_used;
    191 
    192   NotifyRendererOfLoggingAvailability();
    193 }
    194 
    195 void ChromePasswordManagerClient::LogSavePasswordProgress(
    196     const std::string& text) {
    197   if (!IsLoggingActive())
    198     return;
    199   PasswordManagerInternalsService* service =
    200       PasswordManagerInternalsServiceFactory::GetForBrowserContext(profile_);
    201   if (service)
    202     service->ProcessLog(text);
    203 }
    204 
    205 bool ChromePasswordManagerClient::IsLoggingActive() const {
    206   // WebUI tabs do not need to log password saving progress. In particular, the
    207   // internals page itself should not send any logs.
    208   return can_use_log_router_ && !web_contents()->GetWebUI();
    209 }
    210 
    211 // static
    212 password_manager::PasswordGenerationManager*
    213 ChromePasswordManagerClient::GetGenerationManagerFromWebContents(
    214     content::WebContents* contents) {
    215   ChromePasswordManagerClient* client =
    216       ChromePasswordManagerClient::FromWebContents(contents);
    217   if (!client)
    218     return NULL;
    219   return client->GetDriver()->GetPasswordGenerationManager();
    220 }
    221 
    222 // static
    223 password_manager::PasswordManager*
    224 ChromePasswordManagerClient::GetManagerFromWebContents(
    225     content::WebContents* contents) {
    226   ChromePasswordManagerClient* client =
    227       ChromePasswordManagerClient::FromWebContents(contents);
    228   if (!client)
    229     return NULL;
    230   return client->GetDriver()->GetPasswordManager();
    231 }
    232 
    233 void ChromePasswordManagerClient::SetTestObserver(
    234     autofill::PasswordGenerationPopupObserver* observer) {
    235   observer_ = observer;
    236 }
    237 
    238 bool ChromePasswordManagerClient::OnMessageReceived(
    239     const IPC::Message& message) {
    240   bool handled = true;
    241   IPC_BEGIN_MESSAGE_MAP(ChromePasswordManagerClient, message)
    242     IPC_MESSAGE_HANDLER(AutofillHostMsg_ShowPasswordGenerationPopup,
    243                         ShowPasswordGenerationPopup)
    244     IPC_MESSAGE_HANDLER(AutofillHostMsg_ShowPasswordEditingPopup,
    245                         ShowPasswordEditingPopup)
    246     IPC_MESSAGE_HANDLER(AutofillHostMsg_HidePasswordGenerationPopup,
    247                         HidePasswordGenerationPopup)
    248     IPC_MESSAGE_HANDLER(AutofillHostMsg_PasswordAutofillAgentConstructed,
    249                         NotifyRendererOfLoggingAvailability)
    250     IPC_MESSAGE_UNHANDLED(handled = false)
    251   IPC_END_MESSAGE_MAP()
    252   return handled;
    253 }
    254 
    255 gfx::RectF ChromePasswordManagerClient::GetBoundsInScreenSpace(
    256     const gfx::RectF& bounds) {
    257   gfx::Rect client_area = web_contents()->GetContainerBounds();
    258   return bounds + client_area.OffsetFromOrigin();
    259 }
    260 
    261 void ChromePasswordManagerClient::ShowPasswordGenerationPopup(
    262     const gfx::RectF& bounds,
    263     int max_length,
    264     const autofill::PasswordForm& form) {
    265   // TODO(gcasto): Validate data in PasswordForm.
    266 
    267   // Not yet implemented on other platforms.
    268 #if defined(USE_AURA) || defined(OS_MACOSX)
    269   gfx::RectF element_bounds_in_screen_space = GetBoundsInScreenSpace(bounds);
    270 
    271   popup_controller_ =
    272       autofill::PasswordGenerationPopupControllerImpl::GetOrCreate(
    273           popup_controller_,
    274           element_bounds_in_screen_space,
    275           form,
    276           max_length,
    277           driver_.GetPasswordManager(),
    278           observer_,
    279           web_contents(),
    280           web_contents()->GetNativeView());
    281   popup_controller_->Show(true /* display_password */);
    282 #endif  // defined(USE_AURA) || defined(OS_MACOSX)
    283 }
    284 
    285 void ChromePasswordManagerClient::ShowPasswordEditingPopup(
    286     const gfx::RectF& bounds,
    287     const autofill::PasswordForm& form) {
    288   gfx::RectF element_bounds_in_screen_space = GetBoundsInScreenSpace(bounds);
    289   // Not yet implemented on other platforms.
    290 #if defined(USE_AURA) || defined(OS_MACOSX)
    291   popup_controller_ =
    292       autofill::PasswordGenerationPopupControllerImpl::GetOrCreate(
    293           popup_controller_,
    294           element_bounds_in_screen_space,
    295           form,
    296           0,  // Unspecified max length.
    297           driver_.GetPasswordManager(),
    298           observer_,
    299           web_contents(),
    300           web_contents()->GetNativeView());
    301   popup_controller_->Show(false /* display_password */);
    302 #endif  // defined(USE_AURA) || defined(OS_MACOSX)
    303 }
    304 
    305 void ChromePasswordManagerClient::NotifyRendererOfLoggingAvailability() {
    306   if (!web_contents())
    307     return;
    308 
    309   web_contents()->GetRenderViewHost()->Send(new AutofillMsg_SetLoggingState(
    310       web_contents()->GetRenderViewHost()->GetRoutingID(),
    311       can_use_log_router_));
    312 }
    313 
    314 void ChromePasswordManagerClient::CommitFillPasswordForm(
    315     autofill::PasswordFormFillData* data) {
    316   driver_.FillPasswordForm(*data);
    317 }
    318 
    319 bool ChromePasswordManagerClient::IsTheHotNewBubbleUIEnabled() {
    320 #if !defined(USE_AURA)
    321   return false;
    322 #endif
    323   CommandLine* command_line = CommandLine::ForCurrentProcess();
    324   if (command_line->HasSwitch(switches::kDisableSavePasswordBubble))
    325     return false;
    326 
    327   if (command_line->HasSwitch(switches::kEnableSavePasswordBubble))
    328     return true;
    329 
    330   std::string group_name =
    331       base::FieldTrialList::FindFullName("PasswordManagerUI");
    332 
    333   // The bubble should be the default case that runs on the bots.
    334   return group_name != "Infobar";
    335 }
    336