Bug 983619 - Add Window.getInterface/QueryInterface to WebIDL. r=bz.

This commit is contained in:
Peter Van der Beken 2014-02-15 22:12:33 +01:00
parent ee76987bdb
commit bb1ee2a3ab
8 changed files with 71 additions and 18 deletions

View File

@ -3638,17 +3638,7 @@ nsXMLHttpRequest::GetInterface(const nsIID & aIID, void **aResult)
JS::Value
nsXMLHttpRequest::GetInterface(JSContext* aCx, nsIJSID* aIID, ErrorResult& aRv)
{
const nsID* iid = aIID->GetID();
nsCOMPtr<nsISupports> result;
JS::Rooted<JS::Value> v(aCx, JSVAL_NULL);
aRv = GetInterface(*iid, getter_AddRefs(result));
NS_ENSURE_FALSE(aRv.Failed(), JSVAL_NULL);
JS::Rooted<JSObject*> wrapper(aCx, GetWrapper());
JSAutoCompartment ac(aCx, wrapper);
JS::Rooted<JSObject*> global(aCx, JS_GetGlobalForObject(aCx, wrapper));
aRv = nsContentUtils::WrapNative(aCx, global, result, iid, &v);
return aRv.Failed() ? JSVAL_NULL : v;
return dom::GetInterface(aCx, this, aIID, aRv);
}
nsXMLHttpRequestUpload*

View File

@ -10384,6 +10384,12 @@ nsGlobalWindow::GetInterface(const nsIID & aIID, void **aSink)
return *aSink ? NS_OK : NS_ERROR_NO_INTERFACE;
}
JS::Value
nsGlobalWindow::GetInterface(JSContext* aCx, nsIJSID* aIID, ErrorResult& aError)
{
return dom::GetInterface(aCx, this, aIID, aError);
}
void
nsGlobalWindow::FireOfflineStatusEvent()
{

View File

@ -84,6 +84,7 @@ class nsIDOMCrypto;
class nsIDOMOfflineResourceList;
class nsIScrollableFrame;
class nsIControllers;
class nsIJSID;
class nsIScriptContext;
class nsIScriptTimeoutHandler;
class nsIWebBrowserChrome;
@ -979,6 +980,9 @@ public:
mozilla::dom::Element* aPanel,
mozilla::ErrorResult& aError);
JS::Value GetInterface(JSContext* aCx, nsIJSID* aIID,
mozilla::ErrorResult& aError);
protected:
// Array of idle observers that are notified of idle events.
nsTObserverArray<IdleObserverHolder> mIdleObservers;

View File

@ -814,13 +814,20 @@ QueryInterface(JSContext* cx, unsigned argc, JS::Value* vp)
// Get the object. It might be a security wrapper, in which case we do a checked
// unwrap.
JS::Rooted<JSObject*> origObj(cx, &thisv.toObject());
JSObject* obj = js::CheckedUnwrap(origObj);
JSObject* obj = js::CheckedUnwrap(origObj, /* stopAtOuter = */ false);
if (!obj) {
JS_ReportError(cx, "Permission denied to access object");
return false;
}
nsISupports* native = UnwrapDOMObjectToISupports(obj);
// Switch this to UnwrapDOMObjectToISupports once our global objects are
// using new bindings.
JS::Rooted<JS::Value> val(cx, JS::ObjectValue(*obj));
nsISupports* native = nullptr;
nsCOMPtr<nsISupports> nativeRef;
xpc_qsUnwrapArg<nsISupports>(cx, val, &native,
static_cast<nsISupports**>(getter_AddRefs(nativeRef)),
&val);
if (!native) {
return Throw(cx, NS_ERROR_FAILURE);
}
@ -861,6 +868,30 @@ QueryInterface(JSContext* cx, unsigned argc, JS::Value* vp)
return true;
}
JS::Value
GetInterfaceImpl(JSContext* aCx, nsIInterfaceRequestor* aRequestor,
nsWrapperCache* aCache, nsIJSID* aIID, ErrorResult& aError)
{
const nsID* iid = aIID->GetID();
nsCOMPtr<nsISupports> result;
JS::Rooted<JS::Value> v(aCx, JSVAL_NULL);
aError = aRequestor->GetInterface(*iid, getter_AddRefs(result));
if (aError.Failed()) {
return JS::NullValue();
}
JS::Rooted<JSObject*> wrapper(aCx, aCache->GetWrapper());
JSAutoCompartment ac(aCx, wrapper);
JS::Rooted<JSObject*> global(aCx, JS_GetGlobalForObject(aCx, wrapper));
aError = nsContentUtils::WrapNative(aCx, global, result, iid, &v);
if (aError.Failed()) {
return JS::NullValue();
}
return v;
}
bool
ThrowingConstructor(JSContext* cx, unsigned argc, JS::Value* vp)
{

View File

@ -34,6 +34,7 @@
#include "nsWrapperCacheInlines.h"
class nsIJSID;
class nsPIDOMWindow;
extern nsresult
@ -1464,6 +1465,17 @@ WantsQueryInterface
}
};
JS::Value
GetInterfaceImpl(JSContext* aCx, nsIInterfaceRequestor* aRequestor,
nsWrapperCache* aCache, nsIJSID* aIID, ErrorResult& aError);
template<class T>
JS::Value
GetInterface(JSContext* aCx, T* aThis, nsIJSID* aIID, ErrorResult& aError)
{
return GetInterfaceImpl(aCx, aThis, aThis, aIID, aError);
}
bool
ThrowingConstructor(JSContext* cx, unsigned argc, JS::Value* vp);

View File

@ -1216,11 +1216,11 @@ function createInterfaceMap(isXBLScope) {
var interfaceMap = {};
function addInterfaces(interfaces, shouldExpect)
function addInterfaces(interfaces)
{
for (var entry of interfaces) {
if (typeof(entry) === "string") {
interfaceMap[entry] = shouldExpect;
interfaceMap[entry] = true;
} else if ((entry.nightly === !isNightly) ||
(entry.xbl === !isXBLScope) ||
(entry.desktop === !isDesktop) ||
@ -1230,13 +1230,19 @@ function createInterfaceMap(isXBLScope) {
(entry.permission && !hasPermission(entry.permission))) {
interfaceMap[entry.name] = false;
} else {
interfaceMap[entry.name] = shouldExpect;
interfaceMap[entry.name] = true;
}
}
}
addInterfaces(ecmaGlobals, true);
addInterfaces(interfaceNamesInGlobalScope, true);
addInterfaces(ecmaGlobals);
addInterfaces(interfaceNamesInGlobalScope);
if (isXBLScope) {
// We expose QueryInterface to XBL scopes. It's not an interface but we
// need to handle it because it's an own property of the global and the
// property name starts with an uppercase letter.
interfaceMap["QueryInterface"] = true;
}
return interfaceMap;
}

View File

@ -88,6 +88,7 @@ TreeWalker implements LegacyQueryInterface;
UndoManager implements LegacyQueryInterface;
ValidityState implements LegacyQueryInterface;
WebSocket implements LegacyQueryInterface;
Window implements LegacyQueryInterface;
XMLHttpRequest implements LegacyQueryInterface;
XMLHttpRequestUpload implements LegacyQueryInterface;
XMLSerializer implements LegacyQueryInterface;

View File

@ -16,6 +16,7 @@
*/
interface ApplicationCache;
interface IID;
interface MozFrameRequestCallback;
interface nsIBrowserDOMWindow;
interface nsIMessageBroadcaster;
@ -336,6 +337,8 @@ partial interface Window {
[Replaceable, Throws] readonly attribute object? content;
[ChromeOnly, Throws] readonly attribute object? __content;
[Throws, ChromeOnly] any getInterface(IID iid);
};
Window implements TouchEventHandlers;