OLD | NEW |
1 // Copyright (c) 2012 The Chromium Authors. All rights reserved. | 1 // Copyright (c) 2012 The Chromium Authors. All rights reserved. |
2 // Use of this source code is governed by a BSD-style license that can be | 2 // Use of this source code is governed by a BSD-style license that can be |
3 // found in the LICENSE file. | 3 // found in the LICENSE file. |
4 | 4 |
5 #include "chrome/browser/chromeos/drive/file_system_util.h" | 5 #include "chrome/browser/chromeos/drive/file_system_util.h" |
6 | 6 |
7 #include <string> | 7 #include <string> |
8 #include <vector> | 8 #include <vector> |
9 | 9 |
10 #include "base/basictypes.h" | 10 #include "base/basictypes.h" |
11 #include "base/bind.h" | 11 #include "base/bind.h" |
12 #include "base/bind_helpers.h" | 12 #include "base/bind_helpers.h" |
13 #include "base/files/file_path.h" | 13 #include "base/files/file_path.h" |
14 #include "base/files/file_util.h" | 14 #include "base/files/file_util.h" |
15 #include "base/i18n/icu_string_conversions.h" | 15 #include "base/i18n/icu_string_conversions.h" |
16 #include "base/json/json_file_value_serializer.h" | 16 #include "base/json/json_file_value_serializer.h" |
17 #include "base/logging.h" | 17 #include "base/logging.h" |
18 #include "base/memory/scoped_ptr.h" | 18 #include "base/memory/scoped_ptr.h" |
19 #include "base/prefs/pref_service.h" | 19 #include "base/prefs/pref_service.h" |
20 #include "base/strings/string_number_conversions.h" | 20 #include "base/strings/string_number_conversions.h" |
21 #include "base/strings/string_util.h" | 21 #include "base/strings/string_util.h" |
22 #include "base/strings/stringprintf.h" | 22 #include "base/strings/stringprintf.h" |
23 #include "base/thread_task_runner_handle.h" | 23 #include "base/thread_task_runner_handle.h" |
24 #include "base/threading/sequenced_worker_pool.h" | 24 #include "base/threading/sequenced_worker_pool.h" |
25 #include "chrome/browser/browser_process.h" | 25 #include "chrome/browser/browser_process.h" |
26 #include "chrome/browser/chromeos/drive/drive.pb.h" | 26 #include "chrome/browser/chromeos/drive/drive.pb.h" |
27 #include "chrome/browser/chromeos/drive/drive_integration_service.h" | 27 #include "chrome/browser/chromeos/drive/drive_integration_service.h" |
28 #include "chrome/browser/chromeos/drive/drive_pref_names.h" | 28 #include "chrome/browser/chromeos/drive/drive_pref_names.h" |
| 29 #include "chrome/browser/chromeos/drive/file_system_core_util.h" |
29 #include "chrome/browser/chromeos/drive/file_system_interface.h" | 30 #include "chrome/browser/chromeos/drive/file_system_interface.h" |
30 #include "chrome/browser/chromeos/drive/job_list.h" | 31 #include "chrome/browser/chromeos/drive/job_list.h" |
31 #include "chrome/browser/chromeos/drive/write_on_cache_file.h" | 32 #include "chrome/browser/chromeos/drive/write_on_cache_file.h" |
32 #include "chrome/browser/chromeos/profiles/profile_helper.h" | 33 #include "chrome/browser/chromeos/profiles/profile_helper.h" |
33 #include "chrome/browser/chromeos/profiles/profile_util.h" | 34 #include "chrome/browser/chromeos/profiles/profile_util.h" |
34 #include "chrome/browser/profiles/profile.h" | 35 #include "chrome/browser/profiles/profile.h" |
35 #include "chrome/browser/profiles/profile_manager.h" | 36 #include "chrome/browser/profiles/profile_manager.h" |
36 #include "chrome/common/chrome_constants.h" | 37 #include "chrome/common/chrome_constants.h" |
37 #include "chrome/common/chrome_paths_internal.h" | 38 #include "chrome/common/chrome_paths_internal.h" |
38 #include "chrome/common/pref_names.h" | |
39 #include "chromeos/chromeos_constants.h" | 39 #include "chromeos/chromeos_constants.h" |
40 #include "components/user_manager/user_manager.h" | 40 #include "components/user_manager/user_manager.h" |
41 #include "content/public/browser/browser_thread.h" | 41 #include "content/public/browser/browser_thread.h" |
42 #include "net/base/escape.h" | |
43 #include "storage/browser/fileapi/file_system_url.h" | 42 #include "storage/browser/fileapi/file_system_url.h" |
44 | 43 |
45 using content::BrowserThread; | 44 using content::BrowserThread; |
46 | 45 |
47 namespace drive { | 46 namespace drive { |
48 namespace util { | 47 namespace util { |
49 | 48 |
50 namespace { | 49 namespace { |
51 | 50 |
52 std::string ReadStringFromGDocFile(const base::FilePath& file_path, | |
53 const std::string& key) { | |
54 const int64 kMaxGDocSize = 4096; | |
55 int64 file_size = 0; | |
56 if (!base::GetFileSize(file_path, &file_size) || | |
57 file_size > kMaxGDocSize) { | |
58 LOG(WARNING) << "File too large to be a GDoc file " << file_path.value(); | |
59 return std::string(); | |
60 } | |
61 | |
62 JSONFileValueDeserializer reader(file_path); | |
63 std::string error_message; | |
64 scoped_ptr<base::Value> root_value(reader.Deserialize(NULL, &error_message)); | |
65 if (!root_value) { | |
66 LOG(WARNING) << "Failed to parse " << file_path.value() << " as JSON." | |
67 << " error = " << error_message; | |
68 return std::string(); | |
69 } | |
70 | |
71 base::DictionaryValue* dictionary_value = NULL; | |
72 std::string result; | |
73 if (!root_value->GetAsDictionary(&dictionary_value) || | |
74 !dictionary_value->GetString(key, &result)) { | |
75 LOG(WARNING) << "No value for the given key is stored in " | |
76 << file_path.value() << ". key = " << key; | |
77 return std::string(); | |
78 } | |
79 | |
80 return result; | |
81 } | |
82 | |
83 // Returns DriveIntegrationService instance, if Drive is enabled. | 51 // Returns DriveIntegrationService instance, if Drive is enabled. |
84 // Otherwise, NULL. | 52 // Otherwise, NULL. |
85 DriveIntegrationService* GetIntegrationServiceByProfile(Profile* profile) { | 53 DriveIntegrationService* GetIntegrationServiceByProfile(Profile* profile) { |
86 DriveIntegrationService* service = | 54 DriveIntegrationService* service = |
87 DriveIntegrationServiceFactory::FindForProfile(profile); | 55 DriveIntegrationServiceFactory::FindForProfile(profile); |
88 if (!service || !service->IsMounted()) | 56 if (!service || !service->IsMounted()) |
89 return NULL; | 57 return NULL; |
90 return service; | 58 return service; |
91 } | 59 } |
92 | 60 |
93 } // namespace | 61 } // namespace |
94 | 62 |
95 const base::FilePath& GetDriveGrandRootPath() { | |
96 CR_DEFINE_STATIC_LOCAL( | |
97 base::FilePath, grand_root_path, | |
98 (base::FilePath::FromUTF8Unsafe(kDriveGrandRootDirName))); | |
99 return grand_root_path; | |
100 } | |
101 | |
102 const base::FilePath& GetDriveMyDriveRootPath() { | |
103 CR_DEFINE_STATIC_LOCAL( | |
104 base::FilePath, drive_root_path, | |
105 (GetDriveGrandRootPath().AppendASCII(kDriveMyDriveRootDirName))); | |
106 return drive_root_path; | |
107 } | |
108 | |
109 base::FilePath GetDriveMountPointPathForUserIdHash( | |
110 const std::string user_id_hash) { | |
111 static const base::FilePath::CharType kSpecialMountPointRoot[] = | |
112 FILE_PATH_LITERAL("/special"); | |
113 static const char kDriveMountPointNameBase[] = "drive"; | |
114 return base::FilePath(kSpecialMountPointRoot).AppendASCII( | |
115 net::EscapeQueryParamValue( | |
116 kDriveMountPointNameBase + | |
117 (user_id_hash.empty() ? "" : "-" + user_id_hash), false)); | |
118 } | |
119 | |
120 base::FilePath GetDriveMountPointPath(Profile* profile) { | 63 base::FilePath GetDriveMountPointPath(Profile* profile) { |
121 std::string id = chromeos::ProfileHelper::GetUserIdHashFromProfile(profile); | 64 std::string id = chromeos::ProfileHelper::GetUserIdHashFromProfile(profile); |
122 if (id.empty() || id == chrome::kLegacyProfileDir) { | 65 if (id.empty() || id == chrome::kLegacyProfileDir) { |
123 // ProfileHelper::GetUserIdHashFromProfile works only when multi-profile is | 66 // ProfileHelper::GetUserIdHashFromProfile works only when multi-profile is |
124 // enabled. In that case, we fall back to use UserManager (it basically just | 67 // enabled. In that case, we fall back to use UserManager (it basically just |
125 // returns currently active users's hash in such a case.) I still try | 68 // returns currently active users's hash in such a case.) I still try |
126 // ProfileHelper first because it works better in tests. | 69 // ProfileHelper first because it works better in tests. |
127 const user_manager::User* const user = | 70 const user_manager::User* const user = |
128 user_manager::UserManager::IsInitialized() | 71 user_manager::UserManager::IsInitialized() |
129 ? chromeos::ProfileHelper::Get()->GetUserByProfile( | 72 ? chromeos::ProfileHelper::Get()->GetUserByProfile( |
(...skipping 22 matching lines...) Expand all Loading... |
152 if (!g_browser_process->profile_manager()->IsValidProfile(profile)) | 95 if (!g_browser_process->profile_manager()->IsValidProfile(profile)) |
153 return NULL; | 96 return NULL; |
154 return GetFileSystemByProfile(profile); | 97 return GetFileSystemByProfile(profile); |
155 } | 98 } |
156 | 99 |
157 DriveAppRegistry* GetDriveAppRegistryByProfile(Profile* profile) { | 100 DriveAppRegistry* GetDriveAppRegistryByProfile(Profile* profile) { |
158 DCHECK_CURRENTLY_ON(BrowserThread::UI); | 101 DCHECK_CURRENTLY_ON(BrowserThread::UI); |
159 | 102 |
160 DriveIntegrationService* integration_service = | 103 DriveIntegrationService* integration_service = |
161 GetIntegrationServiceByProfile(profile); | 104 GetIntegrationServiceByProfile(profile); |
162 return integration_service ? | 105 return integration_service ? integration_service->drive_app_registry() : NULL; |
163 integration_service->drive_app_registry() : | |
164 NULL; | |
165 } | 106 } |
166 | 107 |
167 DriveServiceInterface* GetDriveServiceByProfile(Profile* profile) { | 108 DriveServiceInterface* GetDriveServiceByProfile(Profile* profile) { |
168 DCHECK_CURRENTLY_ON(BrowserThread::UI); | 109 DCHECK_CURRENTLY_ON(BrowserThread::UI); |
169 | 110 |
170 DriveIntegrationService* integration_service = | 111 DriveIntegrationService* integration_service = |
171 GetIntegrationServiceByProfile(profile); | 112 GetIntegrationServiceByProfile(profile); |
172 return integration_service ? integration_service->drive_service() : NULL; | 113 return integration_service ? integration_service->drive_service() : NULL; |
173 } | 114 } |
174 | 115 |
175 bool IsUnderDriveMountPoint(const base::FilePath& path) { | |
176 return !ExtractDrivePath(path).empty(); | |
177 } | |
178 | |
179 base::FilePath ExtractDrivePath(const base::FilePath& path) { | |
180 std::vector<base::FilePath::StringType> components; | |
181 path.GetComponents(&components); | |
182 if (components.size() < 3) | |
183 return base::FilePath(); | |
184 if (components[0] != FILE_PATH_LITERAL("/")) | |
185 return base::FilePath(); | |
186 if (components[1] != FILE_PATH_LITERAL("special")) | |
187 return base::FilePath(); | |
188 static const base::FilePath::CharType kPrefix[] = FILE_PATH_LITERAL("drive"); | |
189 if (components[2].compare(0, arraysize(kPrefix) - 1, kPrefix) != 0) | |
190 return base::FilePath(); | |
191 | |
192 base::FilePath drive_path = GetDriveGrandRootPath(); | |
193 for (size_t i = 3; i < components.size(); ++i) | |
194 drive_path = drive_path.Append(components[i]); | |
195 return drive_path; | |
196 } | |
197 | |
198 Profile* ExtractProfileFromPath(const base::FilePath& path) { | 116 Profile* ExtractProfileFromPath(const base::FilePath& path) { |
199 DCHECK_CURRENTLY_ON(BrowserThread::UI); | 117 DCHECK_CURRENTLY_ON(BrowserThread::UI); |
200 | 118 |
201 const std::vector<Profile*>& profiles = | 119 const std::vector<Profile*>& profiles = |
202 g_browser_process->profile_manager()->GetLoadedProfiles(); | 120 g_browser_process->profile_manager()->GetLoadedProfiles(); |
203 for (size_t i = 0; i < profiles.size(); ++i) { | 121 for (size_t i = 0; i < profiles.size(); ++i) { |
204 Profile* original_profile = profiles[i]->GetOriginalProfile(); | 122 Profile* original_profile = profiles[i]->GetOriginalProfile(); |
205 if (original_profile == profiles[i] && | 123 if (original_profile == profiles[i] && |
206 !chromeos::ProfileHelper::IsSigninProfile(original_profile)) { | 124 !chromeos::ProfileHelper::IsSigninProfile(original_profile)) { |
207 const base::FilePath base = GetDriveMountPointPath(original_profile); | 125 const base::FilePath base = GetDriveMountPointPath(original_profile); |
(...skipping 14 matching lines...) Expand all Loading... |
222 base::FilePath GetCacheRootPath(Profile* profile) { | 140 base::FilePath GetCacheRootPath(Profile* profile) { |
223 base::FilePath cache_base_path; | 141 base::FilePath cache_base_path; |
224 chrome::GetUserCacheDirectory(profile->GetPath(), &cache_base_path); | 142 chrome::GetUserCacheDirectory(profile->GetPath(), &cache_base_path); |
225 base::FilePath cache_root_path = | 143 base::FilePath cache_root_path = |
226 cache_base_path.Append(chromeos::kDriveCacheDirname); | 144 cache_base_path.Append(chromeos::kDriveCacheDirname); |
227 static const base::FilePath::CharType kFileCacheVersionDir[] = | 145 static const base::FilePath::CharType kFileCacheVersionDir[] = |
228 FILE_PATH_LITERAL("v1"); | 146 FILE_PATH_LITERAL("v1"); |
229 return cache_root_path.Append(kFileCacheVersionDir); | 147 return cache_root_path.Append(kFileCacheVersionDir); |
230 } | 148 } |
231 | 149 |
232 std::string EscapeCacheFileName(const std::string& filename) { | |
233 // This is based on net/base/escape.cc: net::(anonymous namespace)::Escape | |
234 std::string escaped; | |
235 for (size_t i = 0; i < filename.size(); ++i) { | |
236 char c = filename[i]; | |
237 if (c == '%' || c == '.' || c == '/') { | |
238 base::StringAppendF(&escaped, "%%%02X", c); | |
239 } else { | |
240 escaped.push_back(c); | |
241 } | |
242 } | |
243 return escaped; | |
244 } | |
245 | |
246 std::string UnescapeCacheFileName(const std::string& filename) { | |
247 std::string unescaped; | |
248 for (size_t i = 0; i < filename.size(); ++i) { | |
249 char c = filename[i]; | |
250 if (c == '%' && i + 2 < filename.length()) { | |
251 c = (base::HexDigitToInt(filename[i + 1]) << 4) + | |
252 base::HexDigitToInt(filename[i + 2]); | |
253 i += 2; | |
254 } | |
255 unescaped.push_back(c); | |
256 } | |
257 return unescaped; | |
258 } | |
259 | |
260 std::string NormalizeFileName(const std::string& input) { | |
261 DCHECK(base::IsStringUTF8(input)); | |
262 | |
263 std::string output; | |
264 if (!base::ConvertToUtf8AndNormalize(input, base::kCodepageUTF8, &output)) | |
265 output = input; | |
266 base::ReplaceChars(output, "/", "_", &output); | |
267 if (!output.empty() && output.find_first_not_of('.', 0) == std::string::npos) | |
268 output = "_"; | |
269 return output; | |
270 } | |
271 | |
272 void PrepareWritableFileAndRun(Profile* profile, | 150 void PrepareWritableFileAndRun(Profile* profile, |
273 const base::FilePath& path, | 151 const base::FilePath& path, |
274 const PrepareWritableFileCallback& callback) { | 152 const PrepareWritableFileCallback& callback) { |
275 DCHECK_CURRENTLY_ON(BrowserThread::UI); | 153 DCHECK_CURRENTLY_ON(BrowserThread::UI); |
276 DCHECK(!callback.is_null()); | 154 DCHECK(!callback.is_null()); |
277 | 155 |
278 FileSystemInterface* file_system = GetFileSystemByProfile(profile); | 156 FileSystemInterface* file_system = GetFileSystemByProfile(profile); |
279 if (!file_system || !IsUnderDriveMountPoint(path)) { | 157 if (!file_system || !IsUnderDriveMountPoint(path)) { |
280 content::BrowserThread::GetBlockingPool()->PostTask( | 158 content::BrowserThread::GetBlockingPool()->PostTask( |
281 FROM_HERE, base::Bind(callback, FILE_ERROR_FAILED, base::FilePath())); | 159 FROM_HERE, base::Bind(callback, FILE_ERROR_FAILED, base::FilePath())); |
282 return; | 160 return; |
283 } | 161 } |
284 | 162 |
285 WriteOnCacheFile(file_system, | 163 WriteOnCacheFile(file_system, ExtractDrivePath(path), |
286 ExtractDrivePath(path), | |
287 std::string(), // mime_type | 164 std::string(), // mime_type |
288 callback); | 165 callback); |
289 } | 166 } |
290 | 167 |
291 void EnsureDirectoryExists(Profile* profile, | 168 void EnsureDirectoryExists(Profile* profile, |
292 const base::FilePath& directory, | 169 const base::FilePath& directory, |
293 const FileOperationCallback& callback) { | 170 const FileOperationCallback& callback) { |
294 DCHECK_CURRENTLY_ON(BrowserThread::UI); | 171 DCHECK_CURRENTLY_ON(BrowserThread::UI); |
295 DCHECK(!callback.is_null()); | 172 DCHECK(!callback.is_null()); |
296 if (IsUnderDriveMountPoint(directory)) { | 173 if (IsUnderDriveMountPoint(directory)) { |
297 FileSystemInterface* file_system = GetFileSystemByProfile(profile); | 174 FileSystemInterface* file_system = GetFileSystemByProfile(profile); |
298 DCHECK(file_system); | 175 DCHECK(file_system); |
299 file_system->CreateDirectory( | 176 file_system->CreateDirectory(ExtractDrivePath(directory), |
300 ExtractDrivePath(directory), | 177 true /* is_exclusive */, |
301 true /* is_exclusive */, | 178 true /* is_recursive */, callback); |
302 true /* is_recursive */, | |
303 callback); | |
304 } else { | 179 } else { |
305 base::ThreadTaskRunnerHandle::Get()->PostTask( | 180 base::ThreadTaskRunnerHandle::Get()->PostTask( |
306 FROM_HERE, base::Bind(callback, FILE_ERROR_OK)); | 181 FROM_HERE, base::Bind(callback, FILE_ERROR_OK)); |
307 } | 182 } |
308 } | 183 } |
309 | 184 |
310 void EmptyFileOperationCallback(FileError error) { | |
311 } | |
312 | |
313 bool CreateGDocFile(const base::FilePath& file_path, | |
314 const GURL& url, | |
315 const std::string& resource_id) { | |
316 std::string content = base::StringPrintf( | |
317 "{\"url\": \"%s\", \"resource_id\": \"%s\"}", | |
318 url.spec().c_str(), resource_id.c_str()); | |
319 return base::WriteFile(file_path, content.data(), content.size()) == | |
320 static_cast<int>(content.size()); | |
321 } | |
322 | |
323 GURL ReadUrlFromGDocFile(const base::FilePath& file_path) { | |
324 return GURL(ReadStringFromGDocFile(file_path, "url")); | |
325 } | |
326 | |
327 std::string ReadResourceIdFromGDocFile(const base::FilePath& file_path) { | |
328 return ReadStringFromGDocFile(file_path, "resource_id"); | |
329 } | |
330 | |
331 bool IsDriveEnabledForProfile(Profile* profile) { | 185 bool IsDriveEnabledForProfile(Profile* profile) { |
332 DCHECK_CURRENTLY_ON(BrowserThread::UI); | 186 DCHECK_CURRENTLY_ON(BrowserThread::UI); |
333 | 187 |
334 if (!chromeos::IsProfileAssociatedWithGaiaAccount(profile)) | 188 if (!chromeos::IsProfileAssociatedWithGaiaAccount(profile)) |
335 return false; | 189 return false; |
336 | 190 |
337 // Disable Drive if preference is set. This can happen with commandline flag | 191 // Disable Drive if preference is set. This can happen with commandline flag |
338 // --disable-drive or enterprise policy, or with user settings. | 192 // --disable-drive or enterprise policy, or with user settings. |
339 if (profile->GetPrefs()->GetBoolean(prefs::kDisableDrive)) | 193 if (profile->GetPrefs()->GetBoolean(prefs::kDisableDrive)) |
340 return false; | 194 return false; |
(...skipping 18 matching lines...) Expand all Loading... |
359 const bool disable_sync_over_celluar = | 213 const bool disable_sync_over_celluar = |
360 profile->GetPrefs()->GetBoolean(prefs::kDisableDriveOverCellular); | 214 profile->GetPrefs()->GetBoolean(prefs::kDisableDriveOverCellular); |
361 | 215 |
362 if (is_connection_cellular && disable_sync_over_celluar) | 216 if (is_connection_cellular && disable_sync_over_celluar) |
363 return DRIVE_CONNECTED_METERED; | 217 return DRIVE_CONNECTED_METERED; |
364 return DRIVE_CONNECTED; | 218 return DRIVE_CONNECTED; |
365 } | 219 } |
366 | 220 |
367 } // namespace util | 221 } // namespace util |
368 } // namespace drive | 222 } // namespace drive |
OLD | NEW |