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/engine/syncapi.h" 6c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 7dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen#include <algorithm> 83345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick#include <bitset> 9c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch#include <iomanip> 10c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch#include <list> 11dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen#include <queue> 12c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch#include <string> 13c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch#include <vector> 14c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 15c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch#include "base/base64.h" 16dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen#include "base/command_line.h" 17c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch#include "base/logging.h" 18ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen#include "base/memory/scoped_ptr.h" 19c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch#include "base/message_loop.h" 2072a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen#include "base/observer_list.h" 21c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch#include "base/sha1.h" 2272a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen#include "base/string_number_conversions.h" 23c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch#include "base/string_util.h" 2472a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen#include "base/synchronization/lock.h" 25c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch#include "base/task.h" 26ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen#include "base/time.h" 27c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch#include "base/utf_string_conversions.h" 2872a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen#include "base/values.h" 29c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch#include "chrome/browser/sync/engine/all_status.h" 30c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch#include "chrome/browser/sync/engine/change_reorder_buffer.h" 31c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch#include "chrome/browser/sync/engine/model_safe_worker.h" 32ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen#include "chrome/browser/sync/engine/nudge_source.h" 33c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch#include "chrome/browser/sync/engine/net/server_connection_manager.h" 34c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch#include "chrome/browser/sync/engine/net/syncapi_server_connection_manager.h" 35c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch#include "chrome/browser/sync/engine/syncer.h" 36c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch#include "chrome/browser/sync/engine/syncer_thread.h" 37ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen#include "chrome/browser/sync/engine/http_post_provider_factory.h" 3872a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen#include "chrome/browser/sync/js_arg_list.h" 3972a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen#include "chrome/browser/sync/js_backend.h" 4072a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen#include "chrome/browser/sync/js_event_router.h" 41ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen#include "chrome/browser/sync/notifier/sync_notifier.h" 42ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen#include "chrome/browser/sync/notifier/sync_notifier_observer.h" 433345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick#include "chrome/browser/sync/protocol/app_specifics.pb.h" 44c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch#include "chrome/browser/sync/protocol/autofill_specifics.pb.h" 45c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch#include "chrome/browser/sync/protocol/bookmark_specifics.pb.h" 46c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch#include "chrome/browser/sync/protocol/extension_specifics.pb.h" 47c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch#include "chrome/browser/sync/protocol/nigori_specifics.pb.h" 48c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch#include "chrome/browser/sync/protocol/preference_specifics.pb.h" 4972a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen#include "chrome/browser/sync/protocol/proto_value_conversions.h" 50c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch#include "chrome/browser/sync/protocol/service_constants.h" 5172a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen#include "chrome/browser/sync/protocol/session_specifics.pb.h" 52c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch#include "chrome/browser/sync/protocol/sync.pb.h" 53c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch#include "chrome/browser/sync/protocol/theme_specifics.pb.h" 54c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch#include "chrome/browser/sync/protocol/typed_url_specifics.pb.h" 5572a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen#include "chrome/browser/sync/sessions/sync_session.h" 56c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch#include "chrome/browser/sync/sessions/sync_session_context.h" 5721d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen#include "chrome/browser/sync/syncable/autofill_migration.h" 58ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen#include "chrome/browser/sync/syncable/directory_change_listener.h" 59c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch#include "chrome/browser/sync/syncable/directory_manager.h" 60ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen#include "chrome/browser/sync/syncable/model_type_payload_map.h" 61ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen#include "chrome/browser/sync/syncable/model_type.h" 62dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen#include "chrome/browser/sync/syncable/nigori_util.h" 63c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch#include "chrome/browser/sync/syncable/syncable.h" 64c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch#include "chrome/browser/sync/util/crypto_helpers.h" 65dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen#include "chrome/common/chrome_switches.h" 66c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch#include "chrome/common/deprecated/event_sys.h" 67c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch#include "chrome/common/net/gaia/gaia_authenticator.h" 68dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen#include "content/browser/browser_thread.h" 69c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch#include "net/base/network_change_notifier.h" 70c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 71ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsenusing base::TimeDelta; 72c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdochusing browser_sync::AllStatus; 73c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdochusing browser_sync::Cryptographer; 74c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdochusing browser_sync::KeyParams; 75c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdochusing browser_sync::ModelSafeRoutingInfo; 76c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdochusing browser_sync::ModelSafeWorker; 77c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdochusing browser_sync::ModelSafeWorkerRegistrar; 783345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrickusing browser_sync::ServerConnectionEvent; 79ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsenusing browser_sync::ServerConnectionEvent2; 80ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsenusing browser_sync::ServerConnectionEventListener; 81731df977c0511bca2206b5f333555b1205ff1f43Iain Merrickusing browser_sync::SyncEngineEvent; 82731df977c0511bca2206b5f333555b1205ff1f43Iain Merrickusing browser_sync::SyncEngineEventListener; 83c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdochusing browser_sync::Syncer; 84c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdochusing browser_sync::SyncerThread; 85c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdochusing browser_sync::kNigoriTag; 86c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdochusing browser_sync::sessions::SyncSessionContext; 87c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdochusing std::list; 88c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdochusing std::hex; 89c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdochusing std::string; 90c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdochusing std::vector; 91c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdochusing syncable::Directory; 92c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdochusing syncable::DirectoryManager; 93c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdochusing syncable::Entry; 94ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsenusing syncable::ModelTypeBitSet; 95ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsenusing syncable::OriginalEntries; 96ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsenusing syncable::WriterTag; 97c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdochusing syncable::SPECIFICS; 98201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdochusing sync_pb::AutofillProfileSpecifics; 99c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 100c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdochtypedef GoogleServiceAuthError AuthError; 101c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 102c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdochstatic const int kThreadExitTimeoutMsec = 60000; 103c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdochstatic const int kSSLPort = 443; 10472a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsenstatic const int kSyncerThreadDelayMsec = 250; 105c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 106513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch#if defined(OS_CHROMEOS) 107513209b27ff55e2841eac0e4120199c23acce758Ben Murdochstatic const int kChromeOSNetworkChangeReactionDelayHackMsec = 5000; 108513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch#endif // OS_CHROMEOS 109513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch 110c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch// We manage the lifetime of sync_api::SyncManager::SyncInternal ourselves. 111c407dc5cd9bdc5668497f21b26b09d988ab439deBen MurdochDISABLE_RUNNABLE_METHOD_REFCOUNT(sync_api::SyncManager::SyncInternal); 112c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 113c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdochnamespace sync_api { 114c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 115c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdochstatic const FilePath::CharType kBookmarkSyncUserSettingsDatabase[] = 116c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch FILE_PATH_LITERAL("BookmarkSyncSettings.sqlite3"); 117c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdochstatic const char kDefaultNameForNewNodes[] = " "; 118c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 119c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch// The list of names which are reserved for use by the server. 120c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdochstatic const char* kForbiddenServerNames[] = { "", ".", ".." }; 121c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 122c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch////////////////////////////////////////////////////////////////////////// 123c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch// Static helper functions. 124c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 125c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch// Helper function to look up the int64 metahandle of an object given the ID 126c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch// string. 127c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdochstatic int64 IdToMetahandle(syncable::BaseTransaction* trans, 128c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch const syncable::Id& id) { 129c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch syncable::Entry entry(trans, syncable::GET_BY_ID, id); 130c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch if (!entry.good()) 131c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch return kInvalidId; 132c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch return entry.Get(syncable::META_HANDLE); 133c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch} 134c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 135c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch// Checks whether |name| is a server-illegal name followed by zero or more space 136c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch// characters. The three server-illegal names are the empty string, dot, and 137c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch// dot-dot. Very long names (>255 bytes in UTF-8 Normalization Form C) are 138c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch// also illegal, but are not considered here. 139c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdochstatic bool IsNameServerIllegalAfterTrimming(const std::string& name) { 140c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch size_t untrimmed_count = name.find_last_not_of(' ') + 1; 141c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch for (size_t i = 0; i < arraysize(kForbiddenServerNames); ++i) { 142c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch if (name.compare(0, untrimmed_count, kForbiddenServerNames[i]) == 0) 143c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch return true; 144c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch } 145c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch return false; 146c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch} 147c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 148c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdochstatic bool EndsWithSpace(const std::string& string) { 149c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch return !string.empty() && *string.rbegin() == ' '; 150c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch} 151c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 152c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch// When taking a name from the syncapi, append a space if it matches the 153c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch// pattern of a server-illegal name followed by zero or more spaces. 154c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdochstatic void SyncAPINameToServerName(const std::wstring& sync_api_name, 155c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch std::string* out) { 156c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch *out = WideToUTF8(sync_api_name); 157c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch if (IsNameServerIllegalAfterTrimming(*out)) 158c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch out->append(" "); 159c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch} 160c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 161c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch// In the reverse direction, if a server name matches the pattern of a 162c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch// server-illegal name followed by one or more spaces, remove the trailing 163c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch// space. 164c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdochstatic void ServerNameToSyncAPIName(const std::string& server_name, 165c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch std::wstring* out) { 166c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch int length_to_copy = server_name.length(); 167c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch if (IsNameServerIllegalAfterTrimming(server_name) && 168c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch EndsWithSpace(server_name)) 169c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch --length_to_copy; 170c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch if (!UTF8ToWide(server_name.c_str(), length_to_copy, out)) { 171c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch NOTREACHED() << "Could not convert server name from UTF8 to wide"; 172c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch } 173c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch} 174c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 175731df977c0511bca2206b5f333555b1205ff1f43Iain MerrickUserShare::UserShare() {} 176731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick 177731df977c0511bca2206b5f333555b1205ff1f43Iain MerrickUserShare::~UserShare() {} 178731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick 179c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch//////////////////////////////////// 180c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch// BaseNode member definitions. 181c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 182c407dc5cd9bdc5668497f21b26b09d988ab439deBen MurdochBaseNode::BaseNode() {} 183c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 184c407dc5cd9bdc5668497f21b26b09d988ab439deBen MurdochBaseNode::~BaseNode() {} 185c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 186c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdochstd::string BaseNode::GenerateSyncableHash( 187c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch syncable::ModelType model_type, const std::string& client_tag) { 188c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch // blank PB with just the extension in it has termination symbol, 189c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch // handy for delimiter 190c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch sync_pb::EntitySpecifics serialized_type; 191c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch syncable::AddDefaultExtensionValue(model_type, &serialized_type); 192c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch std::string hash_input; 193c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch serialized_type.AppendToString(&hash_input); 194c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch hash_input.append(client_tag); 195c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 196c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch std::string encode_output; 197c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch CHECK(base::Base64Encode(base::SHA1HashString(hash_input), &encode_output)); 198c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch return encode_output; 199c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch} 200c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 2013345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merricksync_pb::PasswordSpecificsData* DecryptPasswordSpecifics( 2023345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick const sync_pb::EntitySpecifics& specifics, Cryptographer* crypto) { 2034a5e2dc747d50c653511c68ccb2cfbfb740bd5a7Ben Murdoch if (!specifics.HasExtension(sync_pb::password)) 2044a5e2dc747d50c653511c68ccb2cfbfb740bd5a7Ben Murdoch return NULL; 205dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen const sync_pb::PasswordSpecifics& password_specifics = 206dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen specifics.GetExtension(sync_pb::password); 207dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen if (!password_specifics.has_encrypted()) 208dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen return NULL; 209dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen const sync_pb::EncryptedData& encrypted = password_specifics.encrypted(); 2103345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick scoped_ptr<sync_pb::PasswordSpecificsData> data( 2113345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick new sync_pb::PasswordSpecificsData); 2123345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick if (!crypto->Decrypt(encrypted, data.get())) 2133345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick return NULL; 2143345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick return data.release(); 2153345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick} 2163345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick 217c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdochbool BaseNode::DecryptIfNecessary(Entry* entry) { 218dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen if (GetIsFolder()) return true; // Ignore the top-level datatype folder. 219c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch const sync_pb::EntitySpecifics& specifics = 220c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch entry->Get(syncable::SPECIFICS); 221c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch if (specifics.HasExtension(sync_pb::password)) { 222dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen // Passwords have their own legacy encryption structure. 2233345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick scoped_ptr<sync_pb::PasswordSpecificsData> data(DecryptPasswordSpecifics( 2243345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick specifics, GetTransaction()->GetCryptographer())); 2253345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick if (!data.get()) 226c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch return false; 227c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch password_data_.swap(data); 228dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen return true; 229dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen } 230dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen 231dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen // We assume any node with the encrypted field set has encrypted data. 232dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen if (!specifics.has_encrypted()) 233dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen return true; 234dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen 235dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen const sync_pb::EncryptedData& encrypted = 236dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen specifics.encrypted(); 237dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen std::string plaintext_data = GetTransaction()->GetCryptographer()-> 238dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen DecryptToString(encrypted); 239dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen if (plaintext_data.length() == 0) 240dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen return false; 241dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen if (!unencrypted_data_.ParseFromString(plaintext_data)) { 242dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen LOG(ERROR) << "Failed to decrypt encrypted node of type " << 243dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen syncable::ModelTypeToString(entry->GetModelType()) << "."; 244dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen return false; 245c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch } 246c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch return true; 247c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch} 248c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 249dc0f95d653279beabeb9817299e2902918ba123eKristian Monsenconst sync_pb::EntitySpecifics& BaseNode::GetUnencryptedSpecifics( 250dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen const syncable::Entry* entry) const { 251dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen const sync_pb::EntitySpecifics& specifics = entry->Get(SPECIFICS); 252dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen if (specifics.has_encrypted()) { 253dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen DCHECK(syncable::GetModelTypeFromSpecifics(unencrypted_data_) != 254dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen syncable::UNSPECIFIED); 255dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen return unencrypted_data_; 256dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen } else { 257dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen DCHECK(syncable::GetModelTypeFromSpecifics(unencrypted_data_) == 258dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen syncable::UNSPECIFIED); 259dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen return specifics; 260dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen } 261dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen} 262dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen 263c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdochint64 BaseNode::GetParentId() const { 264c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch return IdToMetahandle(GetTransaction()->GetWrappedTrans(), 265c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch GetEntry()->Get(syncable::PARENT_ID)); 266c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch} 267c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 268c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdochint64 BaseNode::GetId() const { 269c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch return GetEntry()->Get(syncable::META_HANDLE); 270c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch} 271c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 2723f50c38dc070f4bb515c1b64450dae14f316474eKristian Monsenint64 BaseNode::GetModificationTime() const { 2733f50c38dc070f4bb515c1b64450dae14f316474eKristian Monsen return GetEntry()->Get(syncable::MTIME); 2743f50c38dc070f4bb515c1b64450dae14f316474eKristian Monsen} 2753f50c38dc070f4bb515c1b64450dae14f316474eKristian Monsen 276c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdochbool BaseNode::GetIsFolder() const { 277c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch return GetEntry()->Get(syncable::IS_DIR); 278c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch} 279c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 280c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdochstd::wstring BaseNode::GetTitle() const { 281c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch std::wstring result; 282c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch ServerNameToSyncAPIName(GetEntry()->Get(syncable::NON_UNIQUE_NAME), &result); 283c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch return result; 284c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch} 285c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 286c407dc5cd9bdc5668497f21b26b09d988ab439deBen MurdochGURL BaseNode::GetURL() const { 287c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch return GURL(GetBookmarkSpecifics().url()); 288c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch} 289c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 290c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdochint64 BaseNode::GetPredecessorId() const { 291c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch syncable::Id id_string = GetEntry()->Get(syncable::PREV_ID); 292c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch if (id_string.IsRoot()) 293c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch return kInvalidId; 294c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch return IdToMetahandle(GetTransaction()->GetWrappedTrans(), id_string); 295c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch} 296c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 297c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdochint64 BaseNode::GetSuccessorId() const { 298c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch syncable::Id id_string = GetEntry()->Get(syncable::NEXT_ID); 299c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch if (id_string.IsRoot()) 300c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch return kInvalidId; 301c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch return IdToMetahandle(GetTransaction()->GetWrappedTrans(), id_string); 302c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch} 303c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 304c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdochint64 BaseNode::GetFirstChildId() const { 305c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch syncable::Directory* dir = GetTransaction()->GetLookup(); 306c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch syncable::BaseTransaction* trans = GetTransaction()->GetWrappedTrans(); 307c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch syncable::Id id_string = 308c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch dir->GetFirstChildId(trans, GetEntry()->Get(syncable::ID)); 309c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch if (id_string.IsRoot()) 310c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch return kInvalidId; 311c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch return IdToMetahandle(GetTransaction()->GetWrappedTrans(), id_string); 312c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch} 313c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 31472a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian MonsenDictionaryValue* BaseNode::ToValue() const { 31572a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen DictionaryValue* node_info = new DictionaryValue(); 31672a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen node_info->SetString("id", base::Int64ToString(GetId())); 31772a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen // TODO(akalin): Return time in a better format. 31872a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen node_info->SetString("modificationTime", 31972a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen base::Int64ToString(GetModificationTime())); 32072a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen node_info->SetString("parentId", base::Int64ToString(GetParentId())); 32172a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen node_info->SetBoolean("isFolder", GetIsFolder()); 32272a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen // TODO(akalin): Add a std::string accessor for the title. 32372a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen node_info->SetString("title", WideToUTF8(GetTitle())); 324ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen node_info->Set("type", ModelTypeToValue(GetModelType())); 325ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen // Specifics are already in the Entry value, so no need to duplicate 326ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen // it here. 32772a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen node_info->SetString("externalId", 32872a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen base::Int64ToString(GetExternalId())); 32972a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen node_info->SetString("predecessorId", 33072a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen base::Int64ToString(GetPredecessorId())); 33172a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen node_info->SetString("successorId", 33272a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen base::Int64ToString(GetSuccessorId())); 33372a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen node_info->SetString("firstChildId", 33472a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen base::Int64ToString(GetFirstChildId())); 335ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen node_info->Set("entry", GetEntry()->ToValue()); 33672a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen return node_info; 33772a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen} 33872a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen 339c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdochvoid BaseNode::GetFaviconBytes(std::vector<unsigned char>* output) const { 340c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch if (!output) 341c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch return; 342c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch const std::string& favicon = GetBookmarkSpecifics().favicon(); 343c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch output->assign(reinterpret_cast<const unsigned char*>(favicon.data()), 344c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch reinterpret_cast<const unsigned char*>(favicon.data() + 345c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch favicon.length())); 346c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch} 347c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 348c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdochint64 BaseNode::GetExternalId() const { 349c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch return GetEntry()->Get(syncable::LOCAL_EXTERNAL_ID); 350c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch} 351c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 3523345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrickconst sync_pb::AppSpecifics& BaseNode::GetAppSpecifics() const { 353dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen DCHECK_EQ(syncable::APPS, GetModelType()); 354dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen const sync_pb::EntitySpecifics& unencrypted = 355dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen GetUnencryptedSpecifics(GetEntry()); 356dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen return unencrypted.GetExtension(sync_pb::app); 3573345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick} 3583345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick 359c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdochconst sync_pb::AutofillSpecifics& BaseNode::GetAutofillSpecifics() const { 360dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen DCHECK_EQ(syncable::AUTOFILL, GetModelType()); 361dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen const sync_pb::EntitySpecifics& unencrypted = 362dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen GetUnencryptedSpecifics(GetEntry()); 363dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen return unencrypted.GetExtension(sync_pb::autofill); 364c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch} 365c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 366201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdochconst AutofillProfileSpecifics& BaseNode::GetAutofillProfileSpecifics() const { 367201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch DCHECK_EQ(GetModelType(), syncable::AUTOFILL_PROFILE); 368dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen const sync_pb::EntitySpecifics& unencrypted = 369dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen GetUnencryptedSpecifics(GetEntry()); 370dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen return unencrypted.GetExtension(sync_pb::autofill_profile); 371201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch} 372201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch 373c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdochconst sync_pb::BookmarkSpecifics& BaseNode::GetBookmarkSpecifics() const { 374dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen DCHECK_EQ(syncable::BOOKMARKS, GetModelType()); 375dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen const sync_pb::EntitySpecifics& unencrypted = 376dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen GetUnencryptedSpecifics(GetEntry()); 377dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen return unencrypted.GetExtension(sync_pb::bookmark); 378c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch} 379c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 380c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdochconst sync_pb::NigoriSpecifics& BaseNode::GetNigoriSpecifics() const { 381dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen DCHECK_EQ(syncable::NIGORI, GetModelType()); 382dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen const sync_pb::EntitySpecifics& unencrypted = 383dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen GetUnencryptedSpecifics(GetEntry()); 384dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen return unencrypted.GetExtension(sync_pb::nigori); 385c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch} 386c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 387c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdochconst sync_pb::PasswordSpecificsData& BaseNode::GetPasswordSpecifics() const { 388dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen DCHECK_EQ(syncable::PASSWORDS, GetModelType()); 389c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch DCHECK(password_data_.get()); 390c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch return *password_data_; 391c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch} 392c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 393c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdochconst sync_pb::PreferenceSpecifics& BaseNode::GetPreferenceSpecifics() const { 394dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen DCHECK_EQ(syncable::PREFERENCES, GetModelType()); 395dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen const sync_pb::EntitySpecifics& unencrypted = 396dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen GetUnencryptedSpecifics(GetEntry()); 397dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen return unencrypted.GetExtension(sync_pb::preference); 398c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch} 399c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 400c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdochconst sync_pb::ThemeSpecifics& BaseNode::GetThemeSpecifics() const { 401dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen DCHECK_EQ(syncable::THEMES, GetModelType()); 402dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen const sync_pb::EntitySpecifics& unencrypted = 403dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen GetUnencryptedSpecifics(GetEntry()); 404dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen return unencrypted.GetExtension(sync_pb::theme); 405c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch} 406c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 407c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdochconst sync_pb::TypedUrlSpecifics& BaseNode::GetTypedUrlSpecifics() const { 408dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen DCHECK_EQ(syncable::TYPED_URLS, GetModelType()); 409dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen const sync_pb::EntitySpecifics& unencrypted = 410dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen GetUnencryptedSpecifics(GetEntry()); 411dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen return unencrypted.GetExtension(sync_pb::typed_url); 412c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch} 413c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 414c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdochconst sync_pb::ExtensionSpecifics& BaseNode::GetExtensionSpecifics() const { 415dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen DCHECK_EQ(syncable::EXTENSIONS, GetModelType()); 416dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen const sync_pb::EntitySpecifics& unencrypted = 417dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen GetUnencryptedSpecifics(GetEntry()); 418dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen return unencrypted.GetExtension(sync_pb::extension); 419c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch} 420c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 4213345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrickconst sync_pb::SessionSpecifics& BaseNode::GetSessionSpecifics() const { 422dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen DCHECK_EQ(syncable::SESSIONS, GetModelType()); 423dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen const sync_pb::EntitySpecifics& unencrypted = 424dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen GetUnencryptedSpecifics(GetEntry()); 425dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen return unencrypted.GetExtension(sync_pb::session); 4263345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick} 4273345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick 428c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdochsyncable::ModelType BaseNode::GetModelType() const { 429c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch return GetEntry()->GetModelType(); 430c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch} 431c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 432c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch//////////////////////////////////// 433c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch// WriteNode member definitions 434dc0f95d653279beabeb9817299e2902918ba123eKristian Monsenvoid WriteNode::EncryptIfNecessary(sync_pb::EntitySpecifics* unencrypted) { 435dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen syncable::ModelType type = syncable::GetModelTypeFromSpecifics(*unencrypted); 436dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen DCHECK_NE(type, syncable::UNSPECIFIED); 437dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen DCHECK_NE(type, syncable::PASSWORDS); // Passwords use their own encryption. 438dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen DCHECK_NE(type, syncable::NIGORI); // Nigori is encrypted separately. 439dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen 440dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen syncable::ModelTypeSet encrypted_types = 441dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen GetEncryptedDataTypes(GetTransaction()->GetWrappedTrans()); 442dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen if (encrypted_types.count(type) == 0) { 443dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen // This datatype does not require encryption. 444dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen return; 445dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen } 446dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen 447dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen if (unencrypted->has_encrypted()) { 448dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen // This specifics is already encrypted, our work is done. 449dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen LOG(WARNING) << "Attempted to encrypt an already encrypted entity" 450dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen << " specifics of type " << syncable::ModelTypeToString(type) 451dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen << ". Dropping."; 452dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen return; 453dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen } 454dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen sync_pb::EntitySpecifics encrypted; 455dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen syncable::AddDefaultExtensionValue(type, &encrypted); 456dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen VLOG(2) << "Encrypted specifics of type " << syncable::ModelTypeToString(type) 457dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen << " with content: " << unencrypted->SerializeAsString() << "\n"; 458dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen if (!GetTransaction()->GetCryptographer()->Encrypt( 459dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen *unencrypted, 460dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen encrypted.mutable_encrypted())) { 461dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen LOG(ERROR) << "Could not encrypt data for node of type " << 462dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen syncable::ModelTypeToString(type); 463dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen NOTREACHED(); 464dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen } 465dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen unencrypted->CopyFrom(encrypted); 466dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen} 467dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen 468c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdochvoid WriteNode::SetIsFolder(bool folder) { 469c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch if (entry_->Get(syncable::IS_DIR) == folder) 470c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch return; // Skip redundant changes. 471c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 472c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch entry_->Put(syncable::IS_DIR, folder); 473c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch MarkForSyncing(); 474c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch} 475c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 476c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdochvoid WriteNode::SetTitle(const std::wstring& title) { 477c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch std::string server_legal_name; 478c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch SyncAPINameToServerName(title, &server_legal_name); 479c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 480c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch string old_name = entry_->Get(syncable::NON_UNIQUE_NAME); 481c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 482c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch if (server_legal_name == old_name) 483c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch return; // Skip redundant changes. 484c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 485c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch entry_->Put(syncable::NON_UNIQUE_NAME, server_legal_name); 486c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch MarkForSyncing(); 487c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch} 488c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 489c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdochvoid WriteNode::SetURL(const GURL& url) { 490c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch sync_pb::BookmarkSpecifics new_value = GetBookmarkSpecifics(); 491c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch new_value.set_url(url.spec()); 492c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch SetBookmarkSpecifics(new_value); 493c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch} 494c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 4953345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrickvoid WriteNode::SetAppSpecifics( 4963345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick const sync_pb::AppSpecifics& new_value) { 497dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen DCHECK_EQ(syncable::APPS, GetModelType()); 4983345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick PutAppSpecificsAndMarkForSyncing(new_value); 4993345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick} 5003345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick 501c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdochvoid WriteNode::SetAutofillSpecifics( 502c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch const sync_pb::AutofillSpecifics& new_value) { 503dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen DCHECK_EQ(syncable::AUTOFILL, GetModelType()); 504c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch PutAutofillSpecificsAndMarkForSyncing(new_value); 505c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch} 506c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 507c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdochvoid WriteNode::PutAutofillSpecificsAndMarkForSyncing( 508c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch const sync_pb::AutofillSpecifics& new_value) { 509c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch sync_pb::EntitySpecifics entity_specifics; 510c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch entity_specifics.MutableExtension(sync_pb::autofill)->CopyFrom(new_value); 511dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen EncryptIfNecessary(&entity_specifics); 512c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch PutSpecificsAndMarkForSyncing(entity_specifics); 513c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch} 514c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 51521d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsenvoid WriteNode::SetAutofillProfileSpecifics( 51621d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen const sync_pb::AutofillProfileSpecifics& new_value) { 51721d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen DCHECK_EQ(GetModelType(), syncable::AUTOFILL_PROFILE); 51821d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen PutAutofillProfileSpecificsAndMarkForSyncing(new_value); 51921d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen} 52021d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen 52121d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsenvoid WriteNode::PutAutofillProfileSpecificsAndMarkForSyncing( 52221d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen const sync_pb::AutofillProfileSpecifics& new_value) { 52321d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen sync_pb::EntitySpecifics entity_specifics; 52421d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen entity_specifics.MutableExtension(sync_pb::autofill_profile)->CopyFrom( 52521d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen new_value); 526dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen EncryptIfNecessary(&entity_specifics); 52721d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen PutSpecificsAndMarkForSyncing(entity_specifics); 52821d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen} 52921d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen 530c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdochvoid WriteNode::SetBookmarkSpecifics( 531c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch const sync_pb::BookmarkSpecifics& new_value) { 532dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen DCHECK_EQ(syncable::BOOKMARKS, GetModelType()); 533c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch PutBookmarkSpecificsAndMarkForSyncing(new_value); 534c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch} 535c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 536c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdochvoid WriteNode::PutBookmarkSpecificsAndMarkForSyncing( 537c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch const sync_pb::BookmarkSpecifics& new_value) { 538c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch sync_pb::EntitySpecifics entity_specifics; 539c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch entity_specifics.MutableExtension(sync_pb::bookmark)->CopyFrom(new_value); 540dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen EncryptIfNecessary(&entity_specifics); 541c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch PutSpecificsAndMarkForSyncing(entity_specifics); 542c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch} 543c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 544c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdochvoid WriteNode::SetNigoriSpecifics( 545c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch const sync_pb::NigoriSpecifics& new_value) { 546dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen DCHECK_EQ(syncable::NIGORI, GetModelType()); 547c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch PutNigoriSpecificsAndMarkForSyncing(new_value); 548c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch} 549c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 550c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdochvoid WriteNode::PutNigoriSpecificsAndMarkForSyncing( 551c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch const sync_pb::NigoriSpecifics& new_value) { 552c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch sync_pb::EntitySpecifics entity_specifics; 553c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch entity_specifics.MutableExtension(sync_pb::nigori)->CopyFrom(new_value); 554c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch PutSpecificsAndMarkForSyncing(entity_specifics); 555c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch} 556c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 557c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdochvoid WriteNode::SetPasswordSpecifics( 558c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch const sync_pb::PasswordSpecificsData& data) { 559dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen DCHECK_EQ(syncable::PASSWORDS, GetModelType()); 560ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen 561ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen Cryptographer* cryptographer = GetTransaction()->GetCryptographer(); 562ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen 563ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen // Idempotency check to prevent unnecessary syncing: if the plaintexts match 564ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen // and the old ciphertext is encrypted with the most current key, there's 565ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen // nothing to do here. Because each encryption is seeded with a different 566ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen // random value, checking for equivalence post-encryption doesn't suffice. 567ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen const sync_pb::EncryptedData& old_ciphertext = 568ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen GetEntry()->Get(SPECIFICS).GetExtension(sync_pb::password).encrypted(); 569ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen scoped_ptr<sync_pb::PasswordSpecificsData> old_plaintext( 570ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen DecryptPasswordSpecifics(GetEntry()->Get(SPECIFICS), cryptographer)); 571ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen if (old_plaintext.get() && 572ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen old_plaintext->SerializeAsString() == data.SerializeAsString() && 573ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen cryptographer->CanDecryptUsingDefaultKey(old_ciphertext)) { 574ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen return; 575ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen } 576ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen 577c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch sync_pb::PasswordSpecifics new_value; 578ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen if (!cryptographer->Encrypt(data, new_value.mutable_encrypted())) { 579c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch NOTREACHED(); 580731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick } 581c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch PutPasswordSpecificsAndMarkForSyncing(new_value); 582c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch} 583c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 584c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdochvoid WriteNode::SetPreferenceSpecifics( 585c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch const sync_pb::PreferenceSpecifics& new_value) { 586dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen DCHECK_EQ(syncable::PREFERENCES, GetModelType()); 587c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch PutPreferenceSpecificsAndMarkForSyncing(new_value); 588c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch} 589c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 590c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdochvoid WriteNode::SetThemeSpecifics( 591c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch const sync_pb::ThemeSpecifics& new_value) { 592dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen DCHECK_EQ(syncable::THEMES, GetModelType()); 593c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch PutThemeSpecificsAndMarkForSyncing(new_value); 594c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch} 595c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 5963345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrickvoid WriteNode::SetSessionSpecifics( 5973345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick const sync_pb::SessionSpecifics& new_value) { 598dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen DCHECK_EQ(syncable::SESSIONS, GetModelType()); 5993345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick PutSessionSpecificsAndMarkForSyncing(new_value); 6003345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick} 6013345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick 602dc0f95d653279beabeb9817299e2902918ba123eKristian Monsenvoid WriteNode::ResetFromSpecifics() { 603dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen sync_pb::EntitySpecifics new_data; 604dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen new_data.CopyFrom(GetUnencryptedSpecifics(GetEntry())); 605dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen EncryptIfNecessary(&new_data); 606dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen PutSpecificsAndMarkForSyncing(new_data); 607dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen} 6083345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick 609c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdochvoid WriteNode::PutPasswordSpecificsAndMarkForSyncing( 610c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch const sync_pb::PasswordSpecifics& new_value) { 611c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch sync_pb::EntitySpecifics entity_specifics; 612c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch entity_specifics.MutableExtension(sync_pb::password)->CopyFrom(new_value); 613c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch PutSpecificsAndMarkForSyncing(entity_specifics); 614c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch} 615c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 616c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdochvoid WriteNode::PutPreferenceSpecificsAndMarkForSyncing( 617c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch const sync_pb::PreferenceSpecifics& new_value) { 618c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch sync_pb::EntitySpecifics entity_specifics; 619c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch entity_specifics.MutableExtension(sync_pb::preference)->CopyFrom(new_value); 620dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen EncryptIfNecessary(&entity_specifics); 621c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch PutSpecificsAndMarkForSyncing(entity_specifics); 622c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch} 623c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 624c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdochvoid WriteNode::SetTypedUrlSpecifics( 625c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch const sync_pb::TypedUrlSpecifics& new_value) { 626dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen DCHECK_EQ(syncable::TYPED_URLS, GetModelType()); 627c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch PutTypedUrlSpecificsAndMarkForSyncing(new_value); 628c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch} 629c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 630c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdochvoid WriteNode::SetExtensionSpecifics( 631c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch const sync_pb::ExtensionSpecifics& new_value) { 632dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen DCHECK_EQ(syncable::EXTENSIONS, GetModelType()); 633c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch PutExtensionSpecificsAndMarkForSyncing(new_value); 634c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch} 635c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 6363345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrickvoid WriteNode::PutAppSpecificsAndMarkForSyncing( 6373345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick const sync_pb::AppSpecifics& new_value) { 6383345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick sync_pb::EntitySpecifics entity_specifics; 6393345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick entity_specifics.MutableExtension(sync_pb::app)->CopyFrom(new_value); 640dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen EncryptIfNecessary(&entity_specifics); 6413345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick PutSpecificsAndMarkForSyncing(entity_specifics); 6423345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick} 6433345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick 644c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdochvoid WriteNode::PutThemeSpecificsAndMarkForSyncing( 645c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch const sync_pb::ThemeSpecifics& new_value) { 646c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch sync_pb::EntitySpecifics entity_specifics; 647c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch entity_specifics.MutableExtension(sync_pb::theme)->CopyFrom(new_value); 648dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen EncryptIfNecessary(&entity_specifics); 649c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch PutSpecificsAndMarkForSyncing(entity_specifics); 650c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch} 651c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 652c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdochvoid WriteNode::PutTypedUrlSpecificsAndMarkForSyncing( 653c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch const sync_pb::TypedUrlSpecifics& new_value) { 654c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch sync_pb::EntitySpecifics entity_specifics; 655c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch entity_specifics.MutableExtension(sync_pb::typed_url)->CopyFrom(new_value); 656dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen EncryptIfNecessary(&entity_specifics); 657c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch PutSpecificsAndMarkForSyncing(entity_specifics); 658c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch} 659c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 660c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdochvoid WriteNode::PutExtensionSpecificsAndMarkForSyncing( 661c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch const sync_pb::ExtensionSpecifics& new_value) { 662c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch sync_pb::EntitySpecifics entity_specifics; 663c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch entity_specifics.MutableExtension(sync_pb::extension)->CopyFrom(new_value); 664dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen EncryptIfNecessary(&entity_specifics); 665c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch PutSpecificsAndMarkForSyncing(entity_specifics); 666c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch} 667c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 6683345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrickvoid WriteNode::PutSessionSpecificsAndMarkForSyncing( 6693345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick const sync_pb::SessionSpecifics& new_value) { 6703345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick sync_pb::EntitySpecifics entity_specifics; 6713345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick entity_specifics.MutableExtension(sync_pb::session)->CopyFrom(new_value); 672dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen EncryptIfNecessary(&entity_specifics); 6733345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick PutSpecificsAndMarkForSyncing(entity_specifics); 6743345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick} 6753345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick 676c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdochvoid WriteNode::PutSpecificsAndMarkForSyncing( 677c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch const sync_pb::EntitySpecifics& specifics) { 678c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch // Skip redundant changes. 679c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch if (specifics.SerializeAsString() == 680c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch entry_->Get(SPECIFICS).SerializeAsString()) { 681c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch return; 682c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch } 683c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch entry_->Put(SPECIFICS, specifics); 684c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch MarkForSyncing(); 685c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch} 686c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 687c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdochvoid WriteNode::SetExternalId(int64 id) { 688c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch if (GetExternalId() != id) 689c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch entry_->Put(syncable::LOCAL_EXTERNAL_ID, id); 690c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch} 691c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 692c407dc5cd9bdc5668497f21b26b09d988ab439deBen MurdochWriteNode::WriteNode(WriteTransaction* transaction) 693c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch : entry_(NULL), transaction_(transaction) { 694c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch DCHECK(transaction); 695c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch} 696c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 697c407dc5cd9bdc5668497f21b26b09d988ab439deBen MurdochWriteNode::~WriteNode() { 698c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch delete entry_; 699c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch} 700c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 701c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch// Find an existing node matching the ID |id|, and bind this WriteNode to it. 702c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch// Return true on success. 703c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdochbool WriteNode::InitByIdLookup(int64 id) { 704c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch DCHECK(!entry_) << "Init called twice"; 705c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch DCHECK_NE(id, kInvalidId); 706c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch entry_ = new syncable::MutableEntry(transaction_->GetWrappedWriteTrans(), 707c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch syncable::GET_BY_HANDLE, id); 708c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch return (entry_->good() && !entry_->Get(syncable::IS_DEL) && 709c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch DecryptIfNecessary(entry_)); 710c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch} 711c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 712c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch// Find a node by client tag, and bind this WriteNode to it. 713c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch// Return true if the write node was found, and was not deleted. 714c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch// Undeleting a deleted node is possible by ClientTag. 715c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdochbool WriteNode::InitByClientTagLookup(syncable::ModelType model_type, 716c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch const std::string& tag) { 717c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch DCHECK(!entry_) << "Init called twice"; 718c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch if (tag.empty()) 719c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch return false; 720c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 721c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch const std::string hash = GenerateSyncableHash(model_type, tag); 722c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 723c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch entry_ = new syncable::MutableEntry(transaction_->GetWrappedWriteTrans(), 724c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch syncable::GET_BY_CLIENT_TAG, hash); 725c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch return (entry_->good() && !entry_->Get(syncable::IS_DEL) && 726c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch DecryptIfNecessary(entry_)); 727c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch} 728c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 729c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdochbool WriteNode::InitByTagLookup(const std::string& tag) { 730c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch DCHECK(!entry_) << "Init called twice"; 731c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch if (tag.empty()) 732c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch return false; 733c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch entry_ = new syncable::MutableEntry(transaction_->GetWrappedWriteTrans(), 734c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch syncable::GET_BY_SERVER_TAG, tag); 735c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch if (!entry_->good()) 736c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch return false; 737c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch if (entry_->Get(syncable::IS_DEL)) 738c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch return false; 739c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch syncable::ModelType model_type = GetModelType(); 740dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen DCHECK_EQ(syncable::NIGORI, model_type); 741c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch return true; 742c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch} 743c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 744c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdochvoid WriteNode::PutModelType(syncable::ModelType model_type) { 745c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch // Set an empty specifics of the appropriate datatype. The presence 746c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch // of the specific extension will identify the model type. 747c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch DCHECK(GetModelType() == model_type || 748c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch GetModelType() == syncable::UNSPECIFIED); // Immutable once set. 749c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 750c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch sync_pb::EntitySpecifics specifics; 751c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch syncable::AddDefaultExtensionValue(model_type, &specifics); 752c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch PutSpecificsAndMarkForSyncing(specifics); 753dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen DCHECK_EQ(model_type, GetModelType()); 754c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch} 755c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 756c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch// Create a new node with default properties, and bind this WriteNode to it. 757c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch// Return true on success. 758c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdochbool WriteNode::InitByCreation(syncable::ModelType model_type, 759c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch const BaseNode& parent, 760c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch const BaseNode* predecessor) { 761c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch DCHECK(!entry_) << "Init called twice"; 762c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch // |predecessor| must be a child of |parent| or NULL. 763c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch if (predecessor && predecessor->GetParentId() != parent.GetId()) { 764c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch DCHECK(false); 765c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch return false; 766c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch } 767c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 768c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch syncable::Id parent_id = parent.GetEntry()->Get(syncable::ID); 769c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 770c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch // Start out with a dummy name. We expect 771c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch // the caller to set a meaningful name after creation. 772c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch string dummy(kDefaultNameForNewNodes); 773c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 774c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch entry_ = new syncable::MutableEntry(transaction_->GetWrappedWriteTrans(), 775c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch syncable::CREATE, parent_id, dummy); 776c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 777c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch if (!entry_->good()) 778c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch return false; 779c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 780c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch // Entries are untitled folders by default. 781c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch entry_->Put(syncable::IS_DIR, true); 782c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 783c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch PutModelType(model_type); 784c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 785c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch // Now set the predecessor, which sets IS_UNSYNCED as necessary. 786c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch PutPredecessor(predecessor); 787c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 788c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch return true; 789c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch} 790c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 791c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch// Create a new node with default properties and a client defined unique tag, 792c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch// and bind this WriteNode to it. 793c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch// Return true on success. If the tag exists in the database, then 794c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch// we will attempt to undelete the node. 795c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch// TODO(chron): Code datatype into hash tag. 796c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch// TODO(chron): Is model type ever lost? 797c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdochbool WriteNode::InitUniqueByCreation(syncable::ModelType model_type, 798c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch const BaseNode& parent, 799c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch const std::string& tag) { 800c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch DCHECK(!entry_) << "Init called twice"; 801c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 802c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch const std::string hash = GenerateSyncableHash(model_type, tag); 803c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 804c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch syncable::Id parent_id = parent.GetEntry()->Get(syncable::ID); 805c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 806c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch // Start out with a dummy name. We expect 807c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch // the caller to set a meaningful name after creation. 808c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch string dummy(kDefaultNameForNewNodes); 809c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 810c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch // Check if we have this locally and need to undelete it. 811c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch scoped_ptr<syncable::MutableEntry> existing_entry( 812c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch new syncable::MutableEntry(transaction_->GetWrappedWriteTrans(), 813c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch syncable::GET_BY_CLIENT_TAG, hash)); 814c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 815c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch if (existing_entry->good()) { 816c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch if (existing_entry->Get(syncable::IS_DEL)) { 817c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch // Rules for undelete: 818c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch // BASE_VERSION: Must keep the same. 819c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch // ID: Essential to keep the same. 820c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch // META_HANDLE: Must be the same, so we can't "split" the entry. 821c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch // IS_DEL: Must be set to false, will cause reindexing. 822c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch // This one is weird because IS_DEL is true for "update only" 823c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch // items. It should be OK to undelete an update only. 824c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch // MTIME/CTIME: Seems reasonable to just leave them alone. 825c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch // IS_UNSYNCED: Must set this to true or face database insurrection. 826c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch // We do this below this block. 827c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch // IS_UNAPPLIED_UPDATE: Either keep it the same or also set BASE_VERSION 828c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch // to SERVER_VERSION. We keep it the same here. 829c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch // IS_DIR: We'll leave it the same. 830c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch // SPECIFICS: Reset it. 831c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 832c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch existing_entry->Put(syncable::IS_DEL, false); 833c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 834c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch // Client tags are immutable and must be paired with the ID. 835c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch // If a server update comes down with an ID and client tag combo, 836c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch // and it already exists, always overwrite it and store only one copy. 837c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch // We have to undelete entries because we can't disassociate IDs from 838c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch // tags and updates. 839c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 840c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch existing_entry->Put(syncable::NON_UNIQUE_NAME, dummy); 841c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch existing_entry->Put(syncable::PARENT_ID, parent_id); 842c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch entry_ = existing_entry.release(); 843c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch } else { 844c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch return false; 845c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch } 846c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch } else { 847c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch entry_ = new syncable::MutableEntry(transaction_->GetWrappedWriteTrans(), 848c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch syncable::CREATE, parent_id, dummy); 849c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch if (!entry_->good()) { 850c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch return false; 851c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch } 852c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 853c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch // Only set IS_DIR for new entries. Don't bitflip undeleted ones. 854c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch entry_->Put(syncable::UNIQUE_CLIENT_TAG, hash); 855c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch } 856c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 857c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch // We don't support directory and tag combinations. 858c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch entry_->Put(syncable::IS_DIR, false); 859c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 860c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch // Will clear specifics data. 861c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch PutModelType(model_type); 862c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 863c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch // Now set the predecessor, which sets IS_UNSYNCED as necessary. 864c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch PutPredecessor(NULL); 865c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 866c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch return true; 867c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch} 868c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 869c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdochbool WriteNode::SetPosition(const BaseNode& new_parent, 870c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch const BaseNode* predecessor) { 871c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch // |predecessor| must be a child of |new_parent| or NULL. 872c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch if (predecessor && predecessor->GetParentId() != new_parent.GetId()) { 873c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch DCHECK(false); 874c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch return false; 875c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch } 876c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 877c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch syncable::Id new_parent_id = new_parent.GetEntry()->Get(syncable::ID); 878c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 879c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch // Filter out redundant changes if both the parent and the predecessor match. 880c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch if (new_parent_id == entry_->Get(syncable::PARENT_ID)) { 881c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch const syncable::Id& old = entry_->Get(syncable::PREV_ID); 882c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch if ((!predecessor && old.IsRoot()) || 883c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch (predecessor && (old == predecessor->GetEntry()->Get(syncable::ID)))) { 884c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch return true; 885c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch } 886c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch } 887c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 888c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch // Atomically change the parent. This will fail if it would 889c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch // introduce a cycle in the hierarchy. 890c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch if (!entry_->Put(syncable::PARENT_ID, new_parent_id)) 891c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch return false; 892c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 893c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch // Now set the predecessor, which sets IS_UNSYNCED as necessary. 894c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch PutPredecessor(predecessor); 895c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 896c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch return true; 897c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch} 898c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 899c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdochconst syncable::Entry* WriteNode::GetEntry() const { 900c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch return entry_; 901c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch} 902c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 903c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdochconst BaseTransaction* WriteNode::GetTransaction() const { 904c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch return transaction_; 905c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch} 906c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 907c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdochvoid WriteNode::Remove() { 908c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch entry_->Put(syncable::IS_DEL, true); 909c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch MarkForSyncing(); 910c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch} 911c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 912c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdochvoid WriteNode::PutPredecessor(const BaseNode* predecessor) { 913c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch syncable::Id predecessor_id = predecessor ? 914c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch predecessor->GetEntry()->Get(syncable::ID) : syncable::Id(); 915c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch entry_->PutPredecessor(predecessor_id); 916c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch // Mark this entry as unsynced, to wake up the syncer. 917c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch MarkForSyncing(); 918c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch} 919c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 920c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdochvoid WriteNode::SetFaviconBytes(const vector<unsigned char>& bytes) { 921c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch sync_pb::BookmarkSpecifics new_value = GetBookmarkSpecifics(); 922c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch new_value.set_favicon(bytes.empty() ? NULL : &bytes[0], bytes.size()); 923c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch SetBookmarkSpecifics(new_value); 924c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch} 925c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 926c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdochvoid WriteNode::MarkForSyncing() { 927c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch syncable::MarkForSyncing(entry_); 928c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch} 929c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 930c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch////////////////////////////////////////////////////////////////////////// 931c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch// ReadNode member definitions 932c407dc5cd9bdc5668497f21b26b09d988ab439deBen MurdochReadNode::ReadNode(const BaseTransaction* transaction) 933c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch : entry_(NULL), transaction_(transaction) { 934c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch DCHECK(transaction); 935c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch} 936c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 937201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben MurdochReadNode::ReadNode() { 938201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch entry_ = NULL; 939201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch transaction_ = NULL; 940201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch} 941201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch 942c407dc5cd9bdc5668497f21b26b09d988ab439deBen MurdochReadNode::~ReadNode() { 943c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch delete entry_; 944c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch} 945c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 946c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdochvoid ReadNode::InitByRootLookup() { 947c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch DCHECK(!entry_) << "Init called twice"; 948c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch syncable::BaseTransaction* trans = transaction_->GetWrappedTrans(); 949c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch entry_ = new syncable::Entry(trans, syncable::GET_BY_ID, trans->root_id()); 950c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch if (!entry_->good()) 951c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch DCHECK(false) << "Could not lookup root node for reading."; 952c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch} 953c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 954c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdochbool ReadNode::InitByIdLookup(int64 id) { 955c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch DCHECK(!entry_) << "Init called twice"; 956c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch DCHECK_NE(id, kInvalidId); 957c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch syncable::BaseTransaction* trans = transaction_->GetWrappedTrans(); 958c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch entry_ = new syncable::Entry(trans, syncable::GET_BY_HANDLE, id); 959c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch if (!entry_->good()) 960c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch return false; 961c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch if (entry_->Get(syncable::IS_DEL)) 962c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch return false; 963c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch syncable::ModelType model_type = GetModelType(); 964c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch LOG_IF(WARNING, model_type == syncable::UNSPECIFIED || 965c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch model_type == syncable::TOP_LEVEL_FOLDER) 966c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch << "SyncAPI InitByIdLookup referencing unusual object."; 967c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch return DecryptIfNecessary(entry_); 968c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch} 969c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 970c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdochbool ReadNode::InitByClientTagLookup(syncable::ModelType model_type, 971c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch const std::string& tag) { 972c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch DCHECK(!entry_) << "Init called twice"; 973c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch if (tag.empty()) 974c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch return false; 975c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 976c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch const std::string hash = GenerateSyncableHash(model_type, tag); 977c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 978c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch entry_ = new syncable::Entry(transaction_->GetWrappedTrans(), 979c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch syncable::GET_BY_CLIENT_TAG, hash); 980c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch return (entry_->good() && !entry_->Get(syncable::IS_DEL) && 981c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch DecryptIfNecessary(entry_)); 982c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch} 983c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 984c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdochconst syncable::Entry* ReadNode::GetEntry() const { 985c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch return entry_; 986c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch} 987c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 988c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdochconst BaseTransaction* ReadNode::GetTransaction() const { 989c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch return transaction_; 990c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch} 991c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 992c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdochbool ReadNode::InitByTagLookup(const std::string& tag) { 993c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch DCHECK(!entry_) << "Init called twice"; 994c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch if (tag.empty()) 995c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch return false; 996c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch syncable::BaseTransaction* trans = transaction_->GetWrappedTrans(); 997c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch entry_ = new syncable::Entry(trans, syncable::GET_BY_SERVER_TAG, tag); 998c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch if (!entry_->good()) 999c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch return false; 1000c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch if (entry_->Get(syncable::IS_DEL)) 1001c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch return false; 1002c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch syncable::ModelType model_type = GetModelType(); 1003c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch LOG_IF(WARNING, model_type == syncable::UNSPECIFIED || 1004c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch model_type == syncable::TOP_LEVEL_FOLDER) 1005c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch << "SyncAPI InitByTagLookup referencing unusually typed object."; 1006c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch return DecryptIfNecessary(entry_); 1007c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch} 1008c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 1009c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch////////////////////////////////////////////////////////////////////////// 1010c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch// ReadTransaction member definitions 1011c407dc5cd9bdc5668497f21b26b09d988ab439deBen MurdochReadTransaction::ReadTransaction(UserShare* share) 1012c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch : BaseTransaction(share), 1013c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch transaction_(NULL), 1014c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch close_transaction_(true) { 1015c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch transaction_ = new syncable::ReadTransaction(GetLookup(), __FILE__, __LINE__); 1016c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch} 1017c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 1018c407dc5cd9bdc5668497f21b26b09d988ab439deBen MurdochReadTransaction::ReadTransaction(UserShare* share, 1019c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch syncable::BaseTransaction* trans) 1020c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch : BaseTransaction(share), 1021c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch transaction_(trans), 1022c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch close_transaction_(false) {} 1023c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 1024c407dc5cd9bdc5668497f21b26b09d988ab439deBen MurdochReadTransaction::~ReadTransaction() { 1025c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch if (close_transaction_) { 1026c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch delete transaction_; 1027c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch } 1028c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch} 1029c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 1030c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdochsyncable::BaseTransaction* ReadTransaction::GetWrappedTrans() const { 1031c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch return transaction_; 1032c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch} 1033c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 1034c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch////////////////////////////////////////////////////////////////////////// 1035c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch// WriteTransaction member definitions 1036c407dc5cd9bdc5668497f21b26b09d988ab439deBen MurdochWriteTransaction::WriteTransaction(UserShare* share) 1037c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch : BaseTransaction(share), 1038c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch transaction_(NULL) { 1039c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch transaction_ = new syncable::WriteTransaction(GetLookup(), syncable::SYNCAPI, 1040c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch __FILE__, __LINE__); 1041c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch} 1042c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 1043c407dc5cd9bdc5668497f21b26b09d988ab439deBen MurdochWriteTransaction::~WriteTransaction() { 1044c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch delete transaction_; 1045c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch} 1046c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 1047c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdochsyncable::BaseTransaction* WriteTransaction::GetWrappedTrans() const { 1048c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch return transaction_; 1049c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch} 1050c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 1051731df977c0511bca2206b5f333555b1205ff1f43Iain MerrickSyncManager::ChangeRecord::ChangeRecord() 1052731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick : id(kInvalidId), action(ACTION_ADD) {} 1053731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick 1054731df977c0511bca2206b5f333555b1205ff1f43Iain MerrickSyncManager::ChangeRecord::~ChangeRecord() {} 1055731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick 105672a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian MonsenDictionaryValue* SyncManager::ChangeRecord::ToValue( 105772a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen const BaseTransaction* trans) const { 105872a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen DictionaryValue* value = new DictionaryValue(); 105972a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen std::string action_str; 106072a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen switch (action) { 106172a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen case ACTION_ADD: 106272a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen action_str = "Add"; 106372a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen break; 106472a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen case ACTION_DELETE: 106572a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen action_str = "Delete"; 106672a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen break; 106772a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen case ACTION_UPDATE: 106872a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen action_str = "Update"; 106972a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen break; 107072a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen default: 107172a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen NOTREACHED(); 107272a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen action_str = "Unknown"; 107372a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen break; 107472a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen } 107572a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen value->SetString("action", action_str); 107672a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen Value* node_value = NULL; 107772a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen if (action == ACTION_DELETE) { 107872a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen DictionaryValue* node_dict = new DictionaryValue(); 107972a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen node_dict->SetString("id", base::Int64ToString(id)); 108072a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen node_dict->Set("specifics", 108172a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen browser_sync::EntitySpecificsToValue(specifics)); 108272a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen if (extra.get()) { 108372a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen node_dict->Set("extra", extra->ToValue()); 108472a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen } 108572a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen node_value = node_dict; 108672a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen } else { 108772a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen ReadNode node(trans); 108872a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen if (node.InitByIdLookup(id)) { 108972a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen node_value = node.ToValue(); 109072a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen } 109172a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen } 109272a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen if (!node_value) { 109372a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen NOTREACHED(); 109472a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen node_value = Value::CreateNullValue(); 109572a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen } 109672a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen value->Set("node", node_value); 109772a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen return value; 109872a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen} 109972a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen 1100ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsenbool BaseNode::ContainsString(const std::string& lowercase_query) const { 1101ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen DCHECK(GetEntry()); 1102ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen // TODO(lipalani) - figure out what to do if the node is encrypted. 1103ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen const sync_pb::EntitySpecifics& specifics = GetEntry()->Get(SPECIFICS); 1104ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen std::string temp; 1105ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen // The protobuf serialized string contains the original strings. So 1106ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen // we will just serialize it and search it. 1107ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen specifics.SerializeToString(&temp); 1108ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen 1109ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen // Now convert to lower case. 1110ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen StringToLowerASCII(&temp); 1111ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen 1112ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen return temp.find(lowercase_query) != std::string::npos; 1113ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen} 1114ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen 1115dc0f95d653279beabeb9817299e2902918ba123eKristian MonsenSyncManager::ExtraPasswordChangeRecordData::ExtraPasswordChangeRecordData() {} 1116dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen 1117731df977c0511bca2206b5f333555b1205ff1f43Iain MerrickSyncManager::ExtraPasswordChangeRecordData::ExtraPasswordChangeRecordData( 1118731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick const sync_pb::PasswordSpecificsData& data) 1119dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen : unencrypted_(data) { 1120dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen} 1121731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick 1122731df977c0511bca2206b5f333555b1205ff1f43Iain MerrickSyncManager::ExtraPasswordChangeRecordData::~ExtraPasswordChangeRecordData() {} 1123731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick 112472a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian MonsenDictionaryValue* SyncManager::ExtraPasswordChangeRecordData::ToValue() const { 112572a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen return browser_sync::PasswordSpecificsDataToValue(unencrypted_); 112672a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen} 112772a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen 112872a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsenconst sync_pb::PasswordSpecificsData& 112972a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen SyncManager::ExtraPasswordChangeRecordData::unencrypted() const { 113072a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen return unencrypted_; 113172a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen} 113272a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen 1133ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsennamespace { 1134ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen 1135ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsenstruct NotificationInfo { 1136ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen int total_count; 1137ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen std::string payload; 1138ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen 1139ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen NotificationInfo() : total_count(0) {} 1140ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen 1141ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen ~NotificationInfo() {} 1142ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen 1143ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen // Returned pointer owned by the caller. 1144ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen DictionaryValue* ToValue() const { 1145ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen DictionaryValue* value = new DictionaryValue(); 1146ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen value->SetInteger("totalCount", total_count); 1147ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen value->SetString("payload", payload); 1148ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen return value; 1149ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen } 1150ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen}; 1151ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen 1152ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsentypedef std::map<syncable::ModelType, NotificationInfo> NotificationInfoMap; 1153ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen 1154ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen// returned pointer is owned by the caller. 1155ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian MonsenDictionaryValue* NotificationInfoToValue( 1156ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen const NotificationInfoMap& notification_info) { 1157ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen DictionaryValue* value = new DictionaryValue(); 1158ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen 1159ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen for (NotificationInfoMap::const_iterator it = notification_info.begin(); 1160ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen it != notification_info.end(); ++it) { 1161ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen const std::string& model_type_str = 1162ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen syncable::ModelTypeToString(it->first); 1163ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen value->Set(model_type_str, it->second.ToValue()); 1164ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen } 1165ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen 1166ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen return value; 1167ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen} 1168ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen 1169ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen} // namespace 1170ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen 1171c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch////////////////////////////////////////////////////////////////////////// 1172c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch// SyncManager's implementation: SyncManager::SyncInternal 1173c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdochclass SyncManager::SyncInternal 1174dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen : public net::NetworkChangeNotifier::IPAddressObserver, 1175ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen public sync_notifier::SyncNotifierObserver, 117672a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen public browser_sync::JsBackend, 1177ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen public SyncEngineEventListener, 1178ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen public ServerConnectionEventListener, 1179ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen public syncable::DirectoryChangeListener { 1180c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch static const int kDefaultNudgeDelayMilliseconds; 1181c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch static const int kPreferencesNudgeDelayMilliseconds; 1182c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch public: 1183c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch explicit SyncInternal(SyncManager* sync_manager) 1184c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch : core_message_loop_(NULL), 118572a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen parent_router_(NULL), 1186c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch sync_manager_(sync_manager), 1187c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch registrar_(NULL), 1188c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch initialized_(false), 1189ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen ALLOW_THIS_IN_INITIALIZER_LIST(method_factory_(this)) { 1190731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); 1191c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch } 1192c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 1193731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick virtual ~SyncInternal() { 1194ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen CHECK(!core_message_loop_); 1195731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); 1196c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch } 1197c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 1198c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch bool Init(const FilePath& database_location, 1199c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch const std::string& sync_server_and_path, 1200c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch int port, 1201c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch bool use_ssl, 1202c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch HttpPostProviderFactory* post_factory, 1203c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch ModelSafeWorkerRegistrar* model_safe_worker_registrar, 1204c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch const char* user_agent, 12053345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick const SyncCredentials& credentials, 1206ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen sync_notifier::SyncNotifier* sync_notifier, 12073345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick const std::string& restored_key_for_bootstrapping, 12083345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick bool setup_for_test_mode); 12093345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick 12103345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick // Sign into sync with given credentials. 12113345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick // We do not verify the tokens given. After this call, the tokens are set 12123345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick // and the sync DB is open. True if successful, false if something 12133345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick // went wrong. 12143345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick bool SignIn(const SyncCredentials& credentials); 12153345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick 12163345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick // Update tokens that we're using in Sync. Email must stay the same. 12173345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick void UpdateCredentials(const SyncCredentials& credentials); 1218c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 1219ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen // Called when the user disables or enables a sync type. 1220ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen void UpdateEnabledTypes(); 1221dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen 1222c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch // Tell the sync engine to start the syncing process. 1223c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch void StartSyncing(); 1224c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 12254a5e2dc747d50c653511c68ccb2cfbfb740bd5a7Ben Murdoch // Whether or not the Nigori node is encrypted using an explicit passphrase. 12264a5e2dc747d50c653511c68ccb2cfbfb740bd5a7Ben Murdoch bool IsUsingExplicitPassphrase(); 12274a5e2dc747d50c653511c68ccb2cfbfb740bd5a7Ben Murdoch 1228dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen // Set the datatypes we want to encrypt and encrypt any nodes as necessary. 1229dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen void EncryptDataTypes(const syncable::ModelTypeSet& encrypted_types); 1230dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen 12314a5e2dc747d50c653511c68ccb2cfbfb740bd5a7Ben Murdoch // Try to set the current passphrase to |passphrase|, and record whether 12324a5e2dc747d50c653511c68ccb2cfbfb740bd5a7Ben Murdoch // it is an explicit passphrase or implicitly using gaia in the Nigori 12334a5e2dc747d50c653511c68ccb2cfbfb740bd5a7Ben Murdoch // node. 12344a5e2dc747d50c653511c68ccb2cfbfb740bd5a7Ben Murdoch void SetPassphrase(const std::string& passphrase, bool is_explicit); 1235c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 1236c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch // Call periodically from a database-safe thread to persist recent changes 1237c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch // to the syncapi model. 1238c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch void SaveChanges(); 1239c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 1240ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen // DirectoryChangeListener implementation. 1241c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch // This listener is called upon completion of a syncable transaction, and 1242c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch // builds the list of sync-engine initiated changes that will be forwarded to 1243c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch // the SyncManager's Observers. 1244ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen virtual void HandleTransactionCompleteChangeEvent( 1245ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen const ModelTypeBitSet& models_with_changes); 1246ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen virtual ModelTypeBitSet HandleTransactionEndingChangeEvent( 1247ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen syncable::BaseTransaction* trans); 1248ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen virtual void HandleCalculateChangesChangeEventFromSyncApi( 1249ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen const OriginalEntries& originals, 1250ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen const WriterTag& writer, 1251ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen syncable::BaseTransaction* trans); 1252ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen virtual void HandleCalculateChangesChangeEventFromSyncer( 1253ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen const OriginalEntries& originals, 1254ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen const WriterTag& writer, 1255ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen syncable::BaseTransaction* trans); 1256c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 12573345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick // Listens for notifications from the ServerConnectionManager 1258201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch void HandleServerConnectionEvent(const ServerConnectionEvent& event); 1259c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 12603345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick // Open the directory named with username_for_share 12613345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick bool OpenDirectory(); 1262c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 1263ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen // SyncNotifierObserver implementation. 1264c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch virtual void OnNotificationStateChange( 1265c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch bool notifications_enabled); 1266c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 1267c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch virtual void OnIncomingNotification( 1268ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen const syncable::ModelTypePayloadMap& type_payloads); 1269c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 1270ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen virtual void StoreState(const std::string& cookie); 1271731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick 127272a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen void AddObserver(SyncManager::Observer* observer); 127372a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen 127472a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen void RemoveObserver(SyncManager::Observer* observer); 127572a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen 1276c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch // Accessors for the private members. 1277c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch DirectoryManager* dir_manager() { return share_.dir_manager.get(); } 1278c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch SyncAPIServerConnectionManager* connection_manager() { 1279c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch return connection_manager_.get(); 1280c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch } 1281ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen SyncerThread* syncer_thread() { return syncer_thread_.get(); } 1282c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch UserShare* GetUserShare() { return &share_; } 1283c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 1284c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch // Return the currently active (validated) username for use with syncable 1285c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch // types. 1286c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch const std::string& username_for_share() const { 12873345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick return share_.name; 1288c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch } 1289c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 129072a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen Status GetStatus(); 1291c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 1292ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen void RequestNudge(const tracked_objects::Location& nudge_location); 1293ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen 1294ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen void RequestNudgeWithDataTypes(const TimeDelta& delay, 1295ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen browser_sync::NudgeSource source, const ModelTypeBitSet& types, 1296ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen const tracked_objects::Location& nudge_location); 1297ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen 1298c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch // See SyncManager::Shutdown for information. 1299c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch void Shutdown(); 1300c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 1301c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch // Whether we're initialized to the point of being able to accept changes 1302c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch // (and hence allow transaction creation). See initialized_ for details. 1303c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch bool initialized() const { 130472a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen base::AutoLock lock(initialized_mutex_); 1305c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch return initialized_; 1306c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch } 1307c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 1308dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen // If this is a deletion for a password, sets the legacy 1309dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen // ExtraPasswordChangeRecordData field of |buffer|. Otherwise sets 1310dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen // |buffer|'s specifics field to contain the unencrypted data. 1311c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch void SetExtraChangeRecordData(int64 id, 1312c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch syncable::ModelType type, 1313c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch ChangeReorderBuffer* buffer, 13143345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick Cryptographer* cryptographer, 1315c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch const syncable::EntryKernel& original, 1316c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch bool existed_before, 1317c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch bool exists_now); 1318c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 1319c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch // Called only by our NetworkChangeNotifier. 1320c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch virtual void OnIPAddressChanged(); 1321c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 1322c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch bool InitialSyncEndedForAllEnabledTypes() { 1323c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch syncable::ScopedDirLookup lookup(dir_manager(), username_for_share()); 1324c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch if (!lookup.good()) { 1325c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch DCHECK(false) << "ScopedDirLookup failed when checking initial sync"; 1326c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch return false; 1327c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch } 1328c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 1329c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch ModelSafeRoutingInfo enabled_types; 1330c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch registrar_->GetModelSafeRoutingInfo(&enabled_types); 1331c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch for (ModelSafeRoutingInfo::const_iterator i = enabled_types.begin(); 1332c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch i != enabled_types.end(); ++i) { 1333c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch if (!lookup->initial_sync_ended_for_type(i->first)) 1334c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch return false; 1335c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch } 1336c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch return true; 1337c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch } 1338c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 133921d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen syncable::AutofillMigrationState GetAutofillMigrationState() { 134021d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen syncable::ScopedDirLookup lookup(dir_manager(), username_for_share()); 134121d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen if (!lookup.good()) { 134221d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen DCHECK(false) << "ScopedDirLookup failed when checking initial sync"; 134321d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen return syncable::NOT_MIGRATED; 134421d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen } 134521d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen 134621d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen return lookup->get_autofill_migration_state(); 134721d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen } 134821d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen 134921d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen void SetAutofillMigrationState(syncable::AutofillMigrationState state) { 135021d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen syncable::ScopedDirLookup lookup(dir_manager(), username_for_share()); 135121d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen if (!lookup.good()) { 135221d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen DCHECK(false) << "ScopedDirLookup failed when checking initial sync"; 135321d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen return; 135421d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen } 135521d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen 135621d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen return lookup->set_autofill_migration_state(state); 135721d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen } 135821d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen 135921d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen void SetAutofillMigrationDebugInfo( 136021d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen syncable::AutofillMigrationDebugInfo::PropertyToSet property_to_set, 136121d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen const syncable::AutofillMigrationDebugInfo& info) { 136221d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen syncable::ScopedDirLookup lookup(dir_manager(), username_for_share()); 136321d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen if (!lookup.good()) { 136421d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen DCHECK(false) << "ScopedDirLookup failed when checking initial sync"; 136521d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen return; 136621d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen } 136721d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen 136821d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen return lookup->set_autofill_migration_state_debug_info( 136921d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen property_to_set, info); 137021d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen } 137121d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen 137221d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen syncable::AutofillMigrationDebugInfo 137321d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen GetAutofillMigrationDebugInfo() { 137421d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen syncable::ScopedDirLookup lookup(dir_manager(), username_for_share()); 137521d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen if (!lookup.good()) { 137621d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen DCHECK(false) << "ScopedDirLookup failed when checking initial sync"; 137721d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen syncable::AutofillMigrationDebugInfo null_value = {0}; 137821d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen return null_value; 137921d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen } 138021d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen return lookup->get_autofill_migration_debug_info(); 138121d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen } 138221d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen 1383731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick // SyncEngineEventListener implementation. 1384731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick virtual void OnSyncEngineEvent(const SyncEngineEvent& event); 138572a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen 1386ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen // ServerConnectionEventListener implementation. 1387ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen virtual void OnServerConnectionEvent(const ServerConnectionEvent2& event); 1388ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen 138972a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen // browser_sync::JsBackend implementation. 139072a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen virtual void SetParentJsEventRouter(browser_sync::JsEventRouter* router); 139172a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen virtual void RemoveParentJsEventRouter(); 139272a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen virtual const browser_sync::JsEventRouter* GetParentJsEventRouter() const; 139372a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen virtual void ProcessMessage(const std::string& name, 139472a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen const browser_sync::JsArgList& args, 139572a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen const browser_sync::JsEventHandler* sender); 139672a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen 1397ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen ListValue* FindNodesContainingString(const std::string& query); 1398731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick 1399ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen private: 1400c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch // Helper to call OnAuthError when no authentication credentials are 1401c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch // available. 1402c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch void RaiseAuthNeededEvent(); 1403c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 1404c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch // Helper to set initialized_ to true and raise an event to clients to notify 1405c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch // that initialization is complete and it is safe to send us changes. If 1406c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch // already initialized, this is a no-op. 1407c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch void MarkAndNotifyInitializationComplete(); 1408c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 1409ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen // Sends notifications to peers. 1410ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen void SendNotification(); 1411c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 1412c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch // Determine if the parents or predecessors differ between the old and new 1413c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch // versions of an entry stored in |a| and |b|. Note that a node's index may 1414c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch // change without its NEXT_ID changing if the node at NEXT_ID also moved (but 1415c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch // the relative order is unchanged). To handle such cases, we rely on the 1416c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch // caller to treat a position update on any sibling as updating the positions 1417c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch // of all siblings. 1418c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch static bool VisiblePositionsDiffer(const syncable::EntryKernel& a, 1419c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch const syncable::Entry& b) { 1420c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch // If the datatype isn't one where the browser model cares about position, 1421c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch // don't bother notifying that data model of position-only changes. 1422c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch if (!b.ShouldMaintainPosition()) 1423c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch return false; 1424c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch if (a.ref(syncable::NEXT_ID) != b.Get(syncable::NEXT_ID)) 1425c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch return true; 1426c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch if (a.ref(syncable::PARENT_ID) != b.Get(syncable::PARENT_ID)) 1427c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch return true; 1428c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch return false; 1429c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch } 1430c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 1431c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch // Determine if any of the fields made visible to clients of the Sync API 1432c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch // differ between the versions of an entry stored in |a| and |b|. A return 1433c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch // value of false means that it should be OK to ignore this change. 1434c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch static bool VisiblePropertiesDiffer(const syncable::EntryKernel& a, 1435dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen const syncable::Entry& b, 1436dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen Cryptographer* cryptographer) { 1437c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch syncable::ModelType model_type = b.GetModelType(); 1438c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch // Suppress updates to items that aren't tracked by any browser model. 1439c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch if (model_type == syncable::UNSPECIFIED || 1440c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch model_type == syncable::TOP_LEVEL_FOLDER) { 1441c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch return false; 1442c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch } 1443c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch if (a.ref(syncable::NON_UNIQUE_NAME) != b.Get(syncable::NON_UNIQUE_NAME)) 1444c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch return true; 1445c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch if (a.ref(syncable::IS_DIR) != b.Get(syncable::IS_DIR)) 1446c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch return true; 1447dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen // Check if data has changed (account for encryption). 1448dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen std::string a_str, b_str; 1449dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen if (a.ref(SPECIFICS).has_encrypted()) { 1450dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen const sync_pb::EncryptedData& encrypted = a.ref(SPECIFICS).encrypted(); 1451dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen a_str = cryptographer->DecryptToString(encrypted); 1452dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen } else { 1453dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen a_str = a.ref(SPECIFICS).SerializeAsString(); 1454dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen } 1455dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen if (b.Get(SPECIFICS).has_encrypted()) { 1456dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen const sync_pb::EncryptedData& encrypted = b.Get(SPECIFICS).encrypted(); 1457dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen b_str = cryptographer->DecryptToString(encrypted); 1458dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen } else { 1459dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen b_str = b.Get(SPECIFICS).SerializeAsString(); 1460dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen } 1461dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen if (a_str != b_str) { 1462c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch return true; 1463c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch } 1464c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch if (VisiblePositionsDiffer(a, b)) 1465c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch return true; 1466c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch return false; 1467c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch } 1468c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 1469c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch bool ChangeBuffersAreEmpty() { 1470c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch for (int i = 0; i < syncable::MODEL_TYPE_COUNT; ++i) { 1471c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch if (!change_buffers_[i].IsEmpty()) 1472c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch return false; 1473c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch } 1474c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch return true; 1475c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch } 1476c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 14773345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick void CheckServerReachable() { 14783345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick if (connection_manager()) { 14793345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick connection_manager()->CheckServerReachable(); 14803345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick } else { 14813345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick NOTREACHED() << "Should be valid connection manager!"; 14823345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick } 14833345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick } 14843345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick 1485731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick void ReEncryptEverything(WriteTransaction* trans); 1486731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick 1487731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick // Initializes (bootstraps) the Cryptographer if NIGORI has finished 1488731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick // initial sync so that it can immediately start encrypting / decrypting. 1489731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick // If the restored key is incompatible with the current version of the NIGORI 1490731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick // node (which could happen if a restart occurred just after an update to 1491731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick // NIGORI was downloaded and the user must enter a new passphrase to decrypt) 1492731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick // then we will raise OnPassphraseRequired and set pending keys for 1493731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick // decryption. Otherwise, the cryptographer is made ready (is_ready()). 1494731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick void BootstrapEncryption(const std::string& restored_key_for_bootstrapping); 1495731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick 1496ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen // Called for every notification. This updates the notification statistics 1497ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen // to be displayed in about:sync. 1498ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen void UpdateNotificationInfo( 1499ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen const syncable::ModelTypePayloadMap& type_payloads); 1500ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen 15014a5e2dc747d50c653511c68ccb2cfbfb740bd5a7Ben Murdoch // Helper for migration to new nigori proto to set 15024a5e2dc747d50c653511c68ccb2cfbfb740bd5a7Ben Murdoch // 'using_explicit_passphrase' in the NigoriSpecifics. 15034a5e2dc747d50c653511c68ccb2cfbfb740bd5a7Ben Murdoch // TODO(tim): Bug 62103. Remove this after it has been pushed out to dev 15044a5e2dc747d50c653511c68ccb2cfbfb740bd5a7Ben Murdoch // channel users. 1505ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen void SetUsingExplicitPassphrasePrefForMigration( 1506ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen WriteTransaction* const trans); 15074a5e2dc747d50c653511c68ccb2cfbfb740bd5a7Ben Murdoch 1508513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch // Checks for server reachabilty and requests a nudge. 1509513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch void OnIPAddressChangedImpl(); 1510513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch 151172a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen // Functions called by ProcessMessage(). 151272a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen browser_sync::JsArgList ProcessGetNodeByIdMessage( 151372a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen const browser_sync::JsArgList& args); 151472a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen 1515ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen browser_sync::JsArgList ProcessFindNodesContainingString( 1516ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen const browser_sync::JsArgList& args); 1517ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen 1518c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch // We couple the DirectoryManager and username together in a UserShare member 1519c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch // so we can return a handle to share_ to clients of the API for use when 1520c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch // constructing any transaction type. 1521c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch UserShare share_; 1522c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 1523c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch MessageLoop* core_message_loop_; 1524c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 152572a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen ObserverList<SyncManager::Observer> observers_; 152672a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen 152772a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen browser_sync::JsEventRouter* parent_router_; 1528c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 1529c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch // The ServerConnectionManager used to abstract communication between the 1530c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch // client (the Syncer) and the sync server. 1531c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch scoped_ptr<SyncAPIServerConnectionManager> connection_manager_; 1532c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 1533c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch // The thread that runs the Syncer. Needs to be explicitly Start()ed. 1534ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen scoped_ptr<SyncerThread> syncer_thread_; 1535c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 1536ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen // The SyncNotifier which notifies us when updates need to be downloaded. 1537ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen sync_notifier::SyncNotifier* sync_notifier_; 1538c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 1539c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch // A multi-purpose status watch object that aggregates stats from various 1540c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch // sync components. 1541c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch AllStatus allstatus_; 1542c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 1543c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch // Each element of this array is a store of change records produced by 1544c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch // HandleChangeEvent during the CALCULATE_CHANGES step. The changes are 1545c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch // segregated by model type, and are stored here to be processed and 1546c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch // forwarded to the observer slightly later, at the TRANSACTION_ENDING 15473345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick // step by HandleTransactionEndingChangeEvent. The list is cleared in the 15483345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick // TRANSACTION_COMPLETE step by HandleTransactionCompleteChangeEvent. 1549c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch ChangeReorderBuffer change_buffers_[syncable::MODEL_TYPE_COUNT]; 1550c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 1551201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch // Event listener hookup for the ServerConnectionManager. 1552201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch scoped_ptr<EventListenerHookup> connection_manager_hookup_; 1553201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch 1554c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch // The sync dir_manager to which we belong. 1555c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch SyncManager* const sync_manager_; 1556c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 1557c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch // The entity that provides us with information about which types to sync. 1558c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch // The instance is shared between the SyncManager and the Syncer. 1559c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch ModelSafeWorkerRegistrar* registrar_; 1560c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 1561c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch // Set to true once Init has been called, and we know of an authenticated 1562c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch // valid) username either from a fresh authentication attempt (as in 1563c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch // first-use case) or from a previous attempt stored in our UserSettings 1564c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch // (as in the steady-state), and the syncable::Directory has been opened, 1565c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch // meaning we are ready to accept changes. Protected by initialized_mutex_ 1566c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch // as it can get read/set by both the SyncerThread and the AuthWatcherThread. 1567c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch bool initialized_; 156872a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen mutable base::Lock initialized_mutex_; 1569c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 15703345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick // True if the SyncManager should be running in test mode (no syncer thread 15713345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick // actually communicating with the server). 15723345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick bool setup_for_test_mode_; 15733345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick 15743345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick ScopedRunnableMethodFactory<SyncManager::SyncInternal> method_factory_; 1575dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen 1576ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen // Map used to store the notification info to be displayed in about:sync page. 1577ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen // TODO(lipalani) - prefill the map with enabled data types. 1578ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen NotificationInfoMap notification_info_map_; 1579c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch}; 1580c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdochconst int SyncManager::SyncInternal::kDefaultNudgeDelayMilliseconds = 200; 1581c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdochconst int SyncManager::SyncInternal::kPreferencesNudgeDelayMilliseconds = 2000; 1582c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 158372a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian MonsenSyncManager::Observer::~Observer() {} 158472a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen 1585c407dc5cd9bdc5668497f21b26b09d988ab439deBen MurdochSyncManager::SyncManager() { 1586c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch data_ = new SyncInternal(this); 1587c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch} 1588c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 1589c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdochbool SyncManager::Init(const FilePath& database_location, 1590c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch const char* sync_server_and_path, 1591c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch int sync_server_port, 1592c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch bool use_ssl, 1593c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch HttpPostProviderFactory* post_factory, 1594c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch ModelSafeWorkerRegistrar* registrar, 1595c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch const char* user_agent, 15963345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick const SyncCredentials& credentials, 1597ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen sync_notifier::SyncNotifier* sync_notifier, 15983345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick const std::string& restored_key_for_bootstrapping, 15993345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick bool setup_for_test_mode) { 1600c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch DCHECK(post_factory); 1601731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick VLOG(1) << "SyncManager starting Init..."; 1602c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch string server_string(sync_server_and_path); 1603c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch return data_->Init(database_location, 1604c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch server_string, 1605c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch sync_server_port, 1606c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch use_ssl, 1607c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch post_factory, 1608c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch registrar, 1609c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch user_agent, 16103345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick credentials, 1611ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen sync_notifier, 16123345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick restored_key_for_bootstrapping, 16133345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick setup_for_test_mode); 1614c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch} 1615c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 16163345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrickvoid SyncManager::UpdateCredentials(const SyncCredentials& credentials) { 16173345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick data_->UpdateCredentials(credentials); 16183345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick} 16193345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick 1620ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsenvoid SyncManager::UpdateEnabledTypes() { 1621ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen data_->UpdateEnabledTypes(); 1622dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen} 1623dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen 16243345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick 16253345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrickbool SyncManager::InitialSyncEndedForAllEnabledTypes() { 16263345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick return data_->InitialSyncEndedForAllEnabledTypes(); 1627c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch} 1628c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 1629c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdochvoid SyncManager::StartSyncing() { 1630c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch data_->StartSyncing(); 1631c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch} 1632c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 163321d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsensyncable::AutofillMigrationState 163421d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen SyncManager::GetAutofillMigrationState() { 163521d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen return data_->GetAutofillMigrationState(); 163621d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen} 163721d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen 163821d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsenvoid SyncManager::SetAutofillMigrationState( 163921d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen syncable::AutofillMigrationState state) { 164021d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen return data_->SetAutofillMigrationState(state); 164121d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen} 164221d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen 164321d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsensyncable::AutofillMigrationDebugInfo 164421d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen SyncManager::GetAutofillMigrationDebugInfo() { 164521d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen return data_->GetAutofillMigrationDebugInfo(); 164621d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen} 164721d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen 164821d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsenvoid SyncManager::SetAutofillMigrationDebugInfo( 164921d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen syncable::AutofillMigrationDebugInfo::PropertyToSet property_to_set, 165021d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen const syncable::AutofillMigrationDebugInfo& info) { 165121d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen return data_->SetAutofillMigrationDebugInfo(property_to_set, info); 165221d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen} 165321d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen 16544a5e2dc747d50c653511c68ccb2cfbfb740bd5a7Ben Murdochvoid SyncManager::SetPassphrase(const std::string& passphrase, 16554a5e2dc747d50c653511c68ccb2cfbfb740bd5a7Ben Murdoch bool is_explicit) { 16564a5e2dc747d50c653511c68ccb2cfbfb740bd5a7Ben Murdoch data_->SetPassphrase(passphrase, is_explicit); 16574a5e2dc747d50c653511c68ccb2cfbfb740bd5a7Ben Murdoch} 16584a5e2dc747d50c653511c68ccb2cfbfb740bd5a7Ben Murdoch 1659dc0f95d653279beabeb9817299e2902918ba123eKristian Monsenvoid SyncManager::EncryptDataTypes( 1660dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen const syncable::ModelTypeSet& encrypted_types) { 1661dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen data_->EncryptDataTypes(encrypted_types); 1662dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen} 1663dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen 16644a5e2dc747d50c653511c68ccb2cfbfb740bd5a7Ben Murdochbool SyncManager::IsUsingExplicitPassphrase() { 16654a5e2dc747d50c653511c68ccb2cfbfb740bd5a7Ben Murdoch return data_ && data_->IsUsingExplicitPassphrase(); 1666c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch} 1667c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 1668ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsenvoid SyncManager::RequestNudge(const tracked_objects::Location& location) { 1669ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen data_->RequestNudge(location); 16703345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick} 16713345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick 16723345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrickvoid SyncManager::RequestClearServerData() { 16733345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick if (data_->syncer_thread()) 1674ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen data_->syncer_thread()->ScheduleClearUserData(); 1675c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch} 1676c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 1677dc0f95d653279beabeb9817299e2902918ba123eKristian Monsenvoid SyncManager::RequestConfig(const syncable::ModelTypeBitSet& types) { 1678dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen if (!data_->syncer_thread()) 1679dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen return; 1680ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen StartConfigurationMode(NULL); 1681ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen data_->syncer_thread()->ScheduleConfig(types); 1682ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen} 1683ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen 1684ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsenvoid SyncManager::StartConfigurationMode(ModeChangeCallback* callback) { 1685ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen if (!data_->syncer_thread()) 1686ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen return; 1687ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen data_->syncer_thread()->Start( 1688ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen browser_sync::SyncerThread::CONFIGURATION_MODE, callback); 1689dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen} 1690dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen 1691c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdochconst std::string& SyncManager::GetAuthenticatedUsername() { 1692c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch DCHECK(data_); 1693c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch return data_->username_for_share(); 1694c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch} 1695c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 1696c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdochbool SyncManager::SyncInternal::Init( 1697c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch const FilePath& database_location, 1698c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch const std::string& sync_server_and_path, 1699c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch int port, 1700c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch bool use_ssl, 1701c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch HttpPostProviderFactory* post_factory, 1702c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch ModelSafeWorkerRegistrar* model_safe_worker_registrar, 1703c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch const char* user_agent, 17043345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick const SyncCredentials& credentials, 1705ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen sync_notifier::SyncNotifier* sync_notifier, 17063345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick const std::string& restored_key_for_bootstrapping, 17073345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick bool setup_for_test_mode) { 1708c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 1709731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick VLOG(1) << "Starting SyncInternal initialization."; 1710c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 1711c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch core_message_loop_ = MessageLoop::current(); 1712c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch DCHECK(core_message_loop_); 1713c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch registrar_ = model_safe_worker_registrar; 17143345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick setup_for_test_mode_ = setup_for_test_mode; 1715c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 1716ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen sync_notifier_ = sync_notifier; 1717ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen sync_notifier_->AddObserver(this); 1718ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen 1719c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch share_.dir_manager.reset(new DirectoryManager(database_location)); 1720c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 1721c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch connection_manager_.reset(new SyncAPIServerConnectionManager( 17223345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick sync_server_and_path, port, use_ssl, user_agent, post_factory)); 1723c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 1724dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen net::NetworkChangeNotifier::AddIPAddressObserver(this); 1725ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen 1726ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen connection_manager()->AddListener(this); 1727ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen 1728c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch // TODO(akalin): CheckServerReachable() can block, which may cause jank if we 1729c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch // try to shut down sync. Fix this. 17303345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick core_message_loop_->PostTask(FROM_HERE, 17313345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick method_factory_.NewRunnableMethod(&SyncInternal::CheckServerReachable)); 1732c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 17333345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick // Test mode does not use a syncer context or syncer thread. 173472a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen if (!setup_for_test_mode_) { 17353345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick // Build a SyncSessionContext and store the worker in it. 1736731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick VLOG(1) << "Sync is bringing up SyncSessionContext."; 1737731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick std::vector<SyncEngineEventListener*> listeners; 1738731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick listeners.push_back(&allstatus_); 1739731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick listeners.push_back(this); 17403345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick SyncSessionContext* context = new SyncSessionContext( 1741731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick connection_manager_.get(), 1742731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick dir_manager(), 1743731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick model_safe_worker_registrar, 1744731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick listeners); 1745dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen context->set_account_name(credentials.email); 17463345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick // The SyncerThread takes ownership of |context|. 1747ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen syncer_thread_.reset(new SyncerThread(context, new Syncer())); 1748731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick } 1749731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick 1750731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick bool signed_in = SignIn(credentials); 1751731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick 1752ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen if (signed_in && syncer_thread()) { 1753ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen syncer_thread()->Start( 1754ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen browser_sync::SyncerThread::CONFIGURATION_MODE, NULL); 1755ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen } 1756ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen 1757731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick // Do this once the directory is opened. 1758731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick BootstrapEncryption(restored_key_for_bootstrapping); 1759ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen MarkAndNotifyInitializationComplete(); 1760731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick return signed_in; 1761731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick} 1762731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick 1763731df977c0511bca2206b5f333555b1205ff1f43Iain Merrickvoid SyncManager::SyncInternal::BootstrapEncryption( 1764731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick const std::string& restored_key_for_bootstrapping) { 1765731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick syncable::ScopedDirLookup lookup(dir_manager(), username_for_share()); 1766731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick if (!lookup.good()) { 1767731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick NOTREACHED(); 1768731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick return; 1769731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick } 17703345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick 1771731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick if (!lookup->initial_sync_ended_for_type(syncable::NIGORI)) 1772731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick return; 1773731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick 1774dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen sync_pb::NigoriSpecifics nigori; 1775dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen { 1776ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen // Cryptographer should only be accessed while holding a transaction. 1777dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen ReadTransaction trans(GetUserShare()); 1778ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen Cryptographer* cryptographer = trans.GetCryptographer(); 1779ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen cryptographer->Bootstrap(restored_key_for_bootstrapping); 1780ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen 1781dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen ReadNode node(&trans); 1782dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen if (!node.InitByTagLookup(kNigoriTag)) { 1783dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen NOTREACHED(); 1784dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen return; 1785dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen } 17863345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick 1787dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen nigori.CopyFrom(node.GetNigoriSpecifics()); 1788dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen if (!nigori.encrypted().blob().empty()) { 1789dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen if (cryptographer->CanDecrypt(nigori.encrypted())) { 1790dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen cryptographer->SetKeys(nigori.encrypted()); 1791dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen } else { 1792dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen cryptographer->SetPendingKeys(nigori.encrypted()); 1793dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen FOR_EACH_OBSERVER(SyncManager::Observer, observers_, 1794dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen OnPassphraseRequired(true)); 1795dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen } 1796731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick } 1797731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick } 1798dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen 1799dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen // Refresh list of encrypted datatypes. 1800dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen syncable::ModelTypeSet encrypted_types = 1801dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen syncable::GetEncryptedDataTypesFromNigori(nigori); 1802dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen 1803dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen // Ensure any datatypes that need encryption are encrypted. 1804dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen EncryptDataTypes(encrypted_types); 1805c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch} 1806c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 1807c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdochvoid SyncManager::SyncInternal::StartSyncing() { 1808ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen // Start the syncer thread. This won't actually 1809ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen // result in any syncing until at least the 1810ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen // DirectoryManager broadcasts the OPENED event, 1811ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen // and a valid server connection is detected. 1812c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch if (syncer_thread()) // NULL during certain unittests. 1813ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen syncer_thread()->Start(SyncerThread::NORMAL_MODE, NULL); 1814c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch} 1815c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 1816c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdochvoid SyncManager::SyncInternal::MarkAndNotifyInitializationComplete() { 1817c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch // There is only one real time we need this mutex. If we get an auth 1818c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch // success, and before the initial sync ends we get an auth failure. In this 1819c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch // case we'll be listening to both the AuthWatcher and Syncer, and it's a race 1820c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch // between their respective threads to call MarkAndNotify. We need to make 1821c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch // sure the observer is notified once and only once. 1822c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch { 182372a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen base::AutoLock lock(initialized_mutex_); 1824c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch if (initialized_) 1825c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch return; 1826c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch initialized_ = true; 1827c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch } 1828c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 1829c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch // Notify that initialization is complete. 183072a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen FOR_EACH_OBSERVER(SyncManager::Observer, observers_, 183172a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen OnInitializationComplete()); 1832c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch} 1833c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 1834ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsenvoid SyncManager::SyncInternal::SendNotification() { 1835c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch DCHECK_EQ(MessageLoop::current(), core_message_loop_); 1836ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen if (!sync_notifier_) { 1837ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen VLOG(1) << "Not sending notification: sync_notifier_ is NULL"; 1838c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch return; 1839c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch } 1840ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen allstatus_.IncrementNotificationsSent(); 1841ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen sync_notifier_->SendNotification(); 1842c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch} 1843c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 18443345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrickbool SyncManager::SyncInternal::OpenDirectory() { 18453345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick DCHECK(!initialized()) << "Should only happen once"; 18463345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick 18473345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick bool share_opened = dir_manager()->Open(username_for_share()); 18483345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick DCHECK(share_opened); 18493345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick if (!share_opened) { 185072a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen FOR_EACH_OBSERVER(SyncManager::Observer, observers_, 185172a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen OnStopSyncingPermanently()); 18523345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick 18533345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick LOG(ERROR) << "Could not open share for:" << username_for_share(); 18543345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick return false; 1855c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch } 1856c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 18573345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick // Database has to be initialized for the guid to be available. 18583345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick syncable::ScopedDirLookup lookup(dir_manager(), username_for_share()); 18593345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick if (!lookup.good()) { 18603345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick NOTREACHED(); 18613345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick return false; 18623345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick } 18633345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick 18643345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick connection_manager()->set_client_id(lookup->cache_guid()); 18653345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick 1866ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen lookup->SetChangeListener(this); 18673345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick return true; 1868c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch} 1869c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 18703345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrickbool SyncManager::SyncInternal::SignIn(const SyncCredentials& credentials) { 18713345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick DCHECK_EQ(MessageLoop::current(), core_message_loop_); 18723345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick DCHECK(share_.name.empty()); 18733345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick share_.name = credentials.email; 1874c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 1875731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick VLOG(1) << "Signing in user: " << username_for_share(); 1876731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick if (!OpenDirectory()) 1877c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch return false; 1878c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 1879ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen // Retrieve and set the sync notifier state. This should be done 1880ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen // only after OpenDirectory is called. 1881ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen syncable::ScopedDirLookup lookup(dir_manager(), username_for_share()); 1882ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen std::string state; 1883ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen if (lookup.good()) { 1884ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen state = lookup->GetAndClearNotificationState(); 1885ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen } else { 1886ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen LOG(ERROR) << "Could not read notification state"; 1887ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen } 1888ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen if (VLOG_IS_ON(1)) { 1889ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen std::string encoded_state; 1890ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen base::Base64Encode(state, &encoded_state); 1891ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen VLOG(1) << "Read notification state: " << encoded_state; 189272a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen } 1893ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen sync_notifier_->SetState(state); 1894ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen 1895ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen UpdateCredentials(credentials); 1896ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen UpdateEnabledTypes(); 1897c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch return true; 1898c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch} 1899c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 19003345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrickvoid SyncManager::SyncInternal::UpdateCredentials( 19013345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick const SyncCredentials& credentials) { 19023345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick DCHECK_EQ(MessageLoop::current(), core_message_loop_); 1903dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen DCHECK_EQ(credentials.email, share_.name); 1904ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen DCHECK(!credentials.email.empty()); 1905ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen DCHECK(!credentials.sync_token.empty()); 19063345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick connection_manager()->set_auth_token(credentials.sync_token); 1907ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen sync_notifier_->UpdateCredentials( 1908ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen credentials.email, credentials.sync_token); 1909ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen if (!setup_for_test_mode_) { 1910ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen CheckServerReachable(); 1911dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen } 1912dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen} 1913dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen 1914ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsenvoid SyncManager::SyncInternal::UpdateEnabledTypes() { 1915ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen DCHECK_EQ(MessageLoop::current(), core_message_loop_); 1916ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen ModelSafeRoutingInfo routes; 1917ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen registrar_->GetModelSafeRoutingInfo(&routes); 1918ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen syncable::ModelTypeSet enabled_types; 1919ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen for (ModelSafeRoutingInfo::const_iterator it = routes.begin(); 1920ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen it != routes.end(); ++it) { 1921ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen enabled_types.insert(it->first); 1922731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick } 1923ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen sync_notifier_->UpdateEnabledTypes(enabled_types); 1924731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick} 1925731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick 1926c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdochvoid SyncManager::SyncInternal::RaiseAuthNeededEvent() { 192772a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen FOR_EACH_OBSERVER( 192872a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen SyncManager::Observer, observers_, 192972a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen OnAuthError(AuthError(AuthError::INVALID_GAIA_CREDENTIALS))); 1930c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch} 1931c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 1932ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsenvoid SyncManager::SyncInternal::SetUsingExplicitPassphrasePrefForMigration( 1933ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen WriteTransaction* const trans) { 1934ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen WriteNode node(trans); 19354a5e2dc747d50c653511c68ccb2cfbfb740bd5a7Ben Murdoch if (!node.InitByTagLookup(kNigoriTag)) { 19364a5e2dc747d50c653511c68ccb2cfbfb740bd5a7Ben Murdoch // TODO(albertb): Plumb an UnrecoverableError all the way back to the PSS. 19374a5e2dc747d50c653511c68ccb2cfbfb740bd5a7Ben Murdoch NOTREACHED(); 19384a5e2dc747d50c653511c68ccb2cfbfb740bd5a7Ben Murdoch return; 19394a5e2dc747d50c653511c68ccb2cfbfb740bd5a7Ben Murdoch } 19404a5e2dc747d50c653511c68ccb2cfbfb740bd5a7Ben Murdoch sync_pb::NigoriSpecifics specifics(node.GetNigoriSpecifics()); 19414a5e2dc747d50c653511c68ccb2cfbfb740bd5a7Ben Murdoch specifics.set_using_explicit_passphrase(true); 19424a5e2dc747d50c653511c68ccb2cfbfb740bd5a7Ben Murdoch node.SetNigoriSpecifics(specifics); 19434a5e2dc747d50c653511c68ccb2cfbfb740bd5a7Ben Murdoch} 19444a5e2dc747d50c653511c68ccb2cfbfb740bd5a7Ben Murdoch 1945c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdochvoid SyncManager::SyncInternal::SetPassphrase( 19464a5e2dc747d50c653511c68ccb2cfbfb740bd5a7Ben Murdoch const std::string& passphrase, bool is_explicit) { 1947ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen // All accesses to the cryptographer are protected by a transaction. 1948ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen WriteTransaction trans(GetUserShare()); 1949ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen Cryptographer* cryptographer = trans.GetCryptographer(); 1950c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch KeyParams params = {"localhost", "dummy", passphrase}; 1951ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen 1952c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch if (cryptographer->has_pending_keys()) { 1953c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch if (!cryptographer->DecryptPendingKeys(params)) { 1954dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen VLOG(1) << "Passphrase failed to decrypt pending keys."; 195572a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen FOR_EACH_OBSERVER(SyncManager::Observer, observers_, 1956dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen OnPassphraseFailed()); 1957c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch return; 1958c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch } 19594a5e2dc747d50c653511c68ccb2cfbfb740bd5a7Ben Murdoch 19604a5e2dc747d50c653511c68ccb2cfbfb740bd5a7Ben Murdoch // TODO(tim): If this is the first time the user has entered a passphrase 19614a5e2dc747d50c653511c68ccb2cfbfb740bd5a7Ben Murdoch // since the protocol changed to store passphrase preferences in the cloud, 19624a5e2dc747d50c653511c68ccb2cfbfb740bd5a7Ben Murdoch // make sure we update this preference. See bug 62103. 19634a5e2dc747d50c653511c68ccb2cfbfb740bd5a7Ben Murdoch if (is_explicit) 1964ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen SetUsingExplicitPassphrasePrefForMigration(&trans); 19654a5e2dc747d50c653511c68ccb2cfbfb740bd5a7Ben Murdoch 1966dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen // Nudge the syncer so that encrypted datatype updates that were waiting for 1967dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen // this passphrase get applied as soon as possible. 1968ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen RequestNudge(FROM_HERE); 1969c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch } else { 1970dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen VLOG(1) << "No pending keys, adding provided passphrase."; 1971c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch WriteNode node(&trans); 1972c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch if (!node.InitByTagLookup(kNigoriTag)) { 1973c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch // TODO(albertb): Plumb an UnrecoverableError all the way back to the PSS. 1974c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch NOTREACHED(); 1975c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch return; 1976c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch } 19774a5e2dc747d50c653511c68ccb2cfbfb740bd5a7Ben Murdoch 19784a5e2dc747d50c653511c68ccb2cfbfb740bd5a7Ben Murdoch // Prevent an implicit SetPassphrase request from changing an explicitly 19794a5e2dc747d50c653511c68ccb2cfbfb740bd5a7Ben Murdoch // set passphrase. 19804a5e2dc747d50c653511c68ccb2cfbfb740bd5a7Ben Murdoch if (!is_explicit && node.GetNigoriSpecifics().using_explicit_passphrase()) 19814a5e2dc747d50c653511c68ccb2cfbfb740bd5a7Ben Murdoch return; 19824a5e2dc747d50c653511c68ccb2cfbfb740bd5a7Ben Murdoch 1983c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch cryptographer->AddKey(params); 1984c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 1985731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick // TODO(tim): Bug 58231. It would be nice if SetPassphrase didn't require 1986731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick // messing with the Nigori node, because we can't call SetPassphrase until 1987731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick // download conditions are met vs Cryptographer init. It seems like it's 1988731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick // safe to defer this work. 1989dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen sync_pb::NigoriSpecifics specifics(node.GetNigoriSpecifics()); 1990dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen specifics.clear_encrypted(); 1991c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch cryptographer->GetKeys(specifics.mutable_encrypted()); 19924a5e2dc747d50c653511c68ccb2cfbfb740bd5a7Ben Murdoch specifics.set_using_explicit_passphrase(is_explicit); 1993c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch node.SetNigoriSpecifics(specifics); 1994731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick ReEncryptEverything(&trans); 1995c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch } 19963345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick 19973345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick std::string bootstrap_token; 19983345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick cryptographer->GetBootstrapToken(&bootstrap_token); 199972a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen FOR_EACH_OBSERVER(SyncManager::Observer, observers_, 200072a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen OnPassphraseAccepted(bootstrap_token)); 2001c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch} 2002c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 20034a5e2dc747d50c653511c68ccb2cfbfb740bd5a7Ben Murdochbool SyncManager::SyncInternal::IsUsingExplicitPassphrase() { 20044a5e2dc747d50c653511c68ccb2cfbfb740bd5a7Ben Murdoch ReadTransaction trans(&share_); 20054a5e2dc747d50c653511c68ccb2cfbfb740bd5a7Ben Murdoch ReadNode node(&trans); 20064a5e2dc747d50c653511c68ccb2cfbfb740bd5a7Ben Murdoch if (!node.InitByTagLookup(kNigoriTag)) { 20074a5e2dc747d50c653511c68ccb2cfbfb740bd5a7Ben Murdoch // TODO(albertb): Plumb an UnrecoverableError all the way back to the PSS. 20084a5e2dc747d50c653511c68ccb2cfbfb740bd5a7Ben Murdoch NOTREACHED(); 20094a5e2dc747d50c653511c68ccb2cfbfb740bd5a7Ben Murdoch return false; 20104a5e2dc747d50c653511c68ccb2cfbfb740bd5a7Ben Murdoch } 20114a5e2dc747d50c653511c68ccb2cfbfb740bd5a7Ben Murdoch 20124a5e2dc747d50c653511c68ccb2cfbfb740bd5a7Ben Murdoch return node.GetNigoriSpecifics().using_explicit_passphrase(); 20134a5e2dc747d50c653511c68ccb2cfbfb740bd5a7Ben Murdoch} 20144a5e2dc747d50c653511c68ccb2cfbfb740bd5a7Ben Murdoch 2015dc0f95d653279beabeb9817299e2902918ba123eKristian Monsenvoid SyncManager::SyncInternal::EncryptDataTypes( 2016dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen const syncable::ModelTypeSet& encrypted_types) { 2017dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen VLOG(1) << "Attempting to encrypt datatypes " 2018dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen << syncable::ModelTypeSetToString(encrypted_types); 2019dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen 2020dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen WriteTransaction trans(GetUserShare()); 2021dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen WriteNode node(&trans); 2022dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen if (!node.InitByTagLookup(kNigoriTag)) { 2023dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen LOG(ERROR) << "Unable to set encrypted datatypes because Nigori node not " 2024dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen << "found."; 2025dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen NOTREACHED(); 2026731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick return; 2027731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick } 2028731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick 2029dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen // Update the Nigori node set of encrypted datatypes so other machines notice. 2030dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen // Note, we merge the current encrypted types with those requested. Once a 2031dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen // datatypes is marked as needing encryption, it is never unmarked. 2032dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen sync_pb::NigoriSpecifics nigori; 2033dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen nigori.CopyFrom(node.GetNigoriSpecifics()); 2034dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen syncable::ModelTypeSet current_encrypted_types = 2035dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen syncable::GetEncryptedDataTypesFromNigori(nigori); 2036dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen syncable::ModelTypeSet newly_encrypted_types; 2037dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen std::set_union(current_encrypted_types.begin(), current_encrypted_types.end(), 2038dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen encrypted_types.begin(), encrypted_types.end(), 2039dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen std::inserter(newly_encrypted_types, 2040dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen newly_encrypted_types.begin())); 2041dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen syncable::FillNigoriEncryptedTypes(newly_encrypted_types, &nigori); 2042dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen node.SetNigoriSpecifics(nigori); 2043dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen 2044dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen // TODO(zea): only reencrypt this datatype? ReEncrypting everything is a 2045dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen // safer approach, and should not impact anything that is already encrypted 2046dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen // (redundant changes are ignored). 2047dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen ReEncryptEverything(&trans); 2048dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen return; 2049dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen} 2050dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen 2051ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsennamespace { 2052ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen 2053ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsenvoid FindChildNodesContainingString(const std::string& lowercase_query, 2054ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen const ReadNode& parent_node, 2055ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen sync_api::ReadTransaction* trans, 2056ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen ListValue* result) { 2057ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen int64 child_id = parent_node.GetFirstChildId(); 2058ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen while (child_id != kInvalidId) { 2059ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen ReadNode node(trans); 2060ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen if (node.InitByIdLookup(child_id)) { 2061ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen if (node.ContainsString(lowercase_query)) { 2062ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen result->Append(new StringValue(base::Int64ToString(child_id))); 2063ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen } 2064ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen FindChildNodesContainingString(lowercase_query, node, trans, result); 2065ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen child_id = node.GetSuccessorId(); 2066ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen } else { 2067ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen LOG(WARNING) << "Lookup of node failed. Id: " << child_id; 2068ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen return; 2069ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen } 2070ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen } 2071ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen} 2072ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen} // namespace 2073ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen 2074ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen// Returned pointer owned by the caller. 2075ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian MonsenListValue* SyncManager::SyncInternal::FindNodesContainingString( 2076ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen const std::string& query) { 2077ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen // Convert the query string to lower case to perform case insensitive 2078ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen // searches. 2079ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen std::string lowercase_query = query; 2080ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen StringToLowerASCII(&lowercase_query); 2081ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen ReadTransaction trans(GetUserShare()); 2082ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen ReadNode root(&trans); 2083ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen root.InitByRootLookup(); 2084ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen 2085ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen ListValue* result = new ListValue(); 2086ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen 2087ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen base::Time start_time = base::Time::Now(); 2088ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen FindChildNodesContainingString(lowercase_query, root, &trans, result); 2089ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen base::Time end_time = base::Time::Now(); 2090ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen 2091ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen base::TimeDelta delta = end_time - start_time; 2092ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen VLOG(1) << "Time taken in milliseconds to search " << delta.InMilliseconds(); 2093ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen 2094ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen return result; 2095ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen} 2096ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen 2097dc0f95d653279beabeb9817299e2902918ba123eKristian Monsenvoid SyncManager::SyncInternal::ReEncryptEverything(WriteTransaction* trans) { 2098dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen syncable::ModelTypeSet encrypted_types = 2099dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen GetEncryptedDataTypes(trans->GetWrappedTrans()); 2100dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen ModelSafeRoutingInfo routes; 2101dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen registrar_->GetModelSafeRoutingInfo(&routes); 2102dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen std::string tag; 2103dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen for (syncable::ModelTypeSet::iterator iter = encrypted_types.begin(); 2104dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen iter != encrypted_types.end(); ++iter) { 2105dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen if (*iter == syncable::PASSWORDS || routes.count(*iter) == 0) 2106dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen continue; 2107dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen ReadNode type_root(trans); 2108dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen tag = syncable::ModelTypeToRootTag(*iter); 2109dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen if (!type_root.InitByTagLookup(tag)) { 2110731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick NOTREACHED(); 2111731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick return; 2112731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick } 2113dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen 2114dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen // Iterate through all children of this datatype. 2115dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen std::queue<int64> to_visit; 2116dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen int64 child_id = type_root.GetFirstChildId(); 2117dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen to_visit.push(child_id); 2118dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen while (!to_visit.empty()) { 2119dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen child_id = to_visit.front(); 2120dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen to_visit.pop(); 2121dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen if (child_id == kInvalidId) 2122dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen continue; 2123dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen 2124dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen WriteNode child(trans); 2125dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen if (!child.InitByIdLookup(child_id)) { 2126dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen NOTREACHED(); 2127dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen return; 2128dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen } 2129dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen if (child.GetIsFolder()) { 2130dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen to_visit.push(child.GetFirstChildId()); 2131dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen } else { 2132dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen // Rewrite the specifics of the node with encrypted data if necessary. 2133dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen child.ResetFromSpecifics(); 2134dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen } 2135dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen to_visit.push(child.GetSuccessorId()); 2136dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen } 2137dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen } 2138dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen 2139dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen if (routes.count(syncable::PASSWORDS) > 0) { 2140dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen // Passwords are encrypted with their own legacy scheme. 2141dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen encrypted_types.insert(syncable::PASSWORDS); 2142dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen ReadNode passwords_root(trans); 2143dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen std::string passwords_tag = 2144dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen syncable::ModelTypeToRootTag(syncable::PASSWORDS); 2145dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen if (!passwords_root.InitByTagLookup(passwords_tag)) { 2146dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen LOG(WARNING) << "No passwords to reencrypt."; 2147dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen return; 2148dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen } 2149dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen 2150dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen int64 child_id = passwords_root.GetFirstChildId(); 2151dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen while (child_id != kInvalidId) { 2152dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen WriteNode child(trans); 2153dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen if (!child.InitByIdLookup(child_id)) { 2154dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen NOTREACHED(); 2155dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen return; 2156dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen } 2157dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen child.SetPasswordSpecifics(child.GetPasswordSpecifics()); 2158dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen child_id = child.GetSuccessorId(); 2159dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen } 2160731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick } 2161dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen 2162dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen FOR_EACH_OBSERVER(SyncManager::Observer, observers_, 2163dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen OnEncryptionComplete(encrypted_types)); 2164731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick} 2165731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick 2166c407dc5cd9bdc5668497f21b26b09d988ab439deBen MurdochSyncManager::~SyncManager() { 2167c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch delete data_; 2168c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch} 2169c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 217072a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsenvoid SyncManager::AddObserver(Observer* observer) { 217172a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen data_->AddObserver(observer); 217272a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen} 217372a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen 217472a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsenvoid SyncManager::RemoveObserver(Observer* observer) { 217572a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen data_->RemoveObserver(observer); 2176c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch} 2177c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 217872a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsenbrowser_sync::JsBackend* SyncManager::GetJsBackend() { 217972a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen return data_; 2180c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch} 2181c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 2182c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdochvoid SyncManager::Shutdown() { 2183c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch data_->Shutdown(); 2184c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch} 2185c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 2186c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdochvoid SyncManager::SyncInternal::Shutdown() { 21873345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick method_factory_.RevokeAll(); 21883345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick 2189c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch if (syncer_thread()) { 2190ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen syncer_thread()->Stop(); 2191dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen syncer_thread_.reset(); 2192c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch } 2193c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 2194ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen // We NULL out sync_notifer_ so that any pending tasks do not 2195ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen // trigger further notifications. 2196ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen // TODO(akalin): NULL the other member variables defensively, too. 2197ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen if (sync_notifier_) { 2198ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen sync_notifier_->RemoveObserver(this); 2199c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch } 2200c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 2201ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen // |this| is about to be destroyed, so we have to ensure any messages 2202ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen // that were posted to core_thread_ before or during syncer thread shutdown 2203ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen // are flushed out, else they refer to garbage memory. SendNotification 2204ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen // is an example. 2205ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen // TODO(tim): Remove this monstrosity, perhaps with ObserverListTS once core 2206ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen // thread is removed. Bug 78190. 2207c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch { 2208c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch CHECK(core_message_loop_); 2209c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch bool old_state = core_message_loop_->NestableTasksAllowed(); 2210c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch core_message_loop_->SetNestableTasksAllowed(true); 2211c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch core_message_loop_->RunAllPending(); 2212c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch core_message_loop_->SetNestableTasksAllowed(old_state); 2213c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch } 2214c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 2215dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen net::NetworkChangeNotifier::RemoveIPAddressObserver(this); 2216c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 2217201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch connection_manager_hookup_.reset(); 22183345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick 2219c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch if (dir_manager()) { 2220c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch dir_manager()->FinalSaveChangesForAll(); 2221c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch dir_manager()->Close(username_for_share()); 2222c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch } 2223c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 2224c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch // Reset the DirectoryManager and UserSettings so they relinquish sqlite 2225c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch // handles to backing files. 2226c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch share_.dir_manager.reset(); 2227c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 2228c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch core_message_loop_ = NULL; 2229c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch} 2230c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 2231c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdochvoid SyncManager::SyncInternal::OnIPAddressChanged() { 2232731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick VLOG(1) << "IP address change detected"; 2233513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch#if defined (OS_CHROMEOS) 2234513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch // TODO(tim): This is a hack to intentionally lose a race with flimflam at 2235513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch // shutdown, so we don't cause shutdown to wait for our http request. 2236513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch // http://crosbug.com/8429 2237513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch MessageLoop::current()->PostDelayedTask(FROM_HERE, 2238513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch method_factory_.NewRunnableMethod(&SyncInternal::OnIPAddressChangedImpl), 2239513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch kChromeOSNetworkChangeReactionDelayHackMsec); 2240513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch#else 2241513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch OnIPAddressChangedImpl(); 2242513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch#endif // defined(OS_CHROMEOS) 2243513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch} 2244513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch 2245513209b27ff55e2841eac0e4120199c23acce758Ben Murdochvoid SyncManager::SyncInternal::OnIPAddressChangedImpl() { 2246c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch // TODO(akalin): CheckServerReachable() can block, which may cause 2247c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch // jank if we try to shut down sync. Fix this. 2248c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch connection_manager()->CheckServerReachable(); 2249ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen RequestNudge(FROM_HERE); 2250c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch} 2251c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 2252ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsenvoid SyncManager::SyncInternal::OnServerConnectionEvent( 2253ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen const ServerConnectionEvent2& event) { 2254ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen ServerConnectionEvent legacy; 2255ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen legacy.what_happened = ServerConnectionEvent::STATUS_CHANGED; 2256ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen legacy.connection_code = event.connection_code; 2257ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen legacy.server_reachable = event.server_reachable; 2258ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen HandleServerConnectionEvent(legacy); 22593345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick} 22603345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick 2261201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdochvoid SyncManager::SyncInternal::HandleServerConnectionEvent( 22623345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick const ServerConnectionEvent& event) { 22633345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick allstatus_.HandleServerConnectionEvent(event); 22643345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick if (event.what_happened == ServerConnectionEvent::STATUS_CHANGED) { 22653345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick if (event.connection_code == 22663345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick browser_sync::HttpResponse::SERVER_CONNECTION_OK) { 226772a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen FOR_EACH_OBSERVER(SyncManager::Observer, observers_, 226872a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen OnAuthError(AuthError::None())); 22693345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick } 22703345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick 22713345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick if (event.connection_code == browser_sync::HttpResponse::SYNC_AUTH_ERROR) { 227272a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen FOR_EACH_OBSERVER( 227372a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen SyncManager::Observer, observers_, 227472a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen OnAuthError(AuthError(AuthError::INVALID_GAIA_CREDENTIALS))); 22753345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick } 22763345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick } 22773345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick} 22783345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick 2279ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsenvoid SyncManager::SyncInternal::HandleTransactionCompleteChangeEvent( 2280ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen const syncable::ModelTypeBitSet& models_with_changes) { 2281ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen // This notification happens immediately after the transaction mutex is 2282ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen // released. This allows work to be performed without blocking other threads 2283ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen // from acquiring a transaction. 2284ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen if (observers_.size() <= 0) 2285ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen return; 2286ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen 2287ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen // Call commit. 2288ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen for (int i = 0; i < syncable::MODEL_TYPE_COUNT; ++i) { 2289ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen if (models_with_changes.test(i)) { 2290ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen FOR_EACH_OBSERVER(SyncManager::Observer, observers_, 2291ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen OnChangesComplete(syncable::ModelTypeFromInt(i))); 2292ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen } 2293ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen } 2294ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen} 2295ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen 2296ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian MonsenModelTypeBitSet SyncManager::SyncInternal::HandleTransactionEndingChangeEvent( 2297ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen syncable::BaseTransaction* trans) { 2298c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch // This notification happens immediately before a syncable WriteTransaction 2299c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch // falls out of scope. It happens while the channel mutex is still held, 2300c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch // and while the transaction mutex is held, so it cannot be re-entrant. 230172a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen if (observers_.size() <= 0 || ChangeBuffersAreEmpty()) 2302ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen return ModelTypeBitSet(); 2303c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 2304c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch // This will continue the WriteTransaction using a read only wrapper. 2305c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch // This is the last chance for read to occur in the WriteTransaction 2306c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch // that's closing. This special ReadTransaction will not close the 2307c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch // underlying transaction. 2308ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen ReadTransaction read_trans(GetUserShare(), trans); 2309c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 2310ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen syncable::ModelTypeBitSet models_with_changes; 2311c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch for (int i = 0; i < syncable::MODEL_TYPE_COUNT; ++i) { 2312c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch if (change_buffers_[i].IsEmpty()) 2313c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch continue; 2314c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 2315c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch vector<ChangeRecord> ordered_changes; 2316ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen change_buffers_[i].GetAllChangesInTreeOrder(&read_trans, &ordered_changes); 2317c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch if (!ordered_changes.empty()) { 231872a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen FOR_EACH_OBSERVER( 231972a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen SyncManager::Observer, observers_, 2320ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen OnChangesApplied(syncable::ModelTypeFromInt(i), &read_trans, 232172a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen &ordered_changes[0], ordered_changes.size())); 2322ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen models_with_changes.set(i, true); 2323c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch } 2324c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch change_buffers_[i].Clear(); 2325c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch } 2326ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen return models_with_changes; 2327c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch} 2328c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 2329c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdochvoid SyncManager::SyncInternal::HandleCalculateChangesChangeEventFromSyncApi( 2330ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen const OriginalEntries& originals, 2331ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen const WriterTag& writer, 2332ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen syncable::BaseTransaction* trans) { 2333ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen // We have been notified about a user action changing a sync model. 2334ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen DCHECK(writer == syncable::SYNCAPI || 2335ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen writer == syncable::UNITTEST); 2336c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch LOG_IF(WARNING, !ChangeBuffersAreEmpty()) << 2337c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch "CALCULATE_CHANGES called with unapplied old changes."; 2338c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 2339c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch bool exists_unsynced_items = false; 2340c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch bool only_preference_changes = true; 23414a5e2dc747d50c653511c68ccb2cfbfb740bd5a7Ben Murdoch syncable::ModelTypeBitSet model_types; 2342ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen for (syncable::OriginalEntries::const_iterator i = originals.begin(); 2343ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen i != originals.end() && !exists_unsynced_items; 2344c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch ++i) { 2345c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch int64 id = i->ref(syncable::META_HANDLE); 2346ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen syncable::Entry e(trans, syncable::GET_BY_HANDLE, id); 2347c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch DCHECK(e.good()); 2348c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 2349c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch syncable::ModelType model_type = e.GetModelType(); 2350c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 2351c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch if (e.Get(syncable::IS_UNSYNCED)) { 2352c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch if (model_type == syncable::TOP_LEVEL_FOLDER || 2353c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch model_type == syncable::UNSPECIFIED) { 2354c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch NOTREACHED() << "Permanent or underspecified item changed via syncapi."; 2355c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch continue; 2356c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch } 2357c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch // Unsynced items will cause us to nudge the the syncer. 2358c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch exists_unsynced_items = true; 2359c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 23604a5e2dc747d50c653511c68ccb2cfbfb740bd5a7Ben Murdoch model_types[model_type] = true; 2361c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch if (model_type != syncable::PREFERENCES) 2362c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch only_preference_changes = false; 2363c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch } 2364c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch } 2365c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch if (exists_unsynced_items && syncer_thread()) { 2366c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch int nudge_delay = only_preference_changes ? 2367c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch kPreferencesNudgeDelayMilliseconds : kDefaultNudgeDelayMilliseconds; 2368ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen core_message_loop_->PostTask(FROM_HERE, 2369ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen NewRunnableMethod(this, &SyncInternal::RequestNudgeWithDataTypes, 2370ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen TimeDelta::FromMilliseconds(nudge_delay), 2371ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen browser_sync::NUDGE_SOURCE_LOCAL, 2372ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen model_types, 2373ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen FROM_HERE)); 2374c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch } 2375c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch} 2376c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 2377c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdochvoid SyncManager::SyncInternal::SetExtraChangeRecordData(int64 id, 2378c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch syncable::ModelType type, ChangeReorderBuffer* buffer, 23793345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick Cryptographer* cryptographer, const syncable::EntryKernel& original, 23803345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick bool existed_before, bool exists_now) { 2381dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen // If this is a deletion and the datatype was encrypted, we need to decrypt it 2382dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen // and attach it to the buffer. 2383c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch if (!exists_now && existed_before) { 2384dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen sync_pb::EntitySpecifics original_specifics(original.ref(SPECIFICS)); 23853345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick if (type == syncable::PASSWORDS) { 2386dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen // Passwords must use their own legacy ExtraPasswordChangeRecordData. 23873345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick scoped_ptr<sync_pb::PasswordSpecificsData> data( 2388dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen DecryptPasswordSpecifics(original_specifics, cryptographer)); 23893345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick if (!data.get()) { 23903345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick NOTREACHED(); 23913345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick return; 23923345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick } 23933345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick buffer->SetExtraDataForId(id, new ExtraPasswordChangeRecordData(*data)); 2394dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen } else if (original_specifics.has_encrypted()) { 2395dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen // All other datatypes can just create a new unencrypted specifics and 2396dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen // attach it. 2397dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen const sync_pb::EncryptedData& encrypted = original_specifics.encrypted(); 2398dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen if (!cryptographer->Decrypt(encrypted, &original_specifics)) { 2399dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen NOTREACHED(); 2400dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen return; 2401dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen } 24023345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick } 2403dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen buffer->SetSpecificsForId(id, original_specifics); 2404c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch } 2405c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch} 2406c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 2407c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdochvoid SyncManager::SyncInternal::HandleCalculateChangesChangeEventFromSyncer( 2408ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen const OriginalEntries& originals, 2409ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen const WriterTag& writer, 2410ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen syncable::BaseTransaction* trans) { 2411c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch // We only expect one notification per sync step, so change_buffers_ should 2412c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch // contain no pending entries. 2413ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen DCHECK(writer == syncable::SYNCER || 2414ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen writer == syncable::UNITTEST); 2415c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch LOG_IF(WARNING, !ChangeBuffersAreEmpty()) << 2416c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch "CALCULATE_CHANGES called with unapplied old changes."; 2417c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 2418ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen Cryptographer* crypto = dir_manager()->GetCryptographer(trans); 2419ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen for (syncable::OriginalEntries::const_iterator i = originals.begin(); 2420ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen i != originals.end(); ++i) { 2421c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch int64 id = i->ref(syncable::META_HANDLE); 2422ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen syncable::Entry e(trans, syncable::GET_BY_HANDLE, id); 2423c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch bool existed_before = !i->ref(syncable::IS_DEL); 2424c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch bool exists_now = e.good() && !e.Get(syncable::IS_DEL); 2425c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch DCHECK(e.good()); 2426c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 2427c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch // Omit items that aren't associated with a model. 2428c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch syncable::ModelType type = e.GetModelType(); 2429c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch if (type == syncable::TOP_LEVEL_FOLDER || type == syncable::UNSPECIFIED) 2430c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch continue; 2431c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 2432c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch if (exists_now && !existed_before) 2433c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch change_buffers_[type].PushAddedItem(id); 2434c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch else if (!exists_now && existed_before) 2435c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch change_buffers_[type].PushDeletedItem(id); 2436dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen else if (exists_now && existed_before && 2437ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen VisiblePropertiesDiffer(*i, e, crypto)) { 2438c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch change_buffers_[type].PushUpdatedItem(id, VisiblePositionsDiffer(*i, e)); 2439dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen } 2440c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 2441ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen SetExtraChangeRecordData(id, type, &change_buffers_[type], crypto, *i, 2442c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch existed_before, exists_now); 2443c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch } 2444c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch} 2445c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 244672a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian MonsenSyncManager::Status SyncManager::SyncInternal::GetStatus() { 244772a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen return allstatus_.status(); 2448c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch} 2449c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 2450ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsenvoid SyncManager::SyncInternal::RequestNudge( 2451ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen const tracked_objects::Location& location) { 2452ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen if (syncer_thread()) 2453ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen syncer_thread()->ScheduleNudge( 2454ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen TimeDelta::FromMilliseconds(0), browser_sync::NUDGE_SOURCE_LOCAL, 2455ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen ModelTypeBitSet(), location); 2456ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen} 2457ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen 2458ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsenvoid SyncManager::SyncInternal::RequestNudgeWithDataTypes( 2459ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen const TimeDelta& delay, 2460ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen browser_sync::NudgeSource source, const ModelTypeBitSet& types, 2461ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen const tracked_objects::Location& nudge_location) { 2462ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen if (syncer_thread()) 2463ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen syncer_thread()->ScheduleNudge(delay, source, types, nudge_location); 2464ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen} 2465ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen 2466731df977c0511bca2206b5f333555b1205ff1f43Iain Merrickvoid SyncManager::SyncInternal::OnSyncEngineEvent( 2467731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick const SyncEngineEvent& event) { 246872a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen if (observers_.size() <= 0) 2469c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch return; 2470c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 2471c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch // Only send an event if this is due to a cycle ending and this cycle 2472c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch // concludes a canonical "sync" process; that is, based on what is known 2473c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch // locally we are "all happy" and up-to-date. There may be new changes on 2474c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch // the server, but we'll get them on a subsequent sync. 2475c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch // 2476c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch // Notifications are sent at the end of every sync cycle, regardless of 2477c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch // whether we should sync again. 2478731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick if (event.what_happened == SyncEngineEvent::SYNC_CYCLE_ENDED) { 2479c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch ModelSafeRoutingInfo enabled_types; 2480c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch registrar_->GetModelSafeRoutingInfo(&enabled_types); 2481dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen { 2482dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen // Check to see if we need to notify the frontend that we have newly 2483dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen // encrypted types or that we require a passphrase. 2484dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen sync_api::ReadTransaction trans(GetUserShare()); 2485dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen sync_api::ReadNode node(&trans); 2486dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen if (!node.InitByTagLookup(kNigoriTag)) { 2487dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen DCHECK(!event.snapshot->is_share_usable); 2488dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen return; 2489c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch } 2490dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen const sync_pb::NigoriSpecifics& nigori = node.GetNigoriSpecifics(); 2491dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen syncable::ModelTypeSet encrypted_types = 2492dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen syncable::GetEncryptedDataTypesFromNigori(nigori); 2493dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen // If passwords are enabled, they're automatically considered encrypted. 2494dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen if (enabled_types.count(syncable::PASSWORDS) > 0) 2495dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen encrypted_types.insert(syncable::PASSWORDS); 2496dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen if (!encrypted_types.empty()) { 2497ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen Cryptographer* cryptographer = trans.GetCryptographer(); 2498dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen if (!cryptographer->is_ready() && !cryptographer->has_pending_keys()) { 2499dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen if (!nigori.encrypted().blob().empty()) { 2500dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen DCHECK(!cryptographer->CanDecrypt(nigori.encrypted())); 2501dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen cryptographer->SetPendingKeys(nigori.encrypted()); 2502dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen } 2503dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen } 25043345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick 2505dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen // If we've completed a sync cycle and the cryptographer isn't ready 2506dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen // yet, prompt the user for a passphrase. 2507dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen if (cryptographer->has_pending_keys()) { 2508dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen FOR_EACH_OBSERVER(SyncManager::Observer, observers_, 2509dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen OnPassphraseRequired(true)); 2510dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen } else if (!cryptographer->is_ready()) { 2511dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen FOR_EACH_OBSERVER(SyncManager::Observer, observers_, 2512dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen OnPassphraseRequired(false)); 2513dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen } else { 2514dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen FOR_EACH_OBSERVER(SyncManager::Observer, observers_, 2515dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen OnEncryptionComplete(encrypted_types)); 2516dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen } 2517c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch } 2518c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch } 2519c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 2520c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch if (!initialized()) 2521c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch return; 2522c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 2523c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch if (!event.snapshot->has_more_to_sync) { 252472a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen FOR_EACH_OBSERVER(SyncManager::Observer, observers_, 252572a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen OnSyncCycleCompleted(event.snapshot)); 2526c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch } 2527c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 2528ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen // This is here for tests, which are still using p2p notifications. 2529ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen // SendNotification does not do anything if we are using server based 2530ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen // notifications. 2531ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen // TODO(chron): Consider changing this back to track has_more_to_sync 2532ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen // only notify peers if a successful commit has occurred. 2533ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen bool new_notification = 2534ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen (event.snapshot->syncer_status.num_successful_commits > 0); 2535ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen if (new_notification) { 2536c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch core_message_loop_->PostTask( 2537c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch FROM_HERE, 2538c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch NewRunnableMethod( 2539c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch this, 2540ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen &SyncManager::SyncInternal::SendNotification)); 2541c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch } 2542c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch } 2543c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 2544731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick if (event.what_happened == SyncEngineEvent::STOP_SYNCING_PERMANENTLY) { 254572a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen FOR_EACH_OBSERVER(SyncManager::Observer, observers_, 254672a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen OnStopSyncingPermanently()); 2547c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch return; 2548c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch } 2549c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 2550731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick if (event.what_happened == SyncEngineEvent::CLEAR_SERVER_DATA_SUCCEEDED) { 255172a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen FOR_EACH_OBSERVER(SyncManager::Observer, observers_, 255272a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen OnClearServerDataSucceeded()); 2553c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch return; 2554c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch } 2555c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 2556731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick if (event.what_happened == SyncEngineEvent::CLEAR_SERVER_DATA_FAILED) { 255772a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen FOR_EACH_OBSERVER(SyncManager::Observer, observers_, 255872a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen OnClearServerDataFailed()); 25593345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick return; 25603345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick } 2561c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 2562731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick if (event.what_happened == SyncEngineEvent::UPDATED_TOKEN) { 256372a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen FOR_EACH_OBSERVER(SyncManager::Observer, observers_, 256472a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen OnUpdatedToken(event.updated_token)); 25653345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick return; 25663345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick } 2567c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch} 2568c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 256972a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsenvoid SyncManager::SyncInternal::SetParentJsEventRouter( 257072a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen browser_sync::JsEventRouter* router) { 257172a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen DCHECK(router); 257272a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen parent_router_ = router; 257372a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen} 257472a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen 257572a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsenvoid SyncManager::SyncInternal::RemoveParentJsEventRouter() { 257672a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen parent_router_ = NULL; 257772a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen} 257872a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen 257972a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsenconst browser_sync::JsEventRouter* 258072a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen SyncManager::SyncInternal::GetParentJsEventRouter() const { 258172a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen return parent_router_; 258272a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen} 258372a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen 258472a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsennamespace { 258572a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen 258672a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsenvoid LogNoRouter(const std::string& name, 258772a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen const browser_sync::JsArgList& args) { 258872a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen VLOG(1) << "No parent router; not replying to message " << name 258972a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen << " with args " << args.ToString(); 259072a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen} 259172a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen 259272a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen} // namespace 259372a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen 259472a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsenvoid SyncManager::SyncInternal::ProcessMessage( 259572a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen const std::string& name, const browser_sync::JsArgList& args, 259672a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen const browser_sync::JsEventHandler* sender) { 259772a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen DCHECK(initialized_); 259872a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen if (name == "getNotificationState") { 259972a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen if (!parent_router_) { 260072a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen LogNoRouter(name, args); 260172a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen return; 260272a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen } 260372a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen bool notifications_enabled = allstatus_.status().notifications_enabled; 260472a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen ListValue return_args; 260572a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen return_args.Append(Value::CreateBooleanValue(notifications_enabled)); 260672a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen parent_router_->RouteJsEvent( 260772a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen "onGetNotificationStateFinished", 260872a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen browser_sync::JsArgList(return_args), sender); 2609ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen } else if (name == "getNotificationInfo") { 2610ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen if (!parent_router_) { 2611ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen LogNoRouter(name, args); 2612ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen return; 2613ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen } 2614ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen 2615ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen ListValue return_args; 2616ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen return_args.Append(NotificationInfoToValue(notification_info_map_)); 2617ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen parent_router_->RouteJsEvent("onGetNotificationInfoFinished", 2618ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen browser_sync::JsArgList(return_args), sender); 261972a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen } else if (name == "getRootNode") { 262072a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen if (!parent_router_) { 262172a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen LogNoRouter(name, args); 262272a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen return; 262372a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen } 262472a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen ReadTransaction trans(GetUserShare()); 262572a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen ReadNode root(&trans); 262672a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen root.InitByRootLookup(); 262772a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen ListValue return_args; 262872a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen return_args.Append(root.ToValue()); 262972a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen parent_router_->RouteJsEvent( 263072a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen "onGetRootNodeFinished", 263172a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen browser_sync::JsArgList(return_args), sender); 263272a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen } else if (name == "getNodeById") { 263372a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen if (!parent_router_) { 263472a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen LogNoRouter(name, args); 263572a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen return; 263672a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen } 263772a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen parent_router_->RouteJsEvent( 263872a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen "onGetNodeByIdFinished", ProcessGetNodeByIdMessage(args), sender); 2639ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen } else if (name == "findNodesContainingString") { 2640ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen if (!parent_router_) { 2641ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen LogNoRouter(name, args); 2642ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen return; 2643ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen } 2644ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen parent_router_->RouteJsEvent( 2645ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen "onFindNodesContainingStringFinished", 2646ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen ProcessFindNodesContainingString(args), sender); 264772a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen } else { 264872a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen VLOG(1) << "Dropping unknown message " << name 264972a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen << " with args " << args.ToString(); 265072a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen } 265172a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen} 265272a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen 265372a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsenbrowser_sync::JsArgList SyncManager::SyncInternal::ProcessGetNodeByIdMessage( 265472a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen const browser_sync::JsArgList& args) { 265572a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen ListValue null_return_args_list; 265672a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen null_return_args_list.Append(Value::CreateNullValue()); 265772a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen browser_sync::JsArgList null_return_args(null_return_args_list); 265872a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen std::string id_str; 265972a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen if (!args.Get().GetString(0, &id_str)) { 266072a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen return null_return_args; 266172a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen } 266272a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen int64 id; 266372a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen if (!base::StringToInt64(id_str, &id)) { 266472a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen return null_return_args; 266572a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen } 266672a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen if (id == kInvalidId) { 266772a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen return null_return_args; 266872a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen } 266972a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen ReadTransaction trans(GetUserShare()); 267072a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen ReadNode node(&trans); 267172a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen if (!node.InitByIdLookup(id)) { 267272a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen return null_return_args; 267372a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen } 267472a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen ListValue return_args; 267572a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen return_args.Append(node.ToValue()); 267672a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen return browser_sync::JsArgList(return_args); 267772a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen} 267872a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen 2679ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsenbrowser_sync::JsArgList SyncManager::SyncInternal:: 2680ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen ProcessFindNodesContainingString( 2681ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen const browser_sync::JsArgList& args) { 2682ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen std::string query; 2683ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen ListValue return_args; 2684ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen if (!args.Get().GetString(0, &query)) { 2685ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen return_args.Append(new ListValue()); 2686ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen return browser_sync::JsArgList(return_args); 2687ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen } 2688ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen 2689ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen ListValue* result = FindNodesContainingString(query); 2690ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen return_args.Append(result); 2691ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen return browser_sync::JsArgList(return_args); 2692ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen} 2693ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen 2694c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdochvoid SyncManager::SyncInternal::OnNotificationStateChange( 2695c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch bool notifications_enabled) { 2696731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick VLOG(1) << "P2P: Notifications enabled = " 2697731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick << (notifications_enabled ? "true" : "false"); 2698c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch allstatus_.SetNotificationsEnabled(notifications_enabled); 2699c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch if (syncer_thread()) { 2700ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen syncer_thread()->set_notifications_enabled(notifications_enabled); 2701c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch } 270272a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen if (parent_router_) { 270372a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen ListValue args; 270472a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen args.Append(Value::CreateBooleanValue(notifications_enabled)); 270572a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen // TODO(akalin): Tidy up grammar in event names. 270672a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen parent_router_->RouteJsEvent("onSyncNotificationStateChange", 270772a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen browser_sync::JsArgList(args), NULL); 270872a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen } 2709c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch} 2710c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 2711ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsenvoid SyncManager::SyncInternal::UpdateNotificationInfo( 2712ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen const syncable::ModelTypePayloadMap& type_payloads) { 2713ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen for (syncable::ModelTypePayloadMap::const_iterator it = type_payloads.begin(); 2714ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen it != type_payloads.end(); ++it) { 2715ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen NotificationInfo* info = ¬ification_info_map_[it->first]; 2716ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen info->total_count++; 2717ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen info->payload = it->second; 2718ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen } 2719c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch} 2720c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 2721c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdochvoid SyncManager::SyncInternal::OnIncomingNotification( 2722ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen const syncable::ModelTypePayloadMap& type_payloads) { 2723ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen if (!type_payloads.empty()) { 27244a5e2dc747d50c653511c68ccb2cfbfb740bd5a7Ben Murdoch if (syncer_thread()) { 2725ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen syncer_thread()->ScheduleNudgeWithPayloads( 2726ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen TimeDelta::FromMilliseconds(kSyncerThreadDelayMsec), 2727ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen browser_sync::NUDGE_SOURCE_NOTIFICATION, 2728ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen type_payloads, FROM_HERE); 27294a5e2dc747d50c653511c68ccb2cfbfb740bd5a7Ben Murdoch } 27304a5e2dc747d50c653511c68ccb2cfbfb740bd5a7Ben Murdoch allstatus_.IncrementNotificationsReceived(); 2731ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen UpdateNotificationInfo(type_payloads); 27324a5e2dc747d50c653511c68ccb2cfbfb740bd5a7Ben Murdoch } else { 27334a5e2dc747d50c653511c68ccb2cfbfb740bd5a7Ben Murdoch LOG(WARNING) << "Sync received notification without any type information."; 27344a5e2dc747d50c653511c68ccb2cfbfb740bd5a7Ben Murdoch } 273572a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen 273672a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen if (parent_router_) { 273772a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen ListValue args; 273872a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen ListValue* changed_types = new ListValue(); 273972a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen args.Append(changed_types); 2740ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen for (syncable::ModelTypePayloadMap::const_iterator 2741ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen it = type_payloads.begin(); 2742ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen it != type_payloads.end(); ++it) { 274372a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen const std::string& model_type_str = 274472a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen syncable::ModelTypeToString(it->first); 274572a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen changed_types->Append(Value::CreateStringValue(model_type_str)); 274672a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen } 274772a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen parent_router_->RouteJsEvent("onSyncIncomingNotification", 274872a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen browser_sync::JsArgList(args), NULL); 274972a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen } 2750c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch} 2751c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 2752ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsenvoid SyncManager::SyncInternal::StoreState( 2753ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen const std::string& state) { 2754731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick syncable::ScopedDirLookup lookup(dir_manager(), username_for_share()); 2755731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick if (!lookup.good()) { 2756731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick LOG(ERROR) << "Could not write notification state"; 2757731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick // TODO(akalin): Propagate result callback all the way to this 2758731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick // function and call it with "false" to signal failure. 2759731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick return; 2760731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick } 2761731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick if (VLOG_IS_ON(1)) { 2762731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick std::string encoded_state; 2763731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick base::Base64Encode(state, &encoded_state); 2764731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick VLOG(1) << "Writing notification state: " << encoded_state; 2765731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick } 2766731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick lookup->SetNotificationState(state); 2767731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick lookup->SaveChanges(); 2768731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick} 2769731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick 277072a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsenvoid SyncManager::SyncInternal::AddObserver( 277172a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen SyncManager::Observer* observer) { 277272a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen observers_.AddObserver(observer); 277372a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen} 277472a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen 277572a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsenvoid SyncManager::SyncInternal::RemoveObserver( 277672a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen SyncManager::Observer* observer) { 277772a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen observers_.RemoveObserver(observer); 277872a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen} 277972a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen 2780c407dc5cd9bdc5668497f21b26b09d988ab439deBen MurdochSyncManager::Status::Summary SyncManager::GetStatusSummary() const { 278172a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen return data_->GetStatus().summary; 2782c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch} 2783c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 2784c407dc5cd9bdc5668497f21b26b09d988ab439deBen MurdochSyncManager::Status SyncManager::GetDetailedStatus() const { 278572a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen return data_->GetStatus(); 2786c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch} 2787c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 2788c407dc5cd9bdc5668497f21b26b09d988ab439deBen MurdochSyncManager::SyncInternal* SyncManager::GetImpl() const { return data_; } 2789c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 2790c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdochvoid SyncManager::SaveChanges() { 2791c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch data_->SaveChanges(); 2792c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch} 2793c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 2794c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdochvoid SyncManager::SyncInternal::SaveChanges() { 2795c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch syncable::ScopedDirLookup lookup(dir_manager(), username_for_share()); 2796c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch if (!lookup.good()) { 2797c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch DCHECK(false) << "ScopedDirLookup creation failed; Unable to SaveChanges"; 2798c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch return; 2799c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch } 2800c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch lookup->SaveChanges(); 2801c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch} 2802c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 2803c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch////////////////////////////////////////////////////////////////////////// 2804c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch// BaseTransaction member definitions 2805c407dc5cd9bdc5668497f21b26b09d988ab439deBen MurdochBaseTransaction::BaseTransaction(UserShare* share) 2806c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch : lookup_(NULL) { 2807c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch DCHECK(share && share->dir_manager.get()); 2808c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch lookup_ = new syncable::ScopedDirLookup(share->dir_manager.get(), 28093345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick share->name); 2810ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen cryptographer_ = share->dir_manager->GetCryptographer(this); 2811c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch if (!(lookup_->good())) 2812c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch DCHECK(false) << "ScopedDirLookup failed on valid DirManager."; 2813c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch} 2814c407dc5cd9bdc5668497f21b26b09d988ab439deBen MurdochBaseTransaction::~BaseTransaction() { 2815c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch delete lookup_; 2816c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch} 2817c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 2818c407dc5cd9bdc5668497f21b26b09d988ab439deBen MurdochUserShare* SyncManager::GetUserShare() const { 2819c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch DCHECK(data_->initialized()) << "GetUserShare requires initialization!"; 2820c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch return data_->GetUserShare(); 2821c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch} 2822c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 28233345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrickbool SyncManager::HasUnsyncedItems() const { 28243345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick sync_api::ReadTransaction trans(GetUserShare()); 28253345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick return (trans.GetWrappedTrans()->directory()->unsynced_entity_count() != 0); 28263345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick} 28273345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick 282872a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsenvoid SyncManager::TriggerOnNotificationStateChangeForTest( 282972a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen bool notifications_enabled) { 283072a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen data_->OnNotificationStateChange(notifications_enabled); 283172a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen} 283272a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen 283372a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsenvoid SyncManager::TriggerOnIncomingNotificationForTest( 283472a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen const syncable::ModelTypeBitSet& model_types) { 2835ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen syncable::ModelTypePayloadMap model_types_with_payloads = 2836ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen syncable::ModelTypePayloadMapFromBitSet(model_types, 2837ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen std::string()); 2838ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen 2839ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen data_->OnIncomingNotification(model_types_with_payloads); 284072a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen} 284172a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen 2842c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch} // namespace sync_api 2843