Backed out 3 changesets (bug 1603452, bug 1603114, bug 1577596) for causing lint failure in GeckoSession.java CLOSED TREE

Backed out changeset 1a9be6d049a7 (bug 1577596)
Backed out changeset 11e1f382ea77 (bug 1603114)
Backed out changeset d63c194d1c6c (bug 1603452)
This commit is contained in:
Noemi Erli 2019-12-18 01:12:37 +02:00
Родитель 833a7f9e2e
Коммит 00a57ab6c7
18 изменённых файлов: 452 добавлений и 284 удалений

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

@ -70,6 +70,3 @@ pref("ui.android.mouse_as_touch", 2);
// Fenix is currently not whitelisted for Web Authentication
pref("security.webauth.webauthn_enable_android_fido2", false);
// Enable autoplay permission prompts
pref("media.geckoview.autoplay.request", true);

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

@ -777,8 +777,6 @@ package org.mozilla.geckoview {
method @UiThread default public void onAndroidPermissionsRequest(@NonNull GeckoSession, @Nullable String[], @NonNull GeckoSession.PermissionDelegate.Callback);
method @UiThread default public void onContentPermissionRequest(@NonNull GeckoSession, @Nullable String, int, @NonNull GeckoSession.PermissionDelegate.Callback);
method @UiThread default public void onMediaPermissionRequest(@NonNull GeckoSession, @NonNull String, @Nullable GeckoSession.PermissionDelegate.MediaSource[], @Nullable GeckoSession.PermissionDelegate.MediaSource[], @NonNull GeckoSession.PermissionDelegate.MediaCallback);
field public static final int PERMISSION_AUTOPLAY_AUDIBLE = 4;
field public static final int PERMISSION_AUTOPLAY_INAUDIBLE = 3;
field public static final int PERMISSION_DESKTOP_NOTIFICATION = 1;
field public static final int PERMISSION_GEOLOCATION = 0;
field public static final int PERMISSION_PERSISTENT_STORAGE = 2;

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

@ -223,13 +223,12 @@ dependencies {
testImplementation 'org.mockito:mockito-core:1.10.19'
androidTestImplementation "org.jetbrains.kotlin:kotlin-stdlib:$kotlin_version"
androidTestImplementation "org.jetbrains.kotlinx:kotlinx-coroutines-android:1.3.2"
androidTestImplementation 'com.android.support.test:runner:1.0.2'
androidTestImplementation 'com.android.support.test:rules:1.0.2'
androidTestImplementation 'com.android.support.test.espresso:espresso-core:3.0.2'
androidTestImplementation "com.android.support:support-annotations:$support_library_version"
androidTestImplementation 'com.koushikdutta.async:androidasync:2.+'
androidTestImplementation 'org.eclipse.jetty:jetty-server:7.6.21.v20160908'
}
apply from: "${topsrcdir}/mobile/android/gradle/with_gecko_binaries.gradle"

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

@ -66,8 +66,6 @@ open class BaseSessionTest(noErrorCollector: Boolean = false) {
const val PUSH_HTML_PATH = "/assets/www/push/push.html"
const val OPEN_WINDOW_PATH = "/assets/www/worker/open_window.html"
const val OPEN_WINDOW_TARGET_PATH = "/assets/www/worker/open_window_target.html"
const val TEST_ENDPOINT = GeckoSessionTestRule.TEST_ENDPOINT
}
@get:Rule val sessionRule = GeckoSessionTestRule()

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

@ -4,6 +4,7 @@
package org.mozilla.geckoview.test
import android.support.test.InstrumentationRegistry
import org.mozilla.geckoview.AllowOrDeny
import org.mozilla.geckoview.ContentBlocking
import org.mozilla.geckoview.GeckoResult
@ -23,15 +24,35 @@ import android.support.test.runner.AndroidJUnit4
import org.hamcrest.MatcherAssert
import org.hamcrest.Matchers.*
import org.json.JSONObject
import org.junit.After
import org.junit.Before
import org.junit.Ignore
import org.junit.Test
import org.junit.runner.RunWith
import org.mozilla.geckoview.test.rule.GeckoSessionTestRule
import org.mozilla.geckoview.test.util.HttpBin
import org.mozilla.geckoview.test.util.UiThreadUtils
import java.net.URI
@RunWith(AndroidJUnit4::class)
@MediumTest
class NavigationDelegateTest : BaseSessionTest() {
companion object {
val TEST_ENDPOINT: String = "http://localhost:4242"
}
lateinit var server: HttpBin
@Before
fun setup() {
server = HttpBin(InstrumentationRegistry.getTargetContext(), URI.create(TEST_ENDPOINT))
server.start()
}
@After
fun cleanup() {
server.stop()
}
fun testLoadErrorWithErrorPage(testUri: String, expectedCategory: Int,
expectedError: Int,

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

@ -16,13 +16,13 @@ import android.support.test.InstrumentationRegistry
import android.support.test.filters.MediumTest
import android.support.test.runner.AndroidJUnit4
import org.junit.Assume.assumeThat
import org.hamcrest.Matchers.*
import org.json.JSONArray
import org.junit.Assert.fail
import org.junit.Test
import org.junit.runner.RunWith
import org.junit.Ignore
import org.mozilla.geckoview.GeckoRuntimeSettings
@RunWith(AndroidJUnit4::class)
@MediumTest
@ -260,22 +260,6 @@ class PermissionDelegateTest : BaseSessionTest() {
result as String, equalTo("denied"))
}
@Test
fun autoplayReject() {
sessionRule.runtime.settings.autoplayDefault = GeckoRuntimeSettings.AUTOPLAY_DEFAULT_BLOCKED
mainSession.loadTestPath(AUTOPLAY_PATH)
mainSession.waitUntilCalled(object : Callbacks.PermissionDelegate {
@AssertCalled(count = 2)
override fun onContentPermissionRequest(session: GeckoSession, uri: String?, type: Int, callback: GeckoSession.PermissionDelegate.Callback) {
val expectedType = if (sessionRule.currentCall.counter == 1) GeckoSession.PermissionDelegate.PERMISSION_AUTOPLAY_AUDIBLE else GeckoSession.PermissionDelegate.PERMISSION_AUTOPLAY_INAUDIBLE
assertThat("Type should match", type, equalTo(expectedType))
callback.reject()
}
})
}
// @Test fun persistentStorage() {
// mainSession.loadTestPath(HELLO_HTML_PATH)
// mainSession.waitForPageStop()

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

@ -13,11 +13,11 @@ import android.support.test.InstrumentationRegistry
import android.support.test.filters.MediumTest
import android.support.test.filters.SdkSuppress
import android.support.test.runner.AndroidJUnit4
import kotlinx.coroutines.Dispatchers
import kotlinx.coroutines.runBlocking
import java.math.BigInteger
import java.net.URI
import java.nio.ByteBuffer
import java.nio.CharBuffer
import java.nio.charset.Charset
@ -35,10 +35,14 @@ import org.junit.*
import org.junit.rules.ExpectedException
import org.junit.runner.RunWith
import org.junit.Ignore
import org.mozilla.geckoview.*
import org.mozilla.geckoview.GeckoWebExecutor
import org.mozilla.geckoview.WebRequest
import org.mozilla.geckoview.WebRequestError
import org.mozilla.geckoview.WebResponse
import org.mozilla.geckoview.test.util.HttpBin
import org.mozilla.geckoview.test.util.RuntimeCreator
import org.mozilla.geckoview.test.util.TestServer
import java.io.IOException
import java.net.UnknownHostException
import java.util.*
@ -47,12 +51,11 @@ import java.util.*
@RunWith(AndroidJUnit4::class)
class WebExecutorTest {
companion object {
const val TEST_PORT: Int = 4242
const val TEST_ENDPOINT: String = "http://localhost:${TEST_PORT}"
val TEST_ENDPOINT: String = "http://localhost:4242"
}
lateinit var executor: GeckoWebExecutor
lateinit var server: TestServer
lateinit var server: HttpBin
@get:Rule val thrown = ExpectedException.none()
@ -62,12 +65,15 @@ class WebExecutorTest {
// the tests which are not using @UiThreadTest, so we do that
// ourselves here as GeckoRuntime needs to be initialized
// on the UI thread.
runBlocking(Dispatchers.Main) {
val latch = CountDownLatch(1)
Handler(Looper.getMainLooper()).post {
executor = GeckoWebExecutor(RuntimeCreator.getRuntime())
server = HttpBin(InstrumentationRegistry.getTargetContext(), URI.create(TEST_ENDPOINT))
server.start()
latch.countDown()
}
server = TestServer(InstrumentationRegistry.getTargetContext())
server.start(TEST_PORT)
latch.await()
}
@After
@ -92,9 +98,7 @@ class WebExecutorTest {
}
fun WebResponse.getBodyBytes(): ByteBuffer {
body!!.use {
return ByteBuffer.wrap(it.readBytes())
}
return ByteBuffer.wrap(body!!.readBytes())
}
fun WebResponse.getJSONBody(): JSONObject {
@ -136,7 +140,7 @@ class WebExecutorTest {
assertThat("URI should match", response.uri, equalTo(uri))
assertThat("Status could should match", response.statusCode, equalTo(200))
assertThat("Content type should match", response.headers["Content-Type"], equalTo("application/json; charset=utf-8"))
assertThat("Content type should match", response.headers["Content-Type"], equalTo("application/json"))
assertThat("Redirected should match", response.redirected, equalTo(false))
val body = response.getJSONBody()
@ -156,9 +160,9 @@ class WebExecutorTest {
}
@Test
fun testStatus() {
val response = fetch(WebRequest("$TEST_ENDPOINT/status/500"))
assertThat("Status code should match", response.statusCode, equalTo(500))
fun test404() {
val response = fetch(WebRequest("$TEST_ENDPOINT/status/404"))
assertThat("Status code should match", response.statusCode, equalTo(404))
}
@Test
@ -318,7 +322,7 @@ class WebExecutorTest {
@Test(expected = IOException::class)
fun readClosedStream() {
val response = executor.fetch(WebRequest("$TEST_ENDPOINT/bytes/1024")).pollDefault()!!
val response = executor.fetch(WebRequest("$TEST_ENDPOINT/anything")).pollDefault()!!
assertThat("Status code should match", response.statusCode, equalTo(200))
@ -327,10 +331,11 @@ class WebExecutorTest {
stream.readBytes()
}
@Ignore //bug 1596314 - disable test for frequent failures
@Test(expected = IOException::class)
fun readTimeout() {
val expectedCount = 10
val response = executor.fetch(WebRequest("$TEST_ENDPOINT/trickle/${expectedCount}")).pollDefault()!!
val expectedCount = 1 * 1024 * 1024 // 1MB
val response = executor.fetch(WebRequest("$TEST_ENDPOINT/bytes/$expectedCount")).pollDefault()!!
assertThat("Status code should match", response.statusCode, equalTo(200))
assertThat("Content-Length should match", response.headers["Content-Length"]!!.toInt(), equalTo(expectedCount))

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

@ -23,7 +23,7 @@ import org.mozilla.geckoview.*
import org.mozilla.geckoview.test.rule.GeckoSessionTestRule
import org.mozilla.geckoview.test.rule.GeckoSessionTestRule.AssertCalled
import org.mozilla.geckoview.test.util.Callbacks
import org.mozilla.geckoview.test.util.TestServer
import org.mozilla.geckoview.test.util.HttpBin
import java.net.URI
import java.util.UUID
@ -32,8 +32,7 @@ import java.util.UUID
@MediumTest
class WebExtensionTest : BaseSessionTest() {
companion object {
val TEST_PORT: Int = 4243
val TEST_ENDPOINT: String = "http://localhost:${TEST_PORT}"
val TEST_ENDPOINT: String = "http://localhost:4243"
val TABS_CREATE_BACKGROUND: String = "resource://android/assets/web_extensions/tabs-create/"
val TABS_CREATE_REMOVE_BACKGROUND: String = "resource://android/assets/web_extensions/tabs-create-remove/"
val TABS_REMOVE_BACKGROUND: String = "resource://android/assets/web_extensions/tabs-remove/"
@ -686,16 +685,16 @@ class WebExtensionTest : BaseSessionTest() {
@Test
fun iframeTopLevel() {
val server = TestServer(InstrumentationRegistry.getTargetContext())
val httpBin = HttpBin(InstrumentationRegistry.getTargetContext(), URI.create(TEST_ENDPOINT))
try {
server.start(TEST_PORT)
httpBin.start()
mainSession.loadUri("$TEST_ENDPOINT$HELLO_IFRAME_HTML_PATH")
sessionRule.waitForPageStop()
testIframeTopLevel()
} finally {
server.stop()
httpBin.stop()
}
}

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

@ -20,7 +20,7 @@ import org.mozilla.geckoview.GeckoSessionSettings;
import org.mozilla.geckoview.RuntimeTelemetry;
import org.mozilla.geckoview.SessionTextInput;
import org.mozilla.geckoview.WebExtension;
import org.mozilla.geckoview.test.util.TestServer;
import org.mozilla.geckoview.test.util.HttpBin;
import org.mozilla.geckoview.test.util.RuntimeCreator;
import org.mozilla.geckoview.test.util.Environment;
import org.mozilla.geckoview.test.util.UiThreadUtils;
@ -64,6 +64,7 @@ import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
import java.lang.reflect.ParameterizedType;
import java.lang.reflect.Proxy;
import java.net.URI;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collection;
@ -88,9 +89,7 @@ import kotlin.reflect.KClass;
*/
public class GeckoSessionTestRule implements TestRule {
private static final String LOGTAG = "GeckoSessionTestRule";
private static final int TEST_PORT = 4245;
public static final String TEST_ENDPOINT = "http://localhost:" + TEST_PORT;
public static final String TEST_ENDPOINT = "http://localhost:4245";
private static final Method sOnPageStart;
private static final Method sOnPageStop;
@ -1236,11 +1235,12 @@ public class GeckoSessionTestRule implements TestRule {
public void evaluate() throws Throwable {
final AtomicReference<Throwable> exceptionRef = new AtomicReference<>();
TestServer server = new TestServer(InstrumentationRegistry.getTargetContext());
HttpBin httpBin = new HttpBin(InstrumentationRegistry.getTargetContext(),
URI.create(TEST_ENDPOINT));
mInstrumentation.runOnMainSync(() -> {
try {
server.start(TEST_PORT);
httpBin.start();
RuntimeCreator.setPortDelegate(mPortDelegate);
@ -1273,7 +1273,7 @@ public class GeckoSessionTestRule implements TestRule {
exceptionRef.set(t);
} finally {
try {
server.stop();
httpBin.stop();
cleanupStatement();
} catch (Throwable t) {
exceptionRef.compareAndSet(null, t);

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

@ -0,0 +1,156 @@
/*
* Copyright 2015-2016 Bounce Storage, Inc. <info@bouncestorage.com>
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.mozilla.geckoview.test.util;
import android.content.Context;
import android.os.StrictMode;
import android.support.annotation.NonNull;
import android.util.Log;
import java.net.URI;
import org.eclipse.jetty.server.Server;
import org.eclipse.jetty.util.log.AbstractLogger;
import org.eclipse.jetty.util.log.Logger;
import org.eclipse.jetty.util.thread.ExecutorThreadPool;
/**
* Reimplementation of HttpBin http://httpbin.org/ suitable for offline unit
* tests.
*/
public final class HttpBin {
private static final String LOGTAG = "HttpBin";
private final Server mServer;
static {
org.eclipse.jetty.util.log.Log.setLog(new AndroidLogger());
}
public HttpBin(@NonNull Context context, @NonNull URI endpoint) {
this(endpoint, new HttpBinHandler(context));
}
public HttpBin(@NonNull URI endpoint, @NonNull HttpBinHandler handler) {
StrictMode.setThreadPolicy(new StrictMode.ThreadPolicy.Builder(
StrictMode.getThreadPolicy())
.permitNetwork()
.build());
mServer = new Server(endpoint.getPort());
mServer.setHandler(handler);
}
public void start() throws Exception {
mServer.start();
}
public void stop() throws Exception {
mServer.stop();
}
public int getPort() {
return mServer.getConnectors()[0].getLocalPort();
}
// We need this because the default Logger tries to use some things
// that don't exist in older versions of Android
private static class AndroidLogger extends AbstractLogger {
private boolean mDebugEnabled;
@Override
protected Logger newLogger(String fullname) {
return this;
}
@Override
public String getName() {
return null;
}
@Override
public void warn(String msg, Object... args) {
Log.w(LOGTAG, String.format(msg, args));
}
@Override
public void warn(Throwable thrown) {
Log.w(LOGTAG, thrown);
}
@Override
public void warn(String msg, Throwable thrown) {
Log.w(LOGTAG, msg, thrown);
}
@Override
public void info(String msg, Object... args) {
Log.i(LOGTAG, String.format(msg, args));
}
@Override
public void info(Throwable thrown) {
Log.i(LOGTAG, thrown.getMessage(), thrown);
}
@Override
public void info(String msg, Throwable thrown) {
Log.i(LOGTAG, msg, thrown);
}
@Override
public boolean isDebugEnabled() {
return mDebugEnabled;
}
@Override
public void setDebugEnabled(boolean enabled) {
mDebugEnabled = enabled;
}
@Override
public void debug(String msg, Object... args) {
if (mDebugEnabled) {
Log.d(LOGTAG, String.format(msg, args));
}
}
@Override
public void debug(Throwable thrown) {
if (mDebugEnabled) {
Log.d(LOGTAG, thrown.getMessage(), thrown);
}
}
@Override
public void debug(String msg, Throwable thrown) {
if (mDebugEnabled) {
Log.d(LOGTAG, msg, thrown);
}
}
@Override
public void ignore(Throwable ignored) {
// This is pretty spammy
if (mDebugEnabled) {
Log.w(LOGTAG, "Ignored Exception: ", ignored);
}
}
};
}

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

@ -0,0 +1,226 @@
/*
* Copyright 2015-2016 Bounce Storage, Inc. <info@bouncestorage.com>
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.mozilla.geckoview.test.util;
import android.content.Context;
import android.content.res.AssetManager;
import android.support.annotation.NonNull;
import android.support.annotation.Nullable;
import android.util.Log;
import java.io.ByteArrayOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.math.BigInteger;
import java.security.MessageDigest;
import java.security.NoSuchAlgorithmException;
import java.util.Enumeration;
import java.util.Random;
import javax.servlet.http.Cookie;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import org.eclipse.jetty.server.Request;
import org.eclipse.jetty.server.handler.AbstractHandler;
import org.json.JSONException;
import org.json.JSONObject;
class HttpBinHandler extends AbstractHandler {
private static final String LOGTAG = "HttpBinHandler";
private static final int BUFSIZE = 4096;
private AssetManager mAssets;
public HttpBinHandler(@NonNull Context context) {
super();
mAssets = context.getResources().getAssets();
}
private static void pipe(final @NonNull InputStream is) throws IOException {
pipe(is, null);
}
private static void pipe(final @NonNull InputStream is, final @Nullable OutputStream os)
throws IOException {
final byte[] buf = new byte[BUFSIZE];
int count = 0;
while ((count = is.read(buf)) > 0) {
if (os != null) {
os.write(buf, 0, count);
}
}
}
private void respondJSON(HttpServletResponse response, OutputStream os, JSONObject obj)
throws IOException {
final byte[] body = obj.toString().getBytes();
response.setContentLength(body.length);
response.setContentType("application/json");
response.setStatus(HttpServletResponse.SC_OK);
os.write(body);
os.flush();
}
private void redirectTo(HttpServletResponse response, String location) {
response.setHeader("Location", location);
response.setStatus(HttpServletResponse.SC_MOVED_TEMPORARILY);
}
@Override
@SuppressWarnings("unchecked")
public void handle(String target, Request baseRequest,
HttpServletRequest request, HttpServletResponse servletResponse)
throws IOException {
String method = request.getMethod();
String uri = request.getRequestURI();
try (InputStream is = request.getInputStream();
OutputStream os = servletResponse.getOutputStream()) {
if (method.equals("GET") && uri.startsWith("/status/")) {
pipe(is);
int status = Integer.parseInt(uri.substring(
"/status/".length()));
servletResponse.setStatus(status);
baseRequest.setHandled(true);
} else if (uri.equals("/redirect-to")) {
pipe(is);
redirectTo(servletResponse, request.getParameter("url"));
baseRequest.setHandled(true);
} else if (uri.startsWith("/redirect/")) {
pipe(is);
int count = Integer.parseInt(uri.substring("/redirect/".length())) - 1;
if (count > 0) {
redirectTo(servletResponse, "/redirect/" + count);
} else {
servletResponse.setStatus(HttpServletResponse.SC_OK);
}
baseRequest.setHandled(true);
} else if (uri.equals("/cookies")) {
pipe(is);
final JSONObject cookies = new JSONObject();
if (request.getCookies() != null) {
for (final Cookie cookie : request.getCookies()) {
cookies.put(cookie.getName(), cookie.getValue());
}
}
final JSONObject response = new JSONObject();
response.put("cookies", cookies);
respondJSON(servletResponse, os, response);
baseRequest.setHandled(true);
} else if (uri.startsWith("/cookies/set/")) {
pipe(is);
final String[] parts = uri.substring("/cookies/set/".length()).split("/");
servletResponse.addHeader("Set-Cookie",
String.format("%s=%s; Path=/", parts[0], parts[1]));
servletResponse.setHeader("Location", "/cookies");
servletResponse.setStatus(HttpServletResponse.SC_MOVED_TEMPORARILY);
baseRequest.setHandled(true);
} else if (uri.startsWith("/basic-auth")) {
pipe(is);
// FIXME: we don't actually check the username/password here
servletResponse.addHeader("WWW-Authenticate",
"Basic realm=\"Fake Realm\"");
servletResponse.setStatus(HttpServletResponse.SC_UNAUTHORIZED);
baseRequest.setHandled(true);
} else if (uri.equals("/anything")) {
servletResponse.setStatus(HttpServletResponse.SC_OK);
baseRequest.setHandled(true);
final JSONObject response = new JSONObject();
// Method
response.put("method", method);
// Headers
final JSONObject headers = new JSONObject();
response.put("headers", headers);
for (Enumeration<String> names = request.getHeaderNames(); names.hasMoreElements();) {
final String name = names.nextElement();
headers.put(name, request.getHeader(name));
}
// Body data
final ByteArrayOutputStream data = new ByteArrayOutputStream();
pipe(is, data);
response.put("data", data.toString("UTF-8"));
respondJSON(servletResponse, os, response);
baseRequest.setHandled(true);
} else if (uri.startsWith("/bytes")) {
pipe(is);
final int count = Integer.parseInt(uri.substring("/bytes/".length()));
final Random random = new Random(System.currentTimeMillis());
final byte[] payload = new byte[count];
random.nextBytes(payload);
servletResponse.setStatus(HttpServletResponse.SC_OK);
servletResponse.setContentLength(count);
servletResponse.setContentType("application/octet-stream");
final byte[] digest = MessageDigest.getInstance("SHA-256").digest(payload);
servletResponse.addHeader("X-SHA-256",
String.format("%064x", new BigInteger(1, digest)));
os.write(payload);
os.flush();
baseRequest.setHandled(true);
} else if (uri.startsWith("/assets")) {
pipe(is);
pipe(mAssets.open(uri.substring("/assets/".length())), os);
os.flush();
baseRequest.setHandled(true);
}
if (!baseRequest.isHandled()) {
servletResponse.setStatus(501);
baseRequest.setHandled(true);
}
} catch (JSONException e) {
Log.e(LOGTAG, "JSON error while handling response", e);
servletResponse.setStatus(500);
baseRequest.setHandled(true);
} catch (NoSuchAlgorithmException e) {
Log.e(LOGTAG, "Failed to generate digest", e);
servletResponse.setStatus(500);
baseRequest.setHandled(true);
} catch (IOException e) {
Log.e(LOGTAG, "Failed to respond", e);
servletResponse.setStatus(500);
baseRequest.setHandled(true);
}
}
}

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

@ -1,144 +0,0 @@
package org.mozilla.geckoview.test.util
import android.content.Context
import android.content.res.AssetManager
import android.os.SystemClock
import android.webkit.MimeTypeMap
import com.koushikdutta.async.ByteBufferList
import com.koushikdutta.async.http.server.AsyncHttpServer
import com.koushikdutta.async.http.server.AsyncHttpServerRequest
import com.koushikdutta.async.http.server.AsyncHttpServerResponse
import com.koushikdutta.async.util.TaggedList
import org.json.JSONObject
import java.io.FileNotFoundException
import java.math.BigInteger
import java.security.MessageDigest
import java.util.*
class TestServer {
private val server = AsyncHttpServer()
private val assets: AssetManager
constructor(context: Context) {
assets = context.resources.assets
val anything = { request: AsyncHttpServerRequest, response: AsyncHttpServerResponse ->
val obj = JSONObject()
obj.put("method", request.method)
val headers = JSONObject()
for (key in request.headers.multiMap.keys) {
val values = request.headers.multiMap.get(key) as TaggedList<String>
headers.put(values.tag(), values.joinToString(", "))
}
obj.put("headers", headers)
if (request.method == "POST") {
obj.put("data", request.body.get() as String)
}
response.send(obj)
}
server.post("/anything", anything)
server.get("/anything", anything)
server.get("/assets/.*") { request, response ->
try {
val mimeType = MimeTypeMap.getSingleton()
.getMimeTypeFromExtension(MimeTypeMap.getFileExtensionFromUrl(request.path))
val name = request.path.substring("/assets/".count())
val asset = assets.open(name).readBytes()
response.send(mimeType, asset)
} catch (e: FileNotFoundException) {
response.code(404)
response.end()
}
}
server.get("/status/.*") { request, response ->
val statusCode = request.path.substring("/status/".count()).toInt()
response.code(statusCode)
response.end()
}
server.get("/redirect-to.*") { request, response ->
response.redirect(request.query.getString("url"))
}
server.get("/redirect/.*") { request, response ->
val count = request.path.split('/').last().toInt() - 1
if (count > 0) {
response.redirect("/redirect/${count}")
}
response.end()
}
server.get("/basic-auth/.*") { _, response ->
response.code(401)
response.headers.set("WWW-Authenticate", "Basic realm=\"Fake Realm\"")
response.end()
}
server.get("/cookies") { request, response ->
val cookiesObj = JSONObject()
request.headers.get("cookie")?.split(";")?.forEach {
val parts = it.trim().split('=')
cookiesObj.put(parts[0], parts[1])
}
val obj = JSONObject()
obj.put("cookies", cookiesObj)
response.send(obj)
}
server.get("/cookies/set/.*") { request, response ->
val parts = request.path.substring("/cookies/set/".count()).split('/')
response.headers.set("Set-Cookie", "${parts[0]}=${parts[1]}; Path=/")
response.headers.set("Location", "/cookies")
response.code(302)
response.end()
}
server.get("/bytes/.*") { request, response ->
val count = request.path.split("/").last().toInt()
val random = Random(System.currentTimeMillis())
val payload = ByteArray(count)
random.nextBytes(payload)
val digest = MessageDigest.getInstance("SHA-256").digest(payload)
response.headers.set("X-SHA-256", String.format("%064x", BigInteger(1, digest)))
response.send("application/octet-stream", payload)
}
server.get("/trickle/.*") { request, response ->
val count = request.path.split("/").last().toInt()
response.setContentType("application/octet-stream")
response.headers.set("Content-Length", "${count}")
response.writeHead()
val payload = byteArrayOf(1)
for (i in 1..count) {
response.write(ByteBufferList(payload))
SystemClock.sleep(250)
}
response.end()
}
}
fun start(port: Int) {
server.listen(port)
}
fun stop() {
server.stop()
}
}

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

@ -47,11 +47,6 @@ import java.util.LinkedList;
public synchronized void close() throws IOException {
super.close();
mClosed = true;
if (mSupport != null) {
mSupport.close();
mSupport = null;
}
}
@Override
@ -197,9 +192,6 @@ import java.util.LinkedList;
@WrapForJNI(dispatchTo = "gecko")
private native void resume();
@WrapForJNI(dispatchTo = "gecko")
private native void close();
@Override // JNIObject
protected void disposeNative() {
throw new UnsupportedOperationException();

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

@ -774,6 +774,7 @@ public class GeckoSession implements Parcelable {
final String event,
final GeckoBundle message,
final EventCallback callback) {
if (delegate == null) {
callback.sendSuccess(/* granted */ false);
return;
@ -798,10 +799,6 @@ public class GeckoSession implements Parcelable {
// doesn't support Web MIDI.
callback.sendError("Unsupported");
return;
} else if ("autoplay-media-inaudible".equals(typeString)) {
type = PermissionDelegate.PERMISSION_AUTOPLAY_INAUDIBLE;
} else if ("autoplay-media-audible".equals(typeString)) {
type = PermissionDelegate.PERMISSION_AUTOPLAY_AUDIBLE;
} else {
throw new IllegalArgumentException("Unknown permission request: " + typeString);
}
@ -4970,16 +4967,6 @@ public class GeckoSession implements Parcelable {
*/
int PERMISSION_XR = 3;
/**
* Permission for allowing autoplay of inaudible (silent) video.
*/
int PERMISSION_AUTOPLAY_INAUDIBLE = 3;
/**
* Permission for allowing autoplay of audible video.
*/
int PERMISSION_AUTOPLAY_AUDIBLE = 4;
/**
* Callback interface for notifying the result of a permission request.
*/
@ -5230,10 +5217,7 @@ public class GeckoSession implements Parcelable {
@Retention(RetentionPolicy.SOURCE)
@IntDef({PermissionDelegate.PERMISSION_GEOLOCATION,
PermissionDelegate.PERMISSION_DESKTOP_NOTIFICATION,
PermissionDelegate.PERMISSION_PERSISTENT_STORAGE,
PermissionDelegate.PERMISSION_XR,
PermissionDelegate.PERMISSION_AUTOPLAY_INAUDIBLE,
PermissionDelegate.PERMISSION_AUTOPLAY_AUDIBLE})
PermissionDelegate.PERMISSION_XR})
/* package */ @interface Permission {}
/**

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

@ -26,10 +26,7 @@ exclude: true
attaching a [`LoginStorage.Delegate`][73.8] via
[`GeckoRuntime#setLoginStorageDelegate`][73.9]
([bug 1602881]({{bugzilla}}1602881))
- Added [`GeckoSession.PermissionDelegate#PERMISSION_AUTOPLAY_AUDIBLE`][73.10] and
[`GeckoSession.PermissionDelegate#PERMISSION_AUTOPLAY_INAUDIBLE`][73.11]. These control
autoplay permissions for audible and inaudible videos.
([bug 1577596]({{bugzilla}}1577596))
[73.1]: {{javadoc_uri}}/WebExtensionController.html#install-java.lang.String-
[73.2]: {{javadoc_uri}}/WebExtensionController.html#uninstall-org.mozilla.geckoview.WebExtension-
@ -40,8 +37,6 @@ exclude: true
[73.7]: {{javadoc_uri}}/LoginStorage.html
[73.8]: {{javadoc_uri}}/LoginStorage.Delegate.html
[73.9]: {{javadoc_uri}}/GeckoRuntime.html#setLoginStorageDelegate-org.mozilla.geckoview.LoginStorage.Delegate-
[73.10]: {{javadoc_uri}}/GeckoSession.PermissionDelegate.html#PERMISSION_AUTOPLAY_AUDIBLE
[73.11]: {{javadoc_uri}}/GeckoSession.PermissionDelegate.html#PERMISSION_AUTOPLAY_INAUDIBLE
## v72
- Added [`GeckoSession.NavigationDelegate.LoadRequest#hasUserGesture`][72.1]. This indicates
@ -110,10 +105,9 @@ exclude: true
[72.20]: https://developer.android.com/reference/java/lang/String
[72.21]: {{javadoc_uri}}/WebExtension.Icon.html
[72.22]: {{javadoc_uri}}/GeckoWebExecutor.html#FETCH_FLAGS_STREAM_FAILURE_TEST
[72.23]: {{javadoc_uri}}/CrashReporter.html#sendCrashReport-android.content.Context-java.io.File-org.json.JSONObject-
[72.23]: {{javadoc_uri}}/CrashReporter#sendCrashReport-android.content.Context-java.io.File-org.json.JSONObject-
[72.24]: {{javadoc_uri}}/GeckoSession.PermissionDelegate.html#PERMISSION_PERSISTENT_XR
=
## v71
- Added a content blocking flag for blocked social cookies to [`ContentBlocking`][70.17].
([bug 1584479]({{bugzilla}}1584479))
@ -510,4 +504,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]: 53eef399f685d92e66c3af73363522edebd3ea93
[api-version]: 07ee732ba2eaafada09739c61c0196e427a2f0ed

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

@ -269,7 +269,6 @@ public class GeckoViewActivity
private boolean mShowNotificationsRejected;
private ArrayList<String> mAcceptedPersistentStorage = new ArrayList<String>();
private ArrayList<String> mAcceptedAutoplay = new ArrayList<>();
private ToolbarLayout mToolbarView;
private String mCurrentUri;
@ -1134,26 +1133,6 @@ public class GeckoViewActivity
}
}
class ExampleAutoplayCallback implements GeckoSession.PermissionDelegate.Callback {
private final GeckoSession.PermissionDelegate.Callback mCallback;
private final String mUri;
ExampleAutoplayCallback(final GeckoSession.PermissionDelegate.Callback callback, String uri) {
mCallback = callback;
mUri = uri;
}
@Override
public void reject() {
mCallback.reject();
}
@Override
public void grant() {
mAcceptedAutoplay.add(mUri);
mCallback.grant();
}
}
public void onRequestPermissionsResult(final String[] permissions,
final int[] grantResults) {
if (mCallback == null) {
@ -1201,7 +1180,7 @@ public class GeckoViewActivity
contentPermissionCallback = new ExampleNotificationCallback(callback);
} else if (PERMISSION_PERSISTENT_STORAGE == type) {
if (mAcceptedPersistentStorage.contains(uri)) {
Log.w(LOGTAG, "Persistent Storage for " + uri + " already granted by user.");
Log.w(LOGTAG, "Persistent Storage for "+ uri +" already granted by user.");
callback.grant();
return;
}
@ -1209,15 +1188,6 @@ public class GeckoViewActivity
contentPermissionCallback = new ExamplePersistentStorageCallback(callback, uri);
} else if (PERMISSION_XR == type) {
resId = R.string.request_xr;
} else if (PERMISSION_AUTOPLAY_AUDIBLE == type || PERMISSION_AUTOPLAY_INAUDIBLE == type) {
if (mAcceptedAutoplay.contains(uri)) {
Log.w(LOGTAG, "Autoplay for " + uri + " already granted by user.");
callback.grant();
return;
}
resId = R.string.request_autoplay;
contentPermissionCallback = new ExampleAutoplayCallback(callback, uri);
} else {
Log.w(LOGTAG, "Unknown permission: " + type);
callback.reject();

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

@ -12,7 +12,6 @@
<string name="request_audio">Share audio with "%1$s"</string>
<string name="request_media">Share video and audio with "%1$s"</string>
<string name="request_xr">Share WebXR displays with "%1$s"?</string>
<string name="request_autoplay">Allow video to autoplay on "%1$s"?</string>
<string name="media_back_camera">Back camera</string>
<string name="media_front_camera">Front camera</string>
<string name="media_microphone">Microphone</string>

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

@ -143,24 +143,14 @@ class StreamSupport final
public:
typedef java::GeckoInputStream::Support::Natives<StreamSupport> Base;
using Base::AttachNative;
using Base::DisposeNative;
using Base::GetNative;
explicit StreamSupport(java::GeckoInputStream::Support::Param aInstance,
nsIRequest* aRequest)
: mInstance(aInstance), mRequest(aRequest) {}
void Close() {
mRequest->Cancel(NS_ERROR_ABORT);
mRequest->Resume();
// This is basically `delete this`, so don't run anything else!
Base::DisposeNative(mInstance);
}
explicit StreamSupport(nsIRequest* aRequest) : mRequest(aRequest) {}
void Resume() { mRequest->Resume(); }
private:
java::GeckoInputStream::Support::GlobalRef mInstance;
nsCOMPtr<nsIRequest> mRequest;
};
@ -193,8 +183,8 @@ class LoaderListener final : public nsIStreamListener,
// We're expecting data later via OnDataAvailable, so create the stream now.
mSupport = java::GeckoInputStream::Support::New();
StreamSupport::AttachNative(
mSupport, mozilla::MakeUnique<StreamSupport>(mSupport, aRequest));
StreamSupport::AttachNative(mSupport,
mozilla::MakeUnique<StreamSupport>(aRequest));
mStream = java::GeckoInputStream::New(mSupport);