Home | History | Annotate | Download | only in password_manager
      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 "chrome/browser/password_manager/password_generation_manager.h"
      6 
      7 #include "base/prefs/pref_service.h"
      8 #include "chrome/browser/password_manager/password_manager.h"
      9 #include "chrome/browser/profiles/profile.h"
     10 #include "chrome/browser/sync/profile_sync_service.h"
     11 #include "chrome/browser/sync/profile_sync_service_factory.h"
     12 #include "chrome/browser/ui/browser.h"
     13 #include "chrome/browser/ui/browser_finder.h"
     14 #include "chrome/browser/ui/browser_window.h"
     15 #include "chrome/common/pref_names.h"
     16 #include "components/autofill/core/browser/password_generator.h"
     17 #include "components/autofill/core/common/autofill_messages.h"
     18 #include "components/user_prefs/pref_registry_syncable.h"
     19 #include "content/public/browser/browser_thread.h"
     20 #include "content/public/browser/render_view_host.h"
     21 #include "content/public/browser/web_contents.h"
     22 #include "content/public/common/password_form.h"
     23 #include "ipc/ipc_message_macros.h"
     24 #include "ui/gfx/rect.h"
     25 
     26 DEFINE_WEB_CONTENTS_USER_DATA_KEY(PasswordGenerationManager);
     27 
     28 PasswordGenerationManager::PasswordGenerationManager(
     29     content::WebContents* contents)
     30     : content::WebContentsObserver(contents),
     31       enabled_(false),
     32       weak_factory_(this) {
     33   RegisterWithSyncService();
     34 }
     35 
     36 PasswordGenerationManager::~PasswordGenerationManager() {}
     37 
     38 // static
     39 void PasswordGenerationManager::CreateForWebContents(
     40     content::WebContents* contents) {
     41   content::WebContentsUserData<PasswordGenerationManager>::
     42       CreateForWebContents(contents);
     43 
     44   // Start observing changes to relevant prefs. This is not called in the
     45   // constructor so that it's not enabled in testing.
     46   FromWebContents(contents)->SetUpPrefChangeRegistrar();
     47 }
     48 
     49 // static
     50 void PasswordGenerationManager::RegisterProfilePrefs(
     51     user_prefs::PrefRegistrySyncable* registry) {
     52   registry->RegisterBooleanPref(
     53       prefs::kPasswordGenerationEnabled,
     54       true,
     55       user_prefs::PrefRegistrySyncable::SYNCABLE_PREF);
     56 }
     57 
     58 void PasswordGenerationManager::RegisterWithSyncService() {
     59   Profile* profile = Profile::FromBrowserContext(
     60       web_contents()->GetBrowserContext());
     61   ProfileSyncService* sync_service =
     62       ProfileSyncServiceFactory::GetForProfile(profile);
     63   if (sync_service)
     64     sync_service->AddObserver(this);
     65 }
     66 
     67 void PasswordGenerationManager::SetUpPrefChangeRegistrar() {
     68   registrar_.Init(Profile::FromBrowserContext(
     69       web_contents()->GetBrowserContext())->GetPrefs());
     70   registrar_.Add(
     71       prefs::kPasswordGenerationEnabled,
     72       base::Bind(&PasswordGenerationManager::OnPrefStateChanged,
     73                  weak_factory_.GetWeakPtr()));
     74 }
     75 
     76 void PasswordGenerationManager::RenderViewCreated(
     77     content::RenderViewHost* host) {
     78   UpdateState(host, true);
     79 }
     80 
     81 bool PasswordGenerationManager::OnMessageReceived(const IPC::Message& message) {
     82   bool handled = true;
     83   IPC_BEGIN_MESSAGE_MAP(PasswordGenerationManager, message)
     84     IPC_MESSAGE_HANDLER(AutofillHostMsg_ShowPasswordGenerationPopup,
     85                         OnShowPasswordGenerationPopup)
     86     IPC_MESSAGE_UNHANDLED(handled = false)
     87   IPC_END_MESSAGE_MAP()
     88 
     89   return handled;
     90 }
     91 
     92 void PasswordGenerationManager::WebContentsDestroyed(
     93     content::WebContents* contents) {
     94   Profile* profile = Profile::FromBrowserContext(contents->GetBrowserContext());
     95   ProfileSyncService* sync_service =
     96       ProfileSyncServiceFactory::GetForProfile(profile);
     97   if (sync_service && sync_service->HasObserver(this))
     98     sync_service->RemoveObserver(this);
     99 }
    100 
    101 void PasswordGenerationManager::OnPrefStateChanged() {
    102   DCHECK(content::BrowserThread::CurrentlyOn(content::BrowserThread::UI));
    103   if (web_contents() && web_contents()->GetRenderViewHost())
    104     UpdateState(web_contents()->GetRenderViewHost(), false);
    105 }
    106 
    107 void PasswordGenerationManager::OnStateChanged() {
    108   // It is possible for sync state to change during tab contents destruction.
    109   // In this case, we don't need to update the renderer since it's going away.
    110   if (web_contents() && web_contents()->GetRenderViewHost())
    111     UpdateState(web_contents()->GetRenderViewHost(), false);
    112 }
    113 
    114 // In order for password generation to be enabled, we need to make sure:
    115 // (1) Password sync is enabled,
    116 // (2) Password manager is enabled, and
    117 // (3) Password generation preference check box is checked.
    118 void PasswordGenerationManager::UpdateState(content::RenderViewHost* host,
    119                                             bool new_renderer) {
    120   Profile* profile = Profile::FromBrowserContext(
    121       web_contents()->GetBrowserContext());
    122 
    123   bool saving_passwords_enabled =
    124       PasswordManager::FromWebContents(web_contents())->IsSavingEnabled();
    125 
    126   bool preference_checked = profile->GetPrefs()->GetBoolean(
    127       prefs::kPasswordGenerationEnabled);
    128 
    129   bool password_sync_enabled = false;
    130   ProfileSyncService* sync_service =
    131       ProfileSyncServiceFactory::GetForProfile(profile);
    132   if (sync_service) {
    133     syncer::ModelTypeSet sync_set = sync_service->GetActiveDataTypes();
    134     password_sync_enabled = (sync_service->HasSyncSetupCompleted() &&
    135                              sync_set.Has(syncer::PASSWORDS));
    136   }
    137 
    138   bool new_enabled = (password_sync_enabled &&
    139                       saving_passwords_enabled &&
    140                       preference_checked);
    141 
    142   if (new_enabled != enabled_ || new_renderer) {
    143     enabled_ = new_enabled;
    144     SendStateToRenderer(host, enabled_);
    145   }
    146 }
    147 
    148 void PasswordGenerationManager::SendStateToRenderer(
    149     content::RenderViewHost* host, bool enabled) {
    150   host->Send(new AutofillMsg_PasswordGenerationEnabled(host->GetRoutingID(),
    151                                                        enabled));
    152 }
    153 
    154 void PasswordGenerationManager::OnShowPasswordGenerationPopup(
    155     const gfx::Rect& bounds,
    156     int max_length,
    157     const content::PasswordForm& form) {
    158 #if defined(OS_ANDROID)
    159   NOTIMPLEMENTED();
    160 #else
    161   password_generator_.reset(new autofill::PasswordGenerator(max_length));
    162   Browser* browser = chrome::FindBrowserWithWebContents(web_contents());
    163   browser->window()->ShowPasswordGenerationBubble(bounds,
    164                                                   form,
    165                                                   password_generator_.get());
    166 #endif  // #if defined(OS_ANDROID)
    167 }
    168