/*
 * 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 "Debug.h"
#include "JSRunner.h"

#include "nsCOMPtr.h"
#include "nsIPrincipal.h"
#include "nsIScriptGlobalObject.h"
#include "nsIScriptObjectPrincipal.h"
#include "nsIURI.h"
#include "nsIXPConnect.h"
#include "nsStringAPI.h"

// from js_runner_ff.cc in Gears (http://code.google.com/p/gears/)

bool JSRunner::eval(JSContext* ctx, JSObject* object, const std::string& script) {
  // To eval the script, we need the JSPrincipals to be acquired through
  // nsIPrincipal.  nsIPrincipal can be queried through the
  // nsIScriptObjectPrincipal interface on the Script Global Object.  In order
  // to get the Script Global Object, we need to request the private data
  // associated with the global JSObject on the current context.
  nsCOMPtr<nsIScriptGlobalObject> sgo;
  nsISupports *priv = reinterpret_cast<nsISupports *>(JS_GetPrivate(
                                                          ctx,
                                                          object));
  nsCOMPtr<nsIXPConnectWrappedNative> wrapped_native = do_QueryInterface(priv);

  if (wrapped_native) {
    // The global object is a XPConnect wrapped native, the native in
    // the wrapper might be the nsIScriptGlobalObject.
    sgo = do_QueryWrappedNative(wrapped_native);
  } else {
    sgo = do_QueryInterface(priv);
  }

  JSPrincipals *jsprin = nsnull;
  std::string virtual_filename;
  nsresult nr;

  nsCOMPtr<nsIScriptObjectPrincipal> obj_prin = do_QueryInterface(sgo, &nr);
  if (NS_FAILED(nr)) {
    Debug::log(Debug::Error) << "Error getting object principal" << Debug::flush;
    return false;
  }

  nsIPrincipal *principal = obj_prin->GetPrincipal();
  if (!principal) {
    Debug::log(Debug::Error) << "Error getting principal" << Debug::flush;
    return false;
  }

  // Get the script scheme and host from the principal.  This is the URI that
  // Firefox treats this script as running from.

  // If the codebase is null, the script may be running from a chrome context.
  // In that case, don't construct a virtual filename.

  nsCOMPtr<nsIURI> codebase;
  nr = principal->GetURI(getter_AddRefs(codebase));
  if (codebase) { 
    nsCString scheme;
    nsCString host;

    if (NS_FAILED(codebase->GetScheme(scheme)) ||
        NS_FAILED(codebase->GetHostPort(host))) {
      Debug::log(Debug::Error) << "Error getting codebase" << Debug::flush;
      return false;
    }

    // Build a virtual filename that we'll run as.  This is to workaround
    // http://lxr.mozilla.org/seamonkey/source/dom/src/base/nsJSEnvironment.cpp#500
    // Bug: https://bugzilla.mozilla.org/show_bug.cgi?id=387477
    // The filename is being used as the security origin instead of the principal.
    // TODO(zork): Remove this section if this bug is resolved.
    virtual_filename = std::string(scheme.BeginReading());
    virtual_filename += "://";
    virtual_filename += host.BeginReading();
  }

  principal->GetJSPrincipals(ctx, &jsprin);

  // Set up the JS stack so that our context is on top.  This is needed to
  // play nicely with plugins that access the context stack, such as Firebug.
//  nsCOMPtr<nsIJSContextStack> stack =
//      do_GetService("@mozilla.org/js/xpc/ContextStack;1");
//  if (!stack) { return false; }
//
//  stack->Push(js_engine_context_);

  uintN line_number_start = 0;
  jsval rval;
  JSBool js_ok = JS_EvaluateScriptForPrincipals(ctx, object, jsprin,
      script.c_str(), script.length(), virtual_filename.c_str(),
      line_number_start, &rval);

  // Restore the context stack.
//  JSContext *cx;
//  stack->Pop(&cx);

  // Decrements ref count on jsprin (Was added in GetJSPrincipals()).
  (void) JSPRINCIPALS_DROP(ctx, jsprin);
  if (!js_ok) {
    Debug::log(Debug::Error) << "JS execution failed in JSRunner::eval"
        << Debug::flush;
    return false;
  }

  return true;
}
