Index: components/plugins/renderer/plugin_placeholder.cc |
diff --git a/components/plugins/renderer/plugin_placeholder.cc b/components/plugins/renderer/plugin_placeholder.cc |
index aa82135446bb68a8b2c8b0a2faf53188aa3249aa..d82117e419b3d1b26028b40de9ba48ee675255bc 100644 |
--- a/components/plugins/renderer/plugin_placeholder.cc |
+++ b/components/plugins/renderer/plugin_placeholder.cc |
@@ -34,11 +34,52 @@ using blink::WebPluginContainer; |
using blink::WebPluginParams; |
using blink::WebScriptSource; |
using blink::WebURLRequest; |
-using webkit_glue::CppArgumentList; |
-using webkit_glue::CppVariant; |
namespace plugins { |
+namespace { |
+ |
+// This class is supposed to be stored in an v8::External. It holds a |
+// base::Closure and will delete itself as soon as the v8::External is garbage |
+// collected. |
+class V8ClosureWrapper { |
+ public: |
+ explicit V8ClosureWrapper(const base::Closure& closure) : closure_(closure) {} |
+ |
+ void SetExternal(v8::Isolate* isolate, v8::Handle<v8::External> external) { |
+ DCHECK(external_.IsEmpty()); |
+ external_.Reset(isolate, external); |
+ external_.SetWeak(this, &V8ClosureWrapper::WeakCallback); |
+ } |
+ |
+ void Run() { |
+ closure_.Run(); |
+ } |
+ |
+ private: |
+ static void WeakCallback( |
+ const v8::WeakCallbackData<v8::External, V8ClosureWrapper>& data) { |
+ V8ClosureWrapper* info = data.GetParameter(); |
+ info->external_.Reset(); |
+ delete info; |
+ } |
+ |
+ ~V8ClosureWrapper() {} |
+ |
+ base::Closure closure_; |
+ v8::Persistent<v8::External> external_; |
+ |
+ DISALLOW_COPY_AND_ASSIGN(V8ClosureWrapper); |
+}; |
+ |
+void RunV8ClosureWrapper(const v8::FunctionCallbackInfo<v8::Value>& args) { |
+ V8ClosureWrapper* wrapper = reinterpret_cast<V8ClosureWrapper*>( |
+ v8::External::Cast(*args.Data())->Value()); |
+ wrapper->Run(); |
+} |
+ |
+} // namespace |
+ |
PluginPlaceholder::PluginPlaceholder(content::RenderView* render_view, |
WebFrame* frame, |
const WebPluginParams& params, |
@@ -54,21 +95,56 @@ PluginPlaceholder::PluginPlaceholder(content::RenderView* render_view, |
is_blocked_for_prerendering_(false), |
allow_loading_(false), |
hidden_(false), |
- finished_loading_(false) {} |
+ finished_loading_(false), |
+ weak_factory_(this) { |
+ RegisterCallback( |
+ "load", |
+ base::Bind(&PluginPlaceholder::LoadCallback, weak_factory_.GetWeakPtr())); |
+ RegisterCallback( |
+ "hide", |
+ base::Bind(&PluginPlaceholder::HideCallback, weak_factory_.GetWeakPtr())); |
+ RegisterCallback("didFinishLoading", |
+ base::Bind(&PluginPlaceholder::DidFinishLoadingCallback, |
+ weak_factory_.GetWeakPtr())); |
+} |
PluginPlaceholder::~PluginPlaceholder() {} |
+void PluginPlaceholder::RegisterCallback(const std::string& callback_name, |
+ const base::Closure& callback) { |
+ DCHECK(callbacks_.find(callback_name) == callbacks_.end()); |
+ callbacks_[callback_name] = callback; |
+} |
+ |
void PluginPlaceholder::BindWebFrame(WebFrame* frame) { |
- BindToJavascript(frame, "plugin"); |
- BindCallback( |
- "load", |
- base::Bind(&PluginPlaceholder::LoadCallback, base::Unretained(this))); |
- BindCallback( |
- "hide", |
- base::Bind(&PluginPlaceholder::HideCallback, base::Unretained(this))); |
- BindCallback("didFinishLoading", |
- base::Bind(&PluginPlaceholder::DidFinishLoadingCallback, |
- base::Unretained(this))); |
+ v8::Isolate* isolate = v8::Isolate::GetCurrent(); |
+ v8::HandleScope handle_scope(isolate); |
+ v8::Handle<v8::Context> context = frame->mainWorldScriptContext(); |
+ |
+ if (context.IsEmpty()) |
+ return; |
+ |
+ v8::Context::Scope context_scope(context); |
+ |
+ v8::Handle<v8::FunctionTemplate> plugin_template = |
+ v8::FunctionTemplate::New(); |
+ v8::Handle<v8::Template> prototype = plugin_template->PrototypeTemplate(); |
+ |
+ for (std::map<std::string, base::Closure>::const_iterator callback = |
+ callbacks_.begin(); |
+ callback != callbacks_.end(); |
+ ++callback) { |
+ V8ClosureWrapper* wrapper = new V8ClosureWrapper(callback->second); |
+ v8::Handle<v8::External> wrapper_holder = v8::External::New(wrapper); |
+ wrapper->SetExternal(isolate, wrapper_holder); |
+ prototype->Set( |
+ v8::String::New(callback->first.c_str()), |
+ v8::FunctionTemplate::New(RunV8ClosureWrapper, wrapper_holder)); |
+ } |
+ |
+ v8::Handle<v8::Object> global = context->Global(); |
+ global->Set(v8::String::New("plugin"), |
+ plugin_template->GetFunction()->NewInstance()); |
} |
void PluginPlaceholder::ReplacePlugin(WebPlugin* new_plugin) { |
@@ -206,20 +282,17 @@ void PluginPlaceholder::LoadPlugin() { |
ReplacePlugin(plugin); |
} |
-void PluginPlaceholder::LoadCallback(const CppArgumentList& args, |
- CppVariant* result) { |
+void PluginPlaceholder::LoadCallback() { |
RenderThread::Get()->RecordUserMetrics("Plugin_Load_Click"); |
LoadPlugin(); |
} |
-void PluginPlaceholder::HideCallback(const CppArgumentList& args, |
- CppVariant* result) { |
+void PluginPlaceholder::HideCallback() { |
RenderThread::Get()->RecordUserMetrics("Plugin_Hide_Click"); |
HidePlugin(); |
} |
-void PluginPlaceholder::DidFinishLoadingCallback(const CppArgumentList& args, |
- CppVariant* result) { |
+void PluginPlaceholder::DidFinishLoadingCallback() { |
finished_loading_ = true; |
if (message_.length() > 0) |
UpdateMessage(); |