Bug 1471089: Improve handling of pre-loaded content processes in script preloader. r=erahm

MozReview-Commit-ID: GwZzQ0ic5Et

--HG--
extra : rebase_source : 0c02b45af7ea9f1bea9e9a4bd466b69aa97eb0f9
This commit is contained in:
Kris Maglione 2018-06-25 17:45:34 -07:00
Родитель 00c91fc905
Коммит 923f03d3d3
2 изменённых файлов: 52 добавлений и 7 удалений

Просмотреть файл

@ -27,6 +27,7 @@
#include "nsIFile.h"
#include "nsIObserverService.h"
#include "nsJSUtils.h"
#include "nsNetUtil.h"
#include "nsProxyRelease.h"
#include "nsThreadUtils.h"
#include "nsXULAppAPI.h"
@ -39,6 +40,10 @@
#define SHUTDOWN_TOPIC "quit-application-granted"
#define CACHE_INVALIDATE_TOPIC "startupcache-invalidate"
// The maximum time we'll wait for a child process to finish starting up before
// we send its script data back to the parent.
constexpr uint32_t CHILD_STARTUP_TIMEOUT_MS = 8000;
namespace mozilla {
namespace {
static LazyLogModule gLog("ScriptPreloader");
@ -356,15 +361,22 @@ ScriptPreloader::Observe(nsISupports* subject, const char* topic, const char16_t
getter_AddRefs(mSaveThread), this);
}
} else if (!strcmp(topic, DOC_ELEM_INSERTED_TOPIC)) {
obs->RemoveObserver(this, DOC_ELEM_INSERTED_TOPIC);
// If this is an uninitialized about:blank viewer or a chrome: document
// (which should always be an XBL binding document), ignore it. We don't
// have to worry about it loading malicious content.
if (nsCOMPtr<nsIDocument> doc = do_QueryInterface(subject)) {
nsCOMPtr<nsIURI> uri = doc->GetDocumentURI();
MOZ_ASSERT(XRE_IsContentProcess());
mStartupFinished = true;
if (mChildActor) {
mChildActor->SendScriptsAndFinalize(mScripts);
bool schemeIs;
if ((NS_IsAboutBlank(uri) &&
doc->GetReadyStateEnum() == doc->READYSTATE_UNINITIALIZED) ||
(NS_SUCCEEDED(uri->SchemeIs("chrome", &schemeIs)) && schemeIs)) {
return NS_OK;
}
}
FinishContentStartup();
} else if (!strcmp(topic, "timer-callback")) {
FinishContentStartup();
} else if (!strcmp(topic, SHUTDOWN_TOPIC)) {
ForceWriteCacheFile();
} else if (!strcmp(topic, CLEANUP_TOPIC)) {
@ -376,6 +388,22 @@ ScriptPreloader::Observe(nsISupports* subject, const char* topic, const char16_t
return NS_OK;
}
void
ScriptPreloader::FinishContentStartup()
{
MOZ_ASSERT(XRE_IsContentProcess());
nsCOMPtr<nsIObserverService> obs = services::GetObserverService();
obs->RemoveObserver(this, DOC_ELEM_INSERTED_TOPIC);
mSaveTimer = nullptr;
mStartupFinished = true;
if (mChildActor) {
mChildActor->SendScriptsAndFinalize(mScripts);
}
}
Result<nsCOMPtr<nsIFile>, nsresult>
ScriptPreloader::GetCacheFile(const nsAString& suffix)
@ -458,6 +486,19 @@ ScriptPreloader::InitCache(const Maybe<ipc::FileDescriptor>& cacheFile, ScriptCa
RegisterWeakMemoryReporter(this);
auto cleanup = MakeScopeExit([&] {
// If the parent is expecting cache data from us, make sure we send it
// before it writes out its cache file. For normal proceses, this isn't
// a concern, since they begin loading documents quite early. For the
// preloaded process, we may end up waiting a long time (or, indeed,
// never loading a document), so we need an additional timeout.
if (cacheChild) {
NS_NewTimerWithObserver(getter_AddRefs(mSaveTimer),
this, CHILD_STARTUP_TIMEOUT_MS,
nsITimer::TYPE_ONE_SHOT);
}
});
if (cacheFile.isNothing()){
return Ok();
}

Просмотреть файл

@ -22,6 +22,7 @@
#include "nsIMemoryReporter.h"
#include "nsIObserver.h"
#include "nsIThread.h"
#include "nsITimer.h"
#include "jsapi.h"
#include "js/GCAnnotations.h"
@ -379,6 +380,8 @@ private:
void PrepareCacheWriteInternal();
void FinishContentStartup();
// Returns a file pointer for the cache file with the given name in the
// current profile.
Result<nsCOMPtr<nsIFile>, nsresult>
@ -459,6 +462,7 @@ private:
nsCOMPtr<nsIFile> mProfD;
nsCOMPtr<nsIThread> mSaveThread;
nsCOMPtr<nsITimer> mSaveTimer;
// The mmapped cache data from this session's cache file.
AutoMemMap mCacheData;