--- /dev/null
+// Copyright 2014 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.
+
+#ifdef TIZEN_AUTOFILL_SUPPORT
+
+#include "browser/password_manager/content_password_manager_driver.h"
+
+#include "components/autofill/content/browser/autofill_driver_impl.h"
+#include "components/autofill/content/common/autofill_messages.h"
+#include "components/autofill/core/common/password_form.h"
+#include "content/public/browser/browser_context.h"
+#include "content/public/browser/navigation_details.h"
+#include "content/public/browser/navigation_entry.h"
+#include "content/public/browser/render_view_host.h"
+#include "content/public/browser/web_contents.h"
+#include "content/public/common/page_transition_types.h"
+#include "content/public/common/ssl_status.h"
+#include "ipc/ipc_message_macros.h"
+#include "net/cert/cert_status_flags.h"
+
+ContentPasswordManagerDriver::ContentPasswordManagerDriver(
+ content::WebContents* web_contents,
+ PasswordManagerClient* client)
+ : WebContentsObserver(web_contents),
+ password_manager_(client),
+ password_generation_manager_(web_contents, client) {
+ DCHECK(web_contents);
+}
+
+ContentPasswordManagerDriver::~ContentPasswordManagerDriver() {}
+
+void ContentPasswordManagerDriver::FillPasswordForm(
+ const autofill::PasswordFormFillData& form_data) {
+ DCHECK(web_contents());
+ web_contents()->GetRenderViewHost()->Send(new AutofillMsg_FillPasswordForm(
+ web_contents()->GetRenderViewHost()->GetRoutingID(), form_data));
+}
+
+bool ContentPasswordManagerDriver::DidLastPageLoadEncounterSSLErrors() {
+ DCHECK(web_contents());
+ content::NavigationEntry* entry =
+ web_contents()->GetController().GetActiveEntry();
+ if (!entry) {
+ NOTREACHED();
+ return false;
+ }
+
+ return net::IsCertStatusError(entry->GetSSL().cert_status);
+}
+
+bool ContentPasswordManagerDriver::IsOffTheRecord() {
+ DCHECK(web_contents());
+ return web_contents()->GetBrowserContext()->IsOffTheRecord();
+}
+
+PasswordGenerationManager*
+ContentPasswordManagerDriver::GetPasswordGenerationManager() {
+ return &password_generation_manager_;
+}
+
+PasswordManager* ContentPasswordManagerDriver::GetPasswordManager() {
+ return &password_manager_;
+}
+
+void ContentPasswordManagerDriver::DidNavigateMainFrame(
+ const content::LoadCommittedDetails& details,
+ const content::FrameNavigateParams& params) {
+ password_manager_.DidNavigateMainFrame(details.is_in_page);
+}
+
+bool ContentPasswordManagerDriver::OnMessageReceived(
+ const IPC::Message& message) {
+ bool handled = true;
+ IPC_BEGIN_MESSAGE_MAP(PasswordManager, message)
+ IPC_MESSAGE_FORWARD(AutofillHostMsg_PasswordFormsParsed,
+ &password_manager_,
+ PasswordManager::OnPasswordFormsParsed)
+ IPC_MESSAGE_FORWARD(AutofillHostMsg_PasswordFormsRendered,
+ &password_manager_,
+ PasswordManager::OnPasswordFormsRendered)
+ IPC_MESSAGE_FORWARD(AutofillHostMsg_PasswordFormSubmitted,
+ &password_manager_,
+ PasswordManager::OnPasswordFormSubmitted)
+ IPC_MESSAGE_FORWARD(AutofillHostMsg_ShowPasswordGenerationPopup,
+ &password_generation_manager_,
+ PasswordGenerationManager::OnShowPasswordGenerationPopup)
+ IPC_MESSAGE_FORWARD(AutofillHostMsg_ShowPasswordEditingPopup,
+ &password_generation_manager_,
+ PasswordGenerationManager::OnShowPasswordEditingPopup)
+ IPC_MESSAGE_FORWARD(AutofillHostMsg_HidePasswordGenerationPopup,
+ &password_generation_manager_,
+ PasswordGenerationManager::OnHidePasswordGenerationPopup)
+ IPC_MESSAGE_UNHANDLED(handled = false)
+ IPC_END_MESSAGE_MAP()
+
+ return handled;
+}
+
+autofill::AutofillManager* ContentPasswordManagerDriver::GetAutofillManager() {
+ autofill::AutofillDriverImpl* driver =
+ autofill::AutofillDriverImpl::FromWebContents(web_contents());
+ return driver ? driver->autofill_manager() : NULL;
+}
+
+void ContentPasswordManagerDriver::AllowPasswordGenerationForForm(
+ autofill::PasswordForm* form) {
+ content::RenderViewHost* host = web_contents()->GetRenderViewHost();
+ host->Send(new AutofillMsg_FormNotBlacklisted(host->GetRoutingID(), *form));
+}
+
+#endif // TIZEN_AUTOFILL_SUPPORT
--- /dev/null
+// Copyright 2014 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.
+
+
+#ifndef CONTENT_PASSWORD_MANAGER_DRIVER_H
+#define CONTENT_PASSWORD_MANAGER_DRIVER_H
+
+#ifdef TIZEN_AUTOFILL_SUPPORT
+
+#include "base/basictypes.h"
+#include "base/compiler_specific.h"
+#include "browser/password_manager/password_generation_manager.h"
+#include "browser/password_manager/password_manager.h"
+#include "browser/password_manager/password_manager_driver.h"
+#include "content/public/browser/web_contents_observer.h"
+
+namespace autofill {
+class AutofillManager;
+struct PasswordForm;
+}
+
+namespace content {
+class WebContents;
+}
+
+class ContentPasswordManagerDriver : public PasswordManagerDriver,
+ public content::WebContentsObserver {
+ public:
+ explicit ContentPasswordManagerDriver(content::WebContents* web_contents,
+ PasswordManagerClient* client);
+ virtual ~ContentPasswordManagerDriver();
+
+ // PasswordManagerDriver implementation.
+ virtual void FillPasswordForm(const autofill::PasswordFormFillData& form_data)
+ OVERRIDE;
+ virtual bool DidLastPageLoadEncounterSSLErrors() OVERRIDE;
+ virtual bool IsOffTheRecord() OVERRIDE;
+ virtual PasswordGenerationManager* GetPasswordGenerationManager() OVERRIDE;
+ virtual PasswordManager* GetPasswordManager() OVERRIDE;
+ virtual autofill::AutofillManager* GetAutofillManager() OVERRIDE;
+ virtual void AllowPasswordGenerationForForm(autofill::PasswordForm* form)
+ OVERRIDE;
+
+ // content::WebContentsObserver overrides.
+ virtual bool OnMessageReceived(const IPC::Message& message) OVERRIDE;
+ virtual void DidNavigateMainFrame(
+ const content::LoadCommittedDetails& details,
+ const content::FrameNavigateParams& params) OVERRIDE;
+
+ private:
+ // Must outlive this instance.
+ PasswordManagerClient* client_;
+
+ PasswordManager password_manager_;
+ PasswordGenerationManager password_generation_manager_;
+
+ DISALLOW_COPY_AND_ASSIGN(ContentPasswordManagerDriver);
+};
+
+#endif // TIZEN_AUTOFILL_SUPPORT
+
+#endif // CONTENT_PASSWORD_MANAGER_DRIVER_H
--- /dev/null
+// Copyright (c) 2012 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.
+
+#ifdef TIZEN_AUTOFILL_SUPPORT
+
+#include "browser/password_manager/password_form_manager.h"
+
+#include <algorithm>
+#include "base/metrics/histogram.h"
+#include "base/strings/string_split.h"
+#include "base/strings/string_util.h"
+#include "browser/password_manager/password_manager.h"
+#include "browser/password_manager/password_manager_client.h"
+#include "browser/password_manager/password_manager_driver.h"
+#include "browser/password_manager/password_store_factory.h"
+#include "components/autofill/core/browser/autofill_manager.h"
+#include "components/autofill/core/browser/form_structure.h"
+#include "components/autofill/core/browser/validation.h"
+#include "components/autofill/core/common/password_form.h"
+#include "components/password_manager/core/browser/password_store.h"
+
+using autofill::FormStructure;
+using autofill::PasswordForm;
+using autofill::PasswordFormMap;
+using base::Time;
+
+PasswordFormManager::PasswordFormManager(PasswordManager* password_manager,
+ PasswordManagerClient* client,
+ PasswordManagerDriver* driver,
+ const PasswordForm& observed_form,
+ bool ssl_valid)
+ : best_matches_deleter_(&best_matches_),
+ observed_form_(observed_form),
+ is_new_login_(true),
+ has_generated_password_(false),
+ password_manager_(password_manager),
+ preferred_match_(NULL),
+ state_(PRE_MATCHING_PHASE),
+ client_(client),
+ driver_(driver),
+ manager_action_(kManagerActionNone),
+ user_action_(kUserActionNone),
+ submit_result_(kSubmitResultNotSubmitted) {
+ if (observed_form_.origin.is_valid())
+ base::SplitString(observed_form_.origin.path(), '/', &form_path_tokens_);
+ observed_form_.ssl_valid = ssl_valid;
+}
+
+PasswordFormManager::~PasswordFormManager() {
+ UMA_HISTOGRAM_ENUMERATION("PasswordManager.ActionsTakenWithPsl",
+ GetActionsTaken(),
+ kMaxNumActionsTaken);
+}
+
+int PasswordFormManager::GetActionsTaken() {
+ return user_action_ + kUserActionMax * (manager_action_ +
+ kManagerActionMax * submit_result_);
+};
+
+// TODO(timsteele): use a hash of some sort in the future?
+bool PasswordFormManager::DoesManage(const PasswordForm& form,
+ ActionMatch action_match) const {
+ if (form.scheme != PasswordForm::SCHEME_HTML)
+ return observed_form_.signon_realm == form.signon_realm;
+
+ // HTML form case.
+ // At a minimum, username and password element must match.
+ if (!((form.username_element == observed_form_.username_element) &&
+ (form.password_element == observed_form_.password_element))) {
+ return false;
+ }
+
+ // When action match is required, the action URL must match, but
+ // the form is allowed to have an empty action URL (See bug 1107719).
+ // Otherwise ignore action URL, this is to allow saving password form with
+ // dynamically changed action URL (See bug 27246).
+ if (form.action.is_valid() && (form.action != observed_form_.action)) {
+ if (action_match == ACTION_MATCH_REQUIRED)
+ return false;
+ }
+
+ // If this is a replay of the same form in the case a user entered an invalid
+ // password, the origin of the new form may equal the action of the "first"
+ // form.
+ if (!((form.origin == observed_form_.origin) ||
+ (form.origin == observed_form_.action))) {
+ if (form.origin.SchemeIsSecure() &&
+ !observed_form_.origin.SchemeIsSecure()) {
+ // Compare origins, ignoring scheme. There is no easy way to do this
+ // with GURL because clearing the scheme would result in an invalid url.
+ // This is for some sites (such as Hotmail) that begin on an http page and
+ // head to https for the retry when password was invalid.
+ std::string::const_iterator after_scheme1 = form.origin.spec().begin() +
+ form.origin.scheme().length();
+ std::string::const_iterator after_scheme2 =
+ observed_form_.origin.spec().begin() +
+ observed_form_.origin.scheme().length();
+ return std::search(after_scheme1,
+ form.origin.spec().end(),
+ after_scheme2,
+ observed_form_.origin.spec().end())
+ != form.origin.spec().end();
+ }
+ return false;
+ }
+ return true;
+}
+
+bool PasswordFormManager::IsBlacklisted() {
+ DCHECK_EQ(state_, POST_MATCHING_PHASE);
+ if (preferred_match_ && preferred_match_->blacklisted_by_user)
+ return true;
+ return false;
+}
+
+void PasswordFormManager::PermanentlyBlacklist() {
+ DCHECK_EQ(state_, POST_MATCHING_PHASE);
+
+ // Configure the form about to be saved for blacklist status.
+ pending_credentials_.preferred = true;
+ pending_credentials_.blacklisted_by_user = true;
+ pending_credentials_.username_value.clear();
+ pending_credentials_.password_value.clear();
+
+ // Retroactively forget existing matches for this form, so we NEVER prompt or
+ // autofill it again.
+ int num_passwords_deleted = 0;
+ if (!best_matches_.empty()) {
+ PasswordFormMap::const_iterator iter;
+ PasswordStore* password_store = client_->GetPasswordStore();
+ if (!password_store) {
+ NOTREACHED();
+ return;
+ }
+ for (iter = best_matches_.begin(); iter != best_matches_.end(); ++iter) {
+ // We want to remove existing matches for this form so that the exact
+ // origin match with |blackisted_by_user == true| is the only result that
+ // shows up in the future for this origin URL. However, we don't want to
+ // delete logins that were actually saved on a different page (hence with
+ // different origin URL) and just happened to match this form because of
+ // the scoring algorithm. See bug 1204493.
+ if (iter->second->origin == observed_form_.origin) {
+ password_store->RemoveLogin(*iter->second);
+ ++num_passwords_deleted;
+ }
+ }
+ }
+
+ UMA_HISTOGRAM_COUNTS("PasswordManager.NumPasswordsDeletedWhenBlacklisting",
+ num_passwords_deleted);
+
+ // Save the pending_credentials_ entry marked as blacklisted.
+ SaveAsNewLogin(false);
+}
+
+void PasswordFormManager::SetUseAdditionalPasswordAuthentication(
+ bool use_additional_authentication) {
+ pending_credentials_.use_additional_authentication =
+ use_additional_authentication;
+}
+
+bool PasswordFormManager::IsNewLogin() {
+ DCHECK_EQ(state_, POST_MATCHING_PHASE);
+ return is_new_login_;
+}
+
+bool PasswordFormManager::IsPendingCredentialsPublicSuffixMatch() {
+ return pending_credentials_.IsPublicSuffixMatch();
+}
+
+void PasswordFormManager::SetHasGeneratedPassword() {
+ has_generated_password_ = true;
+}
+
+bool PasswordFormManager::HasGeneratedPassword() {
+ // This check is permissive, as the user may have generated a password and
+ // then edited it in the form itself. However, even in this case the user
+ // has already given consent, so we treat these cases the same.
+ return has_generated_password_;
+}
+
+bool PasswordFormManager::HasValidPasswordForm() {
+ DCHECK_EQ(state_, POST_MATCHING_PHASE);
+ // Non-HTML password forms (primarily HTTP and FTP autentication)
+ // do not contain username_element and password_element values.
+ if (observed_form_.scheme != PasswordForm::SCHEME_HTML)
+ return true;
+ return !observed_form_.username_element.empty() &&
+ !observed_form_.password_element.empty();
+}
+
+void PasswordFormManager::ProvisionallySave(
+ const PasswordForm& credentials,
+ OtherPossibleUsernamesAction action) {
+ DCHECK_EQ(state_, POST_MATCHING_PHASE);
+ DCHECK(DoesManage(credentials, ACTION_MATCH_NOT_REQUIRED));
+
+ // Make sure the important fields stay the same as the initially observed or
+ // autofilled ones, as they may have changed if the user experienced a login
+ // failure.
+ // Look for these credentials in the list containing auto-fill entries.
+ PasswordFormMap::const_iterator it =
+ best_matches_.find(credentials.username_value);
+ if (it != best_matches_.end()) {
+ // The user signed in with a login we autofilled.
+ pending_credentials_ = *it->second;
+
+ // Public suffix matches should always be new logins, since we want to store
+ // them so they can automatically be filled in later.
+ is_new_login_ = IsPendingCredentialsPublicSuffixMatch();
+ if (is_new_login_)
+ user_action_ = kUserActionChoosePslMatch;
+
+ // Check to see if we're using a known username but a new password.
+ if (pending_credentials_.password_value != credentials.password_value)
+ user_action_ = kUserActionOverride;
+ } else if (action == ALLOW_OTHER_POSSIBLE_USERNAMES &&
+ UpdatePendingCredentialsIfOtherPossibleUsername(
+ credentials.username_value)) {
+ // |pending_credentials_| is now set. Note we don't update
+ // |pending_credentials_.username_value| to |credentials.username_value|
+ // yet because we need to keep the original username to modify the stored
+ // credential.
+ selected_username_ = credentials.username_value;
+ is_new_login_ = false;
+ } else {
+ // User typed in a new, unknown username.
+ user_action_ = kUserActionOverride;
+ pending_credentials_ = observed_form_;
+ pending_credentials_.username_value = credentials.username_value;
+ pending_credentials_.other_possible_usernames =
+ credentials.other_possible_usernames;
+ }
+
+ pending_credentials_.action = credentials.action;
+ // If the user selected credentials we autofilled from a PasswordForm
+ // that contained no action URL (IE6/7 imported passwords, for example),
+ // bless it with the action URL from the observed form. See bug 1107719.
+ if (pending_credentials_.action.is_empty())
+ pending_credentials_.action = observed_form_.action;
+
+ pending_credentials_.password_value = credentials.password_value;
+ pending_credentials_.preferred = credentials.preferred;
+
+ if (has_generated_password_)
+ pending_credentials_.type = PasswordForm::TYPE_GENERATED;
+}
+
+void PasswordFormManager::Save() {
+ DCHECK_EQ(state_, POST_MATCHING_PHASE);
+ DCHECK(!driver_->IsOffTheRecord());
+
+ if (IsNewLogin())
+ SaveAsNewLogin(true);
+ else
+ UpdateLogin();
+}
+
+void PasswordFormManager::FetchMatchingLoginsFromPasswordStore(
+ PasswordStore::AuthorizationPromptPolicy prompt_policy) {
+ DCHECK_EQ(state_, PRE_MATCHING_PHASE);
+ state_ = MATCHING_PHASE;
+ PasswordStore* password_store = client_->GetPasswordStore();
+ if (!password_store) {
+ NOTREACHED();
+ return;
+ }
+ password_store->GetLogins(observed_form_, prompt_policy, this);
+}
+
+bool PasswordFormManager::HasCompletedMatching() {
+ return state_ == POST_MATCHING_PHASE;
+}
+
+void PasswordFormManager::OnRequestDone(
+ const std::vector<PasswordForm*>& logins_result) {
+ // Note that the result gets deleted after this call completes, but we own
+ // the PasswordForm objects pointed to by the result vector, thus we keep
+ // copies to a minimum here.
+
+ int best_score = 0;
+ // These credentials will be in the final result regardless of score.
+ std::vector<PasswordForm> credentials_to_keep;
+ for (size_t i = 0; i < logins_result.size(); i++) {
+ if (IgnoreResult(*logins_result[i])) {
+ delete logins_result[i];
+ continue;
+ }
+ // Score and update best matches.
+ int current_score = ScoreResult(*logins_result[i]);
+ // This check is here so we can append empty path matches in the event
+ // they don't score as high as others and aren't added to best_matches_.
+ // This is most commonly imported firefox logins. We skip blacklisted
+ // ones because clearly we don't want to autofill them, and secondly
+ // because they only mean something when we have no other matches already
+ // saved in Chrome - in which case they'll make it through the regular
+ // scoring flow below by design. Note signon_realm == origin implies empty
+ // path logins_result, since signon_realm is a prefix of origin for HTML
+ // password forms.
+ // TODO(timsteele): Bug 1269400. We probably should do something more
+ // elegant for any shorter-path match instead of explicitly handling empty
+ // path matches.
+ if ((observed_form_.scheme == PasswordForm::SCHEME_HTML) &&
+ (observed_form_.signon_realm == logins_result[i]->origin.spec()) &&
+ (current_score > 0) && (!logins_result[i]->blacklisted_by_user)) {
+ credentials_to_keep.push_back(*logins_result[i]);
+ }
+
+ // Always keep generated passwords as part of the result set. If a user
+ // generates a password on a signup form, it should show on a login form
+ // even if they have a previous login saved.
+ // TODO(gcasto): We don't want to cut credentials that were saved on signup
+ // forms even if they weren't generated, but currently it's hard to
+ // distinguish between those forms and two different login forms on the
+ // same domain. Filed http://crbug.com/294468 to look into this.
+ if (logins_result[i]->type == PasswordForm::TYPE_GENERATED)
+ credentials_to_keep.push_back(*logins_result[i]);
+
+ if (current_score < best_score) {
+ delete logins_result[i];
+ continue;
+ }
+ if (current_score == best_score) {
+ best_matches_[logins_result[i]->username_value] = logins_result[i];
+ } else if (current_score > best_score) {
+ best_score = current_score;
+ // This new login has a better score than all those up to this point
+ // Note 'this' owns all the PasswordForms in best_matches_.
+ STLDeleteValues(&best_matches_);
+ best_matches_.clear();
+ preferred_match_ = NULL; // Don't delete, its owned by best_matches_.
+ best_matches_[logins_result[i]->username_value] = logins_result[i];
+ }
+ preferred_match_ = logins_result[i]->preferred ? logins_result[i]
+ : preferred_match_;
+ }
+ // We're done matching now.
+ state_ = POST_MATCHING_PHASE;
+
+ if (best_score <= 0) {
+ return;
+ }
+
+ for (std::vector<PasswordForm>::const_iterator it =
+ credentials_to_keep.begin();
+ it != credentials_to_keep.end(); ++it) {
+ // If we don't already have a result with the same username, add the
+ // lower-scored match (if it had equal score it would already be in
+ // best_matches_).
+ if (best_matches_.find(it->username_value) == best_matches_.end())
+ best_matches_[it->username_value] = new PasswordForm(*it);
+ }
+
+ UMA_HISTOGRAM_COUNTS("PasswordManager.NumPasswordsNotShown",
+ logins_result.size() - best_matches_.size());
+
+ // It is possible we have at least one match but have no preferred_match_,
+ // because a user may have chosen to 'Forget' the preferred match. So we
+ // just pick the first one and whichever the user selects for submit will
+ // be saved as preferred.
+ DCHECK(!best_matches_.empty());
+ if (!preferred_match_)
+ preferred_match_ = best_matches_.begin()->second;
+
+ // Check to see if the user told us to ignore this site in the past.
+ if (preferred_match_->blacklisted_by_user) {
+ manager_action_ = kManagerActionBlacklisted;
+ return;
+ }
+
+ // If not blacklisted, inform the driver that password generation is allowed
+ // for |observed_form_|.
+ driver_->AllowPasswordGenerationForForm(&observed_form_);
+
+ // Proceed to autofill.
+ // Note that we provide the choices but don't actually prefill a value if:
+ // (1) we are in Incognito mode, (2) the ACTION paths don't match,
+ // or (3) if it matched using public suffix domain matching.
+ bool wait_for_username =
+ driver_->IsOffTheRecord() ||
+ observed_form_.action.GetWithEmptyPath() !=
+ preferred_match_->action.GetWithEmptyPath() ||
+ preferred_match_->IsPublicSuffixMatch();
+ if (wait_for_username)
+ manager_action_ = kManagerActionNone;
+ else
+ manager_action_ = kManagerActionAutofilled;
+ password_manager_->Autofill(observed_form_, best_matches_,
+ *preferred_match_, wait_for_username);
+}
+
+void PasswordFormManager::OnGetPasswordStoreResults(
+ const std::vector<autofill::PasswordForm*>& results) {
+ DCHECK_EQ(state_, MATCHING_PHASE);
+
+ if (results.empty()) {
+ state_ = POST_MATCHING_PHASE;
+ // No result means that we visit this site the first time so we don't need
+ // to check whether this site is blacklisted or not. Just send a message
+ // to allow password generation.
+ driver_->AllowPasswordGenerationForForm(&observed_form_);
+ return;
+ }
+ OnRequestDone(results);
+}
+
+bool PasswordFormManager::IgnoreResult(const PasswordForm& form) const {
+ // Ignore change password forms until we have some change password
+ // functionality
+ if (observed_form_.old_password_element.length() != 0) {
+ return true;
+ }
+ // Don't match an invalid SSL form with one saved under secure
+ // circumstances.
+ if (form.ssl_valid && !observed_form_.ssl_valid) {
+ return true;
+ }
+ return false;
+}
+
+void PasswordFormManager::SaveAsNewLogin(bool reset_preferred_login) {
+ DCHECK_EQ(state_, POST_MATCHING_PHASE);
+ DCHECK(IsNewLogin());
+ // The new_form is being used to sign in, so it is preferred.
+ DCHECK(pending_credentials_.preferred);
+ // new_form contains the same basic data as observed_form_ (because its the
+ // same form), but with the newly added credentials.
+
+ DCHECK(!driver_->IsOffTheRecord());
+
+ PasswordStore* password_store = client_->GetPasswordStore();
+ if (!password_store) {
+ NOTREACHED();
+ return;
+ }
+
+ pending_credentials_.date_created = Time::Now();
+ SanitizePossibleUsernames(&pending_credentials_);
+ password_store->AddLogin(pending_credentials_);
+
+ if (reset_preferred_login) {
+ UpdatePreferredLoginState(password_store);
+ }
+}
+
+void PasswordFormManager::SanitizePossibleUsernames(PasswordForm* form) {
+ // Remove any possible usernames that could be credit cards or SSN for privacy
+ // reasons. Also remove duplicates, both in other_possible_usernames and
+ // between other_possible_usernames and username_value.
+ std::set<base::string16> set;
+ for (std::vector<base::string16>::iterator it =
+ form->other_possible_usernames.begin();
+ it != form->other_possible_usernames.end(); ++it) {
+ if (!autofill::IsValidCreditCardNumber(*it) && !autofill::IsSSN(*it))
+ set.insert(*it);
+ }
+ set.erase(form->username_value);
+ std::vector<base::string16> temp(set.begin(), set.end());
+ form->other_possible_usernames.swap(temp);
+}
+
+void PasswordFormManager::UpdatePreferredLoginState(
+ PasswordStore* password_store) {
+ DCHECK(password_store);
+ PasswordFormMap::iterator iter;
+ for (iter = best_matches_.begin(); iter != best_matches_.end(); iter++) {
+ if (iter->second->username_value != pending_credentials_.username_value &&
+ iter->second->preferred) {
+ // This wasn't the selected login but it used to be preferred.
+ iter->second->preferred = false;
+ if (user_action_ == kUserActionNone)
+ user_action_ = kUserActionChoose;
+ password_store->UpdateLogin(*iter->second);
+ }
+ }
+}
+
+void PasswordFormManager::UpdateLogin() {
+ DCHECK_EQ(state_, POST_MATCHING_PHASE);
+ DCHECK(preferred_match_);
+ // If we're doing an Update, we either autofilled correctly and need to
+ // update the stats, or the user typed in a new password for autofilled
+ // username, or the user selected one of the non-preferred matches,
+ // thus requiring a swap of preferred bits.
+ DCHECK(!IsNewLogin() && pending_credentials_.preferred);
+ DCHECK(!driver_->IsOffTheRecord());
+
+ PasswordStore* password_store = client_->GetPasswordStore();
+ if (!password_store) {
+ NOTREACHED();
+ return;
+ }
+
+ // Update metadata.
+ ++pending_credentials_.times_used;
+
+ // Check to see if this form is a candidate for password generation.
+ CheckForAccountCreationForm(pending_credentials_, observed_form_);
+
+ UpdatePreferredLoginState(password_store);
+
+ // Remove alternate usernames. At this point we assume that we have found
+ // the right username.
+ pending_credentials_.other_possible_usernames.clear();
+
+ // Update the new preferred login.
+ if (!selected_username_.empty()) {
+ // An other possible username is selected. We set this selected username
+ // as the real username. The PasswordStore API isn't designed to update
+ // username, so we delete the old credentials and add a new one instead.
+ password_store->RemoveLogin(pending_credentials_);
+ pending_credentials_.username_value = selected_username_;
+ password_store->AddLogin(pending_credentials_);
+ } else if ((observed_form_.scheme == PasswordForm::SCHEME_HTML) &&
+ (observed_form_.origin.spec().length() >
+ observed_form_.signon_realm.length()) &&
+ (observed_form_.signon_realm ==
+ pending_credentials_.origin.spec())) {
+ // Note origin.spec().length > signon_realm.length implies the origin has a
+ // path, since signon_realm is a prefix of origin for HTML password forms.
+ //
+ // The user logged in successfully with one of our autofilled logins on a
+ // page with non-empty path, but the autofilled entry was initially saved/
+ // imported with an empty path. Rather than just mark this entry preferred,
+ // we create a more specific copy for this exact page and leave the "master"
+ // unchanged. This is to prevent the case where that master login is used
+ // on several sites (e.g site.com/a and site.com/b) but the user actually
+ // has a different preference on each site. For example, on /a, he wants the
+ // general empty-path login so it is flagged as preferred, but on /b he logs
+ // in with a different saved entry - we don't want to remove the preferred
+ // status of the former because upon return to /a it won't be the default-
+ // fill match.
+ // TODO(timsteele): Bug 1188626 - expire the master copies.
+ PasswordForm copy(pending_credentials_);
+ copy.origin = observed_form_.origin;
+ copy.action = observed_form_.action;
+ password_store->AddLogin(copy);
+ } else {
+ password_store->UpdateLogin(pending_credentials_);
+ }
+}
+
+bool PasswordFormManager::UpdatePendingCredentialsIfOtherPossibleUsername(
+ const base::string16& username) {
+ for (PasswordFormMap::const_iterator it = best_matches_.begin();
+ it != best_matches_.end(); ++it) {
+ for (size_t i = 0; i < it->second->other_possible_usernames.size(); ++i) {
+ if (it->second->other_possible_usernames[i] == username) {
+ pending_credentials_ = *it->second;
+ return true;
+ }
+ }
+ }
+ return false;
+}
+
+void PasswordFormManager::CheckForAccountCreationForm(
+ const PasswordForm& pending, const PasswordForm& observed) {
+ // We check to see if the saved form_data is the same as the observed
+ // form_data, which should never be true for passwords saved on account
+ // creation forms. This check is only made the first time a password is used
+ // to cut down on false positives. Specifically a site may have multiple login
+ // forms with different markup, which might look similar to a signup form.
+ if (pending.times_used == 1) {
+ FormStructure pending_structure(pending.form_data);
+ FormStructure observed_structure(observed.form_data);
+ // Ignore |pending_structure| if its FormData has no fields. This is to
+ // weed out those credentials that were saved before FormData was added
+ // to PasswordForm. Even without this check, these FormStructure's won't
+ // be uploaded, but it makes it hard to see if we are encountering
+ // unexpected errors.
+ if (!pending.form_data.fields.empty() &&
+ pending_structure.FormSignature() !=
+ observed_structure.FormSignature()) {
+ autofill::AutofillManager* autofill_manager;
+ if ((autofill_manager = driver_->GetAutofillManager())) {
+ // Note that this doesn't guarantee that the upload succeeded, only that
+ // |pending.form_data| is considered uploadable.
+ bool success =
+ autofill_manager->UploadPasswordGenerationForm(pending.form_data);
+ UMA_HISTOGRAM_BOOLEAN("PasswordGeneration.UploadStarted", success);
+ }
+ }
+ }
+}
+
+int PasswordFormManager::ScoreResult(const PasswordForm& candidate) const {
+ DCHECK_EQ(state_, MATCHING_PHASE);
+ // For scoring of candidate login data:
+ // The most important element that should match is the origin, followed by
+ // the action, the password name, the submit button name, and finally the
+ // username input field name.
+ // Exact origin match gives an addition of 64 (1 << 6) + # of matching url
+ // dirs.
+ // Partial match gives an addition of 32 (1 << 5) + # matching url dirs
+ // That way, a partial match cannot trump an exact match even if
+ // the partial one matches all other attributes (action, elements) (and
+ // regardless of the matching depth in the URL path).
+ // If public suffix origin match was not used, it gives an addition of
+ // 16 (1 << 4).
+ int score = 0;
+ if (candidate.origin == observed_form_.origin) {
+ // This check is here for the most common case which
+ // is we have a single match in the db for the given host,
+ // so we don't generally need to walk the entire URL path (the else
+ // clause).
+ score += (1 << 6) + static_cast<int>(form_path_tokens_.size());
+ } else {
+ // Walk the origin URL paths one directory at a time to see how
+ // deep the two match.
+ std::vector<std::string> candidate_path_tokens;
+ base::SplitString(candidate.origin.path(), '/', &candidate_path_tokens);
+ size_t depth = 0;
+ size_t max_dirs = std::min(form_path_tokens_.size(),
+ candidate_path_tokens.size());
+ while ((depth < max_dirs) && (form_path_tokens_[depth] ==
+ candidate_path_tokens[depth])) {
+ depth++;
+ score++;
+ }
+ // do we have a partial match?
+ score += (depth > 0) ? 1 << 5 : 0;
+ }
+ if (observed_form_.scheme == PasswordForm::SCHEME_HTML) {
+ if (!candidate.IsPublicSuffixMatch())
+ score += 1 << 4;
+ if (candidate.action == observed_form_.action)
+ score += 1 << 3;
+ if (candidate.password_element == observed_form_.password_element)
+ score += 1 << 2;
+ if (candidate.submit_element == observed_form_.submit_element)
+ score += 1 << 1;
+ if (candidate.username_element == observed_form_.username_element)
+ score += 1 << 0;
+ }
+
+ return score;
+}
+
+void PasswordFormManager::SubmitPassed() {
+ submit_result_ = kSubmitResultPassed;
+}
+
+void PasswordFormManager::SubmitFailed() {
+ submit_result_ = kSubmitResultFailed;
+}
+#endif // TIZEN_AUTOFILL_SUPPORT
--- /dev/null
+// Copyright (c) 2012 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.
+
+#ifndef PASSWORD_FORM_MANAGER_H
+#define PASSWORD_FORM_MANAGER_H
+
+#ifdef TIZEN_AUTOFILL_SUPPORT
+
+#include <string>
+#include <vector>
+
+#include "build/build_config.h"
+
+#include "base/stl_util.h"
+#include "browser/password_manager/password_manager_driver.h"
+#include "components/autofill/core/common/password_form.h"
+#include "components/password_manager/core/browser/password_store.h"
+#include "components/password_manager/core/browser/password_store_consumer.h"
+
+namespace content {
+class WebContents;
+} // namespace content
+
+class PasswordManager;
+class PasswordManagerClient;
+
+// Per-password-form-{on-page, dialog} class responsible for interactions
+// between a given form, the per-tab PasswordManager, and the PasswordStore.
+class PasswordFormManager : public PasswordStoreConsumer {
+ public:
+ // |password_manager| owns this object
+ // |form_on_page| is the form that may be submitted and could need login data.
+ // |ssl_valid| represents the security of the page containing observed_form,
+ // used to filter login results from database.
+ PasswordFormManager(PasswordManager* password_manager,
+ PasswordManagerClient* client,
+ PasswordManagerDriver* driver,
+ const autofill::PasswordForm& observed_form,
+ bool ssl_valid);
+ virtual ~PasswordFormManager();
+
+ enum ActionMatch {
+ ACTION_MATCH_REQUIRED,
+ ACTION_MATCH_NOT_REQUIRED
+ };
+
+ enum OtherPossibleUsernamesAction {
+ ALLOW_OTHER_POSSIBLE_USERNAMES,
+ IGNORE_OTHER_POSSIBLE_USERNAMES
+ };
+
+ // Compare basic data of observed_form_ with argument. Only check the action
+ // URL when action match is required.
+ bool DoesManage(const autofill::PasswordForm& form,
+ ActionMatch action_match) const;
+
+ // Retrieves potential matching logins from the database.
+ // |prompt_policy| indicates whether it's permissible to prompt the user to
+ // authorize access to locked passwords. This argument is only used on
+ // platforms that support prompting the user for access (such as Mac OS).
+ void FetchMatchingLoginsFromPasswordStore(
+ PasswordStore::AuthorizationPromptPolicy prompt_policy);
+
+ // Simple state-check to verify whether this object as received a callback
+ // from the PasswordStore and completed its matching phase. Note that the
+ // callback in question occurs on the same (and only) main thread from which
+ // instances of this class are ever used, but it is required since it is
+ // conceivable that a user (or ui test) could attempt to submit a login
+ // prompt before the callback has occured, which would InvokeLater a call to
+ // PasswordManager::ProvisionallySave, which would interact with this object
+ // before the db has had time to answer with matching password entries.
+ // This is intended to be a one-time check; if the return value is false the
+ // expectation is caller will give up. This clearly won't work if you put it
+ // in a loop and wait for matching to complete; you're (supposed to be) on
+ // the same thread!
+ bool HasCompletedMatching();
+
+ // Determines if the user opted to 'never remember' passwords for this form.
+ bool IsBlacklisted();
+
+ // Used by PasswordManager to determine whether or not to display
+ // a SavePasswordBar when given the green light to save the PasswordForm
+ // managed by this.
+ bool IsNewLogin();
+
+ // Returns true if the current pending credentials were found using
+ // origin matching of the public suffix, instead of the signon realm of the
+ // form.
+ bool IsPendingCredentialsPublicSuffixMatch();
+
+ // Checks if the form is a valid password form. Forms which lack either
+ // login or password field are not considered valid.
+ bool HasValidPasswordForm();
+
+ // These functions are used to determine if this form has had it's password
+ // auto generated by the browser.
+ bool HasGeneratedPassword();
+ void SetHasGeneratedPassword();
+
+ // Determines if we need to autofill given the results of the query.
+ // Takes ownership of the elements in |result|.
+ void OnRequestDone(const std::vector<autofill::PasswordForm*>& result);
+
+ virtual void OnGetPasswordStoreResults(
+ const std::vector<autofill::PasswordForm*>& results) OVERRIDE;
+
+ // A user opted to 'never remember' passwords for this form.
+ // Blacklist it so that from now on when it is seen we ignore it.
+ // TODO: Make this private once we switch to the new UI.
+ void PermanentlyBlacklist();
+
+ // Sets whether the password form should use additional password
+ // authentication if available before being used for autofill.
+ void SetUseAdditionalPasswordAuthentication(
+ bool use_additional_authentication);
+
+ // If the user has submitted observed_form_, provisionally hold on to
+ // the submitted credentials until we are told by PasswordManager whether
+ // or not the login was successful. |action| describes how we deal with
+ // possible usernames. If |action| is ALLOW_OTHER_POSSIBLE_USERNAMES we will
+ // treat a possible usernames match as a sign that our original heuristics
+ // were wrong and that the user selected the correct username from the
+ // Autofill UI.
+ void ProvisionallySave(const autofill::PasswordForm& credentials,
+ OtherPossibleUsernamesAction action);
+
+ // Handles save-as-new or update of the form managed by this manager.
+ // Note the basic data of updated_credentials must match that of
+ // observed_form_ (e.g DoesManage(pending_credentials_) == true).
+ // TODO: Make this private once we switch to the new UI.
+ void Save();
+
+ // Call these if/when we know the form submission worked or failed.
+ // These routines are used to update internal statistics ("ActionsTaken").
+ void SubmitPassed();
+ void SubmitFailed();
+
+ // Returns the username associated with the credentials.
+ const base::string16& associated_username() const {
+ return pending_credentials_.username_value;
+ }
+
+ // Returns the pending credentials.
+ const autofill::PasswordForm pending_credentials() const {
+ return pending_credentials_;
+ }
+
+ // Returns the best matches.
+ const autofill::PasswordFormMap best_matches() const {
+ return best_matches_;
+ }
+
+ // Returns the realm URL for the form managed my this manager.
+ const std::string& realm() const {
+ return pending_credentials_.signon_realm;
+ }
+
+ private:
+ friend class PasswordFormManagerTest;
+
+ // ManagerAction - What does the manager do with this form? Either it
+ // fills it, or it doesn't. If it doesn't fill it, that's either
+ // because it has no match, or it is blacklisted, or it is disabled
+ // via the AUTOCOMPLETE=off attribute. Note that if we don't have
+ // an exact match, we still provide candidates that the user may
+ // end up choosing.
+ enum ManagerAction {
+ kManagerActionNone = 0,
+ kManagerActionAutofilled,
+ kManagerActionBlacklisted,
+ kManagerActionMax
+ };
+
+ // UserAction - What does the user do with this form? If he or she
+ // does nothing (either by accepting what the password manager did, or
+ // by simply (not typing anything at all), you get None. If there were
+ // multiple choices and the user selects one other than the default,
+ // you get Choose, if user selects an entry from matching against the Public
+ // Suffix List you get ChoosePslMatch, and if the user types in a new value,
+ // you get Override.
+ enum UserAction {
+ kUserActionNone = 0,
+ kUserActionChoose,
+ kUserActionChoosePslMatch,
+ kUserActionOverride,
+ kUserActionMax
+ };
+
+ // Result - What happens to the form?
+ enum SubmitResult {
+ kSubmitResultNotSubmitted = 0,
+ kSubmitResultFailed,
+ kSubmitResultPassed,
+ kSubmitResultMax
+ };
+
+ // The maximum number of combinations of the three preceding enums.
+ // This is used when recording the actions taken by the form in UMA.
+ static const int kMaxNumActionsTaken = kManagerActionMax * kUserActionMax *
+ kSubmitResultMax;
+
+ // Helper for OnGetPasswordStoreResults to determine whether or not
+ // the given result form is worth scoring.
+ bool IgnoreResult(const autofill::PasswordForm& form) const;
+
+ // Helper for Save in the case that best_matches.size() == 0, meaning
+ // we have no prior record of this form/username/password and the user
+ // has opted to 'Save Password'. If |reset_preferred_login| is set,
+ // the previously preferred login from |best_matches_| will be reset.
+ void SaveAsNewLogin(bool reset_preferred_login);
+
+ // Helper for OnGetPasswordStoreResults to score an individual result
+ // against the observed_form_.
+ int ScoreResult(const autofill::PasswordForm& form) const;
+
+ // Helper for Save in the case that best_matches.size() > 0, meaning
+ // we have at least one match for this form/username/password. This
+ // Updates the form managed by this object, as well as any matching forms
+ // that now need to have preferred bit changed, since updated_credentials
+ // is now implicitly 'preferred'.
+ void UpdateLogin();
+
+ // Check to see if |pending| corresponds to an account creation form. If we
+ // think that it does, we label it as such and upload this state to the
+ // Autofill server, so that we will trigger password generation in the future.
+ void CheckForAccountCreationForm(const autofill::PasswordForm& pending,
+ const autofill::PasswordForm& observed);
+
+ // Update all login matches to reflect new preferred state - preferred flag
+ // will be reset on all matched logins that different than the current
+ // |pending_credentials_|.
+ void UpdatePreferredLoginState(PasswordStore* password_store);
+
+ // Returns true if |username| is one of the other possible usernames for a
+ // password form in |best_matches_| and sets |pending_credentials_| to the
+ // match which had this username.
+ bool UpdatePendingCredentialsIfOtherPossibleUsername(
+ const base::string16& username);
+
+ // Converts the "ActionsTaken" fields into an int so they can be logged to
+ // UMA.
+ int GetActionsTaken();
+
+ // Remove possible_usernames that may contains sensitive information and
+ // duplicates.
+ void SanitizePossibleUsernames(autofill::PasswordForm* form);
+
+ // Set of PasswordForms from the DB that best match the form
+ // being managed by this. Use a map instead of vector, because we most
+ // frequently require lookups by username value in IsNewLogin.
+ autofill::PasswordFormMap best_matches_;
+
+ // Cleans up when best_matches_ goes out of scope.
+ STLValueDeleter<autofill::PasswordFormMap> best_matches_deleter_;
+
+ // The PasswordForm from the page or dialog managed by this.
+ autofill::PasswordForm observed_form_;
+
+ // The origin url path of observed_form_ tokenized, for convenience when
+ // scoring.
+ std::vector<std::string> form_path_tokens_;
+
+ // Stores updated credentials when the form was submitted but success is
+ // still unknown.
+ autofill::PasswordForm pending_credentials_;
+
+ // Whether pending_credentials_ stores a new login or is an update
+ // to an existing one.
+ bool is_new_login_;
+
+ // Whether this form has an auto generated password.
+ bool has_generated_password_;
+
+ // Set if the user has selected one of the other possible usernames in
+ // |pending_credentials_|.
+ base::string16 selected_username_;
+
+ // PasswordManager owning this.
+ const PasswordManager* const password_manager_;
+
+ // Convenience pointer to entry in best_matches_ that is marked
+ // as preferred. This is only allowed to be null if there are no best matches
+ // at all, since there will always be one preferred login when there are
+ // multiple matches (when first saved, a login is marked preferred).
+ const autofill::PasswordForm* preferred_match_;
+
+ typedef enum {
+ PRE_MATCHING_PHASE, // Have not yet invoked a GetLogins query to find
+ // matching login information from password store.
+ MATCHING_PHASE, // We've made a GetLogins request, but
+ // haven't received or finished processing result.
+ POST_MATCHING_PHASE // We've queried the DB and processed matching
+ // login results.
+ } PasswordFormManagerState;
+
+ // State of matching process, used to verify that we don't call methods
+ // assuming we've already processed the request for matching logins,
+ // when we actually haven't.
+ PasswordFormManagerState state_;
+
+ // The client which implements embedder-specific PasswordManager operations.
+ PasswordManagerClient* client_;
+
+ // The driver which implements platform-specific PasswordManager operations.
+ PasswordManagerDriver* driver_;
+
+ // These three fields record the "ActionsTaken" by the browser and
+ // the user with this form, and the result. They are combined and
+ // recorded in UMA when the manager is destroyed.
+ ManagerAction manager_action_;
+ UserAction user_action_;
+ SubmitResult submit_result_;
+
+ DISALLOW_COPY_AND_ASSIGN(PasswordFormManager);
+};
+
+#endif // TIZEN_AUTOFILL_SUPPORT
+
+#endif // PASSWORD_FORM_MANAGER_H
--- /dev/null
+// Copyright (c) 2012 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.
+
+#ifdef TIZEN_AUTOFILL_SUPPORT
+
+#include "browser/password_manager/password_generation_manager.h"
+
+#include "browser/password_manager/password_manager.h"
+#include "browser/password_manager/password_manager_client.h"
+#include "browser/password_manager/password_manager_driver.h"
+#include "components/autofill/content/common/autofill_messages.h"
+#include "components/autofill/core/browser/autofill_field.h"
+#include "components/autofill/core/browser/field_types.h"
+#include "components/autofill/core/browser/form_structure.h"
+#include "components/autofill/core/browser/password_generator.h"
+#include "components/autofill/core/common/form_data.h"
+#include "components/autofill/core/common/password_form.h"
+#include "content/public/browser/render_view_host.h"
+#include "content/public/browser/web_contents.h"
+#include "content/public/browser/web_contents_view.h"
+#include "ui/gfx/rect.h"
+
+PasswordGenerationManager::PasswordGenerationManager(
+ content::WebContents* contents,
+ PasswordManagerClient* client)
+ : web_contents_(contents),
+ observer_(NULL),
+ client_(client),
+ driver_(client->GetDriver()) {}
+
+PasswordGenerationManager::~PasswordGenerationManager() {}
+
+void PasswordGenerationManager::SetTestObserver(
+ autofill::PasswordGenerationPopupObserver* observer) {
+ observer_ = observer;
+}
+
+void PasswordGenerationManager::DetectAccountCreationForms(
+ const std::vector<autofill::FormStructure*>& forms) {
+ std::vector<autofill::FormData> account_creation_forms;
+ for (std::vector<autofill::FormStructure*>::const_iterator form_it =
+ forms.begin(); form_it != forms.end(); ++form_it) {
+ autofill::FormStructure* form = *form_it;
+ for (std::vector<autofill::AutofillField*>::const_iterator field_it =
+ form->begin(); field_it != form->end(); ++field_it) {
+ autofill::AutofillField* field = *field_it;
+ if (field->server_type() == autofill::ACCOUNT_CREATION_PASSWORD) {
+ account_creation_forms.push_back(form->ToFormData());
+ break;
+ }
+ }
+ }
+ if (!account_creation_forms.empty() && IsGenerationEnabled()) {
+ SendAccountCreationFormsToRenderer(web_contents_->GetRenderViewHost(),
+ account_creation_forms);
+ }
+}
+
+// In order for password generation to be enabled, we need to make sure:
+// (1) Password sync is enabled, and
+// (2) Password saving is enabled.
+bool PasswordGenerationManager::IsGenerationEnabled() const
+{
+ if (!driver_->GetPasswordManager()->IsPasswordManagerEnabled()) {
+ DVLOG(2) << "Generation disabled because password saving is disabled";
+ return false;
+ }
+
+ if (!client_->IsPasswordSyncEnabled()) {
+ DVLOG(2) << "Generation disabled because passwords are not being synced";
+ return false;
+ }
+
+ return true;
+}
+
+void PasswordGenerationManager::SendAccountCreationFormsToRenderer(
+ content::RenderViewHost* host,
+ const std::vector<autofill::FormData>& forms) {
+ host->Send(new AutofillMsg_AccountCreationFormsDetected(
+ host->GetRoutingID(), forms));
+}
+
+gfx::RectF PasswordGenerationManager::GetBoundsInScreenSpace(
+ const gfx::RectF& bounds) {
+ gfx::Rect client_area;
+ web_contents_->GetView()->GetContainerBounds(&client_area);
+ return bounds + client_area.OffsetFromOrigin();
+}
+
+void PasswordGenerationManager::OnShowPasswordGenerationPopup(
+ const gfx::RectF& bounds,
+ int max_length,
+ const autofill::PasswordForm& form)
+{
+ // TODO: Call Popup for Password
+}
+
+void PasswordGenerationManager::OnShowPasswordEditingPopup(
+ const gfx::RectF& bounds,
+ const autofill::PasswordForm& form)
+{
+ // TODO: Call Popup for Edit Password
+}
+
+void PasswordGenerationManager::OnHidePasswordGenerationPopup()
+{
+ HidePopup();
+}
+
+void PasswordGenerationManager::HidePopup()
+{
+ // TODO: Call Popup Hide
+}
+
+#endif // TIZEN_AUTOFILL_SUPPORT
--- /dev/null
+// Copyright (c) 2012 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.
+
+#ifndef PASSWORD_GENERATION_MANAGER_H
+#define PASSWORD_GENERATION_MANAGER_H
+
+#ifdef TIZEN_AUTOFILL_SUPPORT
+
+#include <vector>
+
+#include "base/basictypes.h"
+#include "base/memory/scoped_ptr.h"
+#include "base/memory/weak_ptr.h"
+#include "ui/gfx/rect.h"
+
+class PasswordManager;
+class PasswordManagerClient;
+class PasswordManagerDriver;
+
+namespace autofill {
+struct FormData;
+class FormStructure;
+class PasswordGenerator;
+class PasswordGenerationPopupObserver;
+struct PasswordForm;
+}
+
+namespace content {
+class RenderViewHost;
+class WebContents;
+}
+
+namespace user_prefs {
+class PrefRegistrySyncable;
+}
+
+// Per-tab manager for password generation. Will enable this feature only if
+//
+// - Password manager is enabled
+// - Password sync is enabled
+//
+// NOTE: At the moment, the creation of the renderer PasswordGenerationManager
+// is controlled by a switch (--enable-password-generation) so this feature will
+// not be enabled regardless of the above criteria without the switch being
+// present.
+//
+// This class is used to determine what forms we should offer to generate
+// passwords for and manages the popup which is created if the user chooses to
+// generate a password.
+class PasswordGenerationManager {
+ public:
+ PasswordGenerationManager(content::WebContents* contents,
+ PasswordManagerClient* client);
+ virtual ~PasswordGenerationManager();
+
+ // Detect account creation forms from forms with autofill type annotated.
+ // Will send a message to the renderer if we find a correctly annotated form
+ // and the feature is enabled.
+ void DetectAccountCreationForms(
+ const std::vector<autofill::FormStructure*>& forms);
+
+ // Hide any visible password generation related popups.
+ void HidePopup();
+
+ // Observer for PasswordGenerationPopup events. Used for testing.
+ void SetTestObserver(autofill::PasswordGenerationPopupObserver* observer);
+
+ // Causes the password generation UI to be shown for the specified form.
+ // The popup will be anchored at |element_bounds|. The generated password
+ // will be no longer than |max_length|.
+ void OnShowPasswordGenerationPopup(const gfx::RectF& element_bounds,
+ int max_length,
+ const autofill::PasswordForm& form);
+
+ // Causes the password editing UI to be shown anchored at |element_bounds|.
+ void OnShowPasswordEditingPopup(const gfx::RectF& element_bounds,
+ const autofill::PasswordForm& form);
+
+ // Hides any visible UI.
+ void OnHidePasswordGenerationPopup();
+
+ private:
+ friend class PasswordGenerationManagerTest;
+
+ // Determines current state of password generation
+ bool IsGenerationEnabled() const;
+
+ // Sends a message to the renderer specifying form(s) that we should enable
+ // password generation on. This is a separate function to aid in testing.
+ virtual void SendAccountCreationFormsToRenderer(
+ content::RenderViewHost* host,
+ const std::vector<autofill::FormData>& forms);
+
+ // Given |bounds| in the renderers coordinate system, return the same bounds
+ // in the screens coordinate system.
+ gfx::RectF GetBoundsInScreenSpace(const gfx::RectF& bounds);
+
+ // The WebContents instance associated with this instance. Scoped to the
+ // lifetime of this class, as this class is indirectly a WCUD via
+ // ChromePasswordManagerClient.
+ // TODO(blundell): Eliminate this ivar. crbug.com/340675
+ content::WebContents* web_contents_;
+
+ // Observer for password generation popup.
+ autofill::PasswordGenerationPopupObserver* observer_;
+
+ // Controls how passwords are generated.
+ scoped_ptr<autofill::PasswordGenerator> password_generator_;
+
+ // Controls the popup
+ //base::WeakPtr<
+ // autofill::PasswordGenerationPopupControllerImpl> popup_controller_;
+
+ // The PasswordManagerClient instance associated with this instance. Must
+ // outlive this instance.
+ PasswordManagerClient* client_;
+
+ // The PasswordManagerDriver instance associated with this instance. Must
+ // outlive this instance.
+ PasswordManagerDriver* driver_;
+
+ DISALLOW_COPY_AND_ASSIGN(PasswordGenerationManager);
+};
+
+#endif // TIZEN_AUTOFILL_SUPPORT
+
+#endif // PASSWORD_GENERATION_MANAGER_H
--- /dev/null
+// Copyright (c) 2012 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.
+
+#ifdef TIZEN_AUTOFILL_SUPPORT
+
+#include "browser/password_manager/password_manager.h"
+
+#include "base/command_line.h"
+#include "base/metrics/field_trial.h"
+#include "base/metrics/histogram.h"
+#include "base/prefs/pref_service.h"
+#include "base/strings/string_util.h"
+#include "base/strings/utf_string_conversions.h"
+#include "base/threading/platform_thread.h"
+#include "browser/password_manager/password_form_manager.h"
+#include "browser/password_manager/password_manager_client.h"
+#include "browser/password_manager/password_manager_driver.h"
+#include "components/autofill/core/common/password_autofill_util.h"
+#include "components/password_manager/core/browser/password_manager_metrics_util.h"
+#include "components/password_manager/core/common/password_manager_pref_names.h"
+#include "components/user_prefs/pref_registry_syncable.h"
+
+using autofill::PasswordForm;
+using autofill::PasswordFormMap;
+
+namespace {
+
+const char kSpdyProxyRealm[] = "/SpdyProxy";
+
+// This routine is called when PasswordManagers are constructed.
+//
+// Currently we report metrics only once at startup. We require
+// that this is only ever called from a single thread in order to
+// avoid needing to lock (a static boolean flag is then sufficient to
+// guarantee running only once).
+void ReportMetrics(bool password_manager_enabled) {
+ static base::PlatformThreadId initial_thread_id =
+ base::PlatformThread::CurrentId();
+ DCHECK(initial_thread_id == base::PlatformThread::CurrentId());
+
+ static bool ran_once = false;
+ if (ran_once)
+ return;
+ ran_once = true;
+
+ UMA_HISTOGRAM_BOOLEAN("PasswordManager.Enabled", password_manager_enabled);
+}
+
+} // namespace
+
+const char PasswordManager::kOtherPossibleUsernamesExperiment[] =
+ "PasswordManagerOtherPossibleUsernames";
+
+// static
+void PasswordManager::RegisterProfilePrefs(user_prefs::PrefRegistrySyncable* registry) {
+}
+
+PasswordManager::PasswordManager(PasswordManagerClient* client)
+ : client_(client), driver_(client->GetDriver()) {
+ DCHECK(client_);
+ DCHECK(driver_);
+ password_manager_enabled_ = false;
+}
+
+PasswordManager::~PasswordManager()
+{
+ FOR_EACH_OBSERVER(LoginModelObserver, observers_, OnLoginModelDestroying());
+}
+
+void PasswordManager::SetFormHasGeneratedPassword(const PasswordForm& form) {
+ for (ScopedVector<PasswordFormManager>::iterator iter =
+ pending_login_managers_.begin();
+ iter != pending_login_managers_.end(); ++iter) {
+ if ((*iter)->DoesManage(
+ form, PasswordFormManager::ACTION_MATCH_REQUIRED)) {
+ (*iter)->SetHasGeneratedPassword();
+ return;
+ }
+ }
+ // If there is no corresponding PasswordFormManager, we create one. This is
+ // not the common case, and should only happen when there is a bug in our
+ // ability to detect forms.
+ bool ssl_valid = (form.origin.SchemeIsSecure() &&
+ !driver_->DidLastPageLoadEncounterSSLErrors());
+ PasswordFormManager* manager = new PasswordFormManager(
+ this, client_, driver_, form, ssl_valid);
+ pending_login_managers_.push_back(manager);
+ manager->SetHasGeneratedPassword();
+}
+
+bool PasswordManager::IsPasswordManagerEnabled() const
+{
+ return password_manager_enabled_ && !driver_->IsOffTheRecord();
+}
+
+void PasswordManager::SetPasswordManagerEnabled(bool enabled)
+{
+ password_manager_enabled_ = enabled;
+}
+
+void PasswordManager::ProvisionallySavePassword(const PasswordForm& form)
+{
+ if (!IsPasswordManagerEnabled()) {
+ RecordFailure(SAVING_DISABLED, form.origin.host());
+ return;
+ }
+
+ // No password to save? Then don't.
+ if (form.password_value.empty()) {
+ RecordFailure(EMPTY_PASSWORD, form.origin.host());
+ return;
+ }
+
+ scoped_ptr<PasswordFormManager> manager;
+ ScopedVector<PasswordFormManager>::iterator matched_manager_it =
+ pending_login_managers_.end();
+ for (ScopedVector<PasswordFormManager>::iterator iter =
+ pending_login_managers_.begin();
+ iter != pending_login_managers_.end(); ++iter) {
+ // If we find a manager that exactly matches the submitted form including
+ // the action URL, exit the loop.
+ if ((*iter)->DoesManage(
+ form, PasswordFormManager::ACTION_MATCH_REQUIRED)) {
+ matched_manager_it = iter;
+ break;
+ // If the current manager matches the submitted form excluding the action
+ // URL, remember it as a candidate and continue searching for an exact
+ // match.
+ } else if ((*iter)->DoesManage(
+ form, PasswordFormManager::ACTION_MATCH_NOT_REQUIRED)) {
+ matched_manager_it = iter;
+ }
+ }
+ // If we didn't find a manager, this means a form was submitted without
+ // first loading the page containing the form. Don't offer to save
+ // passwords in this case.
+ if (matched_manager_it != pending_login_managers_.end()) {
+ // Transfer ownership of the manager from |pending_login_managers_| to
+ // |manager|.
+ manager.reset(*matched_manager_it);
+ pending_login_managers_.weak_erase(matched_manager_it);
+ } else {
+ RecordFailure(NO_MATCHING_FORM, form.origin.host());
+ return;
+ }
+
+ if (!manager->HasCompletedMatching()) {
+ RecordFailure(MATCHING_NOT_COMPLETE, form.origin.host());
+ return;
+ }
+
+ if (manager->IsBlacklisted()) {
+ RecordFailure(FORM_BLACKLISTED, form.origin.host());
+ return;
+ }
+
+ // Bail if we're missing any of the necessary form components.
+ if (!manager->HasValidPasswordForm()) {
+ RecordFailure(INVALID_FORM, form.origin.host());
+ return;
+ }
+
+ // Always save generated passwords, as the user expresses explicit intent for
+ // Chrome to manage such passwords. For other passwords, respect the
+ // autocomplete attribute if autocomplete='off' is not ignored.
+ if (!autofill::ShouldIgnoreAutocompleteOffForPasswordFields() &&
+ !manager->HasGeneratedPassword() &&
+ !form.password_autocomplete_set) {
+ RecordFailure(AUTOCOMPLETE_OFF, form.origin.host());
+ return;
+ }
+
+ PasswordForm provisionally_saved_form(form);
+ provisionally_saved_form.ssl_valid =
+ form.origin.SchemeIsSecure() &&
+ !driver_->DidLastPageLoadEncounterSSLErrors();
+ provisionally_saved_form.preferred = true;
+ PasswordFormManager::OtherPossibleUsernamesAction action =
+ PasswordFormManager::IGNORE_OTHER_POSSIBLE_USERNAMES;
+ if (OtherPossibleUsernamesEnabled())
+ action = PasswordFormManager::ALLOW_OTHER_POSSIBLE_USERNAMES;
+ manager->ProvisionallySave(provisionally_saved_form, action);
+ provisional_save_manager_.swap(manager);
+}
+
+void PasswordManager::RecordFailure(ProvisionalSaveFailure failure, const std::string& form_origin)
+{
+}
+
+void PasswordManager::AddSubmissionCallback(
+ const PasswordSubmittedCallback& callback) {
+ submission_callbacks_.push_back(callback);
+}
+
+void PasswordManager::AddObserver(LoginModelObserver* observer) {
+ observers_.AddObserver(observer);
+}
+
+void PasswordManager::RemoveObserver(LoginModelObserver* observer) {
+ observers_.RemoveObserver(observer);
+}
+
+void PasswordManager::DidNavigateMainFrame(bool is_in_page) {
+ // Clear data after main frame navigation if the navigation was to a
+ // different page.
+ if (!is_in_page)
+ pending_login_managers_.clear();
+}
+
+void PasswordManager::OnPasswordFormSubmitted(
+ const PasswordForm& password_form) {
+ ProvisionallySavePassword(password_form);
+ for (size_t i = 0; i < submission_callbacks_.size(); ++i) {
+ submission_callbacks_[i].Run(password_form);
+ }
+
+ pending_login_managers_.clear();
+}
+
+void PasswordManager::OnPasswordFormsParsed(
+ const std::vector<PasswordForm>& forms) {
+ if(!IsPasswordManagerEnabled()) {
+ return;
+ }
+ // Ask the SSLManager for current security.
+ bool had_ssl_error = driver_->DidLastPageLoadEncounterSSLErrors();
+
+ for (std::vector<PasswordForm>::const_iterator iter = forms.begin();
+ iter != forms.end(); ++iter) {
+ // Don't involve the password manager if this form corresponds to
+ // SpdyProxy authentication, as indicated by the realm.
+ if (EndsWith(iter->signon_realm, kSpdyProxyRealm, true))
+ continue;
+
+ bool ssl_valid = iter->origin.SchemeIsSecure() && !had_ssl_error;
+ PasswordFormManager* manager = new PasswordFormManager(
+ this, client_, driver_, *iter, ssl_valid);
+ pending_login_managers_.push_back(manager);
+
+ // Avoid prompting the user for access to a password if they don't have
+ // password saving enabled.
+ PasswordStore::AuthorizationPromptPolicy prompt_policy =
+ password_manager_enabled_ ? PasswordStore::ALLOW_PROMPT
+ : PasswordStore::DISALLOW_PROMPT;
+
+ manager->FetchMatchingLoginsFromPasswordStore(prompt_policy);
+ }
+}
+
+bool PasswordManager::ShouldPromptUserToSavePassword() const {
+ return provisional_save_manager_->IsNewLogin() &&
+ !provisional_save_manager_->HasGeneratedPassword() &&
+ !provisional_save_manager_->IsPendingCredentialsPublicSuffixMatch();
+}
+
+void PasswordManager::OnPasswordFormsRendered(
+ const std::vector<PasswordForm>& visible_forms) {
+ if(!IsPasswordManagerEnabled()) {
+ return;
+ }
+
+ if (!provisional_save_manager_.get()) {
+ return;
+ }
+ // If we see the login form again, then the login failed.
+ for (size_t i = 0; i < visible_forms.size(); ++i) {
+ // TODO(vabr): The similarity check is just action equality for now. If it
+ // becomes more complex, it may make sense to consider modifying and using
+ // PasswordFormManager::DoesManage for it.
+ if (visible_forms[i].action.is_valid() &&
+ provisional_save_manager_->pending_credentials().action ==
+ visible_forms[i].action) {
+ provisional_save_manager_->SubmitFailed();
+ provisional_save_manager_.reset();
+ return;
+ }
+ }
+
+ // Looks like a successful login attempt. Either show an infobar or
+ // automatically save the login data. We prompt when the user hasn't already
+ // given consent, either through previously accepting the infobar or by having
+ // the browser generate the password.
+ provisional_save_manager_->SubmitPassed();
+ if (provisional_save_manager_->HasGeneratedPassword())
+ UMA_HISTOGRAM_COUNTS("PasswordGeneration.Submitted", 1);
+
+ if (ShouldPromptUserToSavePassword()) {
+ client_->PromptUserToSavePassword(provisional_save_manager_.release());
+ } else {
+ provisional_save_manager_->Save();
+ provisional_save_manager_.reset();
+ }
+}
+
+void PasswordManager::PossiblyInitializeUsernamesExperiment(
+ const PasswordFormMap& best_matches) const {
+ if (base::FieldTrialList::Find(kOtherPossibleUsernamesExperiment))
+ return;
+
+ bool other_possible_usernames_exist = false;
+ for (autofill::PasswordFormMap::const_iterator it = best_matches.begin();
+ it != best_matches.end(); ++it) {
+ if (!it->second->other_possible_usernames.empty()) {
+ other_possible_usernames_exist = true;
+ break;
+ }
+ }
+
+ if (!other_possible_usernames_exist)
+ return;
+
+ const base::FieldTrial::Probability kDivisor = 100;
+ scoped_refptr<base::FieldTrial> trial(
+ base::FieldTrialList::FactoryGetFieldTrial(
+ kOtherPossibleUsernamesExperiment,
+ kDivisor,
+ "Disabled",
+ 2013, 12, 31,
+ base::FieldTrial::ONE_TIME_RANDOMIZED,
+ NULL));
+ base::FieldTrial::Probability enabled_probability =
+ client_->GetProbabilityForExperiment(kOtherPossibleUsernamesExperiment);
+ trial->AppendGroup("Enabled", enabled_probability);
+}
+
+bool PasswordManager::OtherPossibleUsernamesEnabled() const {
+ return base::FieldTrialList::FindFullName(
+ kOtherPossibleUsernamesExperiment) == "Enabled";
+}
+
+void PasswordManager::Autofill(
+ const PasswordForm& form_for_autofill,
+ const PasswordFormMap& best_matches,
+ const PasswordForm& preferred_match,
+ bool wait_for_username) const {
+ PossiblyInitializeUsernamesExperiment(best_matches);
+
+ // TODO(tedchoc): Switch to only requesting authentication if the user is
+ // acting on the autofilled forms (crbug.com/342594) instead
+ // of on page load.
+ bool authentication_required = preferred_match.use_additional_authentication;
+ for (autofill::PasswordFormMap::const_iterator it = best_matches.begin();
+ !authentication_required && it != best_matches.end(); ++it) {
+ if (it->second->use_additional_authentication)
+ authentication_required = true;
+ }
+
+ switch (form_for_autofill.scheme) {
+ case PasswordForm::SCHEME_HTML: {
+ // Note the check above is required because the observers_ for a non-HTML
+ // schemed password form may have been freed, so we need to distinguish.
+ scoped_ptr<autofill::PasswordFormFillData> fill_data(
+ new autofill::PasswordFormFillData());
+ InitPasswordFormFillData(form_for_autofill,
+ best_matches,
+ &preferred_match,
+ wait_for_username,
+ OtherPossibleUsernamesEnabled(),
+ fill_data.get());
+ if (authentication_required)
+ client_->AuthenticateAutofillAndFillForm(fill_data.Pass());
+ else
+ driver_->FillPasswordForm(*fill_data.get());
+ break;
+ }
+ default:
+ FOR_EACH_OBSERVER(
+ LoginModelObserver,
+ observers_,
+ OnAutofillDataAvailable(preferred_match.username_value,
+ preferred_match.password_value));
+ break;
+ }
+
+ client_->PasswordWasAutofilled(best_matches);
+}
+
+#endif // TIZEN_AUTOFILL_SUPPORT
+
--- /dev/null
+// Copyright (c) 2012 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.
+
+#ifndef PASSWORD_MANAGER_H
+#define PASSWORD_MANAGER_H
+
+#ifdef TIZEN_AUTOFILL_SUPPORT
+
+#include <vector>
+
+#include "base/callback.h"
+#include "base/memory/scoped_ptr.h"
+#include "base/memory/scoped_vector.h"
+#include "base/observer_list.h"
+#include "base/prefs/pref_member.h"
+#include "base/stl_util.h"
+#include "browser/password_manager/password_form_manager.h"
+#include "components/autofill/core/common/password_form.h"
+#include "components/autofill/core/common/password_form_fill_data.h"
+#include "components/password_manager/core/browser/login_model.h"
+
+class PasswordManagerClient;
+class PasswordManagerDriver;
+class PasswordManagerTest;
+class PasswordFormManager;
+class PrefRegistrySimple;
+
+namespace content {
+class WebContents;
+}
+
+namespace user_prefs {
+class PrefRegistrySyncable;
+}
+
+// Per-tab password manager. Handles creation and management of UI elements,
+// receiving password form data from the renderer and managing the password
+// database through the PasswordStore. The PasswordManager is a LoginModel
+// for purposes of supporting HTTP authentication dialogs.
+class PasswordManager : public LoginModel {
+ public:
+ static const char kOtherPossibleUsernamesExperiment[];
+
+ static void RegisterProfilePrefs(user_prefs::PrefRegistrySyncable* registry);
+
+ explicit PasswordManager(PasswordManagerClient* client);
+ virtual ~PasswordManager();
+
+ typedef base::Callback<void(const autofill::PasswordForm&)>
+ PasswordSubmittedCallback;
+
+ // There is no corresponding remove function as currently all of the
+ // owners of these callbacks have sufficient lifetimes so that the callbacks
+ // should always be valid when called.
+ void AddSubmissionCallback(const PasswordSubmittedCallback& callback);
+
+ // Is password manager enabled for autofill password
+ bool IsPasswordManagerEnabled() const;
+
+ // Set password manager enabled for autofill password
+ void SetPasswordManagerEnabled(bool enabled);
+
+ // Called by a PasswordFormManager when it decides a form can be autofilled
+ // on the page.
+ virtual void Autofill(const autofill::PasswordForm& form_for_autofill,
+ const autofill::PasswordFormMap& best_matches,
+ const autofill::PasswordForm& preferred_match,
+ bool wait_for_username) const;
+
+ // LoginModel implementation.
+ virtual void AddObserver(LoginModelObserver* observer) OVERRIDE;
+ virtual void RemoveObserver(LoginModelObserver* observer) OVERRIDE;
+
+ // Mark this form as having a generated password.
+ void SetFormHasGeneratedPassword(const autofill::PasswordForm& form);
+
+ // TODO(isherman): This should not be public, but is currently being used by
+ // the LoginPrompt code.
+ // When a form is submitted, we prepare to save the password but wait
+ // until we decide the user has successfully logged in. This is step 1
+ // of 2 (see SavePassword).
+ void ProvisionallySavePassword(const autofill::PasswordForm& form);
+
+ // Should be called when the user navigates the main frame.
+ void DidNavigateMainFrame(bool is_in_page);
+
+ // Handles password forms being parsed.
+ void OnPasswordFormsParsed(
+ const std::vector<autofill::PasswordForm>& forms);
+
+ // Handles password forms being rendered.
+ void OnPasswordFormsRendered(
+ const std::vector<autofill::PasswordForm>& visible_forms);
+
+ // Handles a password form being submitted.
+ virtual void OnPasswordFormSubmitted(
+ const autofill::PasswordForm& password_form);
+
+ private:
+ enum ProvisionalSaveFailure {
+ SAVING_DISABLED,
+ EMPTY_PASSWORD,
+ NO_MATCHING_FORM,
+ MATCHING_NOT_COMPLETE,
+ FORM_BLACKLISTED,
+ INVALID_FORM,
+ AUTOCOMPLETE_OFF,
+ MAX_FAILURE_VALUE
+ };
+
+ // Log failure for UMA. Logs additional metrics if the |form_origin|
+ // corresponds to one of the top, explicitly monitored websites.
+ void RecordFailure(ProvisionalSaveFailure failure,
+ const std::string& form_origin);
+
+ // Possibly set up FieldTrial for testing other possible usernames. This only
+ // happens if there are other_possible_usernames to be shown and the
+ // experiment hasn't already been initialized. We setup the experiment at
+ // such a late time because this experiment will only affect a small number
+ // of users so we want to include a larger fraction of these users than the
+ // normal 10%.
+ void PossiblyInitializeUsernamesExperiment(
+ const autofill::PasswordFormMap& matches) const;
+
+ // Returns true if we can show possible usernames to users in cases where
+ // the username for the form is ambigious.
+ bool OtherPossibleUsernamesEnabled() const;
+
+ // Returns true if the user needs to be prompted before a password can be
+ // saved (instead of automatically saving
+ // the password), based on inspecting the state of
+ // |provisional_save_manager_|.
+ bool ShouldPromptUserToSavePassword() const;
+
+ // Note about how a PasswordFormManager can transition from
+ // pending_login_managers_ to provisional_save_manager_ and the infobar.
+ //
+ // 1. form "seen"
+ // | new
+ // | ___ Infobar
+ // pending_login -- form submit --> provisional_save ___/
+ // ^ | \___ (update DB)
+ // | fail
+ // |-----------<------<---------| !new
+ //
+ // When a form is "seen" on a page, a PasswordFormManager is created
+ // and stored in this collection until user navigates away from page.
+
+ ScopedVector<PasswordFormManager> pending_login_managers_;
+
+ // When the user submits a password/credential, this contains the
+ // PasswordFormManager for the form in question until we deem the login
+ // attempt to have succeeded (as in valid credentials). If it fails, we
+ // send the PasswordFormManager back to the pending_login_managers_ set.
+ // Scoped in case PasswordManager gets deleted (e.g tab closes) between the
+ // time a user submits a login form and gets to the next page.
+ scoped_ptr<PasswordFormManager> provisional_save_manager_;
+
+ // The embedder-level client. Must outlive this class.
+ PasswordManagerClient* const client_;
+
+ // The platform-level driver. Must outlive this class.
+ PasswordManagerDriver* const driver_;
+
+ // Set to false to disable the password manager (will no longer ask if you
+ // want to save passwords but will continue to fill passwords).
+ bool password_manager_enabled_;
+
+ // Observers to be notified of LoginModel events. This is mutable to allow
+ // notification in const member functions.
+ mutable ObserverList<LoginModelObserver> observers_;
+
+ // Callbacks to be notified when a password form has been submitted.
+ std::vector<PasswordSubmittedCallback> submission_callbacks_;
+
+ DISALLOW_COPY_AND_ASSIGN(PasswordManager);
+};
+
+#endif // TIZEN_AUTOFILL_SUPPORT
+
+#endif // PASSWORD_MANAGER_H
--- /dev/null
+// Copyright 2014 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.
+
+#ifdef TIZEN_AUTOFILL_SUPPORT
+
+#include "browser/password_manager/password_manager_client.h"
+
+base::FieldTrial::Probability
+PasswordManagerClient::GetProbabilityForExperiment(
+ const std::string& experiment_name) {
+ return 0;
+}
+
+bool PasswordManagerClient::IsPasswordSyncEnabled() { return false; }
+
+#endif // TIZEN_AUTOFILL_SUPPORT
\ No newline at end of file
--- /dev/null
+// Copyright 2014 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.
+
+#ifndef PASSWORD_MANAGER_CLIENT_H
+#define PASSWORD_MANAGER_CLIENT_H
+
+#ifdef TIZEN_AUTOFILL_SUPPORT
+
+#include "base/metrics/field_trial.h"
+#include "components/autofill/core/common/password_form.h"
+#include "components/autofill/core/common/password_form_fill_data.h"
+
+class PasswordFormManager;
+class PasswordManagerDriver;
+class PasswordStore;
+class PrefService;
+
+// An abstraction of operations that depend on the embedders (e.g. Chrome)
+// environment.
+class PasswordManagerClient {
+ public:
+ PasswordManagerClient() {}
+ virtual ~PasswordManagerClient() {}
+
+ // Informs the embedder of a password form that can be saved if the user
+ // allows it. The embedder is not required to prompt the user if it decides
+ // that this form doesn't need to be saved.
+ virtual void PromptUserToSavePassword(PasswordFormManager* form_to_save) = 0;
+
+ // Called when a password is autofilled. Default implementation is a no-op.
+ virtual void PasswordWasAutofilled(
+ const autofill::PasswordFormMap& best_matches) const {}
+
+ // Called to authenticate the autofill password data. If authentication is
+ // successful, this should continue filling the form.
+ virtual void AuthenticateAutofillAndFillForm(
+ scoped_ptr<autofill::PasswordFormFillData> fill_data) = 0;
+
+ // Returns the PasswordStore associated with this instance.
+ virtual PasswordStore* GetPasswordStore() = 0;
+
+ // Returns the PasswordManagerDriver instance associated with this instance.
+ virtual PasswordManagerDriver* GetDriver() = 0;
+
+ // Returns the probability that the experiment identified by |experiment_name|
+ // should be enabled. The default implementation returns 0.
+ virtual base::FieldTrial::Probability GetProbabilityForExperiment(
+ const std::string& experiment_name);
+
+ // Returns true if password sync is enabled in the embedder. The default
+ // implementation returns false.
+ virtual bool IsPasswordSyncEnabled();
+
+ private:
+ DISALLOW_COPY_AND_ASSIGN(PasswordManagerClient);
+};
+
+#endif // TIZEN_AUTOFILL_SUPPORT
+
+#endif // PASSWORD_MANAGER_CLIENT_H
--- /dev/null
+// Copyright 2014 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.
+
+#ifndef PASSWORD_MANAGER_DRIVER_H
+#define PASSWORD_MANAGER_DRIVER_H
+
+#ifdef TIZEN_AUTOFILL_SUPPORT
+
+class PasswordGenerationManager;
+class PasswordManager;
+
+namespace autofill {
+class AutofillManager;
+struct PasswordForm;
+struct PasswordFormFillData;
+} // namespace autofill
+
+// Interface that allows PasswordManager core code to interact with its driver
+// (i.e., obtain information from it and give information to it).
+class PasswordManagerDriver {
+ public:
+ PasswordManagerDriver() {}
+ virtual ~PasswordManagerDriver() {}
+
+ // Fills forms matching |form_data|.
+ virtual void FillPasswordForm(
+ const autofill::PasswordFormFillData& form_data) = 0;
+
+ // Returns whether any SSL certificate errors were encountered as a result of
+ // the last page load.
+ virtual bool DidLastPageLoadEncounterSSLErrors() = 0;
+
+ // If this browsing session should not be persisted.
+ virtual bool IsOffTheRecord() = 0;
+
+ // Returns the PasswordGenerationManager associated with this instance.
+ virtual PasswordGenerationManager* GetPasswordGenerationManager() = 0;
+
+ // Returns the PasswordManager associated with this instance.
+ virtual PasswordManager* GetPasswordManager() = 0;
+
+ // Returns the AutofillManager associated with this instance.
+ virtual autofill::AutofillManager* GetAutofillManager() = 0;
+
+ // Informs the driver that |form| can be used for password generation.
+ virtual void AllowPasswordGenerationForForm(autofill::PasswordForm* form) = 0;
+
+ private:
+ DISALLOW_COPY_AND_ASSIGN(PasswordManagerDriver);
+};
+
+#endif // TIZEN_AUTOFILL_SUPPORT
+
+#endif // PASSWORD_MANAGER_DRIVER_H
--- /dev/null
+// Copyright 2013 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.
+
+#ifndef PASSWORD_MANAGER_UTIL_H
+#define PASSWORD_MANAGER_UTIL_H
+
+#ifdef TIZEN_AUTOFILL_SUPPORT
+
+#include "base/basictypes.h"
+#include "ui/gfx/native_widget_types.h"
+
+namespace password_manager_util {
+
+enum OsPasswordStatus {
+ PASSWORD_STATUS_UNKNOWN = 0,
+ PASSWORD_STATUS_UNSUPPORTED,
+ PASSWORD_STATUS_BLANK,
+ PASSWORD_STATUS_NONBLANK,
+ PASSWORD_STATUS_WIN_DOMAIN,
+ // NOTE: Add new status types only immediately above this line. Also,
+ // make sure the enum list in tools/histogram/histograms.xml is
+ // updated with any change in here.
+ MAX_PASSWORD_STATUS
+};
+
+// Attempts to (re-)authenticate the user of the OS account. Returns true if
+// the user was successfully authenticated, or if authentication was not
+// possible. On platforms where reauthentication is not possible or does not
+// make sense, the default implementation always returns true.
+bool AuthenticateUser(gfx::NativeWindow window);
+
+// Query the system to determine whether the current logged on user has a
+// password set on their OS account. Returns one of the OsPasswordStatus
+// enum values.
+OsPasswordStatus GetOsPasswordStatus();
+
+} // namespace password_manager_util
+
+#endif // TIZEN_AUTOFILL_SUPPORT
+
+#endif // PASSWORD_MANAGER_UTIL_H
--- /dev/null
+// Copyright (c) 2012 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.
+
+#ifdef TIZEN_AUTOFILL_SUPPORT
+
+#include "browser/password_manager/password_store_factory.h"
+
+#include "base/command_line.h"
+#include "base/environment.h"
+#include "base/prefs/pref_service.h"
+#include "base/path_service.h"
+#include "base/files/file_path.h"
+#include "paths_efl.h"
+#include "browser/webdata/web_data_service.h"
+#include "browser/webdata/web_data_service_factory.h"
+#include "components/browser_context_keyed_service/browser_context_dependency_manager.h"
+#include "components/password_manager/core/browser/login_database.h"
+#include "components/password_manager/core/browser/password_store.h"
+#include "components/password_manager/core/browser/password_store_default.h"
+#include "components/user_prefs/pref_registry_syncable.h"
+#include "content/public/browser/browser_thread.h"
+
+PasswordStoreService::PasswordStoreService(
+ scoped_refptr<PasswordStore> password_store)
+ : password_store_(password_store)
+{
+}
+
+PasswordStoreService::~PasswordStoreService()
+{
+}
+
+scoped_refptr<PasswordStore> PasswordStoreService::GetPasswordStore()
+{
+ return password_store_;
+}
+
+void PasswordStoreService::Shutdown()
+{
+ if (password_store_)
+ password_store_->Shutdown();
+}
+
+// static
+scoped_refptr<PasswordStore> PasswordStoreFactory::GetPasswordStore()
+{
+ PasswordStoreService* service = GetInstance()->GetService();
+ if (!service)
+ return NULL;
+ return service->GetPasswordStore();
+}
+
+// static
+PasswordStoreFactory* PasswordStoreFactory::GetInstance()
+{
+ return Singleton<PasswordStoreFactory>::get();
+}
+
+PasswordStoreFactory::PasswordStoreFactory()
+{
+ WebDataServiceFactory::GetInstance();
+ Init();
+}
+
+PasswordStoreFactory::~PasswordStoreFactory()
+{
+}
+
+void PasswordStoreFactory::Init()
+{
+ base::FilePath db_path;
+ PathService::Get(PathsEfl::WEB_DATABSE_DIR, &db_path);
+
+#ifndef OS_TIZEN
+ if(PathService::Override(base::DIR_MODULE, db_path) == false) {
+ LOG(ERROR)<<"Could not access login database path.";
+ return;
+ }
+#endif
+
+ base::FilePath login_db_file_path = db_path.Append(FILE_PATH_LITERAL("LoginData.db"));
+ LOG(ERROR) <<login_db_file_path.value();
+ scoped_ptr<LoginDatabase> login_db(new LoginDatabase());
+ {
+ base::ThreadRestrictions::ScopedAllowIO allow_io;
+ if (!login_db->Init(login_db_file_path)) {
+ LOG(ERROR) << "Could not initialize login database.";
+ return;
+ }
+ }
+
+ scoped_refptr<base::SingleThreadTaskRunner> main_thread_runner(
+ base::MessageLoopProxy::current());
+ scoped_refptr<base::SingleThreadTaskRunner> db_thread_runner(
+ content::BrowserThread::GetMessageLoopProxyForThread(
+ content::BrowserThread::DB));
+
+ scoped_refptr<PasswordStore> ps;
+
+ ps = new PasswordStoreDefault(
+ main_thread_runner, db_thread_runner, login_db.release());
+
+ if (!ps || !ps->Init()) {
+ NOTREACHED() << "Could not initialize password manager.";
+ return;
+ }
+
+ service_ = new PasswordStoreService(ps);
+}
+
+bool PasswordStoreFactory::ServiceIsNULLWhileTesting() const
+{
+ return true;
+}
+#endif // TIZEN_AUTOFILL_SUPPORT
--- /dev/null
+// Copyright (c) 2012 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.
+
+#ifndef PASSWORD_STORE_FACTORY_H
+#define PASSWORD_STORE_FACTORY_H
+
+#ifdef TIZEN_AUTOFILL_SUPPORT
+
+#include "base/basictypes.h"
+#include "base/memory/singleton.h"
+
+class PasswordStore;
+
+// A wrapper of PasswordStore so we can use it as a profiled keyed service.
+class PasswordStoreService {
+ public:
+ // |password_store| needs to be not-NULL, and the constructor expects that
+ // Init() was already called successfully on it.
+ explicit PasswordStoreService(scoped_refptr<PasswordStore> password_store);
+ virtual ~PasswordStoreService();
+
+ scoped_refptr<PasswordStore> GetPasswordStore();
+
+ virtual void Shutdown() OVERRIDE;
+
+ private:
+ scoped_refptr<PasswordStore> password_store_;
+ DISALLOW_COPY_AND_ASSIGN(PasswordStoreService);
+};
+
+// Singleton that owns all PasswordStores and associates them with
+// Profiles.
+class PasswordStoreFactory {
+ public:
+ static scoped_refptr<PasswordStore> GetPasswordStore();
+
+ static PasswordStoreFactory* GetInstance();
+ PasswordStoreService* GetService() { return service_; }
+
+ private:
+ friend struct DefaultSingletonTraits<PasswordStoreFactory>;
+ void Init();
+ PasswordStoreFactory();
+ virtual ~PasswordStoreFactory();
+
+ virtual bool ServiceIsNULLWhileTesting() const OVERRIDE;
+ PasswordStoreService * service_;
+
+ DISALLOW_COPY_AND_ASSIGN(PasswordStoreFactory);
+};
+
+#endif // TIZEN_AUTOFILL_SUPPORT
+
+#endif // PASSWORD_STORE_FACTORY_H
--- /dev/null
+// Copyright (c) 2012 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.
+
+#ifdef TIZEN_AUTOFILL_SUPPORT
+
+#include "browser/webdata/web_data_service.h"
+
+#include "base/bind.h"
+#include "base/stl_util.h"
+#include "components/webdata/common/web_database_service.h"
+#include "content/public/browser/browser_thread.h"
+#include "content/public/browser/notification_details.h"
+#include "content/public/browser/notification_service.h"
+#include "content/public/browser/notification_source.h"
+
+using base::Bind;
+using base::Time;
+using content::BrowserThread;
+
+
+WebDataService::WebDataService(scoped_refptr<WebDatabaseService> wdbs,
+ const ProfileErrorCallback& callback)
+ : WebDataServiceBase(wdbs, callback,
+ BrowserThread::GetMessageLoopProxyForThread(BrowserThread::UI)) {
+}
+
+WebDataService::WebDataService()
+ : WebDataServiceBase(NULL, ProfileErrorCallback(),
+ BrowserThread::GetMessageLoopProxyForThread(BrowserThread::UI)) {
+}
+
+WebDataService::~WebDataService() {
+}
+
+#endif // TIZEN_AUTOFILL_SUPPORT
--- /dev/null
+// Copyright (c) 2012 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.
+
+
+#ifndef WEB_DATA_SERVICE_H
+#define WEB_DATA_SERVICE_H
+
+#ifdef TIZEN_AUTOFILL_SUPPORT
+
+#include <map>
+#include <string>
+#include <vector>
+
+#include "base/callback_forward.h"
+#include "base/files/file_path.h"
+#include "base/location.h"
+#include "base/memory/ref_counted.h"
+#include "base/sequenced_task_runner_helpers.h"
+#include "components/webdata/common/web_data_results.h"
+#include "components/webdata/common/web_data_service_base.h"
+#include "components/webdata/common/web_data_service_consumer.h"
+#include "components/webdata/common/web_database.h"
+
+class GURL;
+class WebDatabaseService;
+
+namespace base {
+class Thread;
+}
+
+namespace content {
+class BrowserContext;
+}
+
+////////////////////////////////////////////////////////////////////////////////
+//
+// WebDataService is a generic data repository for meta data associated with
+// web pages. All data is retrieved and archived in an asynchronous way.
+//
+// All requests return a handle. The handle can be used to cancel the request.
+//
+////////////////////////////////////////////////////////////////////////////////
+
+typedef base::Callback<scoped_ptr<WDTypedResult>(void)> ResultTask;
+
+class WebDataServiceConsumer;
+
+class WebDataService : public WebDataServiceBase {
+ public:
+ // Retrieve a WebDataService for the given context.
+ static scoped_refptr<WebDataService> FromBrowserContext(
+ content::BrowserContext* context);
+
+ WebDataService(scoped_refptr<WebDatabaseService> wdbs,
+ const ProfileErrorCallback& callback);
+
+ protected:
+ WebDataService();
+ virtual ~WebDataService();
+
+ private:
+ DISALLOW_COPY_AND_ASSIGN(WebDataService);
+};
+
+#endif // TIZEN_AUTOFILL_SUPPORT
+
+#endif // WEB_DATA_SERVICE_H
--- /dev/null
+// Copyright (c) 2012 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.
+
+#ifdef TIZEN_AUTOFILL_SUPPORT
+
+#include "browser/webdata/web_data_service_factory.h"
+
+#include "eweb_view.h"
+#include "base/bind.h"
+#include "base/path_service.h"
+#include "base/files/file_path.h"
+#include "paths_efl.h"
+#include "browser/webdata/web_data_service.h"
+#include "components/autofill/core/browser/autofill_country.h"
+#include "components/autofill/core/browser/webdata/autofill_table.h"
+#include "components/autofill/core/browser/webdata/autofill_webdata_service.h"
+#include "components/webdata/common/webdata_constants.h"
+#include "content/public/browser/browser_thread.h"
+
+using autofill::AutofillWebDataService;
+using content::BrowserThread;
+
+namespace {
+
+// Callback to show error dialog on profile load error.
+void ProfileErrorCallback(int type, sql::InitStatus status) {
+ //TODO:Need to check what type of error to show
+}
+
+void InitSyncableServicesOnDBThread(
+ scoped_refptr<AutofillWebDataService> autofill_web_data,
+ const base::FilePath& profile_path,
+ const std::string& app_locale,
+ autofill::AutofillWebDataBackend* autofill_backend) {
+ //TODO:Need to check if syncable service is needed
+}
+
+} // namespace
+
+WebDataServiceWrapper* WebDataServiceWrapper::GetInstance(){
+ return Singleton<WebDataServiceWrapper>::get();
+}
+
+WebDataServiceWrapper::WebDataServiceWrapper() {
+ base::FilePath db_path;
+ PathService::Get(PathsEfl::WEB_DATABSE_DIR, &db_path);
+#ifndef OS_TIZEN
+ if(PathService::Override(base::DIR_MODULE, db_path) == false) {
+ LOG(ERROR)<<"Could not access web database path.";
+ return;
+ }
+#endif
+ base::FilePath path = db_path.Append(FILE_PATH_LITERAL("FormData.db"));
+
+ scoped_refptr<base::MessageLoopProxy> ui_thread =
+ BrowserThread::GetMessageLoopProxyForThread(BrowserThread::UI);
+ scoped_refptr<base::MessageLoopProxy> db_thread =
+ BrowserThread::GetMessageLoopProxyForThread(BrowserThread::DB);
+ web_database_ = new WebDatabaseService(path, ui_thread, db_thread);
+
+ // All tables objects that participate in managing the database must
+ // be added here.
+ web_database_->AddTable(
+ scoped_ptr<WebDatabaseTable>(new autofill::AutofillTable(
+ EWebView::GetPlatformLocale())));
+
+ web_database_->LoadDatabase();
+
+ autofill_web_data_ = new AutofillWebDataService(
+ web_database_, ui_thread, db_thread, base::Bind(
+ &ProfileErrorCallback, 0));
+ autofill_web_data_->Init();
+
+ web_data_ = new WebDataService(
+ web_database_, base::Bind(&ProfileErrorCallback,0));
+ web_data_->Init();
+
+ autofill_web_data_->GetAutofillBackend(
+ base::Bind(&InitSyncableServicesOnDBThread,
+ autofill_web_data_,
+ db_path,
+ EWebView::GetPlatformLocale()));
+}
+
+WebDataServiceWrapper::~WebDataServiceWrapper() {
+}
+
+void WebDataServiceWrapper::Shutdown() {
+ autofill_web_data_->ShutdownOnUIThread();
+ web_data_->ShutdownOnUIThread();
+ web_database_->ShutdownDatabase();
+}
+
+scoped_refptr<AutofillWebDataService>
+WebDataServiceWrapper::GetAutofillWebData() {
+ return autofill_web_data_.get();
+}
+
+scoped_refptr<WebDataService> WebDataServiceWrapper::GetWebData() {
+ return web_data_.get();
+}
+
+
+// static
+scoped_refptr<WebDataService> WebDataService::FromBrowserContext(
+ content::BrowserContext* context) {
+ WebDataServiceWrapper* wrapper = WebDataServiceFactory::GetDataService();
+ if (wrapper)
+ return wrapper->GetWebData();
+ // |wrapper| can be NULL in Incognito mode.
+ return scoped_refptr<WebDataService>(NULL);
+}
+
+WebDataServiceFactory::WebDataServiceFactory(){
+ // WebDataServiceFactory has no dependecies.
+}
+
+WebDataServiceFactory::~WebDataServiceFactory() {}
+
+// static
+
+WebDataServiceWrapper* WebDataServiceFactory::GetDataService() {
+ return WebDataServiceWrapper::GetInstance();
+}
+
+// static
+scoped_refptr<AutofillWebDataService>
+WebDataServiceFactory::GetAutofillWebDataForProfile() {
+ WebDataServiceWrapper* wrapper =
+ WebDataServiceFactory::GetDataService();
+ // |wrapper| can be NULL in Incognito mode.
+ return wrapper ?
+ wrapper->GetAutofillWebData() :
+ scoped_refptr<AutofillWebDataService>(NULL);
+}
+
+// static
+WebDataServiceFactory* WebDataServiceFactory::GetInstance() {
+ return Singleton<WebDataServiceFactory>::get();
+}
+
+#endif // TIZEN_AUTOFILL_SUPPORT
--- /dev/null
+// Copyright (c) 2012 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.
+
+#ifndef WEB_DATA_SERVICE_FACTORY_H
+#define WEB_DATA_SERVICE_FACTORY_H
+
+#ifdef TIZEN_AUTOFILL_SUPPORT
+
+#include "base/basictypes.h"
+#include "base/memory/ref_counted.h"
+#include "base/memory/singleton.h"
+#include "components/webdata/common/web_database_service.h"
+
+class WebDataService;
+
+namespace autofill {
+class AutofillWebDataService;
+} // namespace autofill
+
+class WebDataServiceWrapper{
+ public:
+ explicit WebDataServiceWrapper();
+
+ virtual ~WebDataServiceWrapper();
+
+ virtual void Shutdown() OVERRIDE;
+
+ virtual scoped_refptr<autofill::AutofillWebDataService> GetAutofillWebData();
+
+ virtual scoped_refptr<WebDataService> GetWebData();
+
+ static WebDataServiceWrapper* GetInstance();
+ private:
+ scoped_refptr<WebDatabaseService> web_database_;
+
+ scoped_refptr<autofill::AutofillWebDataService> autofill_web_data_;
+ scoped_refptr<WebDataService> web_data_;
+
+ DISALLOW_COPY_AND_ASSIGN(WebDataServiceWrapper);
+};
+
+// Singleton that owns all WebDataServiceWrappers
+class WebDataServiceFactory {
+ public:
+
+ static WebDataServiceWrapper* GetDataService();
+
+ static scoped_refptr<autofill::AutofillWebDataService>
+ GetAutofillWebDataForProfile();
+
+ static WebDataServiceFactory* GetInstance();
+
+ private:
+ friend struct DefaultSingletonTraits<WebDataServiceFactory>;
+
+ WebDataServiceFactory();
+ virtual ~WebDataServiceFactory();
+
+ DISALLOW_COPY_AND_ASSIGN(WebDataServiceFactory);
+};
+
+#endif // TIZEN_AUTOFILL_SUPPORT
+
+#endif // WEB_DATA_SERVICE_FACTORY_H
+