Chromium Code Reviews| 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; |