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