91e134405eafdc85b2947e79c16488abc28c917c
[platform/framework/web/crosswalk.git] / src / xwalk / experimental / native_file_system / native_file_system_extension.cc
1 // Copyright (c) 2014 Intel Corporation. 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 "xwalk/experimental/native_file_system/native_file_system_extension.h"
6
7 #include <algorithm>
8 #include <map>
9
10 #include "base/json/json_reader.h"
11 #include "base/json/json_writer.h"
12 #include "content/public/browser/browser_thread.h"
13 #include "content/public/browser/child_process_security_policy.h"
14 #include "grit/xwalk_resources.h"
15 #include "ui/base/resource/resource_bundle.h"
16 #include "webkit/browser/fileapi/isolated_context.h"
17 #include "xwalk/experimental/native_file_system/virtual_root_provider.h"
18
19 namespace xwalk {
20 namespace experimental {
21
22 NativeFileSystemExtension::NativeFileSystemExtension(
23     content::RenderProcessHost* host) {
24   host_ = host;
25   set_name("xwalk.experimental.native_file_system");
26   set_javascript_api(
27       ResourceBundle::GetSharedInstance().GetRawDataResource(
28           IDR_XWALK_NATIVE_FILE_SYSTEM_API).as_string());
29 }
30
31 NativeFileSystemExtension::~NativeFileSystemExtension() {}
32
33 XWalkExtensionInstance* NativeFileSystemExtension::CreateInstance() {
34   return new NativeFileSystemInstance(host_);
35 }
36
37 NativeFileSystemInstance::NativeFileSystemInstance(
38     content::RenderProcessHost* host)
39     : handler_(this),
40       host_(host) {
41 }
42
43 void NativeFileSystemInstance::HandleMessage(scoped_ptr<base::Value> msg) {
44   base::DictionaryValue* msg_value = NULL;
45   if (!msg->GetAsDictionary(&msg_value) || NULL == msg_value) {
46     LOG(ERROR) << "Message object should be a dictionary.";
47     return;
48   }
49   std::string promise_id_string;
50   if (!msg_value->GetString("_promise_id", &promise_id_string)) {
51     LOG(ERROR) << "Invalide promise id.";
52     return;
53   }
54   std::string cmd_string;
55   if (!msg_value->GetString("cmd", &cmd_string) ||
56       "requestNativeFileSystem" != cmd_string) {
57     LOG(ERROR) << "Invalide cmd: " << cmd_string;
58     return;
59   }
60   std::string virtual_root_string;
61   if (!msg_value->GetString("data.virtual_root", &virtual_root_string)) {
62     LOG(ERROR) << "Invalide virtual root: " << virtual_root_string;
63     return;
64   }
65
66   std::string upper_virtual_root_string = virtual_root_string;
67   std::transform(upper_virtual_root_string.begin(),
68       upper_virtual_root_string.end(),
69       upper_virtual_root_string.begin(),
70       ::toupper);
71   std::string real_path =
72       VirtualRootProvider::GetInstance()->GetRealPath(
73           upper_virtual_root_string);
74   if (real_path.empty()) {
75     const scoped_ptr<base::DictionaryValue> res(new base::DictionaryValue());
76     res->SetString("_promise_id", promise_id_string);
77     res->SetString("cmd", "requestNativeFileSystem_ret");
78     res->SetBoolean("data.error", true);
79     res->SetString("data.errorMessage", "Invalide name of virtual root.");
80     std::string msg_string;
81     base::JSONWriter::Write(res.get(), &msg_string);
82     PostMessageToJS(scoped_ptr<base::Value>(new base::StringValue(msg_string)));
83     return;
84   }
85
86   scoped_refptr<FileSystemChecker> checker(
87       new FileSystemChecker(host_->GetID(),
88                             real_path,
89                             virtual_root_string,
90                             promise_id_string,
91                             this));
92   checker->DoTask();
93 }
94
95 FileSystemChecker::FileSystemChecker(
96     int process_id,
97     const std::string& path,
98     const std::string& root_name,
99     const std::string& promise_id,
100     XWalkExtensionInstance* instance)
101     : process_id_(process_id),
102       path_(path),
103       root_name_(root_name),
104       promise_id_(promise_id),
105       instance_(instance) {
106 }
107
108 void FileSystemChecker::DoTask() {
109   content::BrowserThread::PostTask(
110       content::BrowserThread::UI,
111       FROM_HERE,
112       base::Bind(&FileSystemChecker::RegisterFileSystemsAndSendResponse, this));
113 }
114
115 void FileSystemChecker::RegisterFileSystemsAndSendResponse() {
116   CHECK(content::BrowserThread::CurrentlyOn(content::BrowserThread::UI));
117   fileapi::IsolatedContext* isolated_context =
118       fileapi::IsolatedContext::GetInstance();
119   CHECK(isolated_context);
120
121   std::string filesystem_id = isolated_context->RegisterFileSystemForPath(
122       fileapi::kFileSystemTypeNativeForPlatformApp,
123       std::string(),
124       base::FilePath::FromUTF8Unsafe(path_),
125       &root_name_);
126
127   content::ChildProcessSecurityPolicy* policy =
128       content::ChildProcessSecurityPolicy::GetInstance();
129   policy->GrantCreateReadWriteFileSystem(process_id_, filesystem_id);
130
131   const scoped_ptr<base::DictionaryValue> res(new base::DictionaryValue());
132   res->SetString("_promise_id", promise_id_);
133   res->SetString("cmd", "requestNativeFileSystem_ret");
134   res->SetBoolean("data.error", false);
135   res->SetString("data.file_system_id", filesystem_id);
136   std::string msg_string;
137   base::JSONWriter::Write(res.get(), &msg_string);
138   instance_->PostMessageToJS(
139       scoped_ptr<base::Value>(
140           new base::StringValue(msg_string)));
141 }
142
143 }  // namespace experimental
144 }  // namespace xwalk