Index: content/renderer/browser_plugin/browser_plugin.cc |
diff --git a/content/renderer/browser_plugin/browser_plugin.cc b/content/renderer/browser_plugin/browser_plugin.cc |
index f6234bf1c6459f047d64d428c29b9228cfc99165..f0c30636e1b7786bc8ab72f1e4296a103bb2967f 100644 |
--- a/content/renderer/browser_plugin/browser_plugin.cc |
+++ b/content/renderer/browser_plugin/browser_plugin.cc |
@@ -18,8 +18,10 @@ |
#include "content/renderer/browser_plugin/browser_plugin_manager.h" |
#include "content/renderer/render_process_impl.h" |
#include "content/renderer/render_thread_impl.h" |
+#include "content/renderer/v8_value_converter_impl.h" |
#include "skia/ext/platform_canvas.h" |
#include "third_party/WebKit/Source/WebKit/chromium/public/WebBindings.h" |
+#include "third_party/WebKit/Source/WebKit/chromium/public/WebDOMCustomEvent.h" |
#include "third_party/WebKit/Source/WebKit/chromium/public/WebDocument.h" |
#include "third_party/WebKit/Source/WebKit/chromium/public/WebElement.h" |
#include "third_party/WebKit/Source/WebKit/chromium/public/WebFrame.h" |
@@ -27,6 +29,7 @@ |
#include "third_party/WebKit/Source/WebKit/chromium/public/WebPluginContainer.h" |
#include "third_party/WebKit/Source/WebKit/chromium/public/WebPluginParams.h" |
#include "third_party/WebKit/Source/WebKit/chromium/public/platform/WebRect.h" |
+#include "third_party/WebKit/Source/WebKit/chromium/public/WebScriptSource.h" |
#include "webkit/plugins/sad_plugin.h" |
using WebKit::WebCanvas; |
@@ -55,7 +58,7 @@ const char kPartitionAttribute[] = "partition"; |
const char kPersistPrefix[] = "persist:"; |
const char kProcessId[] = "processId"; |
const char kSrcAttribute[] = "src"; |
-const char kType[] = "type"; |
+const char kReason[] = "reason"; |
const char kURL[] = "url"; |
static std::string TerminationStatusToString(base::TerminationStatus status) { |
@@ -74,8 +77,14 @@ static std::string TerminationStatusToString(base::TerminationStatus status) { |
return "unknown"; |
} |
} |
+ |
+v8::Handle<v8::Value> EventAttrGetter(v8::Local<v8::String> name, |
+ const v8::AccessorInfo& info) { |
+ return info.Data(); |
} |
+} // namespace |
+ |
BrowserPlugin::BrowserPlugin( |
int instance_id, |
RenderViewImpl* render_view, |
@@ -105,15 +114,12 @@ BrowserPlugin::BrowserPlugin( |
BrowserPluginManager::Get()->AddBrowserPlugin(instance_id, this); |
bindings_.reset(new BrowserPluginBindings(this)); |
- InitializeEvents(); |
- |
ParseAttributes(params); |
} |
BrowserPlugin::~BrowserPlugin() { |
if (damage_buffer_) |
FreeDamageBuffer(); |
- RemoveEventListeners(); |
BrowserPluginManager::Get()->RemoveBrowserPlugin(instance_id_); |
BrowserPluginManager::Get()->Send( |
new BrowserPluginHostMsg_PluginDestroyed( |
@@ -313,66 +319,35 @@ float BrowserPlugin::GetDeviceScaleFactor() const { |
return render_view_->GetWebView()->deviceScaleFactor(); |
} |
-void BrowserPlugin::InitializeEvents() { |
- event_listener_map_[kExitEventName] = EventListeners(); |
- event_listener_map_[kLoadAbortEventName] = EventListeners(); |
- event_listener_map_[kLoadCommitEventName] = EventListeners(); |
- event_listener_map_[kLoadRedirectEventName] = EventListeners(); |
- event_listener_map_[kLoadStartEventName] = EventListeners(); |
- event_listener_map_[kLoadStopEventName] = EventListeners(); |
-} |
- |
-void BrowserPlugin::RemoveEventListeners() { |
- EventListenerMap::iterator event_listener_map_iter = |
- event_listener_map_.begin(); |
- for (; event_listener_map_iter != event_listener_map_.end(); |
- ++event_listener_map_iter) { |
- EventListeners& listeners = |
- event_listener_map_[event_listener_map_iter->first]; |
- EventListeners::iterator it = listeners.begin(); |
- for (; it != listeners.end(); ++it) { |
- it->Dispose(); |
- } |
- } |
- event_listener_map_.clear(); |
-} |
- |
-bool BrowserPlugin::IsValidEvent(const std::string& event_name) { |
- return event_listener_map_.find(event_name) != event_listener_map_.end(); |
-} |
- |
void BrowserPlugin::TriggerEvent(const std::string& event_name, |
- v8::Local<v8::Object>* event) { |
- WebKit::WebElement plugin = container()->element(); |
- |
- const EventListeners& listeners = event_listener_map_[event_name.c_str()]; |
- // A v8::Local copy of the listeners is created from the v8::Persistent |
- // listeners before firing them. This is to ensure that if one of these |
- // listeners mutate the list of listeners (by calling |
- // addEventListener/removeEventListener), this local copy is not affected. |
- // This means if you mutate the list of listeners for an event X while event X |
- // is firing, the mutation is deferred until all current listeners for X have |
- // fired. |
- EventListenersLocal listeners_local; |
- listeners_local.reserve(listeners.size()); |
- for (EventListeners::const_iterator it = listeners.begin(); |
- it != listeners.end(); |
- ++it) { |
- listeners_local.push_back(v8::Local<v8::Function>::New(*it)); |
+ std::map<std::string, base::Value*>* props) { |
+ WebKit::WebFrame* frame = container()->element().document().frame(); |
+ v8::HandleScope handle_scope; |
+ v8::Local<v8::Context> context = frame->mainWorldScriptContext(); |
+ v8::Context::Scope context_scope(context); |
+ |
+ WebKit::WebDOMEvent dom_event = frame->document().createEvent("Event"); |
+ WebKit::WebDOMCustomEvent event = dom_event.to<WebKit::WebDOMCustomEvent>(); |
sadrul
2012/11/07 03:37:06
Ignore, for the moment, the fact that this is stil
|
+ event.initCustomEvent( |
+ WebKit::WebString::fromUTF8(event_name.c_str()), |
+ false, false); |
+ |
+ v8::Handle<v8::Value> v8event = event.toV8Value(); |
+ if (v8event->IsObject() && props) { |
+ V8ValueConverterImpl converter; |
+ v8::Handle<v8::Object> object = v8event->ToObject(); |
+ for (std::map<std::string, base::Value*>::iterator iter = props->begin(), |
+ end = props->end(); iter != end; ++iter) { |
+ object->SetAccessor(v8::String::NewSymbol(iter->first.data()), |
+ EventAttrGetter, 0, |
+ converter.ToV8Value(iter->second, context), |
+ v8::ALL_CAN_READ, |
+ static_cast<v8::PropertyAttribute>(v8::DontDelete | v8::ReadOnly)); |
+ } |
+ STLDeleteValues(props); |
} |
- (*event)->Set(v8::String::New("name"), |
- v8::String::New(event_name.c_str(), event_name.size()), |
- v8::ReadOnly); |
- v8::Local<v8::Value> argv[] = { *event }; |
- for (EventListenersLocal::const_iterator it = listeners_local.begin(); |
- it != listeners_local.end(); |
- ++it) { |
- WebKit::WebFrame* frame = plugin.document().frame(); |
- if (!frame) |
- break; |
- frame->callFunctionEvenIfScriptDisabled(*it, v8::Object::New(), 1, argv); |
- } |
+ container()->element().dispatchEvent(dom_event); |
} |
void BrowserPlugin::Back() { |
@@ -475,28 +450,17 @@ void BrowserPlugin::UpdateRect( |
void BrowserPlugin::GuestGone(int process_id, base::TerminationStatus status) { |
// We fire the event listeners before painting the sad graphic to give the |
// developer an opportunity to display an alternative overlay image on crash. |
- if (HasListeners(kExitEventName)) { |
- WebKit::WebElement plugin = container()->element(); |
- v8::HandleScope handle_scope; |
- v8::Context::Scope context_scope( |
- plugin.document().frame()->mainWorldScriptContext()); |
- |
- // Construct the exit event object. |
- v8::Local<v8::Object> event = v8::Object::New(); |
- event->Set(v8::String::New(kProcessId, sizeof(kProcessId) - 1), |
- v8::Integer::New(process_id), |
- v8::ReadOnly); |
- std::string termination_status = TerminationStatusToString(status); |
- event->Set(v8::String::New(kType, sizeof(kType) - 1), |
- v8::String::New(termination_status.data(), |
- termination_status.size()), |
- v8::ReadOnly); |
- // Event listeners may remove the BrowserPlugin from the document. If that |
- // happens, the BrowserPlugin will be scheduled for later deletion (see |
- // BrowserPlugin::destroy()). That will clear the container_ reference, |
- // but leave other member variables valid below. |
- TriggerEvent(kExitEventName, &event); |
- } |
+ std::string termination_status = TerminationStatusToString(status); |
+ std::map<std::string, base::Value*> props; |
+ props[kProcessId] = base::Value::CreateIntegerValue(process_id); |
+ props[kReason] = base::Value::CreateStringValue(termination_status); |
+ |
+ // Event listeners may remove the BrowserPlugin from the document. If that |
+ // happens, the BrowserPlugin will be scheduled for later deletion (see |
+ // BrowserPlugin::destroy()). That will clear the container_ reference, |
+ // but leave other member variables valid below. |
+ TriggerEvent(kExitEventName, &props); |
+ |
guest_crashed_ = true; |
// We won't paint the contents of the current backing store again so we might |
// as well toss it out and save memory. |
@@ -508,23 +472,11 @@ void BrowserPlugin::GuestGone(int process_id, base::TerminationStatus status) { |
} |
void BrowserPlugin::LoadStart(const GURL& url, bool is_top_level) { |
- if (!HasListeners(kLoadStartEventName)) |
- return; |
+ std::map<std::string, base::Value*> props; |
+ props[kURL] = base::Value::CreateStringValue(url.spec()); |
+ props[kIsTopLevel] = base::Value::CreateBooleanValue(is_top_level); |
- WebKit::WebElement plugin = container()->element(); |
- v8::HandleScope handle_scope; |
- v8::Context::Scope context_scope( |
- plugin.document().frame()->mainWorldScriptContext()); |
- |
- // Construct the loadStart event object. |
- v8::Local<v8::Object> event = v8::Object::New(); |
- event->Set(v8::String::New(kURL, sizeof(kURL) - 1), |
- v8::String::New(url.spec().data(), url.spec().size()), |
- v8::ReadOnly); |
- event->Set(v8::String::New(kIsTopLevel, sizeof(kIsTopLevel) - 1), |
- v8::Boolean::New(is_top_level), |
- v8::ReadOnly); |
- TriggerEvent(kLoadStartEventName, &event); |
+ TriggerEvent(kLoadStartEventName, &props); |
} |
void BrowserPlugin::LoadCommit( |
@@ -537,90 +489,35 @@ void BrowserPlugin::LoadCommit( |
current_nav_entry_index_ = params.current_entry_index; |
nav_entry_count_ = params.entry_count; |
- if (!HasListeners(kLoadCommitEventName)) |
- return; |
- |
- WebKit::WebElement plugin = container()->element(); |
- v8::HandleScope handle_scope; |
- v8::Context::Scope context_scope( |
- plugin.document().frame()->mainWorldScriptContext()); |
- |
- // Construct the loadCommit event object. |
- v8::Local<v8::Object> event = v8::Object::New(); |
- event->Set(v8::String::New(kURL, sizeof(kURL) - 1), |
- v8::String::New(src_.data(), src_.size()), |
- v8::ReadOnly); |
- event->Set(v8::String::New(kIsTopLevel, sizeof(kIsTopLevel) - 1), |
- v8::Boolean::New(params.is_top_level), |
- v8::ReadOnly); |
- |
- TriggerEvent(kLoadCommitEventName, &event); |
+ std::map<std::string, base::Value*> props; |
+ props[kURL] = base::Value::CreateStringValue(src_); |
+ props[kIsTopLevel] = base::Value::CreateBooleanValue(params.is_top_level); |
+ TriggerEvent(kLoadCommitEventName, &props); |
} |
void BrowserPlugin::LoadStop() { |
- if (!HasListeners(kLoadStopEventName)) |
- return; |
- |
- WebKit::WebElement plugin = container()->element(); |
- v8::HandleScope handle_scope; |
- v8::Context::Scope context_scope( |
- plugin.document().frame()->mainWorldScriptContext()); |
- |
// Construct the loadStop event object. |
- v8::Local<v8::Object> event = v8::Object::New(); |
- TriggerEvent(kLoadStopEventName, &event); |
+ TriggerEvent(kLoadStopEventName, NULL); |
} |
void BrowserPlugin::LoadAbort(const GURL& url, |
bool is_top_level, |
const std::string& type) { |
- if (!HasListeners(kLoadAbortEventName)) |
- return; |
- |
- WebKit::WebElement plugin = container()->element(); |
- v8::HandleScope handle_scope; |
- v8::Context::Scope context_scope( |
- plugin.document().frame()->mainWorldScriptContext()); |
- |
- // Construct the loadAbort event object. |
- v8::Local<v8::Object> event = v8::Object::New(); |
- event->Set(v8::String::New(kURL, sizeof(kURL) - 1), |
- v8::String::New(url.spec().data(), url.spec().size()), |
- v8::ReadOnly); |
- event->Set(v8::String::New(kIsTopLevel, sizeof(kIsTopLevel) - 1), |
- v8::Boolean::New(is_top_level), |
- v8::ReadOnly); |
- event->Set(v8::String::New(kType, sizeof(kType) - 1), |
- v8::String::New(type.data(), type.size()), |
- v8::ReadOnly); |
- |
- TriggerEvent(kLoadAbortEventName, &event); |
+ std::map<std::string, base::Value*> props; |
+ props[kURL] = base::Value::CreateStringValue(url.spec()); |
+ props[kIsTopLevel] = base::Value::CreateBooleanValue(is_top_level); |
+ props[kReason] = base::Value::CreateStringValue(type); |
+ TriggerEvent(kLoadAbortEventName, &props); |
} |
void BrowserPlugin::LoadRedirect(const GURL& old_url, |
const GURL& new_url, |
bool is_top_level) { |
- if (!HasListeners(kLoadRedirectEventName)) |
- return; |
- |
- WebKit::WebElement plugin = container()->element(); |
- v8::HandleScope handle_scope; |
- v8::Context::Scope context_scope( |
- plugin.document().frame()->mainWorldScriptContext()); |
- |
- // Construct the loadRedirect event object. |
- v8::Local<v8::Object> event = v8::Object::New(); |
- event->Set(v8::String::New(kOldURL, sizeof(kOldURL) - 1), |
- v8::String::New(old_url.spec().data(), old_url.spec().size()), |
- v8::ReadOnly); |
- event->Set(v8::String::New(kNewURL, sizeof(kNewURL) - 1), |
- v8::String::New(new_url.spec().data(), new_url.spec().size()), |
- v8::ReadOnly); |
- event->Set(v8::String::New(kIsTopLevel, sizeof(kIsTopLevel) - 1), |
- v8::Boolean::New(is_top_level), |
- v8::ReadOnly); |
- |
- TriggerEvent(kLoadRedirectEventName, &event); |
+ std::map<std::string, base::Value*> props; |
+ props[kOldURL] = base::Value::CreateStringValue(old_url.spec()); |
+ props[kNewURL] = base::Value::CreateStringValue(new_url.spec()); |
+ props[kIsTopLevel] = base::Value::CreateBooleanValue(is_top_level); |
+ TriggerEvent(kLoadRedirectEventName, &props); |
} |
void BrowserPlugin::AdvanceFocus(bool reverse) { |
@@ -639,43 +536,6 @@ void BrowserPlugin::SetAcceptTouchEvents(bool accept) { |
container()->setIsAcceptingTouchEvents(accept); |
} |
-bool BrowserPlugin::HasListeners(const std::string& event_name) { |
- return IsValidEvent(event_name) && |
- !event_listener_map_[event_name].empty(); |
-} |
- |
-bool BrowserPlugin::AddEventListener(const std::string& event_name, |
- v8::Local<v8::Function> function) { |
- if (!IsValidEvent(event_name)) |
- return false; |
- EventListeners& listeners = event_listener_map_[event_name]; |
- for (unsigned int i = 0; i < listeners.size(); ++i) { |
- if (listeners[i] == function) |
- return false; |
- } |
- v8::Persistent<v8::Function> persistent_function = |
- v8::Persistent<v8::Function>::New(function); |
- listeners.push_back(persistent_function); |
- return true; |
-} |
- |
-bool BrowserPlugin::RemoveEventListener(const std::string& event_name, |
- v8::Local<v8::Function> function) { |
- if (!HasListeners(event_name)) |
- return false; |
- |
- EventListeners& listeners = event_listener_map_[event_name]; |
- EventListeners::iterator it = listeners.begin(); |
- for (; it != listeners.end(); ++it) { |
- if (*it == function) { |
- it->Dispose(); |
- listeners.erase(it); |
- return true; |
- } |
- } |
- return false; |
-} |
- |
WebKit::WebPluginContainer* BrowserPlugin::container() const { |
return container_; |
} |