Backed out 4 changesets (bug 1702055) for causing failures on /browser_UsageTelemetry_private_and_restore.js. CLOSED TREE

Backed out changeset af21e2d8324e (bug 1702055)
Backed out changeset ff67df9befe5 (bug 1702055)
Backed out changeset b5f0638dcbc4 (bug 1702055)
Backed out changeset bffaa2c203b3 (bug 1702055)
This commit is contained in:
Butkovits Atila 2021-04-28 04:42:09 +03:00
Родитель a9f0bf8b12
Коммит 2819d98182
18 изменённых файлов: 186 добавлений и 416 удалений

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

@ -504,6 +504,7 @@ class MessageQueue extends Handler {
*/
const MESSAGES = [
"SessionStore:restoreHistory",
"SessionStore:restoreDocShellState",
"SessionStore:restoreTabContent",
"SessionStore:resetRestore",
"SessionStore:flush",
@ -558,6 +559,9 @@ class ContentSessionStore {
case "SessionStore:restoreHistory":
this.restoreHistory(data);
break;
case "SessionStore:restoreDocShellState":
this.restoreDocShellState(data);
break;
case "SessionStore:restoreTabContent":
this.restoreTabContent(data);
break;
@ -639,6 +643,31 @@ class ContentSessionStore {
}
}
// SHIP only
restoreDocShellState(data) {
let { epoch, tabData } = data;
if (!Services.appinfo.sessionHistoryInParent) {
throw new Error("This function should only be used with SHIP");
}
let { docShell } = this.mm;
if (tabData.uri) {
docShell.setCurrentURI(Services.io.newURI(tabData.uri));
}
if (tabData.disallow) {
SessionStoreUtils.restoreDocShellCapabilities(docShell, tabData.disallow);
}
if (tabData.storage) {
SessionStoreUtils.restoreSessionStorage(docShell, tabData.storage);
}
// Since we don't send restoreHistory, we need to tell the parent when
// to call SSTabRestoring (via restoreHistoryComplete)
this.mm.sendAsyncMessage("SessionStore:restoreHistoryComplete", { epoch });
}
restoreTabContent({ loadArguments, isRemotenessUpdate, reason }) {
if (Services.appinfo.sessionHistoryInParent) {
throw new Error("This function should be unused with SHIP");

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

@ -454,10 +454,6 @@ var SessionStore = {
}
},
getCurrentEpoch(browser) {
return SessionStoreInternal.getCurrentEpoch(browser);
},
/**
* Determines whether the passed version number is compatible with
* the current version number of the SessionStore.
@ -523,6 +519,10 @@ var SessionStore = {
finishTabRemotenessChange(aTab, aSwitchId) {
SessionStoreInternal.finishTabRemotenessChange(aTab, aSwitchId);
},
restoreTabContentComplete(aBrowser, aData) {
SessionStoreInternal._restoreTabContentComplete(aBrowser, aData);
},
};
// Freeze the SessionStore object. We don't want anyone to modify it.
@ -3432,13 +3432,9 @@ var SessionStoreInternal = {
let activePageData = tabData.entries[tabData.index - 1] || null;
// If the page has a title and it hasn't yet been updated, set it.
if (!tab._labelIsContentTitle) {
// If the page has a title, set it.
if (activePageData) {
if (
activePageData.title &&
activePageData.title != activePageData.url
) {
if (activePageData.title && activePageData.title != activePageData.url) {
win.gBrowser.setInitialTabTitle(tab, activePageData.title, {
isContentTitle: true,
});
@ -3446,7 +3442,6 @@ var SessionStoreInternal = {
win.gBrowser.setInitialTabTitle(tab, activePageData.url);
}
}
}
// Restore the tab icon.
if ("image" in tabData) {
@ -5625,7 +5620,7 @@ var SessionStoreInternal = {
.get(browser.permanentKey)
.uninstall();
}
browser.browsingContext.clearRestoreState();
SessionStoreUtils.setRestoreData(browser.browsingContext, null);
}
// Keep the tab's previous state for later in this method
@ -5837,7 +5832,7 @@ var SessionStoreInternal = {
* This mirrors ContentRestore.restoreHistory() for parent process session
* history restores, but we're not actually restoring history here.
*/
_restoreHistory(browser, data) {
async _restoreTabState(browser, data) {
if (!Services.appinfo.sessionHistoryInParent) {
throw new Error("This function should only be used with SHIP");
}
@ -5845,36 +5840,33 @@ var SessionStoreInternal = {
// In case about:blank isn't done yet.
browser.stop();
let uri = data.tabData?.entries[data.tabData.index - 1]?.url;
let disallow = data.tabData?.disallow;
let storage = data.tabData?.storage || {};
delete data.tabData?.storage;
let win = browser.ownerGlobal;
let tab = win?.gBrowser.getTabForBrowser(browser);
// We'll likely make multiple calls to _restoreHistory() with the same
// browser element during a single restore, so this promise may be replaced
// in a subsequent call.
data.historyPromise = SessionStoreUtils.restoreDocShellState(
browser.browsingContext,
uri,
disallow,
storage
);
data.historyPromise.finally(() => {
// We only want to call _restoreHistoryComplete() here if we *haven't*
// already begun restoring tab content. If we have started restoring tab
// content, then _restoreTabContent() will handle calling the completion
// function.
//
// Calling _restoreHistoryComplete() here dispatches the "SSTabRestoring"
// event, which tells tabbrowser to call browser.reload(), which will
// trigger the onHistoryReload callback below, where we'll proceed with
// the tab content restore.
if (TAB_STATE_FOR_BROWSER.get(browser) === TAB_STATE_NEEDS_RESTORE) {
delete data.historyPromise;
this._restoreHistoryComplete(browser, data);
browser.messageManager.sendAsyncMessage(
"SessionStore:restoreDocShellState",
{
epoch: data.epoch,
tabData: {
uri: data.tabData?.entries[data.tabData.index - 1]?.url ?? null,
disallow: data.tabData?.disallow,
storage: data.tabData?.storage,
},
}
);
// For the non-remote case, the above will restore, but asynchronously.
// However, we need to restore DocShellState synchronously in the
// parent to avoid a test failure.
if (tab.linkedBrowser.docShell) {
SessionStoreUtils.restoreDocShellCapabilities(
tab.linkedBrowser.docShell,
data.tabData.disallow
);
}
if (data.tabData?.storage) {
delete data.tabData.storage;
}
});
this._shistoryToRestore.set(browser.permanentKey, data);
@ -5918,66 +5910,58 @@ var SessionStoreInternal = {
this._restoreTabContentStarted(browser, restoreData);
let tabData = restoreData.tabData || {};
let promises = [restoreData.historyPromise];
let { tabData } = restoreData;
let uri = null;
let loadFlags = null;
if (tabData.userTypedValue && tabData.userTypedClear) {
if (tabData?.userTypedValue && tabData?.userTypedClear) {
uri = tabData.userTypedValue;
loadFlags = Ci.nsIWebNavigation.LOAD_FLAGS_ALLOW_THIRD_PARTY_FIXUP;
} else if (tabData.entries.length) {
promises.push(
SessionStoreUtils.initializeRestore(
} else if (tabData?.entries.length) {
uri = tabData.entries[tabData.index - 1].url;
let willRestoreContent = SessionStoreUtils.setRestoreData(
browser.browsingContext,
this.buildRestoreData(tabData.formdata, tabData.scroll)
)
);
// We'll manually call RestoreTabContentComplete when the restore is done,
// so we only want to create the listener below if we're not restoring tab
// content.
if (willRestoreContent) {
return;
}
} else {
uri = "about:blank";
loadFlags = Ci.nsIWebNavigation.LOAD_FLAGS_BYPASS_HISTORY;
}
if (uri && loadFlags) {
let deferred = PromiseUtils.defer();
promises.push(deferred.promise);
if (uri) {
this.addProgressListenerForRestore(browser, {
onStopRequest: (request, listener) => {
let requestURI = request.QueryInterface(Ci.nsIChannel)?.originalURI;
// FIXME: We sometimes see spurious STATE_STOP events for about:blank
// URIs, so we have to manually drop those here (unless we're actually
// expecting an about:blank load).
//
// In the case where we're firing _restoreTabContentComplete due to
// a normal load (i.e. !willRestoreContent), we could perhaps just not
// wait for the load here, and instead fix tests that depend on this
// behavior.
if (requestURI?.spec !== "about:blank" || uri === "about:blank") {
listener.uninstall();
deferred.resolve();
this._restoreTabContentComplete(browser, restoreData);
}
},
});
if (loadFlags) {
browser.browsingContext.loadURI(uri, {
loadFlags,
triggeringPrincipal: Services.scriptSecurityManager.getSystemPrincipal(),
});
} else {
browser.browsingContext.sessionHistory.reloadCurrentEntry();
}
Promise.allSettled(promises).then(() => {
// We may have stopped or restarted the restore for this browser prior to
// the resolution of these promises, so this ensures that we're only
// calling the completion functions for browsers that are actively being
// restored.
if (TAB_STATE_FOR_BROWSER.get(browser) === TAB_STATE_RESTORING) {
// We would have already called _restoreHistoryComplete() if the browser
// element was reloaded while a restore was in progress. This avoids
// calling it twice. See the comment in _restoreHistory() for more
// context.
if (restoreData.historyPromise) {
this._restoreHistoryComplete(browser, restoreData);
}
this._restoreTabContentComplete(browser, restoreData);
}
});
},
_sendRestoreTabContent(browser, options) {
@ -6170,7 +6154,7 @@ var SessionStoreInternal = {
}
if (Services.appinfo.sessionHistoryInParent) {
this._restoreHistory(browser, options);
this._restoreTabState(browser, options);
} else {
browser.messageManager.sendAsyncMessage(
"SessionStore:restoreHistory",

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

@ -121,10 +121,7 @@ var TabStateFlusherInternal = {
SessionStore.ensureInitialized(browser.ownerGlobal);
let mm = browser.messageManager;
mm.sendAsyncMessage("SessionStore:flush", {
id,
epoch: SessionStore.getCurrentEpoch(browser),
});
mm.sendAsyncMessage("SessionStore:flush", { id });
// Retrieve active requests for given browser.
let permanentKey = browser.permanentKey;

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

@ -182,6 +182,14 @@ void CanonicalBrowsingContext::ReplacedBy(
}
aNewContext->mWebProgress = std::move(mWebProgress);
bool hasRestoreData = !!mRestoreData && !mRestoreData->IsEmpty();
aNewContext->mRestoreData = std::move(mRestoreData);
aNewContext->mRequestedContentRestores = mRequestedContentRestores;
aNewContext->mCompletedContentRestores = mCompletedContentRestores;
SetRestoreData(nullptr);
mRequestedContentRestores = 0;
mCompletedContentRestores = 0;
// Use the Transaction for the fields which need to be updated whether or not
// the new context has been attached before.
// SetWithoutSyncing can be used if context hasn't been attached.
@ -189,16 +197,13 @@ void CanonicalBrowsingContext::ReplacedBy(
txn.SetBrowserId(GetBrowserId());
txn.SetHistoryID(GetHistoryID());
txn.SetExplicitActive(GetExplicitActive());
txn.SetHasRestoreData(GetHasRestoreData());
txn.SetHasRestoreData(hasRestoreData);
if (aNewContext->EverAttached()) {
MOZ_ALWAYS_SUCCEEDS(txn.Commit(aNewContext));
} else {
txn.CommitWithoutSyncing(aNewContext);
}
aNewContext->mRestoreState = mRestoreState.forget();
MOZ_ALWAYS_SUCCEEDS(SetHasRestoreData(false));
// XXXBFCache name handling is still a bit broken in Fission in general,
// at least in case name should be cleared.
if (aRemotenessOptions.mTryUseBFCache) {
@ -1908,103 +1913,49 @@ void CanonicalBrowsingContext::ResetScalingZoom() {
}
}
void CanonicalBrowsingContext::SetRestoreData(SessionStoreRestoreData* aData,
ErrorResult& aError) {
MOZ_DIAGNOSTIC_ASSERT(aData);
nsCOMPtr<nsIGlobalObject> global = do_QueryInterface(GetParentObject());
RefPtr<Promise> promise = Promise::Create(global, aError);
if (aError.Failed()) {
return;
}
if (NS_WARN_IF(NS_FAILED(SetHasRestoreData(true)))) {
aError.Throw(NS_ERROR_DOM_INVALID_STATE_ERR);
return;
}
mRestoreState = new RestoreState();
mRestoreState->mData = aData;
mRestoreState->mPromise = promise;
}
already_AddRefed<Promise> CanonicalBrowsingContext::GetRestorePromise() {
if (mRestoreState) {
return do_AddRef(mRestoreState->mPromise);
}
return nullptr;
}
void CanonicalBrowsingContext::ClearRestoreState() {
if (!mRestoreState) {
MOZ_DIAGNOSTIC_ASSERT(!GetHasRestoreData());
return;
}
if (mRestoreState->mPromise) {
mRestoreState->mPromise->MaybeRejectWithUndefined();
mRestoreState->mPromise = nullptr;
}
mRestoreState = nullptr;
MOZ_ALWAYS_SUCCEEDS(SetHasRestoreData(false));
}
void CanonicalBrowsingContext::ResolveAndClearRestoreState(
RestoreState* aState) {
MOZ_DIAGNOSTIC_ASSERT(aState->mPromise);
aState->mPromise->MaybeResolveWithUndefined();
aState->mPromise = nullptr;
// We may have started a new restore before the previous one had resolved.
// This ensures that we aren't clearing state for the new restore.
if (aState == mRestoreState) {
ClearRestoreState();
}
void CanonicalBrowsingContext::SetRestoreData(SessionStoreRestoreData* aData) {
MOZ_DIAGNOSTIC_ASSERT(!mRestoreData || !aData,
"must either be clearing or initializing");
MOZ_DIAGNOSTIC_ASSERT(
!aData || mCompletedContentRestores == mRequestedContentRestores,
"must not start restore in an unstable state");
mRestoreData = aData;
MOZ_ALWAYS_SUCCEEDS(SetHasRestoreData(mRestoreData));
}
void CanonicalBrowsingContext::RequestRestoreTabContent(
WindowGlobalParent* aWindow) {
MOZ_DIAGNOSTIC_ASSERT(IsTop());
if (IsDiscarded() || !mRestoreState || !mRestoreState->mData) {
if (IsDiscarded() || !mRestoreData || mRestoreData->IsEmpty()) {
return;
}
CanonicalBrowsingContext* context = aWindow->GetBrowsingContext();
MOZ_DIAGNOSTIC_ASSERT(!context->IsDiscarded());
RefPtr<SessionStoreRestoreData> data =
mRestoreState->mData->FindDataForChild(context);
RefPtr<SessionStoreRestoreData> data = mRestoreData->FindChild(context);
// We'll only arrive here for a toplevel context after we've already sent
// down data for any out-of-process descendants, so it's fine to clear our
// data now.
if (context->IsTop()) {
MOZ_DIAGNOSTIC_ASSERT(context == this);
// We need to wait until the appropriate load event has fired before we
// can "complete" the restore process, so if we're holding an empty data
// object, just resolve the promise immediately.
if (mRestoreState->mData->IsEmpty()) {
MOZ_DIAGNOSTIC_ASSERT(!data || data->IsEmpty());
ResolveAndClearRestoreState(mRestoreState);
return;
}
// Since we're following load event order, we'll only arrive here for a
// toplevel context after we've already sent down data for all child frames,
// so it's safe to clear this reference now. The completion callback below
// relies on the mData field being null to determine if all requests have
// been sent out.
mRestoreState->ClearData();
MOZ_ALWAYS_SUCCEEDS(SetHasRestoreData(false));
SetRestoreData(nullptr);
}
if (data && !data->IsEmpty()) {
auto onTabRestoreComplete = [self = RefPtr{this},
state = RefPtr{mRestoreState}](auto) {
state->mResolves++;
if (!state->mData && state->mRequests == state->mResolves) {
self->ResolveAndClearRestoreState(state);
auto onTabRestoreComplete = [self = RefPtr{this}](auto) {
self->mCompletedContentRestores++;
if (!self->mRestoreData &&
self->mCompletedContentRestores == self->mRequestedContentRestores) {
if (Element* browser = self->GetEmbedderElement()) {
SessionStoreUtils::CallRestoreTabContentComplete(browser);
}
}
};
mRestoreState->mRequests++;
mRequestedContentRestores++;
if (data->CanRestoreInto(aWindow->GetDocumentURI())) {
if (!aWindow->IsInProcess()) {

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

@ -10,7 +10,6 @@
#include "mozilla/dom/BrowsingContext.h"
#include "mozilla/dom/MediaControlKeySource.h"
#include "mozilla/dom/BrowsingContextWebProgress.h"
#include "mozilla/dom/Promise.h"
#include "mozilla/dom/SessionStoreRestoreData.h"
#include "mozilla/dom/SessionStoreUtils.h"
#include "mozilla/dom/ipc/IdType.h"
@ -287,10 +286,8 @@ class CanonicalBrowsingContext final : public BrowsingContext {
return mContainerFeaturePolicy;
}
void SetRestoreData(SessionStoreRestoreData* aData, ErrorResult& aError);
void ClearRestoreState();
void SetRestoreData(SessionStoreRestoreData* aData);
void RequestRestoreTabContent(WindowGlobalParent* aWindow);
already_AddRefed<Promise> GetRestorePromise();
// Called when a BrowserParent for this BrowsingContext has been fully
// destroyed (i.e. `ActorDestroy` was called).
@ -352,20 +349,6 @@ class CanonicalBrowsingContext final : public BrowsingContext {
RemotenessChangeOptions mOptions;
};
struct RestoreState {
NS_INLINE_DECL_REFCOUNTING(RestoreState)
void ClearData() { mData = nullptr; }
RefPtr<SessionStoreRestoreData> mData;
RefPtr<Promise> mPromise;
uint32_t mRequests = 0;
uint32_t mResolves = 0;
private:
~RestoreState() = default;
};
friend class net::DocumentLoadListener;
// Called when a DocumentLoadListener is created to start a load for
// this browsing context. Returns false if a higher priority load is
@ -393,8 +376,6 @@ class CanonicalBrowsingContext final : public BrowsingContext {
// has become unloaded for one reason or another.
void ShowSubframeCrashedUI(BrowserBridgeParent* aBridge);
void ResolveAndClearRestoreState(RestoreState* aState);
// XXX(farre): Store a ContentParent pointer here rather than mProcessId?
// Indicates which process owns the docshell.
uint64_t mProcessId;
@ -443,7 +424,9 @@ class CanonicalBrowsingContext final : public BrowsingContext {
RefPtr<FeaturePolicy> mContainerFeaturePolicy;
RefPtr<RestoreState> mRestoreState;
RefPtr<SessionStoreRestoreData> mRestoreData;
uint32_t mRequestedContentRestores = 0;
uint32_t mCompletedContentRestores = 0;
};
} // namespace dom

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

@ -287,8 +287,6 @@ interface CanonicalBrowsingContext : BrowsingContext {
// The current URI loaded in this BrowsingContext according to nsDocShell.
// This may not match the current window global's document URI in some cases.
readonly attribute URI? currentURI;
void clearRestoreState();
};
[Exposed=Window, ChromeOnly]

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

@ -126,16 +126,8 @@ namespace SessionStoreUtils {
nsISessionStoreRestoreData constructSessionStoreRestoreData();
[Throws]
Promise<void> initializeRestore(CanonicalBrowsingContext browsingContext,
boolean setRestoreData(CanonicalBrowsingContext browsingContext,
nsISessionStoreRestoreData? data);
[Throws]
Promise<void> restoreDocShellState(
CanonicalBrowsingContext browsingContext,
UTF8String? url,
ByteString? docShellCaps,
record<UTF8String, record<DOMString, DOMString>> sessionStorage);
};
[GenerateConversionToJS, GenerateInit]

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

@ -93,9 +93,6 @@ child:
async SetContainerFeaturePolicy(FeaturePolicy aContainerFeaturePolicy);
async RestoreDocShellState(DocShellRestoreState aState)
returns (bool success);
async RestoreTabContent(SessionStoreRestoreData aData) returns (bool success);
both:

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

@ -557,17 +557,6 @@ mozilla::ipc::IPCResult WindowGlobalChild::RecvSetContainerFeaturePolicy(
return IPC_OK();
}
mozilla::ipc::IPCResult WindowGlobalChild::RecvRestoreDocShellState(
const dom::sessionstore::DocShellRestoreState& aState,
RestoreDocShellStateResolver&& aResolve) {
if (mWindowGlobal) {
SessionStoreUtils::RestoreDocShellState(mWindowGlobal->GetDocShell(),
aState);
}
aResolve(true);
return IPC_OK();
}
mozilla::ipc::IPCResult WindowGlobalChild::RecvRestoreTabContent(
dom::SessionStoreRestoreData* aData, RestoreTabContentResolver&& aResolve) {
aData->RestoreInto(BrowsingContext());

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

@ -180,10 +180,6 @@ class WindowGlobalChild final : public WindowGlobalActor,
mozilla::ipc::IPCResult RecvSetContainerFeaturePolicy(
dom::FeaturePolicy* aContainerFeaturePolicy);
mozilla::ipc::IPCResult RecvRestoreDocShellState(
const dom::sessionstore::DocShellRestoreState& aState,
RestoreDocShellStateResolver&& aResolve);
mozilla::ipc::IPCResult RecvRestoreTabContent(
dom::SessionStoreRestoreData* aData,
RestoreTabContentResolver&& aResolve);

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

@ -80,7 +80,9 @@ RestoreTabContentObserver::Observe(nsISupports* aSubject, const char* aTopic,
}
nsCOMPtr<nsIURI> uri = inner->GetDocumentURI();
if (!uri) {
// We'll never need to restore data into an about:blank document, so we can
// ignore those here.
if (!uri || NS_IsAboutBlank(uri)) {
return NS_OK;
}

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

@ -17,6 +17,8 @@ interface nsISessionStoreFunctions : nsISupports {
in uint32_t aEpoch,
in jsval aData, in boolean aCollectSHistory);
void RestoreTabContentComplete(in Element aBrowser);
void UpdateSessionStoreForWindow(
in Element aBrowser, in BrowsingContext aBrowsingContext,
in uint32_t aEpoch, in jsval aData);

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

@ -10,6 +10,10 @@ XPCOMUtils.defineLazyModuleGetters(this, {
SessionStore: "resource:///modules/sessionstore/SessionStore.jsm",
});
function RestoreTabContentComplete(aBrowser) {
SessionStore.restoreTabContentComplete(aBrowser, {});
}
function UpdateSessionStore(
aBrowser,
aBrowsingContext,
@ -40,7 +44,11 @@ function UpdateSessionStoreForWindow(
);
}
var EXPORTED_SYMBOLS = ["UpdateSessionStore", "UpdateSessionStoreForWindow"];
var EXPORTED_SYMBOLS = [
"RestoreTabContentComplete",
"UpdateSessionStore",
"UpdateSessionStoreForWindow",
];
var SessionStoreFuncInternal = {
updateStorage: function SSF_updateStorage(aOrigins, aKeys, aValues) {

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

@ -17,7 +17,7 @@ bool SessionStoreRestoreData::IsEmpty() {
mEntries.IsEmpty() && mChildren.IsEmpty());
}
SessionStoreRestoreData* SessionStoreRestoreData::FindDataForChild(
SessionStoreRestoreData* SessionStoreRestoreData::FindChild(
BrowsingContext* aContext) {
nsTArray<uint32_t> offsets;
for (const BrowsingContext* current = aContext;

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

@ -26,7 +26,7 @@ class SessionStoreRestoreData final : public nsISessionStoreRestoreData {
public:
SessionStoreRestoreData() = default;
bool IsEmpty();
SessionStoreRestoreData* FindDataForChild(BrowsingContext* aContext);
SessionStoreRestoreData* FindChild(BrowsingContext* aContext);
bool CanRestoreInto(nsIURI* aDocumentURI);
bool RestoreInto(RefPtr<BrowsingContext> aContext);

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

@ -7,8 +7,6 @@
using struct CollectedInputDataValue from "mozilla/dom/SessionStoreMessageUtils.h";
using struct nsPoint from "nsPoint.h";
include DOMTypes;
namespace mozilla {
namespace dom {
@ -54,19 +52,7 @@ struct FormData {
nsString innerHTML;
};
struct StorageEntry {
nsCString origin;
nsString[] keys;
nsString[] values;
};
struct DocShellRestoreState {
nsIURI URI;
nsCString docShellCaps;
StorageEntry[] sessionStorage;
};
} // sessionstore
}
} // dom
} // mozilla

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

@ -217,7 +217,8 @@ void SessionStoreUtils::CollectDocShellCapabilities(const GlobalObject& aGlobal,
/* static */
void SessionStoreUtils::RestoreDocShellCapabilities(
nsIDocShell* aDocShell, const nsCString& aDisallowCapabilities) {
const GlobalObject& aGlobal, nsIDocShell* aDocShell,
const nsCString& aDisallowCapabilities) {
aDocShell->SetAllowPlugins(true);
aDocShell->SetAllowJavascript(true);
aDocShell->SetAllowMetaRedirects(true);
@ -1365,18 +1366,6 @@ void SessionStoreUtils::CollectedSessionStorage(
void SessionStoreUtils::RestoreSessionStorage(
const GlobalObject& aGlobal, nsIDocShell* aDocShell,
const Record<nsString, Record<nsString, nsString>>& aData) {
BrowsingContext* const browsingContext =
nsDocShell::Cast(aDocShell)->GetBrowsingContext();
if (!browsingContext) {
return;
}
const RefPtr<SessionStorageManager> storageManager =
browsingContext->GetSessionStorageManager();
if (!storageManager) {
return;
}
for (auto& entry : aData.Entries()) {
// NOTE: In capture() we record the full origin for the URI which the
// sessionStorage is being captured for. As of bug 1235657 this code
@ -1398,11 +1387,21 @@ void SessionStoreUtils::RestoreSessionStorage(
int32_t pos = entry.mKey.RFindChar('^');
nsCOMPtr<nsIPrincipal> principal = BasePrincipal::CreateContentPrincipal(
NS_ConvertUTF16toUTF8(Substring(entry.mKey, 0, pos)));
BrowsingContext* const browsingContext =
nsDocShell::Cast(aDocShell)->GetBrowsingContext();
if (!browsingContext) {
return;
}
nsCOMPtr<nsIPrincipal> storagePrincipal =
BasePrincipal::CreateContentPrincipal(
NS_ConvertUTF16toUTF8(entry.mKey));
const RefPtr<SessionStorageManager> storageManager =
browsingContext->GetSessionStorageManager();
if (!storageManager) {
return;
}
RefPtr<Storage> storage;
// There is no need to pass documentURI, it's only used to fill documentURI
// property of domstorage event, which in this case has no consumer.
@ -1425,71 +1424,6 @@ void SessionStoreUtils::RestoreSessionStorage(
}
}
// This is a mirror of SessionStoreUtils::RestoreSessionStorage for the SHIP
// codepath. We'll be able to remove this when it becomes possible to restore
// storage directly from the parent (bug 1700623).
void RestoreSessionStorage(nsIDocShell* aDocShell,
const nsTArray<StorageEntry>& aData) {
BrowsingContext* const browsingContext =
nsDocShell::Cast(aDocShell)->GetBrowsingContext();
if (!browsingContext) {
return;
}
const RefPtr<SessionStorageManager> storageManager =
browsingContext->GetSessionStorageManager();
if (!storageManager) {
return;
}
for (const auto& entry : aData) {
// NOTE: In capture() we record the full origin for the URI which the
// sessionStorage is being captured for. As of bug 1235657 this code
// stopped parsing any origins which have originattributes correctly, as
// it decided to use the origin attributes from the docshell, and try to
// interpret the origin as a URI. Since bug 1353844 this code now correctly
// parses the full origin, and then discards the origin attributes, to
// make the behavior line up with the original intentions in bug 1235657
// while preserving the ability to read all session storage from
// previous versions. In the future, if this behavior is desired, we may
// want to use the spec instead of the origin as the key, and avoid
// transmitting origin attribute information which we then discard when
// restoring.
//
// If changing this logic, make sure to also change the principal
// computation logic in SessionStore::_sendRestoreHistory.
// OriginAttributes are always after a '^' character
int32_t pos = entry.origin().RFindChar('^');
nsCOMPtr<nsIPrincipal> principal = BasePrincipal::CreateContentPrincipal(
Substring(entry.origin(), 0, pos));
nsCOMPtr<nsIPrincipal> storagePrincipal =
BasePrincipal::CreateContentPrincipal(entry.origin());
RefPtr<Storage> storage;
// There is no need to pass documentURI, it's only used to fill documentURI
// property of domstorage event, which in this case has no consumer.
// Prevention of events in case of missing documentURI will be solved in a
// followup bug to bug 600307.
// Null window because the current window doesn't match the principal yet
// and loads about:blank.
storageManager->CreateStorage(nullptr, principal, storagePrincipal, u""_ns,
false, getter_AddRefs(storage));
if (!storage) {
continue;
}
MOZ_DIAGNOSTIC_ASSERT(entry.keys().Length() == entry.values().Length());
for (size_t i = 0; i < entry.keys().Length(); ++i) {
IgnoredErrorResult result;
storage->SetItem(entry.keys()[i], entry.values()[i], *principal, result);
if (result.Failed()) {
NS_WARNING("storage set item failed!");
}
}
}
}
typedef void (*CollectorFunc)(JSContext* aCx, Document& aDocument,
Nullable<CollectedData>& aRetVal);
@ -1629,99 +1563,34 @@ SessionStoreUtils::ConstructSessionStoreRestoreData(
/* static */
MOZ_CAN_RUN_SCRIPT
already_AddRefed<Promise> SessionStoreUtils::InitializeRestore(
const GlobalObject& aGlobal, CanonicalBrowsingContext& aContext,
nsISessionStoreRestoreData* aData, ErrorResult& aError) {
bool SessionStoreUtils::SetRestoreData(const GlobalObject& aGlobal,
CanonicalBrowsingContext& aContext,
nsISessionStoreRestoreData* aData) {
if (!mozilla::SessionHistoryInParent()) {
MOZ_CRASH("why were we called?");
}
MOZ_DIAGNOSTIC_ASSERT(aContext.IsTop());
MOZ_DIAGNOSTIC_ASSERT(aData);
nsCOMPtr<SessionStoreRestoreData> data = do_QueryInterface(aData);
aContext.SetRestoreData(data, aError);
if (aError.Failed()) {
return nullptr;
aContext.SetRestoreData(data);
if (data && !data->IsEmpty()) {
if (nsISHistory* shistory = aContext.GetSessionHistory()) {
shistory->ReloadCurrentEntry();
return true;
}
}
MOZ_DIAGNOSTIC_ASSERT(aContext.GetSessionHistory());
aContext.GetSessionHistory()->ReloadCurrentEntry();
return aContext.GetRestorePromise();
return false;
}
/* static */
void SessionStoreUtils::RestoreDocShellState(
nsIDocShell* aDocShell, const DocShellRestoreState& aState) {
if (aDocShell) {
if (aState.URI()) {
aDocShell->SetCurrentURI(aState.URI());
}
RestoreDocShellCapabilities(aDocShell, aState.docShellCaps());
// We'll be able to remove this when it becomes possible to restore
// storage directly from the parent.
if (!aState.sessionStorage().IsEmpty()) {
::RestoreSessionStorage(aDocShell, aState.sessionStorage());
}
}
}
/* static */
already_AddRefed<Promise> SessionStoreUtils::RestoreDocShellState(
const GlobalObject& aGlobal, CanonicalBrowsingContext& aContext,
const nsACString& aURL, const nsCString& aDocShellCaps,
const Record<nsCString, Record<nsString, nsString>>& aSessionStorage,
ErrorResult& aError) {
if (!mozilla::SessionHistoryInParent()) {
MOZ_CRASH("why were we called?");
}
MOZ_DIAGNOSTIC_ASSERT(aContext.IsTop());
nsCOMPtr<nsIGlobalObject> global = do_QueryInterface(aGlobal.GetAsSupports());
MOZ_DIAGNOSTIC_ASSERT(global);
RefPtr<Promise> promise = Promise::Create(global, aError);
if (aError.Failed()) {
return nullptr;
}
nsCOMPtr<nsIURI> uri;
if (!aURL.IsEmpty()) {
if (NS_FAILED(NS_NewURI(getter_AddRefs(uri), aURL))) {
aError.Throw(NS_ERROR_FAILURE);
return nullptr;
}
}
// We'll be able to remove this when it becomes possible to restore storage
// directly from the parent.
nsTArray<StorageEntry> storage;
for (const auto& originEntry : aSessionStorage.Entries()) {
StorageEntry* entry = storage.AppendElement();
entry->origin() = originEntry.mKey;
for (const auto& kvEntry : originEntry.mValue.Entries()) {
entry->keys().AppendElement(kvEntry.mKey);
entry->values().AppendElement(kvEntry.mValue);
}
}
DocShellRestoreState state = {uri, aDocShellCaps, storage};
if (WindowGlobalParent* wgp = aContext.GetCurrentWindowGlobal()) {
if (wgp->IsInProcess()) {
RestoreDocShellState(aContext.GetDocShell(), state);
promise->MaybeResolveWithUndefined();
} else {
wgp->SendRestoreDocShellState(state)->Then(
GetMainThreadSerialEventTarget(), __func__,
[promise](void) { promise->MaybeResolveWithUndefined(); },
[promise](void) { promise->MaybeReject(NS_ERROR_FAILURE); });
}
}
return promise.forget();
nsresult SessionStoreUtils::CallRestoreTabContentComplete(Element* aBrowser) {
nsCOMPtr<nsISessionStoreFunctions> funcs =
do_ImportModule("resource://gre/modules/SessionStoreFunctions.jsm");
NS_ENSURE_TRUE(funcs, NS_ERROR_FAILURE);
return funcs->RestoreTabContentComplete(aBrowser);
}
/* static */

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

@ -27,10 +27,8 @@ class GlobalObject;
struct SSScrollPositionDict;
namespace sessionstore {
class DocShellRestoreState;
class FormData;
class FormEntry;
class StorageEntry;
} // namespace sessionstore
class SessionStoreUtils {
@ -54,13 +52,9 @@ class SessionStoreUtils {
nsIDocShell* aDocShell,
nsCString& aRetVal);
static void RestoreDocShellCapabilities(
nsIDocShell* aDocShell, const nsCString& aDisallowCapabilities);
static void RestoreDocShellCapabilities(
const GlobalObject& aGlobal, nsIDocShell* aDocShell,
const nsCString& aDisallowCapabilities) {
return RestoreDocShellCapabilities(aDocShell, aDisallowCapabilities);
}
const nsCString& aDisallowCapabilities);
static void CollectScrollPosition(const GlobalObject& aGlobal,
WindowProxyHolder& aWindow,
@ -119,18 +113,11 @@ class SessionStoreUtils {
static already_AddRefed<nsISessionStoreRestoreData>
ConstructSessionStoreRestoreData(const GlobalObject& aGlobal);
static already_AddRefed<Promise> InitializeRestore(
const GlobalObject& aGlobal, CanonicalBrowsingContext& aContext,
nsISessionStoreRestoreData* aData, ErrorResult& aError);
static bool SetRestoreData(const GlobalObject& aGlobal,
CanonicalBrowsingContext& aContext,
nsISessionStoreRestoreData* aData);
static void RestoreDocShellState(
nsIDocShell* aDocShell, const sessionstore::DocShellRestoreState& aState);
static already_AddRefed<Promise> RestoreDocShellState(
const GlobalObject& aGlobal, CanonicalBrowsingContext& aContext,
const nsACString& aURL, const nsCString& aDocShellCaps,
const Record<nsCString, Record<nsString, nsString>>& aSessionStorage,
ErrorResult& aError);
static nsresult CallRestoreTabContentComplete(Element* aBrowser);
static nsresult ConstructFormDataValues(
JSContext* aCx, const nsTArray<sessionstore::FormEntry>& aValues,