Enable Enterprise enrollment on desktop builds.
[chromium-blink-merge.git] / chrome / browser / extensions / api / sync_file_system / sync_file_system_api.cc
blobf6bd6376e6dd209b9109a6a88b12b820f067cdd5
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
3 // found in the LICENSE file.
5 #include "chrome/browser/extensions/api/sync_file_system/sync_file_system_api.h"
7 #include <string>
8 #include <utility>
10 #include "base/bind.h"
11 #include "base/logging.h"
12 #include "base/strings/stringprintf.h"
13 #include "chrome/browser/extensions/api/sync_file_system/extension_sync_event_observer.h"
14 #include "chrome/browser/extensions/api/sync_file_system/sync_file_system_api_helpers.h"
15 #include "chrome/browser/profiles/profile.h"
16 #include "chrome/browser/sync_file_system/drive_backend_v1/drive_file_sync_service.h"
17 #include "chrome/browser/sync_file_system/sync_file_status.h"
18 #include "chrome/browser/sync_file_system/sync_file_system_service.h"
19 #include "chrome/browser/sync_file_system/sync_file_system_service_factory.h"
20 #include "chrome/common/extensions/api/sync_file_system.h"
21 #include "content/public/browser/browser_context.h"
22 #include "content/public/browser/render_view_host.h"
23 #include "content/public/browser/storage_partition.h"
24 #include "content/public/common/content_client.h"
25 #include "webkit/browser/fileapi/file_system_context.h"
26 #include "webkit/browser/fileapi/file_system_url.h"
27 #include "webkit/browser/quota/quota_manager.h"
28 #include "webkit/common/fileapi/file_system_types.h"
29 #include "webkit/common/fileapi/file_system_util.h"
31 using content::BrowserContext;
32 using content::BrowserThread;
33 using sync_file_system::ConflictResolutionPolicy;
34 using sync_file_system::SyncFileStatus;
35 using sync_file_system::SyncFileSystemServiceFactory;
36 using sync_file_system::SyncStatusCode;
38 namespace extensions {
40 namespace {
42 // Error messages.
43 const char kErrorMessage[] = "%s (error code: %d).";
44 const char kUnsupportedConflictResolutionPolicy[] =
45 "Policy %s is not supported.";
47 sync_file_system::SyncFileSystemService* GetSyncFileSystemService(
48 Profile* profile) {
49 sync_file_system::SyncFileSystemService* service =
50 SyncFileSystemServiceFactory::GetForProfile(profile);
51 DCHECK(service);
52 ExtensionSyncEventObserver* observer =
53 ExtensionSyncEventObserver::GetFactoryInstance()->Get(profile);
54 DCHECK(observer);
55 observer->InitializeForService(service);
56 return service;
59 std::string ErrorToString(SyncStatusCode code) {
60 return base::StringPrintf(
61 kErrorMessage,
62 sync_file_system::SyncStatusCodeToString(code),
63 static_cast<int>(code));
66 } // namespace
68 bool SyncFileSystemDeleteFileSystemFunction::RunImpl() {
69 std::string url;
70 EXTENSION_FUNCTION_VALIDATE(args_->GetString(0, &url));
72 scoped_refptr<fileapi::FileSystemContext> file_system_context =
73 BrowserContext::GetStoragePartition(GetProfile(),
74 render_view_host()->GetSiteInstance())
75 ->GetFileSystemContext();
76 fileapi::FileSystemURL file_system_url(
77 file_system_context->CrackURL(GURL(url)));
79 BrowserThread::PostTask(
80 BrowserThread::IO,
81 FROM_HERE,
82 Bind(&fileapi::FileSystemContext::DeleteFileSystem,
83 file_system_context,
84 source_url().GetOrigin(),
85 file_system_url.type(),
86 Bind(&SyncFileSystemDeleteFileSystemFunction::DidDeleteFileSystem,
87 this)));
88 return true;
91 void SyncFileSystemDeleteFileSystemFunction::DidDeleteFileSystem(
92 base::File::Error error) {
93 // Repost to switch from IO thread to UI thread for SendResponse().
94 if (!BrowserThread::CurrentlyOn(BrowserThread::UI)) {
95 DCHECK_CURRENTLY_ON(BrowserThread::IO);
96 BrowserThread::PostTask(
97 BrowserThread::UI,
98 FROM_HERE,
99 Bind(&SyncFileSystemDeleteFileSystemFunction::DidDeleteFileSystem, this,
100 error));
101 return;
104 DCHECK_CURRENTLY_ON(BrowserThread::UI);
105 if (error != base::File::FILE_OK) {
106 error_ = ErrorToString(sync_file_system::FileErrorToSyncStatusCode(error));
107 SetResult(new base::FundamentalValue(false));
108 SendResponse(false);
109 return;
112 SetResult(new base::FundamentalValue(true));
113 SendResponse(true);
116 bool SyncFileSystemRequestFileSystemFunction::RunImpl() {
117 // SyncFileSystem initialization is done in OpenFileSystem below, but we call
118 // GetSyncFileSystemService here too to initialize sync event observer for
119 // extensions API.
120 GetSyncFileSystemService(GetProfile());
122 // Initializes sync context for this extension and continue to open
123 // a new file system.
124 BrowserThread::PostTask(
125 BrowserThread::IO, FROM_HERE,
126 Bind(&fileapi::FileSystemContext::OpenFileSystem,
127 GetFileSystemContext(),
128 source_url().GetOrigin(),
129 fileapi::kFileSystemTypeSyncable,
130 fileapi::OPEN_FILE_SYSTEM_CREATE_IF_NONEXISTENT,
131 base::Bind(&self::DidOpenFileSystem, this)));
132 return true;
135 fileapi::FileSystemContext*
136 SyncFileSystemRequestFileSystemFunction::GetFileSystemContext() {
137 DCHECK(render_view_host());
138 return BrowserContext::GetStoragePartition(
139 GetProfile(), render_view_host()->GetSiteInstance())
140 ->GetFileSystemContext();
143 void SyncFileSystemRequestFileSystemFunction::DidOpenFileSystem(
144 const GURL& root_url,
145 const std::string& file_system_name,
146 base::File::Error error) {
147 // Repost to switch from IO thread to UI thread for SendResponse().
148 if (!BrowserThread::CurrentlyOn(BrowserThread::UI)) {
149 DCHECK_CURRENTLY_ON(BrowserThread::IO);
150 BrowserThread::PostTask(
151 BrowserThread::UI, FROM_HERE,
152 Bind(&SyncFileSystemRequestFileSystemFunction::DidOpenFileSystem,
153 this, root_url, file_system_name, error));
154 return;
157 DCHECK_CURRENTLY_ON(BrowserThread::UI);
158 if (error != base::File::FILE_OK) {
159 error_ = ErrorToString(sync_file_system::FileErrorToSyncStatusCode(error));
160 SendResponse(false);
161 return;
164 base::DictionaryValue* dict = new base::DictionaryValue();
165 SetResult(dict);
166 dict->SetString("name", file_system_name);
167 dict->SetString("root", root_url.spec());
168 SendResponse(true);
171 bool SyncFileSystemGetFileStatusFunction::RunImpl() {
172 std::string url;
173 EXTENSION_FUNCTION_VALIDATE(args_->GetString(0, &url));
175 scoped_refptr<fileapi::FileSystemContext> file_system_context =
176 BrowserContext::GetStoragePartition(GetProfile(),
177 render_view_host()->GetSiteInstance())
178 ->GetFileSystemContext();
179 fileapi::FileSystemURL file_system_url(
180 file_system_context->CrackURL(GURL(url)));
182 GetSyncFileSystemService(GetProfile())->GetFileSyncStatus(
183 file_system_url,
184 Bind(&SyncFileSystemGetFileStatusFunction::DidGetFileStatus, this));
185 return true;
188 void SyncFileSystemGetFileStatusFunction::DidGetFileStatus(
189 const SyncStatusCode sync_status_code,
190 const SyncFileStatus sync_file_status) {
191 DCHECK_CURRENTLY_ON(BrowserThread::UI);
192 if (sync_status_code != sync_file_system::SYNC_STATUS_OK) {
193 error_ = ErrorToString(sync_status_code);
194 SendResponse(false);
195 return;
198 // Convert from C++ to JavaScript enum.
199 results_ = api::sync_file_system::GetFileStatus::Results::Create(
200 SyncFileStatusToExtensionEnum(sync_file_status));
201 SendResponse(true);
204 SyncFileSystemGetFileStatusesFunction::SyncFileSystemGetFileStatusesFunction() {
207 SyncFileSystemGetFileStatusesFunction::~SyncFileSystemGetFileStatusesFunction(
208 ) {}
210 bool SyncFileSystemGetFileStatusesFunction::RunImpl() {
211 // All FileEntries converted into array of URL Strings in JS custom bindings.
212 base::ListValue* file_entry_urls = NULL;
213 EXTENSION_FUNCTION_VALIDATE(args_->GetList(0, &file_entry_urls));
215 scoped_refptr<fileapi::FileSystemContext> file_system_context =
216 BrowserContext::GetStoragePartition(GetProfile(),
217 render_view_host()->GetSiteInstance())
218 ->GetFileSystemContext();
220 // Map each file path->SyncFileStatus in the callback map.
221 // TODO(calvinlo): Overload GetFileSyncStatus to take in URL array.
222 num_expected_results_ = file_entry_urls->GetSize();
223 num_results_received_ = 0;
224 file_sync_statuses_.clear();
225 sync_file_system::SyncFileSystemService* sync_file_system_service =
226 GetSyncFileSystemService(GetProfile());
227 for (unsigned int i = 0; i < num_expected_results_; i++) {
228 std::string url;
229 file_entry_urls->GetString(i, &url);
230 fileapi::FileSystemURL file_system_url(
231 file_system_context->CrackURL(GURL(url)));
233 sync_file_system_service->GetFileSyncStatus(
234 file_system_url,
235 Bind(&SyncFileSystemGetFileStatusesFunction::DidGetFileStatus,
236 this, file_system_url));
239 return true;
242 void SyncFileSystemGetFileStatusesFunction::DidGetFileStatus(
243 const fileapi::FileSystemURL& file_system_url,
244 SyncStatusCode sync_status_code,
245 SyncFileStatus sync_file_status) {
246 DCHECK_CURRENTLY_ON(BrowserThread::UI);
247 num_results_received_++;
248 DCHECK_LE(num_results_received_, num_expected_results_);
250 file_sync_statuses_[file_system_url] =
251 std::make_pair(sync_status_code, sync_file_status);
253 // Keep mapping file statuses until all of them have been received.
254 // TODO(calvinlo): Get rid of this check when batch version of
255 // GetFileSyncStatus(GURL urls[]); is added.
256 if (num_results_received_ < num_expected_results_)
257 return;
259 // All results received. Dump array of statuses into extension enum values.
260 // Note that the enum types need to be set as strings manually as the
261 // autogenerated Results::Create function thinks the enum values should be
262 // returned as int values.
263 base::ListValue* status_array = new base::ListValue();
264 for (URLToStatusMap::iterator it = file_sync_statuses_.begin();
265 it != file_sync_statuses_.end(); ++it) {
266 base::DictionaryValue* dict = new base::DictionaryValue();
267 status_array->Append(dict);
269 fileapi::FileSystemURL url = it->first;
270 SyncStatusCode file_error = it->second.first;
271 api::sync_file_system::FileStatus file_status =
272 SyncFileStatusToExtensionEnum(it->second.second);
274 dict->Set("entry", CreateDictionaryValueForFileSystemEntry(
275 url, sync_file_system::SYNC_FILE_TYPE_FILE));
276 dict->SetString("status", ToString(file_status));
278 if (file_error == sync_file_system::SYNC_STATUS_OK)
279 continue;
280 dict->SetString("error", ErrorToString(file_error));
282 SetResult(status_array);
284 SendResponse(true);
287 bool SyncFileSystemGetUsageAndQuotaFunction::RunImpl() {
288 std::string url;
289 EXTENSION_FUNCTION_VALIDATE(args_->GetString(0, &url));
291 scoped_refptr<fileapi::FileSystemContext> file_system_context =
292 BrowserContext::GetStoragePartition(GetProfile(),
293 render_view_host()->GetSiteInstance())
294 ->GetFileSystemContext();
295 fileapi::FileSystemURL file_system_url(
296 file_system_context->CrackURL(GURL(url)));
298 scoped_refptr<quota::QuotaManager> quota_manager =
299 BrowserContext::GetStoragePartition(GetProfile(),
300 render_view_host()->GetSiteInstance())
301 ->GetQuotaManager();
303 BrowserThread::PostTask(
304 BrowserThread::IO,
305 FROM_HERE,
306 Bind(&quota::QuotaManager::GetUsageAndQuotaForWebApps,
307 quota_manager,
308 source_url().GetOrigin(),
309 fileapi::FileSystemTypeToQuotaStorageType(file_system_url.type()),
310 Bind(&SyncFileSystemGetUsageAndQuotaFunction::DidGetUsageAndQuota,
311 this)));
313 return true;
316 void SyncFileSystemGetUsageAndQuotaFunction::DidGetUsageAndQuota(
317 quota::QuotaStatusCode status, int64 usage, int64 quota) {
318 // Repost to switch from IO thread to UI thread for SendResponse().
319 if (!BrowserThread::CurrentlyOn(BrowserThread::UI)) {
320 DCHECK_CURRENTLY_ON(BrowserThread::IO);
321 BrowserThread::PostTask(
322 BrowserThread::UI,
323 FROM_HERE,
324 Bind(&SyncFileSystemGetUsageAndQuotaFunction::DidGetUsageAndQuota, this,
325 status, usage, quota));
326 return;
329 DCHECK_CURRENTLY_ON(BrowserThread::UI);
330 if (status != quota::kQuotaStatusOk) {
331 error_ = QuotaStatusCodeToString(status);
332 SendResponse(false);
333 return;
336 api::sync_file_system::StorageInfo info;
337 info.usage_bytes = usage;
338 info.quota_bytes = quota;
339 results_ = api::sync_file_system::GetUsageAndQuota::Results::Create(info);
340 SendResponse(true);
343 bool SyncFileSystemSetConflictResolutionPolicyFunction::RunSync() {
344 std::string policy_string;
345 EXTENSION_FUNCTION_VALIDATE(args_->GetString(0, &policy_string));
346 ConflictResolutionPolicy policy = ExtensionEnumToConflictResolutionPolicy(
347 api::sync_file_system::ParseConflictResolutionPolicy(policy_string));
348 if (policy == sync_file_system::CONFLICT_RESOLUTION_POLICY_UNKNOWN) {
349 SetError(base::StringPrintf(kUnsupportedConflictResolutionPolicy,
350 policy_string.c_str()));
351 return false;
353 sync_file_system::SyncFileSystemService* service =
354 GetSyncFileSystemService(GetProfile());
355 DCHECK(service);
356 SyncStatusCode status = service->SetConflictResolutionPolicy(
357 source_url().GetOrigin(), policy);
358 if (status != sync_file_system::SYNC_STATUS_OK) {
359 SetError(ErrorToString(status));
360 return false;
362 return true;
365 bool SyncFileSystemGetConflictResolutionPolicyFunction::RunSync() {
366 sync_file_system::SyncFileSystemService* service =
367 GetSyncFileSystemService(GetProfile());
368 DCHECK(service);
369 api::sync_file_system::ConflictResolutionPolicy policy =
370 ConflictResolutionPolicyToExtensionEnum(
371 service->GetConflictResolutionPolicy(source_url().GetOrigin()));
372 SetResult(new base::StringValue(
373 api::sync_file_system::ToString(policy)));
374 return true;
377 bool SyncFileSystemGetServiceStatusFunction::RunSync() {
378 sync_file_system::SyncFileSystemService* service =
379 GetSyncFileSystemService(GetProfile());
380 results_ = api::sync_file_system::GetServiceStatus::Results::Create(
381 SyncServiceStateToExtensionEnum(service->GetSyncServiceState()));
382 return true;
385 } // namespace extensions