Commit 5fb49c8d authored by Arthur Edelstein's avatar Arthur Edelstein Committed by Georg Koppen
Browse files

Bug #2874: Block Components.interfaces from content

parent cbb0a005
Loading
Loading
Loading
Loading
+0 −98
Original line number Diff line number Diff line
@@ -1946,11 +1946,6 @@ OldBindingConstructorEnabled(const nsGlobalNameStruct *aStruct,
  return true;
}

static nsresult
LookupComponentsShim(JSContext *cx, JS::Handle<JSObject*> global,
                     nsPIDOMWindow *win,
                     JS::MutableHandle<JSPropertyDescriptor> desc);

// static
bool
nsWindowSH::NameStructEnabled(JSContext* aCx, nsGlobalWindow *aWin,
@@ -1988,10 +1983,6 @@ nsWindowSH::GlobalResolve(nsGlobalWindow *aWin, JSContext *cx,
                          JS::Handle<JSObject*> obj, JS::Handle<jsid> id,
                          JS::MutableHandle<JSPropertyDescriptor> desc)
{
  if (id == XPCJSRuntime::Get()->GetStringID(XPCJSRuntime::IDX_COMPONENTS)) {
    return LookupComponentsShim(cx, obj, aWin, desc);
  }

#ifdef USE_CONTROLLERS_SHIM
  // Note: We use |obj| rather than |aWin| to get the principal here, because
  // this is called during Window setup when the Document isn't necessarily
@@ -2315,95 +2306,6 @@ nsWindowSH::GlobalResolve(nsGlobalWindow *aWin, JSContext *cx,
  return rv;
}

struct InterfaceShimEntry {
  const char *geckoName;
  const char *domName;
};

// We add shims from Components.interfaces.nsIDOMFoo to window.Foo for each
// interface that has interface constants that sites might be getting off
// of Ci.
const InterfaceShimEntry kInterfaceShimMap[] =
{ { "nsIDOMFileReader", "FileReader" },
  { "nsIXMLHttpRequest", "XMLHttpRequest" },
  { "nsIDOMDOMException", "DOMException" },
  { "nsIDOMNode", "Node" },
  { "nsIDOMCSSPrimitiveValue", "CSSPrimitiveValue" },
  { "nsIDOMCSSRule", "CSSRule" },
  { "nsIDOMCSSValue", "CSSValue" },
  { "nsIDOMEvent", "Event" },
  { "nsIDOMNSEvent", "Event" },
  { "nsIDOMKeyEvent", "KeyEvent" },
  { "nsIDOMMouseEvent", "MouseEvent" },
  { "nsIDOMMouseScrollEvent", "MouseScrollEvent" },
  { "nsIDOMMutationEvent", "MutationEvent" },
  { "nsIDOMSimpleGestureEvent", "SimpleGestureEvent" },
  { "nsIDOMUIEvent", "UIEvent" },
  { "nsIDOMHTMLMediaElement", "HTMLMediaElement" },
  { "nsIDOMMediaError", "MediaError" },
  { "nsIDOMOfflineResourceList", "OfflineResourceList" },
  { "nsIDOMRange", "Range" },
  { "nsIDOMSVGLength", "SVGLength" },
  { "nsIDOMNodeFilter", "NodeFilter" },
  { "nsIDOMXPathResult", "XPathResult" } };

static nsresult
LookupComponentsShim(JSContext *cx, JS::Handle<JSObject*> global,
                     nsPIDOMWindow *win,
                     JS::MutableHandle<JSPropertyDescriptor> desc)
{
  // Keep track of how often this happens.
  Telemetry::Accumulate(Telemetry::COMPONENTS_SHIM_ACCESSED_BY_CONTENT, true);

  // Warn once.
  nsCOMPtr<nsIDocument> doc = win->GetExtantDoc();
  if (doc) {
    doc->WarnOnceAbout(nsIDocument::eComponents, /* asError = */ true);
  }

  // Create a fake Components object.
  AssertSameCompartment(cx, global);
  JS::Rooted<JSObject*> components(cx, JS_NewPlainObject(cx));
  NS_ENSURE_TRUE(components, NS_ERROR_OUT_OF_MEMORY);

  // Create a fake interfaces object.
  JS::Rooted<JSObject*> interfaces(cx, JS_NewPlainObject(cx));
  NS_ENSURE_TRUE(interfaces, NS_ERROR_OUT_OF_MEMORY);
  bool ok =
    JS_DefineProperty(cx, components, "interfaces", interfaces,
                      JSPROP_ENUMERATE | JSPROP_PERMANENT | JSPROP_READONLY,
                      JS_STUBGETTER, JS_STUBSETTER);
  NS_ENSURE_TRUE(ok, NS_ERROR_OUT_OF_MEMORY);

  // Define a bunch of shims from the Ci.nsIDOMFoo to window.Foo for DOM
  // interfaces with constants.
  for (uint32_t i = 0; i < ArrayLength(kInterfaceShimMap); ++i) {

    // Grab the names from the table.
    const char *geckoName = kInterfaceShimMap[i].geckoName;
    const char *domName = kInterfaceShimMap[i].domName;

    // Look up the appopriate interface object on the global.
    JS::Rooted<JS::Value> v(cx, JS::UndefinedValue());
    ok = JS_GetProperty(cx, global, domName, &v);
    NS_ENSURE_TRUE(ok, NS_ERROR_OUT_OF_MEMORY);
    if (!v.isObject()) {
      NS_WARNING("Unable to find interface object on global");
      continue;
    }

    // Define the shim on the interfaces object.
    ok = JS_DefineProperty(cx, interfaces, geckoName, v,
                           JSPROP_ENUMERATE | JSPROP_PERMANENT | JSPROP_READONLY,
                           JS_STUBGETTER, JS_STUBSETTER);
    NS_ENSURE_TRUE(ok, NS_ERROR_OUT_OF_MEMORY);
  }

  FillPropertyDescriptor(desc, global, JS::ObjectValue(*components), false);

  return NS_OK;
}

// EventTarget helper

NS_IMETHODIMP
+4 −4
Original line number Diff line number Diff line
@@ -48,7 +48,7 @@ https://bugzilla.mozilla.org/show_bug.cgi?id=238987
        shouldStop = true;
      }
    } else if (e.target.id == "end") {
      modifier = Components.interfaces.nsIDOMEvent.SHIFT_MASK;
      modifier = SpecialPowers.Ci.nsIDOMEvent.SHIFT_MASK;
    } else if (modifier) {
      var expected = backwardFocusArray.pop();
      ok(expected == e.target.id,
@@ -69,7 +69,7 @@ https://bugzilla.mozilla.org/show_bug.cgi?id=238987
    if ("id" in e.target) {
      s = s + ", id=\"" + e.target.id + "\"";
    }
    ok(e.eventPhase == Components.interfaces.nsIDOMEvent.CAPTURING_PHASE,
    ok(e.eventPhase == SpecialPowers.Ci.nsIDOMEvent.CAPTURING_PHASE,
       "|window| should not have got a focus event, " + s);
  }

@@ -95,14 +95,14 @@ https://bugzilla.mozilla.org/show_bug.cgi?id=238987
    if ("id" in e.target) {
      s = s + ", id=\"" + e.target.id + "\"";
    }
    ok(e.eventPhase == Components.interfaces.nsIDOMEvent.CAPTURING_PHASE,
    ok(e.eventPhase == SpecialPowers.Ci.nsIDOMEvent.CAPTURING_PHASE,
       "|window| should not have got a blur event, " + s);
  }

  function tab() {
    var utils = SpecialPowers.DOMWindowUtils;
    // Send tab key events.
    var key = Components.interfaces.nsIDOMKeyEvent.DOM_VK_TAB;
    var key = SpecialPowers.Ci.nsIDOMKeyEvent.DOM_VK_TAB;
    utils.sendKeyEvent("keydown", key, 0, modifier);
    utils.sendKeyEvent("keypress", key, 0, modifier);
    utils.sendKeyEvent("keyup", key, 0, modifier);
+1 −1
Original line number Diff line number Diff line
@@ -15,7 +15,7 @@ var archiveReaderEnabled = false;
// placebo for compat. An easy way to differentiate this from the real thing
// is whether the property is read-only or not.
var c = Object.getOwnPropertyDescriptor(this, 'Components');
if ((!c.value || c.writable) && typeof SpecialPowers === 'object')
if ((!c || !c.value || c.writable) && typeof SpecialPowers === 'object')
  Components = SpecialPowers.Components;

function executeSoon(aFun)
+6 −5
Original line number Diff line number Diff line
@@ -58,10 +58,11 @@ https://bugzilla.mozilla.org/show_bug.cgi?id=795275

  function getWin(id) { return document.getElementById(id).contentWindow.wrappedJSObject; }
  function go() {
    getWin('frame1').touchComponents();
    getWin('frame2').touchInterfaces();
    getWin('frame4').touchComponents();
    getWin('frame4').touchInterfaces();
// TODO: We have removed Components from content scripts. We could remove these tests.
//    getWin('frame1').touchComponents();
//    getWin('frame2').touchInterfaces();
//    getWin('frame4').touchComponents();
//    getWin('frame4').touchInterfaces();
    // This shouldn't warn.
    getWin('frame5').touchViaXBL();

@@ -72,7 +73,7 @@ https://bugzilla.mozilla.org/show_bug.cgi?id=795275

  function done() {
    gConsoleService.unregisterListener(gListener);
    is(gWarnings, 3, "Got the right number of warnings");
    is(gWarnings, 0, "Got the right number of warnings");
    SimpleTest.finish();
  }

+0 −1
Original line number Diff line number Diff line
@@ -74,7 +74,6 @@ skip-if= buildapp == 'mulet'
[test_bug772288.html]
[test_bug781476.html]
[test_bug789713.html]
[test_bug790732.html]
[test_bug793969.html]
[test_bug800864.html]
[test_bug802557.html]
Loading