diff options
-rw-r--r-- | ppapi/proxy/host_var_serialization_rules.cc | 47 | ||||
-rw-r--r-- | ppapi/proxy/host_var_serialization_rules.h | 12 | ||||
-rw-r--r-- | ppapi/proxy/plugin_var_serialization_rules.cc | 27 | ||||
-rw-r--r-- | ppapi/proxy/plugin_var_serialization_rules.h | 12 | ||||
-rw-r--r-- | ppapi/proxy/ppp_messaging_proxy_perftest.cc | 20 | ||||
-rw-r--r-- | ppapi/proxy/serialized_var.cc | 76 | ||||
-rw-r--r-- | ppapi/proxy/serialized_var.h | 35 | ||||
-rw-r--r-- | ppapi/proxy/serialized_var_unittest.cc | 2 | ||||
-rw-r--r-- | ppapi/proxy/var_serialization_rules.h | 39 | ||||
-rw-r--r-- | ppapi/shared_impl/var.cc | 18 | ||||
-rw-r--r-- | ppapi/shared_impl/var.h | 9 |
11 files changed, 180 insertions, 117 deletions
diff --git a/ppapi/proxy/host_var_serialization_rules.cc b/ppapi/proxy/host_var_serialization_rules.cc index 3f11090..45eaf40 100644 --- a/ppapi/proxy/host_var_serialization_rules.cc +++ b/ppapi/proxy/host_var_serialization_rules.cc @@ -24,19 +24,24 @@ HostVarSerializationRules::HostVarSerializationRules(PP_Module pp_module) HostVarSerializationRules::~HostVarSerializationRules() { } -PP_Var HostVarSerializationRules::SendCallerOwned(const PP_Var& var, - std::string* str_val) { +PP_Var HostVarSerializationRules::SendCallerOwned( + const PP_Var& var, + const std::string** str_ptr_out) { if (var.type == PP_VARTYPE_STRING) - VarToString(var, str_val); + VarToStringPtr(var, str_ptr_out); return var; } PP_Var HostVarSerializationRules::BeginReceiveCallerOwned( const PP_Var& var, - const std::string* str_val, + scoped_ptr<std::string> str, Dispatcher* /* dispatcher */) { - if (var.type == PP_VARTYPE_STRING) - return StringVar::StringToPPVar(*str_val); + if (var.type == PP_VARTYPE_STRING) { + // Put the string in to the VarTracker (transferring ownership, since we + // would otherwise just delete the one we received from IPC). This allows + // us to avoid unnecessary copying of the string. + return StringVar::StringToPPVar(str.Pass()); + } return var; } @@ -47,12 +52,13 @@ void HostVarSerializationRules::EndReceiveCallerOwned(const PP_Var& var) { } } -PP_Var HostVarSerializationRules::ReceivePassRef(const PP_Var& var, - const std::string& str_val, - Dispatcher* /* dispatcher */) { +PP_Var HostVarSerializationRules::ReceivePassRef( + const PP_Var& var, + scoped_ptr<std::string> str, + Dispatcher* /* dispatcher */) { if (var.type == PP_VARTYPE_STRING) { - // Convert the string to the context of the current process. - return StringVar::StringToPPVar(str_val); + // Put the string in to the tracker, transferring ownership. + return StringVar::StringToPPVar(str.Pass()); } // See PluginVarSerialization::BeginSendPassRef for an example. @@ -61,12 +67,13 @@ PP_Var HostVarSerializationRules::ReceivePassRef(const PP_Var& var, return var; } -PP_Var HostVarSerializationRules::BeginSendPassRef(const PP_Var& var, - std::string* str_val) { +PP_Var HostVarSerializationRules::BeginSendPassRef( + const PP_Var& var, + const std::string** str_ptr_out) { // See PluginVarSerialization::ReceivePassRef for an example. We don't need // to do anything here other than convert the string. if (var.type == PP_VARTYPE_STRING) - VarToString(var, str_val); + VarToStringPtr(var, str_ptr_out); return var; } @@ -76,16 +83,14 @@ void HostVarSerializationRules::EndSendPassRef(const PP_Var& /* var */, // to do anything here. } -void HostVarSerializationRules::VarToString(const PP_Var& var, - std::string* str) { +void HostVarSerializationRules::VarToStringPtr( + const PP_Var& var, + const std::string** str_ptr_out) { DCHECK(var.type == PP_VARTYPE_STRING); - - // This could be optimized to avoid an extra string copy by going to a lower - // level of the browser's implementation of strings where we already have - // a std::string. + *str_ptr_out = NULL; StringVar* string_var = StringVar::FromPPVar(var); if (string_var) - *str = string_var->value(); + *str_ptr_out = string_var->ptr(); } void HostVarSerializationRules::ReleaseObjectRef(const PP_Var& var) { diff --git a/ppapi/proxy/host_var_serialization_rules.h b/ppapi/proxy/host_var_serialization_rules.h index bbbb3d7..609980f 100644 --- a/ppapi/proxy/host_var_serialization_rules.h +++ b/ppapi/proxy/host_var_serialization_rules.h @@ -22,22 +22,24 @@ class HostVarSerializationRules : public VarSerializationRules { ~HostVarSerializationRules(); // VarSerialization implementation. - virtual PP_Var SendCallerOwned(const PP_Var& var, std::string* str_val); + virtual PP_Var SendCallerOwned(const PP_Var& var, + const std::string** str_ptr_out); virtual PP_Var BeginReceiveCallerOwned(const PP_Var& var, - const std::string* str_val, + scoped_ptr<std::string> str, Dispatcher* dispatcher); virtual void EndReceiveCallerOwned(const PP_Var& var); virtual PP_Var ReceivePassRef(const PP_Var& var, - const std::string& str_val, + scoped_ptr<std::string> str, Dispatcher* dispatcher); - virtual PP_Var BeginSendPassRef(const PP_Var& var, std::string* str_val); + virtual PP_Var BeginSendPassRef(const PP_Var& var, + const std::string** str_ptr_out); virtual void EndSendPassRef(const PP_Var& var, Dispatcher* dispatcher); virtual void ReleaseObjectRef(const PP_Var& var); private: // Converts the given var (which must be a VARTYPE_STRING) to the given // string object. - void VarToString(const PP_Var& var, std::string* str); + void VarToStringPtr(const PP_Var& var, const std::string** str); PP_Module pp_module_; diff --git a/ppapi/proxy/plugin_var_serialization_rules.cc b/ppapi/proxy/plugin_var_serialization_rules.cc index 2e92dd5..87a3cc2 100644 --- a/ppapi/proxy/plugin_var_serialization_rules.cc +++ b/ppapi/proxy/plugin_var_serialization_rules.cc @@ -22,17 +22,19 @@ PluginVarSerializationRules::PluginVarSerializationRules() PluginVarSerializationRules::~PluginVarSerializationRules() { } -PP_Var PluginVarSerializationRules::SendCallerOwned(const PP_Var& var, - std::string* str_val) { +PP_Var PluginVarSerializationRules::SendCallerOwned( + const PP_Var& var, + const std::string** str_ptr_out) { // Objects need special translations to get the IDs valid in the host. if (var.type == PP_VARTYPE_OBJECT) return var_tracker_->GetHostObject(var); - // Retrieve the string to use for IPC. + // Retrieve the pointer to the string in the tracker in order to send the + // string over IPC without unnecessary copies. if (var.type == PP_VARTYPE_STRING) { StringVar* string_var = StringVar::FromPPVar(var); if (string_var) - *str_val = string_var->value(); + *str_ptr_out = string_var->ptr(); else NOTREACHED() << "Trying to send unknown string over IPC."; } @@ -41,10 +43,10 @@ PP_Var PluginVarSerializationRules::SendCallerOwned(const PP_Var& var, PP_Var PluginVarSerializationRules::BeginReceiveCallerOwned( const PP_Var& var, - const std::string* str_val, + scoped_ptr<std::string> str, Dispatcher* dispatcher) { if (var.type == PP_VARTYPE_STRING) - return StringVar::StringToPPVar(*str_val); + return StringVar::StringToPPVar(str.Pass()); if (var.type == PP_VARTYPE_OBJECT) { DCHECK(dispatcher->IsPlugin()); @@ -65,10 +67,10 @@ void PluginVarSerializationRules::EndReceiveCallerOwned(const PP_Var& var) { } PP_Var PluginVarSerializationRules::ReceivePassRef(const PP_Var& var, - const std::string& str_val, + scoped_ptr<std::string> str, Dispatcher* dispatcher) { if (var.type == PP_VARTYPE_STRING) - return StringVar::StringToPPVar(str_val); + return StringVar::StringToPPVar(str.Pass()); // Overview of sending an object with "pass ref" from the browser to the // plugin: @@ -96,8 +98,9 @@ PP_Var PluginVarSerializationRules::ReceivePassRef(const PP_Var& var, return var; } -PP_Var PluginVarSerializationRules::BeginSendPassRef(const PP_Var& var, - std::string* str_val) { +PP_Var PluginVarSerializationRules::BeginSendPassRef( + const PP_Var& var, + const std::string** str_ptr_out) { // Overview of sending an object with "pass ref" from the plugin to the // browser: // Example 1 Example 2 @@ -118,9 +121,11 @@ PP_Var PluginVarSerializationRules::BeginSendPassRef(const PP_Var& var, return var_tracker_->GetHostObject(var); if (var.type == PP_VARTYPE_STRING) { + // Get the pointer to the string that's in the tracker and return it, so we + // can avoid an extra copy of the string when serializing over IPC. StringVar* string_var = StringVar::FromPPVar(var); if (string_var) - *str_val = string_var->value(); + *str_ptr_out = string_var->ptr(); else NOTREACHED() << "Trying to send unknown string over IPC."; } diff --git a/ppapi/proxy/plugin_var_serialization_rules.h b/ppapi/proxy/plugin_var_serialization_rules.h index 6bd9638..8693505 100644 --- a/ppapi/proxy/plugin_var_serialization_rules.h +++ b/ppapi/proxy/plugin_var_serialization_rules.h @@ -1,4 +1,4 @@ -// Copyright (c) 2011 The Chromium Authors. All rights reserved. +// 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. @@ -22,15 +22,17 @@ class PluginVarSerializationRules : public VarSerializationRules { ~PluginVarSerializationRules(); // VarSerialization implementation. - virtual PP_Var SendCallerOwned(const PP_Var& var, std::string* str_val); + virtual PP_Var SendCallerOwned(const PP_Var& var, + const std::string** str_ptr_out); virtual PP_Var BeginReceiveCallerOwned(const PP_Var& var, - const std::string* str_val, + scoped_ptr<std::string> str, Dispatcher* dispatcher); virtual void EndReceiveCallerOwned(const PP_Var& var); virtual PP_Var ReceivePassRef(const PP_Var& var, - const std::string& str_val, + scoped_ptr<std::string> str, Dispatcher* dispatcher); - virtual PP_Var BeginSendPassRef(const PP_Var& var, std::string* str_val); + virtual PP_Var BeginSendPassRef(const PP_Var& var, + const std::string** str_ptr_out); virtual void EndSendPassRef(const PP_Var& var, Dispatcher* dispatcher); virtual void ReleaseObjectRef(const PP_Var& var); diff --git a/ppapi/proxy/ppp_messaging_proxy_perftest.cc b/ppapi/proxy/ppp_messaging_proxy_perftest.cc index a58b025..ecdeb12 100644 --- a/ppapi/proxy/ppp_messaging_proxy_perftest.cc +++ b/ppapi/proxy/ppp_messaging_proxy_perftest.cc @@ -29,6 +29,7 @@ void HandleMessage(PP_Instance /* instance */, PP_Var message_data) { // Do something simple with the string so the compiler won't complain. if (s.length() > 0) s[0] = 'a'; + PpapiGlobals::Get()->GetVarTracker()->ReleaseVar(message_data); handle_message_called.Signal(); } @@ -53,24 +54,29 @@ TEST_F(PppMessagingPerfTest, StringPerformance) { host().host_dispatcher()->GetProxiedInterface( PPP_MESSAGING_INTERFACE)); const PP_Instance kTestInstance = pp_instance(); - int string_size = 100000; + int seed = 123; int string_count = 1000; + int max_string_size = 1000000; CommandLine* command_line = CommandLine::ForCurrentProcess(); if (command_line) { - if (command_line->HasSwitch("string_size")) { - base::StringToInt(command_line->GetSwitchValueASCII("string_size"), - &string_size); + if (command_line->HasSwitch("seed")) { + base::StringToInt(command_line->GetSwitchValueASCII("seed"), + &seed); } if (command_line->HasSwitch("string_count")) { base::StringToInt(command_line->GetSwitchValueASCII("string_count"), &string_count); } + if (command_line->HasSwitch("max_string_size")) { + base::StringToInt(command_line->GetSwitchValueASCII("max_string_size"), + &max_string_size); + } } - // Make a string var of size string_size. - const std::string kTestString(string_size, 'a'); + srand(seed); PerfTimeLogger logger("PppMessagingPerfTest.StringPerformance"); for (int i = 0; i < string_count; ++i) { - PP_Var host_string = StringVar::StringToPPVar(kTestString); + const std::string test_string(rand() % max_string_size, 'a'); + PP_Var host_string = StringVar::StringToPPVar(test_string); ppp_messaging->HandleMessage(kTestInstance, host_string); handle_message_called.Wait(); PpapiGlobals::Get()->GetVarTracker()->ReleaseVar(host_string); diff --git a/ppapi/proxy/serialized_var.cc b/ppapi/proxy/serialized_var.cc index f9d59e5..00bb296 100644 --- a/ppapi/proxy/serialized_var.cc +++ b/ppapi/proxy/serialized_var.cc @@ -1,4 +1,4 @@ -// Copyright (c) 2011 The Chromium Authors. All rights reserved. +// 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. @@ -19,6 +19,7 @@ namespace proxy { SerializedVar::Inner::Inner() : serialization_rules_(NULL), var_(PP_MakeUndefined()), + tracker_string_ptr_(NULL), cleanup_mode_(CLEANUP_NONE), dispatcher_for_end_send_pass_ref_(NULL) { #ifndef NDEBUG @@ -30,18 +31,7 @@ SerializedVar::Inner::Inner() SerializedVar::Inner::Inner(VarSerializationRules* serialization_rules) : serialization_rules_(serialization_rules), var_(PP_MakeUndefined()), - cleanup_mode_(CLEANUP_NONE), - dispatcher_for_end_send_pass_ref_(NULL) { -#ifndef NDEBUG - has_been_serialized_ = false; - has_been_deserialized_ = false; -#endif -} - -SerializedVar::Inner::Inner(VarSerializationRules* serialization_rules, - const PP_Var& var) - : serialization_rules_(serialization_rules), - var_(var), + tracker_string_ptr_(NULL), cleanup_mode_(CLEANUP_NONE), dispatcher_for_end_send_pass_ref_(NULL) { #ifndef NDEBUG @@ -86,14 +76,18 @@ void SerializedVar::Inner::SetVar(PP_Var var) { var_ = var; } -const std::string& SerializedVar::Inner::GetString() const { +scoped_ptr<std::string> SerializedVar::Inner::GetStringDestructive() { DCHECK(serialization_rules_); - return string_value_; + return string_from_ipc_.Pass(); } -std::string* SerializedVar::Inner::GetStringPtr() { +const std::string** SerializedVar::Inner::GetStringPtrPtr() { DCHECK(serialization_rules_); - return &string_value_; + // The caller will set our string pointer, and we promise not to change it. + // This path is taken for the "Send" side of SerializedVars, and we will only + // read the string in those cases, so it's safe for us to point directly to a + // string in the VarTracker. + return &tracker_string_ptr_; } void SerializedVar::Inner::ForceSetVarValueForTest(PP_Var value) { @@ -101,7 +95,10 @@ void SerializedVar::Inner::ForceSetVarValueForTest(PP_Var value) { } void SerializedVar::Inner::ForceSetStringValueForTest(const std::string& str) { - string_value_ = str; + // We don't need to change tracker_string_ptr_, as that is only used for + // serializing, and we're emulating a SerializedVar that was received from + // IPC. + string_from_ipc_.reset(new std::string(str)); } void SerializedVar::Inner::WriteToMessage(IPC::Message* m) const { @@ -126,7 +123,7 @@ void SerializedVar::Inner::WriteToMessage(IPC::Message* m) const { // If the var is not a string type, we should not have ended up with any // string data. - DCHECK(var_.type == PP_VARTYPE_STRING || string_value_.empty()); + DCHECK(var_.type == PP_VARTYPE_STRING || !tracker_string_ptr_); m->WriteInt(static_cast<int>(var_.type)); switch (var_.type) { @@ -150,7 +147,8 @@ void SerializedVar::Inner::WriteToMessage(IPC::Message* m) const { // generated there. Then the function implementing the interface can // handle the invalid string as if it was in process rather than seeing // what looks like a valid empty string. - m->WriteString(string_value_); + m->WriteString(tracker_string_ptr_ ? *tracker_string_ptr_ + : std::string()); break; case PP_VARTYPE_ARRAY_BUFFER: // TODO(dmichael): Proxy ArrayBuffer. @@ -207,7 +205,9 @@ bool SerializedVar::Inner::ReadFromMessage(const IPC::Message* m, void** iter) { success = IPC::ParamTraits<double>::Read(m, iter, &var_.value.as_double); break; case PP_VARTYPE_STRING: - success = m->ReadString(iter, &string_value_); + DCHECK(!tracker_string_ptr_ && !string_from_ipc_.get()); + string_from_ipc_.reset(new std::string); + success = m->ReadString(iter, string_from_ipc_.get()); var_.value.as_id = 0; break; case PP_VARTYPE_OBJECT: @@ -252,11 +252,6 @@ SerializedVar::SerializedVar(VarSerializationRules* serialization_rules) : inner_(new Inner(serialization_rules)) { } -SerializedVar::SerializedVar(VarSerializationRules* serialization_rules, - const PP_Var& var) - : inner_(new Inner(serialization_rules, var)) { -} - SerializedVar::~SerializedVar() { } @@ -266,7 +261,7 @@ SerializedVarSendInput::SerializedVarSendInput(Dispatcher* dispatcher, const PP_Var& var) : SerializedVar(dispatcher->serialization_rules()) { inner_->SetVar(dispatcher->serialization_rules()->SendCallerOwned( - var, inner_->GetStringPtr())); + var, inner_->GetStringPtrPtr())); } // static @@ -274,13 +269,9 @@ void SerializedVarSendInput::ConvertVector(Dispatcher* dispatcher, const PP_Var* input, size_t input_count, std::vector<SerializedVar>* output) { - output->resize(input_count); - for (size_t i = 0; i < input_count; i++) { - SerializedVar& cur = (*output)[i]; - cur = SerializedVar(dispatcher->serialization_rules()); - cur.inner_->SetVar(dispatcher->serialization_rules()->SendCallerOwned( - input[i], cur.inner_->GetStringPtr())); - } + output->reserve(input_count); + for (size_t i = 0; i < input_count; i++) + output->push_back(SerializedVarSendInput(dispatcher, input[i])); } // ReceiveSerializedVarReturnValue --------------------------------------------- @@ -296,7 +287,7 @@ ReceiveSerializedVarReturnValue::ReceiveSerializedVarReturnValue( PP_Var ReceiveSerializedVarReturnValue::Return(Dispatcher* dispatcher) { inner_->set_serialization_rules(dispatcher->serialization_rules()); inner_->SetVar(inner_->serialization_rules()->ReceivePassRef( - inner_->GetIncompleteVar(), inner_->GetString(), dispatcher)); + inner_->GetIncompleteVar(), inner_->GetStringDestructive(), dispatcher)); return inner_->GetVar(); } @@ -313,8 +304,11 @@ ReceiveSerializedException::~ReceiveSerializedException() { if (exception_) { // When an output exception is specified, it will take ownership of the // reference. - inner_->SetVar(inner_->serialization_rules()->ReceivePassRef( - inner_->GetIncompleteVar(), inner_->GetString(), dispatcher_)); + inner_->SetVar( + inner_->serialization_rules()->ReceivePassRef( + inner_->GetIncompleteVar(), + inner_->GetStringDestructive(), + dispatcher_)); *exception_ = inner_->GetVar(); } else { // When no output exception is specified, the browser thinks we have a ref @@ -388,7 +382,7 @@ PP_Var SerializedVarReceiveInput::Get(Dispatcher* dispatcher) { serialized_.inner_->SetVar( serialized_.inner_->serialization_rules()->BeginReceiveCallerOwned( serialized_.inner_->GetIncompleteVar(), - serialized_.inner_->GetStringPtr(), + serialized_.inner_->GetStringDestructive(), dispatcher)); return serialized_.inner_->GetVar(); } @@ -419,7 +413,7 @@ PP_Var* SerializedVarVectorReceiveInput::Get(Dispatcher* dispatcher, serialized_[i].inner_->SetVar( serialized_[i].inner_->serialization_rules()->BeginReceiveCallerOwned( serialized_[i].inner_->GetIncompleteVar(), - serialized_[i].inner_->GetStringPtr(), + serialized_[i].inner_->GetStringDestructive(), dispatcher)); deserialized_[i] = serialized_[i].inner_->GetVar(); } @@ -445,7 +439,7 @@ void SerializedVarReturnValue::Return(Dispatcher* dispatcher, serialized_->inner_->SetVar( dispatcher->serialization_rules()->BeginSendPassRef( var, - serialized_->inner_->GetStringPtr())); + serialized_->inner_->GetStringPtrPtr())); } // static @@ -472,7 +466,7 @@ SerializedVarOutParam::~SerializedVarOutParam() { // in that case. serialized_->inner_->SetVar( serialized_->inner_->serialization_rules()->BeginSendPassRef( - writable_var_, serialized_->inner_->GetStringPtr())); + writable_var_, serialized_->inner_->GetStringPtrPtr())); // Normally the current object will be created on the stack to wrap a // SerializedVar and won't have a scope around the actual IPC send. So we diff --git a/ppapi/proxy/serialized_var.h b/ppapi/proxy/serialized_var.h index c0cb1ac..1ad218d 100644 --- a/ppapi/proxy/serialized_var.h +++ b/ppapi/proxy/serialized_var.h @@ -1,4 +1,4 @@ -// Copyright (c) 2011 The Chromium Authors. All rights reserved. +// 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. @@ -10,6 +10,7 @@ #include "base/basictypes.h" #include "base/memory/ref_counted.h" +#include "base/memory/scoped_ptr.h" #include "ppapi/c/pp_var.h" #include "ppapi/proxy/ppapi_proxy_export.h" @@ -87,7 +88,6 @@ class PPAPI_PROXY_EXPORT SerializedVar { public: Inner(); Inner(VarSerializationRules* serialization_rules); - Inner(VarSerializationRules* serialization_rules, const PP_Var& var); ~Inner(); VarSerializationRules* serialization_rules() { @@ -101,8 +101,14 @@ class PPAPI_PROXY_EXPORT SerializedVar { PP_Var GetVar() const; PP_Var GetIncompleteVar() const; void SetVar(PP_Var var); - const std::string& GetString() const; - std::string* GetStringPtr(); + void SetString(scoped_ptr<std::string> str); + // Return a new string with the contents of the string referenced by Inner. + // The string referenced by the Inner will be empty after this. + scoped_ptr<std::string> GetStringDestructive(); + // Return a pointer to our internal string pointer. This is so that the + // caller will be able to make this Inner point to a string that's owned + // elsewhere (i.e., in the tracker). + const std::string** GetStringPtrPtr(); // For the SerializedVarTestConstructor, this writes the Var value as if // it was just received off the wire, without any serialization rules. @@ -137,7 +143,7 @@ class PPAPI_PROXY_EXPORT SerializedVar { VarSerializationRules* serialization_rules_; // If this is set to VARTYPE_STRING and the 'value.id' is 0, then the - // string_value_ contains the string. This means that the caller hasn't + // string_from_ipc_ holds the string. This means that the caller hasn't // called Deserialize with a valid Dispatcher yet, which is how we can // convert the serialized string value to a PP_Var string ID. // @@ -146,9 +152,17 @@ class PPAPI_PROXY_EXPORT SerializedVar { // a string ID. Before this, the as_id will be 0 for VARTYPE_STRING. PP_Var var_; - // Holds the literal string value to/from IPC. This will be valid if the - // var_ is VARTYPE_STRING. - std::string string_value_; + // If valid, this is a pointer to a string owned by the VarTracker. When our + // outer SerializedVar gets serialized, it will write the string directly + // from the tracker so we do not need to make any unnecessary copies. This + // should only be valid on the sender side. + const std::string* tracker_string_ptr_; + + // If valid, this is a string received from IPC which needs to be inserted + // in to the var tracker. When we provide it to the tracker, we pass + // ownership so that there are no unnecessary copies. This should only ever + // be valid on the receiver side. + scoped_ptr<std::string> string_from_ipc_; CleanupMode cleanup_mode_; @@ -167,7 +181,6 @@ class PPAPI_PROXY_EXPORT SerializedVar { }; SerializedVar(VarSerializationRules* serialization_rules); - SerializedVar(VarSerializationRules* serialization, const PP_Var& var); mutable scoped_refptr<Inner> inner_; }; @@ -453,7 +466,9 @@ class PPAPI_PROXY_EXPORT SerializedVarTestReader : public SerializedVar { // actually want to check. PP_Var GetIncompleteVar() const { return inner_->GetIncompleteVar(); } - const std::string& GetString() const { return inner_->GetString(); } + const std::string* GetTrackerStringPtr() const { + return *inner_->GetStringPtrPtr(); + } }; } // namespace proxy diff --git a/ppapi/proxy/serialized_var_unittest.cc b/ppapi/proxy/serialized_var_unittest.cc index 494a68d..1ad9348 100644 --- a/ppapi/proxy/serialized_var_unittest.cc +++ b/ppapi/proxy/serialized_var_unittest.cc @@ -105,7 +105,7 @@ TEST_F(SerializedVarTest, PluginSerializedStringVarInOutParam) { // the var tracker should have changed yet, and no messages should have been // sent. SerializedVarTestReader reader(sv); - EXPECT_EQ(kTestString, reader.GetString()); + EXPECT_EQ(kTestString, *reader.GetTrackerStringPtr()); EXPECT_EQ(2, var_tracker().GetRefCountForObject(plugin_string)); EXPECT_EQ(0u, sink().message_count()); } diff --git a/ppapi/proxy/var_serialization_rules.h b/ppapi/proxy/var_serialization_rules.h index b77e834..92d0db8 100644 --- a/ppapi/proxy/var_serialization_rules.h +++ b/ppapi/proxy/var_serialization_rules.h @@ -1,10 +1,11 @@ -// Copyright (c) 2011 The Chromium Authors. All rights reserved. +// 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. #ifndef PPAPI_PROXY_VAR_SERIALIZATION_RULES_H_ #define PPAPI_PROXY_VAR_SERIALIZATION_RULES_H_ +#include "base/memory/scoped_ptr.h" #include "ppapi/c/pp_var.h" #include <string> @@ -27,27 +28,32 @@ class VarSerializationRules { // argument. The caller has a reference to the var, and the caller is // responsible for freeing that reference. - // Prepares the given var for sending to the callee. If the var is a string, - // the value of that string will be placed in *str_val. If the var is not - // a string, str_val will be untouched and may be NULL. The return value will - // be the var valid for the host process. - virtual PP_Var SendCallerOwned(const PP_Var& var, std::string* str_val) = 0; + // Prepares the given var for sending to the remote process. If the var is a + // string, *str_ptr_out will be set to point to the string in the tracker + // referenced by var. If the var is not a string, *str_ptr_out will be + // untouched and may be NULL. For object vars, the returned var will contain + // the id valid for the host process. Otherwise, the returned var is valid in + // the local process. + virtual PP_Var SendCallerOwned(const PP_Var& var, + const std::string** str_ptr_out) = 0; // When receiving a caller-owned variable, normally we don't have to do // anything. However, in the case of strings, we need to deserialize the // string from IPC, create a new PP_Var string in the local process, call the // function, and then destroy the temporary string. These two functions - // handle that process + // handle that process. // // BeginReceiveCallerOwned takes a var from IPC and an optional pointer to // the deserialized string (which will be used only when var is a // VARTYPE_STRING and may be NULL otherwise) and returns a new var // representing the input in the local process. // - // EndReceiveCallerOwned destroys the string created by Begin* and does - // nothing otherwise. It should be called with the result of Begin*. + // EndReceiveCallerOwned releases the reference count in the Var tracker for + // the object or string that was added to the tracker. (Note, if the recipient + // took a reference to the Var, it will remain in the tracker after + // EndReceiveCallerOwned). virtual PP_Var BeginReceiveCallerOwned(const PP_Var& var, - const std::string* str_val, + scoped_ptr<std::string> str, Dispatcher* dispatcher) = 0; virtual void EndReceiveCallerOwned(const PP_Var& var) = 0; @@ -65,18 +71,21 @@ class VarSerializationRules { // deserialized var and deserialized string (which will be used only when var // is a VARTYPE_STRING and may be NULL otherwise). The input var/string // should be the result of calling SendPassRef in the remote process. The - // return value is the var valid in the plugin process. + // return value is the var valid in the host process for object vars. + // Otherwise, the return value is a var which is valid in the local process. virtual PP_Var ReceivePassRef(const PP_Var& var, - const std::string& str_val, + scoped_ptr<std::string> str, Dispatcher* dispatcher) = 0; // Prepares a var to be sent to the remote side. One local reference will // be passed to the remote side. Call Begin* before doing the send and End* // after doing the send. See SendCallerOwned for a description of the string. // - // The return value from BeginSendPassRef will be the var valid for the host - // process. This same value must be passed to EndSendPassRef. - virtual PP_Var BeginSendPassRef(const PP_Var& var, std::string* str_val) = 0; + // For object vars, the return value from BeginSendPassRef will be the var + // valid for the host process. Otherwise, it is a var that is valid in the + // local process. This same var must be passed to EndSendPassRef. + virtual PP_Var BeginSendPassRef(const PP_Var& var, + const std::string** str_ptr_out) = 0; virtual void EndSendPassRef(const PP_Var& var, Dispatcher* dispatcher) = 0; // --------------------------------------------------------------------------- diff --git a/ppapi/shared_impl/var.cc b/ppapi/shared_impl/var.cc index 60d439b..d7b0dac 100644 --- a/ppapi/shared_impl/var.cc +++ b/ppapi/shared_impl/var.cc @@ -1,4 +1,4 @@ -// Copyright (c) 2011 The Chromium Authors. All rights reserved. +// 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. @@ -124,6 +124,11 @@ StringVar::StringVar(const char* str, uint32 len) StringVar::~StringVar() { } +StringVar::StringVar(scoped_ptr<std::string> str) { + // Swap the given string's contents in to value to avoid copying. + str->swap(value_); +} + StringVar* StringVar::AsStringVar() { return this; } @@ -146,6 +151,17 @@ PP_Var StringVar::StringToPPVar(const char* data, uint32 len) { } // static +PP_Var StringVar::StringToPPVar(scoped_ptr<std::string> str) { + DCHECK(str.get()); + if (!str.get()) + return PP_MakeNull(); + scoped_refptr<StringVar> str_var(new StringVar(str.Pass())); + if (!str_var || !IsStringUTF8(str_var->value())) + return PP_MakeNull(); + return str_var->GetPPVar(); +} + +// static StringVar* StringVar::FromPPVar(PP_Var var) { if (var.type != PP_VARTYPE_STRING) return NULL; diff --git a/ppapi/shared_impl/var.h b/ppapi/shared_impl/var.h index 4d833ae..ed7f4f1 100644 --- a/ppapi/shared_impl/var.h +++ b/ppapi/shared_impl/var.h @@ -9,6 +9,7 @@ #include "base/compiler_specific.h" #include "base/memory/ref_counted.h" +#include "base/memory/scoped_ptr.h" #include "ppapi/c/pp_var.h" #include "ppapi/shared_impl/ppapi_shared_export.h" @@ -93,9 +94,16 @@ class PPAPI_SHARED_EXPORT StringVar : public Var { public: StringVar(const std::string& str); StringVar(const char* str, uint32 len); + StringVar(scoped_ptr<std::string> str); virtual ~StringVar(); const std::string& value() const { return value_; } + // Return a pointer to the internal string. This allows other objects to + // temporarily store a weak pointer to our internal string. Use with care; the + // pointer *will* become invalid if this StringVar is removed from the + // tracker. (All of this applies to value(), but this one's even easier to use + // dangerously). + const std::string* ptr() const { return &value_; } // Var override. virtual StringVar* AsStringVar() OVERRIDE; @@ -109,6 +117,7 @@ class PPAPI_SHARED_EXPORT StringVar : public Var { // create a StringVar and return the reference to it in the var. static PP_Var StringToPPVar(const std::string& str); static PP_Var StringToPPVar(const char* str, uint32 len); + static PP_Var StringToPPVar(scoped_ptr<std::string> str); // Helper function that converts a PP_Var to a string. This will return NULL // if the PP_Var is not of string type or the string is invalid. |