messaging_bindings.cc revision 010d83a9304c5a91596085d917d248abff47903a
1010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)// Copyright 2014 The Chromium Authors. All rights reserved. 25821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Use of this source code is governed by a BSD-style license that can be 35821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// found in the LICENSE file. 45821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 5010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)#include "extensions/renderer/messaging_bindings.h" 65821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 75821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include <map> 85821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include <string> 95821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "base/basictypes.h" 112a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)#include "base/bind.h" 12bbcdd45c55eb7c4641ab97aef9889b0fc828e7d3Ben Murdoch#include "base/bind_helpers.h" 135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "base/lazy_instance.h" 14bbcdd45c55eb7c4641ab97aef9889b0fc828e7d3Ben Murdoch#include "base/message_loop/message_loop.h" 15c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)#include "base/values.h" 165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "content/public/renderer/render_thread.h" 175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "content/public/renderer/render_view.h" 18c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)#include "content/public/renderer/v8_value_converter.h" 19effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch#include "extensions/common/api/messaging/message.h" 20a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)#include "extensions/common/extension_messages.h" 21010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)#include "extensions/common/manifest_handlers/externally_connectable.h" 22010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)#include "extensions/renderer/dispatcher.h" 23a02191e04bc25c4935f804f2c080ae28663d096dBen Murdoch#include "extensions/renderer/event_bindings.h" 240529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch#include "extensions/renderer/object_backed_native_handler.h" 25c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch#include "extensions/renderer/scoped_persistent.h" 260529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch#include "extensions/renderer/script_context.h" 270529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch#include "extensions/renderer/script_context_set.h" 287d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)#include "third_party/WebKit/public/web/WebScopedMicrotaskSuppression.h" 291e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)#include "third_party/WebKit/public/web/WebScopedUserGesture.h" 305d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)#include "third_party/WebKit/public/web/WebScopedWindowFocusAllowedIndicator.h" 311e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)#include "third_party/WebKit/public/web/WebUserGestureIndicator.h" 325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "v8/include/v8.h" 335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Message passing API example (in a content script): 355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// var extension = 365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// new chrome.Extension('00123456789abcdef0123456789abcdef0123456'); 372a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)// var port = runtime.connect(); 385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// port.postMessage('Can you hear me now?'); 395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// port.onmessage.addListener(function(msg, port) { 405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// alert('response=' + msg); 415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// port.postMessage('I got your reponse'); 425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// }); 435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)using content::RenderThread; 45c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)using content::V8ValueConverter; 465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 475d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)namespace extensions { 485d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) 495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)namespace { 505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)struct ExtensionData { 525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) struct PortData { 535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) int ref_count; // how many contexts have a handle to this port 545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) PortData() : ref_count(0) {} 555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) }; 565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) std::map<int, PortData> ports; // port ID -> data 575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}; 585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 59010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)base::LazyInstance<ExtensionData> g_extension_data = LAZY_INSTANCE_INITIALIZER; 605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 615d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)bool HasPortData(int port_id) { 625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return g_extension_data.Get().ports.find(port_id) != 63010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles) g_extension_data.Get().ports.end(); 645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 665d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)ExtensionData::PortData& GetPortData(int port_id) { 675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return g_extension_data.Get().ports[port_id]; 685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 705d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)void ClearPortData(int port_id) { 715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) g_extension_data.Get().ports.erase(port_id); 725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)const char kPortClosedError[] = "Attempting to use a disconnected port object"; 752a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)const char kReceivingEndDoesntExistError[] = 762a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) "Could not establish connection. Receiving end does not exist."; 775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 780529e5d033099cbfc42635f6f6183833b09dff6eBen Murdochclass ExtensionImpl : public ObjectBackedNativeHandler { 795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) public: 800529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch ExtensionImpl(Dispatcher* dispatcher, ScriptContext* context) 810529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch : ObjectBackedNativeHandler(context), dispatcher_(dispatcher) { 82010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles) RouteFunction( 83010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles) "CloseChannel", 842a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) base::Bind(&ExtensionImpl::CloseChannel, base::Unretained(this))); 85010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles) RouteFunction( 86010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles) "PortAddRef", 872a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) base::Bind(&ExtensionImpl::PortAddRef, base::Unretained(this))); 88010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles) RouteFunction( 89010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles) "PortRelease", 902a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) base::Bind(&ExtensionImpl::PortRelease, base::Unretained(this))); 91010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles) RouteFunction( 92010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles) "PostMessage", 932a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) base::Bind(&ExtensionImpl::PostMessage, base::Unretained(this))); 943551c9c881056c480085172ff9840cab31610854Torne (Richard Coles) // TODO(fsamuel, kalman): Move BindToGC out of messaging natives. 952a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) RouteFunction("BindToGC", 96010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles) base::Bind(&ExtensionImpl::BindToGC, base::Unretained(this))); 975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 992a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) virtual ~ExtensionImpl() {} 1005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1010529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch private: 1025d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) void ClearPortDataAndNotifyDispatcher(int port_id) { 1035d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) ClearPortData(port_id); 1040529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch dispatcher_->ClearPortData(port_id); 1055d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) } 1065d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) 1075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Sends a message along the given channel. 1087d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles) void PostMessage(const v8::FunctionCallbackInfo<v8::Value>& args) { 1090529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch content::RenderView* renderview = context()->GetRenderView(); 1105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (!renderview) 1117d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles) return; 1125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 113eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch // Arguments are (int32 port_id, string message). 114010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles) CHECK(args.Length() == 2 && args[0]->IsInt32() && args[1]->IsString()); 115868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) 116868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) int port_id = args[0]->Int32Value(); 117868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) if (!HasPortData(port_id)) { 118a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) args.GetIsolate()->ThrowException(v8::Exception::Error( 119a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) v8::String::NewFromUtf8(args.GetIsolate(), kPortClosedError))); 1207d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles) return; 1215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 122868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) 123868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) renderview->Send(new ExtensionHostMsg_PostMessage( 124010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles) renderview->GetRoutingID(), port_id, 125010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles) Message(*v8::String::Utf8Value(args[1]), 126010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles) blink::WebUserGestureIndicator::isProcessingUserGesture()))); 1275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 1285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Forcefully disconnects a port. 1307d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles) void CloseChannel(const v8::FunctionCallbackInfo<v8::Value>& args) { 131868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) // Arguments are (int32 port_id, boolean notify_browser). 132868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) CHECK_EQ(2, args.Length()); 133868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) CHECK(args[0]->IsInt32()); 134868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) CHECK(args[1]->IsBoolean()); 135868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) 136868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) int port_id = args[0]->Int32Value(); 137868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) if (!HasPortData(port_id)) 1387d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles) return; 139868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) 140868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) // Send via the RenderThread because the RenderView might be closing. 141868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) bool notify_browser = args[1]->BooleanValue(); 142868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) if (notify_browser) { 143868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) content::RenderThread::Get()->Send( 144868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) new ExtensionHostMsg_CloseChannel(port_id, std::string())); 1455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 146868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) 1475d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) ClearPortDataAndNotifyDispatcher(port_id); 1485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 1495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // A new port has been created for a context. This occurs both when script 1515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // opens a connection, and when a connection is opened to this script. 1527d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles) void PortAddRef(const v8::FunctionCallbackInfo<v8::Value>& args) { 153868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) // Arguments are (int32 port_id). 154868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) CHECK_EQ(1, args.Length()); 155868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) CHECK(args[0]->IsInt32()); 156868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) 157868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) int port_id = args[0]->Int32Value(); 158868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) ++GetPortData(port_id).ref_count; 1595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 1605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // The frame a port lived in has been destroyed. When there are no more 1625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // frames with a reference to a given port, we will disconnect it and notify 1635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // the other end of the channel. 1647d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles) void PortRelease(const v8::FunctionCallbackInfo<v8::Value>& args) { 165868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) // Arguments are (int32 port_id). 166868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) CHECK_EQ(1, args.Length()); 167868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) CHECK(args[0]->IsInt32()); 168868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) 169868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) int port_id = args[0]->Int32Value(); 170868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) if (HasPortData(port_id) && --GetPortData(port_id).ref_count == 0) { 171868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) // Send via the RenderThread because the RenderView might be closing. 172868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) content::RenderThread::Get()->Send( 173868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) new ExtensionHostMsg_CloseChannel(port_id, std::string())); 1745d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) ClearPortDataAndNotifyDispatcher(port_id); 1755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 1765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 1775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 178bbcdd45c55eb7c4641ab97aef9889b0fc828e7d3Ben Murdoch // Holds a |callback| to run sometime after |object| is GC'ed. |callback| will 179bbcdd45c55eb7c4641ab97aef9889b0fc828e7d3Ben Murdoch // not be executed re-entrantly to avoid running JS in an unexpected state. 180bbcdd45c55eb7c4641ab97aef9889b0fc828e7d3Ben Murdoch class GCCallback { 181bbcdd45c55eb7c4641ab97aef9889b0fc828e7d3Ben Murdoch public: 182bbcdd45c55eb7c4641ab97aef9889b0fc828e7d3Ben Murdoch static void Bind(v8::Handle<v8::Object> object, 18358537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles) v8::Handle<v8::Function> callback, 18458537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles) v8::Isolate* isolate) { 18558537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles) GCCallback* cb = new GCCallback(object, callback, isolate); 186a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) cb->object_.SetWeak(cb, NearDeathCallback); 187bbcdd45c55eb7c4641ab97aef9889b0fc828e7d3Ben Murdoch } 1882a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 1892a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) private: 190a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) static void NearDeathCallback( 191a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) const v8::WeakCallbackData<v8::Object, GCCallback>& data) { 192bbcdd45c55eb7c4641ab97aef9889b0fc828e7d3Ben Murdoch // v8 says we need to explicitly reset weak handles from their callbacks. 193bbcdd45c55eb7c4641ab97aef9889b0fc828e7d3Ben Murdoch // It's not implicit as one might expect. 194a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) data.GetParameter()->object_.reset(); 195a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) base::MessageLoop::current()->PostTask( 196a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) FROM_HERE, 197a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) base::Bind(&GCCallback::RunCallback, 198a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) base::Owned(data.GetParameter()))); 199bbcdd45c55eb7c4641ab97aef9889b0fc828e7d3Ben Murdoch } 2005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 20158537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles) GCCallback(v8::Handle<v8::Object> object, 20258537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles) v8::Handle<v8::Function> callback, 20358537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles) v8::Isolate* isolate) 20458537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles) : object_(object), callback_(callback), isolate_(isolate) {} 205bbcdd45c55eb7c4641ab97aef9889b0fc828e7d3Ben Murdoch 206bbcdd45c55eb7c4641ab97aef9889b0fc828e7d3Ben Murdoch void RunCallback() { 20758537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles) v8::HandleScope handle_scope(isolate_); 20858537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles) v8::Handle<v8::Function> callback = callback_.NewHandle(isolate_); 20958537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles) v8::Handle<v8::Context> context = callback->CreationContext(); 210bbcdd45c55eb7c4641ab97aef9889b0fc828e7d3Ben Murdoch if (context.IsEmpty()) 211bbcdd45c55eb7c4641ab97aef9889b0fc828e7d3Ben Murdoch return; 212bbcdd45c55eb7c4641ab97aef9889b0fc828e7d3Ben Murdoch v8::Context::Scope context_scope(context); 213f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) blink::WebScopedMicrotaskSuppression suppression; 21458537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles) callback->Call(context->Global(), 0, NULL); 215bbcdd45c55eb7c4641ab97aef9889b0fc828e7d3Ben Murdoch } 216bbcdd45c55eb7c4641ab97aef9889b0fc828e7d3Ben Murdoch 2175d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) ScopedPersistent<v8::Object> object_; 2185d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) ScopedPersistent<v8::Function> callback_; 21958537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles) v8::Isolate* isolate_; 220bbcdd45c55eb7c4641ab97aef9889b0fc828e7d3Ben Murdoch 221bbcdd45c55eb7c4641ab97aef9889b0fc828e7d3Ben Murdoch DISALLOW_COPY_AND_ASSIGN(GCCallback); 222bbcdd45c55eb7c4641ab97aef9889b0fc828e7d3Ben Murdoch }; 2235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 224bbcdd45c55eb7c4641ab97aef9889b0fc828e7d3Ben Murdoch // void BindToGC(object, callback) 225bbcdd45c55eb7c4641ab97aef9889b0fc828e7d3Ben Murdoch // 226bbcdd45c55eb7c4641ab97aef9889b0fc828e7d3Ben Murdoch // Binds |callback| to be invoked *sometime after* |object| is garbage 227bbcdd45c55eb7c4641ab97aef9889b0fc828e7d3Ben Murdoch // collected. We don't call the method re-entrantly so as to avoid executing 228bbcdd45c55eb7c4641ab97aef9889b0fc828e7d3Ben Murdoch // JS in some bizarro undefined mid-GC state. 2297d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles) void BindToGC(const v8::FunctionCallbackInfo<v8::Value>& args) { 2302a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) CHECK(args.Length() == 2 && args[0]->IsObject() && args[1]->IsFunction()); 23158537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles) GCCallback::Bind(args[0].As<v8::Object>(), 23258537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles) args[1].As<v8::Function>(), 23358537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles) args.GetIsolate()); 2345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 2350529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch 2360529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch // Dispatcher handle. Not owned. 2370529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch Dispatcher* dispatcher_; 2385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}; 2395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 2405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} // namespace 2415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 2420529e5d033099cbfc42635f6f6183833b09dff6eBen MurdochObjectBackedNativeHandler* MessagingBindings::Get(Dispatcher* dispatcher, 2430529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch ScriptContext* context) { 2442a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) return new ExtensionImpl(dispatcher, context); 2455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 2465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 2475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// static 248fb250657ef40d7500f20882d5c9909c1013367d3Ben Murdochvoid MessagingBindings::DispatchOnConnect( 2490529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch const ScriptContextSet::ContextSet& contexts, 2505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) int target_port_id, 2515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) const std::string& channel_name, 252c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) const base::DictionaryValue& source_tab, 2535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) const std::string& source_extension_id, 2545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) const std::string& target_extension_id, 255c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) const GURL& source_url, 2564e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) const std::string& tls_channel_id, 2575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) content::RenderView* restrict_to_render_view) { 258a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) v8::Isolate* isolate = v8::Isolate::GetCurrent(); 259a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) v8::HandleScope handle_scope(isolate); 2605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 261c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) scoped_ptr<V8ValueConverter> converter(V8ValueConverter::create()); 262c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) 2635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) bool port_created = false; 264c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) std::string source_url_spec = source_url.spec(); 2655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 2660529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch // TODO(kalman): pass in the full ScriptContextSet; call ForEach. 2670529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch for (ScriptContextSet::ContextSet::const_iterator it = contexts.begin(); 2680529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch it != contexts.end(); 2690529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch ++it) { 2705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (restrict_to_render_view && 2715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) restrict_to_render_view != (*it)->GetRenderView()) { 2725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) continue; 2735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 2745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 275868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) // TODO(kalman): remove when ContextSet::ForEach is available. 276868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) if ((*it)->v8_context().IsEmpty()) 277868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) continue; 278868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) 279a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) v8::Handle<v8::Value> tab = v8::Null(isolate); 280a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) v8::Handle<v8::Value> tls_channel_id_value = v8::Undefined(isolate); 2815d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) const Extension* extension = (*it)->extension(); 2825d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) if (extension) { 2835d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) if (!source_tab.empty() && !extension->is_platform_app()) 2845d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) tab = converter->ToV8Value(&source_tab, (*it)->v8_context()); 2855d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) 2864e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) ExternallyConnectableInfo* externally_connectable = 2875d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) ExternallyConnectableInfo::Get(extension); 2884e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) if (externally_connectable && 2894e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) externally_connectable->accepts_tls_channel_id) { 2904e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) tls_channel_id_value = 291a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) v8::String::NewFromUtf8(isolate, 292a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) tls_channel_id.c_str(), 293a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) v8::String::kNormalString, 294a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) tls_channel_id.size()); 2954e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) } 2964e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) } 2974e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) 298c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) v8::Handle<v8::Value> arguments[] = { 299010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles) // portId 300010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles) v8::Integer::New(isolate, target_port_id), 301010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles) // channelName 302010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles) v8::String::NewFromUtf8(isolate, 303010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles) channel_name.c_str(), 304010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles) v8::String::kNormalString, 305010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles) channel_name.size()), 306010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles) // sourceTab 307010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles) tab, 308010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles) // sourceExtensionId 309010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles) v8::String::NewFromUtf8(isolate, 310010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles) source_extension_id.c_str(), 311010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles) v8::String::kNormalString, 312010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles) source_extension_id.size()), 313010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles) // targetExtensionId 314010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles) v8::String::NewFromUtf8(isolate, 315010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles) target_extension_id.c_str(), 316010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles) v8::String::kNormalString, 317010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles) target_extension_id.size()), 318010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles) // sourceUrl 319010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles) v8::String::NewFromUtf8(isolate, 320010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles) source_url_spec.c_str(), 321010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles) v8::String::kNormalString, 322010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles) source_url_spec.size()), 323010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles) // tlsChannelId 324010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles) tls_channel_id_value, 325c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) }; 326c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) 327868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) v8::Handle<v8::Value> retval = (*it)->module_system()->CallModuleMethod( 328010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles) "messaging", "dispatchOnConnect", arraysize(arguments), arguments); 3295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 3305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (retval.IsEmpty()) { 331868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) LOG(ERROR) << "Empty return value from dispatchOnConnect."; 3325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) continue; 3335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 3345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 3355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) CHECK(retval->IsBoolean()); 336868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) port_created |= retval->BooleanValue(); 3375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 3385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 3395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // If we didn't create a port, notify the other end of the channel (treat it 3405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // as a disconnect). 3415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (!port_created) { 342010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles) content::RenderThread::Get()->Send(new ExtensionHostMsg_CloseChannel( 343010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles) target_port_id, kReceivingEndDoesntExistError)); 3445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 3455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 3465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 3475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// static 348fb250657ef40d7500f20882d5c9909c1013367d3Ben Murdochvoid MessagingBindings::DeliverMessage( 3490529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch const ScriptContextSet::ContextSet& contexts, 3505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) int target_port_id, 3511e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles) const Message& message, 3525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) content::RenderView* restrict_to_render_view) { 353f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) scoped_ptr<blink::WebScopedUserGesture> web_user_gesture; 3545d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) scoped_ptr<blink::WebScopedWindowFocusAllowedIndicator> allow_window_focus; 3555d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) if (message.user_gesture) { 356f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) web_user_gesture.reset(new blink::WebScopedUserGesture); 3575d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) allow_window_focus.reset(new blink::WebScopedWindowFocusAllowedIndicator); 3585d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) } 3591e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles) 360a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) v8::Isolate* isolate = v8::Isolate::GetCurrent(); 361a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) v8::HandleScope handle_scope(isolate); 3625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 3630529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch // TODO(kalman): pass in the full ScriptContextSet; call ForEach. 3640529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch for (ScriptContextSet::ContextSet::const_iterator it = contexts.begin(); 3650529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch it != contexts.end(); 3660529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch ++it) { 3675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (restrict_to_render_view && 3685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) restrict_to_render_view != (*it)->GetRenderView()) { 3695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) continue; 3705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 3715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 372868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) // TODO(kalman): remove when ContextSet::ForEach is available. 373868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) if ((*it)->v8_context().IsEmpty()) 374868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) continue; 375868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) 3765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Check to see whether the context has this port before bothering to create 3775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // the message. 3785d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) v8::Handle<v8::Value> port_id_handle = 3795d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) v8::Integer::New(isolate, target_port_id); 380868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) v8::Handle<v8::Value> has_port = (*it)->module_system()->CallModuleMethod( 381010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles) "messaging", "hasPort", 1, &port_id_handle); 3825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 3835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) CHECK(!has_port.IsEmpty()); 3845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (!has_port->BooleanValue()) 3855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) continue; 3865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 3875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) std::vector<v8::Handle<v8::Value> > arguments; 388a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) arguments.push_back(v8::String::NewFromUtf8(isolate, 389a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) message.data.c_str(), 390a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) v8::String::kNormalString, 391a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) message.data.size())); 3925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) arguments.push_back(port_id_handle); 393010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles) (*it)->module_system()->CallModuleMethod( 394010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles) "messaging", "dispatchOnMessage", &arguments); 3955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 3965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 3975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 3985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// static 399fb250657ef40d7500f20882d5c9909c1013367d3Ben Murdochvoid MessagingBindings::DispatchOnDisconnect( 4000529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch const ScriptContextSet::ContextSet& contexts, 4015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) int port_id, 4022a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) const std::string& error_message, 4035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) content::RenderView* restrict_to_render_view) { 404a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) v8::Isolate* isolate = v8::Isolate::GetCurrent(); 405a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) v8::HandleScope handle_scope(isolate); 4065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 4070529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch // TODO(kalman): pass in the full ScriptContextSet; call ForEach. 4080529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch for (ScriptContextSet::ContextSet::const_iterator it = contexts.begin(); 4090529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch it != contexts.end(); 4100529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch ++it) { 4115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (restrict_to_render_view && 4125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) restrict_to_render_view != (*it)->GetRenderView()) { 4135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) continue; 4145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 4155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 416868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) // TODO(kalman): remove when ContextSet::ForEach is available. 417868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) if ((*it)->v8_context().IsEmpty()) 418868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) continue; 419868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) 4205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) std::vector<v8::Handle<v8::Value> > arguments; 4215d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) arguments.push_back(v8::Integer::New(isolate, port_id)); 4222a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) if (!error_message.empty()) { 423a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) arguments.push_back( 424a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) v8::String::NewFromUtf8(isolate, error_message.c_str())); 4252a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) } else { 426a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) arguments.push_back(v8::Null(isolate)); 4272a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) } 428010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles) (*it)->module_system()->CallModuleMethod( 429010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles) "messaging", "dispatchOnDisconnect", &arguments); 4305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 4315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 4325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 4335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} // namespace extensions 434