Chromium Code Reviews| Index: third_party/WebKit/Source/modules/broadcastchannel/BroadcastChannel.cpp |
| diff --git a/third_party/WebKit/Source/modules/broadcastchannel/BroadcastChannel.cpp b/third_party/WebKit/Source/modules/broadcastchannel/BroadcastChannel.cpp |
| new file mode 100644 |
| index 0000000000000000000000000000000000000000..e2d8c022d599a3b0fbbaf48fb720c23b5440db30 |
| --- /dev/null |
| +++ b/third_party/WebKit/Source/modules/broadcastchannel/BroadcastChannel.cpp |
| @@ -0,0 +1,142 @@ |
| +// 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/BroadcastChannel.h" |
| + |
| +#include "bindings/core/v8/SerializedScriptValue.h" |
| +#include "core/dom/ExceptionCode.h" |
| +#include "core/events/EventQueue.h" |
| +#include "core/events/MessageEvent.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()); |
|
kinuko
2016/06/09 09:14:58
nit: DCHECK(isMainThread()) ?
Marijn Kruisselbrink
2016/06/22 18:46:57
Done
|
| + Platform::current()->serviceRegistry()->connectToRemoteService(std::move(request)); |
| +} |
| + |
| +webmessaging::mojom::blink::BroadcastChannelServicePtr& getThreadSpecificService() |
|
haraken
2016/06/09 02:09:36
Add a comment why you need to use a thread-local s
Marijn Kruisselbrink
2016/06/22 18:46:56
Done
|
| +{ |
| + DEFINE_THREAD_SAFE_STATIC_LOCAL(ThreadSpecific<webmessaging::mojom::blink::BroadcastChannelServicePtr>, service, new ThreadSpecific<webmessaging::mojom::blink::BroadcastChannelServicePtr>); |
| + if (!service.isSet()) { |
| + Platform::current()->mainThread()->getWebTaskRunner()->postTask(BLINK_FROM_HERE, |
| + threadSafeBind(&connectToService, passed(mojo::GetProxy(&*service)))); |
| + } |
| + return *service; |
| +} |
| + |
| +} // namespace |
| + |
| +// static |
| +BroadcastChannel* BroadcastChannel::create(ExecutionContext* executionContext, const String& name, ExceptionState& exceptionState) |
| +{ |
| + if (executionContext->getSecurityOrigin()->isUnique()) { |
| + // TODO(mek): Decide what to do here depending on https://github.com/whatwg/html/issues/1319 |
| + exceptionState.throwDOMException(NotSupportedError, "Can't create BroadcastChannel in an opaque origin"); |
| + return nullptr; |
| + } |
| + return new BroadcastChannel(executionContext, name); |
| +} |
| + |
| +BroadcastChannel::~BroadcastChannel() |
| +{ |
| +} |
| + |
| +void BroadcastChannel::dispose() |
| +{ |
| + close(); |
| +} |
| + |
| +void BroadcastChannel::postMessage(const ScriptValue& message, ExceptionState& exceptionState) |
| +{ |
| + if (!m_binding.is_bound()) { |
| + exceptionState.throwDOMException(InvalidStateError, "Channel is closed"); |
| + return; |
| + } |
| + RefPtr<SerializedScriptValue> value = SerializedScriptValue::serialize(message.isolate(), message.v8Value(), nullptr, nullptr, exceptionState); |
| + if (exceptionState.hadException()) |
| + return; |
| + |
| + String data = value->toWireString(); |
| + m_remoteClient->OnMessage(data); |
| +} |
| + |
| +void BroadcastChannel::close() |
| +{ |
| + m_remoteClient.reset(); |
| + if (m_binding.is_bound()) |
| + m_binding.Close(); |
| +} |
| + |
| +const AtomicString& BroadcastChannel::interfaceName() const |
| +{ |
| + return EventTargetNames::BroadcastChannel; |
| +} |
| + |
| +bool BroadcastChannel::hasPendingActivity() const |
| +{ |
| + return m_binding.is_bound() && hasEventListeners(EventTypeNames::message); |
| +} |
| + |
| +void BroadcastChannel::contextDestroyed() |
| +{ |
| + close(); |
| +} |
| + |
| +DEFINE_TRACE(BroadcastChannel) |
| +{ |
| + ContextLifecycleObserver::trace(visitor); |
| + EventTargetWithInlineData::trace(visitor); |
| +} |
| + |
| +void BroadcastChannel::OnMessage(const String& message) |
| +{ |
| + // Queue a task to dispatch the event. |
| + RefPtr<SerializedScriptValue> value = SerializedScriptValue::create(message); |
| + MessageEvent* event = MessageEvent::create(nullptr, value.release(), getExecutionContext()->getSecurityOrigin()->toString()); |
| + event->setTarget(this); |
| + bool success = getExecutionContext()->getEventQueue()->enqueueEvent(event); |
| + DCHECK(success); |
| + ALLOW_UNUSED_LOCAL(success); |
| +} |
| + |
| +void BroadcastChannel::onError() |
| +{ |
| + close(); |
| +} |
| + |
| +BroadcastChannel::BroadcastChannel(ExecutionContext* executionContext, const String& name) |
| + : ActiveScriptWrappable(this) |
| + , ContextLifecycleObserver(executionContext) |
| + , m_origin(executionContext->getSecurityOrigin()) |
| + , m_name(name) |
| + , m_binding(this) |
| +{ |
| + webmessaging::mojom::blink::BroadcastChannelServicePtr& service = getThreadSpecificService(); |
| + |
| + // Local BroadcastChannelClient for messages send from the browser to this channel. |
| + webmessaging::mojom::blink::BroadcastChannelClientAssociatedPtrInfo localClientInfo; |
| + m_binding.Bind(&localClientInfo, service.associated_group()); |
| + m_binding.set_connection_error_handler(createBaseCallback(bind(&BroadcastChannel::onError, WeakPersistentThisPointer<BroadcastChannel>(this)))); |
| + |
| + // Remove BroadcastChannelClient for messages send from this channel to the browser. |
|
kinuko
2016/06/09 09:14:58
Um... I guess s/Remove/Remote/ ?
Marijn Kruisselbrink
2016/06/22 18:46:57
Ah yes, done.
|
| + webmessaging::mojom::blink::BroadcastChannelClientAssociatedPtrInfo remoteClientInfo; |
| + mojo::AssociatedInterfaceRequest<webmessaging::mojom::blink::BroadcastChannelClient> remoteCientRequest; |
| + service.associated_group()->CreateAssociatedInterface(mojo::AssociatedGroup::WILL_PASS_REQUEST, &remoteClientInfo, &remoteCientRequest); |
| + m_remoteClient.Bind(std::move(remoteClientInfo)); |
| + m_remoteClient.set_connection_error_handler(createBaseCallback(bind(&BroadcastChannel::onError, WeakPersistentThisPointer<BroadcastChannel>(this)))); |
| + |
| + service->ConnectToChannel(m_origin, m_name, std::move(localClientInfo), std::move(remoteCientRequest)); |
| +} |
| + |
| +} // namespace blink |