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 <errno.h> | 7 #include <errno.h> |
8 #include <sys/stat.h> | 8 #include <sys/stat.h> |
9 | 9 |
10 #include <set> | 10 #include <set> |
(...skipping 844 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
855 | 855 |
856 GDataFileProperties::~GDataFileProperties() { | 856 GDataFileProperties::~GDataFileProperties() { |
857 } | 857 } |
858 | 858 |
859 // GDataFileSystem::GetDocumentsParams struct implementation. | 859 // GDataFileSystem::GetDocumentsParams struct implementation. |
860 | 860 |
861 GDataFileSystem::GetDocumentsParams::GetDocumentsParams( | 861 GDataFileSystem::GetDocumentsParams::GetDocumentsParams( |
862 int start_changestamp, | 862 int start_changestamp, |
863 int root_feed_changestamp, | 863 int root_feed_changestamp, |
864 std::vector<DocumentFeed*>* feed_list, | 864 std::vector<DocumentFeed*>* feed_list, |
865 bool should_fetch_multiple_feeds, | |
865 const FilePath& search_file_path, | 866 const FilePath& search_file_path, |
867 const std::string& search_query, | |
866 const FindEntryCallback& callback) | 868 const FindEntryCallback& callback) |
867 : start_changestamp(start_changestamp), | 869 : start_changestamp(start_changestamp), |
868 root_feed_changestamp(root_feed_changestamp), | 870 root_feed_changestamp(root_feed_changestamp), |
869 feed_list(feed_list), | 871 feed_list(feed_list), |
872 should_fetch_multiple_feeds(should_fetch_multiple_feeds), | |
870 search_file_path(search_file_path), | 873 search_file_path(search_file_path), |
874 search_query(search_query), | |
871 callback(callback) { | 875 callback(callback) { |
872 } | 876 } |
873 | 877 |
874 GDataFileSystem::GetDocumentsParams::~GetDocumentsParams() { | 878 GDataFileSystem::GetDocumentsParams::~GetDocumentsParams() { |
875 STLDeleteElements(feed_list.get()); | 879 STLDeleteElements(feed_list.get()); |
876 } | 880 } |
877 | 881 |
878 // GDataFileSystem::CreateDirectoryParams struct implementation. | 882 // GDataFileSystem::CreateDirectoryParams struct implementation. |
879 | 883 |
880 GDataFileSystem::CreateDirectoryParams::CreateDirectoryParams( | 884 GDataFileSystem::CreateDirectoryParams::CreateDirectoryParams( |
(...skipping 240 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
1121 int local_changestamp, | 1125 int local_changestamp, |
1122 const FilePath& search_file_path, | 1126 const FilePath& search_file_path, |
1123 const FindEntryCallback& callback, | 1127 const FindEntryCallback& callback, |
1124 GDataErrorCode status, | 1128 GDataErrorCode status, |
1125 scoped_ptr<base::Value> feed_data) { | 1129 scoped_ptr<base::Value> feed_data) { |
1126 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); | 1130 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); |
1127 | 1131 |
1128 base::PlatformFileError error = GDataToPlatformError(status); | 1132 base::PlatformFileError error = GDataToPlatformError(status); |
1129 if (error != base::PLATFORM_FILE_OK) { | 1133 if (error != base::PLATFORM_FILE_OK) { |
1130 // Get changes starting from the next changestamp from what we have locally. | 1134 // Get changes starting from the next changestamp from what we have locally. |
1131 LoadFeedFromServer(local_changestamp + 1, 0, search_file_path, callback); | 1135 LoadFeedFromServer(local_changestamp + 1, 0, |
1136 true, | |
1137 search_file_path, | |
1138 std::string() /* no search query*/, | |
Ben Chan
2012/05/03 22:47:39
nit: one space before */
tbarzic
2012/05/03 23:56:17
Done.
| |
1139 callback, | |
1140 base::Bind(&GDataFileSystem::OnFeedFromServerLoaded, | |
1141 ui_weak_ptr_)); | |
1132 return; | 1142 return; |
1133 } | 1143 } |
1134 | 1144 |
1135 scoped_ptr<AccountMetadataFeed> feed; | 1145 scoped_ptr<AccountMetadataFeed> feed; |
1136 if (feed_data.get()) | 1146 if (feed_data.get()) |
1137 feed = AccountMetadataFeed::CreateFrom(*feed_data); | 1147 feed = AccountMetadataFeed::CreateFrom(*feed_data); |
1138 if (!feed.get()) { | 1148 if (!feed.get()) { |
1139 LoadFeedFromServer(local_changestamp + 1, 0, search_file_path, callback); | 1149 LoadFeedFromServer(local_changestamp + 1, 0, |
1150 true, | |
1151 search_file_path, | |
1152 std::string() /* no search query*/, | |
Ben Chan
2012/05/03 22:47:39
nit: one space before */
tbarzic
2012/05/03 23:56:17
Done.
| |
1153 callback, | |
1154 base::Bind(&GDataFileSystem::OnFeedFromServerLoaded, | |
1155 ui_weak_ptr_)); | |
1140 return; | 1156 return; |
1141 } | 1157 } |
1142 | 1158 |
1143 bool changes_detected = true; | 1159 bool changes_detected = true; |
1144 if (local_changestamp >= feed->largest_changestamp()) { | 1160 if (local_changestamp >= feed->largest_changestamp()) { |
1145 if (local_changestamp > feed->largest_changestamp()) { | 1161 if (local_changestamp > feed->largest_changestamp()) { |
1146 LOG(WARNING) << "Cached client feed is fresher than server, client = " | 1162 LOG(WARNING) << "Cached client feed is fresher than server, client = " |
1147 << local_changestamp | 1163 << local_changestamp |
1148 << ", server = " | 1164 << ", server = " |
1149 << feed->largest_changestamp(); | 1165 << feed->largest_changestamp(); |
(...skipping 13 matching lines...) Expand all Loading... | |
1163 | 1179 |
1164 NotifyInitialLoadFinished(); | 1180 NotifyInitialLoadFinished(); |
1165 return; | 1181 return; |
1166 } | 1182 } |
1167 | 1183 |
1168 SaveFeed(feed_data.Pass(), FilePath(kAccountMetadataFile)); | 1184 SaveFeed(feed_data.Pass(), FilePath(kAccountMetadataFile)); |
1169 | 1185 |
1170 // Load changes from the server. | 1186 // Load changes from the server. |
1171 LoadFeedFromServer(local_changestamp > 0 ? local_changestamp + 1 : 0, | 1187 LoadFeedFromServer(local_changestamp > 0 ? local_changestamp + 1 : 0, |
1172 feed->largest_changestamp(), | 1188 feed->largest_changestamp(), |
1189 true, | |
1173 search_file_path, | 1190 search_file_path, |
1174 callback); | 1191 std::string() /* no search query*/, |
Ben Chan
2012/05/03 22:47:39
nit: one space before */
tbarzic
2012/05/03 23:56:17
Done.
| |
1192 callback, | |
1193 base::Bind(&GDataFileSystem::OnFeedFromServerLoaded, | |
1194 ui_weak_ptr_)); | |
1175 } | 1195 } |
1176 | 1196 |
1177 void GDataFileSystem::LoadFeedFromServer( | 1197 void GDataFileSystem::LoadFeedFromServer( |
1178 int start_changestamp, | 1198 int start_changestamp, |
1179 int root_feed_changestamp, | 1199 int root_feed_changestamp, |
1200 bool should_fetch_multiple_feeds, | |
1180 const FilePath& search_file_path, | 1201 const FilePath& search_file_path, |
1181 const FindEntryCallback& callback) { | 1202 const std::string& search_query, |
1203 const FindEntryCallback& entry_found_callback, | |
1204 const LoadDocumentFeedCallback& feed_load_callback) { | |
1182 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); | 1205 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); |
1183 | 1206 |
1184 // ...then also kick off document feed fetching from the server as well. | 1207 // ...then also kick off document feed fetching from the server as well. |
1185 // |feed_list| will contain the list of all collected feed updates that | 1208 // |feed_list| will contain the list of all collected feed updates that |
1186 // we will receive through calls of DocumentsService::GetDocuments(). | 1209 // we will receive through calls of DocumentsService::GetDocuments(). |
1187 scoped_ptr<std::vector<DocumentFeed*> > feed_list( | 1210 scoped_ptr<std::vector<DocumentFeed*> > feed_list( |
1188 new std::vector<DocumentFeed*>); | 1211 new std::vector<DocumentFeed*>); |
1189 // Kick off document feed fetching here if we don't have complete data | 1212 // Kick off document feed fetching here if we don't have complete data |
1190 // to finish this call. | 1213 // to finish this call. |
1191 documents_service_->GetDocuments( | 1214 documents_service_->GetDocuments( |
1192 GURL(), // root feed start. | 1215 GURL(), // root feed start. |
1193 start_changestamp, | 1216 start_changestamp, |
1217 search_query, | |
1194 base::Bind(&GDataFileSystem::OnGetDocuments, | 1218 base::Bind(&GDataFileSystem::OnGetDocuments, |
1195 ui_weak_ptr_, | 1219 ui_weak_ptr_, |
1220 feed_load_callback, | |
1196 base::Owned(new GetDocumentsParams(start_changestamp, | 1221 base::Owned(new GetDocumentsParams(start_changestamp, |
1197 root_feed_changestamp, | 1222 root_feed_changestamp, |
1198 feed_list.release(), | 1223 feed_list.release(), |
1224 should_fetch_multiple_feeds, | |
1199 search_file_path, | 1225 search_file_path, |
1200 callback)))); | 1226 search_query, |
1227 entry_found_callback)))); | |
1228 } | |
1229 | |
1230 void GDataFileSystem::OnFeedFromServerLoaded(GetDocumentsParams* params, | |
1231 base::PlatformFileError error) { | |
1232 if (error != base::PLATFORM_FILE_OK) { | |
1233 params->callback.Run(error, FilePath(), | |
1234 reinterpret_cast<GDataEntry*>(NULL)); | |
1235 return; | |
1236 } | |
1237 | |
1238 error = UpdateFromFeed(*params->feed_list, | |
1239 FROM_SERVER, | |
1240 params->start_changestamp, | |
1241 params->root_feed_changestamp); | |
1242 | |
1243 if (error != base::PLATFORM_FILE_OK) { | |
1244 if (!params->callback.is_null()) { | |
1245 params->callback.Run(error, FilePath(), | |
1246 reinterpret_cast<GDataEntry*>(NULL)); | |
1247 } | |
1248 | |
1249 return; | |
1250 } | |
1251 | |
1252 // Save file system metadata to disk. | |
1253 SaveFileSystemAsProto(); | |
1254 | |
1255 // If we had someone to report this too, then this retrieval was done in a | |
1256 // context of search... so continue search. | |
1257 if (!params->callback.is_null()) { | |
1258 FindEntryByPathSyncOnUIThread(params->search_file_path, params->callback); | |
1259 } | |
1201 } | 1260 } |
1202 | 1261 |
1203 void GDataFileSystem::TransferFile(const FilePath& local_file_path, | 1262 void GDataFileSystem::TransferFile(const FilePath& local_file_path, |
1204 const FilePath& remote_dest_file_path, | 1263 const FilePath& remote_dest_file_path, |
1205 const FileOperationCallback& callback) { | 1264 const FileOperationCallback& callback) { |
1206 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); | 1265 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); |
1207 | 1266 |
1208 base::AutoLock lock(lock_); | 1267 base::AutoLock lock(lock_); |
1209 // Make sure the destination directory exists | 1268 // Make sure the destination directory exists |
1210 GDataEntry* dest_dir = GetGDataEntryByPath( | 1269 GDataEntry* dest_dir = GetGDataEntryByPath( |
(...skipping 140 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
1351 base::Bind(&RelayFileOperationCallback, | 1410 base::Bind(&RelayFileOperationCallback, |
1352 base::MessageLoopProxy::current(), | 1411 base::MessageLoopProxy::current(), |
1353 callback))); | 1412 callback))); |
1354 DCHECK(posted); | 1413 DCHECK(posted); |
1355 return; | 1414 return; |
1356 } | 1415 } |
1357 | 1416 |
1358 CopyOnUIThread(src_file_path, dest_file_path, callback); | 1417 CopyOnUIThread(src_file_path, dest_file_path, callback); |
1359 } | 1418 } |
1360 | 1419 |
1361 void GDataFileSystem::CopyOnUIThread(const FilePath& src_file_path, | 1420 void GDataFileSystem::CopyOnUIThread(const FilePath& original_src_file_path, |
1362 const FilePath& dest_file_path, | 1421 const FilePath& original_dest_file_path, |
1363 const FileOperationCallback& callback) { | 1422 const FileOperationCallback& callback) { |
1364 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); | 1423 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); |
1365 | 1424 |
1366 base::PlatformFileError error = base::PLATFORM_FILE_OK; | 1425 base::PlatformFileError error = base::PLATFORM_FILE_OK; |
1367 FilePath dest_parent_path = dest_file_path.DirName(); | 1426 FilePath dest_parent_path = original_dest_file_path.DirName(); |
1427 | |
1428 FilePath src_file_path; | |
1429 FilePath dest_file_path; | |
1368 | 1430 |
1369 std::string src_file_resource_id; | 1431 std::string src_file_resource_id; |
1370 bool src_file_is_hosted_document = false; | 1432 bool src_file_is_hosted_document = false; |
1371 { | 1433 { |
1372 base::AutoLock lock(lock_); | 1434 base::AutoLock lock(lock_); |
1373 GDataEntry* src_entry = GetGDataEntryByPath(src_file_path); | 1435 GDataEntry* src_entry = GetGDataEntryByPath(original_src_file_path); |
1374 GDataEntry* dest_parent = GetGDataEntryByPath(dest_parent_path); | 1436 GDataEntry* dest_parent = GetGDataEntryByPath(dest_parent_path); |
1375 if (!src_entry || !dest_parent) { | 1437 if (!src_entry || !dest_parent) { |
1376 error = base::PLATFORM_FILE_ERROR_NOT_FOUND; | 1438 error = base::PLATFORM_FILE_ERROR_NOT_FOUND; |
1377 } else if (!dest_parent->AsGDataDirectory()) { | 1439 } else if (!dest_parent->AsGDataDirectory()) { |
1378 error = base::PLATFORM_FILE_ERROR_NOT_A_DIRECTORY; | 1440 error = base::PLATFORM_FILE_ERROR_NOT_A_DIRECTORY; |
1379 } else if (!src_entry->AsGDataFile()) { | 1441 } else if (!src_entry->AsGDataFile() || dest_parent->is_detached()) { |
1380 // TODO(benchan): Implement copy for directories. In the interim, | 1442 // TODO(benchan): Implement copy for directories. In the interim, |
1381 // we handle recursive directory copy in the file manager. | 1443 // we handle recursive directory copy in the file manager. |
1382 error = base::PLATFORM_FILE_ERROR_INVALID_OPERATION; | 1444 error = base::PLATFORM_FILE_ERROR_INVALID_OPERATION; |
1383 } else { | 1445 } else { |
1384 src_file_resource_id = src_entry->resource_id(); | 1446 src_file_resource_id = src_entry->resource_id(); |
1385 src_file_is_hosted_document = | 1447 src_file_is_hosted_document = |
1386 src_entry->AsGDataFile()->is_hosted_document(); | 1448 src_entry->AsGDataFile()->is_hosted_document(); |
1449 // |original_src_file_path| and |original_dest_file_path| don't have to | |
1450 // necessary be equal to |src_entry|'s or |dest_entry|'s file path (e.g. | |
1451 // paths used to display gdata content search results). | |
1452 // That's why, instead of using |original_src_file_path| and | |
1453 // |original_dest_file_path|, we will get file paths to use in copy | |
1454 // operation from the entries. | |
1455 src_file_path = src_entry->GetFilePath(); | |
1456 dest_parent_path = dest_parent->GetFilePath(); | |
1457 dest_file_path = dest_parent_path.Append(dest_file_path.BaseName()); | |
1387 } | 1458 } |
1388 } | 1459 } |
1389 | 1460 |
1461 DCHECK(!src_file_path.empty()); | |
1462 DCHECK(!dest_file_path.empty()); | |
1463 | |
1390 if (error != base::PLATFORM_FILE_OK) { | 1464 if (error != base::PLATFORM_FILE_OK) { |
1391 if (!callback.is_null()) | 1465 if (!callback.is_null()) |
1392 MessageLoop::current()->PostTask(FROM_HERE, base::Bind(callback, error)); | 1466 MessageLoop::current()->PostTask(FROM_HERE, base::Bind(callback, error)); |
1393 | 1467 |
1394 return; | 1468 return; |
1395 } | 1469 } |
1396 | 1470 |
1397 if (src_file_is_hosted_document) { | 1471 if (src_file_is_hosted_document) { |
1398 CopyDocumentToDirectory(dest_parent_path, | 1472 CopyDocumentToDirectory(dest_parent_path, |
1399 src_file_resource_id, | 1473 src_file_resource_id, |
(...skipping 127 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
1527 base::Bind(&RelayFileOperationCallback, | 1601 base::Bind(&RelayFileOperationCallback, |
1528 base::MessageLoopProxy::current(), | 1602 base::MessageLoopProxy::current(), |
1529 callback))); | 1603 callback))); |
1530 DCHECK(posted); | 1604 DCHECK(posted); |
1531 return; | 1605 return; |
1532 } | 1606 } |
1533 | 1607 |
1534 MoveOnUIThread(src_file_path, dest_file_path, callback); | 1608 MoveOnUIThread(src_file_path, dest_file_path, callback); |
1535 } | 1609 } |
1536 | 1610 |
1537 void GDataFileSystem::MoveOnUIThread(const FilePath& src_file_path, | 1611 void GDataFileSystem::MoveOnUIThread(const FilePath& original_src_file_path, |
1538 const FilePath& dest_file_path, | 1612 const FilePath& original_dest_file_path, |
1539 const FileOperationCallback& callback) { | 1613 const FileOperationCallback& callback) { |
1540 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); | 1614 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); |
1541 | 1615 |
1542 base::PlatformFileError error = base::PLATFORM_FILE_OK; | 1616 base::PlatformFileError error = base::PLATFORM_FILE_OK; |
1543 FilePath dest_parent_path = dest_file_path.DirName(); | 1617 FilePath dest_parent_path = original_dest_file_path.DirName(); |
1618 | |
1619 FilePath src_file_path; | |
1620 FilePath dest_file_path; | |
1621 FilePath dest_name = original_dest_file_path.BaseName(); | |
1544 | 1622 |
1545 { | 1623 { |
1546 // This scoped lock needs to be released before calling Rename() below. | 1624 // This scoped lock needs to be released before calling Rename() below. |
1547 base::AutoLock lock(lock_); | 1625 base::AutoLock lock(lock_); |
1548 GDataEntry* src_entry = GetGDataEntryByPath(src_file_path); | 1626 GDataEntry* src_entry = GetGDataEntryByPath(original_src_file_path); |
1549 GDataEntry* dest_parent = GetGDataEntryByPath(dest_parent_path); | 1627 GDataEntry* dest_parent = GetGDataEntryByPath(dest_parent_path); |
1550 if (!src_entry || !dest_parent) { | 1628 if (!src_entry || !dest_parent) { |
1551 error = base::PLATFORM_FILE_ERROR_NOT_FOUND; | 1629 error = base::PLATFORM_FILE_ERROR_NOT_FOUND; |
1552 } else { | 1630 } else if (!dest_parent->AsGDataDirectory()) { |
1553 if (!dest_parent->AsGDataDirectory()) | |
1554 error = base::PLATFORM_FILE_ERROR_NOT_A_DIRECTORY; | 1631 error = base::PLATFORM_FILE_ERROR_NOT_A_DIRECTORY; |
1632 } else if (dest_parent->is_detached()){ | |
1633 // We allow moving to a directory without file system root only if it's | |
1634 // done as part of renaming (i.e. source and destination parent paths are | |
1635 // the same). | |
1636 if (original_src_file_path.DirName() != dest_parent_path) { | |
1637 error = base::PLATFORM_FILE_ERROR_INVALID_OPERATION; | |
1638 } else { | |
1639 // If we are indeed renaming, we have to strip resource id from the file | |
1640 // name. | |
1641 std::string resource_id; | |
1642 std::string file_name; | |
1643 util::ParseSearchFileName(dest_name.value(), &resource_id, &file_name); | |
1644 if (!file_name.empty()) | |
1645 dest_name = FilePath(file_name); | |
1646 } | |
1555 } | 1647 } |
1556 | 1648 |
1557 if (error != base::PLATFORM_FILE_OK) { | 1649 if (error != base::PLATFORM_FILE_OK) { |
1558 if (!callback.is_null()) { | 1650 if (!callback.is_null()) { |
1559 MessageLoop::current()->PostTask(FROM_HERE, | 1651 MessageLoop::current()->PostTask(FROM_HERE, |
1560 base::Bind(callback, error)); | 1652 base::Bind(callback, error)); |
1561 } | 1653 } |
1562 return; | 1654 return; |
1563 } | 1655 } |
1656 // |original_src_file_path| and |original_dest_file_path| don't have to | |
1657 // necessary be equal to |src_entry|'s or |dest_entry|'s file path (e.g. | |
1658 // paths used to display gdata content search results). | |
1659 // That's why, instead of using |original_src_file_path| and | |
1660 // |original_dest_file_path|, we will get file paths to use in move | |
1661 // operation from the entries. | |
1662 src_file_path = src_entry->GetFilePath(); | |
1663 if (!dest_parent->is_detached()) | |
1664 dest_parent_path = dest_parent->GetFilePath(); | |
1665 dest_file_path = dest_parent_path.Append(dest_name); | |
1564 } | 1666 } |
1565 | 1667 |
1668 DCHECK(!src_file_path.empty()); | |
1669 DCHECK(!dest_file_path.empty()); | |
1670 | |
1566 // If the file/directory is moved to the same directory, just rename it. | 1671 // If the file/directory is moved to the same directory, just rename it. |
1567 if (src_file_path.DirName() == dest_parent_path) { | 1672 if (original_src_file_path.DirName() == dest_parent_path) { |
1568 FilePathUpdateCallback final_file_path_update_callback = | 1673 FilePathUpdateCallback final_file_path_update_callback = |
1569 base::Bind(&GDataFileSystem::OnFilePathUpdated, | 1674 base::Bind(&GDataFileSystem::OnFilePathUpdated, |
1570 ui_weak_ptr_, | 1675 ui_weak_ptr_, |
1571 callback); | 1676 callback); |
1572 | 1677 |
1573 Rename(src_file_path, dest_file_path.BaseName().value(), | 1678 Rename(original_src_file_path, dest_name.value(), |
1574 final_file_path_update_callback); | 1679 final_file_path_update_callback); |
1575 return; | 1680 return; |
1576 } | 1681 } |
1577 | 1682 |
1578 // Otherwise, the move operation involves three steps: | 1683 // Otherwise, the move operation involves three steps: |
1579 // 1. Renames the file at |src_file_path| to basename(|dest_file_path|) | 1684 // 1. Renames the file at |src_file_path| to basename(|dest_file_path|) |
1580 // within the same directory. The rename operation is a no-op if | 1685 // within the same directory. The rename operation is a no-op if |
1581 // basename(|src_file_path|) equals to basename(|dest_file_path|). | 1686 // basename(|src_file_path|) equals to basename(|dest_file_path|). |
1582 // 2. Removes the file from its parent directory (the file is not deleted), | 1687 // 2. Removes the file from its parent directory (the file is not deleted), |
1583 // which effectively moves the file to the root directory. | 1688 // which effectively moves the file to the root directory. |
(...skipping 129 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
1713 base::Bind(callback, base::PLATFORM_FILE_ERROR_NOT_FOUND)); | 1818 base::Bind(callback, base::PLATFORM_FILE_ERROR_NOT_FOUND)); |
1714 } | 1819 } |
1715 return; | 1820 return; |
1716 } | 1821 } |
1717 | 1822 |
1718 documents_service_->DeleteDocument( | 1823 documents_service_->DeleteDocument( |
1719 entry->edit_url(), | 1824 entry->edit_url(), |
1720 base::Bind(&GDataFileSystem::OnRemovedDocument, | 1825 base::Bind(&GDataFileSystem::OnRemovedDocument, |
1721 ui_weak_ptr_, | 1826 ui_weak_ptr_, |
1722 callback, | 1827 callback, |
1723 file_path)); | 1828 entry->GetFilePath())); |
1724 } | 1829 } |
1725 | 1830 |
1726 void GDataFileSystem::CreateDirectory( | 1831 void GDataFileSystem::CreateDirectory( |
1727 const FilePath& directory_path, | 1832 const FilePath& directory_path, |
1728 bool is_exclusive, | 1833 bool is_exclusive, |
1729 bool is_recursive, | 1834 bool is_recursive, |
1730 const FileOperationCallback& callback) { | 1835 const FileOperationCallback& callback) { |
1731 if (!BrowserThread::CurrentlyOn(BrowserThread::UI)) { | 1836 if (!BrowserThread::CurrentlyOn(BrowserThread::UI)) { |
1732 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO)); | 1837 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO)); |
1733 const bool posted = BrowserThread::PostTask( | 1838 const bool posted = BrowserThread::PostTask( |
(...skipping 15 matching lines...) Expand all Loading... | |
1749 directory_path, is_exclusive, is_recursive, callback); | 1854 directory_path, is_exclusive, is_recursive, callback); |
1750 } | 1855 } |
1751 | 1856 |
1752 void GDataFileSystem::CreateDirectoryOnUIThread( | 1857 void GDataFileSystem::CreateDirectoryOnUIThread( |
1753 const FilePath& directory_path, | 1858 const FilePath& directory_path, |
1754 bool is_exclusive, | 1859 bool is_exclusive, |
1755 bool is_recursive, | 1860 bool is_recursive, |
1756 const FileOperationCallback& callback) { | 1861 const FileOperationCallback& callback) { |
1757 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); | 1862 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); |
1758 | 1863 |
1864 if (!ShouldCreateDirectory(directory_path)) { | |
1865 if (!callback.is_null()) { | |
1866 MessageLoop::current()->PostTask(FROM_HERE, | |
1867 base::Bind(callback, base::PLATFORM_FILE_ERROR_INVALID_OPERATION)); | |
1868 } | |
1869 return; | |
1870 } | |
1871 | |
1759 FilePath last_parent_dir_path; | 1872 FilePath last_parent_dir_path; |
1760 FilePath first_missing_path; | 1873 FilePath first_missing_path; |
1761 GURL last_parent_dir_url; | 1874 GURL last_parent_dir_url; |
1762 FindMissingDirectoryResult result = | 1875 FindMissingDirectoryResult result = |
1763 FindFirstMissingParentDirectory(directory_path, | 1876 FindFirstMissingParentDirectory(directory_path, |
1764 &last_parent_dir_url, | 1877 &last_parent_dir_url, |
1765 &first_missing_path); | 1878 &first_missing_path); |
1766 switch (result) { | 1879 switch (result) { |
1767 case FOUND_INVALID: { | 1880 case FOUND_INVALID: { |
1768 if (!callback.is_null()) { | 1881 if (!callback.is_null()) { |
(...skipping 894 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
2663 params.callback); | 2776 params.callback); |
2664 return; | 2777 return; |
2665 } | 2778 } |
2666 | 2779 |
2667 if (!params.callback.is_null()) { | 2780 if (!params.callback.is_null()) { |
2668 // Finally done with the create request. | 2781 // Finally done with the create request. |
2669 params.callback.Run(base::PLATFORM_FILE_OK); | 2782 params.callback.Run(base::PLATFORM_FILE_OK); |
2670 } | 2783 } |
2671 } | 2784 } |
2672 | 2785 |
2673 void GDataFileSystem::OnGetDocuments(GetDocumentsParams* params, | 2786 void GDataFileSystem::OnGetEntriesByQuery(const ReadDirectoryCallback& callback, |
2787 GetDocumentsParams* params, | |
2788 base::PlatformFileError error) { | |
2789 // The search results will be returned using virtual directory. | |
2790 // The directory is not really part of the file system, so it has no parent or | |
2791 // root. | |
2792 scoped_ptr<GDataDirectory> search_dir(new GDataDirectory(NULL, NULL)); | |
2793 | |
2794 base::AutoLock lock(lock_); | |
2795 | |
2796 int delta_feed_changestamp = 0; | |
2797 int num_regular_files = 0; | |
2798 int num_hosted_documents = 0; | |
2799 FileResourceIdMap file_map; | |
2800 if (error == base::PLATFORM_FILE_OK) { | |
2801 error = FeedToFileResourceMap(*params->feed_list, | |
2802 &file_map, | |
2803 &delta_feed_changestamp, | |
2804 &num_regular_files, | |
2805 &num_hosted_documents); | |
2806 } | |
2807 | |
2808 if (error == base::PLATFORM_FILE_OK) { | |
2809 std::set<FilePath> ignored; | |
2810 | |
2811 // Go through all entires generated by the feed and add them to the search | |
2812 // result directory. | |
2813 for (FileResourceIdMap::const_iterator it = file_map.begin(); | |
2814 it != file_map.end(); ++it) { | |
2815 scoped_ptr<GDataEntry> entry(it->second); | |
2816 DCHECK_EQ(it->first, entry->resource_id()); | |
2817 DCHECK(!entry->is_deleted()); | |
2818 | |
2819 entry->set_title(entry->resource_id() + "." + entry->title()); | |
2820 | |
2821 search_dir->AddEntry(entry.release()); | |
2822 } | |
2823 } | |
2824 | |
2825 scoped_ptr<GDataDirectoryProto> directory_proto(new GDataDirectoryProto); | |
2826 search_dir->ToProto(directory_proto.get()); | |
2827 | |
2828 if (!callback.is_null()) { | |
2829 callback.Run(error, directory_proto.Pass()); | |
2830 } | |
2831 } | |
2832 | |
2833 void GDataFileSystem::GetEntriesByQueryAsync( | |
2834 const std::string& search_query, | |
2835 const ReadDirectoryCallback& callback) { | |
2836 if (!BrowserThread::CurrentlyOn(BrowserThread::UI)) { | |
2837 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO)); | |
2838 const bool posted = BrowserThread::PostTask( | |
2839 BrowserThread::UI, | |
2840 FROM_HERE, | |
2841 base::Bind(&GDataFileSystem::GetEntriesByQueryAsyncOnUIThread, | |
2842 ui_weak_ptr_, | |
2843 search_query, | |
2844 base::Bind(&RelayReadDirectoryCallback, | |
2845 base::MessageLoopProxy::current(), | |
2846 callback))); | |
2847 DCHECK(posted); | |
2848 return; | |
2849 } | |
2850 | |
2851 GetEntriesByQueryAsyncOnUIThread(search_query, callback); | |
2852 } | |
2853 | |
2854 void GDataFileSystem::GetEntriesByQueryAsyncOnUIThread( | |
2855 const std::string& search_query, | |
2856 const ReadDirectoryCallback& callback) { | |
2857 scoped_ptr<std::vector<DocumentFeed*> > feed_list( | |
2858 new std::vector<DocumentFeed*>); | |
2859 | |
2860 LoadFeedFromServer(0, 0, // We don't use change stamps when fetching search | |
2861 // data; we always fetch the whole result feed. | |
2862 false, // Stop fetching search results after first feed | |
2863 // chunk to avoid displaying huge number of search | |
2864 // results (especially since we don't cache them). | |
2865 FilePath(), // Not used. | |
2866 search_query, | |
2867 FindEntryCallback(), // Not used. | |
2868 base::Bind(&GDataFileSystem::OnGetEntriesByQuery, | |
2869 ui_weak_ptr_, callback)); | |
2870 } | |
2871 | |
2872 void GDataFileSystem::OnGetDocuments(const LoadDocumentFeedCallback& callback, | |
2873 GetDocumentsParams* params, | |
2674 GDataErrorCode status, | 2874 GDataErrorCode status, |
2675 scoped_ptr<base::Value> data) { | 2875 scoped_ptr<base::Value> data) { |
2676 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); | 2876 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); |
2677 | 2877 |
2678 base::PlatformFileError error = GDataToPlatformError(status); | 2878 base::PlatformFileError error = GDataToPlatformError(status); |
2679 if (error == base::PLATFORM_FILE_OK && | 2879 if (error == base::PLATFORM_FILE_OK && |
2680 (!data.get() || data->GetType() != Value::TYPE_DICTIONARY)) { | 2880 (!data.get() || data->GetType() != Value::TYPE_DICTIONARY)) { |
2681 LOG(WARNING) << "No feed content!"; | |
2682 error = base::PLATFORM_FILE_ERROR_FAILED; | 2881 error = base::PLATFORM_FILE_ERROR_FAILED; |
2683 } | 2882 } |
2684 | 2883 |
2685 if (error != base::PLATFORM_FILE_OK) { | 2884 if (error != base::PLATFORM_FILE_OK) { |
2686 if (!params->callback.is_null()) { | 2885 if (!callback.is_null()) { |
2687 params->callback.Run(error, FilePath(), | 2886 callback.Run(params, error); |
2688 reinterpret_cast<GDataEntry*>(NULL)); | |
2689 } | 2887 } |
2690 | 2888 |
2691 return; | 2889 return; |
2692 } | 2890 } |
2693 | 2891 |
2694 // TODO(zelidrag): Find a faster way to get next url rather than parsing | 2892 // TODO(zelidrag): Find a faster way to get next url rather than parsing |
2695 // the entire feed. | 2893 // the entire feed. |
2696 GURL next_feed_url; | 2894 GURL next_feed_url; |
2697 scoped_ptr<DocumentFeed> current_feed(DocumentFeed::ExtractAndParse(*data)); | 2895 scoped_ptr<DocumentFeed> current_feed(DocumentFeed::ExtractAndParse(*data)); |
2698 if (!current_feed.get()) { | 2896 if (!current_feed.get()) { |
2699 if (!params->callback.is_null()) { | 2897 if (!callback.is_null()) { |
2700 params->callback.Run(base::PLATFORM_FILE_ERROR_FAILED, FilePath(), | 2898 callback.Run(params, base::PLATFORM_FILE_ERROR_FAILED); |
2701 reinterpret_cast<GDataEntry*>(NULL)); | |
2702 } | 2899 } |
2703 | 2900 |
2704 return; | 2901 return; |
2705 } | 2902 } |
2706 const bool has_next_feed_url = current_feed->GetNextFeedURL(&next_feed_url); | 2903 const bool has_next_feed_url = current_feed->GetNextFeedURL(&next_feed_url); |
2707 | 2904 |
2708 // Add the current feed to the list of collected feeds for this directory. | 2905 // Add the current feed to the list of collected feeds for this directory. |
2709 params->feed_list->push_back(current_feed.release()); | 2906 params->feed_list->push_back(current_feed.release()); |
2710 | 2907 |
2711 // Check if we need to collect more data to complete the directory list. | 2908 // Check if we need to collect more data to complete the directory list. |
2712 if (has_next_feed_url && !next_feed_url.is_empty()) { | 2909 if (params->should_fetch_multiple_feeds && has_next_feed_url && |
2910 !next_feed_url.is_empty()) { | |
2713 // Kick of the remaining part of the feeds. | 2911 // Kick of the remaining part of the feeds. |
2714 documents_service_->GetDocuments( | 2912 documents_service_->GetDocuments( |
2715 next_feed_url, | 2913 next_feed_url, |
2716 params->start_changestamp, | 2914 params->start_changestamp, |
2915 params->search_query, | |
2717 base::Bind(&GDataFileSystem::OnGetDocuments, | 2916 base::Bind(&GDataFileSystem::OnGetDocuments, |
2718 ui_weak_ptr_, | 2917 ui_weak_ptr_, |
2918 callback, | |
2719 base::Owned( | 2919 base::Owned( |
2720 new GetDocumentsParams(params->start_changestamp, | 2920 new GetDocumentsParams( |
2721 params->root_feed_changestamp, | 2921 params->start_changestamp, |
2722 params->feed_list.release(), | 2922 params->root_feed_changestamp, |
2723 params->search_file_path, | 2923 params->feed_list.release(), |
2724 params->callback)))); | 2924 params->should_fetch_multiple_feeds, |
2925 params->search_file_path, | |
2926 params->search_query, | |
2927 params->callback)))); | |
2725 return; | 2928 return; |
2726 } | 2929 } |
2727 | 2930 |
2728 error = UpdateFromFeed(*params->feed_list, | 2931 if (!callback.is_null()) |
2729 FROM_SERVER, | 2932 callback.Run(params, error); |
2730 params->start_changestamp, | |
2731 params->root_feed_changestamp); | |
2732 | |
2733 if (error != base::PLATFORM_FILE_OK) { | |
2734 if (!params->callback.is_null()) { | |
2735 params->callback.Run(error, FilePath(), | |
2736 reinterpret_cast<GDataEntry*>(NULL)); | |
2737 } | |
2738 | |
2739 return; | |
2740 } | |
2741 | |
2742 // Save file system metadata to disk. | |
2743 SaveFileSystemAsProto(); | |
2744 | |
2745 // If we had someone to report this too, then this retrieval was done in a | |
2746 // context of search... so continue search. | |
2747 if (!params->callback.is_null()) { | |
2748 FindEntryByPathSyncOnUIThread(params->search_file_path, params->callback); | |
2749 } | |
2750 } | 2933 } |
2751 | 2934 |
2752 void GDataFileSystem::LoadRootFeedFromCache( | 2935 void GDataFileSystem::LoadRootFeedFromCache( |
2753 bool should_load_from_server, | 2936 bool should_load_from_server, |
2754 const FilePath& search_file_path, | 2937 const FilePath& search_file_path, |
2755 const FindEntryCallback& callback) { | 2938 const FindEntryCallback& callback) { |
2756 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); | 2939 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); |
2757 | 2940 |
2758 const FilePath path = | 2941 const FilePath path = |
2759 GetCacheDirectoryPath(GDataRootDirectory::CACHE_TYPE_META).Append( | 2942 GetCacheDirectoryPath(GDataRootDirectory::CACHE_TYPE_META).Append( |
(...skipping 743 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
3503 return base::PLATFORM_FILE_ERROR_FAILED; | 3686 return base::PLATFORM_FILE_ERROR_FAILED; |
3504 | 3687 |
3505 GDataEntry* new_entry = GDataEntry::FromDocumentEntry(parent_dir, | 3688 GDataEntry* new_entry = GDataEntry::FromDocumentEntry(parent_dir, |
3506 doc_entry.get(), | 3689 doc_entry.get(), |
3507 root_.get()); | 3690 root_.get()); |
3508 if (!new_entry) | 3691 if (!new_entry) |
3509 return base::PLATFORM_FILE_ERROR_FAILED; | 3692 return base::PLATFORM_FILE_ERROR_FAILED; |
3510 | 3693 |
3511 parent_dir->AddEntry(new_entry); | 3694 parent_dir->AddEntry(new_entry); |
3512 | 3695 |
3513 NotifyDirectoryChanged(directory_path); | 3696 NotifyDirectoryChanged(entry->GetFilePath()); |
3514 return base::PLATFORM_FILE_OK; | 3697 return base::PLATFORM_FILE_OK; |
3515 } | 3698 } |
3516 | 3699 |
3517 GDataFileSystem::FindMissingDirectoryResult | 3700 GDataFileSystem::FindMissingDirectoryResult |
3518 GDataFileSystem::FindFirstMissingParentDirectory( | 3701 GDataFileSystem::FindFirstMissingParentDirectory( |
3519 const FilePath& directory_path, | 3702 const FilePath& directory_path, |
3520 GURL* last_dir_content_url, | 3703 GURL* last_dir_content_url, |
3521 FilePath* first_missing_parent_path) { | 3704 FilePath* first_missing_parent_path) { |
3522 // Let's find which how deep is the existing directory structure and | 3705 // Let's find which how deep is the existing directory structure and |
3523 // get the first element that's missing. | 3706 // get the first element that's missing. |
(...skipping 1246 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
4770 pref_registrar_.reset(new PrefChangeRegistrar()); | 4953 pref_registrar_.reset(new PrefChangeRegistrar()); |
4771 pref_registrar_->Init(profile_->GetPrefs()); | 4954 pref_registrar_->Init(profile_->GetPrefs()); |
4772 pref_registrar_->Add(prefs::kDisableGDataHostedFiles, this); | 4955 pref_registrar_->Add(prefs::kDisableGDataHostedFiles, this); |
4773 } | 4956 } |
4774 | 4957 |
4775 void SetFreeDiskSpaceGetterForTesting(FreeDiskSpaceGetterInterface* getter) { | 4958 void SetFreeDiskSpaceGetterForTesting(FreeDiskSpaceGetterInterface* getter) { |
4776 delete global_free_disk_getter_for_testing; // Safe to delete NULL; | 4959 delete global_free_disk_getter_for_testing; // Safe to delete NULL; |
4777 global_free_disk_getter_for_testing = getter; | 4960 global_free_disk_getter_for_testing = getter; |
4778 } | 4961 } |
4779 | 4962 |
4963 bool GDataFileSystem::ShouldCreateDirectory(const FilePath& directory_path) { | |
4964 // We allow directory creation for paths that are on gdata file system | |
4965 // (GDATA_SEARCH_PATH_INVALID) and paths that reference actual gdata file | |
4966 // system path (GDATA_SEARCH_PATH_RESULT_CHILD). | |
4967 util::GDataSearchPathType path_type = | |
4968 util::GetSearchPathStatus(directory_path); | |
4969 return path_type == util::GDATA_SEARCH_PATH_INVALID || | |
4970 path_type == util::GDATA_SEARCH_PATH_RESULT_CHILD; | |
4971 | |
4972 } | |
4973 | |
4780 } // namespace gdata | 4974 } // namespace gdata |
OLD | NEW |