| 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 |