OLD | NEW |
| (Empty) |
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 "content/renderer/web_intents_host.h" | |
6 | |
7 #include "base/bind.h" | |
8 #include "base/bind_helpers.h" | |
9 #include "base/utf_string_conversions.h" | |
10 #include "content/common/intents_messages.h" | |
11 #include "content/public/renderer/v8_value_converter.h" | |
12 #include "content/renderer/render_view_impl.h" | |
13 #include "third_party/WebKit/Source/Platform/chromium/public/WebCString.h" | |
14 #include "third_party/WebKit/Source/Platform/chromium/public/WebFileSystem.h" | |
15 #include "third_party/WebKit/Source/Platform/chromium/public/WebString.h" | |
16 #include "third_party/WebKit/Source/Platform/chromium/public/WebVector.h" | |
17 #include "third_party/WebKit/Source/WebKit/chromium/public/WebBindings.h" | |
18 #include "third_party/WebKit/Source/WebKit/chromium/public/WebBlob.h" | |
19 #include "third_party/WebKit/Source/WebKit/chromium/public/WebDeliveredIntentCli
ent.h" | |
20 #include "third_party/WebKit/Source/WebKit/chromium/public/WebDocument.h" | |
21 #include "third_party/WebKit/Source/WebKit/chromium/public/WebFrame.h" | |
22 #include "third_party/WebKit/Source/WebKit/chromium/public/WebIntent.h" | |
23 #include "third_party/WebKit/Source/WebKit/chromium/public/WebIntentRequest.h" | |
24 #include "third_party/WebKit/Source/WebKit/chromium/public/WebSerializedScriptVa
lue.h" | |
25 #include "third_party/WebKit/Source/WebKit/chromium/public/WebView.h" | |
26 #include "webkit/fileapi/file_system_util.h" | |
27 #include "webkit/glue/cpp_bound_class.h" | |
28 | |
29 using WebKit::WebBindings; | |
30 using WebKit::WebBlob; | |
31 using WebKit::WebCString; | |
32 using WebKit::WebDeliveredIntentClient; | |
33 using WebKit::WebFrame; | |
34 using WebKit::WebIntent; | |
35 using WebKit::WebIntentRequest; | |
36 using WebKit::WebString; | |
37 using WebKit::WebSerializedScriptValue; | |
38 using WebKit::WebVector; | |
39 | |
40 namespace content { | |
41 | |
42 namespace { | |
43 | |
44 // Reads reply value, either from the data field, or the data_file field. | |
45 WebSerializedScriptValue GetReplyValue( | |
46 const webkit_glue::WebIntentReply& reply) { | |
47 if (reply.data_file_size > -1) { | |
48 // TODO(smckay): seralize the blob value in the web intent script | |
49 // context. We simply don't know how to do this at this time. | |
50 // The following code kills the renderer when we call toV8Value. | |
51 // v8::HandleScope scope; | |
52 // v8::Local<v8::Context> ctx = ....which context? | |
53 // v8::Context::Scope cscope(ctx); | |
54 // WebKit::WebBlob blob = WebBlob::createFromFile( | |
55 // WebString::fromUTF8(reply.data_file.AsUTF8Unsafe()), | |
56 // reply.data_file_size); | |
57 // v8::Handle<v8::Value> value = blob.toV8Value(); | |
58 // return WebSerializedScriptValue::serialize(value); | |
59 return WebSerializedScriptValue::fromString( | |
60 ASCIIToUTF16(reply.data_file.AsUTF8Unsafe())); | |
61 } else { | |
62 return WebSerializedScriptValue::fromString(reply.data); | |
63 } | |
64 } | |
65 | |
66 } // namespace | |
67 | |
68 class DeliveredIntentClientImpl : public WebDeliveredIntentClient { | |
69 public: | |
70 explicit DeliveredIntentClientImpl(WebIntentsHost* host) : host_(host) {} | |
71 virtual ~DeliveredIntentClientImpl() {} | |
72 | |
73 virtual void postResult(const WebSerializedScriptValue& data) const { | |
74 host_->OnResult(data.toString()); | |
75 } | |
76 | |
77 virtual void postFailure(const WebSerializedScriptValue& data) const { | |
78 host_->OnFailure(data.toString()); | |
79 } | |
80 | |
81 virtual void destroy() OVERRIDE { | |
82 } | |
83 | |
84 private: | |
85 WebIntentsHost* host_; | |
86 }; | |
87 | |
88 WebIntentsHost::WebIntentsHost(RenderViewImpl* render_view) | |
89 : RenderViewObserver(render_view), | |
90 id_counter_(0) { | |
91 } | |
92 | |
93 WebIntentsHost::~WebIntentsHost() { | |
94 } | |
95 | |
96 int WebIntentsHost::RegisterWebIntent( | |
97 const WebIntentRequest& request) { | |
98 int id = id_counter_++; | |
99 intent_requests_[id] = request; | |
100 return id; | |
101 } | |
102 | |
103 bool WebIntentsHost::OnMessageReceived(const IPC::Message& message) { | |
104 bool handled = true; | |
105 IPC_BEGIN_MESSAGE_MAP(WebIntentsHost, message) | |
106 IPC_MESSAGE_HANDLER(IntentsMsg_SetWebIntentData, OnSetIntent) | |
107 IPC_MESSAGE_HANDLER(IntentsMsg_WebIntentReply, OnWebIntentReply); | |
108 IPC_MESSAGE_UNHANDLED(handled = false) | |
109 IPC_END_MESSAGE_MAP() | |
110 return handled; | |
111 } | |
112 | |
113 void WebIntentsHost::OnSetIntent(const webkit_glue::WebIntentData& intent) { | |
114 intent_.reset(new webkit_glue::WebIntentData(intent)); | |
115 } | |
116 | |
117 void WebIntentsHost::OnWebIntentReply( | |
118 const webkit_glue::WebIntentReply& reply, | |
119 int intent_id) { | |
120 std::map<int, WebIntentRequest>::iterator request = | |
121 intent_requests_.find(intent_id); | |
122 if (request == intent_requests_.end()) | |
123 return; | |
124 WebIntentRequest intent_request = request->second; | |
125 intent_requests_.erase(request); | |
126 | |
127 if (reply.type == webkit_glue::WEB_INTENT_REPLY_SUCCESS) { | |
128 intent_request.postResult(GetReplyValue(reply)); | |
129 } else { | |
130 intent_request.postFailure( | |
131 WebSerializedScriptValue::fromString(reply.data)); | |
132 } | |
133 } | |
134 | |
135 void WebIntentsHost::OnResult(const WebKit::WebString& data) { | |
136 const webkit_glue::WebIntentReply reply( | |
137 webkit_glue::WEB_INTENT_REPLY_SUCCESS, data); | |
138 Send(new IntentsHostMsg_WebIntentReply(routing_id(), reply)); | |
139 } | |
140 | |
141 void WebIntentsHost::OnFailure(const WebKit::WebString& data) { | |
142 const webkit_glue::WebIntentReply reply( | |
143 webkit_glue::WEB_INTENT_REPLY_FAILURE, data); | |
144 Send(new IntentsHostMsg_WebIntentReply(routing_id(), reply)); | |
145 } | |
146 | |
147 // We set the intent payload into all top-level frame window objects. This | |
148 // should persist the data through redirects, and not deliver it to any | |
149 // sub-frames. | |
150 void WebIntentsHost::DidCreateScriptContext(WebKit::WebFrame* frame, | |
151 v8::Handle<v8::Context> ctx, | |
152 int extension_group, | |
153 int world_id) { | |
154 if (intent_.get() == NULL || frame->top() != frame) | |
155 return; | |
156 | |
157 if (ctx != frame->mainWorldScriptContext()) | |
158 return; | |
159 | |
160 if (!delivered_intent_client_.get()) { | |
161 delivered_intent_client_.reset(new DeliveredIntentClientImpl(this)); | |
162 } | |
163 | |
164 WebIntent web_intent = CreateWebIntent(frame, *intent_); | |
165 | |
166 if (!web_intent.action().isEmpty()) | |
167 frame->deliverIntent(web_intent, NULL, delivered_intent_client_.get()); | |
168 } | |
169 | |
170 WebIntent WebIntentsHost::CreateWebIntent( | |
171 WebFrame* frame, const webkit_glue::WebIntentData& intent_data) { | |
172 // Must be called with v8 scope held. | |
173 DCHECK(v8::Context::InContext()); | |
174 | |
175 // TODO(gbillock): Remove this block when we get rid of |extras|. | |
176 WebVector<WebString> extras_keys(intent_data.extra_data.size()); | |
177 WebVector<WebString> extras_values(intent_data.extra_data.size()); | |
178 std::map<string16, string16>::const_iterator iter = | |
179 intent_data.extra_data.begin(); | |
180 for (size_t i = 0; iter != intent_data.extra_data.end(); ++i, ++iter) { | |
181 extras_keys[i] = iter->first; | |
182 extras_values[i] = iter->second; | |
183 } | |
184 | |
185 switch (intent_data.data_type) { | |
186 case webkit_glue::WebIntentData::SERIALIZED: { | |
187 return WebIntent::create(intent_data.action, intent_data.type, | |
188 intent_data.data, | |
189 extras_keys, extras_values); | |
190 } | |
191 | |
192 case webkit_glue::WebIntentData::UNSERIALIZED: { | |
193 v8::Local<v8::String> dataV8 = v8::String::New( | |
194 reinterpret_cast<const uint16_t*>( | |
195 intent_data.unserialized_data.data()), | |
196 static_cast<int>(intent_data.unserialized_data.length())); | |
197 WebSerializedScriptValue serialized_data = | |
198 WebSerializedScriptValue::serialize(dataV8); | |
199 | |
200 return WebIntent::create(intent_data.action, intent_data.type, | |
201 serialized_data.toString(), | |
202 extras_keys, extras_values); | |
203 } | |
204 | |
205 case webkit_glue::WebIntentData::BLOB: { | |
206 web_blob_ = WebBlob::createFromFile( | |
207 WebString::fromUTF8(intent_data.blob_file.AsUTF8Unsafe()), | |
208 intent_data.blob_length); | |
209 WebSerializedScriptValue serialized_data = | |
210 WebSerializedScriptValue::serialize(web_blob_.toV8Value()); | |
211 return WebIntent::create(intent_data.action, intent_data.type, | |
212 serialized_data.toString(), | |
213 extras_keys, extras_values); | |
214 } | |
215 | |
216 case webkit_glue::WebIntentData::FILESYSTEM: { | |
217 const GURL origin = GURL(frame->document().securityOrigin().toString()); | |
218 const GURL root_url = | |
219 fileapi::GetFileSystemRootURI(origin, | |
220 fileapi::kFileSystemTypeIsolated); | |
221 const std::string url = base::StringPrintf( | |
222 "%s%s/%s/", | |
223 root_url.spec().c_str(), | |
224 intent_data.filesystem_id.c_str(), | |
225 intent_data.root_name.c_str()); | |
226 // TODO(kmadhusu): This is a temporary hack to create a serializable file | |
227 // system. Once we have a better way to create a serializable file system, | |
228 // remove this hack. | |
229 v8::Handle<v8::Value> filesystem_V8 = frame->createSerializableFileSystem( | |
230 WebKit::WebFileSystem::TypeIsolated, | |
231 WebKit::WebString::fromUTF8(intent_data.root_name), | |
232 WebKit::WebString::fromUTF8(url)); | |
233 WebSerializedScriptValue serialized_data = | |
234 WebSerializedScriptValue::serialize(filesystem_V8); | |
235 return WebIntent::create(intent_data.action, intent_data.type, | |
236 serialized_data.toString(), | |
237 extras_keys, extras_values); | |
238 } | |
239 | |
240 case webkit_glue::WebIntentData::MIME_TYPE: { | |
241 scoped_ptr<V8ValueConverter> converter( | |
242 V8ValueConverter::create()); | |
243 v8::Handle<v8::Value> valV8 = converter->ToV8Value( | |
244 &intent_data.mime_data, v8::Context::GetCurrent()); | |
245 | |
246 WebSerializedScriptValue serialized_data = | |
247 WebSerializedScriptValue::serialize(valV8); | |
248 return WebIntent::create(intent_data.action, intent_data.type, | |
249 serialized_data.toString(), | |
250 WebVector<WebString>(), WebVector<WebString>()); | |
251 } | |
252 } | |
253 | |
254 NOTREACHED(); | |
255 return WebIntent(); | |
256 } | |
257 | |
258 } // namespace content | |
OLD | NEW |