/*
 * Copyright (C) 2011 Google Inc. All rights reserved.
 *
 * Redistribution and use in source and binary forms, with or without
 * modification, are permitted provided that the following conditions are
 * met:
 *
 *     * Redistributions of source code must retain the above copyright
 * notice, this list of conditions and the following disclaimer.
 *     * Redistributions in binary form must reproduce the above
 * copyright notice, this list of conditions and the following disclaimer
 * in the documentation and/or other materials provided with the
 * distribution.
 *     * Neither the name of Google Inc. nor the names of its
 * contributors may be used to endorse or promote products derived from
 * this software without specific prior written permission.
 *
 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
 * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
 * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
 * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
 * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
 * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
 * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
 * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
 */

#include "public/web/WebDOMMessageEvent.h"

#include "bindings/core/v8/SerializedScriptValue.h"
#include "core/dom/Document.h"
#include "core/dom/MessagePort.h"
#include "core/events/MessageEvent.h"
#include "core/frame/LocalDOMWindow.h"
#include "public/platform/WebString.h"
#include "public/web/WebDocument.h"
#include "public/web/WebFrame.h"
#include "public/web/WebSerializedScriptValue.h"
#include "web/WebLocalFrameImpl.h"

namespace blink {

WebDOMMessageEvent::WebDOMMessageEvent(const WebSerializedScriptValue& messageData, const WebString& origin, const WebFrame* sourceFrame, const WebDocument& targetDocument, const WebMessagePortChannelArray& channels)
    : WebDOMMessageEvent(MessageEvent::create())
{
    DOMWindow* window = nullptr;
    if (sourceFrame)
        window = sourceFrame->toImplBase()->frame()->domWindow();
    MessagePortArray* ports = nullptr;
    if (!targetDocument.isNull()) {
        RefPtrWillBeRawPtr<Document> coreDocument = PassRefPtrWillBeRawPtr<Document>(targetDocument);
        ports = MessagePort::toMessagePortArray(coreDocument.get(), channels);
    }
    // Use an empty array for |ports| when it is null because this function
    // is used to implement postMessage().
    if (!ports)
        ports = new MessagePortArray;
    // TODO(esprehn): Chromium always passes empty string for lastEventId, is that right?
    unwrap<MessageEvent>()->initMessageEvent("message", false, false, messageData, origin, ""/*lastEventId*/, window, ports);
}

WebSerializedScriptValue WebDOMMessageEvent::data() const
{
    return WebSerializedScriptValue(constUnwrap<MessageEvent>()->dataAsSerializedScriptValue());
}

WebString WebDOMMessageEvent::origin() const
{
    return WebString(constUnwrap<MessageEvent>()->origin());
}

WebMessagePortChannelArray WebDOMMessageEvent::releaseChannels()
{
    MessagePortChannelArray* channels = constUnwrap<MessageEvent>()->channels();
    WebMessagePortChannelArray webChannels(channels ? channels->size() : 0);
    if (channels) {
        for (size_t i = 0; i < channels->size(); ++i)
            webChannels[i] = (*channels)[i].leakPtr();
    }
    return webChannels;
}

} // namespace blink
