Bug 1561079 - Add a `GeckoSession.loadUri()` overload that takes a referring `GeckoSession` r=geckoview-reviewers,ckerschb,esawin,agi

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

--HG--
extra : moz-landing-system : lando
This commit is contained in:
James Willcox 2019-07-24 16:33:52 +00:00
Родитель 7ee695dd56
Коммит 3d039180df
5 изменённых файлов: 127 добавлений и 28 удалений

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

@ -427,6 +427,7 @@ package org.mozilla.geckoview {
method @AnyThread public void loadUri(@NonNull String);
method @AnyThread public void loadUri(@NonNull String, int);
method @AnyThread public void loadUri(@NonNull String, @Nullable String, int);
method @AnyThread public void loadUri(@NonNull String, @Nullable GeckoSession, int);
method @AnyThread public void loadUri(@NonNull Uri);
method @AnyThread public void loadUri(@NonNull Uri, int);
method @AnyThread public void loadUri(@NonNull Uri, @Nullable Uri, int);

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

@ -1174,6 +1174,40 @@ class NavigationDelegateTest : BaseSessionTest() {
equalTo(referrer))
}
@Test fun loadUriReferrerSession() {
val uri = "https://example.com/bar"
val referrer = "https://example.org/foo"
sessionRule.session.loadUri(referrer)
sessionRule.session.waitForPageStop()
val newSession = sessionRule.createOpenSession()
newSession.loadUri(uri, sessionRule.session, GeckoSession.LOAD_FLAGS_NONE)
newSession.waitForPageStop()
assertThat("Referrer should match",
newSession.evaluateJS("document.referrer") as String,
equalTo(referrer))
}
@Test fun loadUriReferrerSessionFileUrl() {
val uri = "file:///system/etc/fonts.xml"
val referrer = "https://example.org"
sessionRule.session.loadUri(referrer)
sessionRule.session.waitForPageStop()
val newSession = sessionRule.createOpenSession()
newSession.loadUri(uri, sessionRule.session, GeckoSession.LOAD_FLAGS_NONE)
newSession.waitUntilCalled(object : Callbacks.NavigationDelegate {
@AssertCalled
override fun onLoadError(session: GeckoSession, uri: String?, error: WebRequestError): GeckoResult<String>? {
return null
}
})
}
@Test(expected = GeckoResult.UncaughtException::class)
fun onNewSession_doesNotAllowOpened() {
// Disable popup blocker.

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

@ -1534,7 +1534,7 @@ public class GeckoSession implements Parcelable {
*/
@AnyThread
public void loadUri(final @NonNull String uri) {
loadUri(uri, null, LOAD_FLAGS_NONE);
loadUri(uri, (GeckoSession)null, LOAD_FLAGS_NONE);
}
/**
@ -1545,7 +1545,7 @@ public class GeckoSession implements Parcelable {
*/
@AnyThread
public void loadUri(final @NonNull String uri, final @LoadFlags int flags) {
loadUri(uri, null, flags);
loadUri(uri, (GeckoSession)null, flags);
}
/**
@ -1563,7 +1563,29 @@ public class GeckoSession implements Parcelable {
msg.putInt("flags", flags);
if (referrer != null) {
msg.putString("referrer", referrer);
msg.putString("referrerUri", referrer);
}
mEventDispatcher.dispatch("GeckoView:LoadUri", msg);
}
/**
* Load the given URI with the specified referrer and load type. This method will also do any
* applicable checks to ensure that the specified URI is both safe and allowable
* according to the referring GeckoSession.
*
* @param uri the URI to load
* @param referrer the referring GeckoSession, may be null
* @param flags the load flags to use, an OR-ed value of {@link #LOAD_FLAGS_NONE LOAD_FLAGS_*}
*/
@AnyThread
public void loadUri(final @NonNull String uri, final @Nullable GeckoSession referrer,
final @LoadFlags int flags) {
final GeckoBundle msg = new GeckoBundle();
msg.putString("uri", uri);
msg.putInt("flags", flags);
if (referrer != null) {
msg.putString("referrerSessionId", referrer.mId);
}
mEventDispatcher.dispatch("GeckoView:LoadUri", msg);
}
@ -1584,7 +1606,7 @@ public class GeckoSession implements Parcelable {
*/
@AnyThread
public void loadUri(final @NonNull Uri uri, final @LoadFlags int flags) {
loadUri(uri.toString(), null, flags);
loadUri(uri.toString(), (GeckoSession)null, flags);
}
/**
@ -1613,7 +1635,7 @@ public class GeckoSession implements Parcelable {
throw new IllegalArgumentException("data cannot be null");
}
loadUri(createDataUri(data, mimeType), null, LOAD_FLAGS_NONE);
loadUri(createDataUri(data, mimeType), (GeckoSession)null, LOAD_FLAGS_NONE);
}
/**
@ -1629,7 +1651,7 @@ public class GeckoSession implements Parcelable {
throw new IllegalArgumentException("data cannot be null");
}
loadUri(createDataUri(bytes, mimeType), null, LOAD_FLAGS_FORCE_ALLOW_DATA_URI);
loadUri(createDataUri(bytes, mimeType), (GeckoSession)null, LOAD_FLAGS_FORCE_ALLOW_DATA_URI);
}
/**

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

@ -22,6 +22,10 @@ exclude: true
manage opening/closing of the `GeckoSession` and instead leave that up to the app. It's also now allowed
to call `setSession` with a closed `GeckoSession`.
- Added an overload of `GeckoSession.loadUri()` that accepts a referring `GeckoSession`. This should be used
when the URI we're loading originates from another page. A common example of this would be long pressing
a link and then opening that in a new `GeckoSession`.
## v69
- Modified behavior of ['setAutomaticFontSizeAdjustment'][69.1] so that it no
longer has any effect on ['setFontInflationEnabled'][69.2]
@ -363,4 +367,4 @@ exclude: true
[65.24]: ../CrashReporter.html#sendCrashReport-android.content.Context-android.os.Bundle-java.lang.String-
[65.25]: ../GeckoResult.html
[api-version]: d770e67f7e5b87640574810468c76208ce4c1a43
[api-version]: 1df14e65ca0dd11e84a014040c0fb3544478827f

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

@ -105,7 +105,7 @@ class GeckoViewNavigation extends GeckoViewModule {
this.browser.gotoIndex(aData.index);
break;
case "GeckoView:LoadUri":
const { uri, referrer, flags } = aData;
const { uri, referrerUri, referrerSessionId, flags } = aData;
let navFlags = 0;
@ -138,34 +138,72 @@ class GeckoViewNavigation extends GeckoViewModule {
this.moduleManager.updateRemoteTypeForURI(uri);
}
let parsedUri;
let triggeringPrincipal;
try {
parsedUri = Services.io.newURI(uri);
if (
parsedUri.schemeIs("about") ||
parsedUri.schemeIs("data") ||
parsedUri.schemeIs("file") ||
parsedUri.schemeIs("resource") ||
parsedUri.schemeIs("moz-extension")
) {
// Only allow privileged loading for certain URIs.
triggeringPrincipal = Services.scriptSecurityManager.createContentPrincipal(
parsedUri,
{}
);
}
} catch (ignored) {}
let triggeringPrincipal, referrerInfo, csp;
if (referrerSessionId) {
const referrerWindow = Services.ww.getWindowByName(
referrerSessionId,
this.window
);
triggeringPrincipal = referrerWindow.browser.contentPrincipal;
csp = referrerWindow.browser.csp;
const referrerPolicy = referrerWindow.browser.referrerInfo
? referrerWindow.browser.referrerInfo.referrerPolicy
: Ci.nsIHttpChannel.REFERRER_POLICY_UNSET;
referrerInfo = new ReferrerInfo(
referrerPolicy,
true,
referrerWindow.browser.documentURI
);
} else {
try {
const parsedUri = Services.io.newURI(uri);
if (
parsedUri.schemeIs("about") ||
parsedUri.schemeIs("data") ||
parsedUri.schemeIs("file") ||
parsedUri.schemeIs("resource") ||
parsedUri.schemeIs("moz-extension")
) {
// Only allow privileged loading for certain URIs.
triggeringPrincipal = Services.scriptSecurityManager.createContentPrincipal(
parsedUri,
{}
);
}
} catch (ignored) {}
referrerInfo = createReferrerInfo(referrerUri);
}
if (!triggeringPrincipal) {
triggeringPrincipal = Services.scriptSecurityManager.createNullPrincipal(
{}
);
}
this.browser.loadURI(parsedUri ? parsedUri.spec : uri, {
// For any navigation here, we should have an appropriate triggeringPrincipal:
//
// 1) If we have a referring session, triggeringPrincipal is the contentPrincipal from the
// referring document.
// 2) For certain URI schemes listed above, we will have a codebase principal.
// 3) In all other cases, we create a NullPrincipal.
//
// The navigation flags are driven by the app. We purposely do not propagate these from
// the referring document, but expect that the app will in most cases.
//
// The referrerInfo is derived from the referring document, if present, by propagating any
// referrer policy. If we only have the referrerUri from the app, we create a referrerInfo
// with the specified URI and no policy set. If no referrerUri is present and we have no
// referring session, the referrerInfo is null.
//
// csp is only present if we have a referring document, null otherwise.
this.browser.loadURI(uri, {
flags: navFlags,
referrerInfo: createReferrerInfo(referrer),
referrerInfo,
triggeringPrincipal,
csp,
});
break;
case "GeckoView:Reload":