| Index: ppapi/proxy/serialized_var.cc
|
| diff --git a/ppapi/proxy/serialized_var.cc b/ppapi/proxy/serialized_var.cc
|
| index f9d59e5e6c9120cbd779594f1474abe830c7ece6..663706fbafb9168d90d46deaac412948e7b0ee3b 100644
|
| --- a/ppapi/proxy/serialized_var.cc
|
| +++ b/ppapi/proxy/serialized_var.cc
|
| @@ -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
|
|
|