diff options
author | mpcomplete@chromium.org <mpcomplete@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98> | 2009-10-06 18:15:58 +0000 |
---|---|---|
committer | mpcomplete@chromium.org <mpcomplete@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98> | 2009-10-06 18:15:58 +0000 |
commit | e4dad9fbf5a48cb65d085e49c8f7917c8f31300b (patch) | |
tree | 3df910ad37afd8d633f16cc47d0f4b46f6647fbf | |
parent | 2a3e3c054891c865540524beb4af96ec68c481ba (diff) | |
download | chromium_src-e4dad9fbf5a48cb65d085e49c8f7917c8f31300b.zip chromium_src-e4dad9fbf5a48cb65d085e49c8f7917c8f31300b.tar.gz chromium_src-e4dad9fbf5a48cb65d085e49c8f7917c8f31300b.tar.bz2 |
Modify extension request IPC messages to pass a ListValue instead of a string.
This allows us to pass binary values through extension requests. I use this in
my next CL to pass SkBitmaps.
BUG=23269
TEST=no
Review URL: http://codereview.chromium.org/251093
git-svn-id: svn://svn.chromium.org/chrome/trunk/src@28130 0039d316-1c4b-4281-b951-d872f2087c98
25 files changed, 107 insertions, 73 deletions
diff --git a/base/values.cc b/base/values.cc index d97da24..51e68a7 100644 --- a/base/values.cc +++ b/base/values.cc @@ -193,7 +193,8 @@ BinaryValue* BinaryValue::Create(char* buffer, size_t size) { } // static -BinaryValue* BinaryValue::CreateWithCopiedBuffer(char* buffer, size_t size) { +BinaryValue* BinaryValue::CreateWithCopiedBuffer(const char* buffer, + size_t size) { if (!buffer) return NULL; diff --git a/base/values.h b/base/values.h index 8e3669b..b3c380c 100644 --- a/base/values.h +++ b/base/values.h @@ -171,7 +171,7 @@ class BinaryValue: public Value { // factory method creates a new BinaryValue by copying the contents of the // buffer that's passed in. // Returns NULL if buffer is NULL. - static BinaryValue* CreateWithCopiedBuffer(char* buffer, size_t size); + static BinaryValue* CreateWithCopiedBuffer(const char* buffer, size_t size); ~BinaryValue(); @@ -181,6 +181,7 @@ class BinaryValue: public Value { size_t GetSize() const { return size_; } char* GetBuffer() { return buffer_; } + const char* GetBuffer() const { return buffer_; } private: // Constructor is private so that only objects with valid buffer pointers diff --git a/chrome/browser/automation/automation_extension_function.cc b/chrome/browser/automation/automation_extension_function.cc index 89288c0..4849583 100644 --- a/chrome/browser/automation/automation_extension_function.cc +++ b/chrome/browser/automation/automation_extension_function.cc @@ -14,8 +14,8 @@ bool AutomationExtensionFunction::enabled_ = false; -void AutomationExtensionFunction::SetArgs(const std::string& args) { - args_ = args; +void AutomationExtensionFunction::SetArgs(const Value* args) { + JSONWriter::Write(args, false, &args_); } const std::string AutomationExtensionFunction::GetResult() { diff --git a/chrome/browser/automation/automation_extension_function.h b/chrome/browser/automation/automation_extension_function.h index 1d1da41..f48adff 100644 --- a/chrome/browser/automation/automation_extension_function.h +++ b/chrome/browser/automation/automation_extension_function.h @@ -20,7 +20,7 @@ class AutomationExtensionFunction : public ExtensionFunction { AutomationExtensionFunction() { } // ExtensionFunction implementation. - virtual void SetArgs(const std::string& args); + virtual void SetArgs(const Value* args); virtual const std::string GetResult(); virtual const std::string GetError(); virtual void Run(); diff --git a/chrome/browser/dom_ui/dom_ui.cc b/chrome/browser/dom_ui/dom_ui.cc index 2088427..7f38aef 100644 --- a/chrome/browser/dom_ui/dom_ui.cc +++ b/chrome/browser/dom_ui/dom_ui.cc @@ -35,7 +35,7 @@ DOMUI::~DOMUI() { // DOMUI, public: ------------------------------------------------------------- void DOMUI::ProcessDOMUIMessage(const std::string& message, - const std::string& content, + const Value* content, int request_id, bool has_callback) { // Look up the callback for this message. @@ -44,20 +44,8 @@ void DOMUI::ProcessDOMUIMessage(const std::string& message, if (callback == message_callbacks_.end()) return; - // Convert the content JSON into a Value. - scoped_ptr<Value> value; - if (!content.empty()) { - value.reset(JSONReader::Read(content, false)); - if (!value.get()) { - // The page sent us something that we didn't understand. - // This probably indicates a programming error. - NOTREACHED(); - return; - } - } - // Forward this message and content on. - callback->second->Run(value.get()); + callback->second->Run(content); } void DOMUI::CallJavascriptFunction(const std::wstring& function_name) { diff --git a/chrome/browser/dom_ui/dom_ui.h b/chrome/browser/dom_ui/dom_ui.h index b359abd..ad4c2dc 100644 --- a/chrome/browser/dom_ui/dom_ui.h +++ b/chrome/browser/dom_ui/dom_ui.h @@ -41,7 +41,7 @@ class DOMUI { // Called from TabContents. virtual void ProcessDOMUIMessage(const std::string& message, - const std::string& content, + const Value* content, int request_id, bool has_callback); diff --git a/chrome/browser/extensions/extension_dom_ui.cc b/chrome/browser/extensions/extension_dom_ui.cc index a718f5c..df4746d 100644 --- a/chrome/browser/extensions/extension_dom_ui.cc +++ b/chrome/browser/extensions/extension_dom_ui.cc @@ -54,7 +54,7 @@ void ExtensionDOMUI::RenderViewReused(RenderViewHost* render_view_host) { } void ExtensionDOMUI::ProcessDOMUIMessage(const std::string& message, - const std::string& content, + const Value* content, int request_id, bool has_callback) { extension_function_dispatcher_->HandleRequest(message, content, request_id, diff --git a/chrome/browser/extensions/extension_dom_ui.h b/chrome/browser/extensions/extension_dom_ui.h index b8ef8dc..a729167 100644 --- a/chrome/browser/extensions/extension_dom_ui.h +++ b/chrome/browser/extensions/extension_dom_ui.h @@ -29,7 +29,7 @@ class ExtensionDOMUI virtual void RenderViewCreated(RenderViewHost* render_view_host); virtual void RenderViewReused(RenderViewHost* render_view_host); virtual void ProcessDOMUIMessage(const std::string& message, - const std::string& content, + const Value* content, int request_id, bool has_callback); diff --git a/chrome/browser/extensions/extension_function.cc b/chrome/browser/extensions/extension_function.cc index 26adefb..c15c18b 100644 --- a/chrome/browser/extensions/extension_function.cc +++ b/chrome/browser/extensions/extension_function.cc @@ -4,24 +4,13 @@ #include "chrome/browser/extensions/extension_function.h" -#include "base/json_reader.h" #include "base/json_writer.h" #include "base/logging.h" #include "chrome/browser/extensions/extension_function_dispatcher.h" -void AsyncExtensionFunction::SetArgs(const std::string& args) { +void AsyncExtensionFunction::SetArgs(const Value* args) { DCHECK(!args_); // Should only be called once. - if (!args.empty()) { - JSONReader reader; - args_ = reader.JsonToValue(args, false, false); - - // Since we do the serialization in the v8 extension, we should always get - // valid JSON. - if (!args_) { - DCHECK(false); - return; - } - } + args_ = args->DeepCopy(); } const std::string AsyncExtensionFunction::GetResult() { diff --git a/chrome/browser/extensions/extension_function.h b/chrome/browser/extensions/extension_function.h index d763696..238f8e4 100644 --- a/chrome/browser/extensions/extension_function.h +++ b/chrome/browser/extensions/extension_function.h @@ -36,8 +36,8 @@ class ExtensionFunction : public base::RefCounted<ExtensionFunction> { void set_name(const std::string& name) { name_ = name; } const std::string name() { return name_; } - // Specifies the raw arguments to the function, as a JSON-encoded string. - virtual void SetArgs(const std::string& args) = 0; + // Specifies the raw arguments to the function, as a JSON value. + virtual void SetArgs(const Value* args) = 0; // Retrieves the results of the function as a JSON-encoded string (may // be empty). @@ -103,7 +103,7 @@ class AsyncExtensionFunction : public ExtensionFunction { AsyncExtensionFunction() : args_(NULL), bad_message_(false) {} virtual ~AsyncExtensionFunction() {} - virtual void SetArgs(const std::string& args); + virtual void SetArgs(const Value* args); virtual const std::string GetResult(); virtual const std::string GetError() { return error_; } virtual void Run() { diff --git a/chrome/browser/extensions/extension_function_dispatcher.cc b/chrome/browser/extensions/extension_function_dispatcher.cc index eb3a92e..d17e575 100644 --- a/chrome/browser/extensions/extension_function_dispatcher.cc +++ b/chrome/browser/extensions/extension_function_dispatcher.cc @@ -279,7 +279,7 @@ Extension* ExtensionFunctionDispatcher::GetExtension() { } void ExtensionFunctionDispatcher::HandleRequest(const std::string& name, - const std::string& args, + const Value* args, int request_id, bool has_callback) { scoped_refptr<ExtensionFunction> function( diff --git a/chrome/browser/extensions/extension_function_dispatcher.h b/chrome/browser/extensions/extension_function_dispatcher.h index 492c431e..b987e0e 100644 --- a/chrome/browser/extensions/extension_function_dispatcher.h +++ b/chrome/browser/extensions/extension_function_dispatcher.h @@ -19,6 +19,7 @@ class ExtensionHost; class Profile; class RenderViewHost; class RenderViewHostDelegate; +class Value; // A factory function for creating new ExtensionFunction instances. typedef ExtensionFunction* (*ExtensionFunctionFactory)(); @@ -61,7 +62,7 @@ class ExtensionFunctionDispatcher { ~ExtensionFunctionDispatcher(); // Handle a request to execute an extension function. - void HandleRequest(const std::string& name, const std::string& args, + void HandleRequest(const std::string& name, const Value* args, int request_id, bool has_callback); // Send a response to a function. diff --git a/chrome/browser/extensions/extension_host.cc b/chrome/browser/extensions/extension_host.cc index 766a12e..8bad4ce 100644 --- a/chrome/browser/extensions/extension_host.cc +++ b/chrome/browser/extensions/extension_host.cc @@ -361,7 +361,7 @@ WebPreferences ExtensionHost::GetWebkitPrefs() { } void ExtensionHost::ProcessDOMUIMessage(const std::string& message, - const std::string& content, + const Value* content, int request_id, bool has_callback) { if (extension_function_dispatcher_.get()) { diff --git a/chrome/browser/extensions/extension_host.h b/chrome/browser/extensions/extension_host.h index c5aeeba..9e54251 100644 --- a/chrome/browser/extensions/extension_host.h +++ b/chrome/browser/extensions/extension_host.h @@ -103,7 +103,7 @@ class ExtensionHost : public RenderViewHostDelegate, virtual WebPreferences GetWebkitPrefs(); virtual void ProcessDOMUIMessage(const std::string& message, - const std::string& content, + const Value* content, int request_id, bool has_callback); virtual void RunJavaScriptMessage(const std::wstring& message, diff --git a/chrome/browser/renderer_host/render_view_host.cc b/chrome/browser/renderer_host/render_view_host.cc index d384fec..667faa4 100644 --- a/chrome/browser/renderer_host/render_view_host.cc +++ b/chrome/browser/renderer_host/render_view_host.cc @@ -10,6 +10,7 @@ #include "app/l10n_util.h" #include "app/resource_bundle.h" #include "base/gfx/native_widget_types.h" +#include "base/json_reader.h" #include "base/string_util.h" #include "base/time.h" #include "base/waitable_event.h" @@ -1219,8 +1220,19 @@ void RenderViewHost::OnMsgDOMUISend( // values here. const int kRequestId = -1; const bool kHasCallback = false; + scoped_ptr<Value> value; + if (!content.empty()) { + value.reset(JSONReader::Read(content, false)); + if (!value.get()) { + // The page sent us something that we didn't understand. + // This probably indicates a programming error. + NOTREACHED() << "Invalid JSON argument in OnMsgDOMUISend."; + return; + } + } - delegate_->ProcessDOMUIMessage(message, content, kRequestId, kHasCallback); + delegate_->ProcessDOMUIMessage(message, value.get(), + kRequestId, kHasCallback); } void RenderViewHost::OnMsgForwardMessageToExternalHost( @@ -1633,7 +1645,7 @@ void RenderViewHost::ForwardMessageFromExternalHost(const std::string& message, } void RenderViewHost::OnExtensionRequest(const std::string& name, - const std::string& args, + const ListValue& args_holder, int request_id, bool has_callback) { if (!ChildProcessSecurityPolicy::GetInstance()-> @@ -1644,6 +1656,15 @@ void RenderViewHost::OnExtensionRequest(const std::string& name, return; } + // The renderer sends the args in a 1-element list to make serialization + // easier. + Value* args = NULL; + if (!args_holder.IsType(Value::TYPE_LIST) || + !static_cast<const ListValue*>(&args_holder)->Get(0, &args)) { + NOTREACHED(); + return; + } + delegate_->ProcessDOMUIMessage(name, args, request_id, has_callback); } diff --git a/chrome/browser/renderer_host/render_view_host.h b/chrome/browser/renderer_host/render_view_host.h index 8fff7cf..37f1215 100644 --- a/chrome/browser/renderer_host/render_view_host.h +++ b/chrome/browser/renderer_host/render_view_host.h @@ -22,6 +22,7 @@ #include "webkit/glue/password_form_dom_manager.h" #include "webkit/glue/window_open_disposition.h" +class ListValue; class RenderViewHostDelegate; class SiteInstance; class SkBitmap; @@ -571,7 +572,7 @@ class RenderViewHost : public RenderWidgetHost, void OnRemoveAutofillEntry(const std::wstring& field_name, const std::wstring& value); - void OnExtensionRequest(const std::string& name, const std::string& args, + void OnExtensionRequest(const std::string& name, const ListValue& args, int request_id, bool has_callback); void OnExtensionPostMessage(int port_id, const std::string& message); void OnAccessibilityFocusChange(int acc_obj_id); diff --git a/chrome/browser/renderer_host/render_view_host_delegate.h b/chrome/browser/renderer_host/render_view_host_delegate.h index 96ed816..0f853c3 100644 --- a/chrome/browser/renderer_host/render_view_host_delegate.h +++ b/chrome/browser/renderer_host/render_view_host_delegate.h @@ -19,6 +19,7 @@ class AutofillForm; struct ContextMenuParams; class FilePath; class GURL; +class Value; struct NativeWebKeyboardEvent; class NavigationEntry; class Profile; @@ -467,7 +468,7 @@ class RenderViewHostDelegate { // A message was sent from HTML-based UI. // By default we ignore such messages. virtual void ProcessDOMUIMessage(const std::string& message, - const std::string& content, + const Value* content, int request_id, bool has_callback) {} diff --git a/chrome/browser/tab_contents/tab_contents.cc b/chrome/browser/tab_contents/tab_contents.cc index 315934e..7735a14 100644 --- a/chrome/browser/tab_contents/tab_contents.cc +++ b/chrome/browser/tab_contents/tab_contents.cc @@ -2208,7 +2208,7 @@ void TabContents::DomOperationResponse(const std::string& json_string, } void TabContents::ProcessDOMUIMessage(const std::string& message, - const std::string& content, + const Value* content, int request_id, bool has_callback) { if (!render_manager_.dom_ui()) { diff --git a/chrome/browser/tab_contents/tab_contents.h b/chrome/browser/tab_contents/tab_contents.h index 3a09eb5..a85c3bb 100644 --- a/chrome/browser/tab_contents/tab_contents.h +++ b/chrome/browser/tab_contents/tab_contents.h @@ -873,7 +873,7 @@ class TabContents : public PageNavigator, virtual void DomOperationResponse(const std::string& json_string, int automation_id); virtual void ProcessDOMUIMessage(const std::string& message, - const std::string& content, + const Value* content, int request_id, bool has_callback); virtual void ProcessExternalHostMessage(const std::string& message, diff --git a/chrome/common/render_messages_internal.h b/chrome/common/render_messages_internal.h index 62451cc..006118e 100644 --- a/chrome/common/render_messages_internal.h +++ b/chrome/common/render_messages_internal.h @@ -1607,7 +1607,7 @@ IPC_BEGIN_MESSAGES(ViewHost) // request. The browser will always respond with a ViewMsg_ExtensionResponse. IPC_MESSAGE_ROUTED4(ViewHostMsg_ExtensionRequest, std::string /* name */, - std::string /* argument */, + ListValue /* argument */, int /* callback id */, bool /* has_callback */) diff --git a/chrome/renderer/extensions/extension_api_client_unittest.cc b/chrome/renderer/extensions/extension_api_client_unittest.cc index 1a06889..64002282 100644 --- a/chrome/renderer/extensions/extension_api_client_unittest.cc +++ b/chrome/renderer/extensions/extension_api_client_unittest.cc @@ -3,6 +3,7 @@ // found in the LICENSE file. #include "base/file_util.h" +#include "base/json_reader.h" #include "base/path_service.h" #include "base/string_util.h" #include "chrome/common/chrome_paths.h" @@ -53,7 +54,14 @@ class ExtensionAPIClientTest : public RenderViewTest { ViewHostMsg_ExtensionRequest::Param params; ViewHostMsg_ExtensionRequest::Read(request_msg, ¶ms); ASSERT_EQ(function.c_str(), params.a) << js; - ASSERT_EQ(arg1.c_str(), params.b) << js; + + Value* args = NULL; + ASSERT_TRUE(params.b.IsType(Value::TYPE_LIST)); + ASSERT_TRUE(static_cast<const ListValue*>(¶ms.b)->Get(0, &args)); + + JSONReader reader; + Value* arg1_value = reader.JsonToValue(arg1, false, false); + ASSERT_TRUE(args->Equals(arg1_value)) << js; render_thread_.sink().ClearMessages(); } }; diff --git a/chrome/renderer/extensions/extension_process_bindings.cc b/chrome/renderer/extensions/extension_process_bindings.cc index 6603582..e083c7c 100644 --- a/chrome/renderer/extensions/extension_process_bindings.cc +++ b/chrome/renderer/extensions/extension_process_bindings.cc @@ -9,6 +9,7 @@ #include "chrome/renderer/extensions/extension_process_bindings.h" +#include "base/json_reader.h" #include "base/singleton.h" #include "chrome/common/extensions/extension.h" #include "chrome/common/extensions/extension_message_bundle.h" @@ -352,17 +353,33 @@ class ExtensionImpl : public ExtensionBase { return ExtensionProcessBindings::ThrowPermissionDeniedException(name); } - std::string json_args = *v8::String::Utf8Value(args[1]); + std::string str_args = *v8::String::Utf8Value(args[1]); int request_id = args[2]->Int32Value(); bool has_callback = args[3]->BooleanValue(); + ListValue args_holder; + JSONReader reader; + Value* json_args = reader.JsonToValue(str_args, false, false); + + // Since we do the serialization in the v8 extension, we should always get + // valid JSON. + if (!json_args) { + NOTREACHED() << "Invalid JSON passed to StartRequest."; + return v8::Undefined(); + } + + // Put the args in a 1-element list for easier serialization. Maybe all + // requests should have a list of args? + args_holder.Append(json_args); + v8::Persistent<v8::Context> current_context = v8::Persistent<v8::Context>::New(v8::Context::GetCurrent()); DCHECK(!current_context.IsEmpty()); GetPendingRequestMap()[request_id].reset(new PendingRequest( current_context, name)); - renderview->SendExtensionRequest(name, json_args, request_id, has_callback); + renderview->SendExtensionRequest(name, args_holder, + request_id, has_callback); return v8::Undefined(); } diff --git a/chrome/renderer/render_view.cc b/chrome/renderer/render_view.cc index 6888fbb..3cce3a9 100644 --- a/chrome/renderer/render_view.cc +++ b/chrome/renderer/render_view.cc @@ -3297,7 +3297,7 @@ void RenderView::OnSetActive(bool active) { } void RenderView::SendExtensionRequest(const std::string& name, - const std::string& args, + const ListValue& args, int request_id, bool has_callback) { Send(new ViewHostMsg_ExtensionRequest(routing_id_, name, args, request_id, diff --git a/chrome/renderer/render_view.h b/chrome/renderer/render_view.h index cdd1c2c..ddcc1a4 100644 --- a/chrome/renderer/render_view.h +++ b/chrome/renderer/render_view.h @@ -414,7 +414,7 @@ class RenderView : public RenderWidget, void OnClearFocusedNode(); - void SendExtensionRequest(const std::string& name, const std::string& args, + void SendExtensionRequest(const std::string& name, const ListValue& args, int request_id, bool has_callback); void OnExtensionResponse(int request_id, bool success, const std::string& response, diff --git a/ipc/ipc_message_utils.cc b/ipc/ipc_message_utils.cc index ac188bf..06408b4 100644 --- a/ipc/ipc_message_utils.cc +++ b/ipc/ipc_message_utils.cc @@ -27,36 +27,38 @@ static void WriteValue(Message* m, const Value* value, int recursion) { m->WriteInt(value->GetType()); switch (value->GetType()) { - case Value::TYPE_NULL: + case Value::TYPE_NULL: break; - case Value::TYPE_BOOLEAN: { + case Value::TYPE_BOOLEAN: { bool val; value->GetAsBoolean(&val); WriteParam(m, val); break; } - case Value::TYPE_INTEGER: { + case Value::TYPE_INTEGER: { int val; value->GetAsInteger(&val); WriteParam(m, val); break; } - case Value::TYPE_REAL: { + case Value::TYPE_REAL: { double val; value->GetAsReal(&val); WriteParam(m, val); break; } - case Value::TYPE_STRING: { + case Value::TYPE_STRING: { std::string val; value->GetAsString(&val); WriteParam(m, val); break; } - case Value::TYPE_BINARY: { - NOTREACHED() << "Don't send BinaryValues over IPC."; + case Value::TYPE_BINARY: { + const BinaryValue* binary = static_cast<const BinaryValue*>(value); + m->WriteData(binary->GetBuffer(), binary->GetSize()); + break; } - case Value::TYPE_DICTIONARY: { + case Value::TYPE_DICTIONARY: { const DictionaryValue* dict = static_cast<const DictionaryValue*>(value); WriteParam(m, static_cast<int>(dict->GetSize())); @@ -73,7 +75,7 @@ static void WriteValue(Message* m, const Value* value, int recursion) { } break; } - case Value::TYPE_LIST: { + case Value::TYPE_LIST: { const ListValue* list = static_cast<const ListValue*>(value); WriteParam(m, static_cast<int>(list->GetSize())); for (size_t i = 0; i < list->GetSize(); ++i) { @@ -139,56 +141,60 @@ static bool ReadValue(const Message* m, void** iter, Value** value, return false; switch (type) { - case Value::TYPE_NULL: + case Value::TYPE_NULL: *value = Value::CreateNullValue(); break; - case Value::TYPE_BOOLEAN: { + case Value::TYPE_BOOLEAN: { bool val; if (!ReadParam(m, iter, &val)) return false; *value = Value::CreateBooleanValue(val); break; } - case Value::TYPE_INTEGER: { + case Value::TYPE_INTEGER: { int val; if (!ReadParam(m, iter, &val)) return false; *value = Value::CreateIntegerValue(val); break; } - case Value::TYPE_REAL: { + case Value::TYPE_REAL: { double val; if (!ReadParam(m, iter, &val)) return false; *value = Value::CreateRealValue(val); break; } - case Value::TYPE_STRING: { + case Value::TYPE_STRING: { std::string val; if (!ReadParam(m, iter, &val)) return false; *value = Value::CreateStringValue(val); break; } - case Value::TYPE_BINARY: { - NOTREACHED() << "Don't send BinaryValues over IPC."; + case Value::TYPE_BINARY: { + const char* data; + int length; + if (!m->ReadData(iter, &data, &length)) + return false; + *value = BinaryValue::CreateWithCopiedBuffer(data, length); break; } - case Value::TYPE_DICTIONARY: { + case Value::TYPE_DICTIONARY: { scoped_ptr<DictionaryValue> val(new DictionaryValue()); if (!ReadDictionaryValue(m, iter, val.get(), recursion)) return false; *value = val.release(); break; } - case Value::TYPE_LIST: { + case Value::TYPE_LIST: { scoped_ptr<ListValue> val(new ListValue()); if (!ReadListValue(m, iter, val.get(), recursion)) return false; *value = val.release(); break; } - default: + default: return false; } |