Bug 1510934 - Ensure that pref changes during content process launch are delivered to the process. r=njn

Some prefs need to be available before IPC is started, so we serialize a
snapshot when we start launching the process, and then stream further
changes over IPC messages.  However, async launch introduces a window
between the snapshot and when the parent can start sending messages,
during which other code can run on the main thread and change prefs.

In order to not lose those updates, they're queued and sent when the
launch is complete.

Depends on D14089

Differential Revision: https://phabricator.services.mozilla.com/D14090

--HG--
extra : moz-landing-system : lando
This commit is contained in:
Jed Davis 2018-12-14 05:28:56 +00:00
Родитель 4213a3e9b6
Коммит d845f69798
2 изменённых файлов: 39 добавлений и 10 удалений

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

@ -1302,9 +1302,12 @@ void ContentParent::Init() {
}
}
// Register ContentParent as an observer for changes to any pref whose prefix
// matches the empty string, i.e. all of them.
Preferences::AddStrongObserver(this, "");
// Flush any pref updates that happened during launch and weren't
// included in the blobs set up in LaunchSubprocessInternal.
for (const Pref& pref : mQueuedPrefs) {
Unused << NS_WARN_IF(!SendPreferenceUpdate(pref));
}
mQueuedPrefs.Clear();
if (obs) {
nsAutoString cpId;
@ -2133,6 +2136,12 @@ void ContentParent::LaunchSubprocessInternal(
// Copy the serialized prefs into the shared memory.
memcpy(static_cast<char*>(shm.memory()), prefs.get(), prefs.Length());
// Register ContentParent as an observer for changes to any pref
// whose prefix matches the empty string, i.e. all of them. The
// observation starts here in order to capture pref updates that
// happen during async launch.
Preferences::AddStrongObserver(this, "");
// Formats a pointer or pointer-sized-integer as a string suitable for passing
// in an arguments list.
auto formatPtrArg = [](auto arg) {
@ -3041,12 +3050,11 @@ ContentParent::Observe(nsISupports* aSubject, const char* aTopic,
NS_ASSERTION(!mSubprocess, "Close should have nulled mSubprocess");
}
if (!IsAlive() || !mSubprocess) return NS_OK;
if (IsDead() || !mSubprocess) {
return NS_OK;
}
// listening for memory pressure event
if (!strcmp(aTopic, "memory-pressure")) {
Unused << SendFlushMemory(nsDependentString(aData));
} else if (!strcmp(aTopic, "nsPref:changed")) {
if (!strcmp(aTopic, "nsPref:changed")) {
// A pref changed. If it's not on the blacklist, inform child processes.
#define BLACKLIST_ENTRY(s) \
{ s, (sizeof(s) / sizeof(char16_t)) - 1 }
@ -3079,9 +3087,24 @@ ContentParent::Observe(nsISupports* aSubject, const char* aTopic,
Pref pref(strData, /* isLocked */ false, null_t(), null_t());
Preferences::GetPreference(&pref);
if (!SendPreferenceUpdate(pref)) {
return NS_ERROR_NOT_AVAILABLE;
if (IsAlive()) {
MOZ_ASSERT(mQueuedPrefs.IsEmpty());
if (!SendPreferenceUpdate(pref)) {
return NS_ERROR_NOT_AVAILABLE;
}
} else {
MOZ_ASSERT(IsLaunching());
mQueuedPrefs.AppendElement(pref);
}
}
if (!IsAlive()) {
return NS_OK;
}
// listening for memory pressure event
if (!strcmp(aTopic, "memory-pressure")) {
Unused << SendFlushMemory(nsDependentString(aData));
} else if (!strcmp(aTopic, NS_IPC_IOSERVICE_SET_OFFLINE_TOPIC)) {
NS_ConvertUTF16toUTF8 dataStr(aData);
const char* offline = dataStr.get();

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

@ -364,6 +364,7 @@ class ContentParent final : public PContentParent,
return mLifecycleState == LifecycleState::LAUNCHING;
}
bool IsAlive() const override;
bool IsDead() const { return mLifecycleState == LifecycleState::DEAD; }
virtual bool IsForBrowser() const override { return mIsForBrowser; }
virtual bool IsForJSPlugin() const override {
@ -1324,6 +1325,11 @@ class ContentParent final : public PContentParent,
UniquePtr<mozilla::ipc::CrashReporterHost> mCrashReporter;
// Collects any pref changes that occur during process launch (after
// the initial map is passed in command-line arguments) to be sent
// when the process can receive IPC messages.
nsTArray<Pref> mQueuedPrefs;
static uint64_t sNextTabParentId;
static nsDataHashtable<nsUint64HashKey, TabParent*> sNextTabParents;