Bug 511761 - Only use compatibility.ini (not .autoreg, or stat()s) to invalidate fastloads and other caches (r=bsmedberg)
This commit is contained in:
Родитель
a6bcf9f738
Коммит
2a87a15f5a
|
@ -298,9 +298,6 @@ libs::
|
|||
endif
|
||||
endif
|
||||
|
||||
libs::
|
||||
touch $(DIST)/bin/.autoreg
|
||||
|
||||
libs:: $(srcdir)/profile/prefs.js
|
||||
$(INSTALL) $(IFLAGS1) $^ $(DIST)/bin/defaults/profile
|
||||
|
||||
|
|
|
@ -88,7 +88,6 @@ const FILE_EXTENSIONS = "extensions.rdf";
|
|||
const FILE_EXTENSION_MANIFEST = "extensions.ini";
|
||||
const FILE_EXTENSIONS_STARTUP_CACHE = "extensions.cache";
|
||||
const FILE_EXTENSIONS_LOG = "extensions.log";
|
||||
const FILE_AUTOREG = ".autoreg";
|
||||
const FILE_INSTALL_MANIFEST = "install.rdf";
|
||||
const FILE_CHROME_MANIFEST = "chrome.manifest";
|
||||
|
||||
|
@ -3599,16 +3598,13 @@ ExtensionManager.prototype = {
|
|||
*/
|
||||
set _extensionListChanged(val) {
|
||||
// When an extension has an operation perform on it (e.g. install, upgrade,
|
||||
// disable, etc.) we are responsible for creating the .autoreg file and
|
||||
// nsAppRunner is responsible for removing it on restart. At some point it
|
||||
// may make sense to be able to cancel a registration but for now we only
|
||||
// create the file.
|
||||
try {
|
||||
var autoregFile = getFile(KEY_PROFILEDIR, [FILE_AUTOREG]);
|
||||
if (val && !autoregFile.exists())
|
||||
autoregFile.create(Ci.nsILocalFile.NORMAL_FILE_TYPE, PERMS_FILE);
|
||||
}
|
||||
catch (e) {
|
||||
// disable, etc.) we are responsible for writing this information to
|
||||
// compatibility.ini, and nsAppRunner is responsible for checking this on
|
||||
// restart. At some point it may make sense to be able to cancel a
|
||||
// registration but for now we only create the file.
|
||||
if (val) {
|
||||
let XRE = Cc["@mozilla.org/xre/app-info;1"].getService(Ci.nsIXULRuntime);
|
||||
XRE.invalidateCachesOnRestart();
|
||||
}
|
||||
return val;
|
||||
},
|
||||
|
|
|
@ -238,6 +238,8 @@ protected:
|
|||
extern void InstallUnixSignalHandlers(const char *ProgramName);
|
||||
#endif
|
||||
|
||||
#define FILE_COMPATIBILITY_INFO NS_LITERAL_CSTRING("compatibility.ini")
|
||||
|
||||
int gArgc;
|
||||
char **gArgv;
|
||||
|
||||
|
@ -712,6 +714,48 @@ nsXULAppInfo::GetWidgetToolkit(nsACString& aResult)
|
|||
return NS_OK;
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
nsXULAppInfo::InvalidateCachesOnRestart()
|
||||
{
|
||||
nsCOMPtr<nsIFile> file;
|
||||
nsresult rv = NS_GetSpecialDirectory(NS_APP_PROFILE_DIR_STARTUP,
|
||||
getter_AddRefs(file));
|
||||
if (NS_FAILED(rv))
|
||||
return rv;
|
||||
if (!file)
|
||||
return NS_ERROR_NOT_AVAILABLE;
|
||||
|
||||
file->AppendNative(FILE_COMPATIBILITY_INFO);
|
||||
|
||||
nsCOMPtr<nsILocalFile> localFile(do_QueryInterface(file));
|
||||
nsINIParser parser;
|
||||
rv = parser.Init(localFile);
|
||||
if (NS_FAILED(rv)) {
|
||||
// This fails if compatibility.ini is not there, so we'll
|
||||
// flush the caches on the next restart anyways.
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
nsCAutoString buf;
|
||||
rv = parser.GetString("Compatibility", "InvalidateCaches", buf);
|
||||
|
||||
if (NS_FAILED(rv)) {
|
||||
PRFileDesc *fd = nsnull;
|
||||
localFile->OpenNSPRFileDesc(PR_RDWR | PR_APPEND, 0600, &fd);
|
||||
if (!fd) {
|
||||
NS_ERROR("could not create output stream");
|
||||
return NS_ERROR_NOT_AVAILABLE;
|
||||
}
|
||||
static const char kInvalidationHeader[] = NS_LINEBREAK "InvalidateCaches=1" NS_LINEBREAK;
|
||||
rv = PR_Write(fd, kInvalidationHeader, sizeof(kInvalidationHeader) - 1);
|
||||
PR_Close(fd);
|
||||
|
||||
if (NS_FAILED(rv))
|
||||
return rv;
|
||||
}
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
#ifdef XP_WIN
|
||||
// Matches the enum in WinNT.h for the Vista SDK but renamed so that we can
|
||||
// safely build with the Vista SDK and without it.
|
||||
|
@ -2147,13 +2191,19 @@ SelectProfile(nsIProfileLock* *aResult, nsINativeAppSupport* aNative,
|
|||
return ShowProfileManager(profileSvc, aNative);
|
||||
}
|
||||
|
||||
#define FILE_COMPATIBILITY_INFO NS_LITERAL_CSTRING("compatibility.ini")
|
||||
|
||||
/**
|
||||
* Checks the compatibility.ini file to see if we have updated our application
|
||||
* or otherwise invalidated our caches. If the application has been updated,
|
||||
* we return PR_FALSE; otherwise, we return PR_TRUE. We also write the status
|
||||
* of the caches (valid/invalid) into the return param aCachesOK. The aCachesOK
|
||||
* is always invalid if the application has been updated.
|
||||
*/
|
||||
static PRBool
|
||||
CheckCompatibility(nsIFile* aProfileDir, const nsCString& aVersion,
|
||||
const nsCString& aOSABI, nsIFile* aXULRunnerDir,
|
||||
nsIFile* aAppDir)
|
||||
nsIFile* aAppDir, PRBool* aCachesOK)
|
||||
{
|
||||
*aCachesOK = false;
|
||||
nsCOMPtr<nsIFile> file;
|
||||
aProfileDir->Clone(getter_AddRefs(file));
|
||||
if (!file)
|
||||
|
@ -2205,6 +2255,10 @@ CheckCompatibility(nsIFile* aProfileDir, const nsCString& aVersion,
|
|||
return PR_FALSE;
|
||||
}
|
||||
|
||||
rv = parser.GetString("Compatibility", "InvalidateCaches", buf);
|
||||
|
||||
// If we see this flag, caches are invalid.
|
||||
*aCachesOK = (NS_FAILED(rv) || !buf.EqualsLiteral("1"));
|
||||
return PR_TRUE;
|
||||
}
|
||||
|
||||
|
@ -2271,19 +2325,6 @@ WriteVersion(nsIFile* aProfileDir, const nsCString& aVersion,
|
|||
PR_Close(fd);
|
||||
}
|
||||
|
||||
static PRBool ComponentsListChanged(nsIFile* aProfileDir)
|
||||
{
|
||||
nsCOMPtr<nsIFile> file;
|
||||
aProfileDir->Clone(getter_AddRefs(file));
|
||||
if (!file)
|
||||
return PR_TRUE;
|
||||
file->AppendNative(NS_LITERAL_CSTRING(".autoreg"));
|
||||
|
||||
PRBool exists = PR_FALSE;
|
||||
file->Exists(&exists);
|
||||
return exists;
|
||||
}
|
||||
|
||||
static void RemoveComponentRegistries(nsIFile* aProfileDir, nsIFile* aLocalProfileDir,
|
||||
PRBool aRemoveEMFiles)
|
||||
{
|
||||
|
@ -2312,6 +2353,9 @@ static void RemoveComponentRegistries(nsIFile* aProfileDir, nsIFile* aLocalProfi
|
|||
|
||||
file->AppendNative(NS_LITERAL_CSTRING("XUL" PLATFORM_FASL_SUFFIX));
|
||||
file->Remove(PR_FALSE);
|
||||
|
||||
file->SetNativeLeafName(NS_LITERAL_CSTRING("XPC" PLATFORM_FASL_SUFFIX));
|
||||
file->Remove(PR_FALSE);
|
||||
}
|
||||
|
||||
// To support application initiated restart via nsIAppStartup.quit, we
|
||||
|
@ -3172,9 +3216,12 @@ XRE_main(int argc, char* argv[], const nsXREAppData* aAppData)
|
|||
// Check for version compatibility with the last version of the app this
|
||||
// profile was started with. The format of the version stamp is defined
|
||||
// by the BuildVersion function.
|
||||
PRBool versionOK = CheckCompatibility(profD, version, osABI,
|
||||
// Also check to see if something has happened to invalidate our
|
||||
// fastload caches, like an extension upgrade or installation.
|
||||
PRBool cachesOK;
|
||||
PRBool versionOK = CheckCompatibility(profD, version, osABI,
|
||||
dirProvider.GetGREDir(),
|
||||
gAppData->directory);
|
||||
gAppData->directory, &cachesOK);
|
||||
|
||||
// Every time a profile is loaded by a build with a different version,
|
||||
// it updates the compatibility.ini file saying what version last wrote
|
||||
|
@ -3189,11 +3236,15 @@ XRE_main(int argc, char* argv[], const nsXREAppData* aAppData)
|
|||
dirProvider.GetGREDir(), gAppData->directory);
|
||||
}
|
||||
else if (versionOK) {
|
||||
if (ComponentsListChanged(profD)) {
|
||||
if (!cachesOK) {
|
||||
// Remove compreg.dat and xpti.dat, forcing component re-registration.
|
||||
// The new list of additional components directories is derived from
|
||||
// information in "extensions.ini".
|
||||
RemoveComponentRegistries(profD, profLD, PR_FALSE);
|
||||
|
||||
// Rewrite compatibility.ini to remove the flag
|
||||
WriteVersion(profD, version, osABI,
|
||||
dirProvider.GetGREDir(), gAppData->directory);
|
||||
}
|
||||
// Nothing need be done for the normal startup case.
|
||||
}
|
||||
|
|
|
@ -285,85 +285,6 @@ RegisterGenericFactory(nsIComponentRegistrar* registrar,
|
|||
return rv;
|
||||
}
|
||||
|
||||
// In order to support the installer, we need
|
||||
// to be told out of band if we should cause
|
||||
// an autoregister. If the file ".autoreg" exists in the binary
|
||||
// directory, we check its timestamp against the timestamp of the
|
||||
// compreg.dat file. If the .autoreg file is newer, we autoregister.
|
||||
static PRBool CheckUpdateFile()
|
||||
{
|
||||
nsresult rv;
|
||||
nsCOMPtr<nsIFile> compregFile;
|
||||
rv = nsDirectoryService::gService->Get(NS_XPCOM_COMPONENT_REGISTRY_FILE,
|
||||
NS_GET_IID(nsIFile),
|
||||
getter_AddRefs(compregFile));
|
||||
|
||||
if (NS_FAILED(rv)) {
|
||||
NS_WARNING("Getting NS_XPCOM_COMPONENT_REGISTRY_FILE failed");
|
||||
return PR_FALSE;
|
||||
}
|
||||
|
||||
PRInt64 compregModTime;
|
||||
rv = compregFile->GetLastModifiedTime(&compregModTime);
|
||||
if (NS_FAILED(rv))
|
||||
return PR_TRUE;
|
||||
|
||||
nsCOMPtr<nsIFile> file;
|
||||
rv = nsDirectoryService::gService->Get(NS_XPCOM_CURRENT_PROCESS_DIR,
|
||||
NS_GET_IID(nsIFile),
|
||||
getter_AddRefs(file));
|
||||
|
||||
if (NS_FAILED(rv)) {
|
||||
NS_WARNING("Getting NS_XPCOM_CURRENT_PROCESS_DIR failed");
|
||||
return PR_FALSE;
|
||||
}
|
||||
|
||||
file->AppendNative(nsDependentCString(".autoreg"));
|
||||
|
||||
// superfluous cast
|
||||
PRInt64 nowTime = PR_Now() / PR_USEC_PER_MSEC;
|
||||
PRInt64 autoregModTime;
|
||||
rv = file->GetLastModifiedTime(&autoregModTime);
|
||||
if (NS_FAILED(rv))
|
||||
goto next;
|
||||
|
||||
if (autoregModTime > compregModTime) {
|
||||
if (autoregModTime < nowTime) {
|
||||
return PR_TRUE;
|
||||
} else {
|
||||
NS_WARNING("Screwy timestamps, ignoring .autoreg");
|
||||
}
|
||||
}
|
||||
|
||||
next:
|
||||
nsCOMPtr<nsIFile> greFile;
|
||||
rv = nsDirectoryService::gService->Get(NS_GRE_DIR,
|
||||
NS_GET_IID(nsIFile),
|
||||
getter_AddRefs(greFile));
|
||||
|
||||
if (NS_FAILED(rv)) {
|
||||
NS_WARNING("Getting NS_GRE_DIR failed");
|
||||
return PR_FALSE;
|
||||
}
|
||||
|
||||
greFile->AppendNative(nsDependentCString(".autoreg"));
|
||||
|
||||
PRBool equals;
|
||||
rv = greFile->Equals(file, &equals);
|
||||
if (NS_SUCCEEDED(rv) && equals)
|
||||
return PR_FALSE;
|
||||
|
||||
rv = greFile->GetLastModifiedTime(&autoregModTime);
|
||||
if (NS_FAILED(rv))
|
||||
return PR_FALSE;
|
||||
|
||||
if (autoregModTime > nowTime) {
|
||||
NS_WARNING("Screwy timestamps, ignoring .autoreg");
|
||||
return PR_FALSE;
|
||||
}
|
||||
return autoregModTime > compregModTime;
|
||||
}
|
||||
|
||||
|
||||
nsComponentManagerImpl* nsComponentManagerImpl::gComponentManager = NULL;
|
||||
PRBool gXPCOMShuttingDown = PR_FALSE;
|
||||
|
@ -684,8 +605,9 @@ NS_InitXPCOM3(nsIServiceManager* *result,
|
|||
nsIInterfaceInfoManager* iim =
|
||||
xptiInterfaceInfoManager::GetInterfaceInfoManagerNoAddRef();
|
||||
|
||||
if (CheckUpdateFile() || NS_FAILED(
|
||||
nsComponentManagerImpl::gComponentManager->ReadPersistentRegistry())) {
|
||||
// "Re-register the world" if compreg.dat doesn't exist
|
||||
rv = nsComponentManagerImpl::gComponentManager->ReadPersistentRegistry();
|
||||
if (NS_FAILED(rv)) {
|
||||
// If the component registry is out of date, malformed, or incomplete,
|
||||
// autoregister the default component directories.
|
||||
(void) iim->AutoRegisterInterfaces();
|
||||
|
|
|
@ -3006,11 +3006,19 @@ nsComponentManagerImpl::AutoRegisterComponent(nsILocalFile* aComponentFile,
|
|||
}
|
||||
|
||||
PRInt64 modTime = 0;
|
||||
if (NS_SUCCEEDED(aComponentFile->GetLastModifiedTime(&modTime))) {
|
||||
PRInt64 cachedModTime;
|
||||
if (mAutoRegEntries.Get(lfhash, &cachedModTime) &&
|
||||
cachedModTime == modTime)
|
||||
PRInt64 cachedModTime;
|
||||
|
||||
// If it's in the cache, it should be valid.
|
||||
// The cache file is removed if files are modified.
|
||||
if (mAutoRegEntries.Get(lfhash, &cachedModTime)) {
|
||||
#ifdef DEBUG
|
||||
if (NS_SUCCEEDED(aComponentFile->GetLastModifiedTime(&modTime))
|
||||
&& cachedModTime == modTime) {
|
||||
return NS_OK;
|
||||
}
|
||||
#else
|
||||
return NS_OK;
|
||||
#endif
|
||||
}
|
||||
|
||||
const char *registryType = nsnull;
|
||||
|
|
|
@ -728,21 +728,20 @@ nsFastLoadFileReader::ReadFooter(nsFastLoadFooter *aFooter)
|
|||
rv = NS_NewNativeLocalFile(filename, PR_TRUE, getter_AddRefs(file));
|
||||
if (NS_FAILED(rv))
|
||||
return rv;
|
||||
|
||||
#ifdef DEBUG
|
||||
PRInt64 currentMtime;
|
||||
rv = file->GetLastModifiedTime(¤tMtime);
|
||||
if (NS_FAILED(rv))
|
||||
return rv;
|
||||
|
||||
if (LL_NE(fastLoadMtime, currentMtime)) {
|
||||
#ifdef DEBUG
|
||||
nsCAutoString path;
|
||||
file->GetNativePath(path);
|
||||
printf("%s mtime changed, invalidating FastLoad file\n",
|
||||
path.get());
|
||||
#endif
|
||||
return NS_ERROR_FAILURE;
|
||||
}
|
||||
#endif
|
||||
|
||||
rv = readDeps->AppendElement(file);
|
||||
if (NS_FAILED(rv))
|
||||
|
|
|
@ -44,7 +44,7 @@
|
|||
* stable/frozen, please contact Benjamin Smedberg.
|
||||
*/
|
||||
|
||||
[scriptable, uuid(17311145-97da-49eb-b984-965bdee8879c)]
|
||||
[scriptable, uuid(C61D0C09-05AD-4E72-BAC5-203F3F380352)]
|
||||
interface nsIXULRuntime : nsISupports
|
||||
{
|
||||
/**
|
||||
|
@ -86,4 +86,11 @@ interface nsIXULRuntime : nsISupports
|
|||
* This is taken from the MOZ_WIDGET_TOOLKIT configure variable.
|
||||
*/
|
||||
readonly attribute AUTF8String widgetToolkit;
|
||||
|
||||
/**
|
||||
* Signal the apprunner to invalidate caches on the next restart.
|
||||
* This will cause components to be autoregistered and all
|
||||
* fastload data to be re-created.
|
||||
*/
|
||||
void invalidateCachesOnRestart();
|
||||
};
|
||||
|
|
|
@ -261,9 +261,6 @@ ifeq ($(OS_ARCH),OS2)
|
|||
cp $(srcdir)/xulrunner-os2.ico $(DIST)/branding/xulrunner.ico
|
||||
endif
|
||||
|
||||
libs::
|
||||
touch $(DIST)/bin/.autoreg
|
||||
|
||||
ifeq (cocoa,$(MOZ_WIDGET_TOOLKIT))
|
||||
|
||||
FRAMEWORK_NAME = XUL
|
||||
|
|
Загрузка…
Ссылка в новой задаче