// Copyright (c) 2012 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 "content/worker/websharedworker_stub.h"

#include "base/compiler_specific.h"
#include "content/child/child_process.h"
#include "content/child/child_thread.h"
#include "content/child/fileapi/file_system_dispatcher.h"
#include "content/child/webmessageportchannel_impl.h"
#include "content/common/worker_messages.h"
#include "content/worker/shared_worker_devtools_agent.h"
#include "content/worker/worker_thread.h"
#include "third_party/WebKit/public/web/WebSharedWorker.h"
#include "third_party/WebKit/public/platform/WebString.h"
#include "third_party/WebKit/public/platform/WebURL.h"

namespace content {

WebSharedWorkerStub::WebSharedWorkerStub(
    const string16& name,
    int route_id,
    const WorkerAppCacheInitInfo& appcache_init_info)
    : route_id_(route_id),
      appcache_init_info_(appcache_init_info),
      client_(route_id, this),
      name_(name),
      started_(false) {

  WorkerThread* worker_thread = WorkerThread::current();
  DCHECK(worker_thread);
  worker_thread->AddWorkerStub(this);
  // Start processing incoming IPCs for this worker.
  worker_thread->AddRoute(route_id_, this);
  ChildProcess::current()->AddRefProcess();

  // TODO(atwilson): Add support for NaCl when they support MessagePorts.
  impl_ = WebKit::WebSharedWorker::create(client());
  worker_devtools_agent_.reset(new SharedWorkerDevToolsAgent(route_id, impl_));
  client()->set_devtools_agent(worker_devtools_agent_.get());
}

WebSharedWorkerStub::~WebSharedWorkerStub() {
  impl_->clientDestroyed();
  WorkerThread* worker_thread = WorkerThread::current();
  DCHECK(worker_thread);
  worker_thread->RemoveWorkerStub(this);
  worker_thread->RemoveRoute(route_id_);
  ChildProcess::current()->ReleaseProcess();
}

void WebSharedWorkerStub::Shutdown() {
  // The worker has exited - free ourselves and the client.
  delete this;
}

void WebSharedWorkerStub::EnsureWorkerContextTerminates() {
  client_.EnsureWorkerContextTerminates();
}

bool WebSharedWorkerStub::OnMessageReceived(const IPC::Message& message) {
  if (worker_devtools_agent_->OnMessageReceived(message))
    return true;

  bool handled = true;
  IPC_BEGIN_MESSAGE_MAP(WebSharedWorkerStub, message)
    IPC_MESSAGE_HANDLER(WorkerMsg_StartWorkerContext, OnStartWorkerContext)
    IPC_MESSAGE_HANDLER(WorkerMsg_TerminateWorkerContext,
                        OnTerminateWorkerContext)
    IPC_MESSAGE_HANDLER(WorkerMsg_Connect, OnConnect)
    IPC_MESSAGE_UNHANDLED(handled = false)
  IPC_END_MESSAGE_MAP()
  return handled;
}

void WebSharedWorkerStub::OnChannelError() {
    OnTerminateWorkerContext();
}

const GURL& WebSharedWorkerStub::url() {
  return url_;
}

void WebSharedWorkerStub::OnStartWorkerContext(
    const GURL& url, const string16& user_agent, const string16& source_code,
    const string16& content_security_policy,
    WebKit::WebContentSecurityPolicyType policy_type) {
  // Ignore multiple attempts to start this worker (can happen if two pages
  // try to start it simultaneously).
  if (started_)
    return;

  impl_->startWorkerContext(url, name_, user_agent, source_code,
                            content_security_policy, policy_type, 0);
  started_ = true;
  url_ = url;

  // Process any pending connections.
  for (PendingConnectInfoList::const_iterator iter = pending_connects_.begin();
       iter != pending_connects_.end();
       ++iter) {
    OnConnect(iter->first, iter->second);
  }
  pending_connects_.clear();
}

void WebSharedWorkerStub::OnConnect(int sent_message_port_id, int routing_id) {
  if (started_) {
    WebKit::WebMessagePortChannel* channel =
        new WebMessagePortChannelImpl(routing_id,
                                      sent_message_port_id,
                                      base::MessageLoopProxy::current().get());
    impl_->connect(channel, NULL);
  } else {
    // If two documents try to load a SharedWorker at the same time, the
    // WorkerMsg_Connect for one of the documents can come in before the
    // worker is started. Just queue up the connect and deliver it once the
    // worker starts.
    PendingConnectInfo pending_connect(sent_message_port_id, routing_id);
    pending_connects_.push_back(pending_connect);
  }
}

void WebSharedWorkerStub::OnTerminateWorkerContext() {
  impl_->terminateWorkerContext();

  // Call the client to make sure context exits.
  EnsureWorkerContextTerminates();
  started_ = false;
}

}  // namespace content
