1ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen// Copyright (c) 2011 The Chromium Authors. All rights reserved. 2c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch// Use of this source code is governed by a BSD-style license that can be 3c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch// found in the LICENSE file. 4c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 5c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch#include "chrome/browser/sync/glue/password_model_associator.h" 6c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 7c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch#include <set> 8c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 9c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch#include "base/stl_util-inl.h" 10c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch#include "base/utf_string_conversions.h" 11c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch#include "chrome/browser/password_manager/password_store.h" 12c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch#include "chrome/browser/sync/engine/syncapi.h" 13c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch#include "chrome/browser/sync/profile_sync_service.h" 14c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch#include "chrome/browser/sync/protocol/password_specifics.pb.h" 15c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch#include "net/base/escape.h" 16c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch#include "webkit/glue/password_form.h" 17c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 18c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdochnamespace browser_sync { 19c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 20c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdochconst char kPasswordTag[] = "google_chrome_passwords"; 21c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 22c407dc5cd9bdc5668497f21b26b09d988ab439deBen MurdochPasswordModelAssociator::PasswordModelAssociator( 23c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch ProfileSyncService* sync_service, 24c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch PasswordStore* password_store) 25c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch : sync_service_(sync_service), 26c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch password_store_(password_store), 27c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch password_node_id_(sync_api::kInvalidId), 28c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch abort_association_pending_(false), 29c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch expected_loop_(MessageLoop::current()) { 30c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch DCHECK(sync_service_); 31c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch DCHECK(password_store_); 32c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch#if defined(OS_MACOSX) 33731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick DCHECK(!BrowserThread::CurrentlyOn(BrowserThread::UI)); 34c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch#else 35731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick DCHECK(BrowserThread::CurrentlyOn(BrowserThread::DB)); 36c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch#endif 37c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch} 38c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 39513209b27ff55e2841eac0e4120199c23acce758Ben MurdochPasswordModelAssociator::~PasswordModelAssociator() {} 40513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch 41c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdochbool PasswordModelAssociator::AssociateModels() { 42c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch DCHECK(expected_loop_ == MessageLoop::current()); 43c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch { 4472a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen base::AutoLock lock(abort_association_pending_lock_); 45c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch abort_association_pending_ = false; 46c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch } 47c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 48ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen // We must not be holding a transaction when we interact with the password 49ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen // store, as it can post tasks to the UI thread which can itself be blocked 50ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen // on our transaction, resulting in deadlock. (http://crbug.com/70658) 51c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch std::vector<webkit_glue::PasswordForm*> passwords; 52c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch if (!password_store_->FillAutofillableLogins(&passwords) || 53c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch !password_store_->FillBlacklistLogins(&passwords)) { 54c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch STLDeleteElements(&passwords); 55c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch LOG(ERROR) << "Could not get the password entries."; 56c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch return false; 57c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch } 58c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 59c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch std::set<std::string> current_passwords; 60c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch PasswordVector new_passwords; 61c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch PasswordVector updated_passwords; 62ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen { 63ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen sync_api::WriteTransaction trans(sync_service_->GetUserShare()); 64ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen sync_api::ReadNode password_root(&trans); 65ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen if (!password_root.InitByTagLookup(kPasswordTag)) { 66ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen LOG(ERROR) << "Server did not create the top-level password node. We " 67ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen << "might be running against an out-of-date server."; 68c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch return false; 69ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen } 70c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 71ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen for (std::vector<webkit_glue::PasswordForm*>::iterator ix = 72ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen passwords.begin(); 73ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen ix != passwords.end(); ++ix) { 74ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen if (IsAbortPending()) 75ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen return false; 76ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen std::string tag = MakeTag(**ix); 77ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen 78ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen sync_api::ReadNode node(&trans); 79ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen if (node.InitByClientTagLookup(syncable::PASSWORDS, tag)) { 80ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen const sync_pb::PasswordSpecificsData& password = 81ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen node.GetPasswordSpecifics(); 82ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen DCHECK_EQ(tag, MakeTag(password)); 83ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen 84ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen webkit_glue::PasswordForm new_password; 85ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen 86ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen if (MergePasswords(password, **ix, &new_password)) { 87ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen sync_api::WriteNode write_node(&trans); 88ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen if (!write_node.InitByClientTagLookup(syncable::PASSWORDS, tag)) { 89ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen STLDeleteElements(&passwords); 90ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen LOG(ERROR) << "Failed to edit password sync node."; 91ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen return false; 92ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen } 93ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen WriteToSyncNode(new_password, &write_node); 94ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen updated_passwords.push_back(new_password); 95ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen } 96c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 97ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen Associate(&tag, node.GetId()); 98ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen } else { 99ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen sync_api::WriteNode node(&trans); 100ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen if (!node.InitUniqueByCreation(syncable::PASSWORDS, 101ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen password_root, tag)) { 102c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch STLDeleteElements(&passwords); 103ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen LOG(ERROR) << "Failed to create password sync node."; 104c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch return false; 105c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch } 106c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 107ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen WriteToSyncNode(**ix, &node); 108c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 109ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen Associate(&tag, node.GetId()); 110ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen } 111c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 112ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen current_passwords.insert(tag); 113c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch } 114c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 115ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen STLDeleteElements(&passwords); 116c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 117ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen int64 sync_child_id = password_root.GetFirstChildId(); 118ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen while (sync_child_id != sync_api::kInvalidId) { 119ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen sync_api::ReadNode sync_child_node(&trans); 120ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen if (!sync_child_node.InitByIdLookup(sync_child_id)) { 121ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen LOG(ERROR) << "Failed to fetch child node."; 122ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen return false; 123ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen } 124ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen const sync_pb::PasswordSpecificsData& password = 125ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen sync_child_node.GetPasswordSpecifics(); 126ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen std::string tag = MakeTag(password); 127c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 128ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen // The password only exists on the server. Add it to the local 129ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen // model. 130ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen if (current_passwords.find(tag) == current_passwords.end()) { 131ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen webkit_glue::PasswordForm new_password; 132c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 133ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen CopyPassword(password, &new_password); 134ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen Associate(&tag, sync_child_node.GetId()); 135ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen new_passwords.push_back(new_password); 136ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen } 137ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen 138ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen sync_child_id = sync_child_node.GetSuccessorId(); 139ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen } 140c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch } 141c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 142ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen // We must not be holding a transaction when we interact with the password 143ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen // store, as it can post tasks to the UI thread which can itself be blocked 144ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen // on our transaction, resulting in deadlock. (http://crbug.com/70658) 145c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch if (!WriteToPasswordStore(&new_passwords, &updated_passwords, NULL)) { 146c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch LOG(ERROR) << "Failed to write passwords."; 147c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch return false; 148c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch } 149c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 150c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch return true; 151c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch} 152c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 153c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdochbool PasswordModelAssociator::DeleteAllNodes( 154c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch sync_api::WriteTransaction* trans) { 155c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch DCHECK(expected_loop_ == MessageLoop::current()); 156c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch for (PasswordToSyncIdMap::iterator node_id = id_map_.begin(); 157c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch node_id != id_map_.end(); ++node_id) { 158c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch sync_api::WriteNode sync_node(trans); 159c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch if (!sync_node.InitByIdLookup(node_id->second)) { 160c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch LOG(ERROR) << "Typed url node lookup failed."; 161c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch return false; 162c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch } 163c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch sync_node.Remove(); 164c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch } 165c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 166c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch id_map_.clear(); 167c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch id_map_inverse_.clear(); 168c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch return true; 169c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch} 170c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 171c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdochbool PasswordModelAssociator::DisassociateModels() { 172c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch id_map_.clear(); 173c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch id_map_inverse_.clear(); 174c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch return true; 175c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch} 176c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 177c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdochbool PasswordModelAssociator::SyncModelHasUserCreatedNodes(bool* has_nodes) { 178c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch DCHECK(has_nodes); 179c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch *has_nodes = false; 180c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch int64 password_sync_id; 181c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch if (!GetSyncIdForTaggedNode(kPasswordTag, &password_sync_id)) { 182c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch LOG(ERROR) << "Server did not create the top-level password node. We " 183c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch << "might be running against an out-of-date server."; 184c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch return false; 185c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch } 18672a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen sync_api::ReadTransaction trans(sync_service_->GetUserShare()); 187c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 188c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch sync_api::ReadNode password_node(&trans); 189c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch if (!password_node.InitByIdLookup(password_sync_id)) { 190c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch LOG(ERROR) << "Server did not create the top-level password node. We " 191c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch << "might be running against an out-of-date server."; 192c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch return false; 193c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch } 194c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 195c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch // The sync model has user created nodes if the password folder has any 196c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch // children. 197c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch *has_nodes = sync_api::kInvalidId != password_node.GetFirstChildId(); 198c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch return true; 199c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch} 200c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 201c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdochvoid PasswordModelAssociator::AbortAssociation() { 202731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); 20372a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen base::AutoLock lock(abort_association_pending_lock_); 204c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch abort_association_pending_ = true; 205c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch} 206c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 207ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsenbool PasswordModelAssociator::CryptoReadyIfNecessary() { 208ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen // We only access the cryptographer while holding a transaction. 209ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen sync_api::ReadTransaction trans(sync_service_->GetUserShare()); 210ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen // We always encrypt passwords, so no need to check if encryption is enabled. 211ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen return sync_service_->IsCryptographerReady(&trans); 212ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen} 213ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen 21421d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsenconst std::string* PasswordModelAssociator::GetChromeNodeFromSyncId( 21521d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen int64 sync_id) { 21621d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen return NULL; 21721d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen} 21821d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen 21921d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsenbool PasswordModelAssociator::InitSyncNodeFromChromeId( 22021d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen const std::string& node_id, 22121d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen sync_api::BaseNode* sync_node) { 22221d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen return false; 22321d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen} 22421d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen 225c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdochbool PasswordModelAssociator::IsAbortPending() { 22672a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen base::AutoLock lock(abort_association_pending_lock_); 227c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch return abort_association_pending_; 228c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch} 229c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 230c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdochint64 PasswordModelAssociator::GetSyncIdFromChromeId( 23121d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen const std::string& password) { 232c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch PasswordToSyncIdMap::const_iterator iter = id_map_.find(password); 233c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch return iter == id_map_.end() ? sync_api::kInvalidId : iter->second; 234c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch} 235c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 236c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdochvoid PasswordModelAssociator::Associate( 237c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch const std::string* password, int64 sync_id) { 238c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch DCHECK(expected_loop_ == MessageLoop::current()); 239c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch DCHECK_NE(sync_api::kInvalidId, sync_id); 240c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch DCHECK(id_map_.find(*password) == id_map_.end()); 241c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch DCHECK(id_map_inverse_.find(sync_id) == id_map_inverse_.end()); 242c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch id_map_[*password] = sync_id; 243c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch id_map_inverse_[sync_id] = *password; 244c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch} 245c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 246c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdochvoid PasswordModelAssociator::Disassociate(int64 sync_id) { 247c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch DCHECK(expected_loop_ == MessageLoop::current()); 248c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch SyncIdToPasswordMap::iterator iter = id_map_inverse_.find(sync_id); 249c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch if (iter == id_map_inverse_.end()) 250c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch return; 251c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch CHECK(id_map_.erase(iter->second)); 252c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch id_map_inverse_.erase(iter); 253c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch} 254c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 255c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdochbool PasswordModelAssociator::GetSyncIdForTaggedNode(const std::string& tag, 256c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch int64* sync_id) { 25772a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen sync_api::ReadTransaction trans(sync_service_->GetUserShare()); 258c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch sync_api::ReadNode sync_node(&trans); 259c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch if (!sync_node.InitByTagLookup(tag.c_str())) 260c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch return false; 261c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch *sync_id = sync_node.GetId(); 262c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch return true; 263c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch} 264c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 265c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdochbool PasswordModelAssociator::WriteToPasswordStore( 266c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch const PasswordVector* new_passwords, 267c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch const PasswordVector* updated_passwords, 268c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch const PasswordVector* deleted_passwords) { 269c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch if (new_passwords) { 270c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch for (PasswordVector::const_iterator password = new_passwords->begin(); 271c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch password != new_passwords->end(); ++password) { 272c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch password_store_->AddLoginImpl(*password); 273c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch } 274c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch } 275c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 276c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch if (updated_passwords) { 277c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch for (PasswordVector::const_iterator password = updated_passwords->begin(); 278c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch password != updated_passwords->end(); ++password) { 279c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch password_store_->UpdateLoginImpl(*password); 280c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch } 281c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch } 282c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 283c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch if (deleted_passwords) { 284c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch for (PasswordVector::const_iterator password = deleted_passwords->begin(); 285c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch password != deleted_passwords->end(); ++password) { 286c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch password_store_->RemoveLoginImpl(*password); 287c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch } 288c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch } 289ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen 290ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen if (new_passwords || updated_passwords || deleted_passwords) { 291ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen // We have to notify password store observers of the change by hand since 292ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen // we use internal password store interfaces to make changes synchronously. 293ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen password_store_->PostNotifyLoginsChanged(); 294ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen } 295c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch return true; 296c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch} 297c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 298c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch// static 299c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdochvoid PasswordModelAssociator::CopyPassword( 300c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch const sync_pb::PasswordSpecificsData& password, 301c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch webkit_glue::PasswordForm* new_password) { 302c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch new_password->scheme = 303c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch static_cast<webkit_glue::PasswordForm::Scheme>(password.scheme()); 304c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch new_password->signon_realm = password.signon_realm(); 305c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch new_password->origin = GURL(password.origin()); 306c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch new_password->action = GURL(password.action()); 307c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch new_password->username_element = 308c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch UTF8ToUTF16(password.username_element()); 309c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch new_password->password_element = 310c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch UTF8ToUTF16(password.password_element()); 311c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch new_password->username_value = 312c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch UTF8ToUTF16(password.username_value()); 313c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch new_password->password_value = 314c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch UTF8ToUTF16(password.password_value()); 315c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch new_password->ssl_valid = password.ssl_valid(); 316c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch new_password->preferred = password.preferred(); 317c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch new_password->date_created = 318c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch base::Time::FromInternalValue(password.date_created()); 319c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch new_password->blacklisted_by_user = 320c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch password.blacklisted(); 321c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch} 322c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 323c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch// static 324c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdochbool PasswordModelAssociator::MergePasswords( 325c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch const sync_pb::PasswordSpecificsData& password, 326c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch const webkit_glue::PasswordForm& password_form, 327c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch webkit_glue::PasswordForm* new_password) { 328c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch DCHECK(new_password); 329c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 330c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch if (password.scheme() == password_form.scheme && 331c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch password_form.signon_realm == password.signon_realm() && 332c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch password_form.origin.spec() == password.origin() && 333c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch password_form.action.spec() == password.action() && 334c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch UTF16ToUTF8(password_form.username_element) == 335c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch password.username_element() && 336c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch UTF16ToUTF8(password_form.password_element) == 337c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch password.password_element() && 338c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch UTF16ToUTF8(password_form.username_value) == 339c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch password.username_value() && 340c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch UTF16ToUTF8(password_form.password_value) == 341c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch password.password_value() && 342c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch password.ssl_valid() == password_form.ssl_valid && 343c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch password.preferred() == password_form.preferred && 344c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch password.date_created() == password_form.date_created.ToInternalValue() && 345c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch password.blacklisted() == password_form.blacklisted_by_user) { 346c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch return false; 347c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch } 348c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 349c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch // If the passwords differ, we take the one that was created more recently. 350c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch if (base::Time::FromInternalValue(password.date_created()) <= 351c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch password_form.date_created) { 352c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch *new_password = password_form; 353c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch } else { 354c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch CopyPassword(password, new_password); 355c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch } 356c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 357c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch return true; 358c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch} 359c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 360c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch// static 361c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdochvoid PasswordModelAssociator::WriteToSyncNode( 362c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch const webkit_glue::PasswordForm& password_form, 363c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch sync_api::WriteNode* node) { 364c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch sync_pb::PasswordSpecificsData password; 365c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch password.set_scheme(password_form.scheme); 366c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch password.set_signon_realm(password_form.signon_realm); 367c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch password.set_origin(password_form.origin.spec()); 368c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch password.set_action(password_form.action.spec()); 369c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch password.set_username_element(UTF16ToUTF8(password_form.username_element)); 370c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch password.set_password_element(UTF16ToUTF8(password_form.password_element)); 371c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch password.set_username_value(UTF16ToUTF8(password_form.username_value)); 372c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch password.set_password_value(UTF16ToUTF8(password_form.password_value)); 373c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch password.set_ssl_valid(password_form.ssl_valid); 374c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch password.set_preferred(password_form.preferred); 375c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch password.set_date_created(password_form.date_created.ToInternalValue()); 376c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch password.set_blacklisted(password_form.blacklisted_by_user); 377c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 378c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch node->SetPasswordSpecifics(password); 379c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch} 380c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 381c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch// static 382c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdochstd::string PasswordModelAssociator::MakeTag( 383c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch const webkit_glue::PasswordForm& password) { 384c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch return MakeTag(password.origin.spec(), 3853345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick UTF16ToUTF8(password.username_element), 3863345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick UTF16ToUTF8(password.username_value), 3873345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick UTF16ToUTF8(password.password_element), 388c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch password.signon_realm); 389c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch} 390c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 391c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch// static 392c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdochstd::string PasswordModelAssociator::MakeTag( 393c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch const sync_pb::PasswordSpecificsData& password) { 394c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch return MakeTag(password.origin(), 395c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch password.username_element(), 396c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch password.username_value(), 397c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch password.password_element(), 398c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch password.signon_realm()); 399c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch} 400c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 401c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch// static 402c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdochstd::string PasswordModelAssociator::MakeTag( 403c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch const std::string& origin_url, 404c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch const std::string& username_element, 405c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch const std::string& username_value, 406c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch const std::string& password_element, 407c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch const std::string& signon_realm) { 408c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch return EscapePath(origin_url) + "|" + 409c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch EscapePath(username_element) + "|" + 410c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch EscapePath(username_value) + "|" + 411c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch EscapePath(password_element) + "|" + 412c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch EscapePath(signon_realm); 413c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch} 414c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 415c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch} // namespace browser_sync 416