OLD | NEW |
| (Empty) |
1 // Copyright (c) 2011 The Chromium Authors. All rights reserved. | |
2 // Use of this source code is governed by a BSD-style license that can be | |
3 // found in the LICENSE file. | |
4 | |
5 #include "chrome/browser/sync/syncable/nigori_util.h" | |
6 | |
7 #include <queue> | |
8 #include <string> | |
9 #include <vector> | |
10 | |
11 #include "chrome/browser/sync/engine/syncapi.h" | |
12 #include "chrome/browser/sync/engine/syncer_util.h" | |
13 #include "chrome/browser/sync/syncable/syncable.h" | |
14 #include "chrome/browser/sync/util/cryptographer.h" | |
15 | |
16 namespace syncable { | |
17 void FillNigoriEncryptedTypes(const ModelTypeSet& types, | |
18 sync_pb::NigoriSpecifics* nigori) { | |
19 DCHECK(nigori); | |
20 nigori->set_encrypt_bookmarks(types.count(BOOKMARKS) > 0); | |
21 nigori->set_encrypt_preferences(types.count(PREFERENCES) > 0); | |
22 nigori->set_encrypt_autofill_profile(types.count(AUTOFILL_PROFILE) > 0); | |
23 nigori->set_encrypt_autofill(types.count(AUTOFILL) > 0); | |
24 nigori->set_encrypt_themes(types.count(THEMES) > 0); | |
25 nigori->set_encrypt_typed_urls(types.count(TYPED_URLS) > 0); | |
26 nigori->set_encrypt_extensions(types.count(EXTENSIONS) > 0); | |
27 nigori->set_encrypt_search_engines(types.count(SEARCH_ENGINES) > 0); | |
28 nigori->set_encrypt_sessions(types.count(SESSIONS) > 0); | |
29 nigori->set_encrypt_apps(types.count(APPS) > 0); | |
30 } | |
31 | |
32 bool ProcessUnsyncedChangesForEncryption( | |
33 WriteTransaction* const trans, | |
34 browser_sync::Cryptographer* cryptographer) { | |
35 DCHECK(cryptographer->is_ready()); | |
36 syncable::ModelTypeSet encrypted_types = cryptographer->GetEncryptedTypes(); | |
37 | |
38 // Get list of all datatypes with unsynced changes. It's possible that our | |
39 // local changes need to be encrypted if encryption for that datatype was | |
40 // just turned on (and vice versa). This should never affect passwords. | |
41 std::vector<int64> handles; | |
42 browser_sync::SyncerUtil::GetUnsyncedEntries(trans, &handles); | |
43 for (size_t i = 0; i < handles.size(); ++i) { | |
44 MutableEntry entry(trans, GET_BY_HANDLE, handles[i]); | |
45 if (!sync_api::WriteNode::UpdateEntryWithEncryption(cryptographer, | |
46 entry.Get(SPECIFICS), | |
47 &entry)) { | |
48 NOTREACHED(); | |
49 return false; | |
50 } | |
51 } | |
52 return true; | |
53 } | |
54 | |
55 bool VerifyUnsyncedChangesAreEncrypted( | |
56 BaseTransaction* const trans, | |
57 const ModelTypeSet& encrypted_types) { | |
58 std::vector<int64> handles; | |
59 browser_sync::SyncerUtil::GetUnsyncedEntries(trans, &handles); | |
60 for (size_t i = 0; i < handles.size(); ++i) { | |
61 Entry entry(trans, GET_BY_HANDLE, handles[i]); | |
62 if (!entry.good()) { | |
63 NOTREACHED(); | |
64 return false; | |
65 } | |
66 const sync_pb::EntitySpecifics& entry_specifics = entry.Get(SPECIFICS); | |
67 ModelType type = entry.GetModelType(); | |
68 if (type == PASSWORDS) | |
69 continue; | |
70 if (encrypted_types.count(type) > 0 && | |
71 !entry_specifics.has_encrypted()) { | |
72 // This datatype requires encryption but this data is not encrypted. | |
73 return false; | |
74 } | |
75 } | |
76 return true; | |
77 } | |
78 | |
79 // Mainly for testing. | |
80 bool VerifyDataTypeEncryption(BaseTransaction* const trans, | |
81 browser_sync::Cryptographer* cryptographer, | |
82 ModelType type, | |
83 bool is_encrypted) { | |
84 if (type == PASSWORDS || type == NIGORI) { | |
85 NOTREACHED(); | |
86 return true; | |
87 } | |
88 std::string type_tag = ModelTypeToRootTag(type); | |
89 Entry type_root(trans, GET_BY_SERVER_TAG, type_tag); | |
90 if (!type_root.good()) { | |
91 NOTREACHED(); | |
92 return false; | |
93 } | |
94 | |
95 std::queue<Id> to_visit; | |
96 Id id_string = | |
97 trans->directory()->GetFirstChildId(trans, type_root.Get(ID)); | |
98 to_visit.push(id_string); | |
99 while (!to_visit.empty()) { | |
100 id_string = to_visit.front(); | |
101 to_visit.pop(); | |
102 if (id_string.IsRoot()) | |
103 continue; | |
104 | |
105 Entry child(trans, GET_BY_ID, id_string); | |
106 if (!child.good()) { | |
107 NOTREACHED(); | |
108 return false; | |
109 } | |
110 if (child.Get(IS_DIR)) { | |
111 // Traverse the children. | |
112 to_visit.push( | |
113 trans->directory()->GetFirstChildId(trans, child.Get(ID))); | |
114 } | |
115 const sync_pb::EntitySpecifics& specifics = child.Get(SPECIFICS); | |
116 DCHECK_EQ(type, child.GetModelType()); | |
117 DCHECK_EQ(type, GetModelTypeFromSpecifics(specifics)); | |
118 // We don't encrypt the server's permanent items. | |
119 if (child.Get(UNIQUE_SERVER_TAG).empty()) { | |
120 if (specifics.has_encrypted() != is_encrypted) | |
121 return false; | |
122 if (specifics.has_encrypted()) { | |
123 if (child.Get(NON_UNIQUE_NAME) != kEncryptedString) | |
124 return false; | |
125 if (!cryptographer->CanDecryptUsingDefaultKey(specifics.encrypted())) | |
126 return false; | |
127 } | |
128 } | |
129 // Push the successor. | |
130 to_visit.push(child.Get(NEXT_ID)); | |
131 } | |
132 return true; | |
133 } | |
134 | |
135 } // namespace syncable | |
OLD | NEW |