/*
 * Copyright 2008 Google Inc.
 *
 * Licensed under the Apache License, Version 2.0 (the "License"); you may not
 * use this file except in compliance with the License. You may obtain a copy of
 * the License at
 *
 * http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
 * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
 * License for the specific language governing permissions and limitations under
 * the License.
 */

#include "ExternalWrapper.h"

#include "nsIHttpProtocolHandler.h"
#include "nsISupports.h"
#include "nsNetCID.h"
#include "nsCOMPtr.h"
#include "nsMemory.h"
#include "nsServiceManagerUtils.h"
#include "nsIPromptService.h"
#include "nsIDOMWindow.h"
#include "nsIDOMWindowInternal.h"
#include "nsIDOMLocation.h"
#include "nsXPCOMStrings.h"
#include "nsICategoryManager.h"
#include "nsIJSContextStack.h"
#include "nsIScriptContext.h"
#include "nsIScriptGlobalObject.h"
#include "nsPIDOMWindow.h"

#ifndef NS_IMPL_ISUPPORTS2_CI
#include "nsIClassInfoImpl.h" // 1.9 only
#endif

#include "LoadModuleMessage.h"
#include "ServerMethods.h"
#include "BrowserChannel.h"
#include "AllowedConnections.h"

NS_IMPL_ISUPPORTS2_CI(ExternalWrapper, IOOPHM, nsISecurityCheckedComponent)

ExternalWrapper::ExternalWrapper() {
  Debug::log(Debug::Spam) << "ExternalWrapper::ExternalWrapper()"
      << Debug::flush;
  preferences = new Preferences();
  windowWatcher = do_GetService(NS_WINDOWWATCHER_CONTRACTID);
  if (!windowWatcher) {
    Debug::log(Debug::Warning) << "Can't get WindowWatcher service"
        << Debug::flush;
    return;
  }
}

ExternalWrapper::~ExternalWrapper() {
  Debug::log(Debug::Spam) << "ExternalWrapper::~ExternalWrapper" << Debug::flush;
}

// define the CID for nsIHttpProtocolHandler
static NS_DEFINE_CID(kHttpHandlerCID, NS_HTTPPROTOCOLHANDLER_CID);

static nsresult getUserAgent(std::string& userAgent) {
  nsresult res;
  nsCOMPtr<nsIHttpProtocolHandler> http = do_GetService(kHttpHandlerCID, &res);
  if (NS_FAILED(res)) {
    return res;
  }
  nsCString userAgentStr;
  res = http->GetUserAgent(userAgentStr);
  if (NS_FAILED(res)) {
    return res;
  }
  userAgent.assign(userAgentStr.get());
  return NS_OK;
}

/**
 * Get JS window object.
 *
 * @param win output parameter to store the window object
 * @return true on success
 */
static bool getWindowObject(nsIDOMWindow** win) {
  // Get JSContext from stack.
  nsCOMPtr<nsIJSContextStack> stack =
      do_GetService("@mozilla.org/js/xpc/ContextStack;1");
  if (!stack) {
    Debug::log(Debug::Error) << "getWindowObject: no context stack"
        << Debug::flush;
    return false;
  }
  JSContext *cx;
  if (NS_FAILED(stack->Peek(&cx)) || !cx) {
    Debug::log(Debug::Error) << "getWindowObject: no context on stack"
        << Debug::flush;
    return false;
  }
  if (!(::JS_GetOptions(cx) & JSOPTION_PRIVATE_IS_NSISUPPORTS)) {
    Debug::log(Debug::Error)
        << "getWindowObject: context doesn't have nsISupports" << Debug::flush;
    return false;
  }

  nsCOMPtr<nsIScriptContext> scx =
    do_QueryInterface(static_cast<nsISupports *>
                                 (::JS_GetContextPrivate(cx)));
  if (!scx) {
    Debug::log(Debug::Error) << "getWindowObject: no script context"
        << Debug::flush;
    return false;
  }
  nsCOMPtr<nsIScriptGlobalObject> globalObj = scx->GetGlobalObject();
  if (!globalObj) {
    Debug::log(Debug::Error) << "getWindowObject: no global object"
        << Debug::flush;
    return false;
  }
  nsCOMPtr<nsPIDOMWindow> window = do_QueryInterface(globalObj);
  if (!window) {
    Debug::log(Debug::Error) << "getWindowObject: window is null"
        << Debug::flush;
    return false;
  }
  NS_ADDREF(*win = window);
  return true;
}

/**
 * Get the URL of a window.
 *
 * @param win DOMWindowInternal instance
 * @param url output wide string for the URL
 * @return true if successful
 */
static bool getWindowUrl(nsIDOMWindowInternal* win, nsAString& url) {
  nsCOMPtr<nsIDOMLocation> loc;
  if (win->GetLocation(getter_AddRefs(loc)) != NS_OK) {
    Debug::log(Debug::Info) << "Unable to get location" << Debug::flush;
    return false;
  }
  if (loc->GetHref(url) != NS_OK) {
    Debug::log(Debug::Info) << "Unable to get URL" << Debug::flush;
    return false;
  }
  return true;
}

/**
 * Get the top-level window for a given window, and its URL.
 *
 * @param win window to start from
 * @param topWinRet output parameter to store top window
 * @param topUrl output parameter to store URL
 * @return true on success, false on error (already logged)
 */
static bool getTopWindow(nsIDOMWindow* win, nsIDOMWindowInternal** topWinRet,
    nsAString& topUrl) {
  nsCOMPtr<nsIDOMWindow> topWin;
  if (win->GetTop(getter_AddRefs(topWin)) != NS_OK) {
    Debug::log(Debug::Error) << "Unable to get top window" << Debug::flush;
    return false;
  }
  nsresult rv;
  nsCOMPtr<nsIDOMWindowInternal> topWinInt = do_QueryInterface(topWin, &rv);
  if (rv != NS_OK) {
    Debug::log(Debug::Error) << "Unable to QI DOMWindowInternal"
        << Debug::flush;
    return false;
  }
  if (!getWindowUrl(topWinInt, topUrl)) {
    Debug::log(Debug::Error) << "Unable to get url of top window"
        << Debug::flush;
    return false;
  }
  *topWinRet = topWinInt;
  return true;
}

std::string ExternalWrapper::computeTabIdentity() {
  std::string returnVal;
  if (!windowWatcher) {
    return returnVal;
  }
  // The nsPIDOMWindow interface of our top-level window appears to be stable
  // across refreshes, so we will use that for our tab ID.
  nsCOMPtr<nsPIDOMWindow> privateWin = do_QueryInterface(topWindow);
  if (!privateWin) {
    return returnVal;
  }
  char buf[20]; // typically 8-16 hex digits plus 0x, not horrible if truncated
  snprintf(buf, sizeof(buf), "%p", privateWin.get());
  buf[19] = 0; // ensure null termination
  returnVal = buf;
  return returnVal;
}

// TODO(jat): remove suppliedWindow and update hosted.html API
NS_IMETHODIMP ExternalWrapper::Init(nsIDOMWindow* suppliedWindow,
    PRBool *_retval) {
  Debug::log(Debug::Debugging) << "Plugin initialized from hosted.html"
      << Debug::flush;
  *_retval = false;
  nsCOMPtr<nsIDOMWindow> computedWindow;
  if (getWindowObject(getter_AddRefs(computedWindow))) {
    Debug::log(Debug::Debugging) << " passed window=" << suppliedWindow
        << ", computed=" << computedWindow << Debug::flush;
    domWindow = computedWindow;
  } else {
    Debug::log(Debug::Warning) << " using supplied window object"
        << Debug::flush;
    // TODO(jat): remove this
    domWindow = suppliedWindow;
  }
  if (getTopWindow(domWindow, getter_AddRefs(topWindow), url)) {
    *_retval = true;
  }
  return NS_OK;
}

bool ExternalWrapper::askUserToAllow(const std::string& url) {
  nsCOMPtr<nsIPromptService> promptService = do_GetService(
      "@mozilla.org/embedcomp/prompt-service;1");
  if (!promptService) {
    return false;
  }
  NS_ConvertASCIItoUTF16 title("Allow GWT Developer Plugin Connection");
  NS_ConvertASCIItoUTF16 text("This web server is requesting a GWT "
      "developer plugin connection -- do you want to allow it?");
  NS_ConvertASCIItoUTF16 checkMsg("Remember this decision for this server "
      "(change in GWT Developer Plugin preferences)");
  PRBool remember = false;
  PRBool include = true;
  if (promptService->ConfirmCheck(domWindow.get(), title.get(), text.get(),
      checkMsg.get(), &remember, &include) != NS_OK) {
    return false;
  }
  if (remember) {
    preferences->addNewRule(AllowedConnections::getHostFromUrl(url), !include);
  }
  return include;
}

// TODO(jat): remove suppliedUrl and update hosted.html API
NS_IMETHODIMP ExternalWrapper::Connect(const nsACString& suppliedUrl,
                const nsACString& sessionKey, const nsACString& aAddr,
                const nsACString& aModuleName, const nsACString& hostedHtmlVersion,
                PRBool *_retval) {
  Debug::log(Debug::Info) << "Connect(url=" <<  url << ", sessionKey="
      << sessionKey << ", address=" << aAddr << ", module=" << aModuleName
      << ", hostedHtmlVersion=" << hostedHtmlVersion << Debug::flush;

  // TODO: string utilities?
  nsCString urlAutoStr;
  NS_UTF16ToCString(url, NS_CSTRING_ENCODING_UTF8, urlAutoStr);
  nsCString sessionKeyAutoStr(sessionKey);
  nsCString addrAutoStr(aAddr);
  nsCString moduleAutoStr(aModuleName);
  nsCString hostedHtmlVersionAutoStr(hostedHtmlVersion);
  std::string hostedUrl(addrAutoStr.get());
  std::string urlStr(urlAutoStr.get());

  bool allowed = false;
  if (!AllowedConnections::matchesRule(urlStr, &allowed)) {
    // If we didn't match an existing rule, prompt the user
    allowed = askUserToAllow(urlStr);
  }
  if (!allowed) {
    *_retval = false;
    return NS_OK;
  }

  size_t index = hostedUrl.find(':');
  if (index == std::string::npos) {
    *_retval = false;
    return NS_OK;
  }
  std::string hostPart = hostedUrl.substr(0, index);
  std::string portPart = hostedUrl.substr(index + 1);

  // TODO(jat): leaks HostChannel -- need to save it in a session object and
  // return that so the host page can call a disconnect method on it at unload
  // time or when it gets GC'd.
  HostChannel* channel = new HostChannel();

  Debug::log(Debug::Debugging) << "Connecting..." << Debug::flush;

  if (!channel->connectToHost(hostPart.c_str(),
      atoi(portPart.c_str()))) {
    *_retval = false;
    return NS_OK;
  }

  Debug::log(Debug::Debugging) << "...Connected" << Debug::flush;
  sessionHandler.reset(new FFSessionHandler(channel/*, ctx*/));

  std::string hostedHtmlVersionStr(hostedHtmlVersionAutoStr.get());
  if (!channel->init(sessionHandler.get(), BROWSERCHANNEL_PROTOCOL_VERSION,
      BROWSERCHANNEL_PROTOCOL_VERSION, hostedHtmlVersionStr)) {
    *_retval = false;
    return NS_OK;
  }

  std::string moduleName(moduleAutoStr.get());
  std::string userAgent;

  // get the user agent
  nsresult res = getUserAgent(userAgent);
  if (NS_FAILED(res)) {
    return res;
  }

  std::string tabKeyStr = computeTabIdentity();
  std::string sessionKeyStr(sessionKeyAutoStr.get());

  LoadModuleMessage::send(*channel, urlStr, tabKeyStr, sessionKeyStr,
      moduleName, userAgent, sessionHandler.get());

  // TODO: return session object?
  *_retval = true;
  return NS_OK;
}

// nsISecurityCheckedComponent
static char* cloneAllAccess() {
  static const char allAccess[] = "allAccess";
  return static_cast<char*>(nsMemory::Clone(allAccess, sizeof(allAccess)));
}

static bool strEquals(const PRUnichar* utf16, const char* ascii) {
  nsCString utf8;
  NS_UTF16ToCString(nsDependentString(utf16), NS_CSTRING_ENCODING_UTF8, utf8);
  return strcmp(ascii, utf8.get()) == 0;
}

NS_IMETHODIMP ExternalWrapper::CanCreateWrapper(const nsIID * iid,
    char **_retval) {
  Debug::log(Debug::Spam) << "ExternalWrapper::CanCreateWrapper"
      << Debug::flush;
  *_retval = cloneAllAccess();
  return NS_OK;
}

NS_IMETHODIMP ExternalWrapper::CanCallMethod(const nsIID * iid,
    const PRUnichar *methodName, char **_retval) {
  Debug::log(Debug::Spam) << "ExternalWrapper::CanCallMethod" << Debug::flush;
  if (strEquals(methodName, "connect") || strEquals(methodName, "init")) {
    *_retval = cloneAllAccess();
  } else {
    *_retval = nsnull;
  }
  return NS_OK;
}

NS_IMETHODIMP ExternalWrapper::CanGetProperty(const nsIID * iid,
    const PRUnichar *propertyName, char **_retval) {
  Debug::log(Debug::Spam) << "ExternalWrapper::CanGetProperty" << Debug::flush;
  *_retval = nsnull;
  return NS_OK;
}
NS_IMETHODIMP ExternalWrapper::CanSetProperty(const nsIID * iid,
    const PRUnichar *propertyName, char **_retval) {
  Debug::log(Debug::Spam) << "ExternalWrapper::CanSetProperty" << Debug::flush;
  *_retval = nsnull;
  return NS_OK;
}
