summaryrefslogtreecommitdiffstats
path: root/content
diff options
context:
space:
mode:
authorgbillock@chromium.org <gbillock@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98>2012-10-16 20:41:20 +0000
committergbillock@chromium.org <gbillock@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98>2012-10-16 20:41:20 +0000
commit7a137c9deed67a943c21f82d0a9c71112da5d603 (patch)
tree776060f62eb90aebdbe304654d176772705f0922 /content
parent84a9361de5e11561f59becc0b38a707fff8da198 (diff)
downloadchromium_src-7a137c9deed67a943c21f82d0a9c71112da5d603.zip
chromium_src-7a137c9deed67a943c21f82d0a9c71112da5d603.tar.gz
chromium_src-7a137c9deed67a943c21f82d0a9c71112da5d603.tar.bz2
Add API to construct new vector interchange MIME data type.
Add test for web intents host. R=groby@chromium.org BUG=153695 Review URL: https://chromiumcodereview.appspot.com/11026070 git-svn-id: svn://svn.chromium.org/chrome/trunk/src@162239 0039d316-1c4b-4281-b951-d872f2087c98
Diffstat (limited to 'content')
-rw-r--r--content/browser/intents/intent_injector.cc7
-rw-r--r--content/content_tests.gypi1
-rw-r--r--content/renderer/render_view_impl.cc3
-rw-r--r--content/renderer/render_view_impl.h1
-rw-r--r--content/renderer/web_intents_host.cc159
-rw-r--r--content/renderer/web_intents_host.h34
-rw-r--r--content/renderer/web_intents_host_browsertest.cc120
7 files changed, 248 insertions, 77 deletions
diff --git a/content/browser/intents/intent_injector.cc b/content/browser/intents/intent_injector.cc
index 6645760..28cd1e2 100644
--- a/content/browser/intents/intent_injector.cc
+++ b/content/browser/intents/intent_injector.cc
@@ -82,8 +82,11 @@ void IntentInjector::RenderViewCreated(RenderViewHost* render_view_host) {
return;
}
- if (source_intent_->data_type == webkit_glue::WebIntentData::BLOB) {
- // Grant read permission on the blob file to the delivered context.
+ // If we're passing a browser-originated blob, either directly or as part of a
+ // payload, grant read permission on the blob file to the delivered context.
+ if (source_intent_->data_type == webkit_glue::WebIntentData::BLOB ||
+ (source_intent_->data_type == webkit_glue::WebIntentData::MIME_TYPE &&
+ !source_intent_->blob_file.empty())) {
const int child_id = render_view_host->GetProcess()->GetID();
ChildProcessSecurityPolicy* policy =
ChildProcessSecurityPolicy::GetInstance();
diff --git a/content/content_tests.gypi b/content/content_tests.gypi
index 19fd56c..5473342 100644
--- a/content/content_tests.gypi
+++ b/content/content_tests.gypi
@@ -699,6 +699,7 @@
'renderer/render_view_browsertest_mac.mm',
'renderer/render_widget_browsertest.cc',
'renderer/renderer_accessibility_browsertest.cc',
+ 'renderer/web_intents_host_browsertest.cc',
'test/content_browser_test.h',
'test/content_browser_test.cc',
'test/content_browser_test_utils.cc',
diff --git a/content/renderer/render_view_impl.cc b/content/renderer/render_view_impl.cc
index b2eb191..e9dd481 100644
--- a/content/renderer/render_view_impl.cc
+++ b/content/renderer/render_view_impl.cc
@@ -3794,6 +3794,9 @@ void RenderViewImpl::didCreateScriptContext(WebFrame* frame,
int world_id) {
content::GetContentClient()->renderer()->DidCreateScriptContext(
frame, context, extension_group, world_id);
+
+ intents_host_->DidCreateScriptContext(
+ frame, context, extension_group, world_id);
}
void RenderViewImpl::willReleaseScriptContext(WebFrame* frame,
diff --git a/content/renderer/render_view_impl.h b/content/renderer/render_view_impl.h
index 2219c97..b3a4f2b 100644
--- a/content/renderer/render_view_impl.h
+++ b/content/renderer/render_view_impl.h
@@ -802,6 +802,7 @@ class RenderViewImpl : public RenderWidget,
friend class ExternalPopupMenuTest;
friend class PepperDeviceTest;
friend class RendererAccessibilityTest;
+ friend class WebIntentsHostTest;
friend class content::RenderViewTest;
FRIEND_TEST_ALL_PREFIXES(ExternalPopupMenuRemoveTest, RemoveOnChange);
diff --git a/content/renderer/web_intents_host.cc b/content/renderer/web_intents_host.cc
index 9c60da3..933f41a 100644
--- a/content/renderer/web_intents_host.cc
+++ b/content/renderer/web_intents_host.cc
@@ -8,6 +8,7 @@
#include "base/bind_helpers.h"
#include "base/utf_string_conversions.h"
#include "content/common/intents_messages.h"
+#include "content/public/renderer/v8_value_converter.h"
#include "content/renderer/render_view_impl.h"
#include "ipc/ipc_message.h"
#include "third_party/WebKit/Source/WebKit/chromium/public/WebBindings.h"
@@ -23,7 +24,6 @@
#include "third_party/WebKit/Source/WebKit/chromium/public/platform/WebSerializedScriptValue.h"
#include "third_party/WebKit/Source/WebKit/chromium/public/platform/WebString.h"
#include "third_party/WebKit/Source/WebKit/chromium/public/platform/WebVector.h"
-#include "v8/include/v8.h"
#include "webkit/fileapi/file_system_util.h"
#include "webkit/glue/cpp_bound_class.h"
@@ -120,81 +120,110 @@ void WebIntentsHost::OnFailure(const WebKit::WebString& data) {
// We set the intent payload into all top-level frame window objects. This
// should persist the data through redirects, and not deliver it to any
// sub-frames.
-// TODO(gbillock): match to spec to double-check registration match before
-// delivery.
-void WebIntentsHost::DidClearWindowObject(WebFrame* frame) {
+void WebIntentsHost::DidCreateScriptContext(WebKit::WebFrame* frame,
+ v8::Handle<v8::Context> ctx,
+ int extension_group,
+ int world_id) {
if (intent_.get() == NULL || frame->top() != frame)
return;
+ if (ctx != frame->mainWorldScriptContext())
+ return;
+
if (!delivered_intent_client_.get()) {
delivered_intent_client_.reset(new DeliveredIntentClientImpl(this));
}
- WebVector<WebString> extras_keys(intent_->extra_data.size());
- WebVector<WebString> extras_values(intent_->extra_data.size());
- std::map<string16, string16>::iterator iter;
- int i;
- for (i = 0, iter = intent_->extra_data.begin();
- iter != intent_->extra_data.end();
- ++i, ++iter) {
+ WebIntent web_intent = CreateWebIntent(frame, *intent_);
+
+ if (!web_intent.action().isEmpty())
+ frame->deliverIntent(web_intent, NULL, delivered_intent_client_.get());
+}
+
+WebIntent WebIntentsHost::CreateWebIntent(
+ WebFrame* frame, const webkit_glue::WebIntentData& intent_data) {
+ // Must be called with v8 scope held.
+ DCHECK(v8::Context::InContext());
+
+ // TODO(gbillock): Remove this block when we get rid of |extras|.
+ WebVector<WebString> extras_keys(intent_data.extra_data.size());
+ WebVector<WebString> extras_values(intent_data.extra_data.size());
+ std::map<string16, string16>::const_iterator iter =
+ intent_data.extra_data.begin();
+ for (size_t i = 0; iter != intent_data.extra_data.end(); ++i, ++iter) {
extras_keys[i] = iter->first;
extras_values[i] = iter->second;
}
- v8::HandleScope scope;
- v8::Local<v8::Context> ctx = frame->mainWorldScriptContext();
- v8::Context::Scope cscope(ctx);
- WebIntent web_intent;
-
- if (intent_->data_type == webkit_glue::WebIntentData::SERIALIZED) {
- web_intent = WebIntent::create(intent_->action, intent_->type,
- intent_->data,
- extras_keys, extras_values);
- } else if (intent_->data_type == webkit_glue::WebIntentData::UNSERIALIZED) {
- v8::Local<v8::String> dataV8 = v8::String::New(
- reinterpret_cast<const uint16_t*>(intent_->unserialized_data.data()),
- static_cast<int>(intent_->unserialized_data.length()));
- WebSerializedScriptValue serialized_data =
- WebSerializedScriptValue::serialize(dataV8);
-
- web_intent = WebIntent::create(intent_->action, intent_->type,
- serialized_data.toString(),
- extras_keys, extras_values);
- } else if (intent_->data_type == webkit_glue::WebIntentData::BLOB) {
- DCHECK(intent_->data_type == webkit_glue::WebIntentData::BLOB);
- web_blob_ = WebBlob::createFromFile(
- WebString::fromUTF8(intent_->blob_file.AsUTF8Unsafe()),
- intent_->blob_length);
- WebSerializedScriptValue serialized_data =
- WebSerializedScriptValue::serialize(web_blob_.toV8Value());
- web_intent = WebIntent::create(intent_->action, intent_->type,
- serialized_data.toString(),
- extras_keys, extras_values);
- } else if (intent_->data_type == webkit_glue::WebIntentData::FILESYSTEM) {
- const GURL origin = GURL(frame->document().securityOrigin().toString());
- const GURL root_url =
- fileapi::GetFileSystemRootURI(origin, fileapi::kFileSystemTypeIsolated);
- const std::string url = base::StringPrintf(
- "%s%s/%s/",
- root_url.spec().c_str(),
- intent_->filesystem_id.c_str(),
- intent_->root_name.c_str());
- // TODO(kmadhusu): This is a temporary hack to create a serializable file
- // system. Once we have a better way to create a serializable file system,
- // remove this hack.
- v8::Handle<v8::Value> filesystem_V8 = frame->createSerializableFileSystem(
- WebKit::WebFileSystem::TypeIsolated,
- WebKit::WebString::fromUTF8(intent_->root_name),
- WebKit::WebString::fromUTF8(url));
- WebSerializedScriptValue serialized_data =
- WebSerializedScriptValue::serialize(filesystem_V8);
- web_intent = WebIntent::create(intent_->action, intent_->type,
- serialized_data.toString(),
- extras_keys, extras_values);
- } else {
- NOTREACHED();
+ switch (intent_data.data_type) {
+ case webkit_glue::WebIntentData::SERIALIZED: {
+ return WebIntent::create(intent_data.action, intent_data.type,
+ intent_data.data,
+ extras_keys, extras_values);
+ }
+
+ case webkit_glue::WebIntentData::UNSERIALIZED: {
+ v8::Local<v8::String> dataV8 = v8::String::New(
+ reinterpret_cast<const uint16_t*>(
+ intent_data.unserialized_data.data()),
+ static_cast<int>(intent_data.unserialized_data.length()));
+ WebSerializedScriptValue serialized_data =
+ WebSerializedScriptValue::serialize(dataV8);
+
+ return WebIntent::create(intent_data.action, intent_data.type,
+ serialized_data.toString(),
+ extras_keys, extras_values);
+ }
+
+ case webkit_glue::WebIntentData::BLOB: {
+ web_blob_ = WebBlob::createFromFile(
+ WebString::fromUTF8(intent_data.blob_file.AsUTF8Unsafe()),
+ intent_data.blob_length);
+ WebSerializedScriptValue serialized_data =
+ WebSerializedScriptValue::serialize(web_blob_.toV8Value());
+ return WebIntent::create(intent_data.action, intent_data.type,
+ serialized_data.toString(),
+ extras_keys, extras_values);
+ }
+
+ case webkit_glue::WebIntentData::FILESYSTEM: {
+ const GURL origin = GURL(frame->document().securityOrigin().toString());
+ const GURL root_url =
+ fileapi::GetFileSystemRootURI(origin,
+ fileapi::kFileSystemTypeIsolated);
+ const std::string url = base::StringPrintf(
+ "%s%s/%s/",
+ root_url.spec().c_str(),
+ intent_data.filesystem_id.c_str(),
+ intent_data.root_name.c_str());
+ // TODO(kmadhusu): This is a temporary hack to create a serializable file
+ // system. Once we have a better way to create a serializable file system,
+ // remove this hack.
+ v8::Handle<v8::Value> filesystem_V8 = frame->createSerializableFileSystem(
+ WebKit::WebFileSystem::TypeIsolated,
+ WebKit::WebString::fromUTF8(intent_data.root_name),
+ WebKit::WebString::fromUTF8(url));
+ WebSerializedScriptValue serialized_data =
+ WebSerializedScriptValue::serialize(filesystem_V8);
+ return WebIntent::create(intent_data.action, intent_data.type,
+ serialized_data.toString(),
+ extras_keys, extras_values);
+ }
+
+ case webkit_glue::WebIntentData::MIME_TYPE: {
+ scoped_ptr<content::V8ValueConverter> converter(
+ content::V8ValueConverter::create());
+ v8::Handle<v8::Value> valV8 = converter->ToV8Value(
+ &intent_data.mime_data, v8::Context::GetCurrent());
+
+ WebSerializedScriptValue serialized_data =
+ WebSerializedScriptValue::serialize(valV8);
+ return WebIntent::create(intent_data.action, intent_data.type,
+ serialized_data.toString(),
+ WebVector<WebString>(), WebVector<WebString>());
+ }
}
- if (!web_intent.action().isEmpty())
- frame->deliverIntent(web_intent, NULL, delivered_intent_client_.get());
+ NOTREACHED();
+ return WebIntent();
}
diff --git a/content/renderer/web_intents_host.h b/content/renderer/web_intents_host.h
index 0116492..3556d76 100644
--- a/content/renderer/web_intents_host.h
+++ b/content/renderer/web_intents_host.h
@@ -10,7 +10,9 @@
#include "base/memory/scoped_ptr.h"
#include "content/public/renderer/render_view_observer.h"
#include "third_party/WebKit/Source/WebKit/chromium/public/WebBlob.h"
+#include "third_party/WebKit/Source/WebKit/chromium/public/WebIntent.h"
#include "third_party/WebKit/Source/WebKit/chromium/public/platform/WebString.h"
+#include "v8/include/v8.h"
#include "webkit/glue/web_intent_data.h"
#include "webkit/glue/web_intent_reply_data.h"
@@ -43,25 +45,27 @@ class WebIntentsHost : public content::RenderViewObserver {
// Called into when the delivered intent object gets a postFailure call.
void OnFailure(const WebKit::WebString& data);
- private:
- // A counter used to assign unique IDs to web intents invocations in this
- // renderer.
- int id_counter_;
-
- // Map tracking registered Web Intent requests by assigned ID numbers to
- // correctly route any return data.
- std::map<int, WebKit::WebIntentRequest> intent_requests_;
+ // Forwarded from RenderViewImpl. Notification that a new script context was
+ // created within webkit.
+ virtual void DidCreateScriptContext(WebKit::WebFrame* frame,
+ v8::Handle<v8::Context> ctx,
+ int extension_group,
+ int world_id);
+ private:
// RenderView::Observer implementation.
virtual bool OnMessageReceived(const IPC::Message& message) OVERRIDE;
- virtual void DidClearWindowObject(WebKit::WebFrame* frame) OVERRIDE;
+
+ // Converts incoming intent data to a WebIntent object.
+ WebKit::WebIntent CreateWebIntent(
+ WebKit::WebFrame* frame, const webkit_glue::WebIntentData& intent_data);
// TODO(gbillock): Do we need various ***ClientRedirect methods to implement
// intent cancelling policy? Figure this out.
// On the service page, handler method for the IntentsMsg_SetWebIntent
// message.
- void OnSetIntent(const webkit_glue::WebIntentData& intent);
+ CONTENT_EXPORT void OnSetIntent(const webkit_glue::WebIntentData& intent);
// On the client page, handler method for the IntentsMsg_WebIntentReply
// message. Forwards the reply |data| to the registered WebIntentRequest
@@ -70,6 +74,16 @@ class WebIntentsHost : public content::RenderViewObserver {
const WebKit::WebString& data,
int intent_id);
+ friend class WebIntentsHostTest;
+
+ // A counter used to assign unique IDs to web intents invocations in this
+ // renderer.
+ int id_counter_;
+
+ // Map tracking registered Web Intent requests by assigned ID numbers to
+ // correctly route any return data.
+ std::map<int, WebKit::WebIntentRequest> intent_requests_;
+
// Delivered intent data from the caller.
scoped_ptr<webkit_glue::WebIntentData> intent_;
diff --git a/content/renderer/web_intents_host_browsertest.cc b/content/renderer/web_intents_host_browsertest.cc
new file mode 100644
index 0000000..9f2abc7
--- /dev/null
+++ b/content/renderer/web_intents_host_browsertest.cc
@@ -0,0 +1,120 @@
+// Copyright (c) 2012 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "base/gtest_prod_util.h"
+#include "base/values.h"
+#include "base/utf_string_conversions.h"
+#include "content/common/intents_messages.h"
+#include "content/public/renderer/v8_value_converter.h"
+#include "content/public/test/render_view_test.h"
+#include "content/renderer/render_view_impl.h"
+#include "content/renderer/web_intents_host.h"
+#include "third_party/WebKit/Source/WebKit/chromium/public/WebDeliveredIntentClient.h"
+#include "third_party/WebKit/Source/WebKit/chromium/public/platform/WebSerializedScriptValue.h"
+#include "webkit/glue/web_intent_data.h"
+
+class WebIntentsHostTest : public content::RenderViewTest {
+ protected:
+ RenderViewImpl* view() { return static_cast<RenderViewImpl*>(view_); }
+ WebIntentsHost* web_intents_host() { return view()->intents_host_; }
+
+ void SetIntentData(const webkit_glue::WebIntentData& data) {
+ web_intents_host()->OnSetIntent(data);
+ }
+
+ base::DictionaryValue* ParseValueFromReply(const IPC::Message* reply_msg) {
+ IntentsHostMsg_WebIntentReply::Param reply_params;
+ IntentsHostMsg_WebIntentReply::Read(reply_msg, &reply_params);
+ WebKit::WebSerializedScriptValue serialized_data =
+ WebKit::WebSerializedScriptValue::fromString(reply_params.b);
+
+ v8::HandleScope scope;
+ v8::Local<v8::Context> ctx = GetMainFrame()->mainWorldScriptContext();
+ v8::Context::Scope cscope(ctx);
+ v8::Handle<v8::Value> v8_val = serialized_data.deserialize();
+ scoped_ptr<content::V8ValueConverter> converter(
+ content::V8ValueConverter::create());
+ base::Value* reply = converter->FromV8Value(v8_val, ctx);
+ EXPECT_TRUE(reply->IsType(base::Value::TYPE_DICTIONARY));
+ base::DictionaryValue* dict = NULL;
+ reply->GetAsDictionary(&dict);
+ return dict;
+ }
+};
+
+TEST_F(WebIntentsHostTest, TestUnserialized) {
+ webkit_glue::WebIntentData data(ASCIIToUTF16("action"), ASCIIToUTF16("type"),
+ ASCIIToUTF16("unserialized data"));
+ SetIntentData(data);
+
+ LoadHTML("<html>"
+ "<head><script>\n"
+ "var d = {};\n"
+ "d.action = window.webkitIntent.action;\n"
+ "d.type = window.webkitIntent.type;\n"
+ "d.data = window.webkitIntent.data;\n"
+ "window.webkitIntent.postResult(d);\n"
+ "</script></head>"
+ "<body>body</body></html>");
+
+ const IPC::Message* reply_msg =
+ render_thread_->sink().GetUniqueMessageMatching(
+ IntentsHostMsg_WebIntentReply::ID);
+ ASSERT_TRUE(reply_msg);
+ scoped_ptr<base::DictionaryValue> dict(ParseValueFromReply(reply_msg));
+
+ std::string reply_action;
+ dict->GetStringASCII(std::string("action"), &reply_action);
+ EXPECT_EQ("action", reply_action);
+ std::string reply_type;
+ dict->GetStringASCII(std::string("type"), &reply_type);
+ EXPECT_EQ("type", reply_type);
+ std::string reply_data;
+ dict->GetStringASCII(std::string("data"), &reply_data);
+ EXPECT_EQ("unserialized data", reply_data);
+}
+
+TEST_F(WebIntentsHostTest, TestVector) {
+ webkit_glue::WebIntentData data(ASCIIToUTF16("action"), ASCIIToUTF16("type"));
+ DictionaryValue* d1 = new DictionaryValue;
+ d1->SetString(std::string("key1"), std::string("val1"));
+ data.mime_data.Append(d1);
+ DictionaryValue* d2 = new DictionaryValue;
+ d2->SetString(std::string("key2"), std::string("val2"));
+ data.mime_data.Append(d2);
+ SetIntentData(data);
+
+ LoadHTML("<html>"
+ "<head><script>\n"
+ "var d = {};\n"
+ "d.action = window.webkitIntent.action;\n"
+ "d.type = window.webkitIntent.type;\n"
+ "d.data = window.webkitIntent.data;\n"
+ "window.webkitIntent.postResult(d);\n"
+ "</script></head>"
+ "<body>body</body></html>");
+
+ const IPC::Message* reply_msg =
+ render_thread_->sink().GetUniqueMessageMatching(
+ IntentsHostMsg_WebIntentReply::ID);
+ ASSERT_TRUE(reply_msg);
+ scoped_ptr<base::DictionaryValue> dict(ParseValueFromReply(reply_msg));
+
+ base::ListValue* payload;
+ ASSERT_TRUE(dict->GetList("data", &payload));
+ EXPECT_EQ(2U, payload->GetSize());
+
+ base::DictionaryValue* v1 = NULL;
+ ASSERT_TRUE(payload->GetDictionary(0, &v1));
+ DCHECK(v1);
+ std::string val1;
+ ASSERT_TRUE(v1->GetStringASCII(std::string("key1"), &val1));
+ EXPECT_EQ("val1", val1);
+
+ base::DictionaryValue* v2 = NULL;
+ ASSERT_TRUE(payload->GetDictionary(1, &v2));
+ std::string val2;
+ v2->GetStringASCII(std::string("key2"), &val2);
+ EXPECT_EQ("val2", val2);
+}