| Index: content/renderer/pepper/pepper_plugin_instance_impl.cc
|
| diff --git a/content/renderer/pepper/pepper_plugin_instance_impl.cc b/content/renderer/pepper/pepper_plugin_instance_impl.cc
|
| index 1fee1a719be267de1509bdc51e9b44dc880d9b5b..304fdf88a897a4a732a9ab1433076cf21d96d6cf 100644
|
| --- a/content/renderer/pepper/pepper_plugin_instance_impl.cc
|
| +++ b/content/renderer/pepper/pepper_plugin_instance_impl.cc
|
| @@ -33,12 +33,12 @@
|
| #include "content/renderer/pepper/host_dispatcher_wrapper.h"
|
| #include "content/renderer/pepper/host_globals.h"
|
| #include "content/renderer/pepper/message_channel.h"
|
| -#include "content/renderer/pepper/npapi_glue.h"
|
| #include "content/renderer/pepper/pepper_browser_connection.h"
|
| #include "content/renderer/pepper/pepper_compositor_host.h"
|
| #include "content/renderer/pepper/pepper_file_ref_renderer_host.h"
|
| #include "content/renderer/pepper/pepper_graphics_2d_host.h"
|
| #include "content/renderer/pepper/pepper_in_process_router.h"
|
| +#include "content/renderer/pepper/pepper_try_catch.h"
|
| #include "content/renderer/pepper/pepper_url_loader_host.h"
|
| #include "content/renderer/pepper/plugin_module.h"
|
| #include "content/renderer/pepper/plugin_object.h"
|
| @@ -115,6 +115,7 @@
|
| #include "third_party/WebKit/public/web/WebPrintParams.h"
|
| #include "third_party/WebKit/public/web/WebPrintScalingOption.h"
|
| #include "third_party/WebKit/public/web/WebScopedUserGesture.h"
|
| +#include "third_party/WebKit/public/web/WebScriptSource.h"
|
| #include "third_party/WebKit/public/web/WebSecurityOrigin.h"
|
| #include "third_party/WebKit/public/web/WebUserGestureIndicator.h"
|
| #include "third_party/WebKit/public/web/WebView.h"
|
| @@ -543,6 +544,7 @@ PepperPluginInstanceImpl::PepperPluginInstanceImpl(
|
| fullscreen_container_(NULL),
|
| flash_fullscreen_(false),
|
| desired_fullscreen_state_(false),
|
| + message_channel_(NULL),
|
| sad_plugin_(NULL),
|
| input_event_mask_(0),
|
| filtered_input_event_mask_(0),
|
| @@ -555,7 +557,6 @@ PepperPluginInstanceImpl::PepperPluginInstanceImpl(
|
| pending_user_gesture_(0.0),
|
| document_loader_(NULL),
|
| external_document_load_(false),
|
| - npp_(new NPP_t),
|
| isolate_(v8::Isolate::GetCurrent()),
|
| is_deleted_(false),
|
| last_input_number_(0),
|
| @@ -616,8 +617,8 @@ PepperPluginInstanceImpl::PepperPluginInstanceImpl(
|
| PepperPluginInstanceImpl::~PepperPluginInstanceImpl() {
|
| DCHECK(!fullscreen_container_);
|
|
|
| - // Free all the plugin objects. This will automatically clear the back-
|
| - // pointer from the NPObject so WebKit can't call into the plugin any more.
|
| + // Notify all the plugin objects of deletion. This will prevent blink from
|
| + // calling into the plugin any more.
|
| //
|
| // Swap out the set so we can delete from it (the objects will try to
|
| // unregister themselves inside the delete call).
|
| @@ -625,8 +626,13 @@ PepperPluginInstanceImpl::~PepperPluginInstanceImpl() {
|
| live_plugin_objects_.swap(plugin_object_copy);
|
| for (PluginObjectSet::iterator i = plugin_object_copy.begin();
|
| i != plugin_object_copy.end();
|
| - ++i)
|
| - delete *i;
|
| + ++i) {
|
| + (*i)->InstanceDeleted();
|
| + }
|
| +
|
| + if (message_channel_)
|
| + message_channel_->InstanceDeleted();
|
| + message_channel_object_.Reset();
|
|
|
| if (TrackedCallback::IsPending(lock_mouse_callback_))
|
| lock_mouse_callback_->Abort();
|
| @@ -657,6 +663,15 @@ PepperPluginInstanceImpl::~PepperPluginInstanceImpl() {
|
| // If a method needs to access a member of the instance after the call has
|
| // returned, then it needs to keep its own reference on the stack.
|
|
|
| +v8::Local<v8::Object> PepperPluginInstanceImpl::GetMessageChannelObject() {
|
| + return v8::Local<v8::Object>::New(isolate_, message_channel_object_);
|
| +}
|
| +
|
| +void PepperPluginInstanceImpl::MessageChannelDestroyed() {
|
| + message_channel_ = NULL;
|
| + message_channel_object_.Reset();
|
| +}
|
| +
|
| v8::Local<v8::Context> PepperPluginInstanceImpl::GetContext() {
|
| if (!container_)
|
| return v8::Handle<v8::Context>();
|
| @@ -683,7 +698,8 @@ void PepperPluginInstanceImpl::Delete() {
|
| // release our last reference to the "InstanceObject" and will probably
|
| // destroy it. We want to do this prior to calling DidDestroy in case the
|
| // destructor of the instance object tries to use the instance.
|
| - message_channel_->SetPassthroughObject(NULL);
|
| + if (message_channel_)
|
| + message_channel_->SetPassthroughObject(v8::Handle<v8::Object>());
|
| // If this is a NaCl plugin instance, shut down the NaCl plugin by calling
|
| // its DidDestroy. Don't call DidDestroy on the untrusted plugin instance,
|
| // since there is little that it can do at this point.
|
| @@ -845,7 +861,7 @@ bool PepperPluginInstanceImpl::Initialize(
|
| bool full_frame) {
|
| if (!render_frame_)
|
| return false;
|
| - message_channel_.reset(new MessageChannel(this));
|
| + message_channel_ = MessageChannel::Create(this, &message_channel_object_);
|
|
|
| full_frame_ = full_frame;
|
|
|
| @@ -868,9 +884,11 @@ bool PepperPluginInstanceImpl::Initialize(
|
| // messages. (E.g., NaCl trusted plugin starting a child NaCl app.)
|
| //
|
| // A host for external plugins will call ResetAsProxied later, at which point
|
| - // we can Start() the message_channel_.
|
| - if (success && (!module_->renderer_ppapi_host()->IsExternalPluginHost()))
|
| - message_channel_->Start();
|
| + // we can Start() the MessageChannel.
|
| + if (success && (!module_->renderer_ppapi_host()->IsExternalPluginHost())) {
|
| + if (message_channel_)
|
| + message_channel_->Start();
|
| + }
|
| return success;
|
| }
|
|
|
| @@ -1173,6 +1191,8 @@ bool PepperPluginInstanceImpl::HandleInputEvent(
|
|
|
| void PepperPluginInstanceImpl::HandleMessage(ScopedPPVar message) {
|
| TRACE_EVENT0("ppapi", "PepperPluginInstanceImpl::HandleMessage");
|
| + if (is_deleted_)
|
| + return;
|
| ppapi::proxy::HostDispatcher* dispatcher =
|
| ppapi::proxy::HostDispatcher::GetForInstance(pp_instance());
|
| if (!dispatcher || (message.get().type == PP_VARTYPE_OBJECT)) {
|
| @@ -1191,6 +1211,8 @@ void PepperPluginInstanceImpl::HandleMessage(ScopedPPVar message) {
|
| bool PepperPluginInstanceImpl::HandleBlockingMessage(ScopedPPVar message,
|
| ScopedPPVar* result) {
|
| TRACE_EVENT0("ppapi", "PepperPluginInstanceImpl::HandleBlockingMessage");
|
| + if (is_deleted_)
|
| + return false;
|
| ppapi::proxy::HostDispatcher* dispatcher =
|
| ppapi::proxy::HostDispatcher::GetForInstance(pp_instance());
|
| if (!dispatcher || (message.get().type == PP_VARTYPE_OBJECT)) {
|
| @@ -1214,10 +1236,12 @@ bool PepperPluginInstanceImpl::HandleBlockingMessage(ScopedPPVar message,
|
| return was_handled;
|
| }
|
|
|
| -PP_Var PepperPluginInstanceImpl::GetInstanceObject() {
|
| +PP_Var PepperPluginInstanceImpl::GetInstanceObject(v8::Isolate* isolate) {
|
| // Keep a reference on the stack. See NOTE above.
|
| scoped_refptr<PepperPluginInstanceImpl> ref(this);
|
|
|
| + DCHECK_EQ(isolate, isolate_);
|
| +
|
| // If the plugin supports the private instance interface, try to retrieve its
|
| // instance object.
|
| if (LoadPrivateInterface())
|
| @@ -1353,7 +1377,8 @@ void PepperPluginInstanceImpl::SetTextInputType(ui::TextInputType type) {
|
| }
|
|
|
| void PepperPluginInstanceImpl::PostMessageToJavaScript(PP_Var message) {
|
| - message_channel_->PostMessageToJavaScript(message);
|
| + if (message_channel_)
|
| + message_channel_->PostMessageToJavaScript(message);
|
| }
|
|
|
| int32_t PepperPluginInstanceImpl::RegisterMessageHandler(
|
| @@ -2352,70 +2377,76 @@ PP_Var PepperPluginInstanceImpl::GetWindowObject(PP_Instance instance) {
|
| if (!container_)
|
| return PP_MakeUndefined();
|
|
|
| + PepperTryCatchVar try_catch(this, NULL);
|
| WebLocalFrame* frame = container_->element().document().frame();
|
| - if (!frame)
|
| + if (!frame) {
|
| + try_catch.SetException("No frame exists for window object.");
|
| return PP_MakeUndefined();
|
| + }
|
|
|
| - return NPObjectToPPVar(this, frame->windowObject());
|
| + ScopedPPVar result =
|
| + try_catch.FromV8(frame->mainWorldScriptContext()->Global());
|
| + DCHECK(!try_catch.HasException());
|
| + return result.Release();
|
| }
|
|
|
| PP_Var PepperPluginInstanceImpl::GetOwnerElementObject(PP_Instance instance) {
|
| if (!container_)
|
| return PP_MakeUndefined();
|
| - return NPObjectToPPVar(this, container_->scriptableObjectForElement());
|
| + PepperTryCatchVar try_catch(this, NULL);
|
| + ScopedPPVar result = try_catch.FromV8(container_->v8ObjectForElement());
|
| + DCHECK(!try_catch.HasException());
|
| + return result.Release();
|
| }
|
|
|
| PP_Var PepperPluginInstanceImpl::ExecuteScript(PP_Instance instance,
|
| - PP_Var script,
|
| + PP_Var script_var,
|
| PP_Var* exception) {
|
| + if (!container_)
|
| + return PP_MakeUndefined();
|
| +
|
| // Executing the script may remove the plugin from the DOM, so we need to keep
|
| // a reference to ourselves so that we can still process the result after the
|
| // WebBindings::evaluate() below.
|
| scoped_refptr<PepperPluginInstanceImpl> ref(this);
|
| - TryCatch try_catch(exception);
|
| - if (try_catch.has_exception())
|
| + PepperTryCatchVar try_catch(this, exception);
|
| +
|
| + // Check for an exception due to the context being destroyed.
|
| + if (try_catch.HasException())
|
| return PP_MakeUndefined();
|
|
|
| - // Convert the script into an inconvenient NPString object.
|
| - StringVar* script_string = StringVar::FromPPVar(script);
|
| - if (!script_string) {
|
| - try_catch.SetException("Script param to ExecuteScript must be a string.");
|
| + WebLocalFrame* frame = container_->element().document().frame();
|
| + if (!frame) {
|
| + try_catch.SetException("No frame to execute script in.");
|
| return PP_MakeUndefined();
|
| }
|
| - NPString np_script;
|
| - np_script.UTF8Characters = script_string->value().c_str();
|
| - np_script.UTF8Length = script_string->value().length();
|
|
|
| - // Get the current frame to pass to the evaluate function.
|
| - WebLocalFrame* frame = NULL;
|
| - if (container_)
|
| - frame = container_->element().document().frame();
|
| - if (!frame || !frame->windowObject()) {
|
| - try_catch.SetException("No context in which to execute script.");
|
| + StringVar* script_string_var = StringVar::FromPPVar(script_var);
|
| + if (!script_string_var) {
|
| + try_catch.SetException("Script param to ExecuteScript must be a string.");
|
| return PP_MakeUndefined();
|
| }
|
|
|
| - NPVariant result;
|
| - bool ok = false;
|
| + std::string script_string = script_string_var->value();
|
| + blink::WebScriptSource script(
|
| + blink::WebString::fromUTF8(script_string.c_str()));
|
| + v8::Handle<v8::Value> result;
|
| if (IsProcessingUserGesture()) {
|
| blink::WebScopedUserGesture user_gesture(CurrentUserGestureToken());
|
| - ok =
|
| - WebBindings::evaluate(NULL, frame->windowObject(), &np_script, &result);
|
| + result = frame->executeScriptAndReturnValue(script);
|
| } else {
|
| - ok =
|
| - WebBindings::evaluate(NULL, frame->windowObject(), &np_script, &result);
|
| - }
|
| - if (!ok) {
|
| - // TryCatch doesn't catch the exceptions properly. Since this is only for
|
| - // a trusted API, just set to a general exception message.
|
| - try_catch.SetException("Exception caught");
|
| - WebBindings::releaseVariantValue(&result);
|
| - return PP_MakeUndefined();
|
| + result = frame->executeScriptAndReturnValue(script);
|
| }
|
|
|
| - PP_Var ret = NPVariantToPPVar(this, &result);
|
| - WebBindings::releaseVariantValue(&result);
|
| - return ret;
|
| + // Check for an exception due to the context being destroyed.
|
| + if (try_catch.HasException())
|
| + return PP_MakeUndefined();
|
| +
|
| + ScopedPPVar var_result = try_catch.FromV8(result);
|
| + if (try_catch.HasException())
|
| + return PP_MakeUndefined();
|
| +
|
| + return var_result.Release();
|
| }
|
|
|
| uint32_t PepperPluginInstanceImpl::GetAudioHardwareOutputSampleRate(
|
| @@ -2944,7 +2975,8 @@ PP_ExternalPluginResult PepperPluginInstanceImpl::ResetAsProxied(
|
| if (!instance_interface_->DidCreate(
|
| pp_instance(), argn_.size(), argn_array.get(), argv_array.get()))
|
| return PP_EXTERNAL_PLUGIN_ERROR_INSTANCE;
|
| - message_channel_->Start();
|
| + if (message_channel_)
|
| + message_channel_->Start();
|
|
|
| // Clear sent_initial_did_change_view_ and cancel any pending DidChangeView
|
| // event. This way, SendDidChangeView will send the "current" view
|
| @@ -2973,8 +3005,6 @@ bool PepperPluginInstanceImpl::IsValidInstanceOf(PluginModule* module) {
|
| return module == module_.get() || module == original_module_.get();
|
| }
|
|
|
| -NPP PepperPluginInstanceImpl::instanceNPP() { return npp_.get(); }
|
| -
|
| PepperPluginInstance* PepperPluginInstance::Get(PP_Instance instance_id) {
|
| return HostGlobals::Get()->GetInstance(instance_id);
|
| }
|
| @@ -3181,7 +3211,8 @@ int PepperPluginInstanceImpl::MakePendingFileRefRendererHost(
|
| }
|
|
|
| void PepperPluginInstanceImpl::SetEmbedProperty(PP_Var key, PP_Var value) {
|
| - message_channel_->SetReadOnlyProperty(key, value);
|
| + if (message_channel_)
|
| + message_channel_->SetReadOnlyProperty(key, value);
|
| }
|
|
|
| bool PepperPluginInstanceImpl::CanAccessMainFrame() const {
|
|
|