| /* |
| * 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; |
| } |