summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorgbillock@chromium.org <gbillock@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98>2012-04-10 04:15:01 +0000
committergbillock@chromium.org <gbillock@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98>2012-04-10 04:15:01 +0000
commit8b0caee3faa74cd59f09a685eae208466f2c5219 (patch)
tree2ab257802b0923001b4cd3a0de074fffe8f2fa76
parent1a3bb2537d9737e3a2f6d70f273fd5cc3f09eb8e (diff)
downloadchromium_src-8b0caee3faa74cd59f09a685eae208466f2c5219.zip
chromium_src-8b0caee3faa74cd59f09a685eae208466f2c5219.tar.gz
chromium_src-8b0caee3faa74cd59f09a685eae208466f2c5219.tar.bz2
Pass content-type resources to web intents. Goes through download, then invokes the picker.
Code to handle policy and intent payload creation is embedder-side. New API for dispatching the browser-initiated internal intent added to content. BUG=105732 TEST=None Review URL: http://codereview.chromium.org/9651020 git-svn-id: svn://svn.chromium.org/chrome/trunk/src@131535 0039d316-1c4b-4281-b951-d872f2087c98
-rw-r--r--chrome/browser/download/chrome_download_manager_delegate.cc69
-rw-r--r--chrome/browser/download/chrome_download_manager_delegate.h7
-rw-r--r--content/browser/intents/intent_injector.cc9
-rw-r--r--content/browser/intents/web_intents_dispatcher_impl.cc11
-rw-r--r--content/common/intents_messages.h3
-rw-r--r--content/public/browser/web_intents_dispatcher.h6
-rw-r--r--content/renderer/web_intents_host.cc58
-rw-r--r--webkit/glue/web_intent_data.cc16
-rw-r--r--webkit/glue/web_intent_data.h24
9 files changed, 169 insertions, 34 deletions
diff --git a/chrome/browser/download/chrome_download_manager_delegate.cc b/chrome/browser/download/chrome_download_manager_delegate.cc
index 6737e09..527de4e 100644
--- a/chrome/browser/download/chrome_download_manager_delegate.cc
+++ b/chrome/browser/download/chrome_download_manager_delegate.cc
@@ -14,6 +14,7 @@
#include "base/rand_util.h"
#include "base/stringprintf.h"
#include "base/time.h"
+#include "base/utf_string_conversions.h"
#include "chrome/browser/browser_process.h"
#include "chrome/browser/download/download_crx_util.h"
#include "chrome/browser/download/download_extensions.h"
@@ -37,8 +38,10 @@
#include "content/public/browser/download_manager.h"
#include "content/public/browser/notification_source.h"
#include "content/public/browser/web_contents.h"
+#include "content/public/browser/web_intents_dispatcher.h"
#include "grit/generated_resources.h"
#include "ui/base/l10n/l10n_util.h"
+#include "webkit/glue/web_intent_data.h"
#if !defined(OS_ANDROID)
#include "chrome/browser/ui/browser.h"
@@ -226,28 +229,60 @@ bool ChromeDownloadManagerDelegate::ShouldCompleteDownload(DownloadItem* item) {
}
bool ChromeDownloadManagerDelegate::ShouldOpenDownload(DownloadItem* item) {
- if (!IsExtensionDownload(item)) {
- return true;
+ if (IsExtensionDownload(item)) {
+ scoped_refptr<CrxInstaller> crx_installer =
+ download_crx_util::OpenChromeExtension(profile_, *item);
+
+ // CRX_INSTALLER_DONE will fire when the install completes. Observe()
+ // will call DelayedDownloadOpened() on this item. If this DownloadItem is
+ // not around when CRX_INSTALLER_DONE fires, Complete() will not be called.
+ registrar_.Add(this,
+ chrome::NOTIFICATION_CRX_INSTALLER_DONE,
+ content::Source<CrxInstaller>(crx_installer.get()));
+
+ crx_installers_[crx_installer.get()] = item->GetId();
+ // The status text and percent complete indicator will change now
+ // that we are installing a CRX. Update observers so that they pick
+ // up the change.
+ item->UpdateObservers();
+ return false;
+ }
+
+ if (ShouldOpenWithWebIntents(item)) {
+ OpenWithWebIntent(item);
+ item->DelayedDownloadOpened();
+ return false;
}
- scoped_refptr<CrxInstaller> crx_installer =
- download_crx_util::OpenChromeExtension(profile_, *item);
-
- // CRX_INSTALLER_DONE will fire when the install completes. Observe()
- // will call DelayedDownloadOpened() on this item. If this DownloadItem is
- // not around when CRX_INSTALLER_DONE fires, Complete() will not be called.
- registrar_.Add(this,
- chrome::NOTIFICATION_CRX_INSTALLER_DONE,
- content::Source<CrxInstaller>(crx_installer.get()));
-
- crx_installers_[crx_installer.get()] = item->GetId();
- // The status text and percent complete indicator will change now
- // that we are installing a CRX. Update observers so that they pick
- // up the change.
- item->UpdateObservers();
+ return true;
+}
+
+bool ChromeDownloadManagerDelegate::ShouldOpenWithWebIntents(
+ const DownloadItem* item) {
return false;
}
+void ChromeDownloadManagerDelegate::OpenWithWebIntent(
+ const DownloadItem* item) {
+ webkit_glue::WebIntentData intent_data(
+ ASCIIToUTF16("http://webintents.org/view"),
+ ASCIIToUTF16(item->GetMimeType()),
+ item->GetFullPath(),
+ item->GetReceivedBytes());
+
+ // TODO(gbillock): Should we pass this? RCH specifies that the receiver gets
+ // the url, but with web intents we don't need to pass it.
+ intent_data.extra_data.insert(make_pair(
+ ASCIIToUTF16("url"), ASCIIToUTF16(item->GetURL().spec())));
+
+ content::WebIntentsDispatcher* dispatcher =
+ content::WebIntentsDispatcher::Create(intent_data);
+ // TODO(gbillock): try to get this to be able to delegate to the Browser
+ // object directly, passing a NULL WebContents?
+ item->GetWebContents()->GetDelegate()->WebIntentDispatch(
+ item->GetWebContents(), dispatcher);
+}
+
bool ChromeDownloadManagerDelegate::GenerateFileHash() {
#if defined(ENABLE_SAFE_BROWSING)
return profile_->GetPrefs()->GetBoolean(prefs::kSafeBrowsingEnabled) &&
diff --git a/chrome/browser/download/chrome_download_manager_delegate.h b/chrome/browser/download/chrome_download_manager_delegate.h
index 93f6721..e5ee17d 100644
--- a/chrome/browser/download/chrome_download_manager_delegate.h
+++ b/chrome/browser/download/chrome_download_manager_delegate.h
@@ -146,6 +146,13 @@ class ChromeDownloadManagerDelegate
// Callback from history system.
void OnItemAddedToPersistentStore(int32 download_id, int64 db_handle);
+ // Check policy of whether we should open this download with a web intents
+ // dispatch.
+ bool ShouldOpenWithWebIntents(const content::DownloadItem* item);
+
+ // Open the given item with a web intent dispatch.
+ void OpenWithWebIntent(const content::DownloadItem* item);
+
Profile* profile_;
int next_download_id_;
scoped_ptr<DownloadPrefs> download_prefs_;
diff --git a/content/browser/intents/intent_injector.cc b/content/browser/intents/intent_injector.cc
index e74bbef..f72518e 100644
--- a/content/browser/intents/intent_injector.cc
+++ b/content/browser/intents/intent_injector.cc
@@ -6,8 +6,10 @@
#include "base/bind.h"
#include "base/command_line.h"
+#include "base/file_path.h"
#include "base/logging.h"
#include "base/string16.h"
+#include "content/browser/child_process_security_policy_impl.h"
#include "content/browser/renderer_host/render_view_host_impl.h"
#include "content/browser/tab_contents/tab_contents.h"
#include "content/common/intents_messages.h"
@@ -71,6 +73,13 @@ 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.
+ int child_id = render_view_host->GetProcess()->GetID();
+ ChildProcessSecurityPolicyImpl::GetInstance()->GrantReadFile(
+ child_id, source_intent_->blob_file);
+ }
+
render_view_host->Send(new IntentsMsg_SetWebIntentData(
render_view_host->GetRoutingID(), *(source_intent_.get())));
}
diff --git a/content/browser/intents/web_intents_dispatcher_impl.cc b/content/browser/intents/web_intents_dispatcher_impl.cc
index 7749593..ad8e096 100644
--- a/content/browser/intents/web_intents_dispatcher_impl.cc
+++ b/content/browser/intents/web_intents_dispatcher_impl.cc
@@ -5,6 +5,7 @@
#include "content/browser/intents/web_intents_dispatcher_impl.h"
#include "content/browser/intents/intent_injector.h"
+#include "content/browser/intents/internal_web_intents_dispatcher.h"
#include "content/browser/tab_contents/tab_contents.h"
#include "content/common/intents_messages.h"
#include "webkit/glue/web_intent_data.h"
@@ -12,6 +13,16 @@
using content::WebContents;
+namespace content {
+
+WebIntentsDispatcher* WebIntentsDispatcher::Create(
+ const webkit_glue::WebIntentData& data) {
+ return new InternalWebIntentsDispatcher(data);
+}
+
+} // namespace content
+
+
WebIntentsDispatcherImpl::WebIntentsDispatcherImpl(
TabContents* source_tab,
const webkit_glue::WebIntentData& intent,
diff --git a/content/common/intents_messages.h b/content/common/intents_messages.h
index 79d9bfc..8f56546 100644
--- a/content/common/intents_messages.h
+++ b/content/common/intents_messages.h
@@ -22,7 +22,10 @@ IPC_STRUCT_TRAITS_BEGIN(webkit_glue::WebIntentData)
IPC_STRUCT_TRAITS_MEMBER(action)
IPC_STRUCT_TRAITS_MEMBER(type)
IPC_STRUCT_TRAITS_MEMBER(data)
+ IPC_STRUCT_TRAITS_MEMBER(extra_data)
IPC_STRUCT_TRAITS_MEMBER(unserialized_data)
+ IPC_STRUCT_TRAITS_MEMBER(blob_file)
+ IPC_STRUCT_TRAITS_MEMBER(blob_length)
IPC_STRUCT_TRAITS_MEMBER(data_type)
IPC_STRUCT_TRAITS_END()
diff --git a/content/public/browser/web_intents_dispatcher.h b/content/public/browser/web_intents_dispatcher.h
index 36d55e0..762aca1 100644
--- a/content/public/browser/web_intents_dispatcher.h
+++ b/content/public/browser/web_intents_dispatcher.h
@@ -17,6 +17,7 @@ struct WebIntentData;
namespace content {
class WebContents;
+class WebContentsDelegate;
// This class is the coordinator for dispatching web intents and seeing that
// return messages are sent to the correct invoking context. The WebContents
@@ -39,6 +40,11 @@ class CONTENT_EXPORT WebIntentsDispatcher {
typedef base::Callback<void(webkit_glue::WebIntentReplyType)>
ReplyNotification;
+ // Create internal (browser-triggered) intent. This will create
+ // a new dispatcher with the passed intent payload |data|. The caller should
+ // manage dispatching it correctly.
+ static WebIntentsDispatcher* Create(const webkit_glue::WebIntentData& data);
+
virtual ~WebIntentsDispatcher() {}
// Get the intent data being dispatched.
diff --git a/content/renderer/web_intents_host.cc b/content/renderer/web_intents_host.cc
index e03473f..5b83bf9 100644
--- a/content/renderer/web_intents_host.cc
+++ b/content/renderer/web_intents_host.cc
@@ -6,10 +6,12 @@
#include "base/bind.h"
#include "base/bind_helpers.h"
+#include "base/utf_string_conversions.h"
#include "content/common/intents_messages.h"
#include "content/renderer/render_view_impl.h"
#include "ipc/ipc_message.h"
#include "third_party/WebKit/Source/WebKit/chromium/public/WebBindings.h"
+#include "third_party/WebKit/Source/WebKit/chromium/public/WebBlob.h"
#include "third_party/WebKit/Source/WebKit/chromium/public/WebFrame.h"
#include "third_party/WebKit/Source/WebKit/chromium/public/WebIntentRequest.h"
#include "third_party/WebKit/Source/WebKit/chromium/public/WebView.h"
@@ -19,6 +21,7 @@
#include "webkit/glue/cpp_bound_class.h"
using WebKit::WebBindings;
+using WebKit::WebBlob;
using WebKit::WebCString;
using WebKit::WebFrame;
using WebKit::WebIntentRequest;
@@ -36,6 +39,7 @@ class WebIntentsHost::BoundDeliveredIntent : public CppBoundClass {
WebFrame* frame) {
action_ = WebString(intent.action).utf8();
type_ = WebString(intent.type).utf8();
+ extra_data_ = intent.extra_data;
parent_ = parent;
v8::HandleScope scope;
@@ -48,25 +52,32 @@ class WebIntentsHost::BoundDeliveredIntent : public CppBoundClass {
WebSerializedScriptValue::fromString(WebString(intent.data));
DCHECK(!ssv.isNull());
data_obj = v8::Local<v8::Value>::New(ssv.deserialize());
- } else {
- DCHECK(intent.data_type == webkit_glue::WebIntentData::UNSERIALIZED);
+ } else if (intent.data_type == webkit_glue::WebIntentData::UNSERIALIZED) {
data_obj = v8::String::New(
reinterpret_cast<const uint16_t*>(intent.unserialized_data.data()),
static_cast<int>(intent.unserialized_data.length()));
+ } else {
+ DCHECK(intent.data_type == webkit_glue::WebIntentData::BLOB);
+ WebBlob web_blob = WebBlob::createFromFile(
+ WebString::fromUTF8(intent.blob_file.AsUTF8Unsafe()),
+ intent.blob_length);
+ data_obj = v8::Local<v8::Value>::New(web_blob.toV8Value());
}
data_val_.reset(new CppVariant);
WebBindings::toNPVariant(data_obj, frame->windowObject(), data_val_.get());
- BindGetterCallback("action", base::Bind(&BoundDeliveredIntent::getAction,
+ BindGetterCallback("action", base::Bind(&BoundDeliveredIntent::GetAction,
base::Unretained(this)));
- BindGetterCallback("type", base::Bind(&BoundDeliveredIntent::getType,
+ BindGetterCallback("type", base::Bind(&BoundDeliveredIntent::GetType,
base::Unretained(this)));
- BindGetterCallback("data", base::Bind(&BoundDeliveredIntent::getData,
+ BindGetterCallback("data", base::Bind(&BoundDeliveredIntent::GetData,
base::Unretained(this)));
- BindCallback("postResult", base::Bind(&BoundDeliveredIntent::postResult,
+ BindCallback("getExtra", base::Bind(&BoundDeliveredIntent::GetExtra,
+ base::Unretained(this)));
+ BindCallback("postResult", base::Bind(&BoundDeliveredIntent::PostResult,
base::Unretained(this)));
- BindCallback("postFailure", base::Bind(&BoundDeliveredIntent::postFailure,
+ BindCallback("postFailure", base::Bind(&BoundDeliveredIntent::PostFailure,
base::Unretained(this)));
}
@@ -85,7 +96,7 @@ class WebIntentsHost::BoundDeliveredIntent : public CppBoundClass {
return ssv.toString();
}
- void postResult(const CppArgumentList& args, CppVariant* retval) {
+ void PostResult(const CppArgumentList& args, CppVariant* retval) {
if (args.size() != 1) {
WebBindings::setException(NULL, "Must pass one argument to postResult");
return;
@@ -95,7 +106,7 @@ class WebIntentsHost::BoundDeliveredIntent : public CppBoundClass {
parent_->OnResult(str);
}
- void postFailure(const CppArgumentList& args, CppVariant* retval) {
+ void PostFailure(const CppArgumentList& args, CppVariant* retval) {
if (args.size() != 1) {
WebBindings::setException(NULL, "Must pass one argument to postFailure");
return;
@@ -105,26 +116,49 @@ class WebIntentsHost::BoundDeliveredIntent : public CppBoundClass {
parent_->OnFailure(str);
}
- void getAction(CppVariant* result) {
+ void GetAction(CppVariant* result) {
std::string action;
action.assign(action_.data(), action_.length());
result->Set(action);
}
- void getType(CppVariant* result) {
+ void GetType(CppVariant* result) {
std::string type;
type.assign(type_.data(), type_.length());
result->Set(type);
}
- void getData(CppVariant* result) {
+ void GetData(CppVariant* result) {
result->Set(*data_val_.get());
}
+ void GetExtra(const CppArgumentList& args, CppVariant* result) {
+ if (args.size() != 1) {
+ WebBindings::setException(NULL, "Must pass one argument to getExtra");
+ return;
+ }
+
+ if (!args[0].isString()) {
+ WebBindings::setException(NULL, "Argument to getExtra must be a string");
+ return;
+ }
+
+ std::string str = args[0].ToString();
+ std::map<string16, string16>::const_iterator iter =
+ extra_data_.find(UTF8ToUTF16(str));
+ if (iter == extra_data_.end()) {
+ result->SetNull();
+ return;
+ }
+ std::string val = UTF16ToUTF8(iter->second);
+ result->Set(val);
+ }
+
private:
// Intent data suitable for surfacing to Javascript callers.
WebCString action_;
WebCString type_;
+ std::map<string16, string16> extra_data_;
scoped_ptr<CppVariant> data_val_;
// The dispatcher object, for forwarding postResult/postFailure calls.
diff --git a/webkit/glue/web_intent_data.cc b/webkit/glue/web_intent_data.cc
index 663b9be..af85b2f 100644
--- a/webkit/glue/web_intent_data.cc
+++ b/webkit/glue/web_intent_data.cc
@@ -9,7 +9,8 @@
namespace webkit_glue {
WebIntentData::WebIntentData()
- : data_type(SERIALIZED) {
+ : blob_length(0),
+ data_type(SERIALIZED) {
}
WebIntentData::~WebIntentData() {
@@ -19,6 +20,7 @@ WebIntentData::WebIntentData(const WebKit::WebIntent& intent)
: action(intent.action()),
type(intent.type()),
data(intent.data()),
+ blob_length(0),
data_type(SERIALIZED) {
}
@@ -28,7 +30,19 @@ WebIntentData::WebIntentData(const string16& action_in,
: action(action_in),
type(type_in),
unserialized_data(unserialized_data_in),
+ blob_length(0),
data_type(UNSERIALIZED) {
}
+WebIntentData::WebIntentData(const string16& action_in,
+ const string16& type_in,
+ const FilePath& blob_file_in,
+ int64 blob_length_in)
+ : action(action_in),
+ type(type_in),
+ blob_file(blob_file_in),
+ blob_length(blob_length_in),
+ data_type(BLOB) {
+}
+
} // namespace webkit_glue
diff --git a/webkit/glue/web_intent_data.h b/webkit/glue/web_intent_data.h
index 78972de..686f604 100644
--- a/webkit/glue/web_intent_data.h
+++ b/webkit/glue/web_intent_data.h
@@ -5,6 +5,9 @@
#ifndef WEBKIT_GLUE_WEB_INTENT_DATA_H_
#define WEBKIT_GLUE_WEB_INTENT_DATA_H_
+#include <map>
+
+#include "base/file_path.h"
#include "base/string16.h"
#include "webkit/glue/webkit_glue_export.h"
@@ -20,17 +23,26 @@ struct WEBKIT_GLUE_EXPORT WebIntentData {
string16 action;
// The MIME type of data in this intent payload.
string16 type;
- // The representation of the payload data. Wire format is from
- // SerializedScriptObject.
+ // The serialized representation of the payload data. Wire format is from
+ // WebSerializedScriptValue.
string16 data;
+ // Any extra key-value pair metadata. (Not serialized.)
+ std::map<string16, string16> extra_data;
// String payload data.
string16 unserialized_data;
+ // The file of a payload blob. Together with |blob_length|, suitable
+ // arguments to WebBlob::createFromFile.
+ FilePath blob_file;
+ // Length of the blob.
+ int64 blob_length;
+
// These enum values indicate which payload data type should be used.
enum DataType {
- SERIALIZED = 0, // The payload is serialized in |data|.
- UNSERIALIZED = 1 // The payload is unseriazed in |unserialized_data|.
+ SERIALIZED = 0, // The payload is serialized in |data|.
+ UNSERIALIZED = 1, // The payload is unserialized in |unserialized_data|.
+ BLOB = 2 // The payload is a blob
};
// Which data payload to use when delivering the intent.
DataType data_type;
@@ -40,6 +52,10 @@ struct WEBKIT_GLUE_EXPORT WebIntentData {
WebIntentData(const string16& action_in,
const string16& type_in,
const string16& unserialized_data_in);
+ WebIntentData(const string16& action_in,
+ const string16& type_in,
+ const FilePath& blob_file_in,
+ int64 blob_length_in);
~WebIntentData();
};