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..6368f1298c07f6768e0046633274b30ab06ed6c1 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: |
+ V8ClosureWrapper(const base::Closure& closure) : closure_(closure) {} |
Bernhard Bauer
2013/11/14 16:25:43
Nit: add `explicit` to constructor
jochen (gone - plz use gerrit)
2013/11/15 10:09:39
Done.
|
+ |
+ 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,71 @@ 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"); |
+ RegisterCallback("hide"); |
+ RegisterCallback("didFinishLoading"); |
+} |
PluginPlaceholder::~PluginPlaceholder() {} |
+void PluginPlaceholder::RegisterCallback(const std::string& callback) { |
+ DCHECK(callbacks_.end() == |
+ std::find(callbacks_.begin(), callbacks_.end(), callback)); |
+ callbacks_.push_back(callback); |
+} |
+ |
+void PluginPlaceholder::Observe(const std::string& callback) { |
+} |
+ |
+void PluginPlaceholder::InternalObserve(const std::string& callback) { |
+ if (callback == "load") { |
+ RenderThread::Get()->RecordUserMetrics("Plugin_Load_Click"); |
+ LoadPlugin(); |
+ } else if (callback == "hide") { |
+ RenderThread::Get()->RecordUserMetrics("Plugin_Hide_Click"); |
+ HidePlugin(); |
+ } else if (callback == "didFinishLoading") { |
+ finished_loading_ = true; |
+ if (message_.length() > 0) |
+ UpdateMessage(); |
+ } else { |
+ Observe(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::vector<std::string>::const_iterator callback = callbacks_.begin(); |
+ callback != callbacks_.end(); |
+ ++callback) { |
+ V8ClosureWrapper* wrapper = |
+ new V8ClosureWrapper(base::Bind(&PluginPlaceholder::InternalObserve, |
Bernhard Bauer
2013/11/14 16:25:43
Out of curiosity, why do you do this instead of ha
jochen (gone - plz use gerrit)
2013/11/15 10:09:39
It strikes me as a safer to use API
Bernhard Bauer
2013/11/15 10:24:03
Why is that? It means that the subclass has to fin
|
+ weak_factory_.GetWeakPtr(), |
+ *callback)); |
+ v8::Handle<v8::External> wrapper_holder = v8::External::New(wrapper); |
+ wrapper->SetExternal(isolate, wrapper_holder); |
+ prototype->Set( |
+ v8::String::New(callback->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,25 +297,6 @@ void PluginPlaceholder::LoadPlugin() { |
ReplacePlugin(plugin); |
} |
-void PluginPlaceholder::LoadCallback(const CppArgumentList& args, |
- CppVariant* result) { |
- RenderThread::Get()->RecordUserMetrics("Plugin_Load_Click"); |
- LoadPlugin(); |
-} |
- |
-void PluginPlaceholder::HideCallback(const CppArgumentList& args, |
- CppVariant* result) { |
- RenderThread::Get()->RecordUserMetrics("Plugin_Hide_Click"); |
- HidePlugin(); |
-} |
- |
-void PluginPlaceholder::DidFinishLoadingCallback(const CppArgumentList& args, |
- CppVariant* result) { |
- finished_loading_ = true; |
- if (message_.length() > 0) |
- UpdateMessage(); |
-} |
- |
void PluginPlaceholder::SetPluginInfo( |
const content::WebPluginInfo& plugin_info) { |
plugin_info_ = plugin_info; |