Add new certificateProvider extension API.
[chromium-blink-merge.git] / chrome / browser / extensions / api / sync_file_system / sync_file_system_api.cc
blob0b9aafc547c3634fae05f95eb0a23642f37a44ab
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/sync_file_status.h"
17 #include "chrome/browser/sync_file_system/sync_file_system_service.h"
18 #include "chrome/browser/sync_file_system/sync_file_system_service_factory.h"
19 #include "chrome/common/extensions/api/sync_file_system.h"
20 #include "content/public/browser/browser_context.h"
21 #include "content/public/browser/render_frame_host.h"
22 #include "content/public/browser/storage_partition.h"
23 #include "content/public/common/content_client.h"
24 #include "storage/browser/fileapi/file_system_context.h"
25 #include "storage/browser/fileapi/file_system_url.h"
26 #include "storage/browser/quota/quota_manager.h"
27 #include "storage/common/fileapi/file_system_types.h"
28 #include "storage/common/fileapi/file_system_util.h"
30 using content::BrowserContext;
31 using content::BrowserThread;
32 using sync_file_system::ConflictResolutionPolicy;
33 using sync_file_system::SyncFileStatus;
34 using sync_file_system::SyncFileSystemServiceFactory;
35 using sync_file_system::SyncStatusCode;
37 namespace extensions {
39 namespace {
41 // Error messages.
42 const char kErrorMessage[] = "%s (error code: %d).";
43 const char kUnsupportedConflictResolutionPolicy[] =
44 "Policy %s is not supported.";
46 sync_file_system::SyncFileSystemService* GetSyncFileSystemService(
47 Profile* profile) {
48 sync_file_system::SyncFileSystemService* service =
49 SyncFileSystemServiceFactory::GetForProfile(profile);
50 if (!service)
51 return nullptr;
52 ExtensionSyncEventObserver* observer =
53 ExtensionSyncEventObserver::GetFactoryInstance()->Get(profile);
54 if (!observer)
55 return nullptr;
56 observer->InitializeForService(service);
57 return service;
60 std::string ErrorToString(SyncStatusCode code) {
61 return base::StringPrintf(
62 kErrorMessage,
63 sync_file_system::SyncStatusCodeToString(code),
64 static_cast<int>(code));
67 } // namespace
69 bool SyncFileSystemDeleteFileSystemFunction::RunAsync() {
70 std::string url;
71 EXTENSION_FUNCTION_VALIDATE(args_->GetString(0, &url));
73 scoped_refptr<storage::FileSystemContext> file_system_context =
74 BrowserContext::GetStoragePartition(
75 GetProfile(), render_frame_host()->GetSiteInstance())
76 ->GetFileSystemContext();
77 storage::FileSystemURL file_system_url(
78 file_system_context->CrackURL(GURL(url)));
80 BrowserThread::PostTask(
81 BrowserThread::IO,
82 FROM_HERE,
83 Bind(&storage::FileSystemContext::DeleteFileSystem,
84 file_system_context,
85 source_url().GetOrigin(),
86 file_system_url.type(),
87 Bind(&SyncFileSystemDeleteFileSystemFunction::DidDeleteFileSystem,
88 this)));
89 return true;
92 void SyncFileSystemDeleteFileSystemFunction::DidDeleteFileSystem(
93 base::File::Error error) {
94 // Repost to switch from IO thread to UI thread for SendResponse().
95 if (!BrowserThread::CurrentlyOn(BrowserThread::UI)) {
96 DCHECK_CURRENTLY_ON(BrowserThread::IO);
97 BrowserThread::PostTask(
98 BrowserThread::UI,
99 FROM_HERE,
100 Bind(&SyncFileSystemDeleteFileSystemFunction::DidDeleteFileSystem, this,
101 error));
102 return;
105 DCHECK_CURRENTLY_ON(BrowserThread::UI);
106 if (error != base::File::FILE_OK) {
107 error_ = ErrorToString(sync_file_system::FileErrorToSyncStatusCode(error));
108 SetResult(new base::FundamentalValue(false));
109 SendResponse(false);
110 return;
113 SetResult(new base::FundamentalValue(true));
114 SendResponse(true);
117 bool SyncFileSystemRequestFileSystemFunction::RunAsync() {
118 // SyncFileSystem initialization is done in OpenFileSystem below, but we call
119 // GetSyncFileSystemService here too to initialize sync event observer for
120 // extensions API.
121 if (!GetSyncFileSystemService(GetProfile()))
122 return false;
124 // Initializes sync context for this extension and continue to open
125 // a new file system.
126 BrowserThread::PostTask(BrowserThread::IO,
127 FROM_HERE,
128 Bind(&storage::FileSystemContext::OpenFileSystem,
129 GetFileSystemContext(),
130 source_url().GetOrigin(),
131 storage::kFileSystemTypeSyncable,
132 storage::OPEN_FILE_SYSTEM_CREATE_IF_NONEXISTENT,
133 base::Bind(&self::DidOpenFileSystem, this)));
134 return true;
137 storage::FileSystemContext*
138 SyncFileSystemRequestFileSystemFunction::GetFileSystemContext() {
139 DCHECK(render_frame_host());
140 return BrowserContext::GetStoragePartition(
141 GetProfile(), render_frame_host()->GetSiteInstance())
142 ->GetFileSystemContext();
145 void SyncFileSystemRequestFileSystemFunction::DidOpenFileSystem(
146 const GURL& root_url,
147 const std::string& file_system_name,
148 base::File::Error error) {
149 // Repost to switch from IO thread to UI thread for SendResponse().
150 if (!BrowserThread::CurrentlyOn(BrowserThread::UI)) {
151 DCHECK_CURRENTLY_ON(BrowserThread::IO);
152 BrowserThread::PostTask(
153 BrowserThread::UI, FROM_HERE,
154 Bind(&SyncFileSystemRequestFileSystemFunction::DidOpenFileSystem,
155 this, root_url, file_system_name, error));
156 return;
159 DCHECK_CURRENTLY_ON(BrowserThread::UI);
160 if (error != base::File::FILE_OK) {
161 error_ = ErrorToString(sync_file_system::FileErrorToSyncStatusCode(error));
162 SendResponse(false);
163 return;
166 base::DictionaryValue* dict = new base::DictionaryValue();
167 SetResult(dict);
168 dict->SetString("name", file_system_name);
169 dict->SetString("root", root_url.spec());
170 SendResponse(true);
173 bool SyncFileSystemGetFileStatusFunction::RunAsync() {
174 std::string url;
175 EXTENSION_FUNCTION_VALIDATE(args_->GetString(0, &url));
177 scoped_refptr<storage::FileSystemContext> file_system_context =
178 BrowserContext::GetStoragePartition(
179 GetProfile(), render_frame_host()->GetSiteInstance())
180 ->GetFileSystemContext();
181 storage::FileSystemURL file_system_url(
182 file_system_context->CrackURL(GURL(url)));
184 sync_file_system::SyncFileSystemService* sync_file_system_service =
185 GetSyncFileSystemService(GetProfile());
186 if (!sync_file_system_service)
187 return false;
189 sync_file_system_service->GetFileSyncStatus(
190 file_system_url,
191 Bind(&SyncFileSystemGetFileStatusFunction::DidGetFileStatus, this));
192 return true;
195 void SyncFileSystemGetFileStatusFunction::DidGetFileStatus(
196 const SyncStatusCode sync_status_code,
197 const SyncFileStatus sync_file_status) {
198 DCHECK_CURRENTLY_ON(BrowserThread::UI);
199 if (sync_status_code != sync_file_system::SYNC_STATUS_OK) {
200 error_ = ErrorToString(sync_status_code);
201 SendResponse(false);
202 return;
205 // Convert from C++ to JavaScript enum.
206 results_ = api::sync_file_system::GetFileStatus::Results::Create(
207 SyncFileStatusToExtensionEnum(sync_file_status));
208 SendResponse(true);
211 SyncFileSystemGetFileStatusesFunction::SyncFileSystemGetFileStatusesFunction() {
214 SyncFileSystemGetFileStatusesFunction::~SyncFileSystemGetFileStatusesFunction(
215 ) {}
217 bool SyncFileSystemGetFileStatusesFunction::RunAsync() {
218 // All FileEntries converted into array of URL Strings in JS custom bindings.
219 base::ListValue* file_entry_urls = NULL;
220 EXTENSION_FUNCTION_VALIDATE(args_->GetList(0, &file_entry_urls));
222 scoped_refptr<storage::FileSystemContext> file_system_context =
223 BrowserContext::GetStoragePartition(
224 GetProfile(), render_frame_host()->GetSiteInstance())
225 ->GetFileSystemContext();
227 // Map each file path->SyncFileStatus in the callback map.
228 // TODO(calvinlo): Overload GetFileSyncStatus to take in URL array.
229 num_expected_results_ = file_entry_urls->GetSize();
230 num_results_received_ = 0;
231 file_sync_statuses_.clear();
232 sync_file_system::SyncFileSystemService* sync_file_system_service =
233 GetSyncFileSystemService(GetProfile());
234 if (!sync_file_system_service)
235 return false;
237 for (unsigned int i = 0; i < num_expected_results_; i++) {
238 std::string url;
239 file_entry_urls->GetString(i, &url);
240 storage::FileSystemURL file_system_url(
241 file_system_context->CrackURL(GURL(url)));
243 sync_file_system_service->GetFileSyncStatus(
244 file_system_url,
245 Bind(&SyncFileSystemGetFileStatusesFunction::DidGetFileStatus,
246 this, file_system_url));
249 return true;
252 void SyncFileSystemGetFileStatusesFunction::DidGetFileStatus(
253 const storage::FileSystemURL& file_system_url,
254 SyncStatusCode sync_status_code,
255 SyncFileStatus sync_file_status) {
256 DCHECK_CURRENTLY_ON(BrowserThread::UI);
257 num_results_received_++;
258 DCHECK_LE(num_results_received_, num_expected_results_);
260 file_sync_statuses_[file_system_url] =
261 std::make_pair(sync_status_code, sync_file_status);
263 // Keep mapping file statuses until all of them have been received.
264 // TODO(calvinlo): Get rid of this check when batch version of
265 // GetFileSyncStatus(GURL urls[]); is added.
266 if (num_results_received_ < num_expected_results_)
267 return;
269 // All results received. Dump array of statuses into extension enum values.
270 // Note that the enum types need to be set as strings manually as the
271 // autogenerated Results::Create function thinks the enum values should be
272 // returned as int values.
273 base::ListValue* status_array = new base::ListValue();
274 for (URLToStatusMap::iterator it = file_sync_statuses_.begin();
275 it != file_sync_statuses_.end(); ++it) {
276 base::DictionaryValue* dict = new base::DictionaryValue();
277 status_array->Append(dict);
279 storage::FileSystemURL url = it->first;
280 SyncStatusCode file_error = it->second.first;
281 api::sync_file_system::FileStatus file_status =
282 SyncFileStatusToExtensionEnum(it->second.second);
284 dict->Set("entry", CreateDictionaryValueForFileSystemEntry(
285 url, sync_file_system::SYNC_FILE_TYPE_FILE));
286 dict->SetString("status", ToString(file_status));
288 if (file_error == sync_file_system::SYNC_STATUS_OK)
289 continue;
290 dict->SetString("error", ErrorToString(file_error));
292 SetResult(status_array);
294 SendResponse(true);
297 bool SyncFileSystemGetUsageAndQuotaFunction::RunAsync() {
298 std::string url;
299 EXTENSION_FUNCTION_VALIDATE(args_->GetString(0, &url));
301 scoped_refptr<storage::FileSystemContext> file_system_context =
302 BrowserContext::GetStoragePartition(
303 GetProfile(), render_frame_host()->GetSiteInstance())
304 ->GetFileSystemContext();
305 storage::FileSystemURL file_system_url(
306 file_system_context->CrackURL(GURL(url)));
308 scoped_refptr<storage::QuotaManager> quota_manager =
309 BrowserContext::GetStoragePartition(
310 GetProfile(), render_frame_host()->GetSiteInstance())
311 ->GetQuotaManager();
313 BrowserThread::PostTask(
314 BrowserThread::IO,
315 FROM_HERE,
316 Bind(&storage::QuotaManager::GetUsageAndQuotaForWebApps,
317 quota_manager,
318 source_url().GetOrigin(),
319 storage::FileSystemTypeToQuotaStorageType(file_system_url.type()),
320 Bind(&SyncFileSystemGetUsageAndQuotaFunction::DidGetUsageAndQuota,
321 this)));
323 return true;
326 void SyncFileSystemGetUsageAndQuotaFunction::DidGetUsageAndQuota(
327 storage::QuotaStatusCode status,
328 int64 usage,
329 int64 quota) {
330 // Repost to switch from IO thread to UI thread for SendResponse().
331 if (!BrowserThread::CurrentlyOn(BrowserThread::UI)) {
332 DCHECK_CURRENTLY_ON(BrowserThread::IO);
333 BrowserThread::PostTask(
334 BrowserThread::UI,
335 FROM_HERE,
336 Bind(&SyncFileSystemGetUsageAndQuotaFunction::DidGetUsageAndQuota, this,
337 status, usage, quota));
338 return;
341 DCHECK_CURRENTLY_ON(BrowserThread::UI);
342 if (status != storage::kQuotaStatusOk) {
343 error_ = QuotaStatusCodeToString(status);
344 SendResponse(false);
345 return;
348 api::sync_file_system::StorageInfo info;
349 info.usage_bytes = usage;
350 info.quota_bytes = quota;
351 results_ = api::sync_file_system::GetUsageAndQuota::Results::Create(info);
352 SendResponse(true);
355 bool SyncFileSystemSetConflictResolutionPolicyFunction::RunSync() {
356 std::string policy_string;
357 EXTENSION_FUNCTION_VALIDATE(args_->GetString(0, &policy_string));
358 ConflictResolutionPolicy policy = ExtensionEnumToConflictResolutionPolicy(
359 api::sync_file_system::ParseConflictResolutionPolicy(policy_string));
360 if (policy != sync_file_system::CONFLICT_RESOLUTION_POLICY_LAST_WRITE_WIN) {
361 SetError(base::StringPrintf(kUnsupportedConflictResolutionPolicy,
362 policy_string.c_str()));
363 return false;
365 return true;
368 bool SyncFileSystemGetConflictResolutionPolicyFunction::RunSync() {
369 SetResult(new base::StringValue(
370 api::sync_file_system::ToString(
371 api::sync_file_system::CONFLICT_RESOLUTION_POLICY_LAST_WRITE_WIN)));
372 return true;
375 bool SyncFileSystemGetServiceStatusFunction::RunSync() {
376 sync_file_system::SyncFileSystemService* service =
377 GetSyncFileSystemService(GetProfile());
378 if (!service)
379 return false;
380 results_ = api::sync_file_system::GetServiceStatus::Results::Create(
381 SyncServiceStateToExtensionEnum(service->GetSyncServiceState()));
382 return true;
385 } // namespace extensions