summaryrefslogtreecommitdiffstats
path: root/extensions/pref/autoconfig/src/nsJSConfigTriggers.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'extensions/pref/autoconfig/src/nsJSConfigTriggers.cpp')
-rw-r--r--extensions/pref/autoconfig/src/nsJSConfigTriggers.cpp163
1 files changed, 163 insertions, 0 deletions
diff --git a/extensions/pref/autoconfig/src/nsJSConfigTriggers.cpp b/extensions/pref/autoconfig/src/nsJSConfigTriggers.cpp
new file mode 100644
index 0000000000..4b2334ae2b
--- /dev/null
+++ b/extensions/pref/autoconfig/src/nsJSConfigTriggers.cpp
@@ -0,0 +1,163 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
+/* This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
+
+#include "nsJSConfigTriggers.h"
+
+#include "jsapi.h"
+#include "nsIXPConnect.h"
+#include "nsCOMPtr.h"
+#include "nsString.h"
+#include "nspr.h"
+#include "mozilla/Attributes.h"
+#include "mozilla/Maybe.h"
+#include "mozilla/NullPrincipal.h"
+#include "mozilla/dom/ScriptSettings.h"
+#include "nsContentUtils.h"
+#include "nsJSPrincipals.h"
+#include "nsIScriptError.h"
+#include "js/Wrapper.h"
+#include "mozilla/Utf8.h"
+
+extern mozilla::LazyLogModule MCD;
+using mozilla::AutoSafeJSContext;
+using mozilla::IsUtf8;
+using mozilla::NullPrincipal;
+using mozilla::dom::AutoJSAPI;
+
+//*****************************************************************************
+
+static JS::PersistentRooted<JSObject*> autoconfigSystemSb;
+static JS::PersistentRooted<JSObject*> autoconfigSb;
+static bool sandboxEnabled;
+
+nsresult CentralizedAdminPrefManagerInit(bool aSandboxEnabled) {
+ // If the sandbox is already created, no need to create it again.
+ if (autoconfigSb.initialized()) return NS_OK;
+
+ sandboxEnabled = aSandboxEnabled;
+
+ // Grab XPConnect.
+ nsCOMPtr<nsIXPConnect> xpc = nsIXPConnect::XPConnect();
+
+ // Grab the system principal.
+ nsCOMPtr<nsIPrincipal> principal;
+ nsContentUtils::GetSecurityManager()->GetSystemPrincipal(
+ getter_AddRefs(principal));
+
+ // Create a sandbox.
+ AutoSafeJSContext cx;
+ JS::Rooted<JSObject*> sandbox(cx);
+ nsresult rv = xpc->CreateSandbox(cx, principal, sandbox.address());
+ NS_ENSURE_SUCCESS(rv, rv);
+
+ // Unwrap, store and root the sandbox.
+ NS_ENSURE_STATE(sandbox);
+ autoconfigSystemSb.init(cx, js::UncheckedUnwrap(sandbox));
+
+ // Create an unprivileged sandbox.
+ principal = NullPrincipal::CreateWithoutOriginAttributes();
+ rv = xpc->CreateSandbox(cx, principal, sandbox.address());
+ NS_ENSURE_SUCCESS(rv, rv);
+
+ autoconfigSb.init(cx, js::UncheckedUnwrap(sandbox));
+
+ // Define gSandbox on system sandbox.
+ JSAutoRealm ar(cx, autoconfigSystemSb);
+
+ JS::Rooted<JS::Value> value(cx, JS::ObjectValue(*sandbox));
+
+ if (!JS_WrapValue(cx, &value) ||
+ !JS_DefineProperty(cx, autoconfigSystemSb, "gSandbox", value,
+ JSPROP_ENUMERATE)) {
+ return NS_ERROR_FAILURE;
+ }
+
+ return NS_OK;
+}
+
+nsresult CentralizedAdminPrefManagerFinish() {
+ if (autoconfigSb.initialized()) {
+ AutoSafeJSContext cx;
+ autoconfigSb.reset();
+ autoconfigSystemSb.reset();
+ JS_MaybeGC(cx);
+ }
+ return NS_OK;
+}
+
+nsresult EvaluateAdminConfigScript(const char* js_buffer, size_t length,
+ const char* filename, bool globalContext,
+ bool callbacks, bool skipFirstLine,
+ bool isPrivileged) {
+ if (!sandboxEnabled) {
+ isPrivileged = true;
+ }
+ return EvaluateAdminConfigScript(
+ isPrivileged ? autoconfigSystemSb : autoconfigSb, js_buffer, length,
+ filename, globalContext, callbacks, skipFirstLine);
+}
+
+nsresult EvaluateAdminConfigScript(JS::HandleObject sandbox,
+ const char* js_buffer, size_t length,
+ const char* filename, bool globalContext,
+ bool callbacks, bool skipFirstLine) {
+ if (skipFirstLine) {
+ /* In order to protect the privacy of the JavaScript preferences file
+ * from loading by the browser, we make the first line unparseable
+ * by JavaScript. We must skip that line here before executing
+ * the JavaScript code.
+ */
+ unsigned int i = 0;
+ while (i < length) {
+ char c = js_buffer[i++];
+ if (c == '\r') {
+ if (js_buffer[i] == '\n') i++;
+ break;
+ }
+ if (c == '\n') break;
+ }
+
+ length -= i;
+ js_buffer += i;
+ }
+
+ // Grab XPConnect.
+ nsCOMPtr<nsIXPConnect> xpc = nsIXPConnect::XPConnect();
+
+ AutoJSAPI jsapi;
+ if (!jsapi.Init(sandbox)) {
+ return NS_ERROR_UNEXPECTED;
+ }
+ JSContext* cx = jsapi.cx();
+
+ nsAutoCString script(js_buffer, length);
+ JS::RootedValue v(cx);
+
+ nsString convertedScript;
+ bool isUTF8 = IsUtf8(script);
+ if (isUTF8) {
+ CopyUTF8toUTF16(script, convertedScript);
+ } else {
+ nsContentUtils::ReportToConsoleNonLocalized(
+ nsLiteralString(
+ u"Your AutoConfig file is ASCII. Please convert it to UTF-8."),
+ nsIScriptError::warningFlag, "autoconfig"_ns, nullptr);
+ /* If the length is 0, the conversion failed. Fallback to ASCII */
+ convertedScript = NS_ConvertASCIItoUTF16(script);
+ }
+ {
+ JSAutoRealm ar(cx, autoconfigSystemSb);
+ JS::Rooted<JS::Value> value(cx, JS::BooleanValue(isUTF8));
+ if (!JS_DefineProperty(cx, autoconfigSystemSb, "gIsUTF8", value,
+ JSPROP_ENUMERATE)) {
+ return NS_ERROR_UNEXPECTED;
+ }
+ }
+ nsresult rv =
+ xpc->EvalInSandboxObject(convertedScript, filename, cx, sandbox, &v);
+ NS_ENSURE_SUCCESS(rv, rv);
+
+ return NS_OK;
+}