diff options
author | gbillock@chromium.org <gbillock@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98> | 2012-04-10 04:15:01 +0000 |
---|---|---|
committer | gbillock@chromium.org <gbillock@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98> | 2012-04-10 04:15:01 +0000 |
commit | 8b0caee3faa74cd59f09a685eae208466f2c5219 (patch) | |
tree | 2ab257802b0923001b4cd3a0de074fffe8f2fa76 | |
parent | 1a3bb2537d9737e3a2f6d70f273fd5cc3f09eb8e (diff) | |
download | chromium_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.cc | 69 | ||||
-rw-r--r-- | chrome/browser/download/chrome_download_manager_delegate.h | 7 | ||||
-rw-r--r-- | content/browser/intents/intent_injector.cc | 9 | ||||
-rw-r--r-- | content/browser/intents/web_intents_dispatcher_impl.cc | 11 | ||||
-rw-r--r-- | content/common/intents_messages.h | 3 | ||||
-rw-r--r-- | content/public/browser/web_intents_dispatcher.h | 6 | ||||
-rw-r--r-- | content/renderer/web_intents_host.cc | 58 | ||||
-rw-r--r-- | webkit/glue/web_intent_data.cc | 16 | ||||
-rw-r--r-- | webkit/glue/web_intent_data.h | 24 |
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(); }; |