messaging_bindings.cc revision f8ee788a64d60abd8f2d742a5fdedde054ecd910
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)
240f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)void DispatchOnConnectToScriptContext(
241f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)    int target_port_id,
242f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)    const std::string& channel_name,
243f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)    const base::DictionaryValue* source_tab,
244f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)    const ExtensionMsg_ExternalConnectionInfo& info,
245f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)    const std::string& tls_channel_id,
246f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)    bool* port_created,
247f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)    ScriptContext* script_context) {
248f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)  v8::Isolate* isolate = script_context->isolate();
249f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)  v8::HandleScope handle_scope(isolate);
250f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)
251f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)  scoped_ptr<V8ValueConverter> converter(V8ValueConverter::create());
252f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)
253f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)  const std::string& source_url_spec = info.source_url.spec();
254f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)  std::string target_extension_id = script_context->GetExtensionID();
255f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)  const Extension* extension = script_context->extension();
256f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)
257f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)  v8::Handle<v8::Value> tab = v8::Null(isolate);
258f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)  v8::Handle<v8::Value> tls_channel_id_value = v8::Undefined(isolate);
259f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)
260f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)  if (extension) {
261f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)    if (!source_tab->empty() && !extension->is_platform_app())
262f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)      tab = converter->ToV8Value(source_tab, script_context->v8_context());
263f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)
264f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)    ExternallyConnectableInfo* externally_connectable =
265f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)        ExternallyConnectableInfo::Get(extension);
266f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)    if (externally_connectable &&
267f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)        externally_connectable->accepts_tls_channel_id) {
268f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)      tls_channel_id_value = v8::String::NewFromUtf8(isolate,
269f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)                                                     tls_channel_id.c_str(),
270f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)                                                     v8::String::kNormalString,
271f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)                                                     tls_channel_id.size());
272f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)    }
273f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)  }
274f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)
275f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)  v8::Handle<v8::Value> arguments[] = {
276f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)      // portId
277f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)      v8::Integer::New(isolate, target_port_id),
278f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)      // channelName
279f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)      v8::String::NewFromUtf8(isolate,
280f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)                              channel_name.c_str(),
281f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)                              v8::String::kNormalString,
282f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)                              channel_name.size()),
283f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)      // sourceTab
284f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)      tab,
285f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)      // sourceExtensionId
286f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)      v8::String::NewFromUtf8(isolate,
287f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)                              info.source_id.c_str(),
288f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)                              v8::String::kNormalString,
289f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)                              info.source_id.size()),
290f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)      // targetExtensionId
291f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)      v8::String::NewFromUtf8(isolate,
292f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)                              target_extension_id.c_str(),
293f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)                              v8::String::kNormalString,
294f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)                              target_extension_id.size()),
295f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)      // sourceUrl
296f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)      v8::String::NewFromUtf8(isolate,
297f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)                              source_url_spec.c_str(),
298f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)                              v8::String::kNormalString,
299f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)                              source_url_spec.size()),
300f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)      // tlsChannelId
301f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)      tls_channel_id_value,
302f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)  };
303f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)
304f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)  v8::Handle<v8::Value> retval =
305f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)      script_context->module_system()->CallModuleMethod(
306f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)          "messaging", "dispatchOnConnect", arraysize(arguments), arguments);
307f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)
308f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)  if (!retval.IsEmpty()) {
309f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)    CHECK(retval->IsBoolean());
310f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)    *port_created |= retval->BooleanValue();
311f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)  } else {
312f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)    LOG(ERROR) << "Empty return value from dispatchOnConnect.";
313f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)  }
314f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)}
315f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)
316f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)void DeliverMessageToScriptContext(const std::string& message_data,
317f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)                                   int target_port_id,
318f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)                                   ScriptContext* script_context) {
319f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)  v8::Isolate* isolate = v8::Isolate::GetCurrent();
320f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)  v8::HandleScope handle_scope(isolate);
321f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)
322f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)  // Check to see whether the context has this port before bothering to create
323f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)  // the message.
324f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)  v8::Handle<v8::Value> port_id_handle =
325f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)      v8::Integer::New(isolate, target_port_id);
326f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)  v8::Handle<v8::Value> has_port =
327f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)      script_context->module_system()->CallModuleMethod(
328f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)          "messaging", "hasPort", 1, &port_id_handle);
329f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)
330f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)  CHECK(!has_port.IsEmpty());
331f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)  if (!has_port->BooleanValue())
332f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)    return;
333f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)
334f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)  std::vector<v8::Handle<v8::Value> > arguments;
335f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)  arguments.push_back(v8::String::NewFromUtf8(isolate,
336f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)                                              message_data.c_str(),
337f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)                                              v8::String::kNormalString,
338f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)                                              message_data.size()));
339f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)  arguments.push_back(port_id_handle);
340f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)  script_context->module_system()->CallModuleMethod(
341f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)      "messaging", "dispatchOnMessage", &arguments);
342f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)}
343f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)
344f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)void DispatchOnDisconnectToScriptContext(int port_id,
345f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)                                         const std::string& error_message,
346f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)                                         ScriptContext* script_context) {
347f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)  v8::Isolate* isolate = script_context->isolate();
348f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)  v8::HandleScope handle_scope(isolate);
349f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)
350f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)  std::vector<v8::Handle<v8::Value> > arguments;
351f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)  arguments.push_back(v8::Integer::New(isolate, port_id));
352f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)  if (!error_message.empty()) {
353f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)    arguments.push_back(
354f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)        v8::String::NewFromUtf8(isolate, error_message.c_str()));
355f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)  } else {
356f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)    arguments.push_back(v8::Null(isolate));
357f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)  }
358f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)
359f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)  script_context->module_system()->CallModuleMethod(
360f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)      "messaging", "dispatchOnDisconnect", &arguments);
361f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)}
362f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)
3635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}  // namespace
3645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
3650529e5d033099cbfc42635f6f6183833b09dff6eBen MurdochObjectBackedNativeHandler* MessagingBindings::Get(Dispatcher* dispatcher,
3660529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch                                                  ScriptContext* context) {
3672a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  return new ExtensionImpl(dispatcher, context);
3685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
3695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
3705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// static
371fb250657ef40d7500f20882d5c9909c1013367d3Ben Murdochvoid MessagingBindings::DispatchOnConnect(
372f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)    const ScriptContextSet& context_set,
3735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    int target_port_id,
3745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    const std::string& channel_name,
375c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    const base::DictionaryValue& source_tab,
376f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)    const ExtensionMsg_ExternalConnectionInfo& info,
3774e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)    const std::string& tls_channel_id,
3785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    content::RenderView* restrict_to_render_view) {
3795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  bool port_created = false;
380f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)  context_set.ForEach(info.target_id,
381f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)                      restrict_to_render_view,
382f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)                      base::Bind(&DispatchOnConnectToScriptContext,
383f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)                                 target_port_id,
384f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)                                 channel_name,
385f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)                                 &source_tab,
386f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)                                 info,
387f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)                                 tls_channel_id,
388f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)                                 &port_created));
3895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
3905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // If we didn't create a port, notify the other end of the channel (treat it
3915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // as a disconnect).
3925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (!port_created) {
393010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)    content::RenderThread::Get()->Send(new ExtensionHostMsg_CloseChannel(
394010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)        target_port_id, kReceivingEndDoesntExistError));
3955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
3965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
3975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
3985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// static
399fb250657ef40d7500f20882d5c9909c1013367d3Ben Murdochvoid MessagingBindings::DeliverMessage(
400f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)    const ScriptContextSet& context_set,
4015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    int target_port_id,
4021e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)    const Message& message,
4035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    content::RenderView* restrict_to_render_view) {
404f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)  scoped_ptr<blink::WebScopedUserGesture> web_user_gesture;
4055d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  scoped_ptr<blink::WebScopedWindowFocusAllowedIndicator> allow_window_focus;
4065d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  if (message.user_gesture) {
407f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)    web_user_gesture.reset(new blink::WebScopedUserGesture);
4085d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    allow_window_focus.reset(new blink::WebScopedWindowFocusAllowedIndicator);
4095d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  }
4101e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)
411f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)  context_set.ForEach(
412f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)      restrict_to_render_view,
413f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)      base::Bind(&DeliverMessageToScriptContext, message.data, target_port_id));
4145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
4155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
4165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// static
417fb250657ef40d7500f20882d5c9909c1013367d3Ben Murdochvoid MessagingBindings::DispatchOnDisconnect(
418f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)    const ScriptContextSet& context_set,
4195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    int port_id,
4202a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    const std::string& error_message,
4215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    content::RenderView* restrict_to_render_view) {
422f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)  context_set.ForEach(
423f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)      restrict_to_render_view,
424f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)      base::Bind(&DispatchOnDisconnectToScriptContext, port_id, error_message));
4255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
4265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
4275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}  // namespace extensions
428