Bug 1501108 - [3.4] Add a StorageController API to delete session context data. r=baku,snorp,geckoview-reviewers

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

--HG--
extra : moz-landing-system : lando
This commit is contained in:
Eugen Sawin 2019-04-17 13:03:49 +00:00
parent c5f6173444
commit 0353b16889
7 changed files with 181 additions and 6 deletions

View File

@ -131,10 +131,12 @@ GeckoViewStartup.prototype = {
SafeBrowsing.init();
// Listen for global EventDispatcher messages
EventDispatcher.instance.registerListener(this,
["GeckoView:ResetUserPrefs",
"GeckoView:SetDefaultPrefs",
"GeckoView:SetLocale"]);
EventDispatcher.instance.registerListener(this, [
"GeckoView:ClearSessionContextData",
"GeckoView:ResetUserPrefs",
"GeckoView:SetDefaultPrefs",
"GeckoView:SetLocale",
]);
break;
}
}
@ -144,6 +146,16 @@ GeckoViewStartup.prototype = {
debug `onEvent ${aEvent}`;
switch (aEvent) {
case "GeckoView:ClearSessionContextData": {
let pattern = {};
if (aData.contextId !== null) {
pattern = { geckoViewSessionContextId: aData.contextId };
}
Services.clearData.deleteDataFromOriginAttributesPattern(pattern);
Services.qms.clearStoragesForOriginAttributesPattern(
JSON.stringify(pattern));
break;
}
case "GeckoView:ResetUserPrefs": {
const prefs = new Preferences();
prefs.reset(aData.names);

View File

@ -78,6 +78,7 @@ import org.mozilla.geckoview.ScreenLength;
import org.mozilla.geckoview.SessionAccessibility;
import org.mozilla.geckoview.SessionFinder;
import org.mozilla.geckoview.SessionTextInput;
import org.mozilla.geckoview.StorageController;
import org.mozilla.geckoview.WebExtension;
import org.mozilla.geckoview.WebMessage;
import org.mozilla.geckoview.WebRequest;
@ -266,7 +267,6 @@ package org.mozilla.geckoview {
}
public final class GeckoRuntime implements Parcelable {
ctor public GeckoRuntime();
method @UiThread public void attachTo(@NonNull Context);
method @UiThread public void configurationChanged(@NonNull Configuration);
method @UiThread @NonNull public static GeckoRuntime create(@NonNull Context);
@ -275,6 +275,7 @@ package org.mozilla.geckoview {
method @UiThread @Nullable public GeckoRuntime.Delegate getDelegate();
method @UiThread @Nullable public File getProfileDir();
method @AnyThread @NonNull public GeckoRuntimeSettings getSettings();
method @AnyThread @NonNull public StorageController getStorageController();
method @UiThread @NonNull public RuntimeTelemetry getTelemetry();
method @UiThread public void orientationChanged();
method @UiThread public void orientationChanged(int);
@ -782,6 +783,7 @@ package org.mozilla.geckoview {
ctor public GeckoSessionSettings(@NonNull GeckoSessionSettings);
method public boolean getAllowJavascript();
method @Nullable public String getChromeUri();
method @Nullable public String getContextId();
method public int getDisplayMode();
method public boolean getFullAccessibilityTree();
method public int getScreenId();
@ -819,6 +821,7 @@ package org.mozilla.geckoview {
method @NonNull public GeckoSessionSettings.Builder allowJavascript(boolean);
method @NonNull public GeckoSessionSettings build();
method @NonNull public GeckoSessionSettings.Builder chromeUri(@NonNull String);
method @NonNull public GeckoSessionSettings.Builder contextId(@Nullable String);
method @NonNull public GeckoSessionSettings.Builder displayMode(int);
method @NonNull public GeckoSessionSettings.Builder fullAccessibilityTree(boolean);
method @NonNull public GeckoSessionSettings.Builder screenId(int);
@ -1029,6 +1032,12 @@ package org.mozilla.geckoview {
method @UiThread public synchronized void setView(@Nullable View);
}
public final class StorageController {
ctor public StorageController();
method @AnyThread public void clearAllSessionContextData();
method @AnyThread public void clearSessionContextData(@NonNull String);
}
public class WebExtension {
ctor public WebExtension(@NonNull String, @NonNull String);
ctor public WebExtension(@NonNull String);

View File

@ -1242,4 +1242,73 @@ class NavigationDelegateTest : BaseSessionTest() {
}
})
}
@WithDevToolsAPI
@Test fun clearSessionContextData() {
val session1 = sessionRule.createOpenSession(
GeckoSessionSettings.Builder(mainSession.settings)
.contextId("1")
.build())
session1.loadTestPath(STORAGE_TITLE_HTML_PATH + "?ctx1")
session1.waitForPageStop()
session1.forCallbacksDuringWait(object: Callbacks.ContentDelegate {
@AssertCalled(count = 1)
override fun onTitleChange(session: GeckoSession, title: String?) {
assertThat("Title should not be empty", title, not(isEmptyOrNullString()))
assertThat("Title should match", title,
equalTo("storage=ctx1"))
}
})
session1.loadTestPath(STORAGE_TITLE_HTML_PATH)
session1.waitForPageStop()
session1.forCallbacksDuringWait(object: Callbacks.ContentDelegate {
@AssertCalled(count = 1)
override fun onTitleChange(session: GeckoSession, title: String?) {
assertThat("Title should not be empty", title, not(isEmptyOrNullString()))
assertThat("Title should match", title,
equalTo("storage=ctx1"))
}
})
session1.close()
val session2 = sessionRule.createOpenSession(
GeckoSessionSettings.Builder(mainSession.settings)
.contextId("1")
.build())
session2.loadTestPath(STORAGE_TITLE_HTML_PATH)
session2.waitForPageStop()
session2.forCallbacksDuringWait(object: Callbacks.ContentDelegate {
@AssertCalled(count = 1)
override fun onTitleChange(session: GeckoSession, title: String?) {
assertThat("Title should not be empty", title, not(isEmptyOrNullString()))
assertThat("Title should match", title,
equalTo("storage=ctx1"))
}
})
session2.close()
sessionRule.runtime.storageController.clearSessionContextData("1")
val session3 = sessionRule.createOpenSession(
GeckoSessionSettings.Builder(mainSession.settings)
.contextId("1")
.build())
session3.loadTestPath(STORAGE_TITLE_HTML_PATH)
session3.waitForPageStop()
session3.forCallbacksDuringWait(object: Callbacks.ContentDelegate {
@AssertCalled(count = 1)
override fun onTitleChange(session: GeckoSession, title: String?) {
assertThat("Title should not be empty", title, not(isEmptyOrNullString()))
assertThat("Title should match", title,
equalTo("storage=null"))
}
})
}
}

View File

@ -87,6 +87,12 @@ public final class GeckoRuntime implements Parcelable {
*/
public static final String EXTRA_CRASH_FATAL = "fatal";
private final StorageController mStorageController;
private GeckoRuntime() {
mStorageController = new StorageController();
}
private static GeckoRuntime sDefaultRuntime;
/**
@ -452,6 +458,17 @@ public final class GeckoRuntime implements Parcelable {
GeckoScreenOrientation.getInstance().update(newOrientation);
}
/**
* Get the storage controller for this runtime.
*
* @return The {@link StorageController} for this instance.
*/
@AnyThread
public @NonNull StorageController getStorageController() {
return mStorageController;
}
@Override // Parcelable
@AnyThread
public int describeContents() {

View File

@ -86,6 +86,10 @@ public final class GeckoSessionSettings implements Parcelable {
* between sessions, only sessions that share the same ID share storage
* data.
*
* Warning: Storage data is collected persistently for each context,
* to delete context data, call {@link StorageController#clearSessionContextData}
* for the given context.
*
* @param value The custom context ID.
* The default ID is null, which removes isolation for this
* instance.

View File

@ -0,0 +1,56 @@
/* -*- Mode: Java; c-basic-offset: 4; tab-width: 20; indent-tabs-mode: nil; -*-
* vim: ts=4 sw=4 expandtab:
* 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/. */
package org.mozilla.geckoview;
import android.support.annotation.AnyThread;
import android.support.annotation.NonNull;
import org.mozilla.gecko.EventDispatcher;
import org.mozilla.gecko.util.GeckoBundle;
/**
* Manage and control runtime storage data.
*
* Retrieve an instance via {@link GeckoRuntime#getStorageController}.
*/
public final class StorageController {
/**
* Clear all browser storage data like cookies and localStorage for the
* given context.
*
* Note: Any open session may re-accumulate previously cleared data. To
* ensure that no persistent data is left behind, you need to close all
* sessions for the given context prior to clearing data.
*
* @param contextId The context ID for the storage data to be deleted.
* For null, all storage data will be cleared.
*/
@AnyThread
public void clearSessionContextData(final @NonNull String contextId) {
final GeckoBundle bundle = new GeckoBundle(1);
bundle.putString("contextId", contextId);
EventDispatcher.getInstance().dispatch(
"GeckoView:ClearSessionContextData", bundle);
}
/**
* Clear all browser storage data like cookies and localStorage.
*
* Note: Any open session may re-accumulate previously cleared data. To
* ensure that no persistent data is left behind, you need to close all
* sessions prior to clearing data.
*/
@AnyThread
public void clearAllSessionContextData() {
final GeckoBundle bundle = new GeckoBundle(1);
bundle.putString("contextId", null);
EventDispatcher.getInstance().dispatch(
"GeckoView:ClearSessionContextData", bundle);
}
}

View File

@ -63,6 +63,14 @@ exclude: true
- [`GeckoView`][65.5] will not create a [`GeckoSession`][65.9] anymore when
attached to a window without a session.
- Added API for session context assignment
[`GeckoSessionSettings.Builder.contextId`][68.14] and deletion of data
related to a session context
[`StorageController.clearSessionContextData`][68.15].
[68.14]: ../GeckoSessionSettings.Builder.html#contextId-
[68.15]: ../StorageController.html#clearSessionContextData-java.lang.String-
## v67
- Added [`setAutomaticFontSizeAdjustment`][67.2] to
[`GeckoRuntimeSettings`][67.3] for automatically adjusting font size settings
@ -269,4 +277,4 @@ exclude: true
[65.24]: ../CrashReporter.html#sendCrashReport-android.content.Context-android.os.Bundle-java.lang.String-
[65.25]: ../GeckoResult.html
[api-version]: 7cba6fdca8edb1858d73704a06dad936f78c9f64
[api-version]: fa2863734daac0ec5cb0671b030139de3aac5029