Chromium Code Reviews| 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 0dbc53fe80a50dc306b41a135f9f866d77bab3ff..73a6a828e1153b590cc210511f7b753434bbd5ee 100644 |
| --- a/content/renderer/browser_plugin/browser_plugin.cc |
| +++ b/content/renderer/browser_plugin/browser_plugin.cc |
| @@ -134,6 +134,8 @@ bool BrowserPlugin::OnMessageReceived(const IPC::Message& message) { |
| OnShouldAcceptTouchEvents) |
| IPC_MESSAGE_HANDLER(BrowserPluginMsg_UpdatedName, OnUpdatedName) |
| IPC_MESSAGE_HANDLER(BrowserPluginMsg_UpdateRect, OnUpdateRect) |
| + IPC_MESSAGE_HANDLER(BrowserPluginMsg_RequestMediaAccess, |
| + OnRequestMediaAccess) |
| IPC_MESSAGE_UNHANDLED(handled = false) |
| IPC_END_MESSAGE_MAP() |
| return handled; |
| @@ -535,6 +537,43 @@ void BrowserPlugin::OnUpdatedName(int instance_id, const std::string& name) { |
| UpdateDOMAttribute(browser_plugin::kAttributeName, name); |
| } |
| +void BrowserPlugin::OnRequestMediaAccess(int instance_id, |
| + int request_id, |
| + const GURL& security_origin) { |
| + if (!HasEventListeners(browser_plugin::kEventRequestPermission)) { |
| + // Automatically deny the request if there are no event listeners for |
| + // permissionrequest. |
| + RespondMediaAccess(request_id, false /* allow */); |
| + return; |
| + } |
| + DCHECK(!media_access_pending_request_ids_.count(request_id)); |
| + media_access_pending_request_ids_.insert(request_id); |
| + |
| + std::map<std::string, base::Value*> props; |
| + props[browser_plugin::kPermission] = |
| + base::Value::CreateStringValue(browser_plugin::kPermissionTypeMedia); |
| + props[browser_plugin::kRequestId] = |
| + base::Value::CreateIntegerValue(request_id); |
| + props[browser_plugin::kURL] = |
| + base::Value::CreateStringValue(security_origin.spec()); |
| + TriggerEvent(browser_plugin::kEventRequestPermission, &props); |
| +} |
| + |
| +bool BrowserPlugin::HasEventListeners(const std::string& event_name) { |
| + if (!container()) |
| + return false; |
| + |
| + // TODO(lazyboy): Fix before submitting: use ancestor list instead similar to |
| + // window.open CL, so bubbling is supported. |
| + WebKit::WebNode parent = container()->element().parentNode(); |
| + if (!parent.isNull() && !parent.shadowHost().isNull()) { |
| + WebKit::WebElement shadow_host = parent.shadowHost(); |
| + return shadow_host.hasEventListeners( |
| + WebKit::WebString::fromUTF8(event_name)); |
| + } |
| + return false; |
| +} |
| + |
| void BrowserPlugin::OnUpdateRect( |
| int instance_id, |
| const BrowserPluginMsg_UpdateRect_Params& params) { |
| @@ -782,6 +821,51 @@ void BrowserPlugin::TriggerEvent(const std::string& event_name, |
| container()->element().dispatchEvent(event); |
| } |
| +void BrowserPlugin::OnMediaRequestGarbageCollected(int request_id) { |
| + // Remove from alive objects. |
| + std::map<int, MediaAccessAliveV8RequestItem*>::iterator iter = |
| + media_access_alive_v8_request_objects_.find(request_id); |
| + if (iter != media_access_alive_v8_request_objects_.end()) { |
| + MediaAccessAliveV8RequestItem* item = iter->second; |
| + DCHECK(*item->first == request_id); |
| + media_access_alive_v8_request_objects_.erase(iter); |
| + delete item->first; |
| + } |
| + |
| + // If a decision has not been made for this request yet, deny it. |
| + RespondMediaAccessIfPending(request_id, false /* allow */); |
| +} |
| + |
| +void BrowserPlugin::PersistRequestObject(const NPVariant* request, int id) { |
|
Fady Samuel
2013/02/07 15:40:34
Can we make this more general to allow for window.
lazyboy
2013/02/07 21:24:41
We need a centralized id generation in that case,
|
| + v8::Persistent<v8::Value> weak_request = |
| + v8::Persistent<v8::Value>::New(WebKit::WebBindings::toV8Value(request)); |
| + int *new_request_id = new int(id); |
|
Fady Samuel
2013/02/07 15:40:34
why are you allocating memory on the heap here? We
lazyboy
2013/02/07 21:24:41
I thought reference to map element is not guarante
|
| + std::pair<int*, BrowserPlugin*>* req = |
| + new std::pair<int*, BrowserPlugin*>( |
| + std::make_pair(new_request_id, this)); |
| + DCHECK(media_access_alive_v8_request_objects_.find(id) == |
| + media_access_alive_v8_request_objects_.end()); |
| + if (media_access_alive_v8_request_objects_.find(id) == |
| + media_access_alive_v8_request_objects_.end()) { |
| + media_access_alive_v8_request_objects_[*new_request_id] = req; |
| + weak_request.MakeWeak(req, WeakCallbackForPersistObject); |
| + } |
| +} |
| + |
| +void BrowserPlugin::WeakCallbackForPersistObject( |
| + v8::Persistent<v8::Value> object, void* param) { |
| + v8::Persistent<v8::Object> persistent_object = |
| + v8::Persistent<v8::Object>::Cast(object); |
| + |
| + MediaAccessAliveV8RequestItem* item_ptr = |
| + static_cast<std::pair<int*, BrowserPlugin*>*>(param); |
|
Fady Samuel
2013/02/07 15:40:34
We're leaking memory here. Seem my suggestion abov
lazyboy
2013/02/07 21:24:41
See above, fixed hopefully.
|
| + int request_id = *(item_ptr->first); |
| + BrowserPlugin* plugin = item_ptr->second; |
| + plugin->OnMediaRequestGarbageCollected(request_id); |
| + |
| + persistent_object.Dispose(); |
| +} |
| + |
| void BrowserPlugin::Back() { |
| if (!navigate_src_sent_) |
| return; |
| @@ -852,6 +936,25 @@ WebKit::WebPluginContainer* BrowserPlugin::container() const { |
| return container_; |
| } |
| +void BrowserPlugin::RespondMediaAccess(int request_id, bool allow) { |
| + browser_plugin_manager()->Send( |
| + new BrowserPluginHostMsg_AllowMediaAccess( |
|
Fady Samuel
2013/02/07 15:40:34
Given the review overhead for introducing new IPCs
lazyboy
2013/02/07 21:24:41
This part should be straight forward.
Done.
|
| + render_view_->GetRoutingID(), instance_id_, request_id, allow)); |
| +} |
| + |
| +void BrowserPlugin::RespondMediaAccessIfPending(int request_id, bool allow) { |
| + MediaAccessPendingRequestIds::iterator iter = |
| + media_access_pending_request_ids_.find(request_id); |
| + if (iter == media_access_pending_request_ids_.end()) |
| + return; |
| + media_access_pending_request_ids_.erase(iter); |
| + RespondMediaAccess(request_id, allow); |
| +} |
| + |
| +void BrowserPlugin::OnListenerCallMediaAccess(int request_id, bool allow) { |
| + RespondMediaAccessIfPending(request_id, allow); |
| +} |
| + |
| bool BrowserPlugin::initialize(WebPluginContainer* container) { |
| container_ = container; |
| container_->setWantsWheelEvents(true); |