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/gdata/gdata_file_system.h" | 5 #include "chrome/browser/chromeos/gdata/gdata_file_system.h" |
6 | 6 |
7 #include <set> | 7 #include <set> |
8 #include <utility> | 8 #include <utility> |
9 | 9 |
10 #include "base/bind.h" | 10 #include "base/bind.h" |
11 #include "base/command_line.h" | |
12 #include "base/file_util.h" | 11 #include "base/file_util.h" |
13 #include "base/json/json_file_value_serializer.h" | 12 #include "base/json/json_file_value_serializer.h" |
14 #include "base/json/json_reader.h" | |
15 #include "base/json/json_writer.h" | |
16 #include "base/message_loop.h" | 13 #include "base/message_loop.h" |
17 #include "base/message_loop_proxy.h" | 14 #include "base/message_loop_proxy.h" |
18 #include "base/metrics/histogram.h" | 15 #include "base/metrics/histogram.h" |
19 #include "base/platform_file.h" | 16 #include "base/platform_file.h" |
20 #include "base/threading/sequenced_worker_pool.h" | 17 #include "base/threading/sequenced_worker_pool.h" |
21 #include "base/values.h" | 18 #include "base/values.h" |
22 #include "chrome/browser/chromeos/gdata/drive_webapps_registry.h" | 19 #include "chrome/browser/chromeos/gdata/drive_webapps_registry.h" |
23 #include "chrome/browser/chromeos/gdata/gdata.pb.h" | 20 #include "chrome/browser/chromeos/gdata/gdata.pb.h" |
24 #include "chrome/browser/chromeos/gdata/gdata_documents_service.h" | 21 #include "chrome/browser/chromeos/gdata/gdata_documents_service.h" |
25 #include "chrome/browser/chromeos/gdata/gdata_download_observer.h" | 22 #include "chrome/browser/chromeos/gdata/gdata_download_observer.h" |
26 #include "chrome/browser/chromeos/gdata/gdata_protocol_handler.h" | 23 #include "chrome/browser/chromeos/gdata/gdata_protocol_handler.h" |
27 #include "chrome/browser/chromeos/gdata/gdata_system_service.h" | 24 #include "chrome/browser/chromeos/gdata/gdata_system_service.h" |
28 #include "chrome/browser/chromeos/gdata/gdata_util.h" | 25 #include "chrome/browser/chromeos/gdata/gdata_util.h" |
29 #include "chrome/browser/prefs/pref_service.h" | 26 #include "chrome/browser/prefs/pref_service.h" |
30 #include "chrome/browser/profiles/profile.h" | 27 #include "chrome/browser/profiles/profile.h" |
31 #include "chrome/common/chrome_switches.h" | |
32 #include "chrome/common/chrome_notification_types.h" | 28 #include "chrome/common/chrome_notification_types.h" |
33 #include "chrome/common/pref_names.h" | 29 #include "chrome/common/pref_names.h" |
34 #include "content/public/browser/browser_thread.h" | 30 #include "content/public/browser/browser_thread.h" |
35 #include "content/public/browser/notification_details.h" | 31 #include "content/public/browser/notification_details.h" |
36 #include "net/base/mime_util.h" | 32 #include "net/base/mime_util.h" |
37 | 33 |
38 using content::BrowserThread; | 34 using content::BrowserThread; |
39 | 35 |
40 namespace gdata { | 36 namespace gdata { |
41 namespace { | 37 namespace { |
42 | 38 |
43 const char kMimeTypeJson[] = "application/json"; | 39 const char kMimeTypeJson[] = "application/json"; |
44 const char kMimeTypeOctetStream[] = "application/octet-stream"; | 40 const char kMimeTypeOctetStream[] = "application/octet-stream"; |
45 | 41 |
46 const FilePath::CharType kAccountMetadataFile[] = | |
47 FILE_PATH_LITERAL("account_metadata.json"); | |
48 const FilePath::CharType kFilesystemProtoFile[] = | |
49 FILE_PATH_LITERAL("file_system.pb"); | |
50 const FilePath::CharType kResourceMetadataDBFile[] = | |
51 FILE_PATH_LITERAL("resource_metadata.db"); | |
52 | |
53 const char kEmptyFilePath[] = "/dev/null"; | 42 const char kEmptyFilePath[] = "/dev/null"; |
54 | 43 |
55 // GData update check interval (in seconds). | 44 // GData update check interval (in seconds). |
56 #ifndef NDEBUG | 45 #ifndef NDEBUG |
57 const int kGDataUpdateCheckIntervalInSec = 5; | 46 const int kGDataUpdateCheckIntervalInSec = 5; |
58 #else | 47 #else |
59 const int kGDataUpdateCheckIntervalInSec = 60; | 48 const int kGDataUpdateCheckIntervalInSec = 60; |
60 #endif | 49 #endif |
61 | 50 |
62 // Update the fetch progress UI per every this number of feeds. | |
63 const int kFetchUiUpdateStep = 10; | |
64 | |
65 // Schedule for dumping root file system proto buffers to disk depending its | |
66 // total protobuffer size in MB. | |
67 typedef struct { | |
68 double size; | |
69 int timeout; | |
70 } SerializationTimetable; | |
71 | |
72 SerializationTimetable kSerializeTimetable[] = { | |
73 #ifndef NDEBUG | |
74 {0.5, 0}, // Less than 0.5MB, dump immediately. | |
75 {-1, 1}, // Any size, dump if older than 1 minute. | |
76 #else | |
77 {0.5, 0}, // Less than 0.5MB, dump immediately. | |
78 {1.0, 15}, // Less than 1.0MB, dump after 15 minutes. | |
79 {2.0, 30}, | |
80 {4.0, 60}, | |
81 {-1, 120}, // Any size, dump if older than 120 minutes. | |
82 #endif | |
83 }; | |
84 | |
85 // Returns true if file system is due to be serialized on disk based on it | |
86 // |serialized_size| and |last_serialized| timestamp. | |
87 bool ShouldSerializeFileSystemNow(size_t serialized_size, | |
88 const base::Time& last_serialized) { | |
89 const double size_in_mb = serialized_size / 1048576.0; | |
90 const int last_proto_dump_in_min = | |
91 (base::Time::Now() - last_serialized).InMinutes(); | |
92 for (size_t i = 0; i < arraysize(kSerializeTimetable); i++) { | |
93 if ((size_in_mb < kSerializeTimetable[i].size || | |
94 kSerializeTimetable[i].size == -1) && | |
95 last_proto_dump_in_min >= kSerializeTimetable[i].timeout) { | |
96 return true; | |
97 } | |
98 } | |
99 return false; | |
100 } | |
101 | |
102 // Converts gdata error code into file platform error code. | |
103 GDataFileError GDataToGDataFileError(GDataErrorCode status) { | |
104 switch (status) { | |
105 case HTTP_SUCCESS: | |
106 case HTTP_CREATED: | |
107 return GDATA_FILE_OK; | |
108 case HTTP_UNAUTHORIZED: | |
109 case HTTP_FORBIDDEN: | |
110 return GDATA_FILE_ERROR_ACCESS_DENIED; | |
111 case HTTP_NOT_FOUND: | |
112 return GDATA_FILE_ERROR_NOT_FOUND; | |
113 case GDATA_PARSE_ERROR: | |
114 case GDATA_FILE_ERROR: | |
115 return GDATA_FILE_ERROR_ABORT; | |
116 case GDATA_NO_CONNECTION: | |
117 return GDATA_FILE_ERROR_NO_CONNECTION; | |
118 default: | |
119 return GDATA_FILE_ERROR_FAILED; | |
120 } | |
121 } | |
122 | |
123 //================================ Helper functions ============================ | 51 //================================ Helper functions ============================ |
124 | 52 |
125 // Invoked upon completion of TransferRegularFile initiated by Copy. | 53 // Invoked upon completion of TransferRegularFile initiated by Copy. |
126 // | 54 // |
127 // |callback| is run on the thread represented by |relay_proxy|. | 55 // |callback| is run on the thread represented by |relay_proxy|. |
128 void OnTransferRegularFileCompleteForCopy( | 56 void OnTransferRegularFileCompleteForCopy( |
129 const FileOperationCallback& callback, | 57 const FileOperationCallback& callback, |
130 scoped_refptr<base::MessageLoopProxy> relay_proxy, | 58 scoped_refptr<base::MessageLoopProxy> relay_proxy, |
131 GDataFileError error) { | 59 GDataFileError error) { |
132 if (!callback.is_null()) | 60 if (!callback.is_null()) |
(...skipping 60 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
193 base::MessageLoopProxy::current()->PostTask(FROM_HERE, callback_); | 121 base::MessageLoopProxy::current()->PostTask(FROM_HERE, callback_); |
194 file_system_->RemoveObserver(this); | 122 file_system_->RemoveObserver(this); |
195 base::MessageLoopProxy::current()->DeleteSoon(FROM_HERE, this); | 123 base::MessageLoopProxy::current()->DeleteSoon(FROM_HERE, this); |
196 } | 124 } |
197 | 125 |
198 private: | 126 private: |
199 GDataFileSystemInterface* file_system_; | 127 GDataFileSystemInterface* file_system_; |
200 base::Closure callback_; | 128 base::Closure callback_; |
201 }; | 129 }; |
202 | 130 |
203 // Saves the string |serialized_proto| to a file at |path| on a blocking thread. | |
204 void SaveProtoOnBlockingPool(const FilePath& path, | |
205 scoped_ptr<std::string> serialized_proto) { | |
206 const int file_size = static_cast<int>(serialized_proto->length()); | |
207 if (file_util::WriteFile(path, serialized_proto->data(), file_size) != | |
208 file_size) { | |
209 LOG(WARNING) << "GData proto file can't be stored at " | |
210 << path.value(); | |
211 if (!file_util::Delete(path, true)) { | |
212 LOG(WARNING) << "GData proto file can't be deleted at " | |
213 << path.value(); | |
214 } | |
215 } | |
216 } | |
217 | |
218 // Loads the file at |path| into the string |serialized_proto| on a blocking | |
219 // thread. | |
220 void LoadProtoOnBlockingPool(const FilePath& path, | |
221 LoadRootFeedParams* params) { | |
222 base::PlatformFileInfo info; | |
223 if (!file_util::GetFileInfo(path, &info)) { | |
224 params->load_error = GDATA_FILE_ERROR_NOT_FOUND; | |
225 return; | |
226 } | |
227 params->last_modified = info.last_modified; | |
228 if (!file_util::ReadFileToString(path, ¶ms->proto)) { | |
229 LOG(WARNING) << "Proto file not found at " << path.value(); | |
230 params->load_error = GDATA_FILE_ERROR_NOT_FOUND; | |
231 return; | |
232 } | |
233 params->load_error = GDATA_FILE_OK; | |
234 } | |
235 | |
236 // Saves json file content content in |feed| to |file_pathname| on blocking | |
237 // pool. Used for debugging. | |
238 void SaveFeedOnBlockingPoolForDebugging( | |
239 const FilePath& file_path, | |
240 scoped_ptr<base::Value> feed) { | |
241 std::string json; | |
242 base::JSONWriter::WriteWithOptions(feed.get(), | |
243 base::JSONWriter::OPTIONS_PRETTY_PRINT, | |
244 &json); | |
245 | |
246 int file_size = static_cast<int>(json.length()); | |
247 if (file_util::WriteFile(file_path, json.data(), file_size) != file_size) { | |
248 LOG(WARNING) << "GData metadata file can't be stored at " | |
249 << file_path.value(); | |
250 if (!file_util::Delete(file_path, true)) { | |
251 LOG(WARNING) << "GData metadata file can't be deleted at " | |
252 << file_path.value(); | |
253 return; | |
254 } | |
255 } | |
256 } | |
257 | |
258 bool UseLevelDB() { | |
259 return CommandLine::ForCurrentProcess()->HasSwitch( | |
260 switches::kUseLevelDBForGData); | |
261 } | |
262 | |
263 // Gets the file size of |local_file|. | 131 // Gets the file size of |local_file|. |
264 void GetLocalFileSizeOnBlockingPool(const FilePath& local_file, | 132 void GetLocalFileSizeOnBlockingPool(const FilePath& local_file, |
265 GDataFileError* error, | 133 GDataFileError* error, |
266 int64* file_size) { | 134 int64* file_size) { |
267 DCHECK(error); | 135 DCHECK(error); |
268 DCHECK(file_size); | 136 DCHECK(file_size); |
269 | 137 |
270 *file_size = 0; | 138 *file_size = 0; |
271 *error = file_util::GetFileSize(local_file, file_size) ? | 139 *error = file_util::GetFileSize(local_file, file_size) ? |
272 GDATA_FILE_OK : | 140 GDATA_FILE_OK : |
(...skipping 230 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
503 }; | 371 }; |
504 | 372 |
505 // Returns callback which runs the given |callback| on the current thread. | 373 // Returns callback which runs the given |callback| on the current thread. |
506 template<typename CallbackType> | 374 template<typename CallbackType> |
507 CallbackType CreateRelayCallback(const CallbackType& callback) { | 375 CallbackType CreateRelayCallback(const CallbackType& callback) { |
508 return base::Bind(&RelayCallback<CallbackType>::Run, | 376 return base::Bind(&RelayCallback<CallbackType>::Run, |
509 base::MessageLoopProxy::current(), | 377 base::MessageLoopProxy::current(), |
510 callback); | 378 callback); |
511 } | 379 } |
512 | 380 |
513 // Wrapper around BrowserThread::PostTask to post a task to the blocking | |
514 // pool with the given sequence token. | |
515 void PostBlockingPoolSequencedTask( | |
516 const tracked_objects::Location& from_here, | |
517 base::SequencedTaskRunner* blocking_task_runner, | |
518 const base::Closure& task) { | |
519 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); | |
520 | |
521 const bool posted = blocking_task_runner->PostTask(from_here, task); | |
522 DCHECK(posted); | |
523 } | |
524 | |
525 // Similar to PostBlockingPoolSequencedTask() but this one takes a reply | |
526 // callback that runs on the calling thread. | |
527 void PostBlockingPoolSequencedTaskAndReply( | |
528 const tracked_objects::Location& from_here, | |
529 base::SequencedTaskRunner* blocking_task_runner, | |
530 const base::Closure& request_task, | |
531 const base::Closure& reply_task) { | |
532 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); | |
533 | |
534 const bool posted = blocking_task_runner->PostTaskAndReply( | |
535 from_here, request_task, reply_task); | |
536 DCHECK(posted); | |
537 } | |
538 | |
539 // Helper function for binding |path| to GetEntryInfoWithFilePathCallback and | 381 // Helper function for binding |path| to GetEntryInfoWithFilePathCallback and |
540 // create GetEntryInfoCallback. | 382 // create GetEntryInfoCallback. |
541 void RunGetEntryInfoWithFilePathCallback( | 383 void RunGetEntryInfoWithFilePathCallback( |
542 const GetEntryInfoWithFilePathCallback& callback, | 384 const GetEntryInfoWithFilePathCallback& callback, |
543 const FilePath& path, | 385 const FilePath& path, |
544 GDataFileError error, | 386 GDataFileError error, |
545 scoped_ptr<GDataEntryProto> entry_proto) { | 387 scoped_ptr<GDataEntryProto> entry_proto) { |
546 if (!callback.is_null()) | 388 if (!callback.is_null()) |
547 callback.Run(error, path, entry_proto.Pass()); | 389 callback.Run(error, path, entry_proto.Pass()); |
548 } | 390 } |
549 | 391 |
550 } // namespace | 392 } // namespace |
551 | 393 |
552 GDataWapiFeedLoader::GDataWapiFeedLoader( | |
553 GDataDirectoryService* directory_service, | |
554 DocumentsServiceInterface* documents_service, | |
555 DriveWebAppsRegistryInterface* webapps_registry, | |
556 GDataCache* cache, | |
557 scoped_refptr<base::SequencedTaskRunner> blocking_task_runner) | |
558 : directory_service_(directory_service), | |
559 documents_service_(documents_service), | |
560 webapps_registry_(webapps_registry), | |
561 cache_(cache), | |
562 blocking_task_runner_(blocking_task_runner), | |
563 weak_ptr_factory_(ALLOW_THIS_IN_INITIALIZER_LIST(this)) { | |
564 } | |
565 | |
566 GDataWapiFeedLoader::~GDataWapiFeedLoader() { | |
567 } | |
568 | |
569 void GDataWapiFeedLoader::AddObserver(Observer* observer) { | |
570 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); | |
571 observers_.AddObserver(observer); | |
572 } | |
573 | |
574 void GDataWapiFeedLoader::RemoveObserver(Observer* observer) { | |
575 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); | |
576 observers_.RemoveObserver(observer); | |
577 } | |
578 | |
579 // Defines set of parameters sent to callback OnNotifyDocumentFeedFetched(). | |
580 // This is a trick to update the number of fetched documents frequently on | |
581 // UI. Due to performance reason, we need to fetch a number of files at | |
582 // a time. However, it'll take long time, and a user has no way to know | |
583 // the current update state. In order to make users confortable, | |
584 // we increment the number of fetched documents with more frequent but smaller | |
585 // steps than actual fetching. | |
586 struct GetDocumentsUiState { | |
587 explicit GetDocumentsUiState(base::TimeTicks start_time) | |
588 : num_fetched_documents(0), | |
589 num_showing_documents(0), | |
590 start_time(start_time), | |
591 weak_ptr_factory(this) { | |
592 } | |
593 | |
594 // The number of fetched documents. | |
595 int num_fetched_documents; | |
596 | |
597 // The number documents shown on UI. | |
598 int num_showing_documents; | |
599 | |
600 // When the UI update has started. | |
601 base::TimeTicks start_time; | |
602 | |
603 // Time elapsed since the feed fetching was started. | |
604 base::TimeDelta feed_fetching_elapsed_time; | |
605 | |
606 base::WeakPtrFactory<GetDocumentsUiState> weak_ptr_factory; | |
607 }; | |
608 | |
609 // Defines set of parameters sent to callback OnGetDocuments(). | |
610 // TODO(satorux): Move this to a new file: crbug.com/138268 | |
611 struct GetDocumentsParams { | |
612 GetDocumentsParams(int start_changestamp, | |
613 int root_feed_changestamp, | |
614 std::vector<DocumentFeed*>* feed_list, | |
615 bool should_fetch_multiple_feeds, | |
616 const FilePath& search_file_path, | |
617 const std::string& search_query, | |
618 const std::string& directory_resource_id, | |
619 const FindEntryCallback& callback, | |
620 GetDocumentsUiState* ui_state); | |
621 ~GetDocumentsParams(); | |
622 | |
623 // Changestamps are positive numbers in increasing order. The difference | |
624 // between two changestamps is proportional equal to number of items in | |
625 // delta feed between them - bigger the difference, more likely bigger | |
626 // number of items in delta feeds. | |
627 int start_changestamp; | |
628 int root_feed_changestamp; | |
629 scoped_ptr<std::vector<DocumentFeed*> > feed_list; | |
630 // Should we stop after getting first feed chunk, even if there is more | |
631 // data. | |
632 bool should_fetch_multiple_feeds; | |
633 FilePath search_file_path; | |
634 std::string search_query; | |
635 std::string directory_resource_id; | |
636 FindEntryCallback callback; | |
637 scoped_ptr<GetDocumentsUiState> ui_state; | |
638 }; | |
639 | |
640 GetDocumentsParams::GetDocumentsParams( | |
641 int start_changestamp, | |
642 int root_feed_changestamp, | |
643 std::vector<DocumentFeed*>* feed_list, | |
644 bool should_fetch_multiple_feeds, | |
645 const FilePath& search_file_path, | |
646 const std::string& search_query, | |
647 const std::string& directory_resource_id, | |
648 const FindEntryCallback& callback, | |
649 GetDocumentsUiState* ui_state) | |
650 : start_changestamp(start_changestamp), | |
651 root_feed_changestamp(root_feed_changestamp), | |
652 feed_list(feed_list), | |
653 should_fetch_multiple_feeds(should_fetch_multiple_feeds), | |
654 search_file_path(search_file_path), | |
655 search_query(search_query), | |
656 directory_resource_id(directory_resource_id), | |
657 callback(callback), | |
658 ui_state(ui_state) { | |
659 } | |
660 | |
661 GetDocumentsParams::~GetDocumentsParams() { | |
662 STLDeleteElements(feed_list.get()); | |
663 } | |
664 | |
665 // GDataFileSystem::CreateDirectoryParams struct implementation. | 394 // GDataFileSystem::CreateDirectoryParams struct implementation. |
666 struct GDataFileSystem::CreateDirectoryParams { | 395 struct GDataFileSystem::CreateDirectoryParams { |
667 CreateDirectoryParams(const FilePath& created_directory_path, | 396 CreateDirectoryParams(const FilePath& created_directory_path, |
668 const FilePath& target_directory_path, | 397 const FilePath& target_directory_path, |
669 bool is_exclusive, | 398 bool is_exclusive, |
670 bool is_recursive, | 399 bool is_recursive, |
671 const FileOperationCallback& callback); | 400 const FileOperationCallback& callback); |
672 ~CreateDirectoryParams(); | 401 ~CreateDirectoryParams(); |
673 | 402 |
674 const FilePath created_directory_path; | 403 const FilePath created_directory_path; |
(...skipping 293 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
968 } | 697 } |
969 | 698 |
970 void GDataFileSystem::FindEntryByPathSyncOnUIThread( | 699 void GDataFileSystem::FindEntryByPathSyncOnUIThread( |
971 const FilePath& search_file_path, | 700 const FilePath& search_file_path, |
972 const FindEntryCallback& callback) { | 701 const FindEntryCallback& callback) { |
973 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); | 702 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); |
974 | 703 |
975 directory_service_->FindEntryByPathAndRunSync(search_file_path, callback); | 704 directory_service_->FindEntryByPathAndRunSync(search_file_path, callback); |
976 } | 705 } |
977 | 706 |
978 void GDataWapiFeedLoader::ReloadFromServerIfNeeded( | |
979 ContentOrigin initial_origin, | |
980 int local_changestamp, | |
981 const FilePath& search_file_path, | |
982 const FindEntryCallback& callback) { | |
983 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); | |
984 | |
985 DVLOG(1) << "ReloadFeedFromServerIfNeeded local_changestamp=" | |
986 << local_changestamp << ", initial_origin=" << initial_origin; | |
987 | |
988 // First fetch the latest changestamp to see if there were any new changes | |
989 // there at all. | |
990 documents_service_->GetAccountMetadata( | |
991 base::Bind(&GDataWapiFeedLoader::OnGetAccountMetadata, | |
992 weak_ptr_factory_.GetWeakPtr(), | |
993 initial_origin, | |
994 local_changestamp, | |
995 search_file_path, | |
996 callback)); | |
997 } | |
998 | |
999 void GDataWapiFeedLoader::OnGetAccountMetadata( | |
1000 ContentOrigin initial_origin, | |
1001 int local_changestamp, | |
1002 const FilePath& search_file_path, | |
1003 const FindEntryCallback& callback, | |
1004 GDataErrorCode status, | |
1005 scoped_ptr<base::Value> feed_data) { | |
1006 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); | |
1007 | |
1008 GDataFileError error = GDataToGDataFileError(status); | |
1009 if (error != GDATA_FILE_OK) { | |
1010 // Get changes starting from the next changestamp from what we have locally. | |
1011 LoadFromServer(initial_origin, | |
1012 local_changestamp + 1, 0, | |
1013 true, /* should_fetch_multiple_feeds */ | |
1014 search_file_path, | |
1015 std::string() /* no search query */, | |
1016 GURL(), /* feed not explicitly set */ | |
1017 std::string() /* no directory resource ID */, | |
1018 callback, | |
1019 base::Bind(&GDataWapiFeedLoader::OnFeedFromServerLoaded, | |
1020 weak_ptr_factory_.GetWeakPtr())); | |
1021 return; | |
1022 } | |
1023 | |
1024 scoped_ptr<AccountMetadataFeed> account_metadata; | |
1025 if (feed_data.get()) { | |
1026 account_metadata = AccountMetadataFeed::CreateFrom(*feed_data); | |
1027 #ifndef NDEBUG | |
1028 // Save account metadata feed for analysis. | |
1029 const FilePath path = | |
1030 cache_->GetCacheDirectoryPath(GDataCache::CACHE_TYPE_META).Append( | |
1031 kAccountMetadataFile); | |
1032 PostBlockingPoolSequencedTask( | |
1033 FROM_HERE, | |
1034 blocking_task_runner_, | |
1035 base::Bind(&SaveFeedOnBlockingPoolForDebugging, | |
1036 path, base::Passed(&feed_data))); | |
1037 #endif | |
1038 } | |
1039 | |
1040 if (!account_metadata.get()) { | |
1041 LoadFromServer(initial_origin, | |
1042 local_changestamp + 1, 0, | |
1043 true, /* should_fetch_multiple_feeds */ | |
1044 search_file_path, | |
1045 std::string() /* no search query */, | |
1046 GURL(), /* feed not explicitly set */ | |
1047 std::string() /* no directory resource ID */, | |
1048 callback, | |
1049 base::Bind(&GDataWapiFeedLoader::OnFeedFromServerLoaded, | |
1050 weak_ptr_factory_.GetWeakPtr())); | |
1051 return; | |
1052 } | |
1053 | |
1054 webapps_registry_->UpdateFromFeed(account_metadata.get()); | |
1055 | |
1056 bool changes_detected = true; | |
1057 if (local_changestamp >= account_metadata->largest_changestamp()) { | |
1058 if (local_changestamp > account_metadata->largest_changestamp()) { | |
1059 LOG(WARNING) << "Cached client feed is fresher than server, client = " | |
1060 << local_changestamp | |
1061 << ", server = " | |
1062 << account_metadata->largest_changestamp(); | |
1063 } | |
1064 // If our cache holds the latest state from the server, change the | |
1065 // state to FROM_SERVER. | |
1066 directory_service_->set_origin( | |
1067 initial_origin == FROM_CACHE ? FROM_SERVER : initial_origin); | |
1068 changes_detected = false; | |
1069 } | |
1070 | |
1071 // No changes detected, continue with search as planned. | |
1072 if (!changes_detected) { | |
1073 if (!callback.is_null()) { | |
1074 directory_service_->FindEntryByPathAndRunSync(search_file_path, | |
1075 callback); | |
1076 } | |
1077 return; | |
1078 } | |
1079 | |
1080 // Load changes from the server. | |
1081 LoadFromServer(initial_origin, | |
1082 local_changestamp > 0 ? local_changestamp + 1 : 0, | |
1083 account_metadata->largest_changestamp(), | |
1084 true, /* should_fetch_multiple_feeds */ | |
1085 search_file_path, | |
1086 std::string() /* no search query */, | |
1087 GURL(), /* feed not explicitly set */ | |
1088 std::string() /* no directory resource ID */, | |
1089 callback, | |
1090 base::Bind(&GDataWapiFeedLoader::OnFeedFromServerLoaded, | |
1091 weak_ptr_factory_.GetWeakPtr())); | |
1092 } | |
1093 | |
1094 void GDataWapiFeedLoader::LoadFromServer( | |
1095 ContentOrigin initial_origin, | |
1096 int start_changestamp, | |
1097 int root_feed_changestamp, | |
1098 bool should_fetch_multiple_feeds, | |
1099 const FilePath& search_file_path, | |
1100 const std::string& search_query, | |
1101 const GURL& feed_to_load, | |
1102 const std::string& directory_resource_id, | |
1103 const FindEntryCallback& entry_found_callback, | |
1104 const LoadDocumentFeedCallback& feed_load_callback) { | |
1105 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); | |
1106 | |
1107 // |feed_list| will contain the list of all collected feed updates that | |
1108 // we will receive through calls of DocumentsService::GetDocuments(). | |
1109 scoped_ptr<std::vector<DocumentFeed*> > feed_list( | |
1110 new std::vector<DocumentFeed*>); | |
1111 const base::TimeTicks start_time = base::TimeTicks::Now(); | |
1112 documents_service_->GetDocuments( | |
1113 feed_to_load, | |
1114 start_changestamp, | |
1115 search_query, | |
1116 directory_resource_id, | |
1117 base::Bind(&GDataWapiFeedLoader::OnGetDocuments, | |
1118 weak_ptr_factory_.GetWeakPtr(), | |
1119 initial_origin, | |
1120 feed_load_callback, | |
1121 base::Owned(new GetDocumentsParams(start_changestamp, | |
1122 root_feed_changestamp, | |
1123 feed_list.release(), | |
1124 should_fetch_multiple_feeds, | |
1125 search_file_path, | |
1126 search_query, | |
1127 directory_resource_id, | |
1128 entry_found_callback, | |
1129 NULL)), | |
1130 start_time)); | |
1131 } | |
1132 | |
1133 void GDataWapiFeedLoader::OnFeedFromServerLoaded(GetDocumentsParams* params, | |
1134 GDataFileError error) { | |
1135 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); | |
1136 | |
1137 if (error != GDATA_FILE_OK) { | |
1138 if (!params->callback.is_null()) | |
1139 params->callback.Run(error, NULL); | |
1140 return; | |
1141 } | |
1142 | |
1143 error = UpdateFromFeed(*params->feed_list, | |
1144 params->start_changestamp, | |
1145 params->root_feed_changestamp); | |
1146 | |
1147 if (error != GDATA_FILE_OK) { | |
1148 if (!params->callback.is_null()) | |
1149 params->callback.Run(error, NULL); | |
1150 | |
1151 return; | |
1152 } | |
1153 | |
1154 // Save file system metadata to disk. | |
1155 SaveFileSystem(); | |
1156 | |
1157 // If we had someone to report this too, then this retrieval was done in a | |
1158 // context of search... so continue search. | |
1159 if (!params->callback.is_null()) { | |
1160 directory_service_->FindEntryByPathAndRunSync(params->search_file_path, | |
1161 params->callback); | |
1162 } | |
1163 | |
1164 FOR_EACH_OBSERVER(Observer, observers_, OnFeedFromServerLoaded()); | |
1165 } | |
1166 | |
1167 void GDataFileSystem::TransferFileFromRemoteToLocal( | 707 void GDataFileSystem::TransferFileFromRemoteToLocal( |
1168 const FilePath& remote_src_file_path, | 708 const FilePath& remote_src_file_path, |
1169 const FilePath& local_dest_file_path, | 709 const FilePath& local_dest_file_path, |
1170 const FileOperationCallback& callback) { | 710 const FileOperationCallback& callback) { |
1171 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); | 711 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); |
1172 | 712 |
1173 GetFileByPath(remote_src_file_path, | 713 GetFileByPath(remote_src_file_path, |
1174 base::Bind(&GDataFileSystem::OnGetFileCompleteForTransferFile, | 714 base::Bind(&GDataFileSystem::OnGetFileCompleteForTransferFile, |
1175 ui_weak_ptr_, | 715 ui_weak_ptr_, |
1176 local_dest_file_path, | 716 local_dest_file_path, |
(...skipping 38 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1215 if (!entry_proto->file_info().is_directory()) { | 755 if (!entry_proto->file_info().is_directory()) { |
1216 // The parent of |remote_dest_file_path| is not a directory. | 756 // The parent of |remote_dest_file_path| is not a directory. |
1217 if (!callback.is_null()) { | 757 if (!callback.is_null()) { |
1218 base::MessageLoopProxy::current()->PostTask( | 758 base::MessageLoopProxy::current()->PostTask( |
1219 FROM_HERE, base::Bind(callback, GDATA_FILE_ERROR_NOT_A_DIRECTORY)); | 759 FROM_HERE, base::Bind(callback, GDATA_FILE_ERROR_NOT_A_DIRECTORY)); |
1220 } | 760 } |
1221 return; | 761 return; |
1222 } | 762 } |
1223 | 763 |
1224 std::string* resource_id = new std::string; | 764 std::string* resource_id = new std::string; |
1225 PostBlockingPoolSequencedTaskAndReply( | 765 util::PostBlockingPoolSequencedTaskAndReply( |
1226 FROM_HERE, | 766 FROM_HERE, |
1227 blocking_task_runner_, | 767 blocking_task_runner_, |
1228 base::Bind(&GetDocumentResourceIdOnBlockingPool, | 768 base::Bind(&GetDocumentResourceIdOnBlockingPool, |
1229 local_src_file_path, | 769 local_src_file_path, |
1230 resource_id), | 770 resource_id), |
1231 base::Bind(&GDataFileSystem::TransferFileForResourceId, | 771 base::Bind(&GDataFileSystem::TransferFileForResourceId, |
1232 ui_weak_ptr_, | 772 ui_weak_ptr_, |
1233 local_src_file_path, | 773 local_src_file_path, |
1234 remote_dest_file_path, | 774 remote_dest_file_path, |
1235 callback, | 775 callback, |
(...skipping 28 matching lines...) Expand all Loading... |
1264 void GDataFileSystem::TransferRegularFile( | 804 void GDataFileSystem::TransferRegularFile( |
1265 const FilePath& local_file_path, | 805 const FilePath& local_file_path, |
1266 const FilePath& remote_dest_file_path, | 806 const FilePath& remote_dest_file_path, |
1267 const FileOperationCallback& callback) { | 807 const FileOperationCallback& callback) { |
1268 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); | 808 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); |
1269 | 809 |
1270 GDataFileError* error = | 810 GDataFileError* error = |
1271 new GDataFileError(GDATA_FILE_OK); | 811 new GDataFileError(GDATA_FILE_OK); |
1272 int64* file_size = new int64; | 812 int64* file_size = new int64; |
1273 std::string* content_type = new std::string; | 813 std::string* content_type = new std::string; |
1274 PostBlockingPoolSequencedTaskAndReply( | 814 util::PostBlockingPoolSequencedTaskAndReply( |
1275 FROM_HERE, | 815 FROM_HERE, |
1276 blocking_task_runner_, | 816 blocking_task_runner_, |
1277 base::Bind(&GetLocalFileInfoOnBlockingPool, | 817 base::Bind(&GetLocalFileInfoOnBlockingPool, |
1278 local_file_path, | 818 local_file_path, |
1279 error, | 819 error, |
1280 file_size, | 820 file_size, |
1281 content_type), | 821 content_type), |
1282 base::Bind(&GDataFileSystem::StartFileUploadOnUIThread, | 822 base::Bind(&GDataFileSystem::StartFileUploadOnUIThread, |
1283 ui_weak_ptr_, | 823 ui_weak_ptr_, |
1284 StartFileUploadParams(local_file_path, | 824 StartFileUploadParams(local_file_path, |
(...skipping 207 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1492 callback.Run(error); | 1032 callback.Run(error); |
1493 | 1033 |
1494 return; | 1034 return; |
1495 } | 1035 } |
1496 | 1036 |
1497 // GetFileByPath downloads the file from gdata to a local cache, which is then | 1037 // GetFileByPath downloads the file from gdata to a local cache, which is then |
1498 // copied to the actual destination path on the local file system using | 1038 // copied to the actual destination path on the local file system using |
1499 // CopyLocalFileOnBlockingPool. | 1039 // CopyLocalFileOnBlockingPool. |
1500 GDataFileError* copy_file_error = | 1040 GDataFileError* copy_file_error = |
1501 new GDataFileError(GDATA_FILE_OK); | 1041 new GDataFileError(GDATA_FILE_OK); |
1502 PostBlockingPoolSequencedTaskAndReply( | 1042 util::PostBlockingPoolSequencedTaskAndReply( |
1503 FROM_HERE, | 1043 FROM_HERE, |
1504 blocking_task_runner_, | 1044 blocking_task_runner_, |
1505 base::Bind(&CopyLocalFileOnBlockingPool, | 1045 base::Bind(&CopyLocalFileOnBlockingPool, |
1506 local_file_path, | 1046 local_file_path, |
1507 local_dest_file_path, | 1047 local_dest_file_path, |
1508 copy_file_error), | 1048 copy_file_error), |
1509 base::Bind(&RunFileOperationCallbackHelper, | 1049 base::Bind(&RunFileOperationCallbackHelper, |
1510 callback, | 1050 callback, |
1511 base::Owned(copy_file_error))); | 1051 base::Owned(copy_file_error))); |
1512 } | 1052 } |
(...skipping 502 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
2015 // For a hosted document, we create a special JSON file to represent the | 1555 // For a hosted document, we create a special JSON file to represent the |
2016 // document instead of fetching the document content in one of the exported | 1556 // document instead of fetching the document content in one of the exported |
2017 // formats. The JSON file contains the edit URL and resource ID of the | 1557 // formats. The JSON file contains the edit URL and resource ID of the |
2018 // document. | 1558 // document. |
2019 if (entry_proto->file_specific_info().is_hosted_document()) { | 1559 if (entry_proto->file_specific_info().is_hosted_document()) { |
2020 GDataFileError* error = | 1560 GDataFileError* error = |
2021 new GDataFileError(GDATA_FILE_OK); | 1561 new GDataFileError(GDATA_FILE_OK); |
2022 FilePath* temp_file_path = new FilePath; | 1562 FilePath* temp_file_path = new FilePath; |
2023 std::string* mime_type = new std::string; | 1563 std::string* mime_type = new std::string; |
2024 GDataFileType* file_type = new GDataFileType(REGULAR_FILE); | 1564 GDataFileType* file_type = new GDataFileType(REGULAR_FILE); |
2025 PostBlockingPoolSequencedTaskAndReply( | 1565 util::PostBlockingPoolSequencedTaskAndReply( |
2026 FROM_HERE, | 1566 FROM_HERE, |
2027 blocking_task_runner_, | 1567 blocking_task_runner_, |
2028 base::Bind(&CreateDocumentJsonFileOnBlockingPool, | 1568 base::Bind(&CreateDocumentJsonFileOnBlockingPool, |
2029 cache_->GetCacheDirectoryPath( | 1569 cache_->GetCacheDirectoryPath( |
2030 GDataCache::CACHE_TYPE_TMP_DOCUMENTS), | 1570 GDataCache::CACHE_TYPE_TMP_DOCUMENTS), |
2031 GURL(entry_proto->file_specific_info().alternate_url()), | 1571 GURL(entry_proto->file_specific_info().alternate_url()), |
2032 entry_proto->resource_id(), | 1572 entry_proto->resource_id(), |
2033 error, | 1573 error, |
2034 temp_file_path, | 1574 temp_file_path, |
2035 mime_type, | 1575 mime_type, |
(...skipping 131 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
2167 params.get_file_callback, | 1707 params.get_file_callback, |
2168 params.get_download_data_callback))); | 1708 params.get_download_data_callback))); |
2169 } | 1709 } |
2170 | 1710 |
2171 void GDataFileSystem::OnGetDocumentEntry(const FilePath& cache_file_path, | 1711 void GDataFileSystem::OnGetDocumentEntry(const FilePath& cache_file_path, |
2172 const GetFileFromCacheParams& params, | 1712 const GetFileFromCacheParams& params, |
2173 GDataErrorCode status, | 1713 GDataErrorCode status, |
2174 scoped_ptr<base::Value> data) { | 1714 scoped_ptr<base::Value> data) { |
2175 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); | 1715 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); |
2176 | 1716 |
2177 GDataFileError error = GDataToGDataFileError(status); | 1717 GDataFileError error = util::GDataToGDataFileError(status); |
2178 | 1718 |
2179 scoped_ptr<GDataEntry> fresh_entry; | 1719 scoped_ptr<GDataEntry> fresh_entry; |
2180 if (error == GDATA_FILE_OK) { | 1720 if (error == GDATA_FILE_OK) { |
2181 scoped_ptr<DocumentEntry> doc_entry(DocumentEntry::ExtractAndParse(*data)); | 1721 scoped_ptr<DocumentEntry> doc_entry(DocumentEntry::ExtractAndParse(*data)); |
2182 if (doc_entry.get()) { | 1722 if (doc_entry.get()) { |
2183 fresh_entry.reset( | 1723 fresh_entry.reset( |
2184 GDataEntry::FromDocumentEntry(NULL, doc_entry.get(), | 1724 GDataEntry::FromDocumentEntry(NULL, doc_entry.get(), |
2185 directory_service_.get())); | 1725 directory_service_.get())); |
2186 } | 1726 } |
2187 if (!fresh_entry.get() || !fresh_entry->AsGDataFile()) { | 1727 if (!fresh_entry.get() || !fresh_entry->AsGDataFile()) { |
(...skipping 14 matching lines...) Expand all Loading... |
2202 | 1742 |
2203 GURL content_url = fresh_entry->content_url(); | 1743 GURL content_url = fresh_entry->content_url(); |
2204 int64 file_size = fresh_entry->file_info().size; | 1744 int64 file_size = fresh_entry->file_info().size; |
2205 | 1745 |
2206 DCHECK_EQ(params.resource_id, fresh_entry->resource_id()); | 1746 DCHECK_EQ(params.resource_id, fresh_entry->resource_id()); |
2207 scoped_ptr<GDataFile> fresh_entry_as_file( | 1747 scoped_ptr<GDataFile> fresh_entry_as_file( |
2208 fresh_entry.release()->AsGDataFile()); | 1748 fresh_entry.release()->AsGDataFile()); |
2209 directory_service_->RefreshFile(fresh_entry_as_file.Pass()); | 1749 directory_service_->RefreshFile(fresh_entry_as_file.Pass()); |
2210 | 1750 |
2211 bool* has_enough_space = new bool(false); | 1751 bool* has_enough_space = new bool(false); |
2212 PostBlockingPoolSequencedTaskAndReply( | 1752 util::PostBlockingPoolSequencedTaskAndReply( |
2213 FROM_HERE, | 1753 FROM_HERE, |
2214 blocking_task_runner_, | 1754 blocking_task_runner_, |
2215 base::Bind(&GDataCache::FreeDiskSpaceIfNeededFor, | 1755 base::Bind(&GDataCache::FreeDiskSpaceIfNeededFor, |
2216 base::Unretained(cache_), | 1756 base::Unretained(cache_), |
2217 file_size, | 1757 file_size, |
2218 has_enough_space), | 1758 has_enough_space), |
2219 base::Bind(&GDataFileSystem::StartDownloadFileIfEnoughSpace, | 1759 base::Bind(&GDataFileSystem::StartDownloadFileIfEnoughSpace, |
2220 ui_weak_ptr_, | 1760 ui_weak_ptr_, |
2221 params, | 1761 params, |
2222 content_url, | 1762 content_url, |
(...skipping 312 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
2535 if (error != GDATA_FILE_OK) { | 2075 if (error != GDATA_FILE_OK) { |
2536 if (!callback.is_null()) | 2076 if (!callback.is_null()) |
2537 callback.Run(error); | 2077 callback.Run(error); |
2538 return; | 2078 return; |
2539 } | 2079 } |
2540 | 2080 |
2541 // Gets the size of the cache file. Since the file is locally modified, the | 2081 // Gets the size of the cache file. Since the file is locally modified, the |
2542 // file size information stored in GDataEntry is not correct. | 2082 // file size information stored in GDataEntry is not correct. |
2543 GDataFileError* get_size_error = new GDataFileError(GDATA_FILE_ERROR_FAILED); | 2083 GDataFileError* get_size_error = new GDataFileError(GDATA_FILE_ERROR_FAILED); |
2544 int64* file_size = new int64(-1); | 2084 int64* file_size = new int64(-1); |
2545 PostBlockingPoolSequencedTaskAndReply( | 2085 util::PostBlockingPoolSequencedTaskAndReply( |
2546 FROM_HERE, | 2086 FROM_HERE, |
2547 blocking_task_runner_, | 2087 blocking_task_runner_, |
2548 base::Bind(&GetLocalFileSizeOnBlockingPool, | 2088 base::Bind(&GetLocalFileSizeOnBlockingPool, |
2549 cache_file_path, | 2089 cache_file_path, |
2550 get_size_error, | 2090 get_size_error, |
2551 file_size), | 2091 file_size), |
2552 base::Bind(&GDataFileSystem::OnGetFileSizeCompleteForUpdateFile, | 2092 base::Bind(&GDataFileSystem::OnGetFileSizeCompleteForUpdateFile, |
2553 ui_weak_ptr_, | 2093 ui_weak_ptr_, |
2554 callback, | 2094 callback, |
2555 resource_id, | 2095 resource_id, |
(...skipping 92 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
2648 ui_weak_ptr_, | 2188 ui_weak_ptr_, |
2649 callback)); | 2189 callback)); |
2650 } | 2190 } |
2651 | 2191 |
2652 void GDataFileSystem::OnGetAvailableSpace( | 2192 void GDataFileSystem::OnGetAvailableSpace( |
2653 const GetAvailableSpaceCallback& callback, | 2193 const GetAvailableSpaceCallback& callback, |
2654 GDataErrorCode status, | 2194 GDataErrorCode status, |
2655 scoped_ptr<base::Value> data) { | 2195 scoped_ptr<base::Value> data) { |
2656 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); | 2196 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); |
2657 | 2197 |
2658 GDataFileError error = GDataToGDataFileError(status); | 2198 GDataFileError error = util::GDataToGDataFileError(status); |
2659 if (error != GDATA_FILE_OK) { | 2199 if (error != GDATA_FILE_OK) { |
2660 callback.Run(error, -1, -1); | 2200 callback.Run(error, -1, -1); |
2661 return; | 2201 return; |
2662 } | 2202 } |
2663 | 2203 |
2664 scoped_ptr<AccountMetadataFeed> feed; | 2204 scoped_ptr<AccountMetadataFeed> feed; |
2665 if (data.get()) | 2205 if (data.get()) |
2666 feed = AccountMetadataFeed::CreateFrom(*data); | 2206 feed = AccountMetadataFeed::CreateFrom(*data); |
2667 if (!feed.get()) { | 2207 if (!feed.get()) { |
2668 callback.Run(GDATA_FILE_ERROR_FAILED, -1, -1); | 2208 callback.Run(GDATA_FILE_ERROR_FAILED, -1, -1); |
2669 return; | 2209 return; |
2670 } | 2210 } |
2671 | 2211 |
2672 callback.Run(GDATA_FILE_OK, | 2212 callback.Run(GDATA_FILE_OK, |
2673 feed->quota_bytes_total(), | 2213 feed->quota_bytes_total(), |
2674 feed->quota_bytes_used()); | 2214 feed->quota_bytes_used()); |
2675 } | 2215 } |
2676 | 2216 |
2677 void GDataFileSystem::OnCreateDirectoryCompleted( | 2217 void GDataFileSystem::OnCreateDirectoryCompleted( |
2678 const CreateDirectoryParams& params, | 2218 const CreateDirectoryParams& params, |
2679 GDataErrorCode status, | 2219 GDataErrorCode status, |
2680 scoped_ptr<base::Value> data) { | 2220 scoped_ptr<base::Value> data) { |
2681 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); | 2221 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); |
2682 | 2222 |
2683 GDataFileError error = GDataToGDataFileError(status); | 2223 GDataFileError error = util::GDataToGDataFileError(status); |
2684 if (error != GDATA_FILE_OK) { | 2224 if (error != GDATA_FILE_OK) { |
2685 if (!params.callback.is_null()) | 2225 if (!params.callback.is_null()) |
2686 params.callback.Run(error); | 2226 params.callback.Run(error); |
2687 | 2227 |
2688 return; | 2228 return; |
2689 } | 2229 } |
2690 | 2230 |
2691 base::DictionaryValue* dict_value = NULL; | 2231 base::DictionaryValue* dict_value = NULL; |
2692 base::Value* created_entry = NULL; | 2232 base::Value* created_entry = NULL; |
2693 if (data.get() && data->GetAsDictionary(&dict_value) && dict_value) | 2233 if (data.get() && data->GetAsDictionary(&dict_value) && dict_value) |
(...skipping 121 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
2815 // chunk to avoid displaying huge number of search | 2355 // chunk to avoid displaying huge number of search |
2816 // results (especially since we don't cache them). | 2356 // results (especially since we don't cache them). |
2817 FilePath(), // Not used. | 2357 FilePath(), // Not used. |
2818 search_query, | 2358 search_query, |
2819 next_feed, | 2359 next_feed, |
2820 std::string(), // No directory resource ID. | 2360 std::string(), // No directory resource ID. |
2821 FindEntryCallback(), // Not used. | 2361 FindEntryCallback(), // Not used. |
2822 base::Bind(&GDataFileSystem::OnSearch, ui_weak_ptr_, callback)); | 2362 base::Bind(&GDataFileSystem::OnSearch, ui_weak_ptr_, callback)); |
2823 } | 2363 } |
2824 | 2364 |
2825 void GDataWapiFeedLoader::OnGetDocuments( | |
2826 ContentOrigin initial_origin, | |
2827 const LoadDocumentFeedCallback& callback, | |
2828 GetDocumentsParams* params, | |
2829 base::TimeTicks start_time, | |
2830 GDataErrorCode status, | |
2831 scoped_ptr<base::Value> data) { | |
2832 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); | |
2833 | |
2834 if (params->feed_list->empty()) { | |
2835 UMA_HISTOGRAM_TIMES("Gdata.InitialFeedLoadTime", | |
2836 base::TimeTicks::Now() - start_time); | |
2837 } | |
2838 | |
2839 GDataFileError error = GDataToGDataFileError(status); | |
2840 if (error == GDATA_FILE_OK && | |
2841 (!data.get() || data->GetType() != Value::TYPE_DICTIONARY)) { | |
2842 error = GDATA_FILE_ERROR_FAILED; | |
2843 } | |
2844 | |
2845 if (error != GDATA_FILE_OK) { | |
2846 directory_service_->set_origin(initial_origin); | |
2847 | |
2848 if (!callback.is_null()) | |
2849 callback.Run(params, error); | |
2850 | |
2851 return; | |
2852 } | |
2853 | |
2854 GURL next_feed_url; | |
2855 scoped_ptr<DocumentFeed> current_feed(DocumentFeed::ExtractAndParse(*data)); | |
2856 if (!current_feed.get()) { | |
2857 if (!callback.is_null()) { | |
2858 callback.Run(params, GDATA_FILE_ERROR_FAILED); | |
2859 } | |
2860 | |
2861 return; | |
2862 } | |
2863 const bool has_next_feed_url = current_feed->GetNextFeedURL(&next_feed_url); | |
2864 | |
2865 #ifndef NDEBUG | |
2866 // Save initial root feed for analysis. | |
2867 std::string file_name = | |
2868 base::StringPrintf("DEBUG_feed_%d.json", | |
2869 params->start_changestamp); | |
2870 PostBlockingPoolSequencedTask( | |
2871 FROM_HERE, | |
2872 blocking_task_runner_, | |
2873 base::Bind(&SaveFeedOnBlockingPoolForDebugging, | |
2874 cache_->GetCacheDirectoryPath( | |
2875 GDataCache::CACHE_TYPE_META).Append(file_name), | |
2876 base::Passed(&data))); | |
2877 #endif | |
2878 | |
2879 // Add the current feed to the list of collected feeds for this directory. | |
2880 params->feed_list->push_back(current_feed.release()); | |
2881 | |
2882 // Compute and notify the number of entries fetched so far. | |
2883 int num_accumulated_entries = 0; | |
2884 for (size_t i = 0; i < params->feed_list->size(); ++i) | |
2885 num_accumulated_entries += params->feed_list->at(i)->entries().size(); | |
2886 | |
2887 // Check if we need to collect more data to complete the directory list. | |
2888 if (params->should_fetch_multiple_feeds && has_next_feed_url && | |
2889 !next_feed_url.is_empty()) { | |
2890 // Post an UI update event to make the UI smoother. | |
2891 GetDocumentsUiState* ui_state = params->ui_state.get(); | |
2892 if (ui_state == NULL) { | |
2893 ui_state = new GetDocumentsUiState(base::TimeTicks::Now()); | |
2894 params->ui_state.reset(ui_state); | |
2895 } | |
2896 DCHECK(ui_state); | |
2897 | |
2898 if ((ui_state->num_fetched_documents - ui_state->num_showing_documents) | |
2899 < kFetchUiUpdateStep) { | |
2900 // Currently the UI update is stopped. Start UI periodic callback. | |
2901 MessageLoop::current()->PostTask( | |
2902 FROM_HERE, | |
2903 base::Bind(&GDataWapiFeedLoader::OnNotifyDocumentFeedFetched, | |
2904 weak_ptr_factory_.GetWeakPtr(), | |
2905 ui_state->weak_ptr_factory.GetWeakPtr())); | |
2906 } | |
2907 ui_state->num_fetched_documents = num_accumulated_entries; | |
2908 ui_state->feed_fetching_elapsed_time = base::TimeTicks::Now() - start_time; | |
2909 | |
2910 // Kick of the remaining part of the feeds. | |
2911 documents_service_->GetDocuments( | |
2912 next_feed_url, | |
2913 params->start_changestamp, | |
2914 params->search_query, | |
2915 params->directory_resource_id, | |
2916 base::Bind(&GDataWapiFeedLoader::OnGetDocuments, | |
2917 weak_ptr_factory_.GetWeakPtr(), | |
2918 initial_origin, | |
2919 callback, | |
2920 base::Owned( | |
2921 new GetDocumentsParams( | |
2922 params->start_changestamp, | |
2923 params->root_feed_changestamp, | |
2924 params->feed_list.release(), | |
2925 params->should_fetch_multiple_feeds, | |
2926 params->search_file_path, | |
2927 params->search_query, | |
2928 params->directory_resource_id, | |
2929 params->callback, | |
2930 params->ui_state.release())), | |
2931 start_time)); | |
2932 return; | |
2933 } | |
2934 | |
2935 // Notify the observers that a document feed is fetched. | |
2936 FOR_EACH_OBSERVER(Observer, observers_, | |
2937 OnDocumentFeedFetched(num_accumulated_entries)); | |
2938 | |
2939 UMA_HISTOGRAM_TIMES("Gdata.EntireFeedLoadTime", | |
2940 base::TimeTicks::Now() - start_time); | |
2941 | |
2942 if (!callback.is_null()) | |
2943 callback.Run(params, error); | |
2944 } | |
2945 | |
2946 void GDataWapiFeedLoader::OnNotifyDocumentFeedFetched( | |
2947 base::WeakPtr<GetDocumentsUiState> ui_state) { | |
2948 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); | |
2949 | |
2950 if (!ui_state) { | |
2951 // The ui state instance is already released, which means the fetching | |
2952 // is done and we don't need to update any more. | |
2953 return; | |
2954 } | |
2955 | |
2956 base::TimeDelta elapsed_time = | |
2957 base::TimeTicks::Now() - ui_state->start_time; | |
2958 | |
2959 if (ui_state->num_showing_documents + kFetchUiUpdateStep <= | |
2960 ui_state->num_fetched_documents) { | |
2961 ui_state->num_showing_documents += kFetchUiUpdateStep; | |
2962 FOR_EACH_OBSERVER(Observer, observers_, | |
2963 OnDocumentFeedFetched(ui_state->num_showing_documents)); | |
2964 | |
2965 int num_remaining_ui_updates = | |
2966 (ui_state->num_fetched_documents - ui_state->num_showing_documents) | |
2967 / kFetchUiUpdateStep; | |
2968 if (num_remaining_ui_updates > 0) { | |
2969 // Heuristically, we use fetched time duration to calculate the next | |
2970 // UI update timing. | |
2971 base::TimeDelta remaining_duration = | |
2972 ui_state->feed_fetching_elapsed_time - elapsed_time; | |
2973 MessageLoop::current()->PostDelayedTask( | |
2974 FROM_HERE, | |
2975 base::Bind(&GDataWapiFeedLoader::OnNotifyDocumentFeedFetched, | |
2976 weak_ptr_factory_.GetWeakPtr(), | |
2977 ui_state->weak_ptr_factory.GetWeakPtr()), | |
2978 remaining_duration / num_remaining_ui_updates); | |
2979 } | |
2980 } | |
2981 } | |
2982 | |
2983 void GDataWapiFeedLoader::LoadFromCache( | |
2984 bool should_load_from_server, | |
2985 const FilePath& search_file_path, | |
2986 const FindEntryCallback& callback) { | |
2987 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); | |
2988 | |
2989 LoadRootFeedParams* params = new LoadRootFeedParams(search_file_path, | |
2990 should_load_from_server, | |
2991 callback); | |
2992 FilePath path = cache_->GetCacheDirectoryPath(GDataCache::CACHE_TYPE_META); | |
2993 if (UseLevelDB()) { | |
2994 path = path.Append(kResourceMetadataDBFile); | |
2995 directory_service_->InitFromDB(path, blocking_task_runner_, | |
2996 base::Bind( | |
2997 &GDataWapiFeedLoader::ContinueWithInitializedDirectoryService, | |
2998 weak_ptr_factory_.GetWeakPtr(), | |
2999 base::Owned(params))); | |
3000 } else { | |
3001 path = path.Append(kFilesystemProtoFile); | |
3002 BrowserThread::GetBlockingPool()->PostTaskAndReply(FROM_HERE, | |
3003 base::Bind(&LoadProtoOnBlockingPool, path, params), | |
3004 base::Bind(&GDataWapiFeedLoader::OnProtoLoaded, | |
3005 weak_ptr_factory_.GetWeakPtr(), | |
3006 base::Owned(params))); | |
3007 } | |
3008 } | |
3009 | |
3010 void GDataFileSystem::OnDirectoryChanged(const FilePath& directory_path) { | 2365 void GDataFileSystem::OnDirectoryChanged(const FilePath& directory_path) { |
3011 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); | 2366 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); |
3012 | 2367 |
3013 FOR_EACH_OBSERVER(GDataFileSystemInterface::Observer, observers_, | 2368 FOR_EACH_OBSERVER(GDataFileSystemInterface::Observer, observers_, |
3014 OnDirectoryChanged(directory_path)); | 2369 OnDirectoryChanged(directory_path)); |
3015 } | 2370 } |
3016 | 2371 |
3017 void GDataFileSystem::OnDocumentFeedFetched(int num_accumulated_entries) { | 2372 void GDataFileSystem::OnDocumentFeedFetched(int num_accumulated_entries) { |
3018 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); | 2373 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); |
3019 | 2374 |
(...skipping 22 matching lines...) Expand all Loading... |
3042 const std::vector<DocumentFeed*>& feed_list, | 2397 const std::vector<DocumentFeed*>& feed_list, |
3043 int start_changestamp, | 2398 int start_changestamp, |
3044 int root_feed_changestamp) { | 2399 int root_feed_changestamp) { |
3045 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); | 2400 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); |
3046 | 2401 |
3047 return feed_loader_->UpdateFromFeed(feed_list, | 2402 return feed_loader_->UpdateFromFeed(feed_list, |
3048 start_changestamp, | 2403 start_changestamp, |
3049 root_feed_changestamp); | 2404 root_feed_changestamp); |
3050 } | 2405 } |
3051 | 2406 |
3052 void GDataWapiFeedLoader::OnProtoLoaded(LoadRootFeedParams* params) { | |
3053 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); | |
3054 | |
3055 // If we have already received updates from the server, bail out. | |
3056 if (directory_service_->origin() == FROM_SERVER) | |
3057 return; | |
3058 | |
3059 // Update directory structure only if everything is OK and we haven't yet | |
3060 // received the feed from the server yet. | |
3061 if (params->load_error == GDATA_FILE_OK) { | |
3062 DVLOG(1) << "ParseFromString"; | |
3063 if (directory_service_->ParseFromString(params->proto)) { | |
3064 directory_service_->set_last_serialized(params->last_modified); | |
3065 directory_service_->set_serialized_size(params->proto.size()); | |
3066 } else { | |
3067 params->load_error = GDATA_FILE_ERROR_FAILED; | |
3068 LOG(WARNING) << "Parse of cached proto file failed"; | |
3069 } | |
3070 } | |
3071 | |
3072 ContinueWithInitializedDirectoryService(params, params->load_error); | |
3073 } | |
3074 | |
3075 void GDataWapiFeedLoader::ContinueWithInitializedDirectoryService( | |
3076 LoadRootFeedParams* params, | |
3077 GDataFileError error) { | |
3078 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); | |
3079 | |
3080 DVLOG(1) << "Time elapsed to load directory service from disk=" | |
3081 << (base::Time::Now() - params->load_start_time).InMilliseconds() | |
3082 << " milliseconds"; | |
3083 | |
3084 FindEntryCallback callback = params->callback; | |
3085 // If we got feed content from cache, try search over it. | |
3086 if (error == GDATA_FILE_OK && !callback.is_null()) { | |
3087 // Continue file content search operation if the delegate hasn't terminated | |
3088 // this search branch already. | |
3089 directory_service_->FindEntryByPathAndRunSync(params->search_file_path, | |
3090 callback); | |
3091 callback.Reset(); | |
3092 } | |
3093 | |
3094 if (!params->should_load_from_server) | |
3095 return; | |
3096 | |
3097 // Decide the |initial_origin| to pass to ReloadFromServerIfNeeded(). | |
3098 // This is used to restore directory content origin to its initial value when | |
3099 // we fail to retrieve the feed from server. | |
3100 // By default, if directory content is not yet initialized, restore content | |
3101 // origin to UNINITIALIZED in case of failure. | |
3102 ContentOrigin initial_origin = UNINITIALIZED; | |
3103 if (directory_service_->origin() != INITIALIZING) { | |
3104 // If directory content is already initialized, restore content origin | |
3105 // to FROM_CACHE in case of failure. | |
3106 initial_origin = FROM_CACHE; | |
3107 directory_service_->set_origin(REFRESHING); | |
3108 } | |
3109 | |
3110 // Kick of the retrieval of the feed from server. If we have previously | |
3111 // |reported| to the original callback, then we just need to refresh the | |
3112 // content without continuing search upon operation completion. | |
3113 ReloadFromServerIfNeeded(initial_origin, | |
3114 directory_service_->largest_changestamp(), | |
3115 params->search_file_path, | |
3116 callback); | |
3117 } | |
3118 | |
3119 void GDataWapiFeedLoader::SaveFileSystem() { | |
3120 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); | |
3121 | |
3122 if (!ShouldSerializeFileSystemNow(directory_service_->serialized_size(), | |
3123 directory_service_->last_serialized())) { | |
3124 return; | |
3125 } | |
3126 | |
3127 if (UseLevelDB()) { | |
3128 directory_service_->SaveToDB(); | |
3129 } else { | |
3130 const FilePath path = | |
3131 cache_->GetCacheDirectoryPath(GDataCache::CACHE_TYPE_META).Append( | |
3132 kFilesystemProtoFile); | |
3133 scoped_ptr<std::string> serialized_proto(new std::string()); | |
3134 directory_service_->SerializeToString(serialized_proto.get()); | |
3135 directory_service_->set_last_serialized(base::Time::Now()); | |
3136 directory_service_->set_serialized_size(serialized_proto->size()); | |
3137 PostBlockingPoolSequencedTask( | |
3138 FROM_HERE, | |
3139 blocking_task_runner_, | |
3140 base::Bind(&SaveProtoOnBlockingPool, path, | |
3141 base::Passed(serialized_proto.Pass()))); | |
3142 } | |
3143 } | |
3144 | |
3145 void GDataFileSystem::OnFilePathUpdated(const FileOperationCallback& callback, | 2407 void GDataFileSystem::OnFilePathUpdated(const FileOperationCallback& callback, |
3146 GDataFileError error, | 2408 GDataFileError error, |
3147 const FilePath& file_path) { | 2409 const FilePath& file_path) { |
3148 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); | 2410 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); |
3149 if (!callback.is_null()) | 2411 if (!callback.is_null()) |
3150 callback.Run(error); | 2412 callback.Run(error); |
3151 } | 2413 } |
3152 | 2414 |
3153 void GDataFileSystem::OnRenameResourceCompleted( | 2415 void GDataFileSystem::OnRenameResourceCompleted( |
3154 const FilePath& file_path, | 2416 const FilePath& file_path, |
3155 const FilePath::StringType& new_name, | 2417 const FilePath::StringType& new_name, |
3156 const FilePathUpdateCallback& callback, | 2418 const FilePathUpdateCallback& callback, |
3157 GDataErrorCode status, | 2419 GDataErrorCode status, |
3158 const GURL& document_url) { | 2420 const GURL& document_url) { |
3159 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); | 2421 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); |
3160 | 2422 |
3161 FilePath updated_file_path; | 2423 FilePath updated_file_path; |
3162 GDataFileError error = GDataToGDataFileError(status); | 2424 GDataFileError error = util::GDataToGDataFileError(status); |
3163 if (error == GDATA_FILE_OK) | 2425 if (error == GDATA_FILE_OK) |
3164 error = RenameFileOnFilesystem(file_path, new_name, &updated_file_path); | 2426 error = RenameFileOnFilesystem(file_path, new_name, &updated_file_path); |
3165 | 2427 |
3166 if (!callback.is_null()) | 2428 if (!callback.is_null()) |
3167 callback.Run(error, updated_file_path); | 2429 callback.Run(error, updated_file_path); |
3168 } | 2430 } |
3169 | 2431 |
3170 void GDataFileSystem::OnCopyDocumentCompleted( | 2432 void GDataFileSystem::OnCopyDocumentCompleted( |
3171 const FilePath& dir_path, | 2433 const FilePath& dir_path, |
3172 const FileOperationCallback& callback, | 2434 const FileOperationCallback& callback, |
3173 GDataErrorCode status, | 2435 GDataErrorCode status, |
3174 scoped_ptr<base::Value> data) { | 2436 scoped_ptr<base::Value> data) { |
3175 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); | 2437 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); |
3176 | 2438 |
3177 GDataFileError error = GDataToGDataFileError(status); | 2439 GDataFileError error = util::GDataToGDataFileError(status); |
3178 if (error != GDATA_FILE_OK) { | 2440 if (error != GDATA_FILE_OK) { |
3179 if (!callback.is_null()) | 2441 if (!callback.is_null()) |
3180 callback.Run(error); | 2442 callback.Run(error); |
3181 | 2443 |
3182 return; | 2444 return; |
3183 } | 2445 } |
3184 | 2446 |
3185 scoped_ptr<DocumentEntry> doc_entry(DocumentEntry::ExtractAndParse(*data)); | 2447 scoped_ptr<DocumentEntry> doc_entry(DocumentEntry::ExtractAndParse(*data)); |
3186 if (!doc_entry.get()) { | 2448 if (!doc_entry.get()) { |
3187 if (!callback.is_null()) | 2449 if (!callback.is_null()) |
(...skipping 19 matching lines...) Expand all Loading... |
3207 } | 2469 } |
3208 | 2470 |
3209 void GDataFileSystem::OnAddEntryToDirectoryCompleted( | 2471 void GDataFileSystem::OnAddEntryToDirectoryCompleted( |
3210 const FileOperationCallback& callback, | 2472 const FileOperationCallback& callback, |
3211 const FilePath& file_path, | 2473 const FilePath& file_path, |
3212 const FilePath& dir_path, | 2474 const FilePath& dir_path, |
3213 GDataErrorCode status, | 2475 GDataErrorCode status, |
3214 const GURL& document_url) { | 2476 const GURL& document_url) { |
3215 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); | 2477 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); |
3216 | 2478 |
3217 GDataFileError error = GDataToGDataFileError(status); | 2479 GDataFileError error = util::GDataToGDataFileError(status); |
3218 if (error == GDATA_FILE_OK) { | 2480 if (error == GDATA_FILE_OK) { |
3219 GDataEntry* entry = directory_service_->FindEntryByPathSync(file_path); | 2481 GDataEntry* entry = directory_service_->FindEntryByPathSync(file_path); |
3220 if (entry) { | 2482 if (entry) { |
3221 DCHECK_EQ(directory_service_->root(), entry->parent()); | 2483 DCHECK_EQ(directory_service_->root(), entry->parent()); |
3222 error = AddEntryToDirectoryOnFilesystem(entry, dir_path); | 2484 error = AddEntryToDirectoryOnFilesystem(entry, dir_path); |
3223 } else { | 2485 } else { |
3224 error = GDATA_FILE_ERROR_NOT_FOUND; | 2486 error = GDATA_FILE_ERROR_NOT_FOUND; |
3225 } | 2487 } |
3226 } | 2488 } |
3227 | 2489 |
3228 if (!callback.is_null()) | 2490 if (!callback.is_null()) |
3229 callback.Run(error); | 2491 callback.Run(error); |
3230 } | 2492 } |
3231 | 2493 |
3232 void GDataFileSystem::OnRemoveEntryFromDirectoryCompleted( | 2494 void GDataFileSystem::OnRemoveEntryFromDirectoryCompleted( |
3233 const FilePathUpdateCallback& callback, | 2495 const FilePathUpdateCallback& callback, |
3234 const FilePath& file_path, | 2496 const FilePath& file_path, |
3235 const FilePath& dir_path, | 2497 const FilePath& dir_path, |
3236 GDataErrorCode status, | 2498 GDataErrorCode status, |
3237 const GURL& document_url) { | 2499 const GURL& document_url) { |
3238 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); | 2500 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); |
3239 | 2501 |
3240 FilePath updated_file_path = file_path; | 2502 FilePath updated_file_path = file_path; |
3241 GDataFileError error = GDataToGDataFileError(status); | 2503 GDataFileError error = util::GDataToGDataFileError(status); |
3242 if (error == GDATA_FILE_OK) | 2504 if (error == GDATA_FILE_OK) |
3243 error = RemoveEntryFromDirectoryOnFilesystem(file_path, dir_path, | 2505 error = RemoveEntryFromDirectoryOnFilesystem(file_path, dir_path, |
3244 &updated_file_path); | 2506 &updated_file_path); |
3245 | 2507 |
3246 if (!callback.is_null()) | 2508 if (!callback.is_null()) |
3247 callback.Run(error, updated_file_path); | 2509 callback.Run(error, updated_file_path); |
3248 } | 2510 } |
3249 | 2511 |
3250 void GDataFileSystem::OnRemovedDocument( | 2512 void GDataFileSystem::OnRemovedDocument( |
3251 const FileOperationCallback& callback, | 2513 const FileOperationCallback& callback, |
3252 const FilePath& file_path, | 2514 const FilePath& file_path, |
3253 GDataErrorCode status, | 2515 GDataErrorCode status, |
3254 const GURL& document_url) { | 2516 const GURL& document_url) { |
3255 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); | 2517 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); |
3256 | 2518 |
3257 GDataFileError error = GDataToGDataFileError(status); | 2519 GDataFileError error = util::GDataToGDataFileError(status); |
3258 | 2520 |
3259 if (error == GDATA_FILE_OK) | 2521 if (error == GDATA_FILE_OK) |
3260 error = RemoveEntryFromFileSystem(file_path); | 2522 error = RemoveEntryFromFileSystem(file_path); |
3261 | 2523 |
3262 if (!callback.is_null()) { | 2524 if (!callback.is_null()) { |
3263 callback.Run(error); | 2525 callback.Run(error); |
3264 } | 2526 } |
3265 } | 2527 } |
3266 | 2528 |
3267 void GDataFileSystem::OnFileDownloaded( | 2529 void GDataFileSystem::OnFileDownloaded( |
(...skipping 17 matching lines...) Expand all Loading... |
3285 | 2547 |
3286 // At this point, the disk can be full or nearly full for several reasons: | 2548 // At this point, the disk can be full or nearly full for several reasons: |
3287 // - The expected file size was incorrect and the file was larger | 2549 // - The expected file size was incorrect and the file was larger |
3288 // - There was an in-flight download operation and it used up space | 2550 // - There was an in-flight download operation and it used up space |
3289 // - The disk became full for some user actions we cannot control | 2551 // - The disk became full for some user actions we cannot control |
3290 // (ex. the user might have downloaded a large file from a regular web site) | 2552 // (ex. the user might have downloaded a large file from a regular web site) |
3291 // | 2553 // |
3292 // If we don't have enough space, we return PLATFORM_FILE_ERROR_NO_SPACE, | 2554 // If we don't have enough space, we return PLATFORM_FILE_ERROR_NO_SPACE, |
3293 // and try to free up space, even if the file was downloaded successfully. | 2555 // and try to free up space, even if the file was downloaded successfully. |
3294 bool* has_enough_space = new bool(false); | 2556 bool* has_enough_space = new bool(false); |
3295 PostBlockingPoolSequencedTaskAndReply( | 2557 util::PostBlockingPoolSequencedTaskAndReply( |
3296 FROM_HERE, | 2558 FROM_HERE, |
3297 blocking_task_runner_, | 2559 blocking_task_runner_, |
3298 base::Bind(&GDataCache::FreeDiskSpaceIfNeededFor, | 2560 base::Bind(&GDataCache::FreeDiskSpaceIfNeededFor, |
3299 base::Unretained(cache_), | 2561 base::Unretained(cache_), |
3300 0, | 2562 0, |
3301 has_enough_space), | 2563 has_enough_space), |
3302 base::Bind(&GDataFileSystem::OnFileDownloadedAndSpaceChecked, | 2564 base::Bind(&GDataFileSystem::OnFileDownloadedAndSpaceChecked, |
3303 ui_weak_ptr_, | 2565 ui_weak_ptr_, |
3304 params, | 2566 params, |
3305 status, | 2567 status, |
(...skipping 15 matching lines...) Expand all Loading... |
3321 } | 2583 } |
3322 | 2584 |
3323 void GDataFileSystem::OnFileDownloadedAndSpaceChecked( | 2585 void GDataFileSystem::OnFileDownloadedAndSpaceChecked( |
3324 const GetFileFromCacheParams& params, | 2586 const GetFileFromCacheParams& params, |
3325 GDataErrorCode status, | 2587 GDataErrorCode status, |
3326 const GURL& content_url, | 2588 const GURL& content_url, |
3327 const FilePath& downloaded_file_path, | 2589 const FilePath& downloaded_file_path, |
3328 bool* has_enough_space) { | 2590 bool* has_enough_space) { |
3329 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); | 2591 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); |
3330 | 2592 |
3331 GDataFileError error = GDataToGDataFileError(status); | 2593 GDataFileError error = util::GDataToGDataFileError(status); |
3332 | 2594 |
3333 // Make sure that downloaded file is properly stored in cache. We don't have | 2595 // Make sure that downloaded file is properly stored in cache. We don't have |
3334 // to wait for this operation to finish since the user can already use the | 2596 // to wait for this operation to finish since the user can already use the |
3335 // downloaded file. | 2597 // downloaded file. |
3336 if (error == GDATA_FILE_OK) { | 2598 if (error == GDATA_FILE_OK) { |
3337 if (*has_enough_space) { | 2599 if (*has_enough_space) { |
3338 cache_->StoreOnUIThread( | 2600 cache_->StoreOnUIThread( |
3339 params.resource_id, | 2601 params.resource_id, |
3340 params.md5, | 2602 params.md5, |
3341 downloaded_file_path, | 2603 downloaded_file_path, |
3342 GDataCache::FILE_OPERATION_MOVE, | 2604 GDataCache::FILE_OPERATION_MOVE, |
3343 base::Bind(&GDataFileSystem::OnDownloadStoredToCache, | 2605 base::Bind(&GDataFileSystem::OnDownloadStoredToCache, |
3344 ui_weak_ptr_)); | 2606 ui_weak_ptr_)); |
3345 } else { | 2607 } else { |
3346 // If we don't have enough space, remove the downloaded file, and | 2608 // If we don't have enough space, remove the downloaded file, and |
3347 // report "no space" error. | 2609 // report "no space" error. |
3348 PostBlockingPoolSequencedTask( | 2610 util::PostBlockingPoolSequencedTask( |
3349 FROM_HERE, | 2611 FROM_HERE, |
3350 blocking_task_runner_, | 2612 blocking_task_runner_, |
3351 base::Bind(base::IgnoreResult(&file_util::Delete), | 2613 base::Bind(base::IgnoreResult(&file_util::Delete), |
3352 downloaded_file_path, | 2614 downloaded_file_path, |
3353 false /* recursive*/)); | 2615 false /* recursive*/)); |
3354 error = GDATA_FILE_ERROR_NO_SPACE; | 2616 error = GDATA_FILE_ERROR_NO_SPACE; |
3355 } | 2617 } |
3356 } | 2618 } |
3357 | 2619 |
3358 if (!params.get_file_callback.is_null()) { | 2620 if (!params.get_file_callback.is_null()) { |
(...skipping 100 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
3459 if (error != GDATA_FILE_OK) | 2721 if (error != GDATA_FILE_OK) |
3460 return error; | 2722 return error; |
3461 | 2723 |
3462 // If resource_id is not empty, remove its corresponding file from cache. | 2724 // If resource_id is not empty, remove its corresponding file from cache. |
3463 if (!resource_id.empty()) | 2725 if (!resource_id.empty()) |
3464 cache_->RemoveOnUIThread(resource_id, CacheOperationCallback()); | 2726 cache_->RemoveOnUIThread(resource_id, CacheOperationCallback()); |
3465 | 2727 |
3466 return GDATA_FILE_OK; | 2728 return GDATA_FILE_OK; |
3467 } | 2729 } |
3468 | 2730 |
3469 GDataFileError GDataWapiFeedLoader::UpdateFromFeed( | |
3470 const std::vector<DocumentFeed*>& feed_list, | |
3471 int start_changestamp, | |
3472 int root_feed_changestamp) { | |
3473 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); | |
3474 DVLOG(1) << "Updating directory with a feed"; | |
3475 | |
3476 std::set<FilePath> changed_dirs; | |
3477 | |
3478 GDataWapiFeedProcessor feed_processor(directory_service_); | |
3479 const GDataFileError error = feed_processor.ApplyFeeds( | |
3480 feed_list, | |
3481 start_changestamp, | |
3482 root_feed_changestamp, | |
3483 &changed_dirs); | |
3484 | |
3485 // Don't send directory content change notification while performing | |
3486 // the initial content retrieval. | |
3487 const bool should_notify_directory_changed = (start_changestamp != 0); | |
3488 if (should_notify_directory_changed) { | |
3489 for (std::set<FilePath>::iterator dir_iter = changed_dirs.begin(); | |
3490 dir_iter != changed_dirs.end(); ++dir_iter) { | |
3491 FOR_EACH_OBSERVER(Observer, observers_, | |
3492 OnDirectoryChanged(*dir_iter)); | |
3493 } | |
3494 } | |
3495 | |
3496 return error; | |
3497 } | |
3498 | |
3499 | |
3500 // static | 2731 // static |
3501 void GDataFileSystem::RemoveStaleEntryOnUpload(const std::string& resource_id, | 2732 void GDataFileSystem::RemoveStaleEntryOnUpload(const std::string& resource_id, |
3502 GDataDirectory* parent_dir, | 2733 GDataDirectory* parent_dir, |
3503 GDataEntry* existing_entry) { | 2734 GDataEntry* existing_entry) { |
3504 if (existing_entry && | 2735 if (existing_entry && |
3505 // This should always match, but just in case. | 2736 // This should always match, but just in case. |
3506 existing_entry->parent() == parent_dir) { | 2737 existing_entry->parent() == parent_dir) { |
3507 parent_dir->RemoveEntry(existing_entry); | 2738 parent_dir->RemoveEntry(existing_entry); |
3508 } else { | 2739 } else { |
3509 LOG(ERROR) << "Entry for the existing file not found: " << resource_id; | 2740 LOG(ERROR) << "Entry for the existing file not found: " << resource_id; |
(...skipping 467 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
3977 if (error != GDATA_FILE_OK) { | 3208 if (error != GDATA_FILE_OK) { |
3978 if (!callback.is_null()) | 3209 if (!callback.is_null()) |
3979 callback.Run(error); | 3210 callback.Run(error); |
3980 return; | 3211 return; |
3981 } | 3212 } |
3982 | 3213 |
3983 // Step 3 of CloseFile: Retrieves the (possibly modified) PlatformFileInfo of | 3214 // Step 3 of CloseFile: Retrieves the (possibly modified) PlatformFileInfo of |
3984 // the cache file. | 3215 // the cache file. |
3985 base::PlatformFileInfo* file_info = new base::PlatformFileInfo; | 3216 base::PlatformFileInfo* file_info = new base::PlatformFileInfo; |
3986 bool* get_file_info_result = new bool(false); | 3217 bool* get_file_info_result = new bool(false); |
3987 PostBlockingPoolSequencedTaskAndReply( | 3218 util::PostBlockingPoolSequencedTaskAndReply( |
3988 FROM_HERE, | 3219 FROM_HERE, |
3989 blocking_task_runner_, | 3220 blocking_task_runner_, |
3990 base::Bind(&GetFileInfoOnBlockingPool, | 3221 base::Bind(&GetFileInfoOnBlockingPool, |
3991 local_cache_path, | 3222 local_cache_path, |
3992 base::Unretained(file_info), | 3223 base::Unretained(file_info), |
3993 base::Unretained(get_file_info_result)), | 3224 base::Unretained(get_file_info_result)), |
3994 base::Bind(&GDataFileSystem::OnGetModifiedFileInfoCompleteForCloseFile, | 3225 base::Bind(&GDataFileSystem::OnGetModifiedFileInfoCompleteForCloseFile, |
3995 ui_weak_ptr_, | 3226 ui_weak_ptr_, |
3996 file_path, | 3227 file_path, |
3997 base::Owned(file_info), | 3228 base::Owned(file_info), |
(...skipping 160 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
4158 // When no dirty cache is found, use the original entry info as is. | 3389 // When no dirty cache is found, use the original entry info as is. |
4159 if (error != GDATA_FILE_OK) { | 3390 if (error != GDATA_FILE_OK) { |
4160 if (!callback.is_null()) | 3391 if (!callback.is_null()) |
4161 callback.Run(GDATA_FILE_OK, entry_proto.Pass()); | 3392 callback.Run(GDATA_FILE_OK, entry_proto.Pass()); |
4162 return; | 3393 return; |
4163 } | 3394 } |
4164 | 3395 |
4165 // If the cache is dirty, obtain the file info from the cache file itself. | 3396 // If the cache is dirty, obtain the file info from the cache file itself. |
4166 base::PlatformFileInfo* file_info = new base::PlatformFileInfo; | 3397 base::PlatformFileInfo* file_info = new base::PlatformFileInfo; |
4167 bool* get_file_info_result = new bool(false); | 3398 bool* get_file_info_result = new bool(false); |
4168 PostBlockingPoolSequencedTaskAndReply( | 3399 util::PostBlockingPoolSequencedTaskAndReply( |
4169 FROM_HERE, | 3400 FROM_HERE, |
4170 blocking_task_runner_, | 3401 blocking_task_runner_, |
4171 base::Bind(&GetFileInfoOnBlockingPool, | 3402 base::Bind(&GetFileInfoOnBlockingPool, |
4172 local_cache_path, | 3403 local_cache_path, |
4173 base::Unretained(file_info), | 3404 base::Unretained(file_info), |
4174 base::Unretained(get_file_info_result)), | 3405 base::Unretained(get_file_info_result)), |
4175 base::Bind(&GDataFileSystem::CheckLocalModificationAndRunAfterGetFileInfo, | 3406 base::Bind(&GDataFileSystem::CheckLocalModificationAndRunAfterGetFileInfo, |
4176 ui_weak_ptr_, | 3407 ui_weak_ptr_, |
4177 base::Passed(&entry_proto), | 3408 base::Passed(&entry_proto), |
4178 callback, | 3409 callback, |
(...skipping 15 matching lines...) Expand all Loading... |
4194 } | 3425 } |
4195 | 3426 |
4196 PlatformFileInfoProto entry_file_info; | 3427 PlatformFileInfoProto entry_file_info; |
4197 GDataEntry::ConvertPlatformFileInfoToProto(*file_info, &entry_file_info); | 3428 GDataEntry::ConvertPlatformFileInfoToProto(*file_info, &entry_file_info); |
4198 *entry_proto->mutable_file_info() = entry_file_info; | 3429 *entry_proto->mutable_file_info() = entry_file_info; |
4199 if (!callback.is_null()) | 3430 if (!callback.is_null()) |
4200 callback.Run(GDATA_FILE_OK, entry_proto.Pass()); | 3431 callback.Run(GDATA_FILE_OK, entry_proto.Pass()); |
4201 } | 3432 } |
4202 | 3433 |
4203 } // namespace gdata | 3434 } // namespace gdata |
OLD | NEW |