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/sync_file_system/drive_file_sync_client.h" | 5 #include "chrome/browser/sync_file_system/drive_file_sync_client.h" |
6 | 6 |
7 #include <sstream> | 7 #include <sstream> |
8 | 8 |
9 #include "base/string_util.h" | 9 #include "base/string_util.h" |
10 #include "base/utf_string_conversions.h" | 10 #include "base/utf_string_conversions.h" |
11 #include "base/values.h" | 11 #include "base/values.h" |
12 #include "chrome/browser/google_apis/drive_uploader.h" | 12 #include "chrome/browser/google_apis/drive_uploader.h" |
13 #include "chrome/browser/google_apis/gdata_wapi_service.h" | 13 #include "chrome/browser/google_apis/gdata_wapi_service.h" |
14 #include "chrome/browser/google_apis/gdata_wapi_url_generator.h" | 14 #include "chrome/browser/google_apis/gdata_wapi_url_generator.h" |
| 15 #include "chrome/common/extensions/extension.h" |
| 16 #include "extensions/common/constants.h" |
15 #include "net/base/escape.h" | 17 #include "net/base/escape.h" |
16 #include "net/base/mime_util.h" | 18 #include "net/base/mime_util.h" |
17 | 19 |
18 namespace sync_file_system { | 20 namespace sync_file_system { |
19 | 21 |
20 namespace { | 22 namespace { |
21 | 23 |
22 const char kRootResourceId[] = ""; | 24 const char kRootResourceId[] = ""; |
23 const char kSyncRootDirectoryName[] = "Chrome Syncable FileSystem"; | 25 const char kSyncRootDirectoryName[] = "Chrome Syncable FileSystem"; |
24 const char kResourceLinkPrefix[] = | |
25 "https://docs.google.com/feeds/default/private/full/"; | |
26 const char kMimeTypeOctetStream[] = "application/octet-stream"; | 26 const char kMimeTypeOctetStream[] = "application/octet-stream"; |
27 | 27 |
28 // This path is not actually used but is required by DriveUploaderInterface. | 28 // This path is not actually used but is required by DriveUploaderInterface. |
29 const FilePath::CharType kDummyDrivePath[] = | 29 const FilePath::CharType kDummyDrivePath[] = |
30 FILE_PATH_LITERAL("/dummy/drive/path"); | 30 FILE_PATH_LITERAL("/dummy/drive/path"); |
31 | 31 |
32 bool HasParentLinkTo(const ScopedVector<google_apis::Link>& links, | 32 bool HasParentLinkTo(const ScopedVector<google_apis::Link>& links, |
33 const std::string& parent_resource_id) { | 33 const GURL& parent_link) { |
34 bool should_not_have_parent = parent_resource_id.empty(); | 34 bool should_not_have_parent = parent_link.is_empty(); |
35 GURL parent_link(kResourceLinkPrefix + net::EscapePath(parent_resource_id)); | |
36 | 35 |
37 for (ScopedVector<google_apis::Link>::const_iterator itr = links.begin(); | 36 for (ScopedVector<google_apis::Link>::const_iterator itr = links.begin(); |
38 itr != links.end(); ++itr) { | 37 itr != links.end(); ++itr) { |
39 if ((*itr)->type() == google_apis::Link::LINK_PARENT) { | 38 if ((*itr)->type() == google_apis::Link::LINK_PARENT) { |
40 if (should_not_have_parent) | 39 if (should_not_have_parent) |
41 return false; | 40 return false; |
42 if ((*itr)->href() == parent_link) | 41 if ((*itr)->href().GetOrigin() == parent_link.GetOrigin() && |
| 42 (*itr)->href().path() == parent_link.path()) |
43 return true; | 43 return true; |
44 } | 44 } |
45 } | 45 } |
46 | 46 |
47 return should_not_have_parent; | 47 return should_not_have_parent; |
48 } | 48 } |
49 | 49 |
50 google_apis::DocumentEntry* GetDocumentByTitleAndParent( | 50 google_apis::DocumentEntry* GetDocumentByTitleAndParent( |
51 const ScopedVector<google_apis::DocumentEntry>& entries, | 51 const ScopedVector<google_apis::DocumentEntry>& entries, |
52 const std::string& parent_resource_id, | 52 const GURL& parent_link, |
53 const string16& title) { | 53 const string16& title) { |
54 typedef ScopedVector<google_apis::DocumentEntry>::const_iterator iterator; | 54 typedef ScopedVector<google_apis::DocumentEntry>::const_iterator iterator; |
55 for (iterator itr = entries.begin(); itr != entries.end(); ++itr) { | 55 for (iterator itr = entries.begin(); itr != entries.end(); ++itr) { |
56 if ((*itr)->title() == title && | 56 if ((*itr)->title() == title && |
57 HasParentLinkTo((*itr)->links(), parent_resource_id)) { | 57 HasParentLinkTo((*itr)->links(), parent_link)) { |
58 return *itr; | 58 return *itr; |
59 } | 59 } |
60 } | 60 } |
61 return NULL; | 61 return NULL; |
62 } | 62 } |
63 | 63 |
64 } // namespace | 64 } // namespace |
65 | 65 |
66 DriveFileSyncClient::DriveFileSyncClient(Profile* profile) { | 66 DriveFileSyncClient::DriveFileSyncClient(Profile* profile) |
| 67 : url_generator_(GURL( |
| 68 google_apis::GDataWapiUrlGenerator::kBaseUrlForProduction)) { |
67 drive_service_.reset(new google_apis::GDataWapiService( | 69 drive_service_.reset(new google_apis::GDataWapiService( |
68 GURL(google_apis::GDataWapiUrlGenerator::kBaseUrlForProduction), | 70 GURL(google_apis::GDataWapiUrlGenerator::kBaseUrlForProduction), |
69 "" /* custom_user_agent */)); | 71 "" /* custom_user_agent */)); |
70 drive_service_->Initialize(profile); | 72 drive_service_->Initialize(profile); |
71 | 73 |
72 drive_uploader_.reset(new google_apis::DriveUploader(drive_service_.get())); | 74 drive_uploader_.reset(new google_apis::DriveUploader(drive_service_.get())); |
73 } | 75 } |
74 | 76 |
75 scoped_ptr<DriveFileSyncClient> DriveFileSyncClient::CreateForTesting( | 77 scoped_ptr<DriveFileSyncClient> DriveFileSyncClient::CreateForTesting( |
76 Profile* profile, | 78 Profile* profile, |
| 79 const GURL& base_url, |
77 scoped_ptr<google_apis::DriveServiceInterface> drive_service, | 80 scoped_ptr<google_apis::DriveServiceInterface> drive_service, |
78 scoped_ptr<google_apis::DriveUploaderInterface> drive_uploader) { | 81 scoped_ptr<google_apis::DriveUploaderInterface> drive_uploader) { |
79 return make_scoped_ptr(new DriveFileSyncClient( | 82 return make_scoped_ptr(new DriveFileSyncClient( |
80 profile, drive_service.Pass(), drive_uploader.Pass())); | 83 profile, base_url, drive_service.Pass(), drive_uploader.Pass())); |
81 } | 84 } |
82 | 85 |
83 DriveFileSyncClient::DriveFileSyncClient( | 86 DriveFileSyncClient::DriveFileSyncClient( |
84 Profile* profile, | 87 Profile* profile, |
| 88 const GURL& base_url, |
85 scoped_ptr<google_apis::DriveServiceInterface> drive_service, | 89 scoped_ptr<google_apis::DriveServiceInterface> drive_service, |
86 scoped_ptr<google_apis::DriveUploaderInterface> drive_uploader) { | 90 scoped_ptr<google_apis::DriveUploaderInterface> drive_uploader) |
| 91 : url_generator_(base_url) { |
87 drive_service_ = drive_service.Pass(); | 92 drive_service_ = drive_service.Pass(); |
88 drive_service_->Initialize(profile); | 93 drive_service_->Initialize(profile); |
89 | 94 |
90 drive_uploader_ = drive_uploader.Pass(); | 95 drive_uploader_ = drive_uploader.Pass(); |
91 } | 96 } |
92 | 97 |
93 DriveFileSyncClient::~DriveFileSyncClient() { | 98 DriveFileSyncClient::~DriveFileSyncClient() { |
94 DCHECK(CalledOnValidThread()); | 99 DCHECK(CalledOnValidThread()); |
95 drive_service_->CancelAll(); | 100 drive_service_->CancelAll(); |
96 } | 101 } |
97 | 102 |
98 void DriveFileSyncClient::GetDriveDirectoryForSyncRoot( | 103 void DriveFileSyncClient::GetDriveDirectoryForSyncRoot( |
99 const ResourceIdCallback& callback) { | 104 const ResourceIdCallback& callback) { |
100 DCHECK(CalledOnValidThread()); | 105 DCHECK(CalledOnValidThread()); |
101 | 106 |
102 std::string directory_name(kSyncRootDirectoryName); | 107 std::string directory_name(kSyncRootDirectoryName); |
103 SearchFilesInDirectory( | 108 SearchFilesInDirectory( |
104 kRootResourceId, | 109 kRootResourceId, |
105 FormatTitleQuery(directory_name), | 110 FormatTitleQuery(directory_name), |
106 base::Bind(&DriveFileSyncClient::DidGetDirectory, AsWeakPtr(), | 111 base::Bind(&DriveFileSyncClient::DidGetDirectory, AsWeakPtr(), |
107 kRootResourceId, directory_name, callback)); | 112 kRootResourceId, directory_name, callback)); |
108 } | 113 } |
109 | 114 |
110 void DriveFileSyncClient::GetDriveDirectoryForOrigin( | 115 void DriveFileSyncClient::GetDriveDirectoryForOrigin( |
111 const std::string& sync_root_resource_id, | 116 const std::string& sync_root_resource_id, |
112 const GURL& origin, | 117 const GURL& origin, |
113 const ResourceIdCallback& callback) { | 118 const ResourceIdCallback& callback) { |
114 DCHECK(CalledOnValidThread()); | 119 DCHECK(CalledOnValidThread()); |
115 | 120 |
116 std::string directory_name(origin.spec()); | 121 std::string directory_name(OriginToDirectoryTitle(origin)); |
117 SearchFilesInDirectory( | 122 SearchFilesInDirectory( |
118 sync_root_resource_id, | 123 sync_root_resource_id, |
119 FormatTitleQuery(directory_name), | 124 FormatTitleQuery(directory_name), |
120 base::Bind(&DriveFileSyncClient::DidGetDirectory, AsWeakPtr(), | 125 base::Bind(&DriveFileSyncClient::DidGetDirectory, AsWeakPtr(), |
121 sync_root_resource_id, directory_name, callback)); | 126 sync_root_resource_id, directory_name, callback)); |
122 } | 127 } |
123 | 128 |
124 void DriveFileSyncClient::DidGetDirectory( | 129 void DriveFileSyncClient::DidGetDirectory( |
125 const std::string& parent_resource_id, | 130 const std::string& parent_resource_id, |
126 const std::string& directory_name, | 131 const std::string& directory_name, |
127 const ResourceIdCallback& callback, | 132 const ResourceIdCallback& callback, |
128 google_apis::GDataErrorCode error, | 133 google_apis::GDataErrorCode error, |
129 scoped_ptr<google_apis::DocumentFeed> feed) { | 134 scoped_ptr<google_apis::DocumentFeed> feed) { |
130 DCHECK(CalledOnValidThread()); | 135 DCHECK(CalledOnValidThread()); |
131 DCHECK(IsStringASCII(directory_name)); | 136 DCHECK(IsStringASCII(directory_name)); |
132 | 137 |
133 if (error != google_apis::HTTP_SUCCESS) { | 138 if (error != google_apis::HTTP_SUCCESS) { |
134 callback.Run(error, std::string()); | 139 callback.Run(error, std::string()); |
135 return; | 140 return; |
136 } | 141 } |
137 | 142 |
| 143 GURL parent_link; |
| 144 if (!parent_resource_id.empty()) |
| 145 parent_link = ResourceIdToResourceLink(parent_resource_id); |
138 google_apis::DocumentEntry* entry = GetDocumentByTitleAndParent( | 146 google_apis::DocumentEntry* entry = GetDocumentByTitleAndParent( |
139 feed->entries(), parent_resource_id, ASCIIToUTF16(directory_name)); | 147 feed->entries(), parent_link, ASCIIToUTF16(directory_name)); |
140 if (!entry) { | 148 if (!entry) { |
141 if (parent_resource_id.empty()) { | 149 if (parent_resource_id.empty()) { |
142 // Use empty content URL for root directory. | 150 // Use empty content URL for root directory. |
143 drive_service_->AddNewDirectory( | 151 drive_service_->AddNewDirectory( |
144 GURL(), // parent_content_url | 152 GURL(), // parent_content_url |
145 FilePath().AppendASCII(directory_name).value(), | 153 FilePath().AppendASCII(directory_name).value(), |
146 base::Bind(&DriveFileSyncClient::DidCreateDirectory, | 154 base::Bind(&DriveFileSyncClient::DidCreateDirectory, |
147 AsWeakPtr(), callback)); | 155 AsWeakPtr(), callback)); |
148 return; | 156 return; |
149 } | 157 } |
(...skipping 199 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
349 const GDataErrorCallback& callback) { | 357 const GDataErrorCallback& callback) { |
350 DCHECK(CalledOnValidThread()); | 358 DCHECK(CalledOnValidThread()); |
351 drive_service_->GetDocumentEntry( | 359 drive_service_->GetDocumentEntry( |
352 resource_id, | 360 resource_id, |
353 base::Bind(&DriveFileSyncClient::DidGetDocumentEntryData, | 361 base::Bind(&DriveFileSyncClient::DidGetDocumentEntryData, |
354 AsWeakPtr(), | 362 AsWeakPtr(), |
355 base::Bind(&DriveFileSyncClient::DeleteFileInternal, | 363 base::Bind(&DriveFileSyncClient::DeleteFileInternal, |
356 AsWeakPtr(), remote_file_md5, callback))); | 364 AsWeakPtr(), remote_file_md5, callback))); |
357 } | 365 } |
358 | 366 |
| 367 // static |
| 368 std::string DriveFileSyncClient::OriginToDirectoryTitle(const GURL& origin) { |
| 369 DCHECK(origin.SchemeIs(extensions::kExtensionScheme)); |
| 370 return origin.host(); |
| 371 } |
| 372 |
| 373 // static |
| 374 GURL DriveFileSyncClient::DirectoryTitleToOrigin(const std::string& title) { |
| 375 return extensions::Extension::GetBaseURLFromExtensionId(title); |
| 376 } |
| 377 |
| 378 GURL DriveFileSyncClient::ResourceIdToResourceLink( |
| 379 const std::string& resource_id) const { |
| 380 return url_generator_.GenerateDocumentEntryUrl(resource_id); |
| 381 } |
| 382 |
359 void DriveFileSyncClient::DidGetDocumentFeedData( | 383 void DriveFileSyncClient::DidGetDocumentFeedData( |
360 const DocumentFeedCallback& callback, | 384 const DocumentFeedCallback& callback, |
361 google_apis::GDataErrorCode error, | 385 google_apis::GDataErrorCode error, |
362 scoped_ptr<base::Value> data) { | 386 scoped_ptr<base::Value> data) { |
363 DCHECK(CalledOnValidThread()); | 387 DCHECK(CalledOnValidThread()); |
364 | 388 |
365 if (error != google_apis::HTTP_SUCCESS) { | 389 if (error != google_apis::HTTP_SUCCESS) { |
366 callback.Run(error, scoped_ptr<google_apis::DocumentFeed>()); | 390 callback.Run(error, scoped_ptr<google_apis::DocumentFeed>()); |
367 return; | 391 return; |
368 } | 392 } |
(...skipping 229 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
598 } | 622 } |
599 | 623 |
600 void DriveFileSyncClient::DidDeleteFile( | 624 void DriveFileSyncClient::DidDeleteFile( |
601 const GDataErrorCallback& callback, | 625 const GDataErrorCallback& callback, |
602 google_apis::GDataErrorCode error) { | 626 google_apis::GDataErrorCode error) { |
603 DCHECK(CalledOnValidThread()); | 627 DCHECK(CalledOnValidThread()); |
604 callback.Run(error); | 628 callback.Run(error); |
605 } | 629 } |
606 | 630 |
607 } // namespace sync_file_system | 631 } // namespace sync_file_system |
OLD | NEW |