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 adde725e61b83c614b638541935b9a737c56661b..6fb2b9ecde01e57e35b7f8cf5cffe544e3775be2 100644 |
| --- a/content/renderer/browser_plugin/browser_plugin.cc |
| +++ b/content/renderer/browser_plugin/browser_plugin.cc |
| @@ -42,7 +42,10 @@ using WebKit::WebVector; |
| namespace content { |
| namespace { |
| +const char kAllowMediaAccessCallbackName[] = "allow"; |
| const char kCrashEventName[] = "crash"; |
| +const char kDenyMediaAccessCallbackName[] = "deny"; |
| +const char kInstanceIdKey[] = "instance_id"; |
| const char kIsTopLevel[] = "isTopLevel"; |
| const char kLoadAbortEventName[] = "loadAbort"; |
| const char kLoadRedirectEventName[] = "loadRedirect"; |
| @@ -52,9 +55,43 @@ const char kNewURL[] = "newUrl"; |
| const char kOldURL[] = "oldUrl"; |
| const char kPartitionAttribute[] = "partition"; |
| const char kPersistPrefix[] = "persist:"; |
| +const char kPermissionRequestEventName[] = "permissionRequest"; |
| +const char kPermissionTypeMedia[] = "media"; |
| +const char kRequestIdKey[] = "request_id"; |
| const char kSrcAttribute[] = "src"; |
| const char kType[] = "type"; |
| const char kURL[] = "url"; |
| + |
| +void SetMediaAccessPermission(bool allow, const v8::Arguments& args) { |
| + int instance_id = -1; |
| + int request_id = -1; |
| + v8::Local<v8::Value> instance_id_value = |
| + args.Callee()->GetHiddenValue(v8::String::New(kInstanceIdKey)); |
| + v8::Local<v8::Value> request_id_value = |
| + args.Callee()->GetHiddenValue(v8::String::New(kRequestIdKey)); |
| + if (instance_id_value->IsInt32()) |
| + instance_id = instance_id_value->ToInt32()->Value(); |
| + if (request_id_value->IsInt32()) |
| + request_id = request_id_value->ToInt32()->Value(); |
| + |
| + if (instance_id != -1 && request_id != -1) { |
|
Fady Samuel
2012/10/11 21:41:00
I feel like these should be DCHECKs rather than if
lazyboy
2012/10/11 23:05:07
Done.
|
| + BrowserPlugin* plugin = |
| + BrowserPluginManager::Get()->GetBrowserPlugin(instance_id); |
| + if (plugin) |
| + plugin->AllowMediaAccess(request_id, allow); |
| + } |
| +} |
| + |
| +v8::Handle<v8::Value> OnJsAllowMediaAccess(const v8::Arguments& args) { |
| + SetMediaAccessPermission(true /* allow */, args); |
| + return v8::Undefined(); |
| +} |
| + |
| +v8::Handle<v8::Value> OnJsDenyMediaAccess(const v8::Arguments& args) { |
| + SetMediaAccessPermission(false /* allow */, args); |
| + return v8::Undefined(); |
| +} |
| + |
| } |
| BrowserPlugin::BrowserPlugin( |
| @@ -477,6 +514,75 @@ void BrowserPlugin::SetAcceptTouchEvents(bool accept) { |
| container()->setIsAcceptingTouchEvents(accept); |
| } |
| +void BrowserPlugin::RequestMediaAccess(int request_id) { |
| + if (!HasListeners(kPermissionRequestEventName)) { |
| + // TODO(lazyboy): Automatically deny request when there is no listener. |
| + return; |
| + } |
| + EventListeners& listeners = event_listener_map_[kPermissionRequestEventName]; |
| + EventListeners::iterator it = listeners.begin(); |
| + |
| + WebKit::WebElement plugin = container()->element(); |
| + v8::HandleScope handle_scope; |
| + v8::Context::Scope context_scope( |
| + plugin.document().frame()->mainWorldScriptContext()); |
| + |
| + // Set callbacks. |
| + // We also save the |instance_id_| and |request_id| in these callbacks. This |
| + // is so that we know where to route the callback to when js calls the |
| + // callback. |
| + // |
| + // Javascript: |
| + // browser.addEventListener('permissionRequest', function(e) { |
| + // e.allow(); // Calls OnJsAllowMediaAccess(). |
| + // e.deny(); // Calls OnJsDenyMediaAccess(). |
| + // }); |
| + |
| + // Allow callback. |
| + v8::Local<v8::Function> allow_function = |
| + v8::FunctionTemplate::New(OnJsAllowMediaAccess)->GetFunction(); |
| + allow_function->SetHiddenValue(v8::String::New(kInstanceIdKey), |
| + v8::Int32::New(instance_id_)); |
| + allow_function->SetHiddenValue(v8::String::New(kRequestIdKey), |
| + v8::Int32::New(request_id)); |
| + // Deny callback. |
| + v8::Local<v8::Function> deny_function = |
| + v8::FunctionTemplate::New(OnJsDenyMediaAccess)->GetFunction(); |
| + deny_function->SetHiddenValue(v8::String::New(kInstanceIdKey), |
| + v8::Int32::New(instance_id_)); |
| + deny_function->SetHiddenValue(v8::String::New(kRequestIdKey), |
| + v8::Int32::New(request_id)); |
| + |
| + // Event object. |
| + v8::Local<v8::Value> event = |
| + v8::Local<v8::Object>::New(v8::Object::New()); |
| + // TODO(lazyboy): Also set permission details. Permission details would |
| + // include: whether the request was for audio(microphone)/video(webcam)/both. |
| + v8::Local<v8::Object>::Cast(event)->Set( |
| + v8::String::New(kType), v8::String::New(kPermissionTypeMedia)); |
| + v8::Local<v8::Object>::Cast(event)->Set( |
| + v8::String::New(kAllowMediaAccessCallbackName), allow_function); |
| + v8::Local<v8::Object>::Cast(event)->Set( |
| + v8::String::New(kDenyMediaAccessCallbackName), deny_function); |
| + |
| + for (; it != listeners.end(); ++it) { |
| + // Fire the event listener. |
| + container()->element().document().frame()-> |
| + callFunctionEvenIfScriptDisabled(*it, |
| + v8::Object::New(), |
| + 1, |
| + &event); |
| + } |
| +} |
| + |
| +void BrowserPlugin::AllowMediaAccess(int request_id, bool allow) { |
| + BrowserPluginManager::Get()->Send( |
| + new BrowserPluginHostMsg_AllowMediaAccess(render_view_->GetRoutingID(), |
| + instance_id_, |
| + request_id, |
| + allow)); |
| +} |
| + |
| bool BrowserPlugin::HasListeners(const std::string& event_name) { |
| return event_listener_map_.find(event_name) != event_listener_map_.end(); |
| } |