Merging mozilla-central with mozilla-inbound.

This commit is contained in:
Mounir Lamouri 2011-06-16 11:59:22 +02:00
commit e87fb91e76
31 changed files with 431 additions and 349 deletions

View File

@ -1081,6 +1081,9 @@ let TabItems = {
tab._tabViewTabItem.removeTrenches();
Items.unsquish(null, tab._tabViewTabItem);
tab._tabViewTabItem.tab = null;
tab._tabViewTabItem.tabCanvas.tab = null;
tab._tabViewTabItem.tabCanvas = null;
tab._tabViewTabItem = null;
Storage.saveTab(tab, null);

View File

@ -1405,6 +1405,7 @@ nsFrameLoader::MaybeCreateDocShell()
nsCOMPtr<nsISupports> container =
doc->GetContainer();
nsCOMPtr<nsIWebNavigation> parentAsWebNav = do_QueryInterface(container);
NS_ENSURE_STATE(parentAsWebNav);
// Create the docshell...
mDocShell = do_CreateInstance("@mozilla.org/docshell;1");
@ -1457,6 +1458,7 @@ nsFrameLoader::MaybeCreateDocShell()
// this some other way..... Not sure how yet.
nsCOMPtr<nsIDocShellTreeOwner> parentTreeOwner;
parentAsItem->GetTreeOwner(getter_AddRefs(parentTreeOwner));
NS_ENSURE_STATE(parentTreeOwner);
mIsTopLevelContent =
AddTreeItemToTreeOwner(docShellAsItem, mOwnerContent, parentTreeOwner,
parentType, parentAsNode);

View File

@ -657,12 +657,6 @@ struct JSRuntime {
#endif
#ifdef DEBUG
/* Function invocation metering. */
jsrefcount inlineCalls;
jsrefcount nativeCalls;
jsrefcount nonInlineCalls;
jsrefcount constructs;
/*
* NB: emptyShapes (in JSCompartment) is init'ed iff at least one
* of these envars is set:

View File

@ -295,14 +295,20 @@ IsFunctionObject(const js::Value &v, JSObject **funobj)
return v.isObject() && (*funobj = &v.toObject())->isFunction();
}
static JS_ALWAYS_INLINE bool
IsFunctionObject(const js::Value &v, JSObject **funobj, JSFunction **fun)
{
bool b = IsFunctionObject(v, funobj);
if (b)
*fun = (*funobj)->getFunctionPrivate();
return b;
}
static JS_ALWAYS_INLINE bool
IsFunctionObject(const js::Value &v, JSFunction **fun)
{
JSObject *funobj;
bool b = IsFunctionObject(v, &funobj);
if (b)
*fun = funobj->getFunctionPrivate();
return b;
return IsFunctionObject(v, &funobj, fun);
}
static JS_ALWAYS_INLINE bool

View File

@ -1212,7 +1212,6 @@ InvokeConstructor(JSContext *cx, const CallArgs &argsRef)
return false;
JS_ASSERT(args.rval().isObject());
JS_RUNTIME_METER(cx->runtime, constructs);
return true;
}
if (clasp->construct) {
@ -4519,153 +4518,90 @@ BEGIN_CASE(JSOP_ENUMELEM)
}
END_CASE(JSOP_ENUMELEM)
{ // begin block around calling opcodes
JSFunction *newfun;
JSObject *callee;
MaybeConstruct construct;
CallArgs args;
BEGIN_CASE(JSOP_NEW)
{
args = CallArgsFromSp(GET_ARGC(regs.pc), regs.sp);
JS_ASSERT(args.base() >= regs.fp()->base());
if (IsFunctionObject(args.calleev(), &callee)) {
newfun = callee->getFunctionPrivate();
if (newfun->isInterpretedConstructor()) {
if (newfun->script()->isEmpty()) {
JSObject *rval = js_CreateThisForFunction(cx, callee);
if (!rval)
goto error;
args.rval().setObject(*rval);
regs.sp = args.spAfterCall();
goto end_new;
}
construct = CONSTRUCT;
goto inline_call;
}
}
if (!InvokeConstructor(cx, args))
goto error;
regs.sp = args.spAfterCall();
CHECK_INTERRUPT_HANDLER();
TRACE_0(NativeCallComplete);
end_new:;
}
END_CASE(JSOP_NEW)
BEGIN_CASE(JSOP_EVAL)
{
args = CallArgsFromSp(GET_ARGC(regs.pc), regs.sp);
if (!IsBuiltinEvalForScope(&regs.fp()->scopeChain(), args.calleev()))
goto call_using_invoke;
if (!DirectEval(cx, args))
goto error;
CallArgs args = CallArgsFromSp(GET_ARGC(regs.pc), regs.sp);
if (IsBuiltinEvalForScope(&regs.fp()->scopeChain(), args.calleev())) {
if (!DirectEval(cx, args))
goto error;
} else {
if (!Invoke(cx, args))
goto error;
}
CHECK_INTERRUPT_HANDLER();
regs.sp = args.spAfterCall();
}
END_CASE(JSOP_EVAL)
BEGIN_CASE(JSOP_NEW)
BEGIN_CASE(JSOP_CALL)
BEGIN_CASE(JSOP_FUNAPPLY)
BEGIN_CASE(JSOP_FUNCALL)
BEGIN_CASE(JSOP_FUNAPPLY)
{
CallArgs args = CallArgsFromSp(GET_ARGC(regs.pc), regs.sp);
JS_ASSERT(args.base() >= regs.fp()->base());
args = CallArgsFromSp(GET_ARGC(regs.pc), regs.sp);
MaybeConstruct construct = *regs.pc == JSOP_NEW ? CONSTRUCT : NO_CONSTRUCT;
if (IsFunctionObject(args.calleev(), &callee)) {
newfun = callee->getFunctionPrivate();
/* Clear frame flag since this is not a constructor call. */
construct = NO_CONSTRUCT;
if (newfun->isInterpreted())
inline_call:
{
JSScript *newscript = newfun->script();
if (JS_UNLIKELY(newscript->isEmpty())) {
args.rval().setUndefined();
regs.sp = args.spAfterCall();
goto end_call;
}
/* Push frame on the stack. */
if (!cx->stack.pushInlineFrame(cx, regs, args, *callee, newfun,
newscript, construct, OOMCheck())) {
JSObject *callee;
JSFunction *fun;
if (!IsFunctionObject(args.calleev(), &callee, &fun) || !fun->isInterpretedConstructor()) {
if (construct) {
if (!InvokeConstructor(cx, args))
goto error;
}
/* Refresh interpreter locals. */
script = newscript;
pcCounts = script->pcCounters.get(JSRUNMODE_INTERP);
argv = regs.fp()->formalArgsEnd() - newfun->nargs;
atoms = script->atomMap.vector;
/* Now that the new frame is rooted, maybe create a call object. */
if (newfun->isHeavyweight() && !CreateFunCallObject(cx, regs.fp()))
} else {
if (!Invoke(cx, args))
goto error;
RESET_USE_METHODJIT();
JS_RUNTIME_METER(rt, inlineCalls);
TRACE_0(EnterFrame);
CHECK_INTERRUPT_HANDLER();
#ifdef JS_METHODJIT
/* Try to ensure methods are method JIT'd. */
mjit::CompileRequest request = (interpMode == JSINTERP_NORMAL)
? mjit::CompileRequest_Interpreter
: mjit::CompileRequest_JIT;
mjit::CompileStatus status = mjit::CanMethodJIT(cx, script, regs.fp(), request);
if (status == mjit::Compile_Error)
goto error;
if (!TRACE_RECORDER(cx) && !TRACE_PROFILER(cx) && status == mjit::Compile_Okay) {
interpReturnOK = mjit::JaegerShot(cx);
CHECK_INTERRUPT_HANDLER();
goto jit_return;
}
#endif
if (!ScriptPrologue(cx, regs.fp()))
goto error;
CHECK_INTERRUPT_HANDLER();
/* Load first op and dispatch it (safe since JSOP_STOP). */
op = (JSOp) *regs.pc;
DO_OP();
}
Probes::enterJSFun(cx, newfun, script);
JSBool ok = CallJSNative(cx, newfun->u.n.native, args);
Probes::exitJSFun(cx, newfun, script);
regs.sp = args.spAfterCall();
if (!ok)
goto error;
CHECK_INTERRUPT_HANDLER();
TRACE_0(NativeCallComplete);
goto end_call;
len = JSOP_CALL_LENGTH;
DO_NEXT_OP(len);
}
call_using_invoke:
bool ok;
ok = Invoke(cx, args);
regs.sp = args.spAfterCall();
CHECK_INTERRUPT_HANDLER();
if (!ok)
script = fun->script();
if (!cx->stack.pushInlineFrame(cx, regs, args, *callee, fun, script, construct, OOMCheck()))
goto error;
JS_RUNTIME_METER(rt, nonInlineCalls);
TRACE_0(NativeCallComplete);
end_call:;
/* Refresh local js::Interpret state. */
pcCounts = script->pcCounters.get(JSRUNMODE_INTERP);
argv = regs.fp()->formalArgsEnd() - fun->nargs;
atoms = script->atomMap.vector;
/* Only create call object after frame is rooted. */
if (fun->isHeavyweight() && !CreateFunCallObject(cx, regs.fp()))
goto error;
RESET_USE_METHODJIT();
TRACE_0(EnterFrame);
#ifdef JS_METHODJIT
{
/* Try to ensure methods are method JIT'd. */
mjit::CompileRequest request = (interpMode == JSINTERP_NORMAL)
? mjit::CompileRequest_Interpreter
: mjit::CompileRequest_JIT;
mjit::CompileStatus status = mjit::CanMethodJIT(cx, script, regs.fp(), request);
if (status == mjit::Compile_Error)
goto error;
if (!TRACE_RECORDER(cx) && !TRACE_PROFILER(cx) && status == mjit::Compile_Okay) {
interpReturnOK = mjit::JaegerShot(cx);
CHECK_INTERRUPT_HANDLER();
goto jit_return;
}
}
#endif
if (!ScriptPrologue(cx, regs.fp()))
goto error;
CHECK_INTERRUPT_HANDLER();
/* Load first op and dispatch it (safe since JSOP_STOP). */
op = (JSOp) *regs.pc;
DO_OP();
}
END_CASE(JSOP_CALL)
} // end block around calling opcodes
BEGIN_CASE(JSOP_SETCALL)
{

View File

@ -371,7 +371,6 @@ ScriptEpilogue(JSContext *cx, StackFrame *fp, bool ok)
if (fp->isConstructing() && ok) {
if (fp->returnValue().isPrimitive())
fp->setReturnValue(ObjectValue(fp->constructorThis()));
JS_RUNTIME_METER(cx->runtime, constructs);
}
return ok;

View File

@ -13672,22 +13672,6 @@ TraceRecorder::createThis(JSObject& ctor, LIns* ctor_ins, LIns** thisobj_insp)
JS_REQUIRES_STACK RecordingStatus
TraceRecorder::interpretedFunctionCall(Value& fval, JSFunction* fun, uintN argc, bool constructing)
{
/*
* The function's identity (JSFunction and therefore JSScript) is guarded,
* so we can optimize away the function call if the corresponding script is
* empty. No need to worry about crossing globals or relocating argv, even,
* in this case!
*/
if (fun->script()->isEmpty()) {
LIns* rval_ins;
if (constructing)
CHECK_STATUS(createThis(fval.toObject(), get(&fval), &rval_ins));
else
rval_ins = w.immiUndefined();
stack(-2 - argc, rval_ins);
return RECORD_CONTINUE;
}
if (fval.toObject().getGlobal() != globalObj)
RETURN_STOP("JSOP_CALL or JSOP_NEW crosses global scopes");

View File

@ -48,14 +48,14 @@ struct JSObject;
[ptr] native JSObjectPtr(JSObject);
[scriptable, uuid(89da3673-e699-4f26-9ed7-11a528011434)]
[scriptable, uuid(3f945a8e-58ca-47ba-a789-82d022e837fd)]
interface xpcIJSModuleLoader : nsISupports
{
/**
* To be called from JavaScript only.
*
* Synchronously loads and evaluates the js file located at
* 'registryLocation' with a new, fully privileged global object.
* aResourceURI with a new, fully privileged global object.
*
* If 'targetObj' is specified and equal to null, returns the
* module's global object. Otherwise (if 'targetObj' is not
@ -85,11 +85,19 @@ interface xpcIJSModuleLoader : nsISupports
/* , [optional] in JSObject targetObj */);
/**
* Imports the JS module at 'registryLocation' to the JS object
* Imports the JS module at aResourceURI to the JS object
* 'targetObj' (if != null) as described for importModule() and
* returns the module's global object.
*/
[noscript] JSObjectPtr importInto(in AUTF8String aResourceURI,
in JSObjectPtr targetObj,
in nsAXPCNativeCallContextPtr cc);
/**
* Unloads the JS module at aResourceURI. Existing references to the module
* will continue to work but any subsequent import of the module will
* reload it and give new reference. If the JS module hasn't yet been imported
* then this method will do nothing.
*/
void unload(in AUTF8String aResourceURI);
};

View File

@ -123,7 +123,7 @@ interface nsIXPCComponents_utils_Sandbox : nsISupports
/**
* interface of Components.utils
*/
[scriptable, uuid(c1d616fa-1875-49ba-b7b8-5861dab31a42)]
[scriptable, uuid(5f0acf45-135a-48d1-976c-082ce3b24ead)]
interface nsIXPCComponents_Utils : nsISupports
{
@ -204,6 +204,16 @@ interface nsIXPCComponents_Utils : nsISupports
void /* JSObject */ import(in AUTF8String registryLocation
/*, [optional] in JSObject targetObj */);
/*
* Unloads the JS module at 'registryLocation'. Existing references to the
* module will continue to work but any subsequent import of the module will
* reload it and give new reference. If the JS module hasn't yet been
* imported then this method will do nothing.
*
* @param resourceURI A resource:// URI string to unload the module from.
*/
void unload(in AUTF8String registryLocation);
/*
* To be called from JS only.
*

View File

@ -1479,6 +1479,76 @@ mozJSComponentLoader::ImportInto(const nsACString & aLocation,
return NS_OK;
}
NS_IMETHODIMP
mozJSComponentLoader::Unload(const nsACString & aLocation)
{
nsresult rv;
if (!mInitialized) {
return NS_OK;
}
nsCOMPtr<nsIIOService> ioService = do_GetIOService(&rv);
NS_ENSURE_SUCCESS(rv, rv);
// Get the URI.
nsCOMPtr<nsIURI> resURI;
rv = ioService->NewURI(aLocation, nsnull, nsnull, getter_AddRefs(resURI));
NS_ENSURE_SUCCESS(rv, rv);
// figure out the resolved URI
nsCOMPtr<nsIChannel> scriptChannel;
rv = ioService->NewChannelFromURI(resURI, getter_AddRefs(scriptChannel));
NS_ENSURE_SUCCESS(rv, NS_ERROR_INVALID_ARG);
nsCOMPtr<nsIURI> resolvedURI;
rv = scriptChannel->GetURI(getter_AddRefs(resolvedURI));
NS_ENSURE_SUCCESS(rv, rv);
// get the JAR if there is one
nsCOMPtr<nsIJARURI> jarURI;
jarURI = do_QueryInterface(resolvedURI, &rv);
nsCOMPtr<nsIFileURL> baseFileURL;
nsCAutoString jarEntry;
if (NS_SUCCEEDED(rv)) {
nsCOMPtr<nsIURI> baseURI;
rv = jarURI->GetJARFile(getter_AddRefs(baseURI));
NS_ENSURE_SUCCESS(rv, rv);
baseFileURL = do_QueryInterface(baseURI, &rv);
NS_ENSURE_SUCCESS(rv, rv);
jarURI->GetJAREntry(jarEntry);
NS_ENSURE_SUCCESS(rv, rv);
} else {
baseFileURL = do_QueryInterface(resolvedURI, &rv);
NS_ENSURE_SUCCESS(rv, rv);
}
nsCOMPtr<nsIFile> sourceFile;
rv = baseFileURL->GetFile(getter_AddRefs(sourceFile));
NS_ENSURE_SUCCESS(rv, rv);
nsCOMPtr<nsILocalFile> sourceLocalFile;
sourceLocalFile = do_QueryInterface(sourceFile, &rv);
NS_ENSURE_SUCCESS(rv, rv);
nsAutoString key;
if (jarEntry.IsEmpty()) {
rv = FileKey(sourceLocalFile, key);
} else {
rv = JarKey(sourceLocalFile, jarEntry, key);
}
NS_ENSURE_SUCCESS(rv, rv);
ModuleEntry* mod;
if (mImports.Get(key, &mod)) {
mImports.Remove(key);
}
return NS_OK;
}
NS_IMETHODIMP
mozJSComponentLoader::Observe(nsISupports *subject, const char *topic,
const PRUnichar *data)

View File

@ -3725,6 +3725,18 @@ nsXPCComponents_Utils::Import(const nsACString & registryLocation)
return moduleloader->Import(registryLocation);
}
/* unload (in AUTF8String registryLocation);
*/
NS_IMETHODIMP
nsXPCComponents_Utils::Unload(const nsACString & registryLocation)
{
nsCOMPtr<xpcIJSModuleLoader> moduleloader =
do_GetService(MOZJSCOMPONENTLOADER_CONTRACTID);
if (!moduleloader)
return NS_ERROR_FAILURE;
return moduleloader->Unload(registryLocation);
}
/* xpcIJSWeakReference getWeakReference (); */
NS_IMETHODIMP
nsXPCComponents_Utils::GetWeakReference(xpcIJSWeakReference **_retval)

View File

@ -0,0 +1,65 @@
/*
* ***** BEGIN LICENSE BLOCK *****
* Version: MPL 1.1/GPL 2.0/LGPL 2.1
*
* The contents of this file are subject to the Mozilla Public License Version
* 1.1 (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.mozilla.org/MPL/
*
* Software distributed under the License is distributed on an "AS IS" basis,
* WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
* for the specific language governing rights and limitations under the
* License.
*
* The Original Code is Mozilla code.
*
* The Initial Developer of the Original Code is
* Mozilla Foundation.
* Portions created by the Initial Developer are Copyright (C) 2011
* the Initial Developer. All Rights Reserved.
*
* Contributor(s):
* Dave Townsend <dtownsend@oxymoronical.com> (original author)
*
* Alternatively, the contents of this file may be used under the terms of
* either the GNU General Public License Version 2 or later (the "GPL"), or
* the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
* in which case the provisions of the GPL or the LGPL are applicable instead
* of those above. If you wish to allow use of your version of this file only
* under the terms of either the GPL or the LGPL, and not to allow others to
* use your version of this file under the terms of the MPL, indicate your
* decision by deleting the provisions above and replace them with the notice
* and other provisions required by the GPL or the LGPL. If you do not delete
* the provisions above, a recipient may use your version of this file under
* the terms of any one of the MPL, the GPL or the LGPL.
*
* ***** END LICENSE BLOCK ***** */
function run_test() {
var scope1 = {};
var global1 = Components.utils.import("resource://gre/modules/NetUtil.jsm", scope1);
var scope2 = {};
var global2 = Components.utils.import("resource://gre/modules/NetUtil.jsm", scope2);
do_check_true(global1 === global2);
do_check_true(scope1.NetUtil === scope2.NetUtil);
Components.utils.unload("resource://gre/modules/NetUtil.jsm");
var scope3 = {};
var global3 = Components.utils.import("resource://gre/modules/NetUtil.jsm", scope3);
do_check_false(global1 === global3);
do_check_false(scope1.NetUtil === scope3.NetUtil);
// Both instances should work
uri1 = scope1.NetUtil.newURI("http://www.example.com");
do_check_true(uri1 instanceof Components.interfaces.nsIURL);
var uri3 = scope3.NetUtil.newURI("http://www.example.com");
do_check_true(uri3 instanceof Components.interfaces.nsIURL);
do_check_true(uri1.equals(uri3));
}

View File

@ -15,3 +15,4 @@ tail =
[test_localeCompare.js]
[test_recursive_import.js]
[test_xpcomutils.js]
[test_unload.js]

View File

@ -82,7 +82,7 @@ DEFINES += -DSHARED_LIBRARY=$(SHARED_LIBRARY) -DNOMINMAX
ifneq (mobile,$(MOZ_BUILD_APP))
_BROWSER_FILES = \
browser/aboutcrashes_utils.js \
browser/head.js \
browser/crashreport.sjs \
browser/browser_aboutCrashes.js \
browser/browser_bug471404.js \

View File

@ -1,10 +1,3 @@
// load our utility script
var scriptLoader = Components.classes["@mozilla.org/moz/jssubscript-loader;1"]
.getService(Components.interfaces.mozIJSSubScriptLoader);
var rootDir = getRootDirectory(gTestPath);
scriptLoader.loadSubScript(rootDir + "aboutcrashes_utils.js", this);
function check_crash_list(tab, crashes) {
let doc = gBrowser.getBrowserForTab(tab).contentDocument;
let crashlinks = doc.getElementById("tbody").getElementsByTagName("a");

View File

@ -1,10 +1,3 @@
// load our utility script
var scriptLoader = Components.classes["@mozilla.org/moz/jssubscript-loader;1"]
.getService(Components.interfaces.mozIJSSubScriptLoader);
var rootDir = getRootDirectory(gTestPath);
scriptLoader.loadSubScript(rootDir + "aboutcrashes_utils.js", this);
function cleanup_and_finish() {
try {
cleanup_fake_appdir();

View File

@ -1,10 +1,3 @@
// load our utility script
var scriptLoader = Components.classes["@mozilla.org/moz/jssubscript-loader;1"]
.getService(Components.interfaces.mozIJSSubScriptLoader);
var rootDir = getRootDirectory(gTestPath);
scriptLoader.loadSubScript(rootDir + "aboutcrashes_utils.js", this);
function check_clear_visible(tab, aVisible) {
let doc = gBrowser.getBrowserForTab(tab).contentDocument;
let visible = false;

View File

@ -1,6 +1,3 @@
const Cc = Components.classes;
const Ci = Components.interfaces;
function create_subdir(dir, subdirname) {
let subdir = dir.clone();
subdir.append(subdirname);

View File

@ -906,6 +906,33 @@ function loadManifestFromFile(aFile) {
return loadManifestFromDir(aFile);
}
/**
* Gets an nsIURI for a file within another file, either a directory or an XPI
* file. If aFile is a directory then this will return a file: URI, if it is an
* XPI file then it will return a jar: URI.
*
* @param aFile
* The file containing the resources, must be either a directory or an
* XPI file
* @param aPath
* The path to find the resource at, "/" separated. If aPath is empty
* then the uri to the root of the contained files will be returned
* @return an nsIURI pointing at the resource
*/
function getURIForResourceInFile(aFile, aPath) {
if (aFile.isDirectory()) {
let resource = aFile.clone();
if (aPath) {
aPath.split("/").forEach(function(aPart) {
resource.append(aPart);
});
}
return NetUtil.newURI(resource);
}
return buildJarURI(aFile, aPath);
}
/**
* Creates a jar: URI for a file inside a ZIP file.
*
@ -933,6 +960,12 @@ function flushJarCache(aJarFile) {
.sendAsyncMessage(MSG_JAR_FLUSH, aJarFile.path);
}
function flushStartupCache() {
// Init this, so it will get the notification.
Cc["@mozilla.org/xul/xul-prototype-cache;1"].getService(Ci.nsISupports);
Services.obs.notifyObservers(null, "startupcache-invalidate", null);
}
/**
* Creates and returns a new unique temporary file. The caller should delete
* the file when it is no longer needed.
@ -1565,9 +1598,7 @@ var XPIProvider = {
}
if (flushCaches) {
// Init this, so it will get the notification.
let xulPrototypeCache = Cc["@mozilla.org/xul/xul-prototype-cache;1"].getService(Ci.nsISupports);
Services.obs.notifyObservers(null, "startupcache-invalidate", null);
flushStartupCache();
// UI displayed early in startup (like the compatibility UI) may have
// caused us to cache parts of the skin or locale in memory. These must
@ -1989,6 +2020,7 @@ var XPIProvider = {
this.callBootstrapMethod(existingAddonID, oldBootstrap.version,
existingAddon, "uninstall", uninstallReason);
this.unloadBootstrapScope(existingAddonID);
flushStartupCache();
}
}
catch (e) {
@ -2259,6 +2291,9 @@ var XPIProvider = {
// If the new add-on is bootstrapped and active then call its install method
if (newAddon.active && newAddon.bootstrap) {
// Startup cache must be flushed before calling the bootstrap script
flushStartupCache();
let installReason = Services.vc.compare(aOldAddon.version, newAddon.version) < 0 ?
BOOTSTRAP_REASONS.ADDON_UPGRADE :
BOOTSTRAP_REASONS.ADDON_DOWNGRADE;
@ -2270,7 +2305,6 @@ var XPIProvider = {
return false;
}
// Otherwise the caches will need to be invalidated
return true;
}
@ -2445,9 +2479,7 @@ var XPIProvider = {
if (aOldAddon.type == "theme")
XPIProvider.enableDefaultTheme();
// If this was not a bootstrapped add-on then we must force a restart.
if (!aOldAddon.bootstrap)
return true;
return true;
}
return false;
@ -2586,10 +2618,16 @@ var XPIProvider = {
let oldAddonFile = Cc["@mozilla.org/file/local;1"].
createInstance(Ci.nsILocalFile);
oldAddonFile.persistentDescriptor = oldBootstrap.descriptor;
XPIProvider.callBootstrapMethod(newAddon.id, oldBootstrap.version,
oldAddonFile, "uninstall",
installReason);
XPIProvider.unloadBootstrapScope(newAddon.id);
// If the new add-on is bootstrapped then we must flush the caches
// before calling the new bootstrap script
if (newAddon.bootstrap)
flushStartupCache();
}
if (!newAddon.bootstrap)
@ -3355,47 +3393,32 @@ var XPIProvider = {
createInstance(Ci.nsIPrincipal);
this.bootstrapScopes[aId] = new Components.utils.Sandbox(principal);
let bootstrap = aFile.clone();
let name = aFile.leafName;
let spec;
if (!bootstrap.exists()) {
if (!aFile.exists()) {
ERROR("Attempted to load bootstrap scope from missing directory " + bootstrap.path);
return;
}
if (bootstrap.isDirectory()) {
bootstrap.append("bootstrap.js");
let uri = Services.io.newFileURI(bootstrap);
spec = uri.spec;
} else {
spec = buildJarURI(bootstrap, "bootstrap.js").spec;
}
if (bootstrap.exists()) {
let loader = Cc["@mozilla.org/moz/jssubscript-loader;1"].
createInstance(Ci.mozIJSSubScriptLoader);
let loader = Cc["@mozilla.org/moz/jssubscript-loader;1"].
createInstance(Ci.mozIJSSubScriptLoader);
try {
// As we don't want our caller to control the JS version used for the
// bootstrap file, we run loadSubScript within the context of the
// sandbox with the latest JS version set explicitly.
this.bootstrapScopes[aId].__SCRIPT_URI_SPEC__ = spec;
Components.utils.evalInSandbox(
"Components.classes['@mozilla.org/moz/jssubscript-loader;1'] \
.createInstance(Components.interfaces.mozIJSSubScriptLoader) \
.loadSubScript(__SCRIPT_URI_SPEC__);", this.bootstrapScopes[aId], "ECMAv5");
}
catch (e) {
WARN("Error loading bootstrap.js for " + aId, e);
}
try {
// As we don't want our caller to control the JS version used for the
// bootstrap file, we run loadSubScript within the context of the
// sandbox with the latest JS version set explicitly.
this.bootstrapScopes[aId].__SCRIPT_URI_SPEC__ =
getURIForResourceInFile(aFile, "bootstrap.js").spec;
Components.utils.evalInSandbox(
"Components.classes['@mozilla.org/moz/jssubscript-loader;1'] \
.createInstance(Components.interfaces.mozIJSSubScriptLoader) \
.loadSubScript(__SCRIPT_URI_SPEC__);", this.bootstrapScopes[aId], "ECMAv5");
}
catch (e) {
WARN("Error loading bootstrap.js for " + aId, e);
}
// Copy the reason values from the global object into the bootstrap scope.
for (let name in BOOTSTRAP_REASONS)
this.bootstrapScopes[aId][name] = BOOTSTRAP_REASONS[name];
}
else {
WARN("Bootstrap missing for " + aId);
}
// Copy the reason values from the global object into the bootstrap scope.
for (let name in BOOTSTRAP_REASONS)
this.bootstrapScopes[aId][name] = BOOTSTRAP_REASONS[name];
},
/**
@ -3443,7 +3466,8 @@ var XPIProvider = {
let params = {
id: aId,
version: aVersion,
installPath: aFile.clone()
installPath: aFile.clone(),
resourceURI: getURIForResourceInFile(aFile, "")
};
LOG("Calling bootstrap method " + aMethod + " on " + aId + " version " +
@ -3623,9 +3647,11 @@ var XPIProvider = {
this.callBootstrapMethod(aAddon.id, aAddon.version, file, "shutdown",
BOOTSTRAP_REASONS.ADDON_UNINSTALL);
}
this.callBootstrapMethod(aAddon.id, aAddon.version, file, "uninstall",
BOOTSTRAP_REASONS.ADDON_UNINSTALL);
this.unloadBootstrapScope(aAddon.id);
flushStartupCache();
}
aAddon._installLocation.uninstallAddon(aAddon.id);
XPIDatabase.removeAddonMetadata(aAddon);
@ -6216,10 +6242,12 @@ AddonInstall.prototype = {
this.existingAddon.version,
file, "shutdown", reason);
}
XPIProvider.callBootstrapMethod(this.existingAddon.id,
this.existingAddon.version,
file, "uninstall", reason);
XPIProvider.unloadBootstrapScope(this.existingAddon.id);
flushStartupCache();
}
if (!isUpgrade && this.existingAddon.active) {
@ -7210,21 +7238,22 @@ function AddonWrapper(aAddon) {
return result;
},
/**
* Returns a URI to the selected resource or to the add-on bundle if aPath
* is null. URIs to the bundle will always be file: URIs. URIs to resources
* will be file: URIs if the add-on is unpacked or jar: URIs if the add-on is
* still an XPI file.
*
* @param aPath
* The path in the add-on to get the URI for or null to get a URI to
* the file or directory the add-on is installed as.
* @return an nsIURI
*/
this.getResourceURI = function(aPath) {
let bundle = aAddon._sourceBundle.clone();
if (bundle.isDirectory()) {
if (aPath) {
aPath.split("/").forEach(function(aPart) {
bundle.append(aPart);
});
}
return Services.io.newFileURI(bundle);
}
if (!aPath)
return Services.io.newFileURI(bundle);
return buildJarURI(bundle, aPath);
return NetUtil.newURI(aAddon._sourceBundle);
return getURIForResourceInFile(aAddon._sourceBundle, aPath);
}
}

View File

@ -1,13 +1,17 @@
Components.utils.import("resource://gre/modules/Services.jsm");
function install(data, reason) {
Services.prefs.setIntPref("bootstraptest.installed_version", 1);
Components.utils.import(data.resourceURI.spec + "version.jsm");
Services.prefs.setIntPref("bootstraptest.installed_version", VERSION);
Services.prefs.setIntPref("bootstraptest.install_reason", reason);
Components.utils.unload(data.resourceURI.spec + "version.jsm");
}
function startup(data, reason) {
Services.prefs.setIntPref("bootstraptest.active_version", 1);
Components.utils.import(data.resourceURI.spec + "version.jsm");
Services.prefs.setIntPref("bootstraptest.active_version", VERSION);
Services.prefs.setIntPref("bootstraptest.startup_reason", reason);
Components.utils.unload(data.resourceURI.spec + "version.jsm");
}
function shutdown(data, reason) {

View File

@ -0,0 +1,3 @@
var EXPORTED_SYMBOLS = ["VERSION"];
var VERSION = 1;

View File

@ -1,13 +1,17 @@
Components.utils.import("resource://gre/modules/Services.jsm");
function install(data, reason) {
Services.prefs.setIntPref("bootstraptest.installed_version", 2);
Components.utils.import(data.resourceURI.spec + "version.jsm");
Services.prefs.setIntPref("bootstraptest.installed_version", VERSION);
Services.prefs.setIntPref("bootstraptest.install_reason", reason);
Components.utils.unload(data.resourceURI.spec + "version.jsm");
}
function startup(data, reason) {
Services.prefs.setIntPref("bootstraptest.active_version", 2);
Components.utils.import(data.resourceURI.spec + "version.jsm");
Services.prefs.setIntPref("bootstraptest.active_version", VERSION);
Services.prefs.setIntPref("bootstraptest.startup_reason", reason);
Components.utils.unload(data.resourceURI.spec + "version.jsm");
}
function shutdown(data, reason) {

View File

@ -0,0 +1,3 @@
var EXPORTED_SYMBOLS = ["VERSION"];
var VERSION = 2;

View File

@ -1,13 +1,17 @@
Components.utils.import("resource://gre/modules/Services.jsm");
function install(data, reason) {
Services.prefs.setIntPref("bootstraptest.installed_version", 3);
Components.utils.import(data.resourceURI.spec + "version.jsm");
Services.prefs.setIntPref("bootstraptest.installed_version", VERSION);
Services.prefs.setIntPref("bootstraptest.install_reason", reason);
Components.utils.unload(data.resourceURI.spec + "version.jsm");
}
function startup(data, reason) {
Services.prefs.setIntPref("bootstraptest.active_version", 3);
Components.utils.import(data.resourceURI.spec + "version.jsm");
Services.prefs.setIntPref("bootstraptest.active_version", VERSION);
Services.prefs.setIntPref("bootstraptest.startup_reason", reason);
Components.utils.unload(data.resourceURI.spec + "version.jsm");
}
function shutdown(data, reason) {

View File

@ -0,0 +1,3 @@
var EXPORTED_SYMBOLS = ["VERSION"];
var VERSION = 3;

View File

@ -6,7 +6,6 @@
* Tests that history navigation works for the add-ons manager.
*/
const PREF_DISCOVERURL = "extensions.webservice.discoverURL";
const MAIN_URL = "https://example.com/" + RELATIVE_DIR + "discovery.html";
const SECOND_URL = "https://example.com/" + RELATIVE_DIR + "releaseNotes.xhtml";
@ -58,9 +57,6 @@ function test() {
waitForExplicitFinish();
Services.prefs.setCharPref(PREF_DISCOVERURL, MAIN_URL);
registerCleanupFunction(function() {
Services.prefs.clearUserPref(PREF_DISCOVERURL);
});
var gProvider = new MockProvider();
gProvider.createAddons([{

View File

@ -5,7 +5,6 @@
// Tests that the discovery view loads properly
const PREF_GETADDONS_CACHE_ENABLED = "extensions.getAddons.cache.enabled";
const PREF_DISCOVERURL = "extensions.webservice.discoverURL";
const MAIN_URL = "https://example.com/" + RELATIVE_DIR + "discovery.html";
var gManagerWindow;
@ -36,15 +35,12 @@ var gProgressListener = {
};
function test() {
var currentURL = Services.prefs.getCharPref(PREF_DISCOVERURL);
// Switch to a known url
Services.prefs.setCharPref(PREF_DISCOVERURL, MAIN_URL);
// Temporarily enable caching
Services.prefs.setBoolPref(PREF_GETADDONS_CACHE_ENABLED, true);
registerCleanupFunction(function() {
Services.prefs.setCharPref(PREF_DISCOVERURL, currentURL);
Services.prefs.setBoolPref(PREF_GETADDONS_CACHE_ENABLED, false);
});

View File

@ -19,6 +19,7 @@ const RELATIVE_DIR = pathParts.slice(4).join("/") + "/";
const TESTROOT = "http://example.com/" + RELATIVE_DIR;
const TESTROOT2 = "http://example.org/" + RELATIVE_DIR;
const CHROMEROOT = pathParts.join("/") + "/";
const PREF_DISCOVERURL = "extensions.webservice.discoverURL";
const MANAGER_URI = "about:addons";
const INSTALL_URI = "chrome://mozapps/content/xpinstall/xpinstallConfirm.xul";
@ -31,6 +32,8 @@ var gTestStart = null;
var gUseInContentUI = !gTestInWindow && ("switchToTabHavingURI" in window);
var gDiscoveryURL = Services.prefs.getCharPref(PREF_DISCOVERURL);
// Turn logging on for all tests
Services.prefs.setBoolPref(PREF_LOGGING_ENABLED, true);
// Turn off remote results in searches
@ -43,6 +46,8 @@ registerCleanupFunction(function() {
catch (e) {
}
Services.prefs.setCharPref(PREF_DISCOVERURL, gDiscoveryURL);
// Throw an error if the add-ons manager window is open anywhere
var windows = Services.wm.getEnumerator("Addons:Manager");
if (windows.hasMoreElements())

View File

@ -1 +1,2 @@
Services.prefs.setBoolPref("extensions.alwaysUnpack", true);
TEST_UNPACKED = true;

View File

@ -19,6 +19,8 @@ var gInternalManager = null;
var gAppInfo = null;
var gAddonsList;
var TEST_UNPACKED = false;
function createAppInfo(id, name, version, platformVersion) {
gAppInfo = {
// nsIXULAppInfo
@ -161,7 +163,7 @@ function do_get_addon_root_uri(aProfileDir, aId) {
}
function do_get_expected_addon_name(aId) {
if (Services.prefs.getBoolPref("extensions.alwaysUnpack"))
if (TEST_UNPACKED)
return aId;
return aId + ".xpi";
}
@ -569,7 +571,7 @@ function writeInstallRDFForExtension(aData, aDir, aId, aExtraFile) {
var dir = aDir.clone();
if (Services.prefs.getBoolPref("extensions.alwaysUnpack")) {
if (TEST_UNPACKED) {
dir.append(id);
writeInstallRDFToDir(aData, dir, aExtraFile);
return dir;

View File

@ -73,6 +73,46 @@ function getUninstallReason() {
return Services.prefs.getIntPref("bootstraptest.uninstall_reason");
}
function manuallyInstall(aXPIFile, aInstallLocation, aID) {
if (TEST_UNPACKED) {
let dir = aInstallLocation.clone();
dir.append(aID);
dir.create(AM_Ci.nsIFile.DIRECTORY_TYPE, 0755);
let zip = AM_Cc["@mozilla.org/libjar/zip-reader;1"].
createInstance(AM_Ci.nsIZipReader);
zip.open(aXPIFile);
let entries = zip.findEntries(null);
while (entries.hasMore()) {
let entry = entries.getNext();
let target = dir.clone();
entry.split("/").forEach(function(aPart) {
target.append(aPart);
});
zip.extract(entry, target);
}
zip.close();
return dir;
}
else {
let target = aInstallLocation.clone();
target.append(aID + ".xpi");
aXPIFile.copyTo(target.parent, target.leafName);
return target;
}
}
function manuallyUninstall(aInstallLocation, aID) {
let file = getFileForAddon(aInstallLocation, aID);
// In reality because the app is restarted a flush isn't necessary for XPIs
// removed outside the app, but for testing we must flush manually.
if (file.isFile())
Services.obs.notifyObservers(file, "flush-cache-entry", null);
file.remove(true);
}
function run_test() {
do_test_pending();
@ -369,18 +409,8 @@ function check_test_7() {
function run_test_8() {
shutdownManager();
let dir = profileDir.clone();
dir.append("bootstrap1@tests.mozilla.org");
dir.create(AM_Ci.nsIFile.DIRECTORY_TYPE, 0755);
let zip = AM_Cc["@mozilla.org/libjar/zip-reader;1"].
createInstance(AM_Ci.nsIZipReader);
zip.open(do_get_addon("test_bootstrap1_1"));
dir.append("install.rdf");
zip.extract("install.rdf", dir);
dir = dir.parent;
dir.append("bootstrap.js");
zip.extract("bootstrap.js", dir);
zip.close();
manuallyInstall(do_get_addon("test_bootstrap1_1"), profileDir,
"bootstrap1@tests.mozilla.org");
startupManager(false);
@ -403,9 +433,8 @@ function run_test_8() {
function run_test_9() {
shutdownManager();
let dir = profileDir.clone();
dir.append("bootstrap1@tests.mozilla.org");
dir.remove(true);
manuallyUninstall(profileDir, "bootstrap1@tests.mozilla.org");
startupManager(false);
AddonManager.getAddonByID("bootstrap1@tests.mozilla.org", function(b1) {
@ -548,18 +577,8 @@ function check_test_11() {
function run_test_12() {
shutdownManager();
let dir = profileDir.clone();
dir.append("bootstrap1@tests.mozilla.org");
dir.create(AM_Ci.nsIFile.DIRECTORY_TYPE, 0755);
let zip = AM_Cc["@mozilla.org/libjar/zip-reader;1"].
createInstance(AM_Ci.nsIZipReader);
zip.open(do_get_addon("test_bootstrap1_1"));
dir.append("install.rdf");
zip.extract("install.rdf", dir);
dir = dir.parent;
dir.append("bootstrap.js");
zip.extract("bootstrap.js", dir);
zip.close();
manuallyInstall(do_get_addon("test_bootstrap1_1"), profileDir,
"bootstrap1@tests.mozilla.org");
startupManager(true);
@ -654,18 +673,8 @@ function check_test_13() {
function run_test_14() {
shutdownManager();
let dir = profileDir.clone();
dir.append("bootstrap1@tests.mozilla.org");
dir.create(AM_Ci.nsIFile.DIRECTORY_TYPE, 0755);
let zip = AM_Cc["@mozilla.org/libjar/zip-reader;1"].
createInstance(AM_Ci.nsIZipReader);
zip.open(do_get_addon("test_bootstrap1_3"));
dir.append("install.rdf");
zip.extract("install.rdf", dir);
dir = dir.parent;
dir.append("bootstrap.js");
zip.extract("bootstrap.js", dir);
zip.close();
manuallyInstall(do_get_addon("test_bootstrap1_3"), profileDir,
"bootstrap1@tests.mozilla.org");
startupManager(false);
@ -808,18 +817,8 @@ function run_test_16() {
function run_test_17() {
shutdownManager();
let dir = userExtDir.clone();
dir.append("bootstrap1@tests.mozilla.org");
dir.create(AM_Ci.nsIFile.DIRECTORY_TYPE, 0755);
let zip = AM_Cc["@mozilla.org/libjar/zip-reader;1"].
createInstance(AM_Ci.nsIZipReader);
zip.open(do_get_addon("test_bootstrap1_1"));
dir.append("install.rdf");
zip.extract("install.rdf", dir);
dir = dir.parent;
dir.append("bootstrap.js");
zip.extract("bootstrap.js", dir);
zip.close();
manuallyInstall(do_get_addon("test_bootstrap1_1"), userExtDir,
"bootstrap1@tests.mozilla.org");
resetPrefs();
startupManager();
@ -902,18 +901,8 @@ function run_test_20() {
resetPrefs();
shutdownManager();
let dir = profileDir.clone();
dir.append("bootstrap1@tests.mozilla.org");
dir.create(AM_Ci.nsIFile.DIRECTORY_TYPE, 0755);
let zip = AM_Cc["@mozilla.org/libjar/zip-reader;1"].
createInstance(AM_Ci.nsIZipReader);
zip.open(do_get_addon("test_bootstrap1_2"));
dir.append("install.rdf");
zip.extract("install.rdf", dir);
dir = dir.parent;
dir.append("bootstrap.js");
zip.extract("bootstrap.js", dir);
zip.close();
manuallyInstall(do_get_addon("test_bootstrap1_2"), profileDir,
"bootstrap1@tests.mozilla.org");
startupManager();
@ -939,9 +928,7 @@ function run_test_21() {
resetPrefs();
shutdownManager();
let dir = profileDir.clone();
dir.append("bootstrap1@tests.mozilla.org");
dir.remove(true);
manuallyUninstall(profileDir, "bootstrap1@tests.mozilla.org");
startupManager();
@ -964,9 +951,7 @@ function run_test_21() {
do_check_eq(getStartupReason(), APP_STARTUP);
dir = userExtDir.clone();
dir.append("bootstrap1@tests.mozilla.org");
dir.remove(true);
manuallyUninstall(userExtDir, "bootstrap1@tests.mozilla.org");
restartManager();
@ -978,21 +963,11 @@ function run_test_21() {
function run_test_22() {
shutdownManager();
let dir = profileDir.clone();
dir.append("bootstrap1@tests.mozilla.org");
dir.create(AM_Ci.nsIFile.DIRECTORY_TYPE, 0755);
let zip = AM_Cc["@mozilla.org/libjar/zip-reader;1"].
createInstance(AM_Ci.nsIZipReader);
zip.open(do_get_addon("test_bootstrap1_1"));
dir.append("install.rdf");
zip.extract("install.rdf", dir);
dir = dir.parent;
dir.append("bootstrap.js");
zip.extract("bootstrap.js", dir);
zip.close();
let file = manuallyInstall(do_get_addon("test_bootstrap1_1"), profileDir,
"bootstrap1@tests.mozilla.org");
// Make it look old so changes are detected
setExtensionModifiedTime(dir.parent, dir.parent.lastModifiedTime - 5000);
setExtensionModifiedTime(file, file.lastModifiedTime - 5000);
startupManager();
@ -1007,18 +982,9 @@ function run_test_22() {
resetPrefs();
shutdownManager();
dir = dir.parent;
dir.remove(true);
dir.create(AM_Ci.nsIFile.DIRECTORY_TYPE, 0755);
let zip = AM_Cc["@mozilla.org/libjar/zip-reader;1"].
createInstance(AM_Ci.nsIZipReader);
zip.open(do_get_addon("test_bootstrap1_2"));
dir.append("install.rdf");
zip.extract("install.rdf", dir);
dir = dir.parent;
dir.append("bootstrap.js");
zip.extract("bootstrap.js", dir);
zip.close();
manuallyUninstall(profileDir, "bootstrap1@tests.mozilla.org");
manuallyInstall(do_get_addon("test_bootstrap1_2"), profileDir,
"bootstrap1@tests.mozilla.org");
startupManager();