blob: 5f459455d3f94f632eaba71e15dee8954baade54 [file] [log] [blame]
// Copyright 2015 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/navigatorconnect/ServicePortCollection.h"
#include "bindings/core/v8/ScriptPromiseResolver.h"
#include "bindings/core/v8/SerializedScriptValueFactory.h"
#include "core/dom/DOMException.h"
#include "core/dom/ExceptionCode.h"
#include "core/dom/MessagePort.h"
#include "core/events/MessageEvent.h"
#include "modules/EventTargetModules.h"
#include "modules/navigatorconnect/AcceptConnectionObserver.h"
#include "modules/navigatorconnect/ServicePort.h"
#include "modules/navigatorconnect/ServicePortConnectEvent.h"
#include "modules/navigatorconnect/ServicePortConnectEventInit.h"
#include "modules/navigatorconnect/ServicePortConnectOptions.h"
#include "public/platform/Platform.h"
#include "public/platform/modules/navigator_services/WebServicePortProvider.h"
namespace blink {
namespace {
class ConnectCallbacks : public WebServicePortConnectCallbacks {
public:
ConnectCallbacks(ScriptPromiseResolver* resolver, ServicePortCollection* collection, const KURL& targetUrl, const String& portName, const String& serializedPortData)
: m_resolver(resolver), m_collection(collection), m_targetUrl(targetUrl), m_portName(portName), m_serializedPortData(serializedPortData)
{
ASSERT(m_resolver);
}
~ConnectCallbacks() override { }
void onSuccess(WebServicePortID portId) override
{
if (!m_resolver->executionContext() || m_resolver->executionContext()->activeDOMObjectsAreStopped()) {
return;
}
WebServicePort webPort;
webPort.id = portId;
webPort.targetUrl = m_targetUrl;
webPort.name = m_portName;
webPort.data = m_serializedPortData;
ServicePort* port = ServicePort::create(m_collection, webPort);
m_collection->addPort(port);
m_resolver->resolve(port);
}
void onError() override
{
// TODO(mek): Pass actual error code back.
if (!m_resolver->executionContext() || m_resolver->executionContext()->activeDOMObjectsAreStopped()) {
return;
}
m_resolver->reject(DOMException::create(AbortError));
}
private:
Persistent<ScriptPromiseResolver> m_resolver;
Persistent<ServicePortCollection> m_collection;
KURL m_targetUrl;
String m_portName;
String m_serializedPortData;
WTF_MAKE_NONCOPYABLE(ConnectCallbacks);
};
} // namespace
ServicePortCollection* ServicePortCollection::create(ExecutionContext* context)
{
return new ServicePortCollection(context);
}
ServicePortCollection::~ServicePortCollection()
{
}
void ServicePortCollection::addPort(ServicePort* port)
{
m_ports.append(port);
}
void ServicePortCollection::closePort(ServicePort* port)
{
m_ports.remove(m_ports.find(port));
if (m_provider)
m_provider->closePort(port->id());
}
ScriptPromise ServicePortCollection::connect(ScriptState* scriptState, const String& url, const ServicePortConnectOptions& options, ExceptionState& exceptionState)
{
if (!m_provider)
return ScriptPromise::rejectWithDOMException(scriptState, DOMException::create(NotSupportedError));
RefPtr<SerializedScriptValue> portData;
if (options.hasData()) {
portData = SerializedScriptValueFactory::instance().create(options.data().isolate(), options.data(), nullptr, exceptionState);
if (exceptionState.hadException())
return exceptionState.reject(scriptState);
}
ScriptPromiseResolver* resolver = ScriptPromiseResolver::create(scriptState);
ScriptPromise promise = resolver->promise();
KURL targetUrl = scriptState->executionContext()->completeURL(url);
m_provider->connect(
targetUrl,
scriptState->executionContext()->securityOrigin()->toString(),
new ConnectCallbacks(resolver, this, targetUrl, options.name(), portData ? portData->toWireString() : String()));
return promise;
}
ScriptPromise ServicePortCollection::match(ScriptState* scriptState, const ServicePortMatchOptions& options)
{
return ScriptPromise::rejectWithDOMException(scriptState, DOMException::create(NotSupportedError));
}
ScriptPromise ServicePortCollection::matchAll(ScriptState* scriptState, const ServicePortMatchOptions& options)
{
return ScriptPromise::rejectWithDOMException(scriptState, DOMException::create(NotSupportedError));
}
const AtomicString& ServicePortCollection::interfaceName() const
{
return EventTargetNames::ServicePortCollection;
}
ExecutionContext* ServicePortCollection::executionContext() const
{
return ContextLifecycleObserver::executionContext();
}
void ServicePortCollection::postMessage(WebServicePortID portId, const WebString& messageString, const WebMessagePortChannelArray& webChannels)
{
OwnPtr<MessagePortChannelArray> channels;
if (webChannels.size()) {
channels = adoptPtr(new MessagePortChannelArray(webChannels.size()));
for (size_t i = 0; i < webChannels.size(); ++i)
(*channels)[i] = adoptPtr(webChannels[i]);
}
RefPtr<SerializedScriptValue> message = SerializedScriptValueFactory::instance().createFromWire(messageString);
MessagePortArray* ports = MessagePort::entanglePorts(*executionContext(), channels.release());
RefPtrWillBeRawPtr<Event> evt = MessageEvent::create(ports, message.release());
// TODO(mek): Lookup ServicePort and set events source attribute.
dispatchEvent(evt.release());
}
void ServicePortCollection::dispatchConnectEvent(PassOwnPtr<WebServicePortConnectEventCallbacks> callbacks, const WebURL& targetURL, const WebString& origin, WebServicePortID portID)
{
AcceptConnectionObserver* observer = AcceptConnectionObserver::create(this, callbacks, portID, targetURL);
ServicePortConnectEventInit init;
init.setTargetURL(targetURL.string());
init.setOrigin(origin);
RefPtrWillBeRawPtr<Event> event = ServicePortConnectEvent::create(EventTypeNames::connect, init, observer);
dispatchEvent(event.release());
observer->didDispatchEvent();
}
DEFINE_TRACE(ServicePortCollection)
{
visitor->trace(m_ports);
RefCountedGarbageCollectedEventTargetWithInlineData<ServicePortCollection>::trace(visitor);
ContextLifecycleObserver::trace(visitor);
}
ServicePortCollection::ServicePortCollection(ExecutionContext* context)
: ContextLifecycleObserver(context)
, m_provider(adoptPtr(Platform::current()->createServicePortProvider(this)))
{
}
} // namespace blink