зеркало из https://github.com/mozilla/gecko-dev.git
Bug 1567549 - Added overloads to GeckoSession.loadUri() that accept additional HTTP request headers r=geckoview-reviewers,snorp,mayhemer
Adds overloads to GeckoSession.loadUri() that accept additional HTTP request headers Differential Revision: https://phabricator.services.mozilla.com/D40951 --HG-- extra : moz-landing-system : lando
This commit is contained in:
Родитель
6333d847ea
Коммит
73adec6cbf
|
@ -479,12 +479,17 @@ package org.mozilla.geckoview {
|
|||
method @AnyThread public void loadData(@NonNull byte[], @Nullable String);
|
||||
method @AnyThread public void loadString(@NonNull String, @Nullable String);
|
||||
method @AnyThread public void loadUri(@NonNull String);
|
||||
method @AnyThread public void loadUri(@NonNull String, @Nullable Map<String,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 String, int, @Nullable Map<String,String>);
|
||||
method @AnyThread public void loadUri(@NonNull String, @Nullable GeckoSession, int);
|
||||
method @AnyThread public void loadUri(@NonNull String, @Nullable GeckoSession, int, @Nullable Map<String,String>);
|
||||
method @AnyThread public void loadUri(@NonNull Uri);
|
||||
method @AnyThread public void loadUri(@NonNull Uri, @Nullable Map<String,String>);
|
||||
method @AnyThread public void loadUri(@NonNull Uri, int);
|
||||
method @AnyThread public void loadUri(@NonNull Uri, @Nullable Uri, int);
|
||||
method @AnyThread public void loadUri(@NonNull Uri, @Nullable Uri, int, @Nullable Map<String,String>);
|
||||
method @UiThread public void open(@NonNull GeckoRuntime);
|
||||
method @AnyThread public void readFromParcel(@NonNull Parcel);
|
||||
method @UiThread public void releaseDisplay(@NonNull GeckoDisplay);
|
||||
|
|
|
@ -21,6 +21,7 @@ import org.mozilla.geckoview.test.util.Callbacks
|
|||
|
||||
import android.support.test.filters.MediumTest
|
||||
import android.support.test.runner.AndroidJUnit4
|
||||
import org.hamcrest.MatcherAssert
|
||||
import org.hamcrest.Matchers.*
|
||||
import org.json.JSONObject
|
||||
import org.junit.After
|
||||
|
@ -1207,6 +1208,63 @@ class NavigationDelegateTest : BaseSessionTest() {
|
|||
})
|
||||
}
|
||||
|
||||
@Test fun loadUriHeader() {
|
||||
val headers = mapOf<String, String>("Header1" to "Value", "Header2" to "Value1, Value2")
|
||||
|
||||
sessionRule.session.loadUri("$TEST_ENDPOINT/anything", headers)
|
||||
sessionRule.session.waitForPageStop()
|
||||
|
||||
val content = sessionRule.session.evaluateJS("document.body.children[0].innerHTML") as String
|
||||
val body = JSONObject(content)
|
||||
|
||||
MatcherAssert.assertThat("Headers should match", body.getJSONObject("headers")
|
||||
.getString("Header1"), equalTo("Value"))
|
||||
MatcherAssert.assertThat("Headers should match", body.getJSONObject("headers")
|
||||
.getString("Header2"), equalTo("Value1, Value2"))
|
||||
}
|
||||
|
||||
@Test fun loadUriHeaderBadOverrides() {
|
||||
val headers = mapOf<String?, String?>(
|
||||
null to "BadNull",
|
||||
"Connection" to "BadConnection",
|
||||
"Host" to "BadHost",
|
||||
"ValueLess1" to "",
|
||||
"ValueLess2" to null,
|
||||
"ValueLess3" to " ",
|
||||
"ValueLess4" to "\t")
|
||||
|
||||
sessionRule.session.loadUri("$TEST_ENDPOINT/anything", headers)
|
||||
sessionRule.session.waitForPageStop()
|
||||
|
||||
val content = sessionRule.session.evaluateJS("document.body.children[0].innerHTML") as String
|
||||
val body = JSONObject(content)
|
||||
val headersJSON = body.getJSONObject("headers")
|
||||
|
||||
headersJSON.keys().forEach { key ->
|
||||
MatcherAssert.assertThat( "No value field should be empty or null",
|
||||
headersJSON.optString(key), not(isEmptyOrNullString()))
|
||||
MatcherAssert.assertThat( "No value field should be only whitespace",
|
||||
headersJSON.getString(key).trim(), not(isEmptyOrNullString()))
|
||||
MatcherAssert.assertThat( "BadNull should not exist as a header value",
|
||||
headersJSON.getString(key), not("BadNull"))
|
||||
}
|
||||
|
||||
MatcherAssert.assertThat("Headers should not match", headersJSON
|
||||
.getString("Connection"), not("BadConnection"))
|
||||
MatcherAssert.assertThat("Headers should not match", headersJSON
|
||||
.getString("Host"), not("BadHost"))
|
||||
|
||||
// As per RFC7230 all request headers must have a field value (Except Host, which we filter)
|
||||
// RFC7230 makes RFC2616 obsolete but 2616 allowed empty field values.
|
||||
MatcherAssert.assertThat("Header with no field value should not be included",
|
||||
!headersJSON.has("ValueLess1"))
|
||||
MatcherAssert.assertThat("Header with no field value should not be included",
|
||||
!headersJSON.has("ValueLess2"))
|
||||
MatcherAssert.assertThat("Header with no field value should not be included",
|
||||
!headersJSON.has("ValueLess3"))
|
||||
MatcherAssert.assertThat("Header with no field value should not be included",
|
||||
!headersJSON.has("ValueLess4"))
|
||||
}
|
||||
|
||||
@Test(expected = GeckoResult.UncaughtException::class)
|
||||
fun onNewSession_doesNotAllowOpened() {
|
||||
|
|
|
@ -10,10 +10,12 @@ import java.lang.annotation.Retention;
|
|||
import java.lang.annotation.RetentionPolicy;
|
||||
import java.lang.ref.WeakReference;
|
||||
import java.util.AbstractSequentialList;
|
||||
import java.util.ArrayList;
|
||||
import java.util.HashMap;
|
||||
import java.util.Iterator;
|
||||
import java.util.List;
|
||||
import java.util.ListIterator;
|
||||
import java.util.Map;
|
||||
import java.util.NoSuchElementException;
|
||||
import java.util.UUID;
|
||||
|
||||
|
@ -1586,13 +1588,45 @@ public class GeckoSession implements Parcelable {
|
|||
*/
|
||||
public static final int LOAD_FLAGS_REPLACE_HISTORY = 1 << 6;
|
||||
|
||||
/**
|
||||
* Formats the map of additional request headers into an ArrayList
|
||||
* @param additionalHeaders Request headers to be formatted
|
||||
* @return Correctly formatted request headers as a ArrayList
|
||||
*/
|
||||
private ArrayList<String> additionalHeadersToStringArray(final @NonNull Map<String, String> additionalHeaders) {
|
||||
ArrayList<String> headers = new ArrayList<String>();
|
||||
for (String key : additionalHeaders.keySet()) {
|
||||
// skip null key if one exists
|
||||
if (key == null)
|
||||
continue;
|
||||
|
||||
String value = additionalHeaders.get(key);
|
||||
|
||||
// As per RFC7230 headers must contain a field value
|
||||
if (value != null && !value.equals("")) {
|
||||
headers.add( String.format("%s:%s", key, additionalHeaders.get(key)) );
|
||||
}
|
||||
}
|
||||
return headers;
|
||||
}
|
||||
|
||||
/**
|
||||
* Load the given URI.
|
||||
* @param uri The URI of the resource to load.
|
||||
*/
|
||||
@AnyThread
|
||||
public void loadUri(final @NonNull String uri) {
|
||||
loadUri(uri, (GeckoSession)null, LOAD_FLAGS_NONE);
|
||||
loadUri(uri, (GeckoSession)null, LOAD_FLAGS_NONE, (Map<String, String>) null);
|
||||
}
|
||||
|
||||
/**
|
||||
* Load the given URI with specified HTTP request headers.
|
||||
* @param uri The URI of the resource to load.
|
||||
* @param additionalHeaders any additional request headers used with the load
|
||||
*/
|
||||
@AnyThread
|
||||
public void loadUri(final @NonNull String uri, final @Nullable Map<String, String> additionalHeaders) {
|
||||
loadUri(uri, (GeckoSession)null, LOAD_FLAGS_NONE, additionalHeaders);
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -1603,7 +1637,7 @@ public class GeckoSession implements Parcelable {
|
|||
*/
|
||||
@AnyThread
|
||||
public void loadUri(final @NonNull String uri, final @LoadFlags int flags) {
|
||||
loadUri(uri, (GeckoSession)null, flags);
|
||||
loadUri(uri, (GeckoSession)null, flags, (Map<String, String>) null);
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -1616,6 +1650,20 @@ public class GeckoSession implements Parcelable {
|
|||
@AnyThread
|
||||
public void loadUri(final @NonNull String uri, final @Nullable String referrer,
|
||||
final @LoadFlags int flags) {
|
||||
loadUri(uri, referrer, flags, (Map<String, String>) null);
|
||||
}
|
||||
|
||||
/**
|
||||
* Load the given URI with the specified referrer, load type and HTTP request headers.
|
||||
*
|
||||
* @param uri the URI to load
|
||||
* @param referrer the referrer, may be null
|
||||
* @param flags the load flags to use, an OR-ed value of {@link #LOAD_FLAGS_NONE LOAD_FLAGS_*}
|
||||
* @param additionalHeaders any additional request headers used with the load
|
||||
*/
|
||||
@AnyThread
|
||||
public void loadUri(final @NonNull String uri, final @Nullable String referrer,
|
||||
final @LoadFlags int flags, final @Nullable Map<String, String> additionalHeaders) {
|
||||
final GeckoBundle msg = new GeckoBundle();
|
||||
msg.putString("uri", uri);
|
||||
msg.putInt("flags", flags);
|
||||
|
@ -1623,6 +1671,10 @@ public class GeckoSession implements Parcelable {
|
|||
if (referrer != null) {
|
||||
msg.putString("referrerUri", referrer);
|
||||
}
|
||||
|
||||
if (additionalHeaders != null) {
|
||||
msg.putStringArray("headers", additionalHeadersToStringArray(additionalHeaders));
|
||||
}
|
||||
mEventDispatcher.dispatch("GeckoView:LoadUri", msg);
|
||||
}
|
||||
|
||||
|
@ -1638,6 +1690,22 @@ public class GeckoSession implements Parcelable {
|
|||
@AnyThread
|
||||
public void loadUri(final @NonNull String uri, final @Nullable GeckoSession referrer,
|
||||
final @LoadFlags int flags) {
|
||||
loadUri(uri, referrer, flags, (Map<String, String>) null);
|
||||
}
|
||||
|
||||
/**
|
||||
* Load the given URI with the specified referrer, load type and HTTP request headers. 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_*}
|
||||
* @param additionalHeaders any additional request headers used with the load
|
||||
*/
|
||||
@AnyThread
|
||||
public void loadUri(final @NonNull String uri, final @Nullable GeckoSession referrer,
|
||||
final @LoadFlags int flags, final @Nullable Map<String, String> additionalHeaders) {
|
||||
final GeckoBundle msg = new GeckoBundle();
|
||||
msg.putString("uri", uri);
|
||||
msg.putInt("flags", flags);
|
||||
|
@ -1645,6 +1713,10 @@ public class GeckoSession implements Parcelable {
|
|||
if (referrer != null) {
|
||||
msg.putString("referrerSessionId", referrer.mId);
|
||||
}
|
||||
|
||||
if (additionalHeaders != null) {
|
||||
msg.putStringArray("headers", additionalHeadersToStringArray(additionalHeaders));
|
||||
}
|
||||
mEventDispatcher.dispatch("GeckoView:LoadUri", msg);
|
||||
}
|
||||
|
||||
|
@ -1654,7 +1726,17 @@ public class GeckoSession implements Parcelable {
|
|||
*/
|
||||
@AnyThread
|
||||
public void loadUri(final @NonNull Uri uri) {
|
||||
loadUri(uri, null, LOAD_FLAGS_NONE);
|
||||
loadUri(uri.toString(), (GeckoSession)null, LOAD_FLAGS_NONE, (Map<String, String>) null);
|
||||
}
|
||||
|
||||
/**
|
||||
* Load the given URI with specified HTTP request headers.
|
||||
* @param uri The URI of the resource to load.
|
||||
* @param additionalHeaders any additional request headers used with the load
|
||||
*/
|
||||
@AnyThread
|
||||
public void loadUri(final @NonNull Uri uri, final @Nullable Map<String, String> additionalHeaders) {
|
||||
loadUri(uri.toString(), (GeckoSession)null, LOAD_FLAGS_NONE, additionalHeaders);
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -1664,7 +1746,7 @@ public class GeckoSession implements Parcelable {
|
|||
*/
|
||||
@AnyThread
|
||||
public void loadUri(final @NonNull Uri uri, final @LoadFlags int flags) {
|
||||
loadUri(uri.toString(), (GeckoSession)null, flags);
|
||||
loadUri(uri.toString(), (GeckoSession)null, flags, (Map<String, String>) null);
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -1676,7 +1758,20 @@ public class GeckoSession implements Parcelable {
|
|||
@AnyThread
|
||||
public void loadUri(final @NonNull Uri uri, final @Nullable Uri referrer,
|
||||
final @LoadFlags int flags) {
|
||||
loadUri(uri.toString(), referrer != null ? referrer.toString() : null, flags);
|
||||
loadUri(uri.toString(), referrer != null ? referrer.toString() : null, flags, (Map<String, String>) null);
|
||||
}
|
||||
|
||||
/**
|
||||
* Load the given URI with the specified referrer, load type and HTTP request headers.
|
||||
* @param uri the URI to load
|
||||
* @param referrer the Uri to use as the referrer
|
||||
* @param flags the load flags to use, an OR-ed value of {@link #LOAD_FLAGS_NONE LOAD_FLAGS_*}
|
||||
* @param additionalHeaders any additional request headers used with the load
|
||||
*/
|
||||
@AnyThread
|
||||
public void loadUri(final @NonNull Uri uri, final @Nullable Uri referrer,
|
||||
final @LoadFlags int flags, final @Nullable Map<String, String> additionalHeaders) {
|
||||
loadUri(uri.toString(), referrer != null ? referrer.toString() : null, flags, additionalHeaders);
|
||||
}
|
||||
|
||||
/**
|
||||
|
|
|
@ -20,12 +20,15 @@ exclude: true
|
|||
`onTelemetryReceived` has been renamed to [`onHistogram`][71.4], and
|
||||
[`Metric`][71.5] now takes a type parameter.
|
||||
([bug 1576730]({{bugzilla}}1576730))
|
||||
- Added overloads of [`GeckoSession.loadUri()`][71.6] that accept a map of
|
||||
additional HTTP request headers.
|
||||
|
||||
[71.1]: {{javadoc_uri}}/RuntimeTelemetry.Delegate.html#onBooleanScalar-org.mozilla.geckoview.RuntimeTelemetry.Metric-
|
||||
[71.2]: {{javadoc_uri}}/RuntimeTelemetry.Delegate.html#onLongScalar-org.mozilla.geckoview.RuntimeTelemetry.Metric-
|
||||
[71.3]: {{javadoc_uri}}/RuntimeTelemetry.Delegate.html#onStringScalar-org.mozilla.geckoview.RuntimeTelemetry.Metric-
|
||||
[71.4]: {{javadoc_uri}}/RuntimeTelemetry.Delegate.html#onHistogram-org.mozilla.geckoview.RuntimeTelemetry.Metric-
|
||||
[71.5]: {{javadoc_uri}}/RuntimeTelemetry.Metric.html
|
||||
[71.6]: {{javadoc_uri}}/GeckoSession.html#loadUri-java.lang.String-java.io.File-java.util.Map-
|
||||
|
||||
## v70
|
||||
- Added API for session context assignment
|
||||
|
@ -348,4 +351,4 @@ exclude: true
|
|||
[65.24]: {{javadoc_uri}}/CrashReporter.html#sendCrashReport-android.content.Context-android.os.Bundle-java.lang.String-
|
||||
[65.25]: {{javadoc_uri}}/GeckoResult.html
|
||||
|
||||
[api-version]: c35dda98b313f389d0bb297a1226c801035f7c77
|
||||
[api-version]: ccc454a846e5d3c22667842aecbbdef182524f94
|
||||
|
|
|
@ -101,7 +101,7 @@ class GeckoViewNavigation extends GeckoViewModule {
|
|||
this.browser.gotoIndex(aData.index);
|
||||
break;
|
||||
case "GeckoView:LoadUri":
|
||||
const { uri, referrerUri, referrerSessionId, flags } = aData;
|
||||
const { uri, referrerUri, referrerSessionId, flags, headers } = aData;
|
||||
|
||||
let navFlags = 0;
|
||||
|
||||
|
@ -183,6 +183,31 @@ class GeckoViewNavigation extends GeckoViewModule {
|
|||
);
|
||||
}
|
||||
|
||||
let additionalHeaders = null;
|
||||
if (headers) {
|
||||
// Filter out request headers as per discussion in Bug #1567549
|
||||
// CONNECTION: Used by Gecko to manage connections
|
||||
// HOST: Relates to how gecko will ultimately interpret the resulting resource as that
|
||||
// determines the effective request URI
|
||||
const badHeaders = ["connection", "host"];
|
||||
additionalHeaders = "";
|
||||
headers.forEach(entry => {
|
||||
const key = entry
|
||||
.split(/:/)[0]
|
||||
.toLowerCase()
|
||||
.trim();
|
||||
|
||||
if (!badHeaders.includes(key)) {
|
||||
additionalHeaders += entry + "\r\n";
|
||||
}
|
||||
});
|
||||
if (additionalHeaders != "") {
|
||||
additionalHeaders = E10SUtils.makeInputStream(additionalHeaders);
|
||||
} else {
|
||||
additionalHeaders = null;
|
||||
}
|
||||
}
|
||||
|
||||
// For any navigation here, we should have an appropriate triggeringPrincipal:
|
||||
//
|
||||
// 1) If we have a referring session, triggeringPrincipal is the contentPrincipal from the
|
||||
|
@ -203,6 +228,7 @@ class GeckoViewNavigation extends GeckoViewModule {
|
|||
flags: navFlags,
|
||||
referrerInfo,
|
||||
triggeringPrincipal,
|
||||
headers: additionalHeaders,
|
||||
csp,
|
||||
});
|
||||
break;
|
||||
|
|
Загрузка…
Ссылка в новой задаче