WCS Feature : Chrome reused files
authorUmesh Kumar Patel <umeshk.patel@samsung.com>
Fri, 6 Jun 2014 11:47:20 +0000 (17:17 +0530)
committerYoungsoo Choi <kenshin.choi@samsung.com>
Tue, 10 Jul 2018 06:57:09 +0000 (06:57 +0000)
Change-Id: Ie7498630ba2cd1e0891e1b5b6bdd65be0cdf25ff

18 files changed:
tizen_src/impl/browser/password_manager/content_password_manager_driver.cc [new file with mode: 0644]
tizen_src/impl/browser/password_manager/content_password_manager_driver.h [new file with mode: 0644]
tizen_src/impl/browser/password_manager/password_form_manager.cc [new file with mode: 0644]
tizen_src/impl/browser/password_manager/password_form_manager.h [new file with mode: 0644]
tizen_src/impl/browser/password_manager/password_generation_manager.cc [new file with mode: 0644]
tizen_src/impl/browser/password_manager/password_generation_manager.h [new file with mode: 0644]
tizen_src/impl/browser/password_manager/password_manager.cc [new file with mode: 0644]
tizen_src/impl/browser/password_manager/password_manager.h [new file with mode: 0644]
tizen_src/impl/browser/password_manager/password_manager_client.cc [new file with mode: 0644]
tizen_src/impl/browser/password_manager/password_manager_client.h [new file with mode: 0644]
tizen_src/impl/browser/password_manager/password_manager_driver.h [new file with mode: 0644]
tizen_src/impl/browser/password_manager/password_manager_util.h [new file with mode: 0644]
tizen_src/impl/browser/password_manager/password_store_factory.cc [new file with mode: 0644]
tizen_src/impl/browser/password_manager/password_store_factory.h [new file with mode: 0644]
tizen_src/impl/browser/webdata/web_data_service.cc [new file with mode: 0644]
tizen_src/impl/browser/webdata/web_data_service.h [new file with mode: 0644]
tizen_src/impl/browser/webdata/web_data_service_factory.cc [new file with mode: 0644]
tizen_src/impl/browser/webdata/web_data_service_factory.h [new file with mode: 0644]

diff --git a/tizen_src/impl/browser/password_manager/content_password_manager_driver.cc b/tizen_src/impl/browser/password_manager/content_password_manager_driver.cc
new file mode 100644 (file)
index 0000000..583ab82
--- /dev/null
@@ -0,0 +1,112 @@
+// 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
diff --git a/tizen_src/impl/browser/password_manager/content_password_manager_driver.h b/tizen_src/impl/browser/password_manager/content_password_manager_driver.h
new file mode 100644 (file)
index 0000000..67f25e0
--- /dev/null
@@ -0,0 +1,63 @@
+// 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
diff --git a/tizen_src/impl/browser/password_manager/password_form_manager.cc b/tizen_src/impl/browser/password_manager/password_form_manager.cc
new file mode 100644 (file)
index 0000000..0c1375e
--- /dev/null
@@ -0,0 +1,648 @@
+// 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
diff --git a/tizen_src/impl/browser/password_manager/password_form_manager.h b/tizen_src/impl/browser/password_manager/password_form_manager.h
new file mode 100644 (file)
index 0000000..55df4c9
--- /dev/null
@@ -0,0 +1,320 @@
+// 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
diff --git a/tizen_src/impl/browser/password_manager/password_generation_manager.cc b/tizen_src/impl/browser/password_manager/password_generation_manager.cc
new file mode 100644 (file)
index 0000000..6b67e22
--- /dev/null
@@ -0,0 +1,117 @@
+// 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
diff --git a/tizen_src/impl/browser/password_manager/password_generation_manager.h b/tizen_src/impl/browser/password_manager/password_generation_manager.h
new file mode 100644 (file)
index 0000000..cd06de2
--- /dev/null
@@ -0,0 +1,128 @@
+// 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
diff --git a/tizen_src/impl/browser/password_manager/password_manager.cc b/tizen_src/impl/browser/password_manager/password_manager.cc
new file mode 100644 (file)
index 0000000..cfc7f9e
--- /dev/null
@@ -0,0 +1,380 @@
+// 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
+
diff --git a/tizen_src/impl/browser/password_manager/password_manager.h b/tizen_src/impl/browser/password_manager/password_manager.h
new file mode 100644 (file)
index 0000000..d688945
--- /dev/null
@@ -0,0 +1,182 @@
+// 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
diff --git a/tizen_src/impl/browser/password_manager/password_manager_client.cc b/tizen_src/impl/browser/password_manager/password_manager_client.cc
new file mode 100644 (file)
index 0000000..84d9ec6
--- /dev/null
@@ -0,0 +1,17 @@
+// 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
diff --git a/tizen_src/impl/browser/password_manager/password_manager_client.h b/tizen_src/impl/browser/password_manager/password_manager_client.h
new file mode 100644 (file)
index 0000000..aa536e8
--- /dev/null
@@ -0,0 +1,61 @@
+// 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
diff --git a/tizen_src/impl/browser/password_manager/password_manager_driver.h b/tizen_src/impl/browser/password_manager/password_manager_driver.h
new file mode 100644 (file)
index 0000000..734deb5
--- /dev/null
@@ -0,0 +1,55 @@
+// 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
diff --git a/tizen_src/impl/browser/password_manager/password_manager_util.h b/tizen_src/impl/browser/password_manager/password_manager_util.h
new file mode 100644 (file)
index 0000000..f60da36
--- /dev/null
@@ -0,0 +1,42 @@
+// 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
diff --git a/tizen_src/impl/browser/password_manager/password_store_factory.cc b/tizen_src/impl/browser/password_manager/password_store_factory.cc
new file mode 100644 (file)
index 0000000..82e70e4
--- /dev/null
@@ -0,0 +1,116 @@
+// 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
diff --git a/tizen_src/impl/browser/password_manager/password_store_factory.h b/tizen_src/impl/browser/password_manager/password_store_factory.h
new file mode 100644 (file)
index 0000000..222f944
--- /dev/null
@@ -0,0 +1,55 @@
+// 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
diff --git a/tizen_src/impl/browser/webdata/web_data_service.cc b/tizen_src/impl/browser/webdata/web_data_service.cc
new file mode 100644 (file)
index 0000000..57133b0
--- /dev/null
@@ -0,0 +1,36 @@
+// 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
diff --git a/tizen_src/impl/browser/webdata/web_data_service.h b/tizen_src/impl/browser/webdata/web_data_service.h
new file mode 100644 (file)
index 0000000..dc544f2
--- /dev/null
@@ -0,0 +1,68 @@
+// 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
diff --git a/tizen_src/impl/browser/webdata/web_data_service_factory.cc b/tizen_src/impl/browser/webdata/web_data_service_factory.cc
new file mode 100644 (file)
index 0000000..dc91677
--- /dev/null
@@ -0,0 +1,143 @@
+// 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
diff --git a/tizen_src/impl/browser/webdata/web_data_service_factory.h b/tizen_src/impl/browser/webdata/web_data_service_factory.h
new file mode 100644 (file)
index 0000000..37ac213
--- /dev/null
@@ -0,0 +1,66 @@
+// 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
+