blob: 4757183085b16368e2aa3a607e2a13fa32e4278e [file] [log] [blame]
/*
Copyright 2011 WebDriver committers
Copyright 2011 Software Freedom Conservancy
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.
*/
goog.provide('fxdriver.moz');
goog.require('bot.userAgent');
goog.require('fxdriver.logging');
goog.require('goog.array');
/** @const */ var CC = Components.classes;
/** @const */ var CI = Components.interfaces;
/** @const */ var CR = Components.results;
/** @const */ var CU = Components.utils;
/**
* Import an existing jsm. We need this function because otherwise the closure
* compiler will choke on the 'import' method. *sigh*
*
* @param {string} module The full path to the module to import.
*/
fxdriver.moz.load = function(module) {
Components.utils['import']('resource://gre/modules/XPCOMUtils.jsm');
};
/**
* Obtain a new instance of an XPCOM service.
*
* @param {string} className The class name to look up.
* @param {string} serviceName The service name to obtain.
* @return {!object} The service.
*/
fxdriver.moz.getService = function(className, serviceName) {
var clazz = CC[className];
if (clazz == undefined) {
// TODO(simon): Replace this with a proper error
throw new Error('Cannot create component ' + className);
}
return clazz.getService(CI[serviceName]);
};
/**
* Create a default implementation of QueryInterface for an XPCOM class.
*
* @param {!object} self The instance which the method is being added to.
* @param {Array.<object>} iids The IIDs to use.
* @return {function(!object):!object} A QueryInterface implementation.
*/
fxdriver.moz.queryInterface = function(self, iids) {
return function(iid) {
if (!iid) {
return CR.NS_ERROR_NO_INTERFACE;
}
if (iid.equals(CI.nsISupports)) {
return self;
}
var match = goog.array.reduce(iids, function(result, curr) {
if (!curr) {
return result;
}
return result || curr.equals(iid);
}, false);
if (match) {
return self;
}
throw CR.NS_ERROR_NO_INTERFACE;
};
};
// This method closely follows unwrapNode() from mozmill-tests
/**
* Unwraps a something which is wrapped into a XPCNativeWrapper or XrayWrapper.
*
* @param {!Object} thing The "something" to unwrap.
* @return {!Object} The object, unwrapped if possible.
*/
fxdriver.moz.unwrap = function(thing) {
// TODO(simon): This is identical to the same function in firefox-chrome
if (!goog.isDefAndNotNull(thing)) {
return thing;
}
// If we've already unwrapped the object, don't unwrap it again.
// TODO(simon): see whether XPCWrapper->IsSecurityWrapper is available in JS
if (thing.__fxdriver_unwrapped) {
return thing;
}
if (thing['wrappedJSObject']) {
thing.wrappedJSObject.__fxdriver_unwrapped = true;
return thing.wrappedJSObject;
}
// unwrap is not available on older branches (3.5 and 3.6) - Bug 533596
try {
var isWrapper = thing == XPCNativeWrapper(thing);
if (isWrapper) {
var unwrapped = XPCNativeWrapper.unwrap(thing);
var toReturn = !!unwrapped ? unwrapped : thing;
toReturn.__fxdriver_unwrapped = true;
return toReturn;
}
} catch (e) {
// Unwrapping will fail for JS literals - numbers, for example. Catch
// the exception and proceed, it will eventually be returned as-is.
}
return thing;
};
/**
* For Firefox 4, some objects (like the Window) are wrapped to make them safe
* to access from privileged code but this hides fields we need, like the
* frames array. Remove this wrapping.
* See: https://developer.mozilla.org/en/XPCNativeWrapper
*/
fxdriver.moz.unwrapXpcOnly = function(thing) {
if (XPCNativeWrapper && 'unwrap' in XPCNativeWrapper) {
try {
return XPCNativeWrapper.unwrap(thing);
} catch (e) {
//Unwrapping will fail for JS literals - numbers, for example. Catch
// the exception and proceed, it will eventually be returend as-is.
fxdriver.logging.warning('Unwrap From XPC only failed: ' + e);
}
}
return thing;
};
fxdriver.moz.unwrapFor4 = function(doc) {
if (bot.userAgent.isProductVersion(4)) {
return fxdriver.moz.unwrap(doc);
}
return doc;
};