Index: third_party/WebKit/Source/modules/broadcastchannel/BroadcastChannelConnection.cpp |
diff --git a/third_party/WebKit/Source/modules/broadcastchannel/BroadcastChannelConnection.cpp b/third_party/WebKit/Source/modules/broadcastchannel/BroadcastChannelConnection.cpp |
new file mode 100644 |
index 0000000000000000000000000000000000000000..5d60e99c34bff7dfeee63b06dbc5dcb219ae50e3 |
--- /dev/null |
+++ b/third_party/WebKit/Source/modules/broadcastchannel/BroadcastChannelConnection.cpp |
@@ -0,0 +1,120 @@ |
+// Copyright 2016 The Chromium Authors. All rights reserved. |
+// Use of this source code is governed by a BSD-style license that can be |
+// found in the LICENSE file. |
+ |
+#include "modules/broadcastchannel/BroadcastChannelConnection.h" |
+ |
+#include "platform/ThreadSafeFunctional.h" |
+#include "platform/mojo/MojoHelper.h" |
+#include "public/platform/Platform.h" |
+#include "public/platform/ServiceRegistry.h" |
+#include "public/platform/WebTaskRunner.h" |
+#include "public/platform/WebTraceLocation.h" |
+ |
+namespace blink { |
+ |
+namespace { |
+ |
+void connectToService(webmessaging::mojom::blink::BroadcastChannelServiceRequest request) |
+{ |
+ DCHECK(Platform::current()->mainThread()->isCurrentThread()); |
+ Platform::current()->serviceRegistry()->connectToRemoteService(std::move(request)); |
+} |
+ |
+webmessaging::mojom::blink::BroadcastChannelServicePtr& getThreadSpecificService() |
+{ |
+ DEFINE_THREAD_SAFE_STATIC_LOCAL(ThreadSpecific<webmessaging::mojom::blink::BroadcastChannelServicePtr>, service, new ThreadSpecific<webmessaging::mojom::blink::BroadcastChannelServicePtr>); |
esprehn
2016/06/06 02:29:42
Hmm why do we need statics for this? I don't think
Marijn Kruisselbrink
2016/06/06 20:05:29
Because in mojo every interface is its own pipe wi
haraken
2016/06/07 00:53:26
OK. Another option would be to use Page for the ma
Marijn Kruisselbrink
2016/06/07 01:18:39
Yeah, anything more contained than a service conne
|
+ if (!service.isSet()) { |
+ Platform::current()->mainThread()->getWebTaskRunner()->postTask(BLINK_FROM_HERE, |
+ threadSafeBind(&connectToService, passed(mojo::GetProxy(&*service)))); |
+ } |
+ return *service; |
+} |
+ |
+// BroadcastChannelConnection instances are jointly owned by the clients using |
+// the connection. This map is merely a way for new clients to lookup the |
+// connection to use, hence it stores weak references to connections. |
+using ConnectionKey = std::pair<RefPtr<SecurityOrigin>, String>; |
+using ConnectionMap = HeapHashMap<ConnectionKey, WeakMember<BroadcastChannelConnection>>; |
+ |
+ConnectionMap* getConnectionMap() |
+{ |
+ DEFINE_THREAD_SAFE_STATIC_LOCAL(ThreadSpecific<Persistent<ConnectionMap>>, connectionMap, new ThreadSpecific<Persistent<ConnectionMap>>); |
haraken
2016/06/06 02:05:47
+sigbjornf@: Please check if this usage is correct
sof
2016/06/06 06:35:45
Usage is exemplary; we don't try to hide very many
|
+ if (!connectionMap.isSet()) { |
+ *connectionMap = new ConnectionMap; |
+ connectionMap->registerAsStaticReference(); |
+ } |
+ return *connectionMap; |
+} |
+ |
+} // namespace |
+ |
+// static |
+BroadcastChannelConnection* BroadcastChannelConnection::getForChannel(const RefPtr<SecurityOrigin>& origin, const String& name) |
+{ |
+ ConnectionMap* connectionMap = getConnectionMap(); |
+ auto it = connectionMap->find(ConnectionKey(origin, name)); |
+ if (it != connectionMap->end()) |
+ return it->value; |
+ |
+ webmessaging::mojom::blink::BroadcastChannelServicePtr& service = getThreadSpecificService(); |
+ webmessaging::mojom::blink::BroadcastChannelClientAssociatedPtrInfo localClientInfo; |
+ BroadcastChannelConnection* connection = new BroadcastChannelConnection(name, origin, &localClientInfo, service.associated_group()); |
+ service->Subscribe(origin, name, std::move(localClientInfo)); |
+ return connection; |
+} |
+ |
+BroadcastChannelConnection::~BroadcastChannelConnection() |
+{ |
+} |
+ |
+void BroadcastChannelConnection::registerClient(Client* client) |
+{ |
+ m_clients.add(client); |
+} |
+ |
+void BroadcastChannelConnection::unregisterClient(Client* client) |
+{ |
+ m_clients.remove(client); |
+} |
+ |
+void BroadcastChannelConnection::broadcast(Client* from, const String& message) |
+{ |
+ for (Client* client : m_clients) { |
+ if (client != from) |
+ client->onMessage(message); |
+ } |
+ getThreadSpecificService()->Broadcast(from->origin(), from->name(), message); |
+} |
+ |
+DEFINE_TRACE(BroadcastChannelConnection) |
+{ |
+ visitor->trace(m_clients); |
+} |
+ |
+BroadcastChannelConnection::BroadcastChannelConnection(const String& name, const RefPtr<SecurityOrigin>& origin, webmessaging::mojom::blink::BroadcastChannelClientAssociatedPtrInfo* clientInfo, mojo::AssociatedGroup* associatedGroup) |
+ : m_name(name) |
+ , m_origin(origin) |
+ , m_binding(this, clientInfo, associatedGroup) |
+{ |
+ m_binding.set_connection_error_handler(createBaseCallback(bind(&BroadcastChannelConnection::onError, WeakPersistentThisPointer<BroadcastChannelConnection>(this)))); |
haraken
2016/06/06 02:05:47
+hiroshige@: Is this a correct usage to bind a Bli
Marijn Kruisselbrink
2016/06/06 20:05:29
fwiw this is how at least PaymentRequest does it (
|
+ auto result = getConnectionMap()->set(ConnectionKey(m_origin, m_name), this); |
+ DCHECK(result.isNewEntry) << "There should only be one connection per channel per thread."; |
+ ALLOW_UNUSED_LOCAL(result); |
haraken
2016/06/06 02:05:47
Nit: Is this needed?
Marijn Kruisselbrink
2016/06/06 20:05:29
Not sure. Assertions.h seems to suggest so though
|
+} |
+ |
+void BroadcastChannelConnection::OnMessage(const String& message) |
+{ |
+ for (Client* client : m_clients) |
+ client->onMessage(message); |
+} |
+ |
+void BroadcastChannelConnection::onError() |
+{ |
+ for (Client* client : m_clients) |
+ client->onError(); |
+ m_clients.clear(); |
+ getConnectionMap()->remove(ConnectionKey(m_origin, m_name)); |
+} |
+ |
+} // namespace blink |