| 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/sync_client.h" | 5 #include "chrome/browser/chromeos/drive/sync_client.h" |
| 6 | 6 |
| 7 #include <vector> | 7 #include <vector> |
| 8 | 8 |
| 9 #include "base/bind.h" | 9 #include "base/bind.h" |
| 10 #include "base/message_loop/message_loop_proxy.h" | 10 #include "base/message_loop/message_loop_proxy.h" |
| 11 #include "chrome/browser/chromeos/drive/drive.pb.h" | 11 #include "chrome/browser/chromeos/drive/drive.pb.h" |
| 12 #include "chrome/browser/chromeos/drive/file_cache.h" | 12 #include "chrome/browser/chromeos/drive/file_cache.h" |
| 13 #include "chrome/browser/chromeos/drive/file_system/download_operation.h" | 13 #include "chrome/browser/chromeos/drive/file_system/download_operation.h" |
| 14 #include "chrome/browser/chromeos/drive/file_system/operation_observer.h" | 14 #include "chrome/browser/chromeos/drive/file_system/operation_observer.h" |
| 15 #include "chrome/browser/chromeos/drive/file_system_util.h" | 15 #include "chrome/browser/chromeos/drive/file_system_util.h" |
| 16 #include "chrome/browser/chromeos/drive/sync/content_update_performer.h" | |
| 17 #include "chrome/browser/chromeos/drive/sync/entry_update_performer.h" | 16 #include "chrome/browser/chromeos/drive/sync/entry_update_performer.h" |
| 18 #include "content/public/browser/browser_thread.h" | 17 #include "content/public/browser/browser_thread.h" |
| 19 #include "google_apis/drive/task_util.h" | 18 #include "google_apis/drive/task_util.h" |
| 20 | 19 |
| 21 using content::BrowserThread; | 20 using content::BrowserThread; |
| 22 | 21 |
| 23 namespace drive { | 22 namespace drive { |
| 24 namespace internal { | 23 namespace internal { |
| 25 | 24 |
| 26 namespace { | 25 namespace { |
| (...skipping 11 matching lines...) Expand all Loading... |
| 38 // may edit the same file repeatedly in a short period of time. | 37 // may edit the same file repeatedly in a short period of time. |
| 39 // | 38 // |
| 40 // TODO(satorux): We should find a way to handle the upload case more nicely, | 39 // TODO(satorux): We should find a way to handle the upload case more nicely, |
| 41 // and shorten the delay. crbug.com/134774 | 40 // and shorten the delay. crbug.com/134774 |
| 42 const int kDelaySeconds = 5; | 41 const int kDelaySeconds = 5; |
| 43 | 42 |
| 44 // The delay constant is used to delay retrying a sync task on server errors. | 43 // The delay constant is used to delay retrying a sync task on server errors. |
| 45 const int kLongDelaySeconds = 600; | 44 const int kLongDelaySeconds = 600; |
| 46 | 45 |
| 47 // Iterates entries and appends IDs to |to_fetch| if the file is pinned but not | 46 // Iterates entries and appends IDs to |to_fetch| if the file is pinned but not |
| 48 // fetched (not present locally), to |to_upload| if the file is dirty but not | 47 // fetched (not present locally), to |to_update| if the file needs update. |
| 49 // uploaded, or to |to_remove| if the entry is in the trash. | |
| 50 void CollectBacklog(ResourceMetadata* metadata, | 48 void CollectBacklog(ResourceMetadata* metadata, |
| 51 std::vector<std::string>* to_fetch, | 49 std::vector<std::string>* to_fetch, |
| 52 std::vector<std::string>* to_upload, | |
| 53 std::vector<std::string>* to_update) { | 50 std::vector<std::string>* to_update) { |
| 54 DCHECK(to_fetch); | 51 DCHECK(to_fetch); |
| 55 DCHECK(to_upload); | |
| 56 DCHECK(to_update); | 52 DCHECK(to_update); |
| 57 | 53 |
| 58 scoped_ptr<ResourceMetadata::Iterator> it = metadata->GetIterator(); | 54 scoped_ptr<ResourceMetadata::Iterator> it = metadata->GetIterator(); |
| 59 for (; !it->IsAtEnd(); it->Advance()) { | 55 for (; !it->IsAtEnd(); it->Advance()) { |
| 60 const std::string& local_id = it->GetID(); | 56 const std::string& local_id = it->GetID(); |
| 61 const ResourceEntry& entry = it->GetValue(); | 57 const ResourceEntry& entry = it->GetValue(); |
| 62 if (entry.parent_local_id() == util::kDriveTrashDirLocalId) { | 58 if (entry.parent_local_id() == util::kDriveTrashDirLocalId) { |
| 63 to_update->push_back(local_id); | 59 to_update->push_back(local_id); |
| 64 continue; | 60 continue; |
| 65 } | 61 } |
| 66 | 62 |
| 63 bool should_update = false; |
| 67 switch (entry.metadata_edit_state()) { | 64 switch (entry.metadata_edit_state()) { |
| 68 case ResourceEntry::CLEAN: | 65 case ResourceEntry::CLEAN: |
| 69 break; | 66 break; |
| 70 case ResourceEntry::SYNCING: | 67 case ResourceEntry::SYNCING: |
| 71 case ResourceEntry::DIRTY: | 68 case ResourceEntry::DIRTY: |
| 72 to_update->push_back(local_id); | 69 should_update = true; |
| 73 break; | 70 break; |
| 74 } | 71 } |
| 75 | 72 |
| 76 FileCacheEntry cache_entry; | 73 FileCacheEntry cache_entry; |
| 77 if (it->GetCacheEntry(&cache_entry)) { | 74 if (it->GetCacheEntry(&cache_entry)) { |
| 78 if (cache_entry.is_pinned() && !cache_entry.is_present()) | 75 if (cache_entry.is_pinned() && !cache_entry.is_present()) |
| 79 to_fetch->push_back(local_id); | 76 to_fetch->push_back(local_id); |
| 80 | 77 |
| 81 if (cache_entry.is_dirty()) | 78 if (cache_entry.is_dirty()) |
| 82 to_upload->push_back(local_id); | 79 should_update = true; |
| 83 } | 80 } |
| 81 if (should_update) |
| 82 to_update->push_back(local_id); |
| 84 } | 83 } |
| 85 DCHECK(!it->HasError()); | 84 DCHECK(!it->HasError()); |
| 86 } | 85 } |
| 87 | 86 |
| 88 // Iterates cache entries and collects IDs of ones with obsolete cache files. | 87 // Iterates cache entries and collects IDs of ones with obsolete cache files. |
| 89 void CheckExistingPinnedFiles(ResourceMetadata* metadata, | 88 void CheckExistingPinnedFiles(ResourceMetadata* metadata, |
| 90 FileCache* cache, | 89 FileCache* cache, |
| 91 std::vector<std::string>* local_ids) { | 90 std::vector<std::string>* local_ids) { |
| 92 scoped_ptr<FileCache::Iterator> it = cache->GetIterator(); | 91 scoped_ptr<FileCache::Iterator> it = cache->GetIterator(); |
| 93 for (; !it->IsAtEnd(); it->Advance()) { | 92 for (; !it->IsAtEnd(); it->Advance()) { |
| (...skipping 48 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 142 operation_observer_(observer), | 141 operation_observer_(observer), |
| 143 metadata_(metadata), | 142 metadata_(metadata), |
| 144 cache_(cache), | 143 cache_(cache), |
| 145 download_operation_(new file_system::DownloadOperation( | 144 download_operation_(new file_system::DownloadOperation( |
| 146 blocking_task_runner, | 145 blocking_task_runner, |
| 147 observer, | 146 observer, |
| 148 scheduler, | 147 scheduler, |
| 149 metadata, | 148 metadata, |
| 150 cache, | 149 cache, |
| 151 temporary_file_directory)), | 150 temporary_file_directory)), |
| 152 content_update_performer_( | |
| 153 new file_system::ContentUpdatePerformer(blocking_task_runner, | |
| 154 scheduler, | |
| 155 metadata, | |
| 156 cache)), | |
| 157 entry_update_performer_(new EntryUpdatePerformer(blocking_task_runner, | 151 entry_update_performer_(new EntryUpdatePerformer(blocking_task_runner, |
| 158 observer, | 152 observer, |
| 159 scheduler, | 153 scheduler, |
| 160 metadata)), | 154 metadata, |
| 155 cache)), |
| 161 delay_(base::TimeDelta::FromSeconds(kDelaySeconds)), | 156 delay_(base::TimeDelta::FromSeconds(kDelaySeconds)), |
| 162 long_delay_(base::TimeDelta::FromSeconds(kLongDelaySeconds)), | 157 long_delay_(base::TimeDelta::FromSeconds(kLongDelaySeconds)), |
| 163 weak_ptr_factory_(this) { | 158 weak_ptr_factory_(this) { |
| 164 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); | 159 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); |
| 165 } | 160 } |
| 166 | 161 |
| 167 SyncClient::~SyncClient() { | 162 SyncClient::~SyncClient() { |
| 168 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); | 163 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); |
| 169 } | 164 } |
| 170 | 165 |
| 171 void SyncClient::StartProcessingBacklog() { | 166 void SyncClient::StartProcessingBacklog() { |
| 172 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); | 167 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); |
| 173 | 168 |
| 174 std::vector<std::string>* to_fetch = new std::vector<std::string>; | 169 std::vector<std::string>* to_fetch = new std::vector<std::string>; |
| 175 std::vector<std::string>* to_upload = new std::vector<std::string>; | 170 std::vector<std::string>* to_update = new std::vector<std::string>; |
| 176 std::vector<std::string>* to_remove = new std::vector<std::string>; | |
| 177 blocking_task_runner_->PostTaskAndReply( | 171 blocking_task_runner_->PostTaskAndReply( |
| 178 FROM_HERE, | 172 FROM_HERE, |
| 179 base::Bind(&CollectBacklog, metadata_, to_fetch, to_upload, to_remove), | 173 base::Bind(&CollectBacklog, metadata_, to_fetch, to_update), |
| 180 base::Bind(&SyncClient::OnGetLocalIdsOfBacklog, | 174 base::Bind(&SyncClient::OnGetLocalIdsOfBacklog, |
| 181 weak_ptr_factory_.GetWeakPtr(), | 175 weak_ptr_factory_.GetWeakPtr(), |
| 182 base::Owned(to_fetch), | 176 base::Owned(to_fetch), |
| 183 base::Owned(to_upload), | 177 base::Owned(to_update))); |
| 184 base::Owned(to_remove))); | |
| 185 } | 178 } |
| 186 | 179 |
| 187 void SyncClient::StartCheckingExistingPinnedFiles() { | 180 void SyncClient::StartCheckingExistingPinnedFiles() { |
| 188 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); | 181 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); |
| 189 | 182 |
| 190 std::vector<std::string>* local_ids = new std::vector<std::string>; | 183 std::vector<std::string>* local_ids = new std::vector<std::string>; |
| 191 blocking_task_runner_->PostTaskAndReply( | 184 blocking_task_runner_->PostTaskAndReply( |
| 192 FROM_HERE, | 185 FROM_HERE, |
| 193 base::Bind(&CheckExistingPinnedFiles, | 186 base::Bind(&CheckExistingPinnedFiles, |
| 194 metadata_, | 187 metadata_, |
| (...skipping 23 matching lines...) Expand all Loading... |
| 218 break; | 211 break; |
| 219 case RUNNING: | 212 case RUNNING: |
| 220 // TODO(kinaba): Cancel tasks in JobScheduler as well. crbug.com/248856 | 213 // TODO(kinaba): Cancel tasks in JobScheduler as well. crbug.com/248856 |
| 221 break; | 214 break; |
| 222 } | 215 } |
| 223 } | 216 } |
| 224 | 217 |
| 225 void SyncClient::AddUploadTask(const ClientContext& context, | 218 void SyncClient::AddUploadTask(const ClientContext& context, |
| 226 const std::string& local_id) { | 219 const std::string& local_id) { |
| 227 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); | 220 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); |
| 228 AddUploadTaskInternal(context, local_id, delay_); | 221 // TODO(hashimoto): Remove this method. |
| 222 AddUpdateTask(context, local_id); |
| 229 } | 223 } |
| 230 | 224 |
| 231 void SyncClient::AddUpdateTask(const ClientContext& context, | 225 void SyncClient::AddUpdateTask(const ClientContext& context, |
| 232 const std::string& local_id) { | 226 const std::string& local_id) { |
| 233 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); | 227 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); |
| 234 AddUpdateTaskInternal(context, local_id, base::TimeDelta::FromSeconds(0)); | 228 AddUpdateTaskInternal(context, local_id, delay_); |
| 235 } | 229 } |
| 236 | 230 |
| 237 void SyncClient::AddFetchTaskInternal(const std::string& local_id, | 231 void SyncClient::AddFetchTaskInternal(const std::string& local_id, |
| 238 const base::TimeDelta& delay) { | 232 const base::TimeDelta& delay) { |
| 239 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); | 233 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); |
| 240 | 234 |
| 241 SyncTask task; | 235 SyncTask task; |
| 242 task.task = base::Bind( | 236 task.task = base::Bind( |
| 243 &file_system::DownloadOperation::EnsureFileDownloadedByLocalId, | 237 &file_system::DownloadOperation::EnsureFileDownloadedByLocalId, |
| 244 base::Unretained(download_operation_.get()), | 238 base::Unretained(download_operation_.get()), |
| 245 local_id, | 239 local_id, |
| 246 ClientContext(BACKGROUND), | 240 ClientContext(BACKGROUND), |
| 247 GetFileContentInitializedCallback(), | 241 GetFileContentInitializedCallback(), |
| 248 google_apis::GetContentCallback(), | 242 google_apis::GetContentCallback(), |
| 249 base::Bind(&SyncClient::OnFetchFileComplete, | 243 base::Bind(&SyncClient::OnFetchFileComplete, |
| 250 weak_ptr_factory_.GetWeakPtr(), | 244 weak_ptr_factory_.GetWeakPtr(), |
| 251 local_id)); | 245 local_id)); |
| 252 AddTask(SyncTasks::key_type(FETCH, local_id), task, delay); | 246 AddTask(SyncTasks::key_type(FETCH, local_id), task, delay); |
| 253 } | 247 } |
| 254 | 248 |
| 255 void SyncClient::AddUploadTaskInternal(const ClientContext& context, | |
| 256 const std::string& local_id, | |
| 257 const base::TimeDelta& delay) { | |
| 258 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); | |
| 259 | |
| 260 SyncTask task; | |
| 261 task.task = base::Bind( | |
| 262 &file_system::ContentUpdatePerformer::UpdateFileByLocalId, | |
| 263 base::Unretained(content_update_performer_.get()), | |
| 264 local_id, | |
| 265 context, | |
| 266 base::Bind(&SyncClient::OnUploadFileComplete, | |
| 267 weak_ptr_factory_.GetWeakPtr(), | |
| 268 local_id)); | |
| 269 AddTask(SyncTasks::key_type(UPLOAD, local_id), task, delay); | |
| 270 } | |
| 271 | |
| 272 void SyncClient::AddUpdateTaskInternal(const ClientContext& context, | 249 void SyncClient::AddUpdateTaskInternal(const ClientContext& context, |
| 273 const std::string& local_id, | 250 const std::string& local_id, |
| 274 const base::TimeDelta& delay) { | 251 const base::TimeDelta& delay) { |
| 275 SyncTask task; | 252 SyncTask task; |
| 276 task.task = base::Bind( | 253 task.task = base::Bind( |
| 277 &EntryUpdatePerformer::UpdateEntry, | 254 &EntryUpdatePerformer::UpdateEntry, |
| 278 base::Unretained(entry_update_performer_.get()), | 255 base::Unretained(entry_update_performer_.get()), |
| 279 local_id, | 256 local_id, |
| 280 context, | 257 context, |
| 281 base::Bind(&SyncClient::OnUpdateComplete, | 258 base::Bind(&SyncClient::OnUpdateComplete, |
| (...skipping 41 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 323 task->state = RUNNING; | 300 task->state = RUNNING; |
| 324 task->task.Run(); | 301 task->task.Run(); |
| 325 break; | 302 break; |
| 326 case RUNNING: // Do nothing. | 303 case RUNNING: // Do nothing. |
| 327 break; | 304 break; |
| 328 } | 305 } |
| 329 } | 306 } |
| 330 | 307 |
| 331 void SyncClient::OnGetLocalIdsOfBacklog( | 308 void SyncClient::OnGetLocalIdsOfBacklog( |
| 332 const std::vector<std::string>* to_fetch, | 309 const std::vector<std::string>* to_fetch, |
| 333 const std::vector<std::string>* to_upload, | |
| 334 const std::vector<std::string>* to_update) { | 310 const std::vector<std::string>* to_update) { |
| 335 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); | 311 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); |
| 336 | 312 |
| 337 // Give priority to upload tasks over fetch tasks, so that dirty files are | 313 // Give priority to upload tasks over fetch tasks, so that dirty files are |
| 338 // uploaded as soon as possible. | 314 // uploaded as soon as possible. |
| 339 for (size_t i = 0; i < to_upload->size(); ++i) { | 315 for (size_t i = 0; i < to_update->size(); ++i) { |
| 340 const std::string& local_id = (*to_upload)[i]; | 316 const std::string& local_id = (*to_update)[i]; |
| 341 DVLOG(1) << "Queuing to upload: " << local_id; | 317 DVLOG(1) << "Queuing to update: " << local_id; |
| 342 AddUploadTaskInternal(ClientContext(BACKGROUND), local_id, delay_); | 318 AddUpdateTask(ClientContext(BACKGROUND), local_id); |
| 343 } | 319 } |
| 344 | 320 |
| 345 for (size_t i = 0; i < to_fetch->size(); ++i) { | 321 for (size_t i = 0; i < to_fetch->size(); ++i) { |
| 346 const std::string& local_id = (*to_fetch)[i]; | 322 const std::string& local_id = (*to_fetch)[i]; |
| 347 DVLOG(1) << "Queuing to fetch: " << local_id; | 323 DVLOG(1) << "Queuing to fetch: " << local_id; |
| 348 AddFetchTaskInternal(local_id, delay_); | 324 AddFetchTaskInternal(local_id, delay_); |
| 349 } | 325 } |
| 350 | |
| 351 for (size_t i = 0; i < to_update->size(); ++i) { | |
| 352 const std::string& local_id = (*to_update)[i]; | |
| 353 DVLOG(1) << "Queuing to update: " << local_id; | |
| 354 AddUpdateTask(ClientContext(BACKGROUND), local_id); | |
| 355 } | |
| 356 } | 326 } |
| 357 | 327 |
| 358 void SyncClient::AddFetchTasks(const std::vector<std::string>* local_ids) { | 328 void SyncClient::AddFetchTasks(const std::vector<std::string>* local_ids) { |
| 359 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); | 329 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); |
| 360 | 330 |
| 361 for (size_t i = 0; i < local_ids->size(); ++i) | 331 for (size_t i = 0; i < local_ids->size(); ++i) |
| 362 AddFetchTask((*local_ids)[i]); | 332 AddFetchTask((*local_ids)[i]); |
| 363 } | 333 } |
| 364 | 334 |
| 365 bool SyncClient::OnTaskComplete(SyncType type, const std::string& local_id) { | 335 bool SyncClient::OnTaskComplete(SyncType type, const std::string& local_id) { |
| (...skipping 50 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 416 default: | 386 default: |
| 417 operation_observer_->OnDriveSyncError( | 387 operation_observer_->OnDriveSyncError( |
| 418 file_system::DRIVE_SYNC_ERROR_MISC, | 388 file_system::DRIVE_SYNC_ERROR_MISC, |
| 419 local_id); | 389 local_id); |
| 420 LOG(WARNING) << "Failed to fetch " << local_id | 390 LOG(WARNING) << "Failed to fetch " << local_id |
| 421 << ": " << FileErrorToString(error); | 391 << ": " << FileErrorToString(error); |
| 422 } | 392 } |
| 423 } | 393 } |
| 424 } | 394 } |
| 425 | 395 |
| 426 void SyncClient::OnUploadFileComplete(const std::string& local_id, | |
| 427 FileError error) { | |
| 428 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); | |
| 429 | |
| 430 if (!OnTaskComplete(UPLOAD, local_id)) | |
| 431 return; | |
| 432 | |
| 433 if (error == FILE_ERROR_OK) { | |
| 434 DVLOG(1) << "Uploaded " << local_id; | |
| 435 } else { | |
| 436 switch (error) { | |
| 437 case FILE_ERROR_NO_CONNECTION: | |
| 438 // Add the task again so that we'll retry once the connection is back. | |
| 439 AddUploadTaskInternal(ClientContext(BACKGROUND), local_id, delay_); | |
| 440 break; | |
| 441 case FILE_ERROR_SERVICE_UNAVAILABLE: | |
| 442 // Add the task again so that we'll retry once the service is back. | |
| 443 AddUploadTaskInternal(ClientContext(BACKGROUND), local_id, long_delay_); | |
| 444 operation_observer_->OnDriveSyncError( | |
| 445 file_system::DRIVE_SYNC_ERROR_SERVICE_UNAVAILABLE, | |
| 446 local_id); | |
| 447 break; | |
| 448 default: | |
| 449 operation_observer_->OnDriveSyncError( | |
| 450 file_system::DRIVE_SYNC_ERROR_MISC, | |
| 451 local_id); | |
| 452 LOG(WARNING) << "Failed to upload " << local_id << ": " | |
| 453 << FileErrorToString(error); | |
| 454 } | |
| 455 } | |
| 456 } | |
| 457 | |
| 458 void SyncClient::OnUpdateComplete(const std::string& local_id, | 396 void SyncClient::OnUpdateComplete(const std::string& local_id, |
| 459 FileError error) { | 397 FileError error) { |
| 460 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); | 398 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); |
| 461 | 399 |
| 462 if (!OnTaskComplete(UPDATE, local_id)) | 400 if (!OnTaskComplete(UPDATE, local_id)) |
| 463 return; | 401 return; |
| 464 | 402 |
| 465 if (error == FILE_ERROR_OK) { | 403 if (error == FILE_ERROR_OK) { |
| 466 DVLOG(1) << "Updated " << local_id; | 404 DVLOG(1) << "Updated " << local_id; |
| 467 } else { | 405 } else { |
| (...skipping 15 matching lines...) Expand all Loading... |
| 483 file_system::DRIVE_SYNC_ERROR_MISC, | 421 file_system::DRIVE_SYNC_ERROR_MISC, |
| 484 local_id); | 422 local_id); |
| 485 LOG(WARNING) << "Failed to update " << local_id << ": " | 423 LOG(WARNING) << "Failed to update " << local_id << ": " |
| 486 << FileErrorToString(error); | 424 << FileErrorToString(error); |
| 487 } | 425 } |
| 488 } | 426 } |
| 489 } | 427 } |
| 490 | 428 |
| 491 } // namespace internal | 429 } // namespace internal |
| 492 } // namespace drive | 430 } // namespace drive |
| OLD | NEW |