// Copyright (c) 2011 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 "chrome/browser/chrome_plugin_host.h"

#include <set>
#include <string>
#include <vector>

#include "base/basictypes.h"
#include "base/command_line.h"
#include "base/file_path.h"
#include "base/file_util.h"
#include "base/message_loop.h"
#include "base/metrics/histogram.h"
#include "base/path_service.h"
#include "base/perftimer.h"
#include "base/singleton.h"
#include "base/string_util.h"
#include "base/utf_string_conversions.h"
#include "chrome/browser/browser_list.h"
#include "chrome/browser/chrome_plugin_browsing_context.h"
#include "chrome/browser/gears_integration.h"
#include "chrome/browser/profiles/profile.h"
#include "chrome/browser/ui/webui/html_dialog_ui.h"
#include "chrome/common/chrome_constants.h"
#include "chrome/common/chrome_counters.h"
#include "chrome/common/chrome_paths.h"
#include "chrome/common/chrome_plugin_lib.h"
#include "chrome/common/chrome_plugin_util.h"
#include "chrome/common/gears_api.h"
#include "chrome/common/net/url_request_context_getter.h"
#include "chrome/common/net/url_request_intercept_job.h"
#include "chrome/common/notification_service.h"
#include "chrome/common/plugin_messages.h"
#include "chrome/common/render_messages.h"
#include "content/browser/browser_thread.h"
#include "content/browser/plugin_process_host.h"
#include "content/browser/plugin_service.h"
#include "content/browser/renderer_host/render_process_host.h"
#include "net/base/cookie_monster.h"
#include "net/base/io_buffer.h"
#include "net/base/net_errors.h"
#include "net/http/http_request_headers.h"
#include "net/url_request/url_request.h"
#include "net/url_request/url_request_context.h"
#include "net/url_request/url_request_error_job.h"
#include "third_party/skia/include/core/SkBitmap.h"


using base::TimeDelta;

// This class manages the interception of network requests.  It queries the
// plugin on every request, and creates an intercept job if the plugin can
// intercept the request.
// NOTE: All methods must be called on the IO thread.
class PluginRequestInterceptor
    : public PluginHelper, public net::URLRequest::Interceptor {
 public:
  static net::URLRequestJob* UninterceptedProtocolHandler(
      net::URLRequest* request, const std::string& scheme) {
    // This will get called if a plugin failed to intercept a request for a
    // protocol it has registered.  In that case, we return NULL and the request
    // will result in an error.
    return new net::URLRequestErrorJob(request, net::ERR_FILE_NOT_FOUND);
  }

  explicit PluginRequestInterceptor(ChromePluginLib* plugin)
      : PluginHelper(plugin) {
    net::URLRequest::RegisterRequestInterceptor(this);
  }

  virtual ~PluginRequestInterceptor() {
    net::URLRequest::UnregisterRequestInterceptor(this);

    // Unregister our protocols.
    for (HandledProtocolList::iterator it = registered_protocols_.begin();
         it != registered_protocols_.end(); ++it) {
      net::URLRequest::ProtocolFactory* factory =
          net::URLRequest::RegisterProtocolFactory(*it, NULL);
      DCHECK(factory == UninterceptedProtocolHandler);
    }
  }

  void RegisterProtocol(const std::string& scheme) {
    DCHECK(CalledOnValidThread());

    std::string lower_scheme = StringToLowerASCII(scheme);
    handled_protocols_.insert(lower_scheme);

    // Only add a protocol factory if the net::URLRequest doesn't already handle
    // it.  If we fail to intercept, the request will be treated as an error.
    if (!net::URLRequest::IsHandledProtocol(lower_scheme)) {
      registered_protocols_.insert(lower_scheme);
      net::URLRequest::RegisterProtocolFactory(lower_scheme,
                                          &UninterceptedProtocolHandler);
    }
  }

  // net::URLRequest::Interceptor
  virtual net::URLRequestJob* MaybeIntercept(net::URLRequest* request) {
    // TODO(darin): This DCHECK fails in the unit tests because our interceptor
    // is being persisted across unit tests.  As a result, each time we get
    // poked on a different thread, but never from more than one thread at a
    // time.  We need a way to have the URLRequestJobManager get reset between
    // unit tests.
    // DCHECK(CalledOnValidThread());

    if (!IsHandledProtocol(request->url().scheme()))
      return NULL;

    CPBrowsingContext context =
        CPBrowsingContextManager::GetInstance()->Lookup(request->context());
    scoped_ptr<ScopableCPRequest> cprequest(
        new ScopableCPRequest(request->url().spec().c_str(),
                              request->method().c_str(),
                              context));

    PerfTimer timer;
    if (!plugin_->functions().should_intercept_request(cprequest.get())) {
      LogInterceptMissTime(timer.Elapsed());
      return NULL;
    }
    LogInterceptHitTime(timer.Elapsed());
    return new URLRequestInterceptJob(request, plugin_, cprequest.release());
  }

 private:
  bool IsHandledProtocol(const std::string& scheme) {
    return handled_protocols_.find(scheme) != handled_protocols_.end();
  }

  void LogInterceptHitTime(const TimeDelta& time) {
    UMA_HISTOGRAM_TIMES("Gears.InterceptHit", time);
  }

  void LogInterceptMissTime(const TimeDelta& time) {
    UMA_HISTOGRAM_TIMES("Gears.InterceptMiss", time);
  }

  typedef std::set<std::string> HandledProtocolList;
  HandledProtocolList handled_protocols_;
  HandledProtocolList registered_protocols_;
};

// This class manages a network request made by the plugin, also acting as
// the net::URLRequest delegate.
// NOTE: All methods must be called on the IO thread.
class PluginRequestHandler : public PluginHelper,
                             public net::URLRequest::Delegate {
 public:
  static PluginRequestHandler* FromCPRequest(CPRequest* request) {
    return ScopableCPRequest::GetData<PluginRequestHandler*>(request);
  }

  PluginRequestHandler(ChromePluginLib* plugin, ScopableCPRequest* cprequest)
      : PluginHelper(plugin), cprequest_(cprequest), user_buffer_(NULL) {
    cprequest_->data = this;  // see FromCPRequest().

    net::URLRequestContext* context = CPBrowsingContextManager::GetInstance()->
        ToURLRequestContext(cprequest_->context);
    // TODO(mpcomplete): remove fallback case when Gears support is prevalent.
    if (!context)
      context = Profile::GetDefaultRequestContext()->GetURLRequestContext();

    GURL gurl(cprequest_->url);
    request_.reset(new net::URLRequest(gurl, this));
    request_->set_context(context);
    request_->set_method(cprequest_->method);
    request_->set_load_flags(PluginResponseUtils::CPLoadFlagsToNetFlags(0));
  }

  net::URLRequest* request() { return request_.get(); }

  // Wraper of net::URLRequest::Read()
  bool Read(char* dest, int dest_size, int *bytes_read) {
    CHECK(!my_buffer_.get());
    // We'll use our own buffer until the read actually completes.
    user_buffer_ = dest;
    my_buffer_ = new net::IOBuffer(dest_size);

    if (request_->Read(my_buffer_, dest_size, bytes_read)) {
      memcpy(dest, my_buffer_->data(), *bytes_read);
      my_buffer_ = NULL;
      return true;
    }

    if (!request_->status().is_io_pending())
      my_buffer_ = NULL;

    return false;
  }

  // net::URLRequest::Delegate
  virtual void OnReceivedRedirect(net::URLRequest* request, const GURL& new_url,
                                  bool* defer_redirect) {
    plugin_->functions().response_funcs->received_redirect(
        cprequest_.get(), new_url.spec().c_str());
  }

  virtual void OnResponseStarted(net::URLRequest* request) {
    // TODO(mpcomplete): better error codes
    CPError result =
        request_->status().is_success() ? CPERR_SUCCESS : CPERR_FAILURE;
    plugin_->functions().response_funcs->start_completed(
        cprequest_.get(), result);
  }

  virtual void OnReadCompleted(net::URLRequest* request, int bytes_read) {
    CHECK(my_buffer_.get());
    CHECK(user_buffer_);
    if (bytes_read > 0) {
      memcpy(user_buffer_, my_buffer_->data(), bytes_read);
    } else if (bytes_read < 0) {
      // TODO(mpcomplete): better error codes
      bytes_read = CPERR_FAILURE;
    }
    my_buffer_ = NULL;
    plugin_->functions().response_funcs->read_completed(
        cprequest_.get(), bytes_read);
  }

 private:
  scoped_ptr<ScopableCPRequest> cprequest_;
  scoped_ptr<net::URLRequest> request_;
  scoped_refptr<net::IOBuffer> my_buffer_;
  char* user_buffer_;
};

// This class manages plugins that want to handle UI commands.  Right now, we
// only allow 1 plugin to do this, so there's only ever 1 instance of this
// class at once.
// NOTE: All methods must be called on the IO thread.
class PluginCommandHandler : public PluginHelper {
 public:
  static void HandleCommand(int command,
                            CPCommandInterface* data,
                            int32 context_as_int32) {
    CPBrowsingContext context =
        static_cast<CPBrowsingContext>(context_as_int32);
    // Ensure plugins are loaded before we try to talk to it.  This will be a
    // noop if plugins are loaded already.
    ChromePluginLib::LoadChromePlugins(GetCPBrowserFuncsForBrowser());

    DCHECK(ChromePluginLib::IsPluginThread());
    CPError rv = CPERR_INVALID_VERSION;
    if (instance_ && instance_->plugin_->functions().handle_command) {
      rv = instance_->plugin_->functions().handle_command(
          context, command, data ? data->GetData() : NULL);
    }
    if (data)
      data->OnCommandInvoked(rv);
  }

  static void RegisterPlugin(ChromePluginLib* plugin) {
    DCHECK(ChromePluginLib::IsPluginThread());
    // TODO(mpcomplete): We only expect to have Gears register a command handler
    // at the moment.  We should either add support for other plugins to do
    // this, or verify that the plugin is Gears.
    DCHECK(!instance_) <<
        "We only support a single plugin handling UI commands.";
    if (instance_)
      return;
    // Deleted in response to a notification in PluginHelper.
    new PluginCommandHandler(plugin);
  }

 private:
  explicit PluginCommandHandler(ChromePluginLib* plugin)
      : PluginHelper(plugin) {
    DCHECK(instance_ == NULL);
    instance_ = this;
  }

  virtual ~PluginCommandHandler() {
    instance_ = NULL;
  }

  static PluginCommandHandler* instance_;
};

PluginCommandHandler* PluginCommandHandler::instance_ = NULL;

// This class acts as a helper to display the HTML dialog.  It is created
// on demand on the plugin thread, and proxies calls to and from the UI thread
// to display the UI.
class ModelessHtmlDialogDelegate : public HtmlDialogUIDelegate {
 public:
  ModelessHtmlDialogDelegate(const GURL& url,
                             int width, int height,
                             const std::string& json_arguments,
                             void* plugin_context,
                             ChromePluginLib* plugin,
                             MessageLoop* main_message_loop,
                             gfx::NativeWindow parent_wnd)
      : main_message_loop_(main_message_loop),
        io_message_loop_(MessageLoop::current()),
        plugin_(plugin),
        plugin_context_(plugin_context),
        parent_wnd_(parent_wnd) {
    DCHECK(ChromePluginLib::IsPluginThread());
    params_.url = url;
    params_.height = height;
    params_.width = width;
    params_.json_input = json_arguments;

    main_message_loop_->PostTask(FROM_HERE, NewRunnableMethod(
        this, &ModelessHtmlDialogDelegate::Show));
  }
  virtual ~ModelessHtmlDialogDelegate() {
    DCHECK(ChromePluginLib::IsPluginThread());
  }

  // The following public methods are called from the UI thread.

  // HtmlDialogUIDelegate implementation:
  virtual bool IsDialogModal() const { return false; }
  virtual std::wstring GetDialogTitle() const { return L"Gears"; }
  virtual GURL GetDialogContentURL() const { return params_.url; }
  virtual void GetWebUIMessageHandlers(
      std::vector<WebUIMessageHandler*>* handlers) const {}
  virtual void GetDialogSize(gfx::Size* size) const {
    size->set_width(params_.width);
    size->set_height(params_.height);
  }
  virtual std::string GetDialogArgs() const { return params_.json_input; }
  virtual void OnDialogClosed(const std::string& json_retval) {
    io_message_loop_->PostTask(FROM_HERE, NewRunnableMethod(
        this, &ModelessHtmlDialogDelegate::ReportResults, json_retval));
  }
  virtual void OnCloseContents(TabContents* source, bool* out_close_dialog) { }
  virtual bool ShouldShowDialogTitle() const { return true; }

 private:
  // Actually shows the dialog on the UI thread.
  void Show() {
    DCHECK(MessageLoop::current() == main_message_loop_);
    Browser* browser = BrowserList::GetLastActive();
    browser->BrowserShowHtmlDialog(this, parent_wnd_);
  }

  // Gives the JSON result string back to the plugin.
  void ReportResults(const std::string& json_retval) {
    DCHECK(MessageLoop::current() == io_message_loop_);
    // The plugin may have unloaded before it was time to report the results.
    if (plugin_->is_loaded())
      plugin_->functions().html_dialog_closed(plugin_context_,
                                              json_retval.c_str());
    delete this;
  }

  // The parameters needed to display a modal HTML dialog.
  HtmlDialogUI::HtmlDialogParams params_;

  // Message loops for sending messages between UI and IO threads.
  MessageLoop* main_message_loop_;
  MessageLoop* io_message_loop_;

  // The plugin object that requested the dialog.  This can only be accessed on
  // the IO thread.
  scoped_refptr<ChromePluginLib> plugin_;

  // The plugin's context argument to CPB_ShowHtmlDialog.
  void* plugin_context_;

  // The window this dialog box should be parented to, or NULL for the last
  // active browser window.
  gfx::NativeWindow parent_wnd_;

  DISALLOW_COPY_AND_ASSIGN(ModelessHtmlDialogDelegate);
};

// Allows InvokeLater without adding refcounting.  The object is only deleted
// when its last InvokeLater is run anyway.
DISABLE_RUNNABLE_METHOD_REFCOUNT(ModelessHtmlDialogDelegate);

namespace {

//
// Generic functions
//

void STDCALL CPB_SetKeepProcessAlive(CPID id, CPBool keep_alive) {
  // This is a no-op in the main browser process
}

CPError STDCALL CPB_GetCookies(CPID id, CPBrowsingContext bcontext,
                               const char* url, char** cookies) {
  CHECK(ChromePluginLib::IsPluginThread());
  net::URLRequestContext* context = CPBrowsingContextManager::GetInstance()->
      ToURLRequestContext(bcontext);
  // TODO(mpcomplete): remove fallback case when Gears support is prevalent.
  if (!context) {
    context = Profile::GetDefaultRequestContext()->GetURLRequestContext();
    if (!context)
      return CPERR_FAILURE;
  }
  std::string cookies_str = context->cookie_store()->GetCookies(GURL(url));
  *cookies = CPB_StringDup(CPB_Alloc, cookies_str);
  return CPERR_SUCCESS;
}

CPError STDCALL CPB_ShowHtmlDialogModal(
    CPID id, CPBrowsingContext context, const char* url, int width, int height,
    const char* json_arguments, char** json_retval) {
  // Should not be called in browser process.
  return CPERR_FAILURE;
}

CPError STDCALL CPB_ShowHtmlDialog(
    CPID id, CPBrowsingContext context, const char* url, int width, int height,
    const char* json_arguments, void* plugin_context) {
  CHECK(ChromePluginLib::IsPluginThread());
  ChromePluginLib* plugin = ChromePluginLib::FromCPID(id);
  CHECK(plugin);

#if defined(OS_WIN)
  HWND parent_hwnd = reinterpret_cast<HWND>(static_cast<uintptr_t>(context));
  PluginService* service = PluginService::GetInstance();
  if (!service)
    return CPERR_FAILURE;
  MessageLoop* main_message_loop = service->main_message_loop();
  ModelessHtmlDialogDelegate* delegate =
      new ModelessHtmlDialogDelegate(GURL(url), width, height, json_arguments,
                                     plugin_context, plugin, main_message_loop,
                                     parent_hwnd);
#else
  // TODO(port): port ModelessHtmlDialogDelegate
  NOTIMPLEMENTED();
#endif

  return CPERR_SUCCESS;
}

CPError STDCALL CPB_GetCommandLineArguments(
    CPID id, CPBrowsingContext context, const char* url, char** arguments) {
  CHECK(ChromePluginLib::IsPluginThread());
  std::string arguments_str;
  CPError rv = CPB_GetCommandLineArgumentsCommon(url, &arguments_str);
  if (rv == CPERR_SUCCESS)
    *arguments = CPB_StringDup(CPB_Alloc, arguments_str);
  return rv;
}

CPBrowsingContext STDCALL CPB_GetBrowsingContextFromNPP(struct _NPP* npp) {
  CHECK(ChromePluginLib::IsPluginThread());
  NOTREACHED() << "NPP does not exist in the browser process.";
  return 0;
}

int STDCALL CPB_GetBrowsingContextInfo(
    CPID id, CPBrowsingContext context, CPBrowsingContextInfoType type,
    void* buf, uint32 buf_size) {
  CHECK(ChromePluginLib::IsPluginThread());
  switch (type) {
  case CPBROWSINGCONTEXT_DATA_DIR_PTR: {
    if (buf_size < sizeof(char*))
      return sizeof(char*);

    // TODO(mpcomplete): http://b/1143021 - When we support multiple profiles,
    // fetch the data dir from the context.
    PluginService* service = PluginService::GetInstance();
    if (!service)
      return CPERR_FAILURE;
    FilePath path = service->GetChromePluginDataDir();
    // This is wrong -- we can't in general stuff a path through a std::string.
    // But this code is Gears-specific, so Windows-only anyway for now.
    std::string retval;
#if defined(OS_WIN)
    retval = WideToUTF8(path.Append(chrome::kChromePluginDataDirname).value());
#else
    NOTREACHED();
#endif
    *static_cast<char**>(buf) = CPB_StringDup(CPB_Alloc, retval);
    return CPERR_SUCCESS;
    }
  case CPBROWSINGCONTEXT_UI_LOCALE_PTR: {
    if (buf_size < sizeof(char*))
      return sizeof(char*);

    PluginService* service = PluginService::GetInstance();
    if (!service)
      return CPERR_FAILURE;
    const std::string& retval = service->GetUILocale();
    *static_cast<char**>(buf) = CPB_StringDup(CPB_Alloc, retval);
    return CPERR_SUCCESS;
    }
  }

  return CPERR_FAILURE;
}

CPError STDCALL CPB_AddUICommand(CPID id, int command) {
  CHECK(ChromePluginLib::IsPluginThread());
  ChromePluginLib* plugin = ChromePluginLib::FromCPID(id);
  CHECK(plugin);

  PluginCommandHandler::RegisterPlugin(plugin);
  return CPERR_SUCCESS;
}

static void NotifyGearsShortcutsChanged() {
  DCHECK(MessageLoop::current() ==
         PluginService::GetInstance()->main_message_loop());

  // TODO(michaeln): source should be the original profile, fix this
  // when gears provides the correct browser context, and when we
  // can relate that to an actual profile.
  NotificationService::current()->Notify(
      NotificationType::WEB_APP_INSTALL_CHANGED,
      Source<Profile>(NULL),
      NotificationService::NoDetails());
}

CPError STDCALL CPB_HandleCommand(
    CPID id, CPBrowsingContext context, int command, void *data) {
  CHECK(ChromePluginLib::IsPluginThread());
  ChromePluginLib* plugin = ChromePluginLib::FromCPID(id);
  CHECK(plugin);

  if (command == GEARSBROWSERCOMMAND_CREATE_SHORTCUT_DONE) {
    GearsCreateShortcutResult* result =
        static_cast<GearsCreateShortcutResult*>(data);
    CHECK(result);

    GearsCreateShortcutData* shortcut_data =
        static_cast<GearsCreateShortcutData*>(result->shortcut);
    shortcut_data->command_interface->OnCommandResponse(result->result);
  } else if (command == GEARSBROWSERCOMMAND_NOTIFY_SHORTCUTS_CHANGED) {
    PluginService* service = PluginService::GetInstance();
    if (!service)
      return CPERR_FAILURE;
    service->main_message_loop()->PostTask(FROM_HERE,
        NewRunnableFunction(NotifyGearsShortcutsChanged));
    return CPERR_SUCCESS;
  }
  return CPERR_FAILURE;
}

CPError STDCALL CPB_GetDragData(
    CPID id, CPBrowsingContext context, struct NPObject* event, bool add_data,
    int32* identity, int32* event_id, char** drag_type, char** drag_data) {
  *identity = *event_id = 0;
  NOTREACHED() << "Should not be called in the browser process.";
  return CPERR_FAILURE;
}

CPError STDCALL CPB_SetDropEffect(
    CPID id, CPBrowsingContext context, struct NPObject* event, int effect) {
  NOTREACHED() << "Should not be called in the browser process.";
  return CPERR_FAILURE;
}

CPError STDCALL CPB_AllowFileDrop(
    CPID id, CPBrowsingContext context, const char* file_drag_data) {
  NOTREACHED() << "Should not be called in the browser process.";
  return CPERR_FAILURE;
}

//
// Functions related to network interception
//

void STDCALL CPB_EnableRequestIntercept(CPID id, const char** schemes,
                                        uint32 num_schemes) {
  CHECK(ChromePluginLib::IsPluginThread());
  ChromePluginLib* plugin = ChromePluginLib::FromCPID(id);
  CHECK(plugin);

  if (schemes && num_schemes > 0) {
    PluginRequestInterceptor* interceptor =
        new PluginRequestInterceptor(plugin);
    for (uint32 i = 0; i < num_schemes; ++i)
      interceptor->RegisterProtocol(schemes[i]);
  } else {
    PluginRequestInterceptor::DestroyAllHelpersForPlugin(plugin);
  }
}

void STDCALL CPRR_ReceivedRedirect(CPRequest* request, const char* new_url) {
}

void STDCALL CPRR_StartCompleted(CPRequest* request, CPError result) {
  CHECK(ChromePluginLib::IsPluginThread());
  URLRequestInterceptJob* job = URLRequestInterceptJob::FromCPRequest(request);
  CHECK(job);
  job->OnStartCompleted(result);
}

void STDCALL CPRR_ReadCompleted(CPRequest* request, int bytes_read) {
  CHECK(ChromePluginLib::IsPluginThread());
  URLRequestInterceptJob* job = URLRequestInterceptJob::FromCPRequest(request);
  CHECK(job);
  job->OnReadCompleted(bytes_read);
}

void STDCALL CPRR_UploadProgress(CPRequest* request, uint64 pos, uint64 size) {
  // Does not apply, plugins do not yet intercept uploads
}

//
// Functions related to serving network requests to the plugin
//

CPError STDCALL CPB_CreateRequest(CPID id, CPBrowsingContext context,
                                  const char* method, const char* url,
                                  CPRequest** request) {
  CHECK(ChromePluginLib::IsPluginThread());
  ChromePluginLib* plugin = ChromePluginLib::FromCPID(id);
  CHECK(plugin);

  ScopableCPRequest* cprequest = new ScopableCPRequest(url, method, context);
  PluginRequestHandler* handler = new PluginRequestHandler(plugin, cprequest);
  CHECK(handler);

  *request = cprequest;
  return CPERR_SUCCESS;
}

CPError STDCALL CPR_StartRequest(CPRequest* request) {
  CHECK(ChromePluginLib::IsPluginThread());
  PluginRequestHandler* handler = PluginRequestHandler::FromCPRequest(request);
  CHECK(handler);
  handler->request()->Start();
  return CPERR_IO_PENDING;
}

void STDCALL CPR_EndRequest(CPRequest* request, CPError reason) {
  CHECK(ChromePluginLib::IsPluginThread());
  PluginRequestHandler* handler = PluginRequestHandler::FromCPRequest(request);
  delete handler;
}

void STDCALL CPR_SetExtraRequestHeaders(CPRequest* request,
                                        const char* headers) {
  CHECK(ChromePluginLib::IsPluginThread());
  PluginRequestHandler* handler = PluginRequestHandler::FromCPRequest(request);
  CHECK(handler);
  net::HttpRequestHeaders http_headers;
  http_headers.AddHeadersFromString(headers);
  handler->request()->SetExtraRequestHeaders(http_headers);
}

void STDCALL CPR_SetRequestLoadFlags(CPRequest* request, uint32 flags) {
  CHECK(ChromePluginLib::IsPluginThread());
  PluginRequestHandler* handler = PluginRequestHandler::FromCPRequest(request);
  CHECK(handler);
  uint32 net_flags = PluginResponseUtils::CPLoadFlagsToNetFlags(flags);
  handler->request()->set_load_flags(net_flags);
}

void STDCALL CPR_AppendDataToUpload(CPRequest* request, const char* bytes,
                                    int bytes_len) {
  CHECK(ChromePluginLib::IsPluginThread());
  PluginRequestHandler* handler = PluginRequestHandler::FromCPRequest(request);
  CHECK(handler);
  handler->request()->AppendBytesToUpload(bytes, bytes_len);
}

CPError STDCALL CPR_AppendFileToUpload(CPRequest* request, const char* filepath,
                                       uint64 offset, uint64 length) {
  CHECK(ChromePluginLib::IsPluginThread());
  PluginRequestHandler* handler = PluginRequestHandler::FromCPRequest(request);
  CHECK(handler);

  if (!length) length = kuint64max;
  FilePath path(FilePath::FromWStringHack(UTF8ToWide(filepath)));
  handler->request()->AppendFileRangeToUpload(path, offset, length,
                                              base::Time());
  return CPERR_SUCCESS;
}

int STDCALL CPR_GetResponseInfo(CPRequest* request, CPResponseInfoType type,
                                void* buf, uint32 buf_size) {
  CHECK(ChromePluginLib::IsPluginThread());
  PluginRequestHandler* handler = PluginRequestHandler::FromCPRequest(request);
  CHECK(handler);
  return PluginResponseUtils::GetResponseInfo(
      handler->request()->response_headers(), type, buf, buf_size);
}

int STDCALL CPR_Read(CPRequest* request, void* buf, uint32 buf_size) {
  CHECK(ChromePluginLib::IsPluginThread());
  PluginRequestHandler* handler = PluginRequestHandler::FromCPRequest(request);
  CHECK(handler);

  int bytes_read;
  if (handler->Read(static_cast<char*>(buf), buf_size, &bytes_read))
    return bytes_read;  // 0 == CPERR_SUCESS

  if (handler->request()->status().is_io_pending())
    return CPERR_IO_PENDING;

  return CPERR_FAILURE;
}

CPBool STDCALL CPB_IsPluginProcessRunning(CPID id) {
  CHECK(ChromePluginLib::IsPluginThread());
  ChromePluginLib* plugin = ChromePluginLib::FromCPID(id);
  CHECK(plugin);
  PluginService* service = PluginService::GetInstance();
  if (!service)
    return false;
  PluginProcessHost *host = service->FindNpapiPluginProcess(plugin->filename());
  return host ? true : false;
}

CPProcessType STDCALL CPB_GetProcessType(CPID id) {
  CHECK(ChromePluginLib::IsPluginThread());
  return CP_PROCESS_BROWSER;
}

CPError STDCALL CPB_SendMessage(CPID id, const void *data, uint32 data_len) {
  CHECK(ChromePluginLib::IsPluginThread());
  ChromePluginLib* plugin = ChromePluginLib::FromCPID(id);
  CHECK(plugin);

  PluginService* service = PluginService::GetInstance();
  if (!service)
    return CPERR_FAILURE;
  PluginProcessHost *host =
  service->FindOrStartNpapiPluginProcess(plugin->filename());
  if (!host)
    return CPERR_FAILURE;

  const unsigned char* data_ptr = static_cast<const unsigned char*>(data);
  std::vector<uint8> v(data_ptr, data_ptr + data_len);
#if defined(OS_WIN)
  if (!host->Send(new PluginProcessMsg_PluginMessage(v)))
    return CPERR_FAILURE;
#else
  // TODO(port): Implement PluginProcessMsg.
  NOTIMPLEMENTED();
#endif

  return CPERR_SUCCESS;
}

CPError STDCALL CPB_SendSyncMessage(CPID id, const void *data, uint32 data_len,
                                    void **retval, uint32 *retval_len) {
  NOTREACHED() << "Sync messages should not be sent from the browser process.";

  return CPERR_FAILURE;
}

CPError STDCALL CPB_PluginThreadAsyncCall(CPID id,
                                          void (*func)(void *),
                                          void *user_data) {
  bool posted = BrowserThread::PostTask(
      BrowserThread::IO, FROM_HERE,
      NewRunnableFunction(func, user_data));
  return posted ? CPERR_SUCCESS : CPERR_FAILURE;
}

CPError STDCALL CPB_OpenFileDialog(CPID id,
                                   CPBrowsingContext context,
                                   bool multiple_files,
                                   const char *title,
                                   const char *filter,
                                   void *user_data) {
  NOTREACHED() <<
    "Open file dialog should only be called from the renderer process.";

  return CPERR_FAILURE;
}

}  // namespace

CPBrowserFuncs* GetCPBrowserFuncsForBrowser() {
  static CPBrowserFuncs browser_funcs;
  static CPRequestFuncs request_funcs;
  static CPResponseFuncs response_funcs;
  static bool initialized = false;
  if (!initialized) {
    initialized = true;

    browser_funcs.size = sizeof(browser_funcs);
    browser_funcs.version = CP_VERSION;
    browser_funcs.enable_request_intercept = CPB_EnableRequestIntercept;
    browser_funcs.create_request = CPB_CreateRequest;
    browser_funcs.get_cookies = CPB_GetCookies;
    browser_funcs.alloc = CPB_Alloc;
    browser_funcs.free = CPB_Free;
    browser_funcs.set_keep_process_alive = CPB_SetKeepProcessAlive;
    browser_funcs.show_html_dialog_modal = CPB_ShowHtmlDialogModal;
    browser_funcs.show_html_dialog = CPB_ShowHtmlDialog;
    browser_funcs.is_plugin_process_running = CPB_IsPluginProcessRunning;
    browser_funcs.get_process_type = CPB_GetProcessType;
    browser_funcs.send_message = CPB_SendMessage;
    browser_funcs.get_browsing_context_from_npp = CPB_GetBrowsingContextFromNPP;
    browser_funcs.get_browsing_context_info = CPB_GetBrowsingContextInfo;
    browser_funcs.get_command_line_arguments = CPB_GetCommandLineArguments;
    browser_funcs.add_ui_command = CPB_AddUICommand;
    browser_funcs.handle_command = CPB_HandleCommand;

    browser_funcs.request_funcs = &request_funcs;
    browser_funcs.response_funcs = &response_funcs;
    browser_funcs.send_sync_message = CPB_SendSyncMessage;
    browser_funcs.plugin_thread_async_call = CPB_PluginThreadAsyncCall;
    browser_funcs.open_file_dialog = CPB_OpenFileDialog;
    browser_funcs.get_drag_data = CPB_GetDragData;
    browser_funcs.set_drop_effect = CPB_SetDropEffect;
    browser_funcs.allow_file_drop = CPB_AllowFileDrop;

    request_funcs.size = sizeof(request_funcs);
    request_funcs.start_request = CPR_StartRequest;
    request_funcs.end_request = CPR_EndRequest;
    request_funcs.set_extra_request_headers = CPR_SetExtraRequestHeaders;
    request_funcs.set_request_load_flags = CPR_SetRequestLoadFlags;
    request_funcs.append_data_to_upload = CPR_AppendDataToUpload;
    request_funcs.get_response_info = CPR_GetResponseInfo;
    request_funcs.read = CPR_Read;
    request_funcs.append_file_to_upload = CPR_AppendFileToUpload;

    response_funcs.size = sizeof(response_funcs);
    response_funcs.received_redirect = CPRR_ReceivedRedirect;
    response_funcs.start_completed = CPRR_StartCompleted;
    response_funcs.read_completed = CPRR_ReadCompleted;
    response_funcs.upload_progress = CPRR_UploadProgress;
  }

  return &browser_funcs;
}

void CPCommandInterface::OnCommandInvoked(CPError retval) {
  delete this;
}

void CPCommandInterface::OnCommandResponse(CPError retval) {}

void CPHandleCommand(int command, CPCommandInterface* data,
                     CPBrowsingContext context) {
  // Sadly if we try and pass context through, we seem to break cl's little
  // brain trying to compile the Tuple3 ctor. This cast works.
  int32 context_as_int32 = static_cast<int32>(context);
  // Plugins can only be accessed on the IO thread.
  BrowserThread::PostTask(
      BrowserThread::IO, FROM_HERE,
      NewRunnableFunction(PluginCommandHandler::HandleCommand,
                          command, data, context_as_int32));
}
