diff options
-rw-r--r-- | chrome/browser/password_manager/password_manager.cc | 101 | ||||
-rw-r--r-- | chrome/browser/password_manager/password_manager.h | 38 | ||||
-rw-r--r-- | chrome/browser/password_manager/password_manager_unittest.cc | 206 | ||||
-rw-r--r-- | chrome/browser/pref_service.h | 2 | ||||
-rw-r--r-- | chrome/browser/tab_contents/tab_contents.cc | 83 | ||||
-rw-r--r-- | chrome/browser/tab_contents/tab_contents.h | 14 | ||||
-rw-r--r-- | chrome/chrome_tests.gypi | 1 |
7 files changed, 349 insertions, 96 deletions
diff --git a/chrome/browser/password_manager/password_manager.cc b/chrome/browser/password_manager/password_manager.cc index 069ec4c..fc6c58e 100644 --- a/chrome/browser/password_manager/password_manager.cc +++ b/chrome/browser/password_manager/password_manager.cc @@ -13,100 +13,34 @@ #include "chrome/browser/password_manager/password_form_manager.h" #include "chrome/browser/pref_service.h" #include "chrome/browser/profile.h" -#include "chrome/browser/renderer_host/render_view_host.h" -#include "chrome/browser/tab_contents/tab_contents.h" #include "chrome/common/notification_registrar.h" #include "chrome/common/notification_service.h" #include "chrome/common/pref_names.h" -#include "grit/chromium_strings.h" #include "grit/generated_resources.h" -#include "grit/theme_resources.h" using webkit_glue::PasswordForm; using webkit_glue::PasswordFormMap; -// After a successful *new* login attempt, we take the PasswordFormManager in -// provisional_save_manager_ and move it to a SavePasswordInfoBarDelegate while -// the user makes up their mind with the "save password" infobar. Note if the -// login is one we already know about, the end of the line is -// provisional_save_manager_ because we just update it on success and so such -// forms never end up in an infobar. -class SavePasswordInfoBarDelegate : public ConfirmInfoBarDelegate { - public: - SavePasswordInfoBarDelegate(TabContents* tab_contents, - PasswordFormManager* form_to_save) : - ConfirmInfoBarDelegate(tab_contents), - form_to_save_(form_to_save) { - } - - virtual ~SavePasswordInfoBarDelegate() { } - - // Overridden from ConfirmInfoBarDelegate: - virtual void InfoBarClosed() { - delete this; - } - - virtual std::wstring GetMessageText() const { - return l10n_util::GetString(IDS_PASSWORD_MANAGER_SAVE_PASSWORD_PROMPT); - } - - virtual SkBitmap* GetIcon() const { - return ResourceBundle::GetSharedInstance().GetBitmapNamed( - IDR_INFOBAR_SAVE_PASSWORD); - } - - virtual int GetButtons() const { - return BUTTON_OK | BUTTON_CANCEL; - } - - virtual std::wstring GetButtonLabel(InfoBarButton button) const { - if (button == BUTTON_OK) - return l10n_util::GetString(IDS_PASSWORD_MANAGER_SAVE_BUTTON); - if (button == BUTTON_CANCEL) - return l10n_util::GetString(IDS_PASSWORD_MANAGER_BLACKLIST_BUTTON); - NOTREACHED(); - return std::wstring(); - } - - virtual bool Accept() { - DCHECK(form_to_save_.get()); - form_to_save_->Save(); - return true; - } - - virtual bool Cancel() { - DCHECK(form_to_save_.get()); - form_to_save_->PermanentlyBlacklist(); - return true; - } - - private: - // The PasswordFormManager managing the form we're asking the user about, - // and should update as per her decision. - scoped_ptr<PasswordFormManager> form_to_save_; - - DISALLOW_COPY_AND_ASSIGN(SavePasswordInfoBarDelegate); -}; - // static void PasswordManager::RegisterUserPrefs(PrefService* prefs) { prefs->RegisterBooleanPref(prefs::kPasswordManagerEnabled, true); } -PasswordManager::PasswordManager(TabContents* tab_contents) +PasswordManager::PasswordManager(Delegate* delegate) : login_managers_deleter_(&pending_login_managers_), - tab_contents_(tab_contents), + delegate_(delegate), observer_(NULL) { + DCHECK(delegate_); password_manager_enabled_.Init(prefs::kPasswordManagerEnabled, - tab_contents->profile()->GetPrefs(), NULL); + delegate_->GetProfileForPasswordManager()->GetPrefs(), NULL); } PasswordManager::~PasswordManager() { } void PasswordManager::ProvisionallySavePassword(PasswordForm form) { - if (!tab_contents_->profile() || - tab_contents_->profile()->IsOffTheRecord() || + if (!delegate_->GetProfileForPasswordManager() || + delegate_->GetProfileForPasswordManager()->IsOffTheRecord() || !*password_manager_enabled_) return; @@ -142,8 +76,7 @@ void PasswordManager::ProvisionallySavePassword(PasswordForm form) { return; form.ssl_valid = form.origin.SchemeIsSecure() && - !tab_contents_->controller().ssl_manager()-> - ProcessedSSLErrorFromRequest(); + !delegate_->DidLastPageLoadEncounterSSLErrors(); form.preferred = true; manager->ProvisionallySave(form); provisional_save_manager_.reset(manager); @@ -168,16 +101,13 @@ void PasswordManager::DidStopLoading() { if (!provisional_save_manager_.get()) return; - DCHECK(!tab_contents_->profile()->IsOffTheRecord()); + DCHECK(!delegate_->GetProfileForPasswordManager()->IsOffTheRecord()); DCHECK(!provisional_save_manager_->IsBlacklisted()); - if (!tab_contents_->profile() || - !tab_contents_->profile()->GetWebDataService(Profile::IMPLICIT_ACCESS)) + if (!delegate_->GetProfileForPasswordManager()) return; if (provisional_save_manager_->IsNewLogin()) { - tab_contents_->AddInfoBar( - new SavePasswordInfoBarDelegate(tab_contents_, - provisional_save_manager_.release())); + delegate_->AddSavePasswordInfoBar(provisional_save_manager_.release()); } else { // If the save is not a new username entry, then we just want to save this // data (since the user already has related data saved), so don't prompt. @@ -188,15 +118,13 @@ void PasswordManager::DidStopLoading() { void PasswordManager::PasswordFormsSeen( const std::vector<PasswordForm>& forms) { - if (!tab_contents_->profile() || - !tab_contents_->profile()->GetWebDataService(Profile::EXPLICIT_ACCESS)) + if (!delegate_->GetProfileForPasswordManager()) return; if (!*password_manager_enabled_) return; // Ask the SSLManager for current security. - bool had_ssl_error = tab_contents_->controller().ssl_manager()-> - ProcessedSSLErrorFromRequest(); + bool had_ssl_error = delegate_->DidLastPageLoadEncounterSSLErrors(); std::vector<PasswordForm>::const_iterator iter; for (iter = forms.begin(); iter != forms.end(); iter++) { @@ -212,7 +140,7 @@ void PasswordManager::PasswordFormsSeen( } else { bool ssl_valid = iter->origin.SchemeIsSecure() && !had_ssl_error; PasswordFormManager* manager = - new PasswordFormManager(tab_contents_->profile(), + new PasswordFormManager(delegate_->GetProfileForPasswordManager(), this, *iter, ssl_valid); pending_login_managers_.push_back(manager); manager->FetchMatchingLoginsFromWebDatabase(); @@ -224,7 +152,6 @@ void PasswordManager::Autofill( const PasswordForm& form_for_autofill, const PasswordFormMap& best_matches, const PasswordForm* const preferred_match) const { - DCHECK(tab_contents_); DCHECK(preferred_match); switch (form_for_autofill.scheme) { case PasswordForm::SCHEME_HTML: { @@ -238,7 +165,7 @@ void PasswordManager::Autofill( preferred_match, action_mismatch, &fill_data); - tab_contents_->render_view_host()->FillPasswordForm(fill_data); + delegate_->FillPasswordForm(fill_data); return; } default: diff --git a/chrome/browser/password_manager/password_manager.h b/chrome/browser/password_manager/password_manager.h index 002cb29..2e7991c 100644 --- a/chrome/browser/password_manager/password_manager.h +++ b/chrome/browser/password_manager/password_manager.h @@ -8,14 +8,13 @@ #include "base/scoped_ptr.h" #include "base/stl_util-inl.h" #include "chrome/browser/login_model.h" +#include "chrome/browser/password_manager/password_form_manager.h" #include "chrome/browser/pref_member.h" -#include "chrome/browser/tab_contents/infobar_delegate.h" #include "webkit/glue/password_form.h" #include "webkit/glue/password_form_dom_manager.h" class PasswordFormManager; class PrefService; -class TabContents; // Per-tab password manager. Handles creation and management of UI elements, // receiving password form data from the renderer and managing the password @@ -23,9 +22,37 @@ class TabContents; // for purposes of supporting HTTP authentication dialogs. class PasswordManager : public LoginModel { public: + // An abstraction of operations in the external environment (TabContents) + // that the PasswordManager depends on. This allows for more targeted + // unit testing. + class Delegate { + public: + Delegate() {} + virtual ~Delegate() {} + + // Fill forms matching |form_data| in |tab_contents|. By default, goes + // through the RenderViewHost to FillPasswordForm. Tests can override this + // to sever the dependency on the entire rendering stack. + virtual void FillPasswordForm( + const webkit_glue::PasswordFormDomManager::FillData& form_data) = 0; + + // A mechanism to show an infobar in the current tab at our request. + virtual void AddSavePasswordInfoBar(PasswordFormManager* form_to_save) = 0; + + // Get the profile for which we are managing passwords. + virtual Profile* GetProfileForPasswordManager() = 0; + + // If any SSL certificate errors were encountered as a result of the last + // page load. + virtual bool DidLastPageLoadEncounterSSLErrors() = 0; + private: + DISALLOW_COPY_AND_ASSIGN(Delegate); + }; + static void RegisterUserPrefs(PrefService* prefs); - explicit PasswordManager(TabContents* tab_contents); + // The delegate passed in is required to outlive the PasswordManager. + explicit PasswordManager(Delegate* delegate); ~PasswordManager(); // Called by a PasswordFormManager when it decides a form can be autofilled @@ -88,8 +115,9 @@ class PasswordManager : public LoginModel { // time a user submits a login form and gets to the next page. scoped_ptr<PasswordFormManager> provisional_save_manager_; - // The containing TabContents. - TabContents* tab_contents_; + // Our delegate for carrying out external operations. This is typically the + // containing TabContents. + Delegate* delegate_; // The LoginModelObserver (i.e LoginView) requiring autofill. LoginModelObserver* observer_; diff --git a/chrome/browser/password_manager/password_manager_unittest.cc b/chrome/browser/password_manager/password_manager_unittest.cc new file mode 100644 index 0000000..cd2fb2b --- /dev/null +++ b/chrome/browser/password_manager/password_manager_unittest.cc @@ -0,0 +1,206 @@ +// Copyright (c) 2010 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#include "base/file_path.h" +#include "base/string_util.h" +#include "chrome/browser/password_manager/password_manager.h" +#include "chrome/browser/password_manager/password_store.h" +#include "chrome/browser/pref_service.h" +#include "chrome/common/url_constants.h" +#include "chrome/test/testing_profile.h" +#include "testing/gtest/include/gtest/gtest.h" +#include "testing/gmock/include/gmock/gmock.h" + +using webkit_glue::PasswordForm; +using testing::_; +using testing::DoAll; +using ::testing::Exactly; +using ::testing::WithArg; +using ::testing::Return; + +class MockPasswordManagerDelegate : public PasswordManager::Delegate { + public: + MOCK_METHOD1(FillPasswordForm, void( + const webkit_glue::PasswordFormDomManager::FillData&)); + MOCK_METHOD1(AddSavePasswordInfoBar, void(PasswordFormManager*)); + MOCK_METHOD0(GetProfileForPasswordManager, Profile*()); + MOCK_METHOD0(DidLastPageLoadEncounterSSLErrors, bool()); +}; + +class TestingProfileWithPasswordStore : public TestingProfile { + public: + explicit TestingProfileWithPasswordStore(PasswordStore* store) + : store_(store) {} + virtual PasswordStore* GetPasswordStore(ServiceAccessType access) { + return store_; + } + private: + PasswordStore* store_; +}; + +class MockPasswordStore : public PasswordStore { + public: + MOCK_METHOD1(RemoveLogin, void(const PasswordForm&)); + MOCK_METHOD2(GetLogins, int(const PasswordForm&, PasswordStoreConsumer*)); + MOCK_METHOD1(AddLogin, void(const PasswordForm&)); + MOCK_METHOD1(UpdateLogin, void(const PasswordForm&)); + MOCK_METHOD1(AddLoginImpl, void(const PasswordForm&)); + MOCK_METHOD1(UpdateLoginImpl, void(const PasswordForm&)); + MOCK_METHOD1(RemoveLoginImpl, void(const PasswordForm&)); + MOCK_METHOD2(RemoveLoginsCreatedBetweenImpl, void(const base::Time&, + const base::Time&)); + MOCK_METHOD2(GetLoginsImpl, void(GetLoginsRequest*, const PasswordForm&)); + MOCK_METHOD1(GetAutofillableLoginsImpl, void(GetLoginsRequest*)); + MOCK_METHOD1(GetBlacklistLoginsImpl, void(GetLoginsRequest*)); +}; + +ACTION_P2(InvokeConsumer, handle, forms) { + arg0->OnPasswordStoreRequestDone(handle, forms); +} + +ACTION_P(SaveToScopedPtr, scoped) { + scoped->reset(arg0); +} + +class PasswordManagerTest : public testing::Test { + public: + PasswordManagerTest() {} + protected: + + virtual void SetUp() { + store_ = new MockPasswordStore(); + profile_.reset(new TestingProfileWithPasswordStore(store_)); + EXPECT_CALL(delegate_, GetProfileForPasswordManager()) + .WillRepeatedly(Return(profile_.get())); + manager_.reset(new PasswordManager(&delegate_)); + EXPECT_CALL(delegate_, DidLastPageLoadEncounterSSLErrors()) + .WillRepeatedly(Return(false)); + } + + virtual void TearDown() { + manager_.reset(); + store_ = NULL; + } + + PasswordForm MakeSimpleForm() { + PasswordForm form; + form.origin = GURL("http://www.google.com/a/LoginAuth"); + form.action = GURL("http://www.google.com/a/Login"); + form.username_element = ASCIIToUTF16("Email"); + form.password_element = ASCIIToUTF16("Passwd"); + form.username_value = ASCIIToUTF16("google"); + form.password_value = ASCIIToUTF16("password"); + form.submit_element = ASCIIToUTF16("signIn"); + form.signon_realm = "http://www.google.com"; + return form; + } + + PasswordManager* manager() { return manager_.get(); } + + scoped_ptr<Profile> profile_; + scoped_refptr<MockPasswordStore> store_; + MockPasswordManagerDelegate delegate_; // Owned by manager_. + scoped_ptr<PasswordManager> manager_; +}; + +MATCHER_P(FormMatches, form, "") { + return form.signon_realm == arg.signon_realm && + form.origin == arg.origin && + form.action == arg.action && + form.username_element == arg.username_element && + form.password_element == arg.password_element && + form.submit_element == arg.submit_element; +} + +TEST_F(PasswordManagerTest, FormSubmitEmptyStore) { + // Test that observing a newly submitted form shows the save password bar. + std::vector<PasswordForm*> result; // Empty password store. + EXPECT_CALL(delegate_, FillPasswordForm(_)).Times(Exactly(0)); + EXPECT_CALL(*store_, GetLogins(_,_)) + .WillOnce(DoAll(WithArg<1>(InvokeConsumer(0, result)), Return(0))); + std::vector<PasswordForm> observed; + PasswordForm form(MakeSimpleForm()); + observed.push_back(form); + manager()->PasswordFormsSeen(observed); // The initial load. + + // And the form submit contract is to call ProvisionallySavePassword. + manager()->ProvisionallySavePassword(form); + + scoped_ptr<PasswordFormManager> form_to_save; + EXPECT_CALL(delegate_, AddSavePasswordInfoBar(_)) + .WillOnce(WithArg<0>(SaveToScopedPtr(&form_to_save))); + + // Now the password manager waits for the navigation to complete. + manager()->DidStopLoading(); + + EXPECT_FALSE(NULL == form_to_save.get()); + EXPECT_CALL(*store_, AddLogin(FormMatches(form))); + + // Simulate saving the form, as if the info bar was accepted. + form_to_save->Save(); +} + +TEST_F(PasswordManagerTest, FormSubmitNoGoodMatch) { + // Same as above, except with an existing form for the same signon realm, + // but different origin. Detailed cases like this are covered by + // PasswordFormManagerTest. + std::vector<PasswordForm*> result; + PasswordForm* existing_different = new PasswordForm(MakeSimpleForm()); + existing_different->username_value = ASCIIToUTF16("google2"); + result.push_back(existing_different); + EXPECT_CALL(delegate_, FillPasswordForm(_)); + EXPECT_CALL(*store_, GetLogins(_,_)) + .WillOnce(DoAll(WithArg<1>(InvokeConsumer(0, result)), Return(0))); + + std::vector<PasswordForm> observed; + PasswordForm form(MakeSimpleForm()); + observed.push_back(form); + manager()->PasswordFormsSeen(observed); // The initial load. + manager()->ProvisionallySavePassword(form); + + // We still expect an add, since we didn't have a good match. + scoped_ptr<PasswordFormManager> form_to_save; + EXPECT_CALL(delegate_, AddSavePasswordInfoBar(_)) + .WillOnce(WithArg<0>(SaveToScopedPtr(&form_to_save))); + + manager()->DidStopLoading(); + + EXPECT_CALL(*store_, AddLogin(FormMatches(form))); + // Simulate saving the form. + form_to_save->Save(); +} + +TEST_F(PasswordManagerTest, FormSeenThenLeftPage) { + std::vector<PasswordForm*> result; // Empty password store. + EXPECT_CALL(delegate_, FillPasswordForm(_)).Times(Exactly(0)); + EXPECT_CALL(*store_, GetLogins(_,_)) + .WillOnce(DoAll(WithArg<1>(InvokeConsumer(0, result)), Return(0))); + std::vector<PasswordForm> observed; + PasswordForm form(MakeSimpleForm()); + observed.push_back(form); + manager()->PasswordFormsSeen(observed); // The initial load. + + manager()->DidNavigate(); + + // No expected calls. + manager()->DidStopLoading(); +} + +TEST_F(PasswordManagerTest, FormSubmitFailedLogin) { + std::vector<PasswordForm*> result; // Empty password store. + EXPECT_CALL(delegate_, FillPasswordForm(_)).Times(Exactly(0)); + EXPECT_CALL(*store_, GetLogins(_,_)) + .WillOnce(DoAll(WithArg<1>(InvokeConsumer(0, result)), Return(0))); + std::vector<PasswordForm> observed; + PasswordForm form(MakeSimpleForm()); + observed.push_back(form); + manager()->PasswordFormsSeen(observed); // The initial load. + + manager()->ProvisionallySavePassword(form); + + manager()->PasswordFormsSeen(observed); // Simulated re-appearance. + + // No expected calls to the PasswordStore... + manager()->DidStopLoading(); +} diff --git a/chrome/browser/pref_service.h b/chrome/browser/pref_service.h index 584063f..4f660ee 100644 --- a/chrome/browser/pref_service.h +++ b/chrome/browser/pref_service.h @@ -127,7 +127,7 @@ class PrefService : public NonThreadSafe { // If the pref at the given path changes, we call the observer's Observe // method with NOTIFY_PREF_CHANGED. - void AddPrefObserver(const wchar_t* path, NotificationObserver* obs); + virtual void AddPrefObserver(const wchar_t* path, NotificationObserver* obs); void RemovePrefObserver(const wchar_t* path, NotificationObserver* obs); // Removes a user pref and restores the pref to its default value. diff --git a/chrome/browser/tab_contents/tab_contents.cc b/chrome/browser/tab_contents/tab_contents.cc index d9e96b4..9ac90a9 100644 --- a/chrome/browser/tab_contents/tab_contents.cc +++ b/chrome/browser/tab_contents/tab_contents.cc @@ -76,9 +76,11 @@ #include "chrome/common/render_messages.h" #include "chrome/common/renderer_preferences.h" #include "chrome/common/url_constants.h" +#include "grit/chromium_strings.h" #include "grit/generated_resources.h" #include "grit/locale_settings.h" #include "grit/platform_locale_settings.h" +#include "grit/theme_resources.h" #include "net/base/mime_util.h" #include "net/base/net_errors.h" #include "net/base/net_util.h" @@ -3054,3 +3056,84 @@ void TabContents::SetAppIcon(const SkBitmap& app_icon) { app_icon_ = app_icon; NotifyNavigationStateChanged(INVALIDATE_TITLE); } + +// After a successful *new* login attempt, we take the PasswordFormManager in +// provisional_save_manager_ and move it to a SavePasswordInfoBarDelegate while +// the user makes up their mind with the "save password" infobar. Note if the +// login is one we already know about, the end of the line is +// provisional_save_manager_ because we just update it on success and so such +// forms never end up in an infobar. +class SavePasswordInfoBarDelegate : public ConfirmInfoBarDelegate { + public: + SavePasswordInfoBarDelegate(TabContents* tab_contents, + PasswordFormManager* form_to_save) : + ConfirmInfoBarDelegate(tab_contents), + form_to_save_(form_to_save) { + } + + virtual ~SavePasswordInfoBarDelegate() { } + + // Overridden from ConfirmInfoBarDelegate: + virtual void InfoBarClosed() { + delete this; + } + + virtual std::wstring GetMessageText() const { + return l10n_util::GetString(IDS_PASSWORD_MANAGER_SAVE_PASSWORD_PROMPT); + } + + virtual SkBitmap* GetIcon() const { + return ResourceBundle::GetSharedInstance().GetBitmapNamed( + IDR_INFOBAR_SAVE_PASSWORD); + } + + virtual int GetButtons() const { + return BUTTON_OK | BUTTON_CANCEL; + } + + virtual std::wstring GetButtonLabel(InfoBarButton button) const { + if (button == BUTTON_OK) + return l10n_util::GetString(IDS_PASSWORD_MANAGER_SAVE_BUTTON); + if (button == BUTTON_CANCEL) + return l10n_util::GetString(IDS_PASSWORD_MANAGER_BLACKLIST_BUTTON); + NOTREACHED(); + return std::wstring(); + } + + virtual bool Accept() { + DCHECK(form_to_save_.get()); + form_to_save_->Save(); + return true; + } + + virtual bool Cancel() { + DCHECK(form_to_save_.get()); + form_to_save_->PermanentlyBlacklist(); + return true; + } + + private: + // The PasswordFormManager managing the form we're asking the user about, + // and should update as per her decision. + scoped_ptr<PasswordFormManager> form_to_save_; + + DISALLOW_COPY_AND_ASSIGN(SavePasswordInfoBarDelegate); +}; + +void TabContents::FillPasswordForm( + const webkit_glue::PasswordFormDomManager::FillData& form_data) { + render_view_host()->FillPasswordForm(form_data); +} + +void TabContents::AddSavePasswordInfoBar(PasswordFormManager* form_to_save) { + AddInfoBar(new SavePasswordInfoBarDelegate(this, form_to_save)); +} + +Profile* TabContents::GetProfileForPasswordManager() { + return profile(); +} + +bool TabContents::DidLastPageLoadEncounterSSLErrors() { + return controller().ssl_manager()->ProcessedSSLErrorFromRequest(); +} + diff --git a/chrome/browser/tab_contents/tab_contents.h b/chrome/browser/tab_contents/tab_contents.h index 732e0d4..e503455 100644 --- a/chrome/browser/tab_contents/tab_contents.h +++ b/chrome/browser/tab_contents/tab_contents.h @@ -25,6 +25,7 @@ #include "chrome/browser/find_notification_details.h" #include "chrome/browser/jsmessage_box_client.h" #include "chrome/browser/net/url_request_context_getter.h" +#include "chrome/browser/password_manager/password_manager.h" #include "chrome/browser/printing/print_view_manager.h" #include "chrome/browser/shell_dialogs.h" #include "chrome/browser/renderer_host/render_view_host_delegate.h" @@ -76,7 +77,6 @@ class Extension; class AutocompleteHistoryManager; class LoadNotificationDetails; class OmniboxSearchHint; -class PasswordManager; class PluginInstaller; class Profile; struct RendererPreferences; @@ -102,7 +102,8 @@ class TabContents : public PageNavigator, public RenderViewHostManager::Delegate, public SelectFileDialog::Listener, public JavaScriptMessageBoxClient, - public ImageLoadingTracker::Observer { + public ImageLoadingTracker::Observer, + public PasswordManager::Delegate { public: // Flags passed to the TabContentsDelegate.NavigationStateChanged to tell it // what has changed. Combine them to update more than one thing. @@ -453,7 +454,7 @@ class TabContents : public PageNavigator, // Infobars ------------------------------------------------------------------ // Adds an InfoBar for the specified |delegate|. - void AddInfoBar(InfoBarDelegate* delegate); + virtual void AddInfoBar(InfoBarDelegate* delegate); // Removes the InfoBar for the specified |delegate|. void RemoveInfoBar(InfoBarDelegate* delegate); @@ -690,6 +691,13 @@ class TabContents : public PageNavigator, virtual void SetBookmarkDragDelegate( RenderViewHostDelegate::BookmarkDrag* bookmark_drag); + // PasswordManager::Delegate implementation. + virtual void FillPasswordForm( + const webkit_glue::PasswordFormDomManager::FillData& form_data); + virtual void AddSavePasswordInfoBar(PasswordFormManager* form_to_save); + virtual Profile* GetProfileForPasswordManager(); + virtual bool DidLastPageLoadEncounterSSLErrors(); + private: friend class NavigationController; // Used to access the child_windows_ (ConstrainedWindowList) for testing diff --git a/chrome/chrome_tests.gypi b/chrome/chrome_tests.gypi index c7ee70e..d443899 100644 --- a/chrome/chrome_tests.gypi +++ b/chrome/chrome_tests.gypi @@ -854,6 +854,7 @@ 'browser/password_manager/encryptor_unittest.cc', 'browser/password_manager/login_database_unittest.cc', 'browser/password_manager/password_form_manager_unittest.cc', + 'browser/password_manager/password_manager_unittest.cc', 'browser/password_manager/password_form_data.cc', 'browser/password_manager/password_store_linux_unittest.cc', 'browser/password_manager/password_store_mac_unittest.cc', |