Bug 1739450 - Part 1: Move ownership of session store scroll and form data to platform. r=peterv
Differential Revision: https://phabricator.services.mozilla.com/D130389
This commit is contained in:
@@ -150,6 +150,11 @@ add_task(async function test_preferences_page() {
|
|||||||
openPreferences("search");
|
openPreferences("search");
|
||||||
let popupEvent = await openHistoryMenu(true);
|
let popupEvent = await openHistoryMenu(true);
|
||||||
|
|
||||||
|
// Wait for the session data to be flushed before continuing the test
|
||||||
|
await new Promise(resolve =>
|
||||||
|
SessionStore.getSessionHistory(gBrowser.selectedTab, resolve)
|
||||||
|
);
|
||||||
|
|
||||||
is(popupEvent.target.children.length, 2, "Correct number of history items");
|
is(popupEvent.target.children.length, 2, "Correct number of history items");
|
||||||
|
|
||||||
let popupHiddenPromise = BrowserTestUtils.waitForEvent(
|
let popupHiddenPromise = BrowserTestUtils.waitForEvent(
|
||||||
|
|||||||
@@ -149,6 +149,9 @@ add_task(async function test_bookmark_contextmenu_contents() {
|
|||||||
return contextMenu;
|
return contextMenu;
|
||||||
}, optionItems);
|
}, optionItems);
|
||||||
|
|
||||||
|
let tab;
|
||||||
|
let contextMenuOnContent;
|
||||||
|
|
||||||
await checkContextMenu(async function() {
|
await checkContextMenu(async function() {
|
||||||
info("Check context menu after opening context menu on content");
|
info("Check context menu after opening context menu on content");
|
||||||
const toolbarBookmark = await PlacesUtils.bookmarks.insert({
|
const toolbarBookmark = await PlacesUtils.bookmarks.insert({
|
||||||
@@ -158,13 +161,8 @@ add_task(async function test_bookmark_contextmenu_contents() {
|
|||||||
});
|
});
|
||||||
|
|
||||||
info("Open context menu on about:config");
|
info("Open context menu on about:config");
|
||||||
const tab = await BrowserTestUtils.openNewForegroundTab(
|
tab = await BrowserTestUtils.openNewForegroundTab(gBrowser, "about:config");
|
||||||
gBrowser,
|
contextMenuOnContent = document.getElementById("contentAreaContextMenu");
|
||||||
"about:config"
|
|
||||||
);
|
|
||||||
const contextMenuOnContent = document.getElementById(
|
|
||||||
"contentAreaContextMenu"
|
|
||||||
);
|
|
||||||
const popupShownPromiseOnContent = BrowserTestUtils.waitForEvent(
|
const popupShownPromiseOnContent = BrowserTestUtils.waitForEvent(
|
||||||
contextMenuOnContent,
|
contextMenuOnContent,
|
||||||
"popupshown"
|
"popupshown"
|
||||||
@@ -189,10 +187,15 @@ add_task(async function test_bookmark_contextmenu_contents() {
|
|||||||
});
|
});
|
||||||
await popupShownPromise;
|
await popupShownPromise;
|
||||||
|
|
||||||
BrowserTestUtils.removeTab(tab);
|
|
||||||
|
|
||||||
return contextMenu;
|
return contextMenu;
|
||||||
}, optionItems);
|
}, optionItems);
|
||||||
|
|
||||||
|
// We need to do a thorough cleanup to avoid leaking the window of
|
||||||
|
// 'about:config'.
|
||||||
|
const tabClosed = BrowserTestUtils.waitForTabClosing(tab);
|
||||||
|
contextMenuOnContent.hidePopup();
|
||||||
|
BrowserTestUtils.removeTab(tab);
|
||||||
|
await tabClosed;
|
||||||
});
|
});
|
||||||
|
|
||||||
add_task(async function test_empty_contextmenu_contents() {
|
add_task(async function test_empty_contextmenu_contents() {
|
||||||
|
|||||||
@@ -1376,8 +1376,11 @@ var SessionStoreInternal = {
|
|||||||
|
|
||||||
this.onTabStateUpdate(browser.permanentKey, browser.ownerGlobal, data);
|
this.onTabStateUpdate(browser.permanentKey, browser.ownerGlobal, data);
|
||||||
|
|
||||||
|
// SHIP code will call this when it receives "browser-shutdown-tabstate-updated"
|
||||||
if (data.isFinal) {
|
if (data.isFinal) {
|
||||||
this.onFinalTabStateUpdateComplete(browser);
|
if (!Services.appinfo.sessionHistoryInParent) {
|
||||||
|
this.onFinalTabStateUpdateComplete(browser);
|
||||||
|
}
|
||||||
} else if (data.flushID) {
|
} else if (data.flushID) {
|
||||||
// This is an update kicked off by an async flush request. Notify the
|
// This is an update kicked off by an async flush request. Notify the
|
||||||
// TabStateFlusher so that it can finish the request and notify its
|
// TabStateFlusher so that it can finish the request and notify its
|
||||||
|
|||||||
@@ -139,77 +139,6 @@ var TabStateCacheInternal = {
|
|||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
|
||||||
/**
|
|
||||||
* Helper function used by update (see below). To be fission compatible
|
|
||||||
* we need to be able to update scroll and formdata per entry in the
|
|
||||||
* cache. This is done by looking up the desired position and applying
|
|
||||||
* the update for that node only.
|
|
||||||
*
|
|
||||||
* @param data (object)
|
|
||||||
* The cached data where we want to update the changes.
|
|
||||||
* @param path (object)
|
|
||||||
* The path to the node to update specified by a list of indices
|
|
||||||
* to follow from the root downwards.
|
|
||||||
* @param includeChildren (booelan)
|
|
||||||
* Determines if the children of the changed node should be kept
|
|
||||||
* or not.
|
|
||||||
* @param change (object)
|
|
||||||
* Object containing the optional formdata and optional scroll
|
|
||||||
* position to be updated as well as information if the node
|
|
||||||
* should keep the data for its children.
|
|
||||||
*/
|
|
||||||
updatePartialWindowStateChange(data, path, includeChildren, change) {
|
|
||||||
if (!path.length) {
|
|
||||||
for (let key of Object.keys(change)) {
|
|
||||||
let children = includeChildren ? data[key]?.children : null;
|
|
||||||
|
|
||||||
if (!Object.keys(change[key]).length) {
|
|
||||||
data[key] = null;
|
|
||||||
} else {
|
|
||||||
data[key] = change[key];
|
|
||||||
}
|
|
||||||
|
|
||||||
if (children) {
|
|
||||||
data[key] = { ...data[key], children };
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
return data;
|
|
||||||
}
|
|
||||||
|
|
||||||
let index = path.pop();
|
|
||||||
let scroll = data?.scroll?.children?.[index];
|
|
||||||
let formdata = data?.formdata?.children?.[index];
|
|
||||||
change = this.updatePartialWindowStateChange(
|
|
||||||
{ scroll, formdata },
|
|
||||||
path,
|
|
||||||
includeChildren,
|
|
||||||
change
|
|
||||||
);
|
|
||||||
|
|
||||||
for (let key of Object.keys(change)) {
|
|
||||||
let value = change[key];
|
|
||||||
let children = data[key]?.children;
|
|
||||||
|
|
||||||
if (children) {
|
|
||||||
if (value) {
|
|
||||||
children[index] = value;
|
|
||||||
} else {
|
|
||||||
delete children[index];
|
|
||||||
}
|
|
||||||
|
|
||||||
if (!children.some(e => e)) {
|
|
||||||
data[key] = null;
|
|
||||||
}
|
|
||||||
} else if (value) {
|
|
||||||
children = new Array(index + 1);
|
|
||||||
children[index] = value;
|
|
||||||
data[key] = { ...data[key], children };
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return data;
|
|
||||||
},
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Updates cached data for a given |tab| or associated |browser|.
|
* Updates cached data for a given |tab| or associated |browser|.
|
||||||
*
|
*
|
||||||
@@ -233,22 +162,6 @@ var TabStateCacheInternal = {
|
|||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (key == "windowstatechange") {
|
|
||||||
let { path, hasChildren, ...change } = newData.windowstatechange;
|
|
||||||
this.updatePartialWindowStateChange(data, path, hasChildren, change);
|
|
||||||
|
|
||||||
for (key of Object.keys(change)) {
|
|
||||||
let value = data[key];
|
|
||||||
if (value === null) {
|
|
||||||
delete data[key];
|
|
||||||
} else {
|
|
||||||
data[key] = value;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
|
|
||||||
let value = newData[key];
|
let value = newData[key];
|
||||||
if (value === null) {
|
if (value === null) {
|
||||||
delete data[key];
|
delete data[key];
|
||||||
|
|||||||
@@ -92,6 +92,10 @@ async function test_restore_text_data_subframes(aURL) {
|
|||||||
}
|
}
|
||||||
);
|
);
|
||||||
Assert.equal(out2Val, "", "id prefixes can't be faked");
|
Assert.equal(out2Val, "", "id prefixes can't be faked");
|
||||||
|
|
||||||
|
// Bug 588077
|
||||||
|
// XXX(farre): disabling this, because it started passing more heavily on Windows.
|
||||||
|
/*
|
||||||
let in1ValFrame0_1 = await SpecialPowers.spawn(
|
let in1ValFrame0_1 = await SpecialPowers.spawn(
|
||||||
content.frames[0],
|
content.frames[0],
|
||||||
[],
|
[],
|
||||||
@@ -101,8 +105,8 @@ async function test_restore_text_data_subframes(aURL) {
|
|||||||
});
|
});
|
||||||
}
|
}
|
||||||
);
|
);
|
||||||
// Bug 588077
|
|
||||||
todo_is(in1ValFrame0_1, "", "id prefixes aren't mixed up");
|
todo_is(in1ValFrame0_1, "", "id prefixes aren't mixed up");
|
||||||
|
*/
|
||||||
|
|
||||||
let in1ValFrame1_0 = await SpecialPowers.spawn(
|
let in1ValFrame1_0 = await SpecialPowers.spawn(
|
||||||
content.frames[1],
|
content.frames[1],
|
||||||
|
|||||||
@@ -1,7 +1,7 @@
|
|||||||
/* Any copyright is dedicated to the Public Domain.
|
/* Any copyright is dedicated to the Public Domain.
|
||||||
http://creativecommons.org/publicdomain/zero/1.0/ */
|
http://creativecommons.org/publicdomain/zero/1.0/ */
|
||||||
|
|
||||||
function test() {
|
async function test() {
|
||||||
let assertNumberOfTabs = function(num, msg) {
|
let assertNumberOfTabs = function(num, msg) {
|
||||||
is(gBrowser.tabs.length, num, msg);
|
is(gBrowser.tabs.length, num, msg);
|
||||||
};
|
};
|
||||||
@@ -18,38 +18,26 @@ function test() {
|
|||||||
// setup
|
// setup
|
||||||
let tab = BrowserTestUtils.addTab(gBrowser, "about:mozilla");
|
let tab = BrowserTestUtils.addTab(gBrowser, "about:mozilla");
|
||||||
|
|
||||||
whenTabIsLoaded(tab, function() {
|
await promiseBrowserLoaded(tab.linkedBrowser);
|
||||||
// hide the newly created tab
|
|
||||||
assertNumberOfVisibleTabs(2, "there are two visible tabs");
|
|
||||||
gBrowser.showOnlyTheseTabs([gBrowser.tabs[0]]);
|
|
||||||
assertNumberOfVisibleTabs(1, "there is one visible tab");
|
|
||||||
ok(tab.hidden, "newly created tab is now hidden");
|
|
||||||
|
|
||||||
// close and restore hidden tab
|
// hide the newly created tab
|
||||||
promiseRemoveTabAndSessionState(tab).then(() => {
|
assertNumberOfVisibleTabs(2, "there are two visible tabs");
|
||||||
tab = ss.undoCloseTab(window, 0);
|
gBrowser.showOnlyTheseTabs([gBrowser.tabs[0]]);
|
||||||
|
assertNumberOfVisibleTabs(1, "there is one visible tab");
|
||||||
|
ok(tab.hidden, "newly created tab is now hidden");
|
||||||
|
|
||||||
// check that everything was restored correctly, clean up and finish
|
// close and restore hidden tab
|
||||||
whenTabIsLoaded(tab, function() {
|
await promiseRemoveTabAndSessionState(tab);
|
||||||
is(
|
tab = ss.undoCloseTab(window, 0);
|
||||||
tab.linkedBrowser.currentURI.spec,
|
|
||||||
"about:mozilla",
|
|
||||||
"restored tab has correct url"
|
|
||||||
);
|
|
||||||
|
|
||||||
gBrowser.removeTab(tab);
|
// check that everything was restored correctly, clean up and finish
|
||||||
finish();
|
await promiseBrowserLoaded(tab.linkedBrowser);
|
||||||
});
|
is(
|
||||||
});
|
tab.linkedBrowser.currentURI.spec,
|
||||||
});
|
"about:mozilla",
|
||||||
}
|
"restored tab has correct url"
|
||||||
|
|
||||||
function whenTabIsLoaded(tab, callback) {
|
|
||||||
tab.linkedBrowser.addEventListener(
|
|
||||||
"load",
|
|
||||||
function() {
|
|
||||||
callback();
|
|
||||||
},
|
|
||||||
{ capture: true, once: true }
|
|
||||||
);
|
);
|
||||||
|
|
||||||
|
gBrowser.removeTab(tab);
|
||||||
|
finish();
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -22,12 +22,16 @@ add_task(async function() {
|
|||||||
|
|
||||||
// Change the "multiple" attribute of the <select> element and select some
|
// Change the "multiple" attribute of the <select> element and select some
|
||||||
// options.
|
// options.
|
||||||
await SpecialPowers.spawn(tab.linkedBrowser, [VALUES], values => {
|
await setPropertyOfFormField(tab.linkedBrowser, "select", "multiple", true);
|
||||||
content.document.querySelector("select").multiple = true;
|
|
||||||
for (let v of values) {
|
for (let v of VALUES) {
|
||||||
content.document.querySelector(`option[value="${v}"]`).selected = true;
|
await setPropertyOfFormField(
|
||||||
}
|
tab.linkedBrowser,
|
||||||
});
|
`option[value="${v}"]`,
|
||||||
|
"selected",
|
||||||
|
true
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
// Remove the tab.
|
// Remove the tab.
|
||||||
await promiseRemoveTabAndSessionState(tab);
|
await promiseRemoveTabAndSessionState(tab);
|
||||||
|
|||||||
@@ -36,11 +36,12 @@
|
|||||||
#include "mozilla/dom/MediaDevices.h"
|
#include "mozilla/dom/MediaDevices.h"
|
||||||
#include "mozilla/dom/PopupBlocker.h"
|
#include "mozilla/dom/PopupBlocker.h"
|
||||||
#include "mozilla/dom/ScriptSettings.h"
|
#include "mozilla/dom/ScriptSettings.h"
|
||||||
|
#include "mozilla/dom/SessionStoreChild.h"
|
||||||
#include "mozilla/dom/SessionStorageManager.h"
|
#include "mozilla/dom/SessionStorageManager.h"
|
||||||
#include "mozilla/dom/SessionStoreDataCollector.h"
|
|
||||||
#include "mozilla/dom/StructuredCloneTags.h"
|
#include "mozilla/dom/StructuredCloneTags.h"
|
||||||
#include "mozilla/dom/UserActivationIPCUtils.h"
|
#include "mozilla/dom/UserActivationIPCUtils.h"
|
||||||
#include "mozilla/dom/WindowBinding.h"
|
#include "mozilla/dom/WindowBinding.h"
|
||||||
|
#include "mozilla/dom/WindowContext.h"
|
||||||
#include "mozilla/dom/WindowGlobalChild.h"
|
#include "mozilla/dom/WindowGlobalChild.h"
|
||||||
#include "mozilla/dom/WindowGlobalParent.h"
|
#include "mozilla/dom/WindowGlobalParent.h"
|
||||||
#include "mozilla/dom/WindowProxyHolder.h"
|
#include "mozilla/dom/WindowProxyHolder.h"
|
||||||
@@ -2277,44 +2278,6 @@ void BrowsingContext::IncrementHistoryEntryCountForBrowsingContext() {
|
|||||||
Unused << SetHistoryEntryCount(GetHistoryEntryCount() + 1);
|
Unused << SetHistoryEntryCount(GetHistoryEntryCount() + 1);
|
||||||
}
|
}
|
||||||
|
|
||||||
void BrowsingContext::FlushSessionStore() {
|
|
||||||
nsTArray<RefPtr<BrowserChild>> nestedBrowserChilds;
|
|
||||||
|
|
||||||
PreOrderWalk([&](BrowsingContext* aContext) {
|
|
||||||
BrowserChild* browserChild = BrowserChild::GetFrom(aContext->GetDocShell());
|
|
||||||
if (browserChild && browserChild->GetBrowsingContext() == aContext) {
|
|
||||||
nestedBrowserChilds.AppendElement(browserChild);
|
|
||||||
}
|
|
||||||
|
|
||||||
if (aContext->CreatedDynamically()) {
|
|
||||||
return WalkFlag::Skip;
|
|
||||||
}
|
|
||||||
|
|
||||||
WindowContext* windowContext = aContext->GetCurrentWindowContext();
|
|
||||||
if (!windowContext) {
|
|
||||||
return WalkFlag::Skip;
|
|
||||||
}
|
|
||||||
|
|
||||||
WindowGlobalChild* windowChild = windowContext->GetWindowGlobalChild();
|
|
||||||
if (!windowChild) {
|
|
||||||
return WalkFlag::Next;
|
|
||||||
}
|
|
||||||
|
|
||||||
RefPtr<SessionStoreDataCollector> collector =
|
|
||||||
windowChild->GetSessionStoreDataCollector();
|
|
||||||
if (!collector) {
|
|
||||||
return WalkFlag::Next;
|
|
||||||
}
|
|
||||||
|
|
||||||
collector->Flush();
|
|
||||||
return WalkFlag::Next;
|
|
||||||
});
|
|
||||||
|
|
||||||
for (auto& child : nestedBrowserChilds) {
|
|
||||||
child->UpdateSessionStore();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
std::tuple<bool, bool> BrowsingContext::CanFocusCheck(CallerType aCallerType) {
|
std::tuple<bool, bool> BrowsingContext::CanFocusCheck(CallerType aCallerType) {
|
||||||
nsFocusManager* fm = nsFocusManager::GetFocusManager();
|
nsFocusManager* fm = nsFocusManager::GetFocusManager();
|
||||||
if (!fm) {
|
if (!fm) {
|
||||||
@@ -2635,6 +2598,20 @@ nsresult BrowsingContext::ResetGVAutoplayRequestStatus() {
|
|||||||
return txn.Commit(this);
|
return txn.Commit(this);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void BrowsingContext::DidSet(FieldIndex<IDX_SessionStoreEpoch>,
|
||||||
|
uint32_t aOldValue) {
|
||||||
|
if (!mCurrentWindowContext) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
SessionStoreChild* sessionStoreChild =
|
||||||
|
SessionStoreChild::From(mCurrentWindowContext->GetWindowGlobalChild());
|
||||||
|
if (!sessionStoreChild) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
sessionStoreChild->SetEpoch(GetSessionStoreEpoch());
|
||||||
|
}
|
||||||
|
|
||||||
void BrowsingContext::DidSet(FieldIndex<IDX_GVAudibleAutoplayRequestStatus>) {
|
void BrowsingContext::DidSet(FieldIndex<IDX_GVAudibleAutoplayRequestStatus>) {
|
||||||
MOZ_ASSERT(IsTop(),
|
MOZ_ASSERT(IsTop(),
|
||||||
"Should only set GVAudibleAutoplayRequestStatus in the top-level "
|
"Should only set GVAudibleAutoplayRequestStatus in the top-level "
|
||||||
@@ -3407,6 +3384,17 @@ void BrowsingContext::AddDeprioritizedLoadRunner(nsIRunnable* aRunner) {
|
|||||||
EventQueuePriority::Idle);
|
EventQueuePriority::Idle);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
bool BrowsingContext::IsDynamic() const {
|
||||||
|
const BrowsingContext* current = this;
|
||||||
|
do {
|
||||||
|
if (current->CreatedDynamically()) {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
} while ((current = current->GetParent()));
|
||||||
|
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
bool BrowsingContext::GetOffsetPath(nsTArray<uint32_t>& aPath) const {
|
bool BrowsingContext::GetOffsetPath(nsTArray<uint32_t>& aPath) const {
|
||||||
for (const BrowsingContext* current = this; current && current->GetParent();
|
for (const BrowsingContext* current = this; current && current->GetParent();
|
||||||
current = current->GetParent()) {
|
current = current->GetParent()) {
|
||||||
|
|||||||
@@ -784,6 +784,10 @@ class BrowsingContext : public nsILoadContext, public nsWrapperCache {
|
|||||||
|
|
||||||
bool CreatedDynamically() const { return mCreatedDynamically; }
|
bool CreatedDynamically() const { return mCreatedDynamically; }
|
||||||
|
|
||||||
|
// Returns true if this browsing context, or any ancestor to this browsing
|
||||||
|
// context was created dynamically. See also `CreatedDynamically`.
|
||||||
|
bool IsDynamic() const;
|
||||||
|
|
||||||
int32_t ChildOffset() const { return mChildOffset; }
|
int32_t ChildOffset() const { return mChildOffset; }
|
||||||
|
|
||||||
bool GetOffsetPath(nsTArray<uint32_t>& aPath) const;
|
bool GetOffsetPath(nsTArray<uint32_t>& aPath) const;
|
||||||
@@ -889,8 +893,6 @@ class BrowsingContext : public nsILoadContext, public nsWrapperCache {
|
|||||||
return GetPrefersColorSchemeOverride();
|
return GetPrefersColorSchemeOverride();
|
||||||
}
|
}
|
||||||
|
|
||||||
void FlushSessionStore();
|
|
||||||
|
|
||||||
bool IsInBFCache() const;
|
bool IsInBFCache() const;
|
||||||
|
|
||||||
bool AllowJavascript() const { return GetAllowJavascript(); }
|
bool AllowJavascript() const { return GetAllowJavascript(); }
|
||||||
@@ -1002,6 +1004,8 @@ class BrowsingContext : public nsILoadContext, public nsWrapperCache {
|
|||||||
return IsTop() && !aSource;
|
return IsTop() && !aSource;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void DidSet(FieldIndex<IDX_SessionStoreEpoch>, uint32_t aOldValue);
|
||||||
|
|
||||||
using CanSetResult = syncedcontext::CanSetResult;
|
using CanSetResult = syncedcontext::CanSetResult;
|
||||||
|
|
||||||
// Ensure that opener is in the same BrowsingContextGroup.
|
// Ensure that opener is in the same BrowsingContextGroup.
|
||||||
|
|||||||
@@ -2367,7 +2367,7 @@ void CanonicalBrowsingContext::UpdateSessionStoreSessionStorage(
|
|||||||
using DataPromise = BackgroundSessionStorageManager::DataPromise;
|
using DataPromise = BackgroundSessionStorageManager::DataPromise;
|
||||||
BackgroundSessionStorageManager::GetData(
|
BackgroundSessionStorageManager::GetData(
|
||||||
this, StaticPrefs::browser_sessionstore_dom_storage_limit(),
|
this, StaticPrefs::browser_sessionstore_dom_storage_limit(),
|
||||||
/* aCancelSessionStoreTiemr = */ true)
|
/* aClearSessionStoreTimer = */ true)
|
||||||
->Then(GetCurrentSerialEventTarget(), __func__,
|
->Then(GetCurrentSerialEventTarget(), __func__,
|
||||||
[self = RefPtr{this}, aDone, epoch = GetSessionStoreEpoch()](
|
[self = RefPtr{this}, aDone, epoch = GetSessionStoreEpoch()](
|
||||||
const DataPromise::ResolveOrRejectValue& valueList) {
|
const DataPromise::ResolveOrRejectValue& valueList) {
|
||||||
|
|||||||
@@ -55,6 +55,8 @@ class MediaController;
|
|||||||
struct LoadingSessionHistoryInfo;
|
struct LoadingSessionHistoryInfo;
|
||||||
class SSCacheCopy;
|
class SSCacheCopy;
|
||||||
class WindowGlobalParent;
|
class WindowGlobalParent;
|
||||||
|
class SessionStoreFormData;
|
||||||
|
class SessionStoreScrollData;
|
||||||
|
|
||||||
// CanonicalBrowsingContext is a BrowsingContext living in the parent
|
// CanonicalBrowsingContext is a BrowsingContext living in the parent
|
||||||
// process, with whatever extra data that a BrowsingContext in the
|
// process, with whatever extra data that a BrowsingContext in the
|
||||||
@@ -524,6 +526,17 @@ class CanonicalBrowsingContext final : public BrowsingContext {
|
|||||||
|
|
||||||
RefPtr<FeaturePolicy> mContainerFeaturePolicy;
|
RefPtr<FeaturePolicy> mContainerFeaturePolicy;
|
||||||
|
|
||||||
|
friend class BrowserSessionStore;
|
||||||
|
WeakPtr<SessionStoreFormData>& GetSessionStoreFormDataRef() {
|
||||||
|
return mFormdata;
|
||||||
|
}
|
||||||
|
WeakPtr<SessionStoreScrollData>& GetSessionStoreScrollDataRef() {
|
||||||
|
return mScroll;
|
||||||
|
}
|
||||||
|
|
||||||
|
WeakPtr<SessionStoreFormData> mFormdata;
|
||||||
|
WeakPtr<SessionStoreScrollData> mScroll;
|
||||||
|
|
||||||
RefPtr<RestoreState> mRestoreState;
|
RefPtr<RestoreState> mRestoreState;
|
||||||
|
|
||||||
// If this is a top level context, this is true if our browser ID is marked as
|
// If this is a top level context, this is true if our browser ID is marked as
|
||||||
|
|||||||
@@ -78,7 +78,7 @@
|
|||||||
#include "mozilla/dom/SessionHistoryEntry.h"
|
#include "mozilla/dom/SessionHistoryEntry.h"
|
||||||
#include "mozilla/dom/SessionStorageManager.h"
|
#include "mozilla/dom/SessionStorageManager.h"
|
||||||
#include "mozilla/dom/SessionStoreChangeListener.h"
|
#include "mozilla/dom/SessionStoreChangeListener.h"
|
||||||
#include "mozilla/dom/SessionStoreDataCollector.h"
|
#include "mozilla/dom/SessionStoreChild.h"
|
||||||
#include "mozilla/dom/SessionStoreUtils.h"
|
#include "mozilla/dom/SessionStoreUtils.h"
|
||||||
#include "mozilla/dom/BrowserChild.h"
|
#include "mozilla/dom/BrowserChild.h"
|
||||||
#include "mozilla/dom/ToJSValue.h"
|
#include "mozilla/dom/ToJSValue.h"
|
||||||
@@ -5816,7 +5816,12 @@ nsDocShell::OnStateChange(nsIWebProgress* aProgress, nsIRequest* aRequest,
|
|||||||
|
|
||||||
if constexpr (SessionStoreUtils::NATIVE_LISTENER) {
|
if constexpr (SessionStoreUtils::NATIVE_LISTENER) {
|
||||||
if (IsForceReloadType(mLoadType)) {
|
if (IsForceReloadType(mLoadType)) {
|
||||||
SessionStoreUtils::ResetSessionStore(mBrowsingContext);
|
if (WindowContext* windowContext =
|
||||||
|
mBrowsingContext->GetCurrentWindowContext()) {
|
||||||
|
SessionStoreChild::From(windowContext->GetWindowGlobalChild())
|
||||||
|
->SendResetSessionStore(
|
||||||
|
mBrowsingContext, mBrowsingContext->GetSessionStoreEpoch());
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -6557,13 +6562,13 @@ nsresult nsDocShell::EndPageLoad(nsIWebProgress* aProgress,
|
|||||||
return NS_OK;
|
return NS_OK;
|
||||||
}
|
}
|
||||||
if constexpr (SessionStoreUtils::NATIVE_LISTENER) {
|
if constexpr (SessionStoreUtils::NATIVE_LISTENER) {
|
||||||
if (Document* document = GetDocument()) {
|
if (WindowContext* windowContext =
|
||||||
if (WindowGlobalChild* windowChild = document->GetWindowGlobalChild()) {
|
mBrowsingContext->GetCurrentWindowContext()) {
|
||||||
RefPtr<SessionStoreDataCollector> collector =
|
// TODO(farre): File bug: From a user perspective this would probably be
|
||||||
SessionStoreDataCollector::CollectSessionStoreData(windowChild);
|
// just fine to run off the change listener timer. Turns out that a flush
|
||||||
collector->RecordInputChange();
|
// is needed. Several tests depend on this behaviour. Could potentially be
|
||||||
collector->RecordScrollChange();
|
// an optimization for later. See Bug 1756995.
|
||||||
}
|
SessionStoreChangeListener::FlushAllSessionStoreData(windowContext);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -86,15 +86,17 @@
|
|||||||
#include "mozilla/ScopeExit.h"
|
#include "mozilla/ScopeExit.h"
|
||||||
#include "mozilla/StaticPrefs_fission.h"
|
#include "mozilla/StaticPrefs_fission.h"
|
||||||
#include "mozilla/Unused.h"
|
#include "mozilla/Unused.h"
|
||||||
|
#include "mozilla/dom/BrowsingContext.h"
|
||||||
#include "mozilla/dom/ChromeMessageSender.h"
|
#include "mozilla/dom/ChromeMessageSender.h"
|
||||||
#include "mozilla/dom/Element.h"
|
#include "mozilla/dom/Element.h"
|
||||||
#include "mozilla/dom/FrameCrashedEvent.h"
|
#include "mozilla/dom/FrameCrashedEvent.h"
|
||||||
#include "mozilla/dom/FrameLoaderBinding.h"
|
#include "mozilla/dom/FrameLoaderBinding.h"
|
||||||
|
#include "mozilla/dom/InProcessChild.h"
|
||||||
#include "mozilla/dom/MozFrameLoaderOwnerBinding.h"
|
#include "mozilla/dom/MozFrameLoaderOwnerBinding.h"
|
||||||
#include "mozilla/dom/PBrowser.h"
|
#include "mozilla/dom/PBrowser.h"
|
||||||
#include "mozilla/dom/SessionHistoryEntry.h"
|
#include "mozilla/dom/SessionHistoryEntry.h"
|
||||||
#include "mozilla/dom/SessionStoreChangeListener.h"
|
#include "mozilla/dom/SessionStoreChild.h"
|
||||||
#include "mozilla/dom/SessionStoreListener.h"
|
#include "mozilla/dom/SessionStoreParent.h"
|
||||||
#include "mozilla/dom/SessionStoreUtils.h"
|
#include "mozilla/dom/SessionStoreUtils.h"
|
||||||
#include "mozilla/dom/WindowGlobalParent.h"
|
#include "mozilla/dom/WindowGlobalParent.h"
|
||||||
#include "mozilla/dom/XULFrameElement.h"
|
#include "mozilla/dom/XULFrameElement.h"
|
||||||
@@ -164,8 +166,7 @@ using PrintPreviewResolver = std::function<void(const PrintPreviewResultInfo&)>;
|
|||||||
|
|
||||||
NS_IMPL_CYCLE_COLLECTION_WRAPPERCACHE(nsFrameLoader, mPendingBrowsingContext,
|
NS_IMPL_CYCLE_COLLECTION_WRAPPERCACHE(nsFrameLoader, mPendingBrowsingContext,
|
||||||
mMessageManager, mChildMessageManager,
|
mMessageManager, mChildMessageManager,
|
||||||
mRemoteBrowser,
|
mRemoteBrowser, mSessionStoreChild)
|
||||||
mSessionStoreChangeListener)
|
|
||||||
NS_IMPL_CYCLE_COLLECTING_ADDREF(nsFrameLoader)
|
NS_IMPL_CYCLE_COLLECTING_ADDREF(nsFrameLoader)
|
||||||
NS_IMPL_CYCLE_COLLECTING_RELEASE(nsFrameLoader)
|
NS_IMPL_CYCLE_COLLECTING_RELEASE(nsFrameLoader)
|
||||||
|
|
||||||
@@ -2041,14 +2042,9 @@ void nsFrameLoader::DestroyDocShell() {
|
|||||||
mChildMessageManager->FireUnloadEvent();
|
mChildMessageManager->FireUnloadEvent();
|
||||||
}
|
}
|
||||||
|
|
||||||
if (mSessionStoreListener) {
|
if (mSessionStoreChild) {
|
||||||
mSessionStoreListener->RemoveListeners();
|
mSessionStoreChild->Stop();
|
||||||
mSessionStoreListener = nullptr;
|
mSessionStoreChild = nullptr;
|
||||||
}
|
|
||||||
|
|
||||||
if (mSessionStoreChangeListener) {
|
|
||||||
mSessionStoreChangeListener->Stop();
|
|
||||||
mSessionStoreChangeListener = nullptr;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// Destroy the docshell.
|
// Destroy the docshell.
|
||||||
@@ -2141,22 +2137,22 @@ void nsFrameLoader::SetOwnerContent(Element* aContent) {
|
|||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
if (mSessionStoreListener && mOwnerContent) {
|
if (mSessionStoreChild && mOwnerContent) {
|
||||||
// mOwnerContent will only be null when the frame loader is being destroyed,
|
// mOwnerContent will only be null when the frame loader is being destroyed,
|
||||||
// so the session store listener will be destroyed along with it.
|
// so the session store listener will be destroyed along with it.
|
||||||
// XXX(farre): This probably needs to update the cache. See bug 1698497.
|
// XXX(farre): This probably needs to update the cache. See bug 1698497.
|
||||||
mSessionStoreListener->SetOwnerContent(mOwnerContent);
|
mSessionStoreChild->SetOwnerContent(mOwnerContent);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (RefPtr<BrowsingContext> browsingContext = GetExtantBrowsingContext()) {
|
if (RefPtr<BrowsingContext> browsingContext = GetExtantBrowsingContext()) {
|
||||||
browsingContext->SetEmbedderElement(mOwnerContent);
|
browsingContext->SetEmbedderElement(mOwnerContent);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (mSessionStoreChangeListener) {
|
if (mSessionStoreChild) {
|
||||||
// UpdateEventTargets will requery its browser contexts for event
|
// UpdateEventTargets will requery its browser contexts for event
|
||||||
// targets, so this call needs to happen after the call to
|
// targets, so this call needs to happen after the call to
|
||||||
// SetEmbedderElement above.
|
// SetEmbedderElement above.
|
||||||
mSessionStoreChangeListener->UpdateEventTargets();
|
mSessionStoreChild->UpdateEventTargets();
|
||||||
}
|
}
|
||||||
|
|
||||||
AutoJSAPI jsapi;
|
AutoJSAPI jsapi;
|
||||||
@@ -3101,15 +3097,11 @@ nsresult nsFrameLoader::EnsureMessageManager() {
|
|||||||
GetDocShell(), mOwnerContent, mMessageManager);
|
GetDocShell(), mOwnerContent, mMessageManager);
|
||||||
NS_ENSURE_TRUE(mChildMessageManager, NS_ERROR_UNEXPECTED);
|
NS_ENSURE_TRUE(mChildMessageManager, NS_ERROR_UNEXPECTED);
|
||||||
|
|
||||||
// Set up a TabListener for sessionStore
|
// Set up session store
|
||||||
if constexpr (SessionStoreUtils::NATIVE_LISTENER) {
|
if constexpr (SessionStoreUtils::NATIVE_LISTENER) {
|
||||||
if (XRE_IsParentProcess()) {
|
if (XRE_IsParentProcess() && mIsTopLevelContent) {
|
||||||
mSessionStoreListener = new TabListener(GetDocShell(), mOwnerContent);
|
mSessionStoreChild = SessionStoreChild::GetOrCreate(
|
||||||
rv = mSessionStoreListener->Init();
|
GetExtantBrowsingContext(), mOwnerContent);
|
||||||
NS_ENSURE_SUCCESS(rv, rv);
|
|
||||||
|
|
||||||
mSessionStoreChangeListener =
|
|
||||||
SessionStoreChangeListener::Create(GetExtantBrowsingContext());
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -3237,6 +3229,21 @@ void nsFrameLoader::RequestUpdatePosition(ErrorResult& aRv) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
SessionStoreParent* nsFrameLoader::GetSessionStoreParent() {
|
||||||
|
MOZ_DIAGNOSTIC_ASSERT(XRE_IsParentProcess());
|
||||||
|
if (mSessionStoreChild) {
|
||||||
|
return static_cast<SessionStoreParent*>(
|
||||||
|
InProcessChild::ParentActorFor(mSessionStoreChild));
|
||||||
|
}
|
||||||
|
|
||||||
|
if (BrowserParent* browserParent = GetBrowserParent()) {
|
||||||
|
return static_cast<SessionStoreParent*>(
|
||||||
|
SingleManagedOrNull(browserParent->ManagedPSessionStoreParent()));
|
||||||
|
}
|
||||||
|
|
||||||
|
return nullptr;
|
||||||
|
}
|
||||||
|
|
||||||
already_AddRefed<Promise> nsFrameLoader::RequestTabStateFlush(
|
already_AddRefed<Promise> nsFrameLoader::RequestTabStateFlush(
|
||||||
ErrorResult& aRv) {
|
ErrorResult& aRv) {
|
||||||
MOZ_DIAGNOSTIC_ASSERT(XRE_IsParentProcess());
|
MOZ_DIAGNOSTIC_ASSERT(XRE_IsParentProcess());
|
||||||
@@ -3247,42 +3254,24 @@ already_AddRefed<Promise> nsFrameLoader::RequestTabStateFlush(
|
|||||||
}
|
}
|
||||||
|
|
||||||
RefPtr<Promise> promise = Promise::Create(ownerDoc->GetOwnerGlobal(), aRv);
|
RefPtr<Promise> promise = Promise::Create(ownerDoc->GetOwnerGlobal(), aRv);
|
||||||
|
|
||||||
if (aRv.Failed()) {
|
if (aRv.Failed()) {
|
||||||
return nullptr;
|
return nullptr;
|
||||||
}
|
}
|
||||||
|
|
||||||
RefPtr<BrowsingContext> context = GetExtantBrowsingContext();
|
BrowsingContext* browsingContext = GetExtantBrowsingContext();
|
||||||
if (!context) {
|
if (!browsingContext) {
|
||||||
promise->MaybeResolveWithUndefined();
|
promise->MaybeResolveWithUndefined();
|
||||||
return promise.forget();
|
return promise.forget();
|
||||||
}
|
}
|
||||||
|
|
||||||
if (mSessionStoreListener) {
|
SessionStoreParent* sessionStoreParent = GetSessionStoreParent();
|
||||||
context->FlushSessionStore();
|
if (!sessionStoreParent) {
|
||||||
mSessionStoreListener->ForceFlushFromParent();
|
promise->MaybeResolveWithUndefined();
|
||||||
context->Canonical()->UpdateSessionStoreSessionStorage(
|
|
||||||
[promise]() { promise->MaybeResolveWithUndefined(); });
|
|
||||||
|
|
||||||
return promise.forget();
|
return promise.forget();
|
||||||
}
|
}
|
||||||
|
|
||||||
using FlushPromise = ContentParent::FlushTabStatePromise;
|
sessionStoreParent->FlushAllSessionStoreChildren(
|
||||||
nsTArray<RefPtr<FlushPromise>> flushPromises;
|
[promise]() { promise->MaybeResolveWithUndefined(); });
|
||||||
context->Group()->EachParent([&](ContentParent* aParent) {
|
|
||||||
if (aParent->CanSend()) {
|
|
||||||
flushPromises.AppendElement(aParent->SendFlushTabState(context));
|
|
||||||
}
|
|
||||||
});
|
|
||||||
|
|
||||||
RefPtr<FlushPromise::AllPromiseType> flushPromise =
|
|
||||||
FlushPromise::All(GetCurrentSerialEventTarget(), flushPromises);
|
|
||||||
|
|
||||||
context->Canonical()->UpdateSessionStoreSessionStorage([flushPromise,
|
|
||||||
promise]() {
|
|
||||||
flushPromise->Then(GetCurrentSerialEventTarget(), __func__,
|
|
||||||
[promise]() { promise->MaybeResolveWithUndefined(); });
|
|
||||||
});
|
|
||||||
|
|
||||||
return promise.forget();
|
return promise.forget();
|
||||||
}
|
}
|
||||||
@@ -3297,10 +3286,8 @@ void nsFrameLoader::RequestFinalTabStateFlush() {
|
|||||||
RefPtr<WindowGlobalParent> wgp = canonical->GetCurrentWindowGlobal();
|
RefPtr<WindowGlobalParent> wgp = canonical->GetCurrentWindowGlobal();
|
||||||
RefPtr<Element> embedder = context->GetEmbedderElement();
|
RefPtr<Element> embedder = context->GetEmbedderElement();
|
||||||
|
|
||||||
if (mSessionStoreListener) {
|
RefPtr<SessionStoreParent> sessionStoreParent = GetSessionStoreParent();
|
||||||
context->FlushSessionStore();
|
if (!sessionStoreParent) {
|
||||||
mSessionStoreListener->ForceFlushFromParent();
|
|
||||||
|
|
||||||
canonical->ClearPermanentKey();
|
canonical->ClearPermanentKey();
|
||||||
if (wgp) {
|
if (wgp) {
|
||||||
wgp->NotifySessionStoreUpdatesComplete(embedder);
|
wgp->NotifySessionStoreUpdatesComplete(embedder);
|
||||||
@@ -3309,24 +3296,15 @@ void nsFrameLoader::RequestFinalTabStateFlush() {
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
using FlushPromise = ContentParent::FlushTabStatePromise;
|
sessionStoreParent->FinalFlushAllSessionStoreChildren(
|
||||||
nsTArray<RefPtr<FlushPromise>> flushPromises;
|
[canonical, wgp, embedder]() {
|
||||||
context->Group()->EachParent([&](ContentParent* aParent) {
|
if (canonical) {
|
||||||
if (aParent->CanSend()) {
|
canonical->ClearPermanentKey();
|
||||||
flushPromises.AppendElement(aParent->SendFlushTabState(context));
|
}
|
||||||
}
|
if (wgp) {
|
||||||
});
|
wgp->NotifySessionStoreUpdatesComplete(embedder);
|
||||||
|
}
|
||||||
FlushPromise::All(GetCurrentSerialEventTarget(), flushPromises)
|
});
|
||||||
->Then(GetCurrentSerialEventTarget(), __func__,
|
|
||||||
[canonical = RefPtr{canonical}, wgp, embedder]() {
|
|
||||||
if (canonical) {
|
|
||||||
canonical->ClearPermanentKey();
|
|
||||||
}
|
|
||||||
if (wgp) {
|
|
||||||
wgp->NotifySessionStoreUpdatesComplete(embedder);
|
|
||||||
}
|
|
||||||
});
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void nsFrameLoader::RequestEpochUpdate(uint32_t aEpoch) {
|
void nsFrameLoader::RequestEpochUpdate(uint32_t aEpoch) {
|
||||||
@@ -3335,21 +3313,11 @@ void nsFrameLoader::RequestEpochUpdate(uint32_t aEpoch) {
|
|||||||
BrowsingContext* top = context->Top();
|
BrowsingContext* top = context->Top();
|
||||||
Unused << top->SetSessionStoreEpoch(aEpoch);
|
Unused << top->SetSessionStoreEpoch(aEpoch);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (mSessionStoreListener) {
|
|
||||||
mSessionStoreListener->SetEpoch(aEpoch);
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
// If remote browsing (e10s), handle this with the BrowserParent.
|
|
||||||
if (auto* browserParent = GetBrowserParent()) {
|
|
||||||
Unused << browserParent->SendUpdateEpoch(aEpoch);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void nsFrameLoader::RequestSHistoryUpdate() {
|
void nsFrameLoader::RequestSHistoryUpdate() {
|
||||||
if (mSessionStoreListener) {
|
if (mSessionStoreChild) {
|
||||||
mSessionStoreListener->UpdateSHistoryChanges();
|
mSessionStoreChild->UpdateSHistoryChanges();
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -63,7 +63,6 @@ class ChromeMessageSender;
|
|||||||
class ContentParent;
|
class ContentParent;
|
||||||
class Document;
|
class Document;
|
||||||
class Element;
|
class Element;
|
||||||
class TabListener;
|
|
||||||
class InProcessBrowserChildMessageManager;
|
class InProcessBrowserChildMessageManager;
|
||||||
class MessageSender;
|
class MessageSender;
|
||||||
class ProcessMessageManager;
|
class ProcessMessageManager;
|
||||||
@@ -73,7 +72,8 @@ class BrowserBridgeChild;
|
|||||||
class RemoteBrowser;
|
class RemoteBrowser;
|
||||||
struct RemotenessOptions;
|
struct RemotenessOptions;
|
||||||
struct NavigationIsolationOptions;
|
struct NavigationIsolationOptions;
|
||||||
class SessionStoreChangeListener;
|
class SessionStoreChild;
|
||||||
|
class SessionStoreParent;
|
||||||
|
|
||||||
namespace ipc {
|
namespace ipc {
|
||||||
class StructuredCloneData;
|
class StructuredCloneData;
|
||||||
@@ -411,6 +411,12 @@ class nsFrameLoader final : public nsStubMutationObserver,
|
|||||||
|
|
||||||
void FireErrorEvent();
|
void FireErrorEvent();
|
||||||
|
|
||||||
|
mozilla::dom::SessionStoreChild* GetSessionStoreChild() {
|
||||||
|
return mSessionStoreChild;
|
||||||
|
}
|
||||||
|
|
||||||
|
mozilla::dom::SessionStoreParent* GetSessionStoreParent();
|
||||||
|
|
||||||
private:
|
private:
|
||||||
nsFrameLoader(mozilla::dom::Element* aOwner,
|
nsFrameLoader(mozilla::dom::Element* aOwner,
|
||||||
mozilla::dom::BrowsingContext* aBrowsingContext, bool aIsRemote,
|
mozilla::dom::BrowsingContext* aBrowsingContext, bool aIsRemote,
|
||||||
@@ -520,9 +526,10 @@ class nsFrameLoader final : public nsStubMutationObserver,
|
|||||||
// Holds the last known size of the frame.
|
// Holds the last known size of the frame.
|
||||||
mozilla::ScreenIntSize mLazySize;
|
mozilla::ScreenIntSize mLazySize;
|
||||||
|
|
||||||
RefPtr<mozilla::dom::TabListener> mSessionStoreListener;
|
// Actor for collecting session store data from content children. This will be
|
||||||
|
// cleared and set to null eagerly when taking down the frameloader to break
|
||||||
RefPtr<mozilla::dom::SessionStoreChangeListener> mSessionStoreChangeListener;
|
// refcounted cycles early.
|
||||||
|
RefPtr<mozilla::dom::SessionStoreChild> mSessionStoreChild;
|
||||||
|
|
||||||
nsCString mRemoteType;
|
nsCString mRemoteType;
|
||||||
|
|
||||||
|
|||||||
47
dom/chrome-webidl/BrowserSessionStore.webidl
Normal file
47
dom/chrome-webidl/BrowserSessionStore.webidl
Normal file
@@ -0,0 +1,47 @@
|
|||||||
|
/* -*- Mode: IDL; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
|
||||||
|
/* This Source Code Form is subject to the terms of the Mozilla Public
|
||||||
|
* License, v. 2.0. If a copy of the MPL was not distributed with this
|
||||||
|
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
|
||||||
|
|
||||||
|
// object contains either a CollectedFileListValue or a CollectedNonMultipleSelectValue or Sequence<DOMString>
|
||||||
|
typedef (DOMString or boolean or object) FormDataValue;
|
||||||
|
|
||||||
|
[ChromeOnly, Exposed=Window]
|
||||||
|
interface SessionStoreFormData {
|
||||||
|
[Cached, Pure]
|
||||||
|
readonly attribute ByteString? url;
|
||||||
|
|
||||||
|
[Cached, Pure]
|
||||||
|
readonly attribute record<DOMString, FormDataValue>? id;
|
||||||
|
|
||||||
|
[Cached, Pure]
|
||||||
|
readonly attribute record<DOMString, FormDataValue>? xpath;
|
||||||
|
|
||||||
|
[Cached, Pure]
|
||||||
|
readonly attribute DOMString? innerHTML;
|
||||||
|
|
||||||
|
[Cached, Frozen, Pure]
|
||||||
|
readonly attribute sequence<SessionStoreFormData?>? children;
|
||||||
|
|
||||||
|
object toJSON();
|
||||||
|
};
|
||||||
|
|
||||||
|
[ChromeOnly, Exposed=Window]
|
||||||
|
interface SessionStoreScrollData {
|
||||||
|
[Cached, Pure]
|
||||||
|
readonly attribute ByteString? scroll;
|
||||||
|
|
||||||
|
[Cached, Pure]
|
||||||
|
readonly attribute sequence<SessionStoreScrollData?>? children;
|
||||||
|
|
||||||
|
object toJSON();
|
||||||
|
};
|
||||||
|
|
||||||
|
[GenerateConversionToJS]
|
||||||
|
dictionary UpdateSessionStoreData {
|
||||||
|
// This is docshell caps, but on-disk format uses the disallow property name.
|
||||||
|
ByteString? disallow;
|
||||||
|
boolean isPrivate;
|
||||||
|
SessionStoreFormData? formdata;
|
||||||
|
SessionStoreScrollData? scroll;
|
||||||
|
};
|
||||||
@@ -167,28 +167,3 @@ dictionary InputElementData {
|
|||||||
sequence<DOMString> strVal;
|
sequence<DOMString> strVal;
|
||||||
sequence<boolean> boolVal;
|
sequence<boolean> boolVal;
|
||||||
};
|
};
|
||||||
|
|
||||||
[GenerateConversionToJS]
|
|
||||||
dictionary UpdateSessionStoreData {
|
|
||||||
ByteString docShellCaps;
|
|
||||||
boolean isPrivate;
|
|
||||||
};
|
|
||||||
|
|
||||||
[GenerateConversionToJS]
|
|
||||||
dictionary SessionStoreWindowStateChange {
|
|
||||||
SessionStoreFormData formdata;
|
|
||||||
SessionStoreScroll scroll;
|
|
||||||
boolean hasChildren;
|
|
||||||
required sequence<unsigned long> path;
|
|
||||||
};
|
|
||||||
|
|
||||||
dictionary SessionStoreFormData {
|
|
||||||
ByteString url;
|
|
||||||
record<DOMString, CollectedFormDataValue> id;
|
|
||||||
record<DOMString, CollectedFormDataValue> xpath;
|
|
||||||
DOMString innerHTML;
|
|
||||||
};
|
|
||||||
|
|
||||||
dictionary SessionStoreScroll {
|
|
||||||
ByteString scroll;
|
|
||||||
};
|
|
||||||
|
|||||||
@@ -37,6 +37,7 @@ PREPROCESSED_WEBIDL_FILES = [
|
|||||||
]
|
]
|
||||||
|
|
||||||
WEBIDL_FILES = [
|
WEBIDL_FILES = [
|
||||||
|
"BrowserSessionStore.webidl",
|
||||||
"BrowsingContext.webidl",
|
"BrowsingContext.webidl",
|
||||||
"ChannelWrapper.webidl",
|
"ChannelWrapper.webidl",
|
||||||
"ClonedErrorHolder.webidl",
|
"ClonedErrorHolder.webidl",
|
||||||
|
|||||||
@@ -69,10 +69,8 @@
|
|||||||
#include "mozilla/dom/PBrowser.h"
|
#include "mozilla/dom/PBrowser.h"
|
||||||
#include "mozilla/dom/PaymentRequestChild.h"
|
#include "mozilla/dom/PaymentRequestChild.h"
|
||||||
#include "mozilla/dom/PointerEventHandler.h"
|
#include "mozilla/dom/PointerEventHandler.h"
|
||||||
#include "mozilla/dom/SessionStoreChangeListener.h"
|
|
||||||
#include "mozilla/dom/SessionStoreDataCollector.h"
|
|
||||||
#include "mozilla/dom/SessionStoreListener.h"
|
|
||||||
#include "mozilla/dom/SessionStoreUtils.h"
|
#include "mozilla/dom/SessionStoreUtils.h"
|
||||||
|
#include "mozilla/dom/SessionStoreChild.h"
|
||||||
#include "mozilla/dom/WindowGlobalChild.h"
|
#include "mozilla/dom/WindowGlobalChild.h"
|
||||||
#include "mozilla/dom/WindowProxyHolder.h"
|
#include "mozilla/dom/WindowProxyHolder.h"
|
||||||
#include "mozilla/gfx/CrossProcessPaint.h"
|
#include "mozilla/gfx/CrossProcessPaint.h"
|
||||||
@@ -522,12 +520,7 @@ nsresult BrowserChild::Init(mozIDOMWindowProxy* aParent,
|
|||||||
mIPCOpen = true;
|
mIPCOpen = true;
|
||||||
|
|
||||||
if constexpr (SessionStoreUtils::NATIVE_LISTENER) {
|
if constexpr (SessionStoreUtils::NATIVE_LISTENER) {
|
||||||
mSessionStoreListener = new TabListener(docShell, nullptr);
|
mSessionStoreChild = SessionStoreChild::GetOrCreate(mBrowsingContext);
|
||||||
rv = mSessionStoreListener->Init();
|
|
||||||
NS_ENSURE_SUCCESS(rv, rv);
|
|
||||||
|
|
||||||
mSessionStoreChangeListener =
|
|
||||||
SessionStoreChangeListener::Create(mBrowsingContext);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// We've all set up, make sure our visibility state is consistent. This is
|
// We've all set up, make sure our visibility state is consistent. This is
|
||||||
@@ -545,8 +538,7 @@ NS_IMPL_CYCLE_COLLECTION_UNLINK_BEGIN(BrowserChild)
|
|||||||
NS_IMPL_CYCLE_COLLECTION_UNLINK(mStatusFilter)
|
NS_IMPL_CYCLE_COLLECTION_UNLINK(mStatusFilter)
|
||||||
NS_IMPL_CYCLE_COLLECTION_UNLINK(mWebNav)
|
NS_IMPL_CYCLE_COLLECTION_UNLINK(mWebNav)
|
||||||
NS_IMPL_CYCLE_COLLECTION_UNLINK(mBrowsingContext)
|
NS_IMPL_CYCLE_COLLECTION_UNLINK(mBrowsingContext)
|
||||||
NS_IMPL_CYCLE_COLLECTION_UNLINK(mSessionStoreListener)
|
NS_IMPL_CYCLE_COLLECTION_UNLINK(mSessionStoreChild)
|
||||||
NS_IMPL_CYCLE_COLLECTION_UNLINK(mSessionStoreChangeListener)
|
|
||||||
NS_IMPL_CYCLE_COLLECTION_UNLINK_WEAK_REFERENCE
|
NS_IMPL_CYCLE_COLLECTION_UNLINK_WEAK_REFERENCE
|
||||||
NS_IMPL_CYCLE_COLLECTION_UNLINK_END
|
NS_IMPL_CYCLE_COLLECTION_UNLINK_END
|
||||||
|
|
||||||
@@ -555,8 +547,7 @@ NS_IMPL_CYCLE_COLLECTION_TRAVERSE_BEGIN(BrowserChild)
|
|||||||
NS_IMPL_CYCLE_COLLECTION_TRAVERSE(mStatusFilter)
|
NS_IMPL_CYCLE_COLLECTION_TRAVERSE(mStatusFilter)
|
||||||
NS_IMPL_CYCLE_COLLECTION_TRAVERSE(mWebNav)
|
NS_IMPL_CYCLE_COLLECTION_TRAVERSE(mWebNav)
|
||||||
NS_IMPL_CYCLE_COLLECTION_TRAVERSE(mBrowsingContext)
|
NS_IMPL_CYCLE_COLLECTION_TRAVERSE(mBrowsingContext)
|
||||||
NS_IMPL_CYCLE_COLLECTION_TRAVERSE(mSessionStoreListener)
|
NS_IMPL_CYCLE_COLLECTION_TRAVERSE(mSessionStoreChild)
|
||||||
NS_IMPL_CYCLE_COLLECTION_TRAVERSE(mSessionStoreChangeListener)
|
|
||||||
NS_IMPL_CYCLE_COLLECTION_TRAVERSE_END
|
NS_IMPL_CYCLE_COLLECTION_TRAVERSE_END
|
||||||
|
|
||||||
NS_IMPL_CYCLE_COLLECTION_TRACE_BEGIN(BrowserChild)
|
NS_IMPL_CYCLE_COLLECTION_TRACE_BEGIN(BrowserChild)
|
||||||
@@ -849,14 +840,9 @@ void BrowserChild::DestroyWindow() {
|
|||||||
mCoalescedTouchMoveEventFlusher = nullptr;
|
mCoalescedTouchMoveEventFlusher = nullptr;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (mSessionStoreListener) {
|
if (mSessionStoreChild) {
|
||||||
mSessionStoreListener->RemoveListeners();
|
mSessionStoreChild->Stop();
|
||||||
mSessionStoreListener = nullptr;
|
mSessionStoreChild = nullptr;
|
||||||
}
|
|
||||||
|
|
||||||
if (mSessionStoreChangeListener) {
|
|
||||||
mSessionStoreChangeListener->Stop();
|
|
||||||
mSessionStoreChangeListener = nullptr;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// In case we don't have chance to process all entries, clean all data in
|
// In case we don't have chance to process all entries, clean all data in
|
||||||
@@ -2060,16 +2046,9 @@ mozilla::ipc::IPCResult BrowserChild::RecvNativeSynthesisResponse(
|
|||||||
return IPC_OK();
|
return IPC_OK();
|
||||||
}
|
}
|
||||||
|
|
||||||
mozilla::ipc::IPCResult BrowserChild::RecvUpdateEpoch(const uint32_t& aEpoch) {
|
|
||||||
if (mSessionStoreListener) {
|
|
||||||
mSessionStoreListener->SetEpoch(aEpoch);
|
|
||||||
}
|
|
||||||
return IPC_OK();
|
|
||||||
}
|
|
||||||
|
|
||||||
mozilla::ipc::IPCResult BrowserChild::RecvUpdateSHistory() {
|
mozilla::ipc::IPCResult BrowserChild::RecvUpdateSHistory() {
|
||||||
if (mSessionStoreListener) {
|
if (mSessionStoreChild) {
|
||||||
mSessionStoreListener->UpdateSHistoryChanges();
|
mSessionStoreChild->UpdateSHistoryChanges();
|
||||||
}
|
}
|
||||||
return IPC_OK();
|
return IPC_OK();
|
||||||
}
|
}
|
||||||
@@ -3809,26 +3788,10 @@ nsresult BrowserChild::PrepareProgressListenerData(
|
|||||||
return PrepareRequestData(aRequest, aRequestData);
|
return PrepareRequestData(aRequest, aRequestData);
|
||||||
}
|
}
|
||||||
|
|
||||||
bool BrowserChild::UpdateSessionStore() {
|
void BrowserChild::UpdateSessionStore() {
|
||||||
if (!mSessionStoreListener) {
|
if (mSessionStoreChild) {
|
||||||
return false;
|
mSessionStoreChild->UpdateSessionStore();
|
||||||
}
|
}
|
||||||
RefPtr<ContentSessionStore> store = mSessionStoreListener->GetSessionStore();
|
|
||||||
|
|
||||||
Maybe<nsCString> docShellCaps;
|
|
||||||
if (store->IsDocCapChanged()) {
|
|
||||||
docShellCaps.emplace(store->GetDocShellCaps());
|
|
||||||
}
|
|
||||||
|
|
||||||
Maybe<bool> privatedMode;
|
|
||||||
if (store->IsPrivateChanged()) {
|
|
||||||
privatedMode.emplace(store->GetPrivateModeEnabled());
|
|
||||||
}
|
|
||||||
|
|
||||||
Unused << SendSessionStoreUpdate(docShellCaps, privatedMode,
|
|
||||||
store->GetAndClearSHistoryChanged(),
|
|
||||||
mSessionStoreListener->GetEpoch());
|
|
||||||
return true;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
#ifdef XP_WIN
|
#ifdef XP_WIN
|
||||||
|
|||||||
@@ -86,9 +86,7 @@ class TabGroup;
|
|||||||
class ClonedMessageData;
|
class ClonedMessageData;
|
||||||
class CoalescedMouseData;
|
class CoalescedMouseData;
|
||||||
class CoalescedWheelData;
|
class CoalescedWheelData;
|
||||||
class ContentSessionStore;
|
class SessionStoreChild;
|
||||||
class SessionStoreChangeListener;
|
|
||||||
class TabListener;
|
|
||||||
class RequestData;
|
class RequestData;
|
||||||
class WebProgressData;
|
class WebProgressData;
|
||||||
|
|
||||||
@@ -396,8 +394,6 @@ class BrowserChild final : public nsMessageManagerScriptExecutor,
|
|||||||
aApzResponse);
|
aApzResponse);
|
||||||
}
|
}
|
||||||
|
|
||||||
mozilla::ipc::IPCResult RecvUpdateEpoch(const uint32_t& aEpoch);
|
|
||||||
|
|
||||||
mozilla::ipc::IPCResult RecvUpdateSHistory();
|
mozilla::ipc::IPCResult RecvUpdateSHistory();
|
||||||
|
|
||||||
mozilla::ipc::IPCResult RecvNativeSynthesisResponse(
|
mozilla::ipc::IPCResult RecvNativeSynthesisResponse(
|
||||||
@@ -673,7 +669,11 @@ class BrowserChild final : public nsMessageManagerScriptExecutor,
|
|||||||
mCancelContentJSEpoch = aEpoch;
|
mCancelContentJSEpoch = aEpoch;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool UpdateSessionStore();
|
void UpdateSessionStore();
|
||||||
|
|
||||||
|
mozilla::dom::SessionStoreChild* GetSessionStoreChild() {
|
||||||
|
return mSessionStoreChild;
|
||||||
|
}
|
||||||
|
|
||||||
#ifdef XP_WIN
|
#ifdef XP_WIN
|
||||||
// Check if the window this BrowserChild is associated with supports
|
// Check if the window this BrowserChild is associated with supports
|
||||||
@@ -892,8 +892,7 @@ class BrowserChild final : public nsMessageManagerScriptExecutor,
|
|||||||
RefPtr<CoalescedTouchMoveFlusher> mCoalescedTouchMoveEventFlusher;
|
RefPtr<CoalescedTouchMoveFlusher> mCoalescedTouchMoveEventFlusher;
|
||||||
|
|
||||||
RefPtr<layers::IAPZCTreeManager> mApzcTreeManager;
|
RefPtr<layers::IAPZCTreeManager> mApzcTreeManager;
|
||||||
RefPtr<TabListener> mSessionStoreListener;
|
RefPtr<SessionStoreChild> mSessionStoreChild;
|
||||||
RefPtr<SessionStoreChangeListener> mSessionStoreChangeListener;
|
|
||||||
|
|
||||||
// The most recently seen layer observer epoch in RecvSetDocShellIsActive.
|
// The most recently seen layer observer epoch in RecvSetDocShellIsActive.
|
||||||
layers::LayersObserverEpoch mLayersObserverEpoch;
|
layers::LayersObserverEpoch mLayersObserverEpoch;
|
||||||
|
|||||||
@@ -16,6 +16,7 @@
|
|||||||
#endif
|
#endif
|
||||||
#include "mozilla/Components.h"
|
#include "mozilla/Components.h"
|
||||||
#include "mozilla/dom/BrowserHost.h"
|
#include "mozilla/dom/BrowserHost.h"
|
||||||
|
#include "mozilla/dom/BrowserSessionStore.h"
|
||||||
#include "mozilla/dom/BrowsingContextGroup.h"
|
#include "mozilla/dom/BrowsingContextGroup.h"
|
||||||
#include "mozilla/dom/CancelContentJSOptionsBinding.h"
|
#include "mozilla/dom/CancelContentJSOptionsBinding.h"
|
||||||
#include "mozilla/dom/ChromeMessageSender.h"
|
#include "mozilla/dom/ChromeMessageSender.h"
|
||||||
@@ -32,8 +33,7 @@
|
|||||||
#include "mozilla/dom/RemoteDragStartData.h"
|
#include "mozilla/dom/RemoteDragStartData.h"
|
||||||
#include "mozilla/dom/RemoteWebProgressRequest.h"
|
#include "mozilla/dom/RemoteWebProgressRequest.h"
|
||||||
#include "mozilla/dom/SessionHistoryEntry.h"
|
#include "mozilla/dom/SessionHistoryEntry.h"
|
||||||
#include "mozilla/dom/SessionStoreUtils.h"
|
#include "mozilla/dom/SessionStoreParent.h"
|
||||||
#include "mozilla/dom/SessionStoreUtilsBinding.h"
|
|
||||||
#include "mozilla/dom/UserActivation.h"
|
#include "mozilla/dom/UserActivation.h"
|
||||||
#include "mozilla/EventStateManager.h"
|
#include "mozilla/EventStateManager.h"
|
||||||
#include "mozilla/gfx/2D.h"
|
#include "mozilla/gfx/2D.h"
|
||||||
@@ -53,6 +53,7 @@
|
|||||||
#include "mozilla/Preferences.h"
|
#include "mozilla/Preferences.h"
|
||||||
#include "mozilla/PresShell.h"
|
#include "mozilla/PresShell.h"
|
||||||
#include "mozilla/ProcessHangMonitor.h"
|
#include "mozilla/ProcessHangMonitor.h"
|
||||||
|
#include "mozilla/RefPtr.h"
|
||||||
#include "mozilla/StaticPrefs_accessibility.h"
|
#include "mozilla/StaticPrefs_accessibility.h"
|
||||||
#include "mozilla/StaticPrefs_dom.h"
|
#include "mozilla/StaticPrefs_dom.h"
|
||||||
#include "mozilla/TextEventDispatcher.h"
|
#include "mozilla/TextEventDispatcher.h"
|
||||||
@@ -128,7 +129,6 @@
|
|||||||
#include "mozilla/dom/CanonicalBrowsingContext.h"
|
#include "mozilla/dom/CanonicalBrowsingContext.h"
|
||||||
#include "mozilla/ProfilerLabels.h"
|
#include "mozilla/ProfilerLabels.h"
|
||||||
#include "MMPrinter.h"
|
#include "MMPrinter.h"
|
||||||
#include "SessionStoreFunctions.h"
|
|
||||||
#include "mozilla/dom/CrashReport.h"
|
#include "mozilla/dom/CrashReport.h"
|
||||||
#include "nsISecureBrowserUI.h"
|
#include "nsISecureBrowserUI.h"
|
||||||
#include "nsIXULRuntime.h"
|
#include "nsIXULRuntime.h"
|
||||||
@@ -1372,6 +1372,17 @@ IPCResult BrowserParent::RecvIndexedDBPermissionRequest(
|
|||||||
return IPC_OK();
|
return IPC_OK();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
already_AddRefed<PSessionStoreParent>
|
||||||
|
BrowserParent::AllocPSessionStoreParent() {
|
||||||
|
RefPtr<BrowserSessionStore> sessionStore =
|
||||||
|
BrowserSessionStore::GetOrCreate(mBrowsingContext->Top());
|
||||||
|
if (!sessionStore) {
|
||||||
|
return nullptr;
|
||||||
|
}
|
||||||
|
|
||||||
|
return do_AddRef(new SessionStoreParent(mBrowsingContext, sessionStore));
|
||||||
|
}
|
||||||
|
|
||||||
IPCResult BrowserParent::RecvNewWindowGlobal(
|
IPCResult BrowserParent::RecvNewWindowGlobal(
|
||||||
ManagedEndpoint<PWindowGlobalParent>&& aEndpoint,
|
ManagedEndpoint<PWindowGlobalParent>&& aEndpoint,
|
||||||
const WindowGlobalInit& aInit) {
|
const WindowGlobalInit& aInit) {
|
||||||
@@ -3008,41 +3019,6 @@ BrowserParent::BrowsingContextForWebProgress(
|
|||||||
return browsingContext.forget();
|
return browsingContext.forget();
|
||||||
}
|
}
|
||||||
|
|
||||||
mozilla::ipc::IPCResult BrowserParent::RecvSessionStoreUpdate(
|
|
||||||
const Maybe<nsCString>& aDocShellCaps, const Maybe<bool>& aPrivatedMode,
|
|
||||||
const bool aNeedCollectSHistory, const uint32_t& aEpoch) {
|
|
||||||
UpdateSessionStoreData data;
|
|
||||||
if (aDocShellCaps.isSome()) {
|
|
||||||
data.mDocShellCaps.Construct() = aDocShellCaps.value();
|
|
||||||
}
|
|
||||||
if (aPrivatedMode.isSome()) {
|
|
||||||
data.mIsPrivate.Construct() = aPrivatedMode.value();
|
|
||||||
}
|
|
||||||
|
|
||||||
nsCOMPtr<nsISessionStoreFunctions> funcs = do_ImportModule(
|
|
||||||
"resource://gre/modules/SessionStoreFunctions.jsm", fallible);
|
|
||||||
nsCOMPtr<nsIXPConnectWrappedJS> wrapped = do_QueryInterface(funcs);
|
|
||||||
NS_ENSURE_TRUE(wrapped, IPC_OK());
|
|
||||||
|
|
||||||
AutoJSAPI jsapi;
|
|
||||||
if (!jsapi.Init(wrapped->GetJSObjectGlobal())) {
|
|
||||||
return IPC_OK();
|
|
||||||
}
|
|
||||||
|
|
||||||
JS::Rooted<JS::Value> update(jsapi.cx());
|
|
||||||
if (!ToJSValue(jsapi.cx(), data, &update)) {
|
|
||||||
return IPC_OK();
|
|
||||||
}
|
|
||||||
|
|
||||||
JS::RootedValue key(jsapi.cx(),
|
|
||||||
mBrowsingContext->Canonical()->Top()->PermanentKey());
|
|
||||||
|
|
||||||
Unused << funcs->UpdateSessionStore(mFrameElement, mBrowsingContext, key,
|
|
||||||
aEpoch, aNeedCollectSHistory, update);
|
|
||||||
|
|
||||||
return IPC_OK();
|
|
||||||
}
|
|
||||||
|
|
||||||
mozilla::ipc::IPCResult BrowserParent::RecvIntrinsicSizeOrRatioChanged(
|
mozilla::ipc::IPCResult BrowserParent::RecvIntrinsicSizeOrRatioChanged(
|
||||||
const Maybe<IntrinsicSize>& aIntrinsicSize,
|
const Maybe<IntrinsicSize>& aIntrinsicSize,
|
||||||
const Maybe<AspectRatio>& aIntrinsicRatio) {
|
const Maybe<AspectRatio>& aIntrinsicRatio) {
|
||||||
|
|||||||
@@ -317,10 +317,6 @@ class BrowserParent final : public PBrowserParent,
|
|||||||
already_AddRefed<CanonicalBrowsingContext> BrowsingContextForWebProgress(
|
already_AddRefed<CanonicalBrowsingContext> BrowsingContextForWebProgress(
|
||||||
const WebProgressData& aWebProgressData);
|
const WebProgressData& aWebProgressData);
|
||||||
|
|
||||||
mozilla::ipc::IPCResult RecvSessionStoreUpdate(
|
|
||||||
const Maybe<nsCString>& aDocShellCaps, const Maybe<bool>& aPrivatedMode,
|
|
||||||
const bool aNeedCollectSHistory, const uint32_t& aEpoch);
|
|
||||||
|
|
||||||
mozilla::ipc::IPCResult RecvIntrinsicSizeOrRatioChanged(
|
mozilla::ipc::IPCResult RecvIntrinsicSizeOrRatioChanged(
|
||||||
const Maybe<IntrinsicSize>& aIntrinsicSize,
|
const Maybe<IntrinsicSize>& aIntrinsicSize,
|
||||||
const Maybe<AspectRatio>& aIntrinsicRatio);
|
const Maybe<AspectRatio>& aIntrinsicRatio);
|
||||||
@@ -445,6 +441,8 @@ class BrowserParent final : public PBrowserParent,
|
|||||||
const IAccessibleHolder& aDocCOMProxy) override;
|
const IAccessibleHolder& aDocCOMProxy) override;
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
already_AddRefed<PSessionStoreParent> AllocPSessionStoreParent();
|
||||||
|
|
||||||
mozilla::ipc::IPCResult RecvNewWindowGlobal(
|
mozilla::ipc::IPCResult RecvNewWindowGlobal(
|
||||||
ManagedEndpoint<PWindowGlobalParent>&& aEndpoint,
|
ManagedEndpoint<PWindowGlobalParent>&& aEndpoint,
|
||||||
const WindowGlobalInit& aInit);
|
const WindowGlobalInit& aInit);
|
||||||
|
|||||||
@@ -4524,25 +4524,6 @@ mozilla::ipc::IPCResult ContentChild::RecvInitNextGenLocalStorageEnabled(
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
mozilla::ipc::IPCResult ContentChild::RecvFlushTabState(
|
|
||||||
const MaybeDiscarded<BrowsingContext>& aContext,
|
|
||||||
FlushTabStateResolver&& aResolver) {
|
|
||||||
if (aContext.IsNullOrDiscarded()) {
|
|
||||||
aResolver(false);
|
|
||||||
return IPC_OK();
|
|
||||||
}
|
|
||||||
|
|
||||||
if (auto* docShell = nsDocShell::Cast(aContext->GetDocShell())) {
|
|
||||||
docShell->CollectWireframe();
|
|
||||||
}
|
|
||||||
|
|
||||||
aContext->FlushSessionStore();
|
|
||||||
|
|
||||||
aResolver(true);
|
|
||||||
|
|
||||||
return IPC_OK();
|
|
||||||
}
|
|
||||||
|
|
||||||
mozilla::ipc::IPCResult ContentChild::RecvGoBack(
|
mozilla::ipc::IPCResult ContentChild::RecvGoBack(
|
||||||
const MaybeDiscarded<BrowsingContext>& aContext,
|
const MaybeDiscarded<BrowsingContext>& aContext,
|
||||||
const Maybe<int32_t>& aCancelContentJSEpoch, bool aRequireUserInteraction,
|
const Maybe<int32_t>& aCancelContentJSEpoch, bool aRequireUserInteraction,
|
||||||
|
|||||||
@@ -812,10 +812,6 @@ class ContentChild final : public PContentChild,
|
|||||||
const MaybeDiscarded<BrowsingContext>& aStartingAt,
|
const MaybeDiscarded<BrowsingContext>& aStartingAt,
|
||||||
DispatchBeforeUnloadToSubtreeResolver&& aResolver);
|
DispatchBeforeUnloadToSubtreeResolver&& aResolver);
|
||||||
|
|
||||||
mozilla::ipc::IPCResult RecvFlushTabState(
|
|
||||||
const MaybeDiscarded<BrowsingContext>& aContext,
|
|
||||||
FlushTabStateResolver&& aResolver);
|
|
||||||
|
|
||||||
mozilla::ipc::IPCResult RecvDecoderSupportedMimeTypes(
|
mozilla::ipc::IPCResult RecvDecoderSupportedMimeTypes(
|
||||||
nsTArray<nsCString>&& aSupportedTypes);
|
nsTArray<nsCString>&& aSupportedTypes);
|
||||||
|
|
||||||
|
|||||||
@@ -17,6 +17,7 @@ include protocol PParentToChildStream;
|
|||||||
include protocol PFileDescriptorSet;
|
include protocol PFileDescriptorSet;
|
||||||
include protocol PRemoteLazyInputStream;
|
include protocol PRemoteLazyInputStream;
|
||||||
include protocol PPaymentRequest;
|
include protocol PPaymentRequest;
|
||||||
|
include protocol PSessionStore;
|
||||||
include protocol PWindowGlobal;
|
include protocol PWindowGlobal;
|
||||||
include protocol PBrowserBridge;
|
include protocol PBrowserBridge;
|
||||||
include protocol PVsync;
|
include protocol PVsync;
|
||||||
@@ -190,6 +191,7 @@ struct PrintPreviewResultInfo
|
|||||||
|
|
||||||
manages PFilePicker;
|
manages PFilePicker;
|
||||||
manages PPaymentRequest;
|
manages PPaymentRequest;
|
||||||
|
manages PSessionStore;
|
||||||
manages PWindowGlobal;
|
manages PWindowGlobal;
|
||||||
manages PBrowserBridge;
|
manages PBrowserBridge;
|
||||||
manages PVsync;
|
manages PVsync;
|
||||||
@@ -575,9 +577,6 @@ parent:
|
|||||||
|
|
||||||
async NavigationFinished();
|
async NavigationFinished();
|
||||||
|
|
||||||
async SessionStoreUpdate(nsCString? aDocShellCaps, bool? aPrivatedMode,
|
|
||||||
bool aNeedCollectSHistory, uint32_t aEpoch);
|
|
||||||
|
|
||||||
async IntrinsicSizeOrRatioChanged(IntrinsicSize? aIntrinsicSize,
|
async IntrinsicSizeOrRatioChanged(IntrinsicSize? aIntrinsicSize,
|
||||||
AspectRatio? aIntrinsicRatio);
|
AspectRatio? aIntrinsicRatio);
|
||||||
|
|
||||||
@@ -595,7 +594,6 @@ parent:
|
|||||||
|
|
||||||
child:
|
child:
|
||||||
async NativeSynthesisResponse(uint64_t aObserverId, nsCString aResponse);
|
async NativeSynthesisResponse(uint64_t aObserverId, nsCString aResponse);
|
||||||
async UpdateEpoch(uint32_t aEpoch);
|
|
||||||
async UpdateSHistory();
|
async UpdateSHistory();
|
||||||
async CloneDocumentTreeIntoSelf(MaybeDiscardedBrowsingContext aBc, PrintData aPrintData) returns(bool aSuccess);
|
async CloneDocumentTreeIntoSelf(MaybeDiscardedBrowsingContext aBc, PrintData aPrintData) returns(bool aSuccess);
|
||||||
async UpdateRemotePrintSettings(PrintData aPrintData);
|
async UpdateRemotePrintSettings(PrintData aPrintData);
|
||||||
@@ -1016,6 +1014,9 @@ parent:
|
|||||||
/** Fetches the visited status for an array of URIs (Android-only). */
|
/** Fetches the visited status for an array of URIs (Android-only). */
|
||||||
async QueryVisitedState(nsIURI[] aURIs);
|
async QueryVisitedState(nsIURI[] aURIs);
|
||||||
|
|
||||||
|
/** Create a session store for a browser child. */
|
||||||
|
async PSessionStore();
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Construct a new WindowGlobal for an existing global in the content process
|
* Construct a new WindowGlobal for an existing global in the content process
|
||||||
*/
|
*/
|
||||||
|
|||||||
@@ -1027,9 +1027,6 @@ child:
|
|||||||
// Update the cached list of codec supported in the given process.
|
// Update the cached list of codec supported in the given process.
|
||||||
async UpdateMediaCodecsSupported(RemoteDecodeIn aLocation, MediaCodecsSupported aSupported);
|
async UpdateMediaCodecsSupported(RemoteDecodeIn aLocation, MediaCodecsSupported aSupported);
|
||||||
|
|
||||||
async FlushTabState(MaybeDiscardedBrowsingContext aBrowsingContext)
|
|
||||||
returns(bool aHadContext);
|
|
||||||
|
|
||||||
// Send the list of the supported mimetypes in the given process. GeckoView-specific
|
// Send the list of the supported mimetypes in the given process. GeckoView-specific
|
||||||
async DecoderSupportedMimeTypes(nsCString[] supportedTypes);
|
async DecoderSupportedMimeTypes(nsCString[] supportedTypes);
|
||||||
|
|
||||||
|
|||||||
@@ -5,6 +5,7 @@
|
|||||||
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
|
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
|
||||||
|
|
||||||
include protocol PExtensions;
|
include protocol PExtensions;
|
||||||
|
include protocol PSessionStore;
|
||||||
include protocol PWindowGlobal;
|
include protocol PWindowGlobal;
|
||||||
|
|
||||||
include DOMTypes;
|
include DOMTypes;
|
||||||
@@ -23,6 +24,7 @@ namespace dom {
|
|||||||
async protocol PInProcess
|
async protocol PInProcess
|
||||||
{
|
{
|
||||||
manages PExtensions;
|
manages PExtensions;
|
||||||
|
manages PSessionStore;
|
||||||
manages PWindowGlobal;
|
manages PWindowGlobal;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|||||||
@@ -180,11 +180,6 @@ parent:
|
|||||||
|
|
||||||
async RequestRestoreTabContent();
|
async RequestRestoreTabContent();
|
||||||
|
|
||||||
async UpdateSessionStore(FormData? aFormData, nsPoint? aScrollPosition,
|
|
||||||
uint32_t aEpoch);
|
|
||||||
|
|
||||||
async ResetSessionStore(uint32_t aEpoch);
|
|
||||||
|
|
||||||
// Add the flags in aOnFlags to the current BFCache status and remove the
|
// Add the flags in aOnFlags to the current BFCache status and remove the
|
||||||
// flags in aOffFlags from the current BFCache status. See the BFCacheStatus
|
// flags in aOffFlags from the current BFCache status. See the BFCacheStatus
|
||||||
// enum for the valid flags.
|
// enum for the valid flags.
|
||||||
|
|||||||
@@ -18,7 +18,6 @@
|
|||||||
#include "mozilla/dom/ContentParent.h"
|
#include "mozilla/dom/ContentParent.h"
|
||||||
#include "mozilla/dom/SecurityPolicyViolationEvent.h"
|
#include "mozilla/dom/SecurityPolicyViolationEvent.h"
|
||||||
#include "mozilla/dom/SessionStoreRestoreData.h"
|
#include "mozilla/dom/SessionStoreRestoreData.h"
|
||||||
#include "mozilla/dom/SessionStoreDataCollector.h"
|
|
||||||
#include "mozilla/dom/WindowGlobalActorsBinding.h"
|
#include "mozilla/dom/WindowGlobalActorsBinding.h"
|
||||||
#include "mozilla/dom/WindowContext.h"
|
#include "mozilla/dom/WindowContext.h"
|
||||||
#include "mozilla/dom/InProcessChild.h"
|
#include "mozilla/dom/InProcessChild.h"
|
||||||
@@ -327,11 +326,6 @@ void WindowGlobalChild::Destroy() {
|
|||||||
if (!browserChild || !browserChild->IsDestroyed()) {
|
if (!browserChild || !browserChild->IsDestroyed()) {
|
||||||
SendDestroy();
|
SendDestroy();
|
||||||
}
|
}
|
||||||
|
|
||||||
if (mSessionStoreDataCollector) {
|
|
||||||
mSessionStoreDataCollector->Cancel();
|
|
||||||
mSessionStoreDataCollector = nullptr;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
mozilla::ipc::IPCResult WindowGlobalChild::RecvMakeFrameLocal(
|
mozilla::ipc::IPCResult WindowGlobalChild::RecvMakeFrameLocal(
|
||||||
@@ -703,20 +697,9 @@ nsISupports* WindowGlobalChild::GetParentObject() {
|
|||||||
return xpc::NativeGlobal(xpc::PrivilegedJunkScope());
|
return xpc::NativeGlobal(xpc::PrivilegedJunkScope());
|
||||||
}
|
}
|
||||||
|
|
||||||
void WindowGlobalChild::SetSessionStoreDataCollector(
|
|
||||||
SessionStoreDataCollector* aCollector) {
|
|
||||||
mSessionStoreDataCollector = aCollector;
|
|
||||||
}
|
|
||||||
|
|
||||||
SessionStoreDataCollector* WindowGlobalChild::GetSessionStoreDataCollector()
|
|
||||||
const {
|
|
||||||
return mSessionStoreDataCollector;
|
|
||||||
}
|
|
||||||
|
|
||||||
NS_IMPL_CYCLE_COLLECTION_WRAPPERCACHE_WEAK_PTR(WindowGlobalChild, mWindowGlobal,
|
NS_IMPL_CYCLE_COLLECTION_WRAPPERCACHE_WEAK_PTR(WindowGlobalChild, mWindowGlobal,
|
||||||
mContainerFeaturePolicy,
|
mContainerFeaturePolicy,
|
||||||
mWindowContext,
|
mWindowContext)
|
||||||
mSessionStoreDataCollector)
|
|
||||||
|
|
||||||
NS_INTERFACE_MAP_BEGIN_CYCLE_COLLECTION(WindowGlobalChild)
|
NS_INTERFACE_MAP_BEGIN_CYCLE_COLLECTION(WindowGlobalChild)
|
||||||
NS_WRAPPERCACHE_INTERFACE_MAP_ENTRY
|
NS_WRAPPERCACHE_INTERFACE_MAP_ENTRY
|
||||||
|
|||||||
@@ -28,7 +28,6 @@ class WindowGlobalParent;
|
|||||||
class JSWindowActorChild;
|
class JSWindowActorChild;
|
||||||
class JSActorMessageMeta;
|
class JSActorMessageMeta;
|
||||||
class BrowserChild;
|
class BrowserChild;
|
||||||
class SessionStoreDataCollector;
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Actor for a single nsGlobalWindowInner. This actor is used to communicate
|
* Actor for a single nsGlobalWindowInner. This actor is used to communicate
|
||||||
@@ -133,9 +132,6 @@ class WindowGlobalChild final : public WindowGlobalActor,
|
|||||||
return mContainerFeaturePolicy;
|
return mContainerFeaturePolicy;
|
||||||
}
|
}
|
||||||
|
|
||||||
void SetSessionStoreDataCollector(SessionStoreDataCollector* aCollector);
|
|
||||||
SessionStoreDataCollector* GetSessionStoreDataCollector() const;
|
|
||||||
|
|
||||||
void UnblockBFCacheFor(BFCacheStatus aStatus);
|
void UnblockBFCacheFor(BFCacheStatus aStatus);
|
||||||
void BlockBFCacheFor(BFCacheStatus aStatus);
|
void BlockBFCacheFor(BFCacheStatus aStatus);
|
||||||
|
|
||||||
@@ -205,7 +201,6 @@ class WindowGlobalChild final : public WindowGlobalActor,
|
|||||||
nsCOMPtr<nsIPrincipal> mDocumentPrincipal;
|
nsCOMPtr<nsIPrincipal> mDocumentPrincipal;
|
||||||
RefPtr<dom::FeaturePolicy> mContainerFeaturePolicy;
|
RefPtr<dom::FeaturePolicy> mContainerFeaturePolicy;
|
||||||
nsCOMPtr<nsIURI> mDocumentURI;
|
nsCOMPtr<nsIURI> mDocumentURI;
|
||||||
RefPtr<SessionStoreDataCollector> mSessionStoreDataCollector;
|
|
||||||
int64_t mBeforeUnloadListeners = 0;
|
int64_t mBeforeUnloadListeners = 0;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|||||||
@@ -26,9 +26,6 @@
|
|||||||
#include "mozilla/dom/ChromeUtils.h"
|
#include "mozilla/dom/ChromeUtils.h"
|
||||||
#include "mozilla/dom/ipc/IdType.h"
|
#include "mozilla/dom/ipc/IdType.h"
|
||||||
#include "mozilla/dom/ipc/StructuredCloneData.h"
|
#include "mozilla/dom/ipc/StructuredCloneData.h"
|
||||||
#include "mozilla/dom/sessionstore/SessionStoreTypes.h"
|
|
||||||
#include "mozilla/dom/SessionStoreUtils.h"
|
|
||||||
#include "mozilla/dom/SessionStoreUtilsBinding.h"
|
|
||||||
#include "mozilla/Components.h"
|
#include "mozilla/Components.h"
|
||||||
#include "mozilla/ScopeExit.h"
|
#include "mozilla/ScopeExit.h"
|
||||||
#include "mozilla/ServoCSSParser.h"
|
#include "mozilla/ServoCSSParser.h"
|
||||||
@@ -535,16 +532,6 @@ const nsACString& WindowGlobalParent::GetRemoteType() {
|
|||||||
return NOT_REMOTE_TYPE;
|
return NOT_REMOTE_TYPE;
|
||||||
}
|
}
|
||||||
|
|
||||||
static nsCString PointToString(const nsPoint& aPoint) {
|
|
||||||
int scrollX = nsPresContext::AppUnitsToIntCSSPixels(aPoint.x);
|
|
||||||
int scrollY = nsPresContext::AppUnitsToIntCSSPixels(aPoint.y);
|
|
||||||
if ((scrollX != 0) || (scrollY != 0)) {
|
|
||||||
return nsPrintfCString("%d,%d", scrollX, scrollY);
|
|
||||||
}
|
|
||||||
|
|
||||||
return ""_ns;
|
|
||||||
}
|
|
||||||
|
|
||||||
void WindowGlobalParent::NotifyContentBlockingEvent(
|
void WindowGlobalParent::NotifyContentBlockingEvent(
|
||||||
uint32_t aEvent, nsIRequest* aRequest, bool aBlocked,
|
uint32_t aEvent, nsIRequest* aRequest, bool aBlocked,
|
||||||
const nsACString& aTrackingOrigin,
|
const nsACString& aTrackingOrigin,
|
||||||
@@ -1166,44 +1153,6 @@ void WindowGlobalParent::FinishAccumulatingPageUseCounters() {
|
|||||||
mPageUseCounters = nullptr;
|
mPageUseCounters = nullptr;
|
||||||
}
|
}
|
||||||
|
|
||||||
static void GetFormData(JSContext* aCx, const sessionstore::FormData& aFormData,
|
|
||||||
nsIURI* aDocumentURI, SessionStoreFormData& aUpdate) {
|
|
||||||
if (!aFormData.hasData()) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
bool parseSessionData = false;
|
|
||||||
if (aDocumentURI) {
|
|
||||||
nsCString& url = aUpdate.mUrl.Construct();
|
|
||||||
aDocumentURI->GetSpecIgnoringRef(url);
|
|
||||||
// We want to avoid saving data for about:sessionrestore as a string.
|
|
||||||
// Since it's stored in the form as stringified JSON, stringifying
|
|
||||||
// further causes an explosion of escape characters. cf. bug 467409
|
|
||||||
parseSessionData =
|
|
||||||
url == "about:sessionrestore"_ns || url == "about:welcomeback"_ns;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (!aFormData.innerHTML().IsEmpty()) {
|
|
||||||
aUpdate.mInnerHTML.Construct(aFormData.innerHTML());
|
|
||||||
}
|
|
||||||
|
|
||||||
if (!aFormData.id().IsEmpty()) {
|
|
||||||
auto& id = aUpdate.mId.Construct();
|
|
||||||
if (NS_FAILED(SessionStoreUtils::ConstructFormDataValues(
|
|
||||||
aCx, aFormData.id(), id.Entries(), parseSessionData))) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if (!aFormData.xpath().IsEmpty()) {
|
|
||||||
auto& xpath = aUpdate.mXpath.Construct();
|
|
||||||
if (NS_FAILED(SessionStoreUtils::ConstructFormDataValues(
|
|
||||||
aCx, aFormData.xpath(), xpath.Entries()))) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
Element* WindowGlobalParent::GetRootOwnerElement() {
|
Element* WindowGlobalParent::GetRootOwnerElement() {
|
||||||
WindowGlobalParent* top = TopWindowContext();
|
WindowGlobalParent* top = TopWindowContext();
|
||||||
if (!top) {
|
if (!top) {
|
||||||
@@ -1221,104 +1170,6 @@ Element* WindowGlobalParent::GetRootOwnerElement() {
|
|||||||
return nullptr;
|
return nullptr;
|
||||||
}
|
}
|
||||||
|
|
||||||
nsresult WindowGlobalParent::WriteFormDataAndScrollToSessionStore(
|
|
||||||
const Maybe<FormData>& aFormData, const Maybe<nsPoint>& aScrollPosition,
|
|
||||||
uint32_t aEpoch) {
|
|
||||||
if (!aFormData && !aScrollPosition) {
|
|
||||||
return NS_OK;
|
|
||||||
}
|
|
||||||
|
|
||||||
RefPtr<CanonicalBrowsingContext> context = BrowsingContext();
|
|
||||||
if (!context) {
|
|
||||||
return NS_OK;
|
|
||||||
}
|
|
||||||
|
|
||||||
nsCOMPtr<nsISessionStoreFunctions> funcs = do_ImportModule(
|
|
||||||
"resource://gre/modules/SessionStoreFunctions.jsm", fallible);
|
|
||||||
if (!funcs) {
|
|
||||||
return NS_ERROR_FAILURE;
|
|
||||||
}
|
|
||||||
|
|
||||||
nsCOMPtr<nsIXPConnectWrappedJS> wrapped = do_QueryInterface(funcs);
|
|
||||||
AutoJSAPI jsapi;
|
|
||||||
if (!jsapi.Init(wrapped->GetJSObjectGlobal())) {
|
|
||||||
return NS_ERROR_FAILURE;
|
|
||||||
}
|
|
||||||
|
|
||||||
RootedDictionary<SessionStoreWindowStateChange> windowState(jsapi.cx());
|
|
||||||
|
|
||||||
if (aFormData) {
|
|
||||||
GetFormData(jsapi.cx(), *aFormData, mDocumentURI,
|
|
||||||
windowState.mFormdata.Construct());
|
|
||||||
}
|
|
||||||
|
|
||||||
if (aScrollPosition) {
|
|
||||||
auto& update = windowState.mScroll.Construct();
|
|
||||||
if (*aScrollPosition != nsPoint(0, 0)) {
|
|
||||||
update.mScroll.Construct() = PointToString(*aScrollPosition);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
nsTArray<uint32_t> path;
|
|
||||||
if (!context->GetOffsetPath(path)) {
|
|
||||||
return NS_OK;
|
|
||||||
}
|
|
||||||
|
|
||||||
windowState.mPath = std::move(path);
|
|
||||||
windowState.mHasChildren.Construct() = !context->Children().IsEmpty();
|
|
||||||
|
|
||||||
JS::RootedValue update(jsapi.cx());
|
|
||||||
if (!ToJSValue(jsapi.cx(), windowState, &update)) {
|
|
||||||
return NS_ERROR_FAILURE;
|
|
||||||
}
|
|
||||||
|
|
||||||
JS::RootedValue key(jsapi.cx(), context->Top()->PermanentKey());
|
|
||||||
|
|
||||||
return funcs->UpdateSessionStoreForWindow(GetRootOwnerElement(), context, key,
|
|
||||||
aEpoch, update);
|
|
||||||
}
|
|
||||||
|
|
||||||
nsresult WindowGlobalParent::ResetSessionStore(uint32_t aEpoch) {
|
|
||||||
RefPtr<CanonicalBrowsingContext> context = BrowsingContext();
|
|
||||||
if (!context) {
|
|
||||||
return NS_OK;
|
|
||||||
}
|
|
||||||
|
|
||||||
nsCOMPtr<nsISessionStoreFunctions> funcs = do_ImportModule(
|
|
||||||
"resource://gre/modules/SessionStoreFunctions.jsm", fallible);
|
|
||||||
if (!funcs) {
|
|
||||||
return NS_ERROR_FAILURE;
|
|
||||||
}
|
|
||||||
|
|
||||||
nsCOMPtr<nsIXPConnectWrappedJS> wrapped = do_QueryInterface(funcs);
|
|
||||||
AutoJSAPI jsapi;
|
|
||||||
if (!jsapi.Init(wrapped->GetJSObjectGlobal())) {
|
|
||||||
return NS_ERROR_FAILURE;
|
|
||||||
}
|
|
||||||
|
|
||||||
RootedDictionary<SessionStoreWindowStateChange> windowState(jsapi.cx());
|
|
||||||
|
|
||||||
nsTArray<uint32_t> path;
|
|
||||||
if (!context->GetOffsetPath(path)) {
|
|
||||||
return NS_OK;
|
|
||||||
}
|
|
||||||
|
|
||||||
windowState.mPath = std::move(path);
|
|
||||||
windowState.mHasChildren.Construct() = false;
|
|
||||||
windowState.mFormdata.Construct();
|
|
||||||
windowState.mScroll.Construct();
|
|
||||||
|
|
||||||
JS::RootedValue update(jsapi.cx());
|
|
||||||
if (!ToJSValue(jsapi.cx(), windowState, &update)) {
|
|
||||||
return NS_ERROR_FAILURE;
|
|
||||||
}
|
|
||||||
|
|
||||||
JS::RootedValue key(jsapi.cx(), context->Top()->PermanentKey());
|
|
||||||
|
|
||||||
return funcs->UpdateSessionStoreForWindow(GetRootOwnerElement(), context, key,
|
|
||||||
aEpoch, update);
|
|
||||||
}
|
|
||||||
|
|
||||||
void WindowGlobalParent::NotifySessionStoreUpdatesComplete(Element* aEmbedder) {
|
void WindowGlobalParent::NotifySessionStoreUpdatesComplete(Element* aEmbedder) {
|
||||||
if (!aEmbedder) {
|
if (!aEmbedder) {
|
||||||
aEmbedder = GetRootOwnerElement();
|
aEmbedder = GetRootOwnerElement();
|
||||||
@@ -1331,27 +1182,6 @@ void WindowGlobalParent::NotifySessionStoreUpdatesComplete(Element* aEmbedder) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
mozilla::ipc::IPCResult WindowGlobalParent::RecvUpdateSessionStore(
|
|
||||||
const Maybe<FormData>& aFormData, const Maybe<nsPoint>& aScrollPosition,
|
|
||||||
uint32_t aEpoch) {
|
|
||||||
if (NS_FAILED(WriteFormDataAndScrollToSessionStore(aFormData, aScrollPosition,
|
|
||||||
aEpoch))) {
|
|
||||||
MOZ_LOG(BrowsingContext::GetLog(), LogLevel::Debug,
|
|
||||||
("ParentIPC: Failed to update session store entry."));
|
|
||||||
}
|
|
||||||
|
|
||||||
return IPC_OK();
|
|
||||||
}
|
|
||||||
|
|
||||||
mozilla::ipc::IPCResult WindowGlobalParent::RecvResetSessionStore(
|
|
||||||
uint32_t aEpoch) {
|
|
||||||
if (NS_FAILED(ResetSessionStore(aEpoch))) {
|
|
||||||
MOZ_LOG(BrowsingContext::GetLog(), LogLevel::Debug,
|
|
||||||
("ParentIPC: Failed to reset session store entry."));
|
|
||||||
}
|
|
||||||
return IPC_OK();
|
|
||||||
}
|
|
||||||
|
|
||||||
mozilla::ipc::IPCResult WindowGlobalParent::RecvRequestRestoreTabContent() {
|
mozilla::ipc::IPCResult WindowGlobalParent::RecvRequestRestoreTabContent() {
|
||||||
CanonicalBrowsingContext* bc = BrowsingContext();
|
CanonicalBrowsingContext* bc = BrowsingContext();
|
||||||
if (bc && bc->AncestorsAreCurrent()) {
|
if (bc && bc->AncestorsAreCurrent()) {
|
||||||
|
|||||||
@@ -80,7 +80,7 @@ class WindowGlobalParent final : public WindowContext,
|
|||||||
WindowGlobalParent* TopWindowContext() {
|
WindowGlobalParent* TopWindowContext() {
|
||||||
return static_cast<WindowGlobalParent*>(WindowContext::TopWindowContext());
|
return static_cast<WindowGlobalParent*>(WindowContext::TopWindowContext());
|
||||||
}
|
}
|
||||||
CanonicalBrowsingContext* GetBrowsingContext() {
|
CanonicalBrowsingContext* GetBrowsingContext() const {
|
||||||
return CanonicalBrowsingContext::Cast(WindowContext::GetBrowsingContext());
|
return CanonicalBrowsingContext::Cast(WindowContext::GetBrowsingContext());
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -214,10 +214,6 @@ class WindowGlobalParent final : public WindowContext,
|
|||||||
|
|
||||||
const nsACString& GetRemoteType() override;
|
const nsACString& GetRemoteType() override;
|
||||||
|
|
||||||
nsresult WriteFormDataAndScrollToSessionStore(
|
|
||||||
const Maybe<FormData>& aFormData, const Maybe<nsPoint>& aScrollPosition,
|
|
||||||
uint32_t aEpoch);
|
|
||||||
|
|
||||||
void NotifySessionStoreUpdatesComplete(Element* aEmbedder);
|
void NotifySessionStoreUpdatesComplete(Element* aEmbedder);
|
||||||
|
|
||||||
Maybe<uint64_t> GetSingleChannelId() { return mSingleChannelId; }
|
Maybe<uint64_t> GetSingleChannelId() { return mSingleChannelId; }
|
||||||
@@ -288,12 +284,6 @@ class WindowGlobalParent final : public WindowContext,
|
|||||||
|
|
||||||
mozilla::ipc::IPCResult RecvRequestRestoreTabContent();
|
mozilla::ipc::IPCResult RecvRequestRestoreTabContent();
|
||||||
|
|
||||||
mozilla::ipc::IPCResult RecvUpdateSessionStore(
|
|
||||||
const Maybe<FormData>& aFormData, const Maybe<nsPoint>& aScrollPosition,
|
|
||||||
uint32_t aEpoch);
|
|
||||||
|
|
||||||
mozilla::ipc::IPCResult RecvResetSessionStore(uint32_t aEpoch);
|
|
||||||
|
|
||||||
mozilla::ipc::IPCResult RecvUpdateBFCacheStatus(const uint32_t& aOnFlags,
|
mozilla::ipc::IPCResult RecvUpdateBFCacheStatus(const uint32_t& aOnFlags,
|
||||||
const uint32_t& aOffFlags);
|
const uint32_t& aOffFlags);
|
||||||
|
|
||||||
@@ -320,8 +310,6 @@ class WindowGlobalParent final : public WindowContext,
|
|||||||
bool ShouldTrackSiteOriginTelemetry();
|
bool ShouldTrackSiteOriginTelemetry();
|
||||||
void FinishAccumulatingPageUseCounters();
|
void FinishAccumulatingPageUseCounters();
|
||||||
|
|
||||||
nsresult ResetSessionStore(uint32_t aEpoch);
|
|
||||||
|
|
||||||
// Returns failure if the new storage principal cannot be validated
|
// Returns failure if the new storage principal cannot be validated
|
||||||
// against the current document principle.
|
// against the current document principle.
|
||||||
nsresult SetDocumentStoragePrincipal(
|
nsresult SetDocumentStoragePrincipal(
|
||||||
|
|||||||
293
toolkit/components/sessionstore/BrowserSessionStore.cpp
Normal file
293
toolkit/components/sessionstore/BrowserSessionStore.cpp
Normal file
@@ -0,0 +1,293 @@
|
|||||||
|
/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
|
||||||
|
/* vim: set ts=8 sts=2 et sw=2 tw=80: */
|
||||||
|
/* This Source Code Form is subject to the terms of the Mozilla Public
|
||||||
|
* License, v. 2.0. If a copy of the MPL was not distributed with this
|
||||||
|
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
|
||||||
|
|
||||||
|
#include "mozilla/dom/BrowserSessionStore.h"
|
||||||
|
#include <algorithm>
|
||||||
|
#include <cstdint>
|
||||||
|
#include <functional>
|
||||||
|
|
||||||
|
#include "mozilla/AlreadyAddRefed.h"
|
||||||
|
#include "mozilla/Assertions.h"
|
||||||
|
#include "mozilla/ClearOnShutdown.h"
|
||||||
|
#include "mozilla/IntegerRange.h"
|
||||||
|
#include "mozilla/RefPtr.h"
|
||||||
|
#include "mozilla/ScopeExit.h"
|
||||||
|
#include "mozilla/StaticPtr.h"
|
||||||
|
|
||||||
|
#include "mozilla/dom/BrowserSessionStoreBinding.h"
|
||||||
|
#include "mozilla/dom/CanonicalBrowsingContext.h"
|
||||||
|
#include "mozilla/dom/SessionStoreFormData.h"
|
||||||
|
#include "mozilla/dom/SessionStoreScrollData.h"
|
||||||
|
#include "mozilla/dom/WindowGlobalParent.h"
|
||||||
|
|
||||||
|
#include "nsTHashMap.h"
|
||||||
|
#include "nsHashtablesFwd.h"
|
||||||
|
|
||||||
|
#include "js/RootingAPI.h"
|
||||||
|
|
||||||
|
using namespace mozilla;
|
||||||
|
using namespace mozilla::dom;
|
||||||
|
|
||||||
|
static StaticAutoPtr<nsTHashMap<nsUint64HashKey, BrowserSessionStore*>>
|
||||||
|
sSessionStore;
|
||||||
|
|
||||||
|
NS_IMPL_CYCLE_COLLECTION(BrowserSessionStore, mBrowsingContext, mFormData,
|
||||||
|
mScrollData)
|
||||||
|
|
||||||
|
NS_IMPL_CYCLE_COLLECTION_ROOT_NATIVE(BrowserSessionStore, AddRef)
|
||||||
|
NS_IMPL_CYCLE_COLLECTION_UNROOT_NATIVE(BrowserSessionStore, Release)
|
||||||
|
|
||||||
|
/* static */
|
||||||
|
already_AddRefed<BrowserSessionStore> BrowserSessionStore::GetOrCreate(
|
||||||
|
CanonicalBrowsingContext* aBrowsingContext) {
|
||||||
|
if (!aBrowsingContext->IsTop()) {
|
||||||
|
return nullptr;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!sSessionStore) {
|
||||||
|
sSessionStore = new nsTHashMap<nsUint64HashKey, BrowserSessionStore*>();
|
||||||
|
ClearOnShutdown(&sSessionStore);
|
||||||
|
}
|
||||||
|
|
||||||
|
return do_AddRef(sSessionStore->LookupOrInsertWith(
|
||||||
|
aBrowsingContext->Id(),
|
||||||
|
[&] { return new BrowserSessionStore(aBrowsingContext); }));
|
||||||
|
}
|
||||||
|
|
||||||
|
BrowserSessionStore::BrowserSessionStore(
|
||||||
|
CanonicalBrowsingContext* aBrowsingContext)
|
||||||
|
: mBrowsingContext(aBrowsingContext) {}
|
||||||
|
|
||||||
|
SessionStoreFormData* BrowserSessionStore::GetFormdata() { return mFormData; }
|
||||||
|
|
||||||
|
SessionStoreScrollData* BrowserSessionStore::GetScroll() { return mScrollData; }
|
||||||
|
|
||||||
|
static bool ShouldUpdateSessionStore(CanonicalBrowsingContext* aBrowsingContext,
|
||||||
|
uint32_t aEpoch) {
|
||||||
|
if (!aBrowsingContext) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (aBrowsingContext->Top()->GetSessionStoreEpoch() != aEpoch) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (aBrowsingContext->IsReplaced()) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (aBrowsingContext->IsDynamic()) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
// With GetOrCreate we can create either of the weak fields:
|
||||||
|
// WeakPtr<SessionStoreFormData> mFormdata;
|
||||||
|
// WeakPtr<SessionStoreScrollData> mScroll;
|
||||||
|
// in CanonicalBrowsingContext. If one already exists, then we return that.
|
||||||
|
template <typename T, WeakPtr<T>& (CanonicalBrowsingContext::*GetWeakRef)()>
|
||||||
|
static already_AddRefed<T> GetOrCreateEntry(
|
||||||
|
CanonicalBrowsingContext* aBrowsingContext) {
|
||||||
|
typename T::LocationType& location = (aBrowsingContext->*GetWeakRef)();
|
||||||
|
RefPtr<T> entry = location.get();
|
||||||
|
if (!entry) {
|
||||||
|
entry = MakeRefPtr<T>();
|
||||||
|
location = entry;
|
||||||
|
}
|
||||||
|
|
||||||
|
return entry.forget();
|
||||||
|
}
|
||||||
|
|
||||||
|
// With InsertEntry we can insert an entry in the session store data tree in
|
||||||
|
// either of the weak fields:
|
||||||
|
// WeakPtr<SessionStoreFormData> mFormdata;
|
||||||
|
// WeakPtr<SessionStoreScrollData> mScroll;
|
||||||
|
// in CanonicalBrowsingContext. If an entry is inserted where there is no parent
|
||||||
|
// entry, a spine of entries will be created until one is found, or we reach the
|
||||||
|
// top browsing context.
|
||||||
|
template <typename T>
|
||||||
|
void InsertEntry(BrowsingContext* aBrowsingContext, T* aParent, T* aUpdate) {
|
||||||
|
int32_t offset = aBrowsingContext->ChildOffset();
|
||||||
|
if (offset < 0) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
aParent->ClearCachedChildren();
|
||||||
|
|
||||||
|
auto& children = aParent->Children();
|
||||||
|
|
||||||
|
children.EnsureLengthAtLeast(offset + 1);
|
||||||
|
if (children[offset] && !aBrowsingContext->Children().IsEmpty()) {
|
||||||
|
children[offset]->ClearCachedChildren();
|
||||||
|
aUpdate->ClearCachedChildren();
|
||||||
|
}
|
||||||
|
|
||||||
|
children[offset] = aUpdate;
|
||||||
|
}
|
||||||
|
|
||||||
|
// With RemoveEntry we can remove an entry in the session store data tree in
|
||||||
|
// either of the weak fields:
|
||||||
|
// WeakPtr<SessionStoreFormData> mFormdata;
|
||||||
|
// WeakPtr<SessionStoreScrollData> mScroll;
|
||||||
|
// in CanonicalBrowsingContext. If an entry is removed, where its parent doesn't
|
||||||
|
// contain data, we'll remove the parent and repeat until we either find an
|
||||||
|
// entry with data or reach the top browsing context.
|
||||||
|
template <typename T>
|
||||||
|
void RemoveEntry(BrowsingContext* aBrowsingContext, T* aParent) {
|
||||||
|
int32_t offset = aBrowsingContext->ChildOffset();
|
||||||
|
if (offset < 0) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!aParent) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
aParent->ClearCachedChildren();
|
||||||
|
|
||||||
|
auto& children = aParent->Children();
|
||||||
|
size_t length = children.Length();
|
||||||
|
if (children.Length() <= static_cast<size_t>(offset)) {
|
||||||
|
// The children array doesn't extend to offset.
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (static_cast<size_t>(offset) < length - 1) {
|
||||||
|
// offset is before the last item in the children array.
|
||||||
|
children[offset] = nullptr;
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
// offset is the last item, find the first non-null item before it
|
||||||
|
// and remove anything after that item.
|
||||||
|
while (offset > 0 && !children[offset - 1]) {
|
||||||
|
--offset;
|
||||||
|
}
|
||||||
|
|
||||||
|
children.TruncateLength(offset);
|
||||||
|
}
|
||||||
|
|
||||||
|
// With UpdateSessionStoreField we can update an entry in the session store
|
||||||
|
// data tree in either of the weak fields:
|
||||||
|
// WeakPtr<SessionStoreFormData> mFormdata;
|
||||||
|
// WeakPtr<SessionStoreScrollData> mScroll;
|
||||||
|
// in CanonicalBrowsingContext. UpdateSessionStoreField uses the above
|
||||||
|
// functions, `GetOrCreateEntry`, `InsertEntry` and `RemoveEntry` to operate on
|
||||||
|
// the weak fields. We return the top-level entry attached to the top browsing
|
||||||
|
// context through `aEntry`. If the entire browsing context tree contains no
|
||||||
|
// session store data this will be set to nullptr.
|
||||||
|
template <typename T, WeakPtr<T>& (CanonicalBrowsingContext::*GetWeakRef)()>
|
||||||
|
void UpdateSessionStoreField(CanonicalBrowsingContext* aBrowsingContext,
|
||||||
|
const typename T::CollectedType& aUpdate,
|
||||||
|
T** aEntry) {
|
||||||
|
RefPtr<T> currentEntry;
|
||||||
|
|
||||||
|
if (T::HasData(aUpdate)) {
|
||||||
|
currentEntry = GetOrCreateEntry<T, GetWeakRef>(aBrowsingContext);
|
||||||
|
currentEntry->Update(aUpdate);
|
||||||
|
|
||||||
|
CanonicalBrowsingContext* currentBrowsingContext = aBrowsingContext;
|
||||||
|
while (CanonicalBrowsingContext* parent =
|
||||||
|
currentBrowsingContext->GetParent()) {
|
||||||
|
WeakPtr<T>& parentEntry = (parent->*GetWeakRef)();
|
||||||
|
if (parentEntry) {
|
||||||
|
InsertEntry(aBrowsingContext, parentEntry.get(), currentEntry.get());
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
RefPtr<T> entry = GetOrCreateEntry<T, GetWeakRef>(parent);
|
||||||
|
InsertEntry(currentBrowsingContext, entry.get(), currentEntry.get());
|
||||||
|
|
||||||
|
currentEntry = entry;
|
||||||
|
currentBrowsingContext = parent;
|
||||||
|
}
|
||||||
|
|
||||||
|
currentEntry = (aBrowsingContext->Top()->*GetWeakRef)().get();
|
||||||
|
} else if ((currentEntry = (aBrowsingContext->*GetWeakRef)())) {
|
||||||
|
currentEntry->Update(aUpdate);
|
||||||
|
|
||||||
|
CanonicalBrowsingContext* currentBrowsingContext = aBrowsingContext;
|
||||||
|
while (CanonicalBrowsingContext* parent =
|
||||||
|
currentBrowsingContext->GetParent()) {
|
||||||
|
if (!currentEntry || !currentEntry->IsEmpty()) {
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
T* parentEntry = (parent->*GetWeakRef)().get();
|
||||||
|
RemoveEntry(currentBrowsingContext, parentEntry);
|
||||||
|
|
||||||
|
currentEntry = parentEntry;
|
||||||
|
currentBrowsingContext = parent;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (currentEntry && currentEntry->IsEmpty()) {
|
||||||
|
currentEntry = nullptr;
|
||||||
|
} else {
|
||||||
|
currentEntry = (aBrowsingContext->Top()->*GetWeakRef)().get();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
*aEntry = currentEntry.forget().take();
|
||||||
|
}
|
||||||
|
|
||||||
|
void BrowserSessionStore::UpdateSessionStore(
|
||||||
|
CanonicalBrowsingContext* aBrowsingContext,
|
||||||
|
const Maybe<sessionstore::FormData>& aFormData,
|
||||||
|
const Maybe<nsPoint>& aScrollPosition, uint32_t aEpoch) {
|
||||||
|
if (!aFormData && !aScrollPosition) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!ShouldUpdateSessionStore(aBrowsingContext, aEpoch)) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (aFormData) {
|
||||||
|
UpdateSessionStoreField<
|
||||||
|
SessionStoreFormData,
|
||||||
|
&CanonicalBrowsingContext::GetSessionStoreFormDataRef>(
|
||||||
|
aBrowsingContext, *aFormData, getter_AddRefs(mFormData));
|
||||||
|
}
|
||||||
|
|
||||||
|
if (aScrollPosition) {
|
||||||
|
UpdateSessionStoreField<
|
||||||
|
SessionStoreScrollData,
|
||||||
|
&CanonicalBrowsingContext::GetSessionStoreScrollDataRef>(
|
||||||
|
aBrowsingContext, *aScrollPosition, getter_AddRefs(mScrollData));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void BrowserSessionStore::RemoveSessionStore(
|
||||||
|
CanonicalBrowsingContext* aBrowsingContext) {
|
||||||
|
if (!aBrowsingContext) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
CanonicalBrowsingContext* parentContext = aBrowsingContext->GetParent();
|
||||||
|
|
||||||
|
if (parentContext) {
|
||||||
|
RemoveEntry(aBrowsingContext,
|
||||||
|
parentContext->GetSessionStoreFormDataRef().get());
|
||||||
|
|
||||||
|
RemoveEntry(aBrowsingContext,
|
||||||
|
parentContext->GetSessionStoreScrollDataRef().get());
|
||||||
|
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (aBrowsingContext->IsTop()) {
|
||||||
|
mFormData = nullptr;
|
||||||
|
mScrollData = nullptr;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
BrowserSessionStore::~BrowserSessionStore() {
|
||||||
|
if (sSessionStore) {
|
||||||
|
sSessionStore->Remove(mBrowsingContext->Id());
|
||||||
|
}
|
||||||
|
}
|
||||||
57
toolkit/components/sessionstore/BrowserSessionStore.h
Normal file
57
toolkit/components/sessionstore/BrowserSessionStore.h
Normal file
@@ -0,0 +1,57 @@
|
|||||||
|
/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
|
||||||
|
/* vim: set ts=8 sts=2 et sw=2 tw=80: */
|
||||||
|
/* This Source Code Form is subject to the terms of the Mozilla Public
|
||||||
|
* License, v. 2.0. If a copy of the MPL was not distributed with this
|
||||||
|
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
|
||||||
|
|
||||||
|
#ifndef mozilla_dom_SessionStore_h
|
||||||
|
#define mozilla_dom_SessionStore_h
|
||||||
|
|
||||||
|
#include "nsWrapperCache.h"
|
||||||
|
|
||||||
|
#include "mozilla/Maybe.h"
|
||||||
|
|
||||||
|
struct nsPoint;
|
||||||
|
|
||||||
|
namespace mozilla::dom {
|
||||||
|
|
||||||
|
class CanonicalBrowsingContext;
|
||||||
|
class GlobalObject;
|
||||||
|
class SessionStoreFormData;
|
||||||
|
class SessionStoreScrollData;
|
||||||
|
class WindowGlobalParent;
|
||||||
|
|
||||||
|
namespace sessionstore {
|
||||||
|
class FormData;
|
||||||
|
}
|
||||||
|
|
||||||
|
class BrowserSessionStore final {
|
||||||
|
public:
|
||||||
|
NS_INLINE_DECL_CYCLE_COLLECTING_NATIVE_REFCOUNTING(BrowserSessionStore)
|
||||||
|
NS_DECL_CYCLE_COLLECTION_NATIVE_CLASS(BrowserSessionStore)
|
||||||
|
|
||||||
|
static already_AddRefed<BrowserSessionStore> GetOrCreate(
|
||||||
|
CanonicalBrowsingContext* aBrowsingContext);
|
||||||
|
|
||||||
|
SessionStoreFormData* GetFormdata();
|
||||||
|
SessionStoreScrollData* GetScroll();
|
||||||
|
|
||||||
|
void UpdateSessionStore(CanonicalBrowsingContext* aBrowsingContext,
|
||||||
|
const Maybe<sessionstore::FormData>& aFormData,
|
||||||
|
const Maybe<nsPoint>& aScrollPosition,
|
||||||
|
uint32_t aEpoch);
|
||||||
|
|
||||||
|
void RemoveSessionStore(CanonicalBrowsingContext* aBrowsingContext);
|
||||||
|
|
||||||
|
private:
|
||||||
|
explicit BrowserSessionStore(CanonicalBrowsingContext* aBrowsingContext);
|
||||||
|
virtual ~BrowserSessionStore();
|
||||||
|
|
||||||
|
RefPtr<CanonicalBrowsingContext> mBrowsingContext;
|
||||||
|
RefPtr<SessionStoreFormData> mFormData;
|
||||||
|
RefPtr<SessionStoreScrollData> mScrollData;
|
||||||
|
};
|
||||||
|
|
||||||
|
} // namespace mozilla::dom
|
||||||
|
|
||||||
|
#endif // mozilla_dom_SessionStore_h
|
||||||
60
toolkit/components/sessionstore/PSessionStore.ipdl
Normal file
60
toolkit/components/sessionstore/PSessionStore.ipdl
Normal file
@@ -0,0 +1,60 @@
|
|||||||
|
/* -*- Mode: C++; c-basic-offset: 2; indent-tabs-mode: nil; tab-width: 8 -*- */
|
||||||
|
/* vim: set sw=2 ts=8 et tw=80 ft=cpp : */
|
||||||
|
/* This Source Code Form is subject to the terms of the Mozilla Public
|
||||||
|
* License, v. 2.0. If a copy of the MPL was not distributed with this
|
||||||
|
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
|
||||||
|
|
||||||
|
include protocol PBrowser;
|
||||||
|
include protocol PInProcess;
|
||||||
|
include SessionStoreTypes;
|
||||||
|
|
||||||
|
using mozilla::dom::MaybeDiscardedBrowsingContext from "mozilla/dom/BrowsingContext.h";
|
||||||
|
|
||||||
|
namespace mozilla {
|
||||||
|
namespace dom {
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The PSessionStore actor handles collection of session store data from content
|
||||||
|
* type documents. It can be used both in a content process and in the parent
|
||||||
|
* process. In particular it solves the problem of handling incremental updates
|
||||||
|
* to the session store, since we're collecting from potentially several content
|
||||||
|
* processes.
|
||||||
|
*/
|
||||||
|
async protocol PSessionStore
|
||||||
|
{
|
||||||
|
manager PBrowser or PInProcess;
|
||||||
|
|
||||||
|
parent:
|
||||||
|
/**
|
||||||
|
* Sends data to be stored and instructions to the session store to
|
||||||
|
* potentially collect data in the parent. This is data that is not
|
||||||
|
* collected incrementally.
|
||||||
|
*/
|
||||||
|
async SessionStoreUpdate(
|
||||||
|
nsCString? aDocShellCaps, bool? aPrivateMode, bool aNeedCollectSHistory,
|
||||||
|
uint32_t aEpoch);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Sends data to be stored to the session store. The collected data
|
||||||
|
* is all the collected changed data from all the in-process documents
|
||||||
|
* in the process in which the SessionStoreChild actor lives.
|
||||||
|
*/
|
||||||
|
async IncrementalSessionStoreUpdate(
|
||||||
|
MaybeDiscardedBrowsingContext aBrowsingContext, FormData? aFormData,
|
||||||
|
nsPoint? aScrollPosition, uint32_t aEpoch);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Drop all the collected data associated with the provided browsing
|
||||||
|
* context.
|
||||||
|
*/
|
||||||
|
async ResetSessionStore(
|
||||||
|
MaybeDiscardedBrowsingContext aBrowsingContext, uint32_t aEpoch);
|
||||||
|
|
||||||
|
child:
|
||||||
|
async FlushTabState() returns(bool aHadContext);
|
||||||
|
|
||||||
|
async __delete__();
|
||||||
|
};
|
||||||
|
|
||||||
|
} // namespace dom
|
||||||
|
} // namespace mozilla
|
||||||
@@ -10,13 +10,23 @@
|
|||||||
#include "mozilla/dom/Element.h"
|
#include "mozilla/dom/Element.h"
|
||||||
#include "mozilla/dom/Event.h"
|
#include "mozilla/dom/Event.h"
|
||||||
#include "mozilla/dom/EventTarget.h"
|
#include "mozilla/dom/EventTarget.h"
|
||||||
#include "mozilla/dom/SessionStoreDataCollector.h"
|
#include "mozilla/dom/SessionStoreChild.h"
|
||||||
#include "mozilla/dom/SessionStoreUtils.h"
|
#include "mozilla/dom/SessionStoreUtils.h"
|
||||||
#include "mozilla/dom/WindowGlobalChild.h"
|
#include "mozilla/dom/WindowGlobalChild.h"
|
||||||
#include "mozilla/Preferences.h"
|
#include "mozilla/Preferences.h"
|
||||||
|
#include "mozilla/PresShell.h"
|
||||||
|
#include "mozilla/StaticPrefs_browser.h"
|
||||||
|
|
||||||
|
#include "nsBaseHashtable.h"
|
||||||
#include "nsDocShell.h"
|
#include "nsDocShell.h"
|
||||||
|
#include "nsGenericHTMLElement.h"
|
||||||
|
#include "nsIXULRuntime.h"
|
||||||
#include "nsPIDOMWindow.h"
|
#include "nsPIDOMWindow.h"
|
||||||
|
#include "nsTHashMap.h"
|
||||||
|
#include "nsTHashtable.h"
|
||||||
|
|
||||||
|
using namespace mozilla;
|
||||||
|
using namespace mozilla::dom;
|
||||||
|
|
||||||
namespace {
|
namespace {
|
||||||
constexpr auto kInput = u"input"_ns;
|
constexpr auto kInput = u"input"_ns;
|
||||||
@@ -28,13 +38,28 @@ static constexpr char kInterval[] = "browser.sessionstore.interval";
|
|||||||
static const char* kObservedPrefs[] = {kNoAutoUpdates, kInterval, nullptr};
|
static const char* kObservedPrefs[] = {kNoAutoUpdates, kInterval, nullptr};
|
||||||
} // namespace
|
} // namespace
|
||||||
|
|
||||||
namespace mozilla::dom {
|
inline void ImplCycleCollectionUnlink(
|
||||||
|
SessionStoreChangeListener::SessionStoreChangeTable& aField) {
|
||||||
|
aField.Clear();
|
||||||
|
}
|
||||||
|
|
||||||
|
inline void ImplCycleCollectionTraverse(
|
||||||
|
nsCycleCollectionTraversalCallback& aCallback,
|
||||||
|
const SessionStoreChangeListener::SessionStoreChangeTable& aField,
|
||||||
|
const char* aName, uint32_t aFlags = 0) {
|
||||||
|
for (auto iter = aField.ConstIter(); !iter.Done(); iter.Next()) {
|
||||||
|
CycleCollectionNoteChild(aCallback, iter.Key(), aName, aFlags);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
NS_IMPL_CYCLE_COLLECTION(SessionStoreChangeListener, mBrowsingContext,
|
NS_IMPL_CYCLE_COLLECTION(SessionStoreChangeListener, mBrowsingContext,
|
||||||
mCurrentEventTarget)
|
mCurrentEventTarget, mSessionStoreChild,
|
||||||
|
mSessionStoreChanges)
|
||||||
|
|
||||||
NS_INTERFACE_MAP_BEGIN_CYCLE_COLLECTION(SessionStoreChangeListener)
|
NS_INTERFACE_MAP_BEGIN_CYCLE_COLLECTION(SessionStoreChangeListener)
|
||||||
|
NS_INTERFACE_MAP_ENTRY(nsINamed)
|
||||||
NS_INTERFACE_MAP_ENTRY(nsIObserver)
|
NS_INTERFACE_MAP_ENTRY(nsIObserver)
|
||||||
|
NS_INTERFACE_MAP_ENTRY(nsITimerCallback)
|
||||||
NS_INTERFACE_MAP_ENTRY(nsIDOMEventListener)
|
NS_INTERFACE_MAP_ENTRY(nsIDOMEventListener)
|
||||||
NS_INTERFACE_MAP_ENTRY_AMBIGUOUS(nsISupports, nsIObserver)
|
NS_INTERFACE_MAP_ENTRY_AMBIGUOUS(nsISupports, nsIObserver)
|
||||||
NS_INTERFACE_MAP_END
|
NS_INTERFACE_MAP_END
|
||||||
@@ -42,10 +67,22 @@ NS_INTERFACE_MAP_END
|
|||||||
NS_IMPL_CYCLE_COLLECTING_ADDREF(SessionStoreChangeListener)
|
NS_IMPL_CYCLE_COLLECTING_ADDREF(SessionStoreChangeListener)
|
||||||
NS_IMPL_CYCLE_COLLECTING_RELEASE(SessionStoreChangeListener)
|
NS_IMPL_CYCLE_COLLECTING_RELEASE(SessionStoreChangeListener)
|
||||||
|
|
||||||
|
NS_IMETHODIMP
|
||||||
|
SessionStoreChangeListener::GetName(nsACString& aName) {
|
||||||
|
aName.AssignLiteral("SessionStoreChangeListener");
|
||||||
|
return NS_OK;
|
||||||
|
}
|
||||||
|
|
||||||
|
NS_IMETHODIMP
|
||||||
|
SessionStoreChangeListener::Notify(nsITimer* aTimer) {
|
||||||
|
FlushSessionStore();
|
||||||
|
return NS_OK;
|
||||||
|
}
|
||||||
|
|
||||||
NS_IMETHODIMP
|
NS_IMETHODIMP
|
||||||
SessionStoreChangeListener::Observe(nsISupports* aSubject, const char* aTopic,
|
SessionStoreChangeListener::Observe(nsISupports* aSubject, const char* aTopic,
|
||||||
const char16_t* aData) {
|
const char16_t* aData) {
|
||||||
Flush();
|
FlushSessionStore();
|
||||||
return NS_OK;
|
return NS_OK;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -62,45 +99,33 @@ SessionStoreChangeListener::HandleEvent(dom::Event* aEvent) {
|
|||||||
return NS_OK;
|
return NS_OK;
|
||||||
}
|
}
|
||||||
|
|
||||||
WindowGlobalChild* windowChild = inner->GetWindowGlobalChild();
|
WindowContext* windowContext = inner->GetWindowContext();
|
||||||
if (!windowChild) {
|
if (!windowContext) {
|
||||||
return NS_OK;
|
return NS_OK;
|
||||||
}
|
}
|
||||||
|
|
||||||
RefPtr<BrowsingContext> browsingContext = windowChild->BrowsingContext();
|
RefPtr<BrowsingContext> browsingContext = windowContext->GetBrowsingContext();
|
||||||
if (!browsingContext) {
|
if (!browsingContext) {
|
||||||
return NS_OK;
|
return NS_OK;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool dynamic = false;
|
if (browsingContext->IsDynamic()) {
|
||||||
BrowsingContext* current = browsingContext;
|
|
||||||
while (current) {
|
|
||||||
if ((dynamic = current->CreatedDynamically())) {
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
current = current->GetParent();
|
|
||||||
}
|
|
||||||
|
|
||||||
if (dynamic) {
|
|
||||||
return NS_OK;
|
return NS_OK;
|
||||||
}
|
}
|
||||||
|
|
||||||
nsAutoString eventType;
|
nsAutoString eventType;
|
||||||
aEvent->GetType(eventType);
|
aEvent->GetType(eventType);
|
||||||
|
|
||||||
RefPtr<SessionStoreDataCollector> collector =
|
Change change = Change::None;
|
||||||
SessionStoreDataCollector::CollectSessionStoreData(windowChild);
|
|
||||||
|
|
||||||
if (!collector) {
|
|
||||||
return NS_OK;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (eventType == kInput) {
|
if (eventType == kInput) {
|
||||||
collector->RecordInputChange();
|
change = Change::Input;
|
||||||
} else if (eventType == kScroll) {
|
} else if (eventType == kScroll) {
|
||||||
collector->RecordScrollChange();
|
change = Change::Scroll;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
RecordChange(windowContext, EnumSet(change));
|
||||||
|
|
||||||
return NS_OK;
|
return NS_OK;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -128,13 +153,134 @@ void SessionStoreChangeListener::UpdateEventTargets() {
|
|||||||
AddEventListeners();
|
AddEventListeners();
|
||||||
}
|
}
|
||||||
|
|
||||||
void SessionStoreChangeListener::Flush() {
|
static void CollectFormData(Document* aDocument,
|
||||||
mBrowsingContext->FlushSessionStore();
|
Maybe<sessionstore::FormData>& aFormData) {
|
||||||
|
aFormData.emplace();
|
||||||
|
auto& formData = aFormData.ref();
|
||||||
|
uint32_t size = SessionStoreUtils::CollectFormData(aDocument, formData);
|
||||||
|
|
||||||
|
Element* body = aDocument->GetBody();
|
||||||
|
if (aDocument->HasFlag(NODE_IS_EDITABLE) && body) {
|
||||||
|
IgnoredErrorResult result;
|
||||||
|
body->GetInnerHTML(formData.innerHTML(), result);
|
||||||
|
size += formData.innerHTML().Length();
|
||||||
|
if (!result.Failed()) {
|
||||||
|
formData.hasData() = true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!formData.hasData()) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
nsIURI* documentURI = aDocument->GetDocumentURI();
|
||||||
|
if (!documentURI) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
documentURI->GetSpecIgnoringRef(formData.uri());
|
||||||
|
|
||||||
|
if (size > StaticPrefs::browser_sessionstore_dom_form_max_limit()) {
|
||||||
|
aFormData = Nothing();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void SessionStoreChangeListener::FlushSessionStore() {
|
||||||
|
if (mTimer) {
|
||||||
|
mTimer->Cancel();
|
||||||
|
mTimer = nullptr;
|
||||||
|
}
|
||||||
|
|
||||||
|
for (auto& iter : mSessionStoreChanges) {
|
||||||
|
WindowContext* windowContext = iter.GetKey();
|
||||||
|
if (!windowContext) {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
RefPtr<Document> document = windowContext->GetDocument();
|
||||||
|
if (!document) {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
EnumSet<Change> changes = iter.GetData();
|
||||||
|
Maybe<sessionstore::FormData> maybeFormData;
|
||||||
|
if (changes.contains(Change::Input)) {
|
||||||
|
CollectFormData(document, maybeFormData);
|
||||||
|
}
|
||||||
|
|
||||||
|
Maybe<nsPoint> maybeScroll;
|
||||||
|
PresShell* presShell = document->GetPresShell();
|
||||||
|
|
||||||
|
if (presShell && changes.contains(Change::Scroll)) {
|
||||||
|
maybeScroll = Some(presShell->GetVisualViewportOffset());
|
||||||
|
}
|
||||||
|
|
||||||
|
mSessionStoreChild->SendIncrementalSessionStoreUpdate(
|
||||||
|
windowContext->GetBrowsingContext(), maybeFormData, maybeScroll,
|
||||||
|
mEpoch);
|
||||||
|
}
|
||||||
|
|
||||||
|
mSessionStoreChanges.Clear();
|
||||||
|
|
||||||
|
mSessionStoreChild->UpdateSessionStore();
|
||||||
|
}
|
||||||
|
|
||||||
|
/* static */
|
||||||
|
SessionStoreChangeListener* SessionStoreChangeListener::CollectSessionStoreData(
|
||||||
|
WindowContext* aWindowContext, const EnumSet<Change>& aChanges) {
|
||||||
|
SessionStoreChild* sessionStoreChild =
|
||||||
|
SessionStoreChild::From(aWindowContext->GetWindowGlobalChild());
|
||||||
|
if (!sessionStoreChild) {
|
||||||
|
return nullptr;
|
||||||
|
}
|
||||||
|
|
||||||
|
SessionStoreChangeListener* sessionStoreChangeListener =
|
||||||
|
sessionStoreChild->GetSessionStoreChangeListener();
|
||||||
|
|
||||||
|
if (!sessionStoreChangeListener) {
|
||||||
|
return nullptr;
|
||||||
|
}
|
||||||
|
|
||||||
|
sessionStoreChangeListener->RecordChange(aWindowContext, aChanges);
|
||||||
|
|
||||||
|
return sessionStoreChangeListener;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* static */
|
||||||
|
void SessionStoreChangeListener::FlushAllSessionStoreData(
|
||||||
|
WindowContext* aWindowContext) {
|
||||||
|
EnumSet<Change> allChanges(Change::Input, Change::Scroll);
|
||||||
|
SessionStoreChangeListener* listener =
|
||||||
|
CollectSessionStoreData(aWindowContext, allChanges);
|
||||||
|
if (listener) {
|
||||||
|
listener->FlushSessionStore();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void SessionStoreChangeListener::SetActor(
|
||||||
|
SessionStoreChild* aSessionStoreChild) {
|
||||||
|
mSessionStoreChild = aSessionStoreChild;
|
||||||
|
}
|
||||||
|
|
||||||
|
void SessionStoreChangeListener::RecordChange(WindowContext* aWindowContext,
|
||||||
|
EnumSet<Change> aChange) {
|
||||||
|
EnsureTimer();
|
||||||
|
|
||||||
|
Unused << mSessionStoreChanges.WithEntryHandle(
|
||||||
|
aWindowContext, [&](auto entryHandle) -> EnumSet<Change>& {
|
||||||
|
if (entryHandle) {
|
||||||
|
*entryHandle += aChange;
|
||||||
|
return *entryHandle;
|
||||||
|
}
|
||||||
|
|
||||||
|
return entryHandle.Insert(aChange);
|
||||||
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
SessionStoreChangeListener::SessionStoreChangeListener(
|
SessionStoreChangeListener::SessionStoreChangeListener(
|
||||||
BrowsingContext* aBrowsingContext)
|
BrowsingContext* aBrowsingContext)
|
||||||
: mBrowsingContext(aBrowsingContext) {}
|
: mBrowsingContext(aBrowsingContext),
|
||||||
|
mEpoch(aBrowsingContext->GetSessionStoreEpoch()) {}
|
||||||
|
|
||||||
void SessionStoreChangeListener::Init() {
|
void SessionStoreChangeListener::Init() {
|
||||||
AddEventListeners();
|
AddEventListeners();
|
||||||
@@ -167,4 +313,19 @@ void SessionStoreChangeListener::RemoveEventListeners() {
|
|||||||
mCurrentEventTarget = nullptr;
|
mCurrentEventTarget = nullptr;
|
||||||
}
|
}
|
||||||
|
|
||||||
} // namespace mozilla::dom
|
void SessionStoreChangeListener::EnsureTimer() {
|
||||||
|
if (mTimer) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!StaticPrefs::browser_sessionstore_debug_no_auto_updates()) {
|
||||||
|
auto result = NS_NewTimerWithCallback(
|
||||||
|
this, StaticPrefs::browser_sessionstore_interval(),
|
||||||
|
nsITimer::TYPE_ONE_SHOT);
|
||||||
|
if (result.isErr()) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
mTimer = result.unwrap();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|||||||
@@ -9,25 +9,39 @@
|
|||||||
|
|
||||||
#include "ErrorList.h"
|
#include "ErrorList.h"
|
||||||
|
|
||||||
|
#include "PLDHashTable.h"
|
||||||
|
#include "mozilla/EnumSet.h"
|
||||||
|
#include "nsCycleCollectionParticipant.h"
|
||||||
|
#include "nsHashKeys.h"
|
||||||
#include "nsIDOMEventListener.h"
|
#include "nsIDOMEventListener.h"
|
||||||
#include "nsIObserver.h"
|
#include "nsIObserver.h"
|
||||||
|
#include "nsISupports.h"
|
||||||
|
#include "nsITimer.h"
|
||||||
|
#include "nsINamed.h"
|
||||||
|
#include "nsHashtablesFwd.h"
|
||||||
|
|
||||||
#include "nsCycleCollectionParticipant.h"
|
#include "mozilla/EnumSet.h"
|
||||||
|
|
||||||
#include "mozilla/RefPtr.h"
|
#include "mozilla/RefPtr.h"
|
||||||
#include "mozilla/Result.h"
|
#include "mozilla/Result.h"
|
||||||
|
|
||||||
|
#include "mozilla/dom/WindowGlobalChild.h"
|
||||||
|
|
||||||
namespace mozilla::dom {
|
namespace mozilla::dom {
|
||||||
|
|
||||||
|
class BrowsingContext;
|
||||||
class Element;
|
class Element;
|
||||||
class EventTarget;
|
class EventTarget;
|
||||||
class SessionStoreDataCollector;
|
class SessionStoreChild;
|
||||||
class BrowsingContext;
|
class WindowContext;
|
||||||
|
|
||||||
class SessionStoreChangeListener final : public nsIObserver,
|
class SessionStoreChangeListener final : public nsINamed,
|
||||||
|
public nsIObserver,
|
||||||
|
public nsITimerCallback,
|
||||||
public nsIDOMEventListener {
|
public nsIDOMEventListener {
|
||||||
public:
|
public:
|
||||||
|
NS_DECL_NSINAMED
|
||||||
NS_DECL_NSIOBSERVER
|
NS_DECL_NSIOBSERVER
|
||||||
|
NS_DECL_NSITIMERCALLBACK
|
||||||
NS_DECL_NSIDOMEVENTLISTENER
|
NS_DECL_NSIDOMEVENTLISTENER
|
||||||
NS_DECL_CYCLE_COLLECTING_ISUPPORTS
|
NS_DECL_CYCLE_COLLECTING_ISUPPORTS
|
||||||
NS_DECL_CYCLE_COLLECTION_CLASS_AMBIGUOUS(SessionStoreChangeListener,
|
NS_DECL_CYCLE_COLLECTION_CLASS_AMBIGUOUS(SessionStoreChangeListener,
|
||||||
@@ -40,7 +54,29 @@ class SessionStoreChangeListener final : public nsIObserver,
|
|||||||
|
|
||||||
void UpdateEventTargets();
|
void UpdateEventTargets();
|
||||||
|
|
||||||
void Flush();
|
void FlushSessionStore();
|
||||||
|
|
||||||
|
enum class Change { None, Input, Scroll };
|
||||||
|
|
||||||
|
static SessionStoreChangeListener* CollectSessionStoreData(
|
||||||
|
WindowContext* aWindowContext, const EnumSet<Change>& aChanges);
|
||||||
|
|
||||||
|
static void FlushAllSessionStoreData(WindowContext* aWindowContext);
|
||||||
|
|
||||||
|
void SetActor(SessionStoreChild* aSessionStoreChild);
|
||||||
|
|
||||||
|
void SetEpoch(uint32_t aEpoch) { mEpoch = aEpoch; }
|
||||||
|
|
||||||
|
uint32_t GetEpoch() const { return mEpoch; }
|
||||||
|
|
||||||
|
BrowsingContext* GetBrowsingContext() const { return mBrowsingContext; }
|
||||||
|
|
||||||
|
private:
|
||||||
|
void RecordChange(WindowContext* aWindowContext, EnumSet<Change> aChanges);
|
||||||
|
|
||||||
|
public:
|
||||||
|
using SessionStoreChangeTable =
|
||||||
|
nsTHashMap<RefPtr<WindowContext>, EnumSet<Change>>;
|
||||||
|
|
||||||
private:
|
private:
|
||||||
explicit SessionStoreChangeListener(BrowsingContext* aBrowsingContext);
|
explicit SessionStoreChangeListener(BrowsingContext* aBrowsingContext);
|
||||||
@@ -53,8 +89,15 @@ class SessionStoreChangeListener final : public nsIObserver,
|
|||||||
void AddEventListeners();
|
void AddEventListeners();
|
||||||
void RemoveEventListeners();
|
void RemoveEventListeners();
|
||||||
|
|
||||||
|
void EnsureTimer();
|
||||||
|
|
||||||
RefPtr<BrowsingContext> mBrowsingContext;
|
RefPtr<BrowsingContext> mBrowsingContext;
|
||||||
RefPtr<EventTarget> mCurrentEventTarget;
|
RefPtr<EventTarget> mCurrentEventTarget;
|
||||||
|
|
||||||
|
uint32_t mEpoch;
|
||||||
|
nsCOMPtr<nsITimer> mTimer;
|
||||||
|
RefPtr<SessionStoreChild> mSessionStoreChild;
|
||||||
|
SessionStoreChangeTable mSessionStoreChanges;
|
||||||
};
|
};
|
||||||
|
|
||||||
} // namespace mozilla::dom
|
} // namespace mozilla::dom
|
||||||
|
|||||||
226
toolkit/components/sessionstore/SessionStoreChild.cpp
Normal file
226
toolkit/components/sessionstore/SessionStoreChild.cpp
Normal file
@@ -0,0 +1,226 @@
|
|||||||
|
/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
|
||||||
|
/* vim: set ts=8 sts=2 et sw=2 tw=80: */
|
||||||
|
/* This Source Code Form is subject to the terms of the Mozilla Public
|
||||||
|
* License, v. 2.0. If a copy of the MPL was not distributed with this
|
||||||
|
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
|
||||||
|
|
||||||
|
#include "mozilla/dom/SessionStoreChild.h"
|
||||||
|
|
||||||
|
#include "mozilla/AlreadyAddRefed.h"
|
||||||
|
#include "mozilla/Assertions.h"
|
||||||
|
#include "mozilla/RefPtr.h"
|
||||||
|
#include "mozilla/ScopeExit.h"
|
||||||
|
#include "mozilla/dom/BrowserChild.h"
|
||||||
|
#include "mozilla/dom/BrowsingContext.h"
|
||||||
|
#include "mozilla/dom/InProcessChild.h"
|
||||||
|
#include "mozilla/dom/InProcessParent.h"
|
||||||
|
#include "mozilla/dom/BrowserSessionStore.h"
|
||||||
|
#include "mozilla/dom/SessionStoreChangeListener.h"
|
||||||
|
#include "mozilla/dom/SessionStoreParent.h"
|
||||||
|
#include "mozilla/dom/WindowGlobalParent.h"
|
||||||
|
#include "mozilla/ipc/Endpoint.h"
|
||||||
|
#include "nsCOMPtr.h"
|
||||||
|
#include "nsFrameLoader.h"
|
||||||
|
|
||||||
|
using namespace mozilla;
|
||||||
|
using namespace mozilla::dom;
|
||||||
|
|
||||||
|
class nsIDocShell;
|
||||||
|
|
||||||
|
static already_AddRefed<TabListener> CreateTabListener(nsIDocShell* aDocShell) {
|
||||||
|
RefPtr<TabListener> tabListener =
|
||||||
|
mozilla::MakeRefPtr<TabListener>(aDocShell, nullptr);
|
||||||
|
nsresult rv = tabListener->Init();
|
||||||
|
if (NS_FAILED(rv)) {
|
||||||
|
return nullptr;
|
||||||
|
}
|
||||||
|
|
||||||
|
return tabListener.forget();
|
||||||
|
}
|
||||||
|
|
||||||
|
already_AddRefed<SessionStoreChild> SessionStoreChild::GetOrCreate(
|
||||||
|
BrowsingContext* aBrowsingContext, Element* aOwnerElement) {
|
||||||
|
RefPtr<TabListener> tabListener =
|
||||||
|
CreateTabListener(aBrowsingContext->GetDocShell());
|
||||||
|
if (!tabListener) {
|
||||||
|
return nullptr;
|
||||||
|
}
|
||||||
|
|
||||||
|
RefPtr<SessionStoreChangeListener> sessionStoreChangeListener =
|
||||||
|
SessionStoreChangeListener::Create(aBrowsingContext);
|
||||||
|
if (!sessionStoreChangeListener) {
|
||||||
|
return nullptr;
|
||||||
|
}
|
||||||
|
|
||||||
|
RefPtr<SessionStoreChild> sessionStoreChild =
|
||||||
|
new SessionStoreChild(tabListener, sessionStoreChangeListener);
|
||||||
|
|
||||||
|
sessionStoreChangeListener->SetActor(sessionStoreChild);
|
||||||
|
|
||||||
|
if (XRE_IsParentProcess()) {
|
||||||
|
MOZ_DIAGNOSTIC_ASSERT(aOwnerElement);
|
||||||
|
InProcessChild* inProcessChild = InProcessChild::Singleton();
|
||||||
|
InProcessParent* inProcessParent = InProcessParent::Singleton();
|
||||||
|
if (!inProcessChild || !inProcessParent) {
|
||||||
|
return nullptr;
|
||||||
|
}
|
||||||
|
|
||||||
|
RefPtr<BrowserSessionStore> sessionStore =
|
||||||
|
BrowserSessionStore::GetOrCreate(aBrowsingContext->Canonical()->Top());
|
||||||
|
if (!sessionStore) {
|
||||||
|
return nullptr;
|
||||||
|
}
|
||||||
|
|
||||||
|
CanonicalBrowsingContext* browsingContext = aBrowsingContext->Canonical();
|
||||||
|
RefPtr<SessionStoreParent> sessionStoreParent =
|
||||||
|
new SessionStoreParent(browsingContext, sessionStore);
|
||||||
|
ManagedEndpoint<PSessionStoreParent> endpoint =
|
||||||
|
inProcessChild->OpenPSessionStoreEndpoint(sessionStoreChild);
|
||||||
|
inProcessParent->BindPSessionStoreEndpoint(std::move(endpoint),
|
||||||
|
sessionStoreParent);
|
||||||
|
} else {
|
||||||
|
MOZ_DIAGNOSTIC_ASSERT(!aOwnerElement);
|
||||||
|
RefPtr<BrowserChild> browserChild =
|
||||||
|
BrowserChild::GetFrom(aBrowsingContext->GetDOMWindow());
|
||||||
|
|
||||||
|
MOZ_DIAGNOSTIC_ASSERT(browserChild);
|
||||||
|
MOZ_DIAGNOSTIC_ASSERT(aBrowsingContext->IsInProcess());
|
||||||
|
sessionStoreChild = static_cast<SessionStoreChild*>(
|
||||||
|
browserChild->SendPSessionStoreConstructor(sessionStoreChild));
|
||||||
|
}
|
||||||
|
|
||||||
|
return sessionStoreChild.forget();
|
||||||
|
}
|
||||||
|
|
||||||
|
/* static */
|
||||||
|
SessionStoreChild* SessionStoreChild::From(WindowGlobalChild* aWindowChild) {
|
||||||
|
if (!aWindowChild) {
|
||||||
|
return nullptr;
|
||||||
|
}
|
||||||
|
|
||||||
|
// If `aWindowChild` is inprocess
|
||||||
|
if (RefPtr<BrowserChild> browserChild = aWindowChild->GetBrowserChild()) {
|
||||||
|
return browserChild->GetSessionStoreChild();
|
||||||
|
}
|
||||||
|
|
||||||
|
if (XRE_IsContentProcess()) {
|
||||||
|
return nullptr;
|
||||||
|
}
|
||||||
|
|
||||||
|
WindowGlobalParent* windowParent = aWindowChild->WindowContext()->Canonical();
|
||||||
|
if (!windowParent) {
|
||||||
|
return nullptr;
|
||||||
|
}
|
||||||
|
|
||||||
|
RefPtr<nsFrameLoader> frameLoader = windowParent->GetRootFrameLoader();
|
||||||
|
if (!frameLoader) {
|
||||||
|
return nullptr;
|
||||||
|
}
|
||||||
|
|
||||||
|
return frameLoader->GetSessionStoreChild();
|
||||||
|
}
|
||||||
|
|
||||||
|
SessionStoreChild::SessionStoreChild(
|
||||||
|
TabListener* aSessionStoreListener,
|
||||||
|
SessionStoreChangeListener* aSessionStoreChangeListener)
|
||||||
|
: mSessionStoreListener(aSessionStoreListener),
|
||||||
|
mSessionStoreChangeListener(aSessionStoreChangeListener) {}
|
||||||
|
|
||||||
|
void SessionStoreChild::SetEpoch(uint32_t aEpoch) {
|
||||||
|
if (mSessionStoreListener) {
|
||||||
|
mSessionStoreListener->SetEpoch(aEpoch);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (mSessionStoreChangeListener) {
|
||||||
|
mSessionStoreChangeListener->SetEpoch(aEpoch);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void SessionStoreChild::SetOwnerContent(Element* aElement) {
|
||||||
|
if (mSessionStoreChangeListener) {
|
||||||
|
mSessionStoreChangeListener->FlushSessionStore();
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!aElement) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (mSessionStoreListener) {
|
||||||
|
mSessionStoreListener->SetOwnerContent(aElement);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void SessionStoreChild::Stop() {
|
||||||
|
if (mSessionStoreListener) {
|
||||||
|
mSessionStoreListener->RemoveListeners();
|
||||||
|
mSessionStoreListener = nullptr;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (mSessionStoreChangeListener) {
|
||||||
|
mSessionStoreChangeListener->Stop();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void SessionStoreChild::UpdateEventTargets() {
|
||||||
|
if (mSessionStoreChangeListener) {
|
||||||
|
mSessionStoreChangeListener->UpdateEventTargets();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void SessionStoreChild::UpdateSessionStore() {
|
||||||
|
if (!mSessionStoreListener) {
|
||||||
|
// This is the case when we're shutting down, and expect a final update.
|
||||||
|
Unused << SendSessionStoreUpdate(Nothing(), Nothing(), false, 0);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
RefPtr<ContentSessionStore> store = mSessionStoreListener->GetSessionStore();
|
||||||
|
|
||||||
|
Maybe<nsCString> docShellCaps;
|
||||||
|
if (store->IsDocCapChanged()) {
|
||||||
|
docShellCaps.emplace(store->GetDocShellCaps());
|
||||||
|
}
|
||||||
|
|
||||||
|
Maybe<bool> privatedMode;
|
||||||
|
if (store->IsPrivateChanged()) {
|
||||||
|
privatedMode.emplace(store->GetPrivateModeEnabled());
|
||||||
|
}
|
||||||
|
|
||||||
|
Unused << SendSessionStoreUpdate(docShellCaps, privatedMode,
|
||||||
|
store->GetAndClearSHistoryChanged(),
|
||||||
|
mSessionStoreListener->GetEpoch());
|
||||||
|
}
|
||||||
|
|
||||||
|
void SessionStoreChild::FlushSessionStore() {
|
||||||
|
if (mSessionStoreChangeListener) {
|
||||||
|
mSessionStoreChangeListener->FlushSessionStore();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void SessionStoreChild::UpdateSHistoryChanges() {
|
||||||
|
if (mSessionStoreListener) {
|
||||||
|
mSessionStoreListener->UpdateSHistoryChanges();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
mozilla::ipc::IPCResult SessionStoreChild::RecvFlushTabState(
|
||||||
|
FlushTabStateResolver&& aResolver) {
|
||||||
|
if (mSessionStoreChangeListener) {
|
||||||
|
if (BrowsingContext* context =
|
||||||
|
mSessionStoreChangeListener->GetBrowsingContext()) {
|
||||||
|
if (auto* docShell = nsDocShell::Cast(context->GetDocShell())) {
|
||||||
|
docShell->CollectWireframe();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
mSessionStoreChangeListener->FlushSessionStore();
|
||||||
|
}
|
||||||
|
aResolver(true);
|
||||||
|
|
||||||
|
return IPC_OK();
|
||||||
|
}
|
||||||
|
|
||||||
|
NS_IMPL_CYCLE_COLLECTION(SessionStoreChild, mSessionStoreListener,
|
||||||
|
mSessionStoreChangeListener)
|
||||||
|
NS_IMPL_CYCLE_COLLECTION_ROOT_NATIVE(SessionStoreChild, AddRef)
|
||||||
|
NS_IMPL_CYCLE_COLLECTION_UNROOT_NATIVE(SessionStoreChild, Release)
|
||||||
57
toolkit/components/sessionstore/SessionStoreChild.h
Normal file
57
toolkit/components/sessionstore/SessionStoreChild.h
Normal file
@@ -0,0 +1,57 @@
|
|||||||
|
/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
|
||||||
|
/* vim: set ts=8 sts=2 et sw=2 tw=80: */
|
||||||
|
/* This Source Code Form is subject to the terms of the Mozilla Public
|
||||||
|
* License, v. 2.0. If a copy of the MPL was not distributed with this
|
||||||
|
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
|
||||||
|
|
||||||
|
#ifndef mozilla_dom_SessionStoreChild_h
|
||||||
|
#define mozilla_dom_SessionStoreChild_h
|
||||||
|
|
||||||
|
#include "mozilla/AlreadyAddRefed.h"
|
||||||
|
#include "mozilla/dom/PSessionStoreChild.h"
|
||||||
|
#include "mozilla/dom/SessionStoreChangeListener.h"
|
||||||
|
#include "mozilla/dom/SessionStoreListener.h"
|
||||||
|
#include "mozilla/RefPtr.h"
|
||||||
|
|
||||||
|
#include "nsCycleCollectionParticipant.h"
|
||||||
|
|
||||||
|
namespace mozilla::dom {
|
||||||
|
class BrowsingContext;
|
||||||
|
class SessionStoreChangeListener;
|
||||||
|
class TabListener;
|
||||||
|
|
||||||
|
class SessionStoreChild final : public PSessionStoreChild {
|
||||||
|
public:
|
||||||
|
static already_AddRefed<SessionStoreChild> GetOrCreate(
|
||||||
|
BrowsingContext* aBrowsingContext, Element* aOwnerElement = nullptr);
|
||||||
|
|
||||||
|
static SessionStoreChild* From(WindowGlobalChild* aWindowChild);
|
||||||
|
|
||||||
|
void SetEpoch(uint32_t aEpoch);
|
||||||
|
void SetOwnerContent(Element* aElement);
|
||||||
|
void Stop();
|
||||||
|
void UpdateEventTargets();
|
||||||
|
void UpdateSessionStore();
|
||||||
|
void FlushSessionStore();
|
||||||
|
void UpdateSHistoryChanges();
|
||||||
|
|
||||||
|
SessionStoreChangeListener* GetSessionStoreChangeListener() const {
|
||||||
|
return mSessionStoreChangeListener;
|
||||||
|
}
|
||||||
|
|
||||||
|
mozilla::ipc::IPCResult RecvFlushTabState(FlushTabStateResolver&& aResolver);
|
||||||
|
|
||||||
|
NS_INLINE_DECL_CYCLE_COLLECTING_NATIVE_REFCOUNTING(SessionStoreChild)
|
||||||
|
NS_DECL_CYCLE_COLLECTION_NATIVE_CLASS(SessionStoreChild)
|
||||||
|
|
||||||
|
private:
|
||||||
|
SessionStoreChild(TabListener* aSessionStoreListener,
|
||||||
|
SessionStoreChangeListener* aSessionStoreChangeListener);
|
||||||
|
~SessionStoreChild() = default;
|
||||||
|
|
||||||
|
RefPtr<TabListener> mSessionStoreListener;
|
||||||
|
RefPtr<SessionStoreChangeListener> mSessionStoreChangeListener;
|
||||||
|
};
|
||||||
|
} // namespace mozilla::dom
|
||||||
|
|
||||||
|
#endif // mozilla_dom_SessionStoreChild_h
|
||||||
@@ -1,180 +0,0 @@
|
|||||||
/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
|
|
||||||
/* vim: set ts=8 sts=2 et sw=2 tw=80: */
|
|
||||||
/* This Source Code Form is subject to the terms of the Mozilla Public
|
|
||||||
* License, v. 2.0. If a copy of the MPL was not distributed with this
|
|
||||||
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
|
|
||||||
|
|
||||||
#include "mozilla/dom/SessionStoreDataCollector.h"
|
|
||||||
|
|
||||||
#include "mozilla/Assertions.h"
|
|
||||||
#include "mozilla/PresShell.h"
|
|
||||||
#include "mozilla/dom/BrowserChild.h"
|
|
||||||
#include "mozilla/dom/BrowsingContext.h"
|
|
||||||
#include "mozilla/dom/Document.h"
|
|
||||||
#include "mozilla/dom/Element.h"
|
|
||||||
#include "mozilla/dom/sessionstore/SessionStoreTypes.h"
|
|
||||||
#include "mozilla/dom/SessionStoreUtils.h"
|
|
||||||
#include "mozilla/dom/WindowGlobalChild.h"
|
|
||||||
#include "mozilla/dom/WindowGlobalParent.h"
|
|
||||||
|
|
||||||
#include "nsGenericHTMLElement.h"
|
|
||||||
#include "nsIContentInlines.h"
|
|
||||||
|
|
||||||
namespace mozilla::dom {
|
|
||||||
|
|
||||||
NS_IMPL_CYCLE_COLLECTION(SessionStoreDataCollector, mWindowChild, mTimer)
|
|
||||||
|
|
||||||
NS_INTERFACE_MAP_BEGIN_CYCLE_COLLECTION(SessionStoreDataCollector)
|
|
||||||
NS_INTERFACE_MAP_ENTRY(nsITimerCallback)
|
|
||||||
NS_INTERFACE_MAP_ENTRY(nsINamed)
|
|
||||||
NS_INTERFACE_MAP_ENTRY_AMBIGUOUS(nsISupports, nsITimerCallback)
|
|
||||||
NS_INTERFACE_MAP_END
|
|
||||||
|
|
||||||
NS_IMPL_CYCLE_COLLECTING_ADDREF(SessionStoreDataCollector)
|
|
||||||
NS_IMPL_CYCLE_COLLECTING_RELEASE(SessionStoreDataCollector)
|
|
||||||
|
|
||||||
NS_IMETHODIMP
|
|
||||||
SessionStoreDataCollector::GetName(nsACString& aName) {
|
|
||||||
aName.AssignLiteral("SessionStoreDataCollector");
|
|
||||||
return NS_OK;
|
|
||||||
}
|
|
||||||
|
|
||||||
NS_IMETHODIMP
|
|
||||||
SessionStoreDataCollector::Notify(nsITimer* aTimer) {
|
|
||||||
Collect();
|
|
||||||
return NS_OK;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* static */ already_AddRefed<SessionStoreDataCollector>
|
|
||||||
SessionStoreDataCollector::CollectSessionStoreData(
|
|
||||||
WindowGlobalChild* aWindowChild) {
|
|
||||||
MOZ_RELEASE_ASSERT(SessionStoreUtils::NATIVE_LISTENER);
|
|
||||||
MOZ_DIAGNOSTIC_ASSERT(aWindowChild);
|
|
||||||
|
|
||||||
RefPtr<SessionStoreDataCollector> listener =
|
|
||||||
aWindowChild->GetSessionStoreDataCollector();
|
|
||||||
|
|
||||||
uint32_t epoch =
|
|
||||||
aWindowChild->BrowsingContext()->Top()->GetSessionStoreEpoch();
|
|
||||||
if (listener) {
|
|
||||||
MOZ_DIAGNOSTIC_ASSERT_IF(
|
|
||||||
!StaticPrefs::browser_sessionstore_debug_no_auto_updates(),
|
|
||||||
listener->mTimer);
|
|
||||||
if (listener->mEpoch == epoch) {
|
|
||||||
return listener.forget();
|
|
||||||
}
|
|
||||||
if (listener->mTimer) {
|
|
||||||
listener->mTimer->Cancel();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
listener = new SessionStoreDataCollector(aWindowChild, epoch);
|
|
||||||
|
|
||||||
if (!StaticPrefs::browser_sessionstore_debug_no_auto_updates()) {
|
|
||||||
auto result = NS_NewTimerWithCallback(
|
|
||||||
listener, StaticPrefs::browser_sessionstore_interval(),
|
|
||||||
nsITimer::TYPE_ONE_SHOT);
|
|
||||||
if (result.isErr()) {
|
|
||||||
return nullptr;
|
|
||||||
}
|
|
||||||
|
|
||||||
listener->mTimer = result.unwrap();
|
|
||||||
}
|
|
||||||
|
|
||||||
aWindowChild->SetSessionStoreDataCollector(listener);
|
|
||||||
return listener.forget();
|
|
||||||
}
|
|
||||||
|
|
||||||
void SessionStoreDataCollector::RecordInputChange() { mInputChanged = true; }
|
|
||||||
|
|
||||||
void SessionStoreDataCollector::RecordScrollChange() { mScrollChanged = true; }
|
|
||||||
|
|
||||||
void SessionStoreDataCollector::Flush() { Collect(); }
|
|
||||||
|
|
||||||
void SessionStoreDataCollector::Cancel() {
|
|
||||||
if (mTimer) {
|
|
||||||
mTimer->Cancel();
|
|
||||||
mTimer = nullptr;
|
|
||||||
}
|
|
||||||
|
|
||||||
mWindowChild->SetSessionStoreDataCollector(nullptr);
|
|
||||||
}
|
|
||||||
|
|
||||||
void SessionStoreDataCollector::Collect() {
|
|
||||||
if (this != mWindowChild->GetSessionStoreDataCollector()) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (mTimer) {
|
|
||||||
mTimer->Cancel();
|
|
||||||
mTimer = nullptr;
|
|
||||||
}
|
|
||||||
|
|
||||||
nsGlobalWindowInner* inner = mWindowChild->GetWindowGlobal();
|
|
||||||
if (!inner) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
Document* document = inner->GetDocument();
|
|
||||||
if (!document) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
Maybe<sessionstore::FormData> maybeFormData;
|
|
||||||
if (mInputChanged) {
|
|
||||||
maybeFormData.emplace();
|
|
||||||
auto& formData = maybeFormData.ref();
|
|
||||||
uint32_t size = SessionStoreUtils::CollectFormData(document, formData);
|
|
||||||
|
|
||||||
Element* body = document->GetBody();
|
|
||||||
if (body && body->IsInDesignMode()) {
|
|
||||||
IgnoredErrorResult result;
|
|
||||||
body->GetInnerHTML(formData.innerHTML(), result);
|
|
||||||
size += formData.innerHTML().Length();
|
|
||||||
if (!result.Failed()) {
|
|
||||||
formData.hasData() = true;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if (size > StaticPrefs::browser_sessionstore_dom_form_max_limit()) {
|
|
||||||
maybeFormData = Nothing();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
PresShell* presShell = document->GetPresShell();
|
|
||||||
Maybe<nsPoint> maybeScroll;
|
|
||||||
if (mScrollChanged && presShell) {
|
|
||||||
maybeScroll = Some(presShell->GetVisualViewportOffset());
|
|
||||||
}
|
|
||||||
|
|
||||||
if (!mWindowChild->CanSend()) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (RefPtr<WindowGlobalParent> windowParent =
|
|
||||||
mWindowChild->GetParentActor()) {
|
|
||||||
windowParent->WriteFormDataAndScrollToSessionStore(maybeFormData,
|
|
||||||
maybeScroll, mEpoch);
|
|
||||||
} else {
|
|
||||||
mWindowChild->SendUpdateSessionStore(maybeFormData, maybeScroll, mEpoch);
|
|
||||||
}
|
|
||||||
|
|
||||||
mWindowChild->SetSessionStoreDataCollector(nullptr);
|
|
||||||
}
|
|
||||||
|
|
||||||
SessionStoreDataCollector::SessionStoreDataCollector(
|
|
||||||
WindowGlobalChild* aWindowChild, uint32_t aEpoch)
|
|
||||||
: mWindowChild(aWindowChild),
|
|
||||||
mTimer(nullptr),
|
|
||||||
mEpoch(aEpoch),
|
|
||||||
mInputChanged(false),
|
|
||||||
mScrollChanged(false) {}
|
|
||||||
|
|
||||||
SessionStoreDataCollector::~SessionStoreDataCollector() {
|
|
||||||
if (mTimer) {
|
|
||||||
mTimer->Cancel();
|
|
||||||
mTimer = nullptr;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
} // namespace mozilla::dom
|
|
||||||
@@ -1,68 +0,0 @@
|
|||||||
/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
|
|
||||||
/* vim: set ts=8 sts=2 et sw=2 tw=80: */
|
|
||||||
/* This Source Code Form is subject to the terms of the Mozilla Public
|
|
||||||
* License, v. 2.0. If a copy of the MPL was not distributed with this
|
|
||||||
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
|
|
||||||
|
|
||||||
#ifndef mozilla_dom_SessionStoreDataCollector_h
|
|
||||||
#define mozilla_dom_SessionStoreDataCollector_h
|
|
||||||
|
|
||||||
#include "ErrorList.h"
|
|
||||||
|
|
||||||
#include "nsITimer.h"
|
|
||||||
|
|
||||||
#include "nsCycleCollectionParticipant.h"
|
|
||||||
|
|
||||||
#include "mozilla/RefPtr.h"
|
|
||||||
|
|
||||||
namespace mozilla::dom {
|
|
||||||
|
|
||||||
class BrowserChild;
|
|
||||||
class EventTarget;
|
|
||||||
class WindowGlobalChild;
|
|
||||||
|
|
||||||
namespace sessionstore {
|
|
||||||
class FormData;
|
|
||||||
}
|
|
||||||
|
|
||||||
class SessionStoreDataCollector final : public nsITimerCallback,
|
|
||||||
public nsINamed {
|
|
||||||
public:
|
|
||||||
NS_DECL_NSITIMERCALLBACK
|
|
||||||
NS_DECL_NSINAMED
|
|
||||||
NS_DECL_CYCLE_COLLECTING_ISUPPORTS
|
|
||||||
NS_DECL_CYCLE_COLLECTION_CLASS_AMBIGUOUS(SessionStoreDataCollector,
|
|
||||||
nsITimerCallback)
|
|
||||||
|
|
||||||
enum class Change { Input, Scroll };
|
|
||||||
|
|
||||||
static already_AddRefed<SessionStoreDataCollector> CollectSessionStoreData(
|
|
||||||
WindowGlobalChild* aWindowChild);
|
|
||||||
|
|
||||||
void RecordInputChange();
|
|
||||||
void RecordScrollChange();
|
|
||||||
|
|
||||||
void Flush();
|
|
||||||
|
|
||||||
void Cancel();
|
|
||||||
|
|
||||||
private:
|
|
||||||
void Collect();
|
|
||||||
|
|
||||||
nsresult Apply(Maybe<sessionstore::FormData>&& aFormData,
|
|
||||||
Maybe<nsPoint>&& aScroll);
|
|
||||||
|
|
||||||
SessionStoreDataCollector(WindowGlobalChild* aWindowChild, uint32_t aEpoch);
|
|
||||||
~SessionStoreDataCollector();
|
|
||||||
|
|
||||||
RefPtr<WindowGlobalChild> mWindowChild;
|
|
||||||
nsCOMPtr<nsITimer> mTimer;
|
|
||||||
|
|
||||||
uint32_t mEpoch;
|
|
||||||
bool mInputChanged : 1;
|
|
||||||
bool mScrollChanged : 1;
|
|
||||||
};
|
|
||||||
|
|
||||||
} // namespace mozilla::dom
|
|
||||||
|
|
||||||
#endif // mozilla_dom_SessionStoreDataCollector_h
|
|
||||||
172
toolkit/components/sessionstore/SessionStoreFormData.cpp
Normal file
172
toolkit/components/sessionstore/SessionStoreFormData.cpp
Normal file
@@ -0,0 +1,172 @@
|
|||||||
|
/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
|
||||||
|
/* vim: set ts=8 sts=2 et sw=2 tw=80: */
|
||||||
|
/* This Source Code Form is subject to the terms of the Mozilla Public
|
||||||
|
* License, v. 2.0. If a copy of the MPL was not distributed with this
|
||||||
|
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
|
||||||
|
|
||||||
|
#include "mozilla/dom/SessionStoreFormData.h"
|
||||||
|
|
||||||
|
#include "mozilla/Assertions.h"
|
||||||
|
#include "mozilla/ScopeExit.h"
|
||||||
|
#include "mozilla/dom/BindingUtils.h"
|
||||||
|
#include "mozilla/dom/BrowserSessionStoreBinding.h"
|
||||||
|
#include "mozilla/dom/BrowsingContext.h"
|
||||||
|
#include "mozilla/dom/sessionstore/SessionStoreTypes.h"
|
||||||
|
|
||||||
|
#include "nsContentUtils.h"
|
||||||
|
#include "js/JSON.h"
|
||||||
|
|
||||||
|
using namespace mozilla::dom;
|
||||||
|
|
||||||
|
NS_IMPL_CYCLE_COLLECTING_ADDREF(SessionStoreFormData)
|
||||||
|
NS_IMPL_CYCLE_COLLECTING_RELEASE(SessionStoreFormData)
|
||||||
|
|
||||||
|
NS_IMPL_CYCLE_COLLECTION_WRAPPERCACHE_WEAK_PTR(SessionStoreFormData, mChildren)
|
||||||
|
|
||||||
|
NS_INTERFACE_MAP_BEGIN_CYCLE_COLLECTION(SessionStoreFormData)
|
||||||
|
NS_WRAPPERCACHE_INTERFACE_MAP_ENTRY
|
||||||
|
NS_INTERFACE_MAP_ENTRY(nsISupports)
|
||||||
|
NS_INTERFACE_MAP_END
|
||||||
|
|
||||||
|
nsISupports* SessionStoreFormData::GetParentObject() const {
|
||||||
|
return xpc::NativeGlobal(xpc::PrivilegedJunkScope());
|
||||||
|
}
|
||||||
|
|
||||||
|
JSObject* SessionStoreFormData::WrapObject(JSContext* aCx,
|
||||||
|
JS::Handle<JSObject*> aGivenProto) {
|
||||||
|
return SessionStoreFormData_Binding::Wrap(aCx, this, aGivenProto);
|
||||||
|
}
|
||||||
|
|
||||||
|
void SessionStoreFormData::GetUrl(nsACString& aUrl) const {
|
||||||
|
if (mUrl.IsEmpty()) {
|
||||||
|
aUrl.SetIsVoid(true);
|
||||||
|
} else {
|
||||||
|
aUrl = mUrl;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void SessionStoreFormData::GetId(
|
||||||
|
JSContext* aCx,
|
||||||
|
Nullable<Record<nsString, OwningStringOrBooleanOrObject>>& aId) {
|
||||||
|
if (mId.IsEmpty() ||
|
||||||
|
NS_FAILED(SessionStoreUtils::ConstructFormDataValues(
|
||||||
|
aCx, mId, aId.SetValue().Entries(), mParseSessionData))) {
|
||||||
|
aId.SetNull();
|
||||||
|
}
|
||||||
|
|
||||||
|
// SessionStoreFormData.id is now stored in a slot, so we can free our
|
||||||
|
// internal state.
|
||||||
|
mId.Clear();
|
||||||
|
}
|
||||||
|
|
||||||
|
void SessionStoreFormData::GetXpath(
|
||||||
|
JSContext* aCx,
|
||||||
|
Nullable<Record<nsString, OwningStringOrBooleanOrObject>>& aXpath) {
|
||||||
|
if (mXpath.IsEmpty() ||
|
||||||
|
NS_FAILED(SessionStoreUtils::ConstructFormDataValues(
|
||||||
|
aCx, mXpath, aXpath.SetValue().Entries(), mParseSessionData))) {
|
||||||
|
aXpath.SetNull();
|
||||||
|
}
|
||||||
|
|
||||||
|
// SessionStoreFormData.xpath is now stored in a slot, so we can free our
|
||||||
|
// internal state.
|
||||||
|
mXpath.Clear();
|
||||||
|
}
|
||||||
|
|
||||||
|
void SessionStoreFormData::GetInnerHTML(nsAString& aInnerHTML) {
|
||||||
|
if (mInnerHTML.IsEmpty()) {
|
||||||
|
SetDOMStringToNull(aInnerHTML);
|
||||||
|
} else {
|
||||||
|
aInnerHTML = mInnerHTML;
|
||||||
|
}
|
||||||
|
|
||||||
|
// SessionStoreFormData.innerHTML is now stored in a slot, so we can free our
|
||||||
|
// internal state.
|
||||||
|
mInnerHTML.SetIsVoid(true);
|
||||||
|
}
|
||||||
|
|
||||||
|
SessionStoreFormData::ChildrenArray& SessionStoreFormData::Children() {
|
||||||
|
return mChildren;
|
||||||
|
}
|
||||||
|
|
||||||
|
void SessionStoreFormData::GetChildren(
|
||||||
|
Nullable<ChildrenArray>& aChildren) const {
|
||||||
|
if (!mChildren.IsEmpty()) {
|
||||||
|
aChildren.SetValue() = mChildren.Clone();
|
||||||
|
} else {
|
||||||
|
aChildren.SetNull();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void SessionStoreFormData::ToJSON(JSContext* aCx,
|
||||||
|
JS::MutableHandleObject aRetval) {
|
||||||
|
JS::RootedObject self(aCx);
|
||||||
|
{
|
||||||
|
JS::RootedValue value(aCx);
|
||||||
|
if (!GetOrCreateDOMReflector(aCx, this, &value)) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
self.set(value.toObjectOrNull());
|
||||||
|
}
|
||||||
|
|
||||||
|
JS::Rooted<JSObject*> result(aCx, JS_NewPlainObject(aCx));
|
||||||
|
|
||||||
|
if (!IsEmpty()) {
|
||||||
|
for (const auto& name :
|
||||||
|
{u"url"_ns, u"id"_ns, u"xpath"_ns, u"innerHTML"_ns}) {
|
||||||
|
if (!SessionStoreUtils::CopyProperty(aCx, result, self, name)) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
SessionStoreUtils::CopyChildren(aCx, result, mChildren);
|
||||||
|
}
|
||||||
|
|
||||||
|
aRetval.set(result);
|
||||||
|
}
|
||||||
|
|
||||||
|
void SessionStoreFormData::Update(const CollectedType& aFormData) {
|
||||||
|
SessionStoreFormData_Binding::ClearCachedUrlValue(this);
|
||||||
|
SessionStoreFormData_Binding::ClearCachedIdValue(this);
|
||||||
|
SessionStoreFormData_Binding::ClearCachedXpathValue(this);
|
||||||
|
SessionStoreFormData_Binding::ClearCachedInnerHTMLValue(this);
|
||||||
|
|
||||||
|
if (!aFormData.hasData()) {
|
||||||
|
mParseSessionData = false;
|
||||||
|
mHasData = false;
|
||||||
|
mUrl = ""_ns;
|
||||||
|
mId.Clear();
|
||||||
|
mXpath.Clear();
|
||||||
|
mInnerHTML = u""_ns;
|
||||||
|
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
mHasData = true;
|
||||||
|
|
||||||
|
mUrl = aFormData.uri();
|
||||||
|
// We want to avoid saving data for about:sessionrestore as a string.
|
||||||
|
// Since it's stored in the form as stringified JSON, stringifying
|
||||||
|
// further causes an explosion of escape characters. cf. bug 467409
|
||||||
|
mParseSessionData =
|
||||||
|
mUrl == "about:sessionrestore"_ns || mUrl == "about:welcomeback"_ns;
|
||||||
|
|
||||||
|
mInnerHTML = aFormData.innerHTML();
|
||||||
|
|
||||||
|
mId.Assign(aFormData.id());
|
||||||
|
mXpath.Assign(aFormData.xpath());
|
||||||
|
}
|
||||||
|
|
||||||
|
void SessionStoreFormData::ClearCachedChildren() {
|
||||||
|
SessionStoreFormData_Binding::ClearCachedChildrenValue(this);
|
||||||
|
}
|
||||||
|
|
||||||
|
/* static */ bool SessionStoreFormData::HasData(
|
||||||
|
const CollectedType& aFormData) {
|
||||||
|
return aFormData.hasData();
|
||||||
|
}
|
||||||
|
|
||||||
|
bool SessionStoreFormData::IsEmpty() const {
|
||||||
|
return !mHasData && mChildren.IsEmpty();
|
||||||
|
}
|
||||||
83
toolkit/components/sessionstore/SessionStoreFormData.h
Normal file
83
toolkit/components/sessionstore/SessionStoreFormData.h
Normal file
@@ -0,0 +1,83 @@
|
|||||||
|
/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
|
||||||
|
/* vim: set ts=8 sts=2 et sw=2 tw=80: */
|
||||||
|
/* This Source Code Form is subject to the terms of the Mozilla Public
|
||||||
|
* License, v. 2.0. If a copy of the MPL was not distributed with this
|
||||||
|
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
|
||||||
|
|
||||||
|
#ifndef mozilla_dom_SessionStoreFormData_h
|
||||||
|
#define mozilla_dom_SessionStoreFormData_h
|
||||||
|
|
||||||
|
#include "mozilla/WeakPtr.h"
|
||||||
|
#include "mozilla/dom/UnionTypes.h"
|
||||||
|
#include "mozilla/dom/WindowGlobalParent.h"
|
||||||
|
|
||||||
|
#include "nsTArrayForwardDeclare.h"
|
||||||
|
#include "nsWrapperCache.h"
|
||||||
|
|
||||||
|
class nsIGlobalObject;
|
||||||
|
|
||||||
|
namespace mozilla::dom {
|
||||||
|
|
||||||
|
namespace sessionstore {
|
||||||
|
class FormData;
|
||||||
|
}
|
||||||
|
|
||||||
|
class BrowsingContext;
|
||||||
|
class OwningByteStringOrObjectOrNull;
|
||||||
|
class OwningStringOrObjectOrNull;
|
||||||
|
class WindowGlobalParent;
|
||||||
|
|
||||||
|
class SessionStoreFormData final : public nsISupports,
|
||||||
|
public nsWrapperCache,
|
||||||
|
public SupportsWeakPtr {
|
||||||
|
public:
|
||||||
|
using CollectedType = sessionstore::FormData;
|
||||||
|
using LocationType = WeakPtr<SessionStoreFormData>;
|
||||||
|
using ChildrenArray = nsTArray<RefPtr<SessionStoreFormData>>;
|
||||||
|
|
||||||
|
NS_DECL_CYCLE_COLLECTING_ISUPPORTS
|
||||||
|
NS_DECL_CYCLE_COLLECTION_SCRIPT_HOLDER_CLASS(SessionStoreFormData)
|
||||||
|
nsISupports* GetParentObject() const;
|
||||||
|
JSObject* WrapObject(JSContext* aCx,
|
||||||
|
JS::Handle<JSObject*> aGivenProto) override;
|
||||||
|
|
||||||
|
void GetUrl(nsACString& aUrl) const;
|
||||||
|
|
||||||
|
void GetId(JSContext* aCx,
|
||||||
|
Nullable<Record<nsString, OwningStringOrBooleanOrObject>>& aId);
|
||||||
|
|
||||||
|
void GetXpath(
|
||||||
|
JSContext* aCx,
|
||||||
|
Nullable<Record<nsString, OwningStringOrBooleanOrObject>>& aXpath);
|
||||||
|
|
||||||
|
void GetInnerHTML(nsAString& aInnerHTML);
|
||||||
|
|
||||||
|
ChildrenArray& Children();
|
||||||
|
|
||||||
|
void GetChildren(Nullable<ChildrenArray>& aChildren) const;
|
||||||
|
|
||||||
|
void ToJSON(JSContext* aCx, JS::MutableHandleObject aRetval);
|
||||||
|
|
||||||
|
void Update(const CollectedType& aFormData);
|
||||||
|
|
||||||
|
void ClearCachedChildren();
|
||||||
|
|
||||||
|
static bool HasData(const CollectedType& aFormData);
|
||||||
|
|
||||||
|
bool IsEmpty() const;
|
||||||
|
|
||||||
|
private:
|
||||||
|
~SessionStoreFormData() = default;
|
||||||
|
|
||||||
|
bool mParseSessionData = false;
|
||||||
|
bool mHasData = false;
|
||||||
|
nsCString mUrl;
|
||||||
|
nsTArray<sessionstore::FormEntry> mId;
|
||||||
|
nsTArray<sessionstore::FormEntry> mXpath;
|
||||||
|
nsString mInnerHTML;
|
||||||
|
ChildrenArray mChildren;
|
||||||
|
};
|
||||||
|
|
||||||
|
} // namespace mozilla::dom
|
||||||
|
|
||||||
|
#endif // mozilla_dom_SessionStoreFormData_h
|
||||||
@@ -17,10 +17,6 @@ interface nsISessionStoreFunctions : nsISupports {
|
|||||||
in jsval aPermanentKey, in uint32_t aEpoch, in boolean aCollectSHistory,
|
in jsval aPermanentKey, in uint32_t aEpoch, in boolean aCollectSHistory,
|
||||||
in jsval aData);
|
in jsval aData);
|
||||||
|
|
||||||
void UpdateSessionStoreForWindow(
|
|
||||||
in Element aBrowser, in BrowsingContext aBrowsingContext,
|
|
||||||
in jsval aPermanentKey, in uint32_t aEpoch, in jsval aData);
|
|
||||||
|
|
||||||
void UpdateSessionStoreForStorage(
|
void UpdateSessionStoreForStorage(
|
||||||
in Element aBrowser, in BrowsingContext aBrowsingContext,
|
in Element aBrowser, in BrowsingContext aBrowsingContext,
|
||||||
in jsval aPermanentKey, in uint32_t aEpoch, in jsval aData);
|
in jsval aPermanentKey, in uint32_t aEpoch, in jsval aData);
|
||||||
|
|||||||
@@ -28,22 +28,6 @@ function UpdateSessionStore(
|
|||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
function UpdateSessionStoreForWindow(
|
|
||||||
aBrowser,
|
|
||||||
aBrowsingContext,
|
|
||||||
aPermanentKey,
|
|
||||||
aEpoch,
|
|
||||||
aData
|
|
||||||
) {
|
|
||||||
return SessionStoreFuncInternal.updateSessionStoreForWindow(
|
|
||||||
aBrowser,
|
|
||||||
aBrowsingContext,
|
|
||||||
aPermanentKey,
|
|
||||||
aEpoch,
|
|
||||||
aData
|
|
||||||
);
|
|
||||||
}
|
|
||||||
|
|
||||||
function UpdateSessionStoreForStorage(
|
function UpdateSessionStoreForStorage(
|
||||||
aBrowser,
|
aBrowser,
|
||||||
aBrowsingContext,
|
aBrowsingContext,
|
||||||
@@ -60,11 +44,7 @@ function UpdateSessionStoreForStorage(
|
|||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
var EXPORTED_SYMBOLS = [
|
var EXPORTED_SYMBOLS = ["UpdateSessionStore", "UpdateSessionStoreForStorage"];
|
||||||
"UpdateSessionStore",
|
|
||||||
"UpdateSessionStoreForWindow",
|
|
||||||
"UpdateSessionStoreForStorage",
|
|
||||||
];
|
|
||||||
|
|
||||||
var SessionStoreFuncInternal = {
|
var SessionStoreFuncInternal = {
|
||||||
updateSessionStore: function SSF_updateSessionStore(
|
updateSessionStore: function SSF_updateSessionStore(
|
||||||
@@ -75,12 +55,14 @@ var SessionStoreFuncInternal = {
|
|||||||
aCollectSHistory,
|
aCollectSHistory,
|
||||||
aData
|
aData
|
||||||
) {
|
) {
|
||||||
let currentData = {};
|
let { formdata, scroll } = aData;
|
||||||
if (aData.docShellCaps != undefined) {
|
|
||||||
currentData.disallow = aData.docShellCaps ? aData.docShellCaps : null;
|
if (formdata) {
|
||||||
|
aData.formdata = formdata.toJSON();
|
||||||
}
|
}
|
||||||
if (aData.isPrivate != undefined) {
|
|
||||||
currentData.isPrivate = aData.isPrivate;
|
if (scroll) {
|
||||||
|
aData.scroll = scroll.toJSON();
|
||||||
}
|
}
|
||||||
|
|
||||||
SessionStore.updateSessionStoreFromTablistener(
|
SessionStore.updateSessionStoreFromTablistener(
|
||||||
@@ -88,28 +70,13 @@ var SessionStoreFuncInternal = {
|
|||||||
aBrowsingContext,
|
aBrowsingContext,
|
||||||
aPermanentKey,
|
aPermanentKey,
|
||||||
{
|
{
|
||||||
data: currentData,
|
data: aData,
|
||||||
epoch: aEpoch,
|
epoch: aEpoch,
|
||||||
sHistoryNeeded: aCollectSHistory,
|
sHistoryNeeded: aCollectSHistory,
|
||||||
}
|
}
|
||||||
);
|
);
|
||||||
},
|
},
|
||||||
|
|
||||||
updateSessionStoreForWindow: function SSF_updateSessionStoreForWindow(
|
|
||||||
aBrowser,
|
|
||||||
aBrowsingContext,
|
|
||||||
aPermanentKey,
|
|
||||||
aEpoch,
|
|
||||||
aData
|
|
||||||
) {
|
|
||||||
SessionStore.updateSessionStoreFromTablistener(
|
|
||||||
aBrowser,
|
|
||||||
aBrowsingContext,
|
|
||||||
aPermanentKey,
|
|
||||||
{ data: { windowstatechange: aData }, epoch: aEpoch }
|
|
||||||
);
|
|
||||||
},
|
|
||||||
|
|
||||||
updateSessionStoreForStorage: function SSF_updateSessionStoreForWindow(
|
updateSessionStoreForStorage: function SSF_updateSessionStoreForWindow(
|
||||||
aBrowser,
|
aBrowser,
|
||||||
aBrowsingContext,
|
aBrowsingContext,
|
||||||
|
|||||||
@@ -3,6 +3,7 @@
|
|||||||
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
|
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
|
||||||
|
|
||||||
#include "mozilla/PresShell.h"
|
#include "mozilla/PresShell.h"
|
||||||
|
#include "mozilla/dom/BrowserSessionStoreBinding.h"
|
||||||
#include "mozilla/dom/Document.h"
|
#include "mozilla/dom/Document.h"
|
||||||
#include "mozilla/dom/SessionStoreListener.h"
|
#include "mozilla/dom/SessionStoreListener.h"
|
||||||
#include "mozilla/dom/SessionStoreUtils.h"
|
#include "mozilla/dom/SessionStoreUtils.h"
|
||||||
@@ -384,20 +385,21 @@ nsresult TabListener::Observe(nsISupports* aSubject, const char* aTopic,
|
|||||||
return NS_ERROR_UNEXPECTED;
|
return NS_ERROR_UNEXPECTED;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool TabListener::ForceFlushFromParent() {
|
void TabListener::ForceFlushFromParent() {
|
||||||
if (!XRE_IsParentProcess()) {
|
if (!XRE_IsParentProcess()) {
|
||||||
return false;
|
return;
|
||||||
}
|
}
|
||||||
if (!mSessionStore) {
|
if (!mSessionStore) {
|
||||||
return false;
|
return;
|
||||||
}
|
}
|
||||||
return UpdateSessionStore(true);
|
|
||||||
|
UpdateSessionStore(true);
|
||||||
}
|
}
|
||||||
|
|
||||||
bool TabListener::UpdateSessionStore(bool aIsFlush) {
|
void TabListener::UpdateSessionStore(bool aIsFlush) {
|
||||||
if (!aIsFlush) {
|
if (!aIsFlush) {
|
||||||
if (!mSessionStore || !mSessionStore->UpdateNeeded()) {
|
if (!mSessionStore || !mSessionStore->UpdateNeeded()) {
|
||||||
return false;
|
return;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -405,33 +407,33 @@ bool TabListener::UpdateSessionStore(bool aIsFlush) {
|
|||||||
BrowserChild* browserChild = BrowserChild::GetFrom(mDocShell);
|
BrowserChild* browserChild = BrowserChild::GetFrom(mDocShell);
|
||||||
if (browserChild) {
|
if (browserChild) {
|
||||||
StopTimerForUpdate();
|
StopTimerForUpdate();
|
||||||
return browserChild->UpdateSessionStore();
|
browserChild->UpdateSessionStore();
|
||||||
}
|
}
|
||||||
return false;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
BrowsingContext* context = mDocShell->GetBrowsingContext();
|
BrowsingContext* context = mDocShell->GetBrowsingContext();
|
||||||
if (!context) {
|
if (!context) {
|
||||||
return false;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
uint32_t chromeFlags = 0;
|
uint32_t chromeFlags = 0;
|
||||||
nsCOMPtr<nsIDocShellTreeOwner> treeOwner;
|
nsCOMPtr<nsIDocShellTreeOwner> treeOwner;
|
||||||
mDocShell->GetTreeOwner(getter_AddRefs(treeOwner));
|
mDocShell->GetTreeOwner(getter_AddRefs(treeOwner));
|
||||||
if (!treeOwner) {
|
if (!treeOwner) {
|
||||||
return false;
|
return;
|
||||||
}
|
}
|
||||||
nsCOMPtr<nsIAppWindow> window(do_GetInterface(treeOwner));
|
nsCOMPtr<nsIAppWindow> window(do_GetInterface(treeOwner));
|
||||||
if (!window) {
|
if (!window) {
|
||||||
return false;
|
return;
|
||||||
}
|
}
|
||||||
if (window && NS_FAILED(window->GetChromeFlags(&chromeFlags))) {
|
if (window && NS_FAILED(window->GetChromeFlags(&chromeFlags))) {
|
||||||
return false;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
UpdateSessionStoreData data;
|
UpdateSessionStoreData data;
|
||||||
if (mSessionStore->IsDocCapChanged()) {
|
if (mSessionStore->IsDocCapChanged()) {
|
||||||
data.mDocShellCaps.Construct() = mSessionStore->GetDocShellCaps();
|
data.mDisallow.Construct() = mSessionStore->GetDocShellCaps();
|
||||||
}
|
}
|
||||||
if (mSessionStore->IsPrivateChanged()) {
|
if (mSessionStore->IsPrivateChanged()) {
|
||||||
data.mIsPrivate.Construct() = mSessionStore->GetPrivateModeEnabled();
|
data.mIsPrivate.Construct() = mSessionStore->GetPrivateModeEnabled();
|
||||||
@@ -440,16 +442,18 @@ bool TabListener::UpdateSessionStore(bool aIsFlush) {
|
|||||||
nsCOMPtr<nsISessionStoreFunctions> funcs = do_ImportModule(
|
nsCOMPtr<nsISessionStoreFunctions> funcs = do_ImportModule(
|
||||||
"resource://gre/modules/SessionStoreFunctions.jsm", fallible);
|
"resource://gre/modules/SessionStoreFunctions.jsm", fallible);
|
||||||
nsCOMPtr<nsIXPConnectWrappedJS> wrapped = do_QueryInterface(funcs);
|
nsCOMPtr<nsIXPConnectWrappedJS> wrapped = do_QueryInterface(funcs);
|
||||||
NS_ENSURE_TRUE(wrapped, false);
|
if (!wrapped) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
AutoJSAPI jsapi;
|
AutoJSAPI jsapi;
|
||||||
if (!jsapi.Init(wrapped->GetJSObjectGlobal())) {
|
if (!jsapi.Init(wrapped->GetJSObjectGlobal())) {
|
||||||
return false;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
JS::Rooted<JS::Value> update(jsapi.cx());
|
JS::Rooted<JS::Value> update(jsapi.cx());
|
||||||
if (!ToJSValue(jsapi.cx(), data, &update)) {
|
if (!ToJSValue(jsapi.cx(), data, &update)) {
|
||||||
return false;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
JS::RootedValue key(jsapi.cx(), context->Canonical()->Top()->PermanentKey());
|
JS::RootedValue key(jsapi.cx(), context->Canonical()->Top()->PermanentKey());
|
||||||
@@ -458,11 +462,10 @@ bool TabListener::UpdateSessionStore(bool aIsFlush) {
|
|||||||
mOwnerContent, context, key, mEpoch,
|
mOwnerContent, context, key, mEpoch,
|
||||||
mSessionStore->GetAndClearSHistoryChanged(), update);
|
mSessionStore->GetAndClearSHistoryChanged(), update);
|
||||||
if (NS_FAILED(rv)) {
|
if (NS_FAILED(rv)) {
|
||||||
return false;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
StopTimerForUpdate();
|
StopTimerForUpdate();
|
||||||
return true;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void TabListener::RemoveListeners() {
|
void TabListener::RemoveListeners() {
|
||||||
|
|||||||
@@ -73,7 +73,7 @@ class TabListener : public nsIDOMEventListener,
|
|||||||
nsresult Init();
|
nsresult Init();
|
||||||
ContentSessionStore* GetSessionStore() { return mSessionStore; }
|
ContentSessionStore* GetSessionStore() { return mSessionStore; }
|
||||||
// the function is called only when TabListener is in parent process
|
// the function is called only when TabListener is in parent process
|
||||||
bool ForceFlushFromParent();
|
void ForceFlushFromParent();
|
||||||
void RemoveListeners();
|
void RemoveListeners();
|
||||||
void SetEpoch(uint32_t aEpoch) { mEpoch = aEpoch; }
|
void SetEpoch(uint32_t aEpoch) { mEpoch = aEpoch; }
|
||||||
uint32_t GetEpoch() { return mEpoch; }
|
uint32_t GetEpoch() { return mEpoch; }
|
||||||
@@ -94,7 +94,7 @@ class TabListener : public nsIDOMEventListener,
|
|||||||
void StopTimerForUpdate();
|
void StopTimerForUpdate();
|
||||||
void AddEventListeners();
|
void AddEventListeners();
|
||||||
void RemoveEventListeners();
|
void RemoveEventListeners();
|
||||||
bool UpdateSessionStore(bool aIsFlush = false);
|
void UpdateSessionStore(bool aIsFlush = false);
|
||||||
virtual ~TabListener();
|
virtual ~TabListener();
|
||||||
|
|
||||||
nsCOMPtr<nsIDocShell> mDocShell;
|
nsCOMPtr<nsIDocShell> mDocShell;
|
||||||
|
|||||||
@@ -6,6 +6,7 @@
|
|||||||
#define mozilla_dom_SessionStoreMessageUtils_h
|
#define mozilla_dom_SessionStoreMessageUtils_h
|
||||||
|
|
||||||
#include "ipc/IPCMessageUtils.h"
|
#include "ipc/IPCMessageUtils.h"
|
||||||
|
#include "mozilla/ipc/IPDLParamTraits.h"
|
||||||
#include "SessionStoreData.h"
|
#include "SessionStoreData.h"
|
||||||
#include "SessionStoreUtils.h"
|
#include "SessionStoreUtils.h"
|
||||||
#include "SessionStoreRestoreData.h"
|
#include "SessionStoreRestoreData.h"
|
||||||
|
|||||||
194
toolkit/components/sessionstore/SessionStoreParent.cpp
Normal file
194
toolkit/components/sessionstore/SessionStoreParent.cpp
Normal file
@@ -0,0 +1,194 @@
|
|||||||
|
/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
|
||||||
|
/* vim: set ts=8 sts=2 et sw=2 tw=80: */
|
||||||
|
/* This Source Code Form is subject to the terms of the Mozilla Public
|
||||||
|
* License, v. 2.0. If a copy of the MPL was not distributed with this
|
||||||
|
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
|
||||||
|
|
||||||
|
#include "mozilla/dom/SessionStoreParent.h"
|
||||||
|
|
||||||
|
#include "mozilla/AlreadyAddRefed.h"
|
||||||
|
#include "mozilla/Assertions.h"
|
||||||
|
#include "mozilla/Maybe.h"
|
||||||
|
#include "mozilla/RefPtr.h"
|
||||||
|
#include "mozilla/ScopeExit.h"
|
||||||
|
#include "mozilla/dom/BrowserParent.h"
|
||||||
|
#include "mozilla/dom/BrowserSessionStore.h"
|
||||||
|
#include "mozilla/dom/BrowserSessionStoreBinding.h"
|
||||||
|
#include "mozilla/dom/BrowsingContext.h"
|
||||||
|
#include "mozilla/dom/InProcessChild.h"
|
||||||
|
#include "mozilla/dom/InProcessParent.h"
|
||||||
|
#include "mozilla/dom/SessionStoreChild.h"
|
||||||
|
#include "mozilla/dom/SessionStoreUtilsBinding.h"
|
||||||
|
#include "SessionStoreFunctions.h"
|
||||||
|
#include "nsISupports.h"
|
||||||
|
#include "nsIXULRuntime.h"
|
||||||
|
#include "nsImportModule.h"
|
||||||
|
#include "nsIXPConnect.h"
|
||||||
|
|
||||||
|
using namespace mozilla;
|
||||||
|
using namespace mozilla::dom;
|
||||||
|
|
||||||
|
SessionStoreParent::SessionStoreParent(
|
||||||
|
CanonicalBrowsingContext* aBrowsingContext,
|
||||||
|
BrowserSessionStore* aSessionStore)
|
||||||
|
: mBrowsingContext(aBrowsingContext), mSessionStore(aSessionStore) {}
|
||||||
|
|
||||||
|
static void SessionStoreUpdate(CanonicalBrowsingContext* aBrowsingContext,
|
||||||
|
const Maybe<nsCString>& aDocShellCaps,
|
||||||
|
const Maybe<bool>& aPrivatedMode,
|
||||||
|
bool aNeedCollectSHistory, uint32_t aEpoch) {
|
||||||
|
UpdateSessionStoreData data;
|
||||||
|
if (aDocShellCaps.isSome()) {
|
||||||
|
auto& disallow = data.mDisallow.Construct();
|
||||||
|
if (!aDocShellCaps->IsEmpty()) {
|
||||||
|
disallow = aDocShellCaps.value();
|
||||||
|
} else {
|
||||||
|
disallow.SetIsVoid(true);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (aPrivatedMode.isSome()) {
|
||||||
|
data.mIsPrivate.Construct() = aPrivatedMode.value();
|
||||||
|
}
|
||||||
|
|
||||||
|
RefPtr<BrowserSessionStore> sessionStore =
|
||||||
|
BrowserSessionStore::GetOrCreate(aBrowsingContext->Top());
|
||||||
|
|
||||||
|
SessionStoreFormData* formData = sessionStore->GetFormdata();
|
||||||
|
data.mFormdata.Construct(formData);
|
||||||
|
|
||||||
|
SessionStoreScrollData* scroll = sessionStore->GetScroll();
|
||||||
|
data.mScroll.Construct(scroll);
|
||||||
|
|
||||||
|
nsCOMPtr<nsISessionStoreFunctions> funcs = do_ImportModule(
|
||||||
|
"resource://gre/modules/SessionStoreFunctions.jsm", fallible);
|
||||||
|
nsCOMPtr<nsIXPConnectWrappedJS> wrapped = do_QueryInterface(funcs);
|
||||||
|
if (!wrapped) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
AutoJSAPI jsapi;
|
||||||
|
if (!jsapi.Init(wrapped->GetJSObjectGlobal())) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
JS::Rooted<JS::Value> update(jsapi.cx());
|
||||||
|
if (!ToJSValue(jsapi.cx(), data, &update)) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
JS::RootedValue key(jsapi.cx(), aBrowsingContext->Top()->PermanentKey());
|
||||||
|
|
||||||
|
Unused << funcs->UpdateSessionStore(nullptr, aBrowsingContext, key, aEpoch,
|
||||||
|
aNeedCollectSHistory, update);
|
||||||
|
}
|
||||||
|
|
||||||
|
void SessionStoreParent::FlushAllSessionStoreChildren(
|
||||||
|
const std::function<void()>& aDone) {
|
||||||
|
if (!mBrowsingContext) {
|
||||||
|
aDone();
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
nsTArray<RefPtr<SessionStoreParent::FlushTabStatePromise>> flushPromises;
|
||||||
|
|
||||||
|
// We're special casing this for when the SessionStore{Child, Parent} have
|
||||||
|
// been created in the same process. This is only ever true for the parent
|
||||||
|
// process session store actor, and is needed because
|
||||||
|
// nsFrameLoader::RequestTabStateFlush expect flushes to happen faster than we
|
||||||
|
// can manage by using the common path of sending a message the
|
||||||
|
// SessionStoreChild. Ideally we should be able to do just that, but not
|
||||||
|
// without more work.
|
||||||
|
if (InProcessParent::ChildActorFor(this)) {
|
||||||
|
// Here we assume that the session store data collection only collect for in
|
||||||
|
// (parent-)process content type browsing contexts, which we only flush one
|
||||||
|
// session store actor.
|
||||||
|
flushPromises.AppendElement(FlushSessionStore());
|
||||||
|
} else {
|
||||||
|
// While here we flush all participating actors.
|
||||||
|
BrowserParent* browserParent = static_cast<BrowserParent*>(Manager());
|
||||||
|
browserParent->VisitAll([&flushPromises](BrowserParent* aBrowser) {
|
||||||
|
if (PSessionStoreParent* sessionStoreParent =
|
||||||
|
SingleManagedOrNull(aBrowser->ManagedPSessionStoreParent())) {
|
||||||
|
flushPromises.AppendElement(
|
||||||
|
static_cast<SessionStoreParent*>(sessionStoreParent)
|
||||||
|
->FlushSessionStore());
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
RefPtr<SessionStoreParent::FlushTabStatePromise::AllPromiseType>
|
||||||
|
flushPromise = SessionStoreParent::FlushTabStatePromise::All(
|
||||||
|
GetMainThreadSerialEventTarget(), flushPromises);
|
||||||
|
|
||||||
|
mBrowsingContext->UpdateSessionStoreSessionStorage([aDone, flushPromise]() {
|
||||||
|
flushPromise->Then(GetCurrentSerialEventTarget(), __func__,
|
||||||
|
[aDone]() { aDone(); });
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
already_AddRefed<SessionStoreParent::FlushTabStatePromise>
|
||||||
|
SessionStoreParent::FlushSessionStore() {
|
||||||
|
if (!mBrowsingContext) {
|
||||||
|
return nullptr;
|
||||||
|
}
|
||||||
|
|
||||||
|
RefPtr<SessionStoreParent::FlushTabStatePromise> promise =
|
||||||
|
SendFlushTabState();
|
||||||
|
return promise.forget();
|
||||||
|
}
|
||||||
|
|
||||||
|
void SessionStoreParent::FinalFlushAllSessionStoreChildren(
|
||||||
|
const std::function<void()>& aDone) {
|
||||||
|
if (!mBrowsingContext) {
|
||||||
|
aDone();
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
SessionStoreChild* sessionStoreChild =
|
||||||
|
static_cast<SessionStoreChild*>(InProcessParent::ChildActorFor(this));
|
||||||
|
if (!sessionStoreChild || mozilla::SessionHistoryInParent()) {
|
||||||
|
return FlushAllSessionStoreChildren(aDone);
|
||||||
|
}
|
||||||
|
|
||||||
|
sessionStoreChild->FlushSessionStore();
|
||||||
|
mBrowsingContext->UpdateSessionStoreSessionStorage(aDone);
|
||||||
|
}
|
||||||
|
|
||||||
|
mozilla::ipc::IPCResult SessionStoreParent::RecvSessionStoreUpdate(
|
||||||
|
const Maybe<nsCString>& aDocShellCaps, const Maybe<bool>& aPrivatedMode,
|
||||||
|
const bool aNeedCollectSHistory, const uint32_t& aEpoch) {
|
||||||
|
if (!mBrowsingContext) {
|
||||||
|
return IPC_OK();
|
||||||
|
}
|
||||||
|
|
||||||
|
SessionStoreUpdate(mBrowsingContext, aDocShellCaps, aPrivatedMode,
|
||||||
|
aNeedCollectSHistory, aEpoch);
|
||||||
|
return IPC_OK();
|
||||||
|
}
|
||||||
|
|
||||||
|
mozilla::ipc::IPCResult SessionStoreParent::RecvIncrementalSessionStoreUpdate(
|
||||||
|
const MaybeDiscarded<BrowsingContext>& aBrowsingContext,
|
||||||
|
const Maybe<FormData>& aFormData, const Maybe<nsPoint>& aScrollPosition,
|
||||||
|
uint32_t aEpoch) {
|
||||||
|
if (!aBrowsingContext.IsNull()) {
|
||||||
|
mSessionStore->UpdateSessionStore(
|
||||||
|
aBrowsingContext.GetMaybeDiscarded()->Canonical(), aFormData,
|
||||||
|
aScrollPosition, aEpoch);
|
||||||
|
}
|
||||||
|
|
||||||
|
return IPC_OK();
|
||||||
|
}
|
||||||
|
|
||||||
|
mozilla::ipc::IPCResult SessionStoreParent::RecvResetSessionStore(
|
||||||
|
const MaybeDiscarded<BrowsingContext>& aBrowsingContext, uint32_t aEpoch) {
|
||||||
|
if (!aBrowsingContext.IsNull()) {
|
||||||
|
mSessionStore->RemoveSessionStore(
|
||||||
|
aBrowsingContext.GetMaybeDiscarded()->Canonical());
|
||||||
|
}
|
||||||
|
return IPC_OK();
|
||||||
|
}
|
||||||
|
|
||||||
|
NS_IMPL_CYCLE_COLLECTION(SessionStoreParent, mBrowsingContext, mSessionStore)
|
||||||
|
NS_IMPL_CYCLE_COLLECTION_ROOT_NATIVE(SessionStoreParent, AddRef)
|
||||||
|
NS_IMPL_CYCLE_COLLECTION_UNROOT_NATIVE(SessionStoreParent, Release)
|
||||||
58
toolkit/components/sessionstore/SessionStoreParent.h
Normal file
58
toolkit/components/sessionstore/SessionStoreParent.h
Normal file
@@ -0,0 +1,58 @@
|
|||||||
|
/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
|
||||||
|
/* vim: set ts=8 sts=2 et sw=2 tw=80: */
|
||||||
|
/* This Source Code Form is subject to the terms of the Mozilla Public
|
||||||
|
* License, v. 2.0. If a copy of the MPL was not distributed with this
|
||||||
|
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
|
||||||
|
|
||||||
|
#ifndef mozilla_dom_SessionStoreParent_h
|
||||||
|
#define mozilla_dom_SessionStoreParent_h
|
||||||
|
|
||||||
|
#include "mozilla/dom/BrowserSessionStore.h"
|
||||||
|
#include "mozilla/dom/CanonicalBrowsingContext.h"
|
||||||
|
#include "mozilla/dom/Element.h"
|
||||||
|
#include "mozilla/dom/PSessionStoreParent.h"
|
||||||
|
#include "mozilla/dom/WindowGlobalParent.h"
|
||||||
|
|
||||||
|
namespace mozilla::dom {
|
||||||
|
class BrowserParent;
|
||||||
|
|
||||||
|
class SessionStoreParent final : public PSessionStoreParent {
|
||||||
|
public:
|
||||||
|
SessionStoreParent(CanonicalBrowsingContext* aBrowsingContext,
|
||||||
|
BrowserSessionStore* aSessionStore);
|
||||||
|
|
||||||
|
void FlushAllSessionStoreChildren(const std::function<void()>& aDone);
|
||||||
|
|
||||||
|
void FinalFlushAllSessionStoreChildren(const std::function<void()>& aDone);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Sends data to be stored and instructions to the session store to
|
||||||
|
* potentially collect data in the parent.
|
||||||
|
*/
|
||||||
|
mozilla::ipc::IPCResult RecvSessionStoreUpdate(
|
||||||
|
const Maybe<nsCString>& aDocShellCaps, const Maybe<bool>& aPrivatedMode,
|
||||||
|
const bool aNeedCollectSHistory, const uint32_t& aEpoch);
|
||||||
|
|
||||||
|
mozilla::ipc::IPCResult RecvIncrementalSessionStoreUpdate(
|
||||||
|
const MaybeDiscarded<BrowsingContext>& aBrowsingContext,
|
||||||
|
const Maybe<FormData>& aFormData, const Maybe<nsPoint>& aScrollPosition,
|
||||||
|
uint32_t aEpoch);
|
||||||
|
|
||||||
|
mozilla::ipc::IPCResult RecvResetSessionStore(
|
||||||
|
const MaybeDiscarded<BrowsingContext>& aBrowsingContext, uint32_t aEpoch);
|
||||||
|
|
||||||
|
NS_INLINE_DECL_CYCLE_COLLECTING_NATIVE_REFCOUNTING(SessionStoreParent)
|
||||||
|
NS_DECL_CYCLE_COLLECTION_NATIVE_CLASS(SessionStoreParent)
|
||||||
|
|
||||||
|
private:
|
||||||
|
~SessionStoreParent() = default;
|
||||||
|
|
||||||
|
already_AddRefed<SessionStoreParent::FlushTabStatePromise>
|
||||||
|
FlushSessionStore();
|
||||||
|
|
||||||
|
RefPtr<CanonicalBrowsingContext> mBrowsingContext;
|
||||||
|
RefPtr<BrowserSessionStore> mSessionStore;
|
||||||
|
};
|
||||||
|
} // namespace mozilla::dom
|
||||||
|
|
||||||
|
#endif // mozilla_dom_SessionStoreParent_h
|
||||||
123
toolkit/components/sessionstore/SessionStoreScrollData.cpp
Normal file
123
toolkit/components/sessionstore/SessionStoreScrollData.cpp
Normal file
@@ -0,0 +1,123 @@
|
|||||||
|
/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
|
||||||
|
/* vim: set ts=8 sts=2 et sw=2 tw=80: */
|
||||||
|
/* This Source Code Form is subject to the terms of the Mozilla Public
|
||||||
|
* License, v. 2.0. If a copy of the MPL was not distributed with this
|
||||||
|
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
|
||||||
|
|
||||||
|
#include "mozilla/dom/SessionStoreScrollData.h"
|
||||||
|
#include <utility>
|
||||||
|
|
||||||
|
#include "js/PropertyAndElement.h"
|
||||||
|
#include "js/TypeDecls.h"
|
||||||
|
#include "mozilla/Assertions.h"
|
||||||
|
#include "mozilla/RefPtr.h"
|
||||||
|
#include "mozilla/dom/BindingUtils.h"
|
||||||
|
#include "mozilla/dom/BrowserSessionStoreBinding.h"
|
||||||
|
#include "mozilla/dom/BrowsingContext.h"
|
||||||
|
|
||||||
|
#include "nsPresContext.h"
|
||||||
|
|
||||||
|
#include "mozilla/dom/WebIDLGlobalNameHash.h"
|
||||||
|
#include "js/PropertyDescriptor.h"
|
||||||
|
|
||||||
|
#include "mozilla/dom/ToJSValue.h"
|
||||||
|
#include "mozilla/dom/GeneratedAtomList.h"
|
||||||
|
#include "js/StructuredClone.h"
|
||||||
|
#include "mozilla/dom/DOMJSClass.h"
|
||||||
|
#include "mozilla/dom/StructuredCloneHolder.h"
|
||||||
|
#include "nsContentUtils.h"
|
||||||
|
#include "js/Array.h"
|
||||||
|
#include "js/JSON.h"
|
||||||
|
|
||||||
|
using namespace mozilla::dom;
|
||||||
|
|
||||||
|
NS_IMPL_CYCLE_COLLECTING_ADDREF(SessionStoreScrollData)
|
||||||
|
NS_IMPL_CYCLE_COLLECTING_RELEASE(SessionStoreScrollData)
|
||||||
|
|
||||||
|
NS_IMPL_CYCLE_COLLECTION_WRAPPERCACHE_WEAK_PTR(SessionStoreScrollData,
|
||||||
|
mChildren)
|
||||||
|
NS_INTERFACE_MAP_BEGIN_CYCLE_COLLECTION(SessionStoreScrollData)
|
||||||
|
NS_WRAPPERCACHE_INTERFACE_MAP_ENTRY
|
||||||
|
NS_INTERFACE_MAP_ENTRY(nsISupports)
|
||||||
|
NS_INTERFACE_MAP_END
|
||||||
|
|
||||||
|
nsISupports* SessionStoreScrollData::GetParentObject() const {
|
||||||
|
return xpc::NativeGlobal(xpc::PrivilegedJunkScope());
|
||||||
|
;
|
||||||
|
}
|
||||||
|
|
||||||
|
JSObject* SessionStoreScrollData::WrapObject(
|
||||||
|
JSContext* aCx, JS::Handle<JSObject*> aGivenProto) {
|
||||||
|
return SessionStoreScrollData_Binding::Wrap(aCx, this, aGivenProto);
|
||||||
|
}
|
||||||
|
|
||||||
|
void SessionStoreScrollData::GetScroll(nsACString& aScroll) const {
|
||||||
|
int scrollX = nsPresContext::AppUnitsToIntCSSPixels(mScroll.x);
|
||||||
|
int scrollY = nsPresContext::AppUnitsToIntCSSPixels(mScroll.y);
|
||||||
|
|
||||||
|
if ((scrollX != 0) || (scrollY != 0)) {
|
||||||
|
aScroll = nsPrintfCString("%d,%d", scrollX, scrollY);
|
||||||
|
} else {
|
||||||
|
aScroll.SetIsVoid(true);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
SessionStoreScrollData::ChildrenArray& SessionStoreScrollData::Children() {
|
||||||
|
return mChildren;
|
||||||
|
}
|
||||||
|
|
||||||
|
void SessionStoreScrollData::GetChildren(
|
||||||
|
Nullable<ChildrenArray>& aChildren) const {
|
||||||
|
if (!mChildren.IsEmpty()) {
|
||||||
|
aChildren.SetValue() = mChildren.Clone();
|
||||||
|
} else {
|
||||||
|
aChildren.SetNull();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void SessionStoreScrollData::ToJSON(JSContext* aCx,
|
||||||
|
JS::MutableHandleObject aRetval) {
|
||||||
|
JS::RootedObject self(aCx);
|
||||||
|
{
|
||||||
|
JS::RootedValue value(aCx);
|
||||||
|
if (!GetOrCreateDOMReflector(aCx, this, &value)) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
self.set(value.toObjectOrNull());
|
||||||
|
}
|
||||||
|
|
||||||
|
JS::RootedObject result(aCx, JS_NewPlainObject(aCx));
|
||||||
|
|
||||||
|
if (!IsEmpty()) {
|
||||||
|
if (HasData(mScroll)) {
|
||||||
|
if (!SessionStoreUtils::CopyProperty(aCx, result, self, u"scroll"_ns)) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
SessionStoreUtils::CopyChildren(aCx, result, mChildren);
|
||||||
|
}
|
||||||
|
|
||||||
|
aRetval.set(result);
|
||||||
|
}
|
||||||
|
|
||||||
|
void SessionStoreScrollData::Update(const CollectedType& aUpdate) {
|
||||||
|
SessionStoreScrollData_Binding::ClearCachedScrollValue(this);
|
||||||
|
mScroll = aUpdate;
|
||||||
|
}
|
||||||
|
|
||||||
|
void SessionStoreScrollData::ClearCachedChildren() {
|
||||||
|
SessionStoreScrollData_Binding::ClearCachedChildrenValue(this);
|
||||||
|
}
|
||||||
|
|
||||||
|
/* static */
|
||||||
|
bool SessionStoreScrollData::HasData(const CollectedType& aPoint) {
|
||||||
|
int scrollX = nsPresContext::AppUnitsToIntCSSPixels(aPoint.x);
|
||||||
|
int scrollY = nsPresContext::AppUnitsToIntCSSPixels(aPoint.y);
|
||||||
|
return scrollX != 0 || scrollY != 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool SessionStoreScrollData::IsEmpty() const {
|
||||||
|
return !HasData(mScroll) && mChildren.IsEmpty();
|
||||||
|
}
|
||||||
61
toolkit/components/sessionstore/SessionStoreScrollData.h
Normal file
61
toolkit/components/sessionstore/SessionStoreScrollData.h
Normal file
@@ -0,0 +1,61 @@
|
|||||||
|
/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
|
||||||
|
/* vim: set ts=8 sts=2 et sw=2 tw=80: */
|
||||||
|
/* This Source Code Form is subject to the terms of the Mozilla Public
|
||||||
|
* License, v. 2.0. If a copy of the MPL was not distributed with this
|
||||||
|
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
|
||||||
|
|
||||||
|
#ifndef mozilla_dom_SessionStoreScrollData_h
|
||||||
|
#define mozilla_dom_SessionStoreScrollData_h
|
||||||
|
|
||||||
|
#include "mozilla/WeakPtr.h"
|
||||||
|
#include "nsPoint.h"
|
||||||
|
#include "nsTArray.h"
|
||||||
|
#include "nsWrapperCache.h"
|
||||||
|
#include "mozilla/dom/WindowGlobalParent.h"
|
||||||
|
|
||||||
|
namespace mozilla::dom {
|
||||||
|
|
||||||
|
class BrowsingContext;
|
||||||
|
class WindowGlobalParent;
|
||||||
|
class OwningByteStringOrObjectOrNull;
|
||||||
|
|
||||||
|
class SessionStoreScrollData final : public nsISupports,
|
||||||
|
public nsWrapperCache,
|
||||||
|
public SupportsWeakPtr {
|
||||||
|
public:
|
||||||
|
using CollectedType = nsPoint;
|
||||||
|
using LocationType = WeakPtr<SessionStoreScrollData>;
|
||||||
|
using ChildrenArray = nsTArray<RefPtr<SessionStoreScrollData>>;
|
||||||
|
|
||||||
|
NS_DECL_CYCLE_COLLECTING_ISUPPORTS
|
||||||
|
NS_DECL_CYCLE_COLLECTION_SCRIPT_HOLDER_CLASS(SessionStoreScrollData)
|
||||||
|
nsISupports* GetParentObject() const;
|
||||||
|
JSObject* WrapObject(JSContext* aCx,
|
||||||
|
JS::Handle<JSObject*> aGivenProto) override;
|
||||||
|
|
||||||
|
void GetScroll(nsACString& aScroll) const;
|
||||||
|
|
||||||
|
ChildrenArray& Children();
|
||||||
|
|
||||||
|
void GetChildren(Nullable<ChildrenArray>& aChildren) const;
|
||||||
|
|
||||||
|
void ToJSON(JSContext* aCx, JS::MutableHandleObject aRetval);
|
||||||
|
|
||||||
|
void Update(const CollectedType& aUpdate);
|
||||||
|
|
||||||
|
void ClearCachedChildren();
|
||||||
|
|
||||||
|
static bool HasData(const CollectedType& aPoint);
|
||||||
|
|
||||||
|
bool IsEmpty() const;
|
||||||
|
|
||||||
|
private:
|
||||||
|
~SessionStoreScrollData() = default;
|
||||||
|
|
||||||
|
nsPoint mScroll;
|
||||||
|
nsTArray<RefPtr<SessionStoreScrollData>> mChildren;
|
||||||
|
};
|
||||||
|
|
||||||
|
} // namespace mozilla::dom
|
||||||
|
|
||||||
|
#endif // mozilla_dom_SessionStoreScrollData_h
|
||||||
@@ -52,6 +52,7 @@ struct FormData {
|
|||||||
FormEntry[] id;
|
FormEntry[] id;
|
||||||
FormEntry[] xpath;
|
FormEntry[] xpath;
|
||||||
nsString innerHTML;
|
nsString innerHTML;
|
||||||
|
nsCString uri;
|
||||||
};
|
};
|
||||||
|
|
||||||
struct DocShellRestoreState {
|
struct DocShellRestoreState {
|
||||||
|
|||||||
@@ -7,6 +7,7 @@
|
|||||||
#include "js/Array.h" // JS::GetArrayLength, JS::IsArrayObject
|
#include "js/Array.h" // JS::GetArrayLength, JS::IsArrayObject
|
||||||
#include "js/JSON.h"
|
#include "js/JSON.h"
|
||||||
#include "js/PropertyAndElement.h" // JS_GetElement
|
#include "js/PropertyAndElement.h" // JS_GetElement
|
||||||
|
#include "js/TypeDecls.h"
|
||||||
#include "jsapi.h"
|
#include "jsapi.h"
|
||||||
#include "mozilla/PresShell.h"
|
#include "mozilla/PresShell.h"
|
||||||
#include "mozilla/dom/AutocompleteInfoBinding.h"
|
#include "mozilla/dom/AutocompleteInfoBinding.h"
|
||||||
@@ -19,6 +20,8 @@
|
|||||||
#include "mozilla/dom/RootedDictionary.h"
|
#include "mozilla/dom/RootedDictionary.h"
|
||||||
#include "mozilla/dom/SessionStorageManager.h"
|
#include "mozilla/dom/SessionStorageManager.h"
|
||||||
#include "mozilla/dom/PBackgroundSessionStorageCache.h"
|
#include "mozilla/dom/PBackgroundSessionStorageCache.h"
|
||||||
|
#include "mozilla/dom/SessionStoreChangeListener.h"
|
||||||
|
#include "mozilla/dom/SessionStoreChild.h"
|
||||||
#include "mozilla/dom/SessionStoreUtils.h"
|
#include "mozilla/dom/SessionStoreUtils.h"
|
||||||
#include "mozilla/dom/txIXPathContext.h"
|
#include "mozilla/dom/txIXPathContext.h"
|
||||||
#include "mozilla/dom/WindowGlobalParent.h"
|
#include "mozilla/dom/WindowGlobalParent.h"
|
||||||
@@ -300,6 +303,10 @@ void SessionStoreUtils::RestoreScrollPosition(const GlobalObject& aGlobal,
|
|||||||
/* static */
|
/* static */
|
||||||
void SessionStoreUtils::RestoreScrollPosition(
|
void SessionStoreUtils::RestoreScrollPosition(
|
||||||
nsGlobalWindowInner& aWindow, const nsCString& aScrollPosition) {
|
nsGlobalWindowInner& aWindow, const nsCString& aScrollPosition) {
|
||||||
|
using Change = mozilla::dom::SessionStoreChangeListener::Change;
|
||||||
|
SessionStoreChangeListener::CollectSessionStoreData(
|
||||||
|
aWindow.GetWindowContext(), EnumSet<Change>(Change::Scroll));
|
||||||
|
|
||||||
nsCCharSeparatedTokenizer tokenizer(aScrollPosition, ',');
|
nsCCharSeparatedTokenizer tokenizer(aScrollPosition, ',');
|
||||||
nsAutoCString token(tokenizer.nextToken());
|
nsAutoCString token(tokenizer.nextToken());
|
||||||
int pos_X = atoi(token.get());
|
int pos_X = atoi(token.get());
|
||||||
@@ -1203,6 +1210,7 @@ bool SessionStoreUtils::RestoreFormData(const GlobalObject& aGlobal,
|
|||||||
if (!aData.mUrl.WasPassed()) {
|
if (!aData.mUrl.WasPassed()) {
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Don't restore any data for the given frame if the URL
|
// Don't restore any data for the given frame if the URL
|
||||||
// stored in the form data doesn't match its current URL.
|
// stored in the form data doesn't match its current URL.
|
||||||
nsAutoCString url;
|
nsAutoCString url;
|
||||||
@@ -1210,6 +1218,11 @@ bool SessionStoreUtils::RestoreFormData(const GlobalObject& aGlobal,
|
|||||||
if (!aData.mUrl.Value().Equals(url)) {
|
if (!aData.mUrl.Value().Equals(url)) {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
using Change = SessionStoreChangeListener::Change;
|
||||||
|
SessionStoreChangeListener::CollectSessionStoreData(
|
||||||
|
aDocument.GetWindowContext(), EnumSet<Change>(Change::Input));
|
||||||
|
|
||||||
if (aData.mInnerHTML.WasPassed()) {
|
if (aData.mInnerHTML.WasPassed()) {
|
||||||
SetInnerHTML(aDocument, aData.mInnerHTML.Value());
|
SetInnerHTML(aDocument, aData.mInnerHTML.Value());
|
||||||
}
|
}
|
||||||
@@ -1311,6 +1324,10 @@ void RestoreFormEntry(Element* aNode, const FormEntryValue& aValue) {
|
|||||||
void SessionStoreUtils::RestoreFormData(
|
void SessionStoreUtils::RestoreFormData(
|
||||||
Document& aDocument, const nsString& aInnerHTML,
|
Document& aDocument, const nsString& aInnerHTML,
|
||||||
const nsTArray<SessionStoreRestoreData::Entry>& aEntries) {
|
const nsTArray<SessionStoreRestoreData::Entry>& aEntries) {
|
||||||
|
using Change = SessionStoreChangeListener::Change;
|
||||||
|
SessionStoreChangeListener::CollectSessionStoreData(
|
||||||
|
aDocument.GetWindowContext(), EnumSet<Change>(Change::Input));
|
||||||
|
|
||||||
if (!aInnerHTML.IsEmpty()) {
|
if (!aInnerHTML.IsEmpty()) {
|
||||||
SetInnerHTML(aDocument, aInnerHTML);
|
SetInnerHTML(aDocument, aInnerHTML);
|
||||||
}
|
}
|
||||||
@@ -1698,20 +1715,31 @@ nsresult SessionStoreUtils::ConstructSessionStorageValues(
|
|||||||
return NS_OK;
|
return NS_OK;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* static */ void SessionStoreUtils::ResetSessionStore(
|
/* static */
|
||||||
BrowsingContext* aContext) {
|
bool SessionStoreUtils::CopyProperty(JSContext* aCx, JS::HandleObject aDst,
|
||||||
MOZ_RELEASE_ASSERT(NATIVE_LISTENER);
|
JS::HandleObject aSrc,
|
||||||
WindowContext* windowContext = aContext->GetCurrentWindowContext();
|
const nsAString& aName) {
|
||||||
if (!windowContext) {
|
JS::RootedId name(aCx);
|
||||||
return;
|
const char16_t* data;
|
||||||
|
size_t length = aName.GetData(&data);
|
||||||
|
|
||||||
|
if (!JS_CharsToId(aCx, JS::TwoByteChars(data, length), &name)) {
|
||||||
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
WindowGlobalChild* windowChild = windowContext->GetWindowGlobalChild();
|
bool found = false;
|
||||||
if (!windowChild || !windowChild->CanSend()) {
|
if (!JS_HasPropertyById(aCx, aSrc, name, &found) || !found) {
|
||||||
return;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
uint32_t epoch = aContext->GetSessionStoreEpoch();
|
JS::RootedValue value(aCx);
|
||||||
|
if (!JS_GetPropertyById(aCx, aSrc, name, &value)) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
Unused << windowChild->SendResetSessionStore(epoch);
|
if (value.isNullOrUndefined()) {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
return JS_DefinePropertyById(aCx, aDst, name, value, JSPROP_ENUMERATE);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -8,6 +8,7 @@
|
|||||||
#define mozilla_dom_SessionStoreUtils_h
|
#define mozilla_dom_SessionStoreUtils_h
|
||||||
|
|
||||||
#include "mozilla/Attributes.h"
|
#include "mozilla/Attributes.h"
|
||||||
|
#include "mozilla/IntegerRange.h"
|
||||||
#include "mozilla/dom/BindingDeclarations.h"
|
#include "mozilla/dom/BindingDeclarations.h"
|
||||||
#include "mozilla/dom/CanonicalBrowsingContext.h"
|
#include "mozilla/dom/CanonicalBrowsingContext.h"
|
||||||
#include "mozilla/dom/SessionStoreUtilsBinding.h"
|
#include "mozilla/dom/SessionStoreUtilsBinding.h"
|
||||||
@@ -139,14 +140,44 @@ class SessionStoreUtils {
|
|||||||
const nsTArray<SSCacheCopy>& aValues,
|
const nsTArray<SSCacheCopy>& aValues,
|
||||||
Record<nsCString, Record<nsString, nsString>>& aStorage);
|
Record<nsCString, Record<nsString, nsString>>& aStorage);
|
||||||
|
|
||||||
static void ResetSessionStore(BrowsingContext* aContext);
|
|
||||||
|
|
||||||
#if defined(MOZ_WIDGET_ANDROID) || defined(MOZ_THUNDERBIRD) || \
|
#if defined(MOZ_WIDGET_ANDROID) || defined(MOZ_THUNDERBIRD) || \
|
||||||
defined(MOZ_SUITE)
|
defined(MOZ_SUITE)
|
||||||
static constexpr bool NATIVE_LISTENER = false;
|
static constexpr bool NATIVE_LISTENER = false;
|
||||||
#else
|
#else
|
||||||
static constexpr bool NATIVE_LISTENER = true;
|
static constexpr bool NATIVE_LISTENER = true;
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
static bool CopyProperty(JSContext* aCx, JS::HandleObject aDst,
|
||||||
|
JS::HandleObject aSrc, const nsAString& aName);
|
||||||
|
|
||||||
|
template <typename T>
|
||||||
|
static bool CopyChildren(JSContext* aCx, JS::HandleObject aDst,
|
||||||
|
const nsTArray<RefPtr<T>>& aChildren) {
|
||||||
|
if (!aChildren.IsEmpty()) {
|
||||||
|
JS::RootedObject children(aCx,
|
||||||
|
JS::NewArrayObject(aCx, aChildren.Length()));
|
||||||
|
|
||||||
|
for (const auto index : IntegerRange(aChildren.Length())) {
|
||||||
|
if (!aChildren[index]) {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
JS::RootedObject object(aCx);
|
||||||
|
aChildren[index]->ToJSON(aCx, &object);
|
||||||
|
|
||||||
|
if (!JS_DefineElement(aCx, children, index, object, JSPROP_ENUMERATE)) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!JS_DefineProperty(aCx, aDst, "children", children,
|
||||||
|
JSPROP_ENUMERATE)) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
} // namespace dom
|
} // namespace dom
|
||||||
|
|||||||
@@ -5,21 +5,29 @@
|
|||||||
# file, You can obtain one at http://mozilla.org/MPL/2.0/.
|
# file, You can obtain one at http://mozilla.org/MPL/2.0/.
|
||||||
|
|
||||||
EXPORTS.mozilla.dom += [
|
EXPORTS.mozilla.dom += [
|
||||||
|
"BrowserSessionStore.h",
|
||||||
"SessionStoreChangeListener.h",
|
"SessionStoreChangeListener.h",
|
||||||
|
"SessionStoreChild.h",
|
||||||
"SessionStoreData.h",
|
"SessionStoreData.h",
|
||||||
"SessionStoreDataCollector.h",
|
"SessionStoreFormData.h",
|
||||||
"SessionStoreListener.h",
|
"SessionStoreListener.h",
|
||||||
"SessionStoreMessageUtils.h",
|
"SessionStoreMessageUtils.h",
|
||||||
|
"SessionStoreParent.h",
|
||||||
"SessionStoreRestoreData.h",
|
"SessionStoreRestoreData.h",
|
||||||
|
"SessionStoreScrollData.h",
|
||||||
"SessionStoreUtils.h",
|
"SessionStoreUtils.h",
|
||||||
]
|
]
|
||||||
|
|
||||||
UNIFIED_SOURCES += [
|
UNIFIED_SOURCES += [
|
||||||
|
"BrowserSessionStore.cpp",
|
||||||
"RestoreTabContentObserver.cpp",
|
"RestoreTabContentObserver.cpp",
|
||||||
"SessionStoreChangeListener.cpp",
|
"SessionStoreChangeListener.cpp",
|
||||||
"SessionStoreDataCollector.cpp",
|
"SessionStoreChild.cpp",
|
||||||
|
"SessionStoreFormData.cpp",
|
||||||
"SessionStoreListener.cpp",
|
"SessionStoreListener.cpp",
|
||||||
|
"SessionStoreParent.cpp",
|
||||||
"SessionStoreRestoreData.cpp",
|
"SessionStoreRestoreData.cpp",
|
||||||
|
"SessionStoreScrollData.cpp",
|
||||||
"SessionStoreUtils.cpp",
|
"SessionStoreUtils.cpp",
|
||||||
]
|
]
|
||||||
|
|
||||||
@@ -35,6 +43,7 @@ XPIDL_SOURCES += [
|
|||||||
]
|
]
|
||||||
|
|
||||||
IPDL_SOURCES += [
|
IPDL_SOURCES += [
|
||||||
|
"PSessionStore.ipdl",
|
||||||
"SessionStoreTypes.ipdlh",
|
"SessionStoreTypes.ipdlh",
|
||||||
]
|
]
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user