зеркало из https://github.com/mozilla/gecko-dev.git
Bug 1600742 - Implement WebExtensionController.list. r=snorp,esawin
Differential Revision: https://phabricator.services.mozilla.com/D56793 --HG-- extra : moz-landing-system : lando
This commit is contained in:
Родитель
f3e3650c45
Коммит
dafbe96c98
|
@ -1549,6 +1549,7 @@ package org.mozilla.geckoview {
|
|||
method @UiThread @Nullable public WebExtensionController.PromptDelegate getPromptDelegate();
|
||||
method @UiThread @Nullable public WebExtensionController.TabDelegate getTabDelegate();
|
||||
method @NonNull @AnyThread public GeckoResult<WebExtension> install(@NonNull String);
|
||||
method @AnyThread @NonNull public GeckoResult<List<WebExtension>> list();
|
||||
method @UiThread public void setPromptDelegate(@Nullable WebExtensionController.PromptDelegate);
|
||||
method @UiThread public void setTabDelegate(@Nullable WebExtensionController.TabDelegate);
|
||||
method @NonNull @AnyThread public GeckoResult<Void> uninstall(@NonNull WebExtension);
|
||||
|
|
Двоичные данные
mobile/android/geckoview/src/androidTest/assets/web_extensions/dummy.xpi
Normal file
Двоичные данные
mobile/android/geckoview/src/androidTest/assets/web_extensions/dummy.xpi
Normal file
Двоичный файл не отображается.
|
@ -0,0 +1 @@
|
|||
console.log("Hi, I'm a dummy.");
|
|
@ -0,0 +1,17 @@
|
|||
{
|
||||
"manifest_version": 2,
|
||||
"name": "Dummy",
|
||||
"version": "1.0",
|
||||
"applications": {
|
||||
"gecko": {
|
||||
"id": "dummy@tests.mozilla.org"
|
||||
}
|
||||
},
|
||||
"description": "Doesn't do anything.",
|
||||
"content_scripts": [
|
||||
{
|
||||
"matches": ["*://*.example.com/*"],
|
||||
"js": ["dummy.js"]
|
||||
}
|
||||
]
|
||||
}
|
|
@ -137,9 +137,16 @@ class WebExtensionTest : BaseSessionTest() {
|
|||
assertThat("Content script should have been applied",
|
||||
color as String, equalTo("red"))
|
||||
|
||||
var list = sessionRule.waitForResult(controller.list())
|
||||
assertEquals(list.size, 1)
|
||||
assertEquals(list[0].id, borderify.id)
|
||||
|
||||
// Unregister WebExtension and check again
|
||||
sessionRule.waitForResult(controller.uninstall(borderify))
|
||||
|
||||
list = sessionRule.waitForResult(controller.list())
|
||||
assertEquals(list, emptyList<WebExtension>())
|
||||
|
||||
mainSession.reload()
|
||||
sessionRule.waitForPageStop()
|
||||
|
||||
|
@ -149,6 +156,53 @@ class WebExtensionTest : BaseSessionTest() {
|
|||
colorAfter as String, equalTo(""))
|
||||
}
|
||||
|
||||
@Test
|
||||
fun installMultiple() {
|
||||
// dummy.xpi is not signed, but it could be
|
||||
sessionRule.setPrefsUntilTestEnd(mapOf(
|
||||
"xpinstall.signatures.required" to false
|
||||
))
|
||||
|
||||
// First, make sure the list starts empty
|
||||
var list = sessionRule.waitForResult(controller.list())
|
||||
assertEquals(list, emptyList<WebExtension>())
|
||||
|
||||
sessionRule.delegateDuringNextWait(object : WebExtensionController.PromptDelegate {
|
||||
@AssertCalled(count=2)
|
||||
override fun onInstallPrompt(extension: WebExtension): GeckoResult<AllowOrDeny> {
|
||||
return GeckoResult.fromValue(AllowOrDeny.ALLOW)
|
||||
}
|
||||
})
|
||||
|
||||
// Install in parallell borderify and dummy
|
||||
val borderifyResult = controller.install(
|
||||
"resource://android/assets/web_extensions/borderify.xpi")
|
||||
val dummyResult = controller.install(
|
||||
"resource://android/assets/web_extensions/dummy.xpi")
|
||||
|
||||
val (borderify, dummy) = sessionRule.waitForResult(
|
||||
GeckoResult.allOf(borderifyResult, dummyResult))
|
||||
|
||||
// Make sure the list is updated accordingly
|
||||
list = sessionRule.waitForResult(controller.list())
|
||||
assertTrue(list.find { it.id == borderify.id } != null)
|
||||
assertTrue(list.find { it.id == dummy.id } != null)
|
||||
assertEquals(list.size, 2)
|
||||
|
||||
// Uninstall borderify and verify that it's not in the list anymore
|
||||
sessionRule.waitForResult(controller.uninstall(borderify))
|
||||
|
||||
list = sessionRule.waitForResult(controller.list())
|
||||
assertEquals(list.size, 1)
|
||||
assertEquals(list[0].id, dummy.id)
|
||||
|
||||
// Uninstall dummy and make sure the list is now empty
|
||||
sessionRule.waitForResult(controller.uninstall(dummy))
|
||||
|
||||
list = sessionRule.waitForResult(controller.list())
|
||||
assertEquals(list, emptyList<WebExtension>())
|
||||
}
|
||||
|
||||
private fun testInstallError(name: String, expectedError: Int) {
|
||||
sessionRule.delegateDuringNextWait(object : WebExtensionController.PromptDelegate {
|
||||
@AssertCalled(count = 0)
|
||||
|
|
|
@ -20,6 +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.WebExtensionController;
|
||||
import org.mozilla.geckoview.test.util.HttpBin;
|
||||
import org.mozilla.geckoview.test.util.RuntimeCreator;
|
||||
import org.mozilla.geckoview.test.util.Environment;
|
||||
|
@ -27,6 +28,7 @@ import org.mozilla.geckoview.test.util.UiThreadUtils;
|
|||
import org.mozilla.geckoview.test.util.Callbacks;
|
||||
|
||||
import static org.hamcrest.Matchers.*;
|
||||
import static org.junit.Assert.assertEquals;
|
||||
import static org.junit.Assert.assertThat;
|
||||
import static org.junit.Assert.fail;
|
||||
|
||||
|
@ -1191,7 +1193,21 @@ public class GeckoSessionTestRule implements TestRule {
|
|||
}
|
||||
}
|
||||
|
||||
protected void cleanupStatement() {
|
||||
protected void cleanupExtensions() throws Throwable {
|
||||
WebExtensionController controller = getRuntime().getWebExtensionController();
|
||||
List<WebExtension> list = waitForResult(controller.list());
|
||||
|
||||
// Uninstall any left-over extensions
|
||||
for (WebExtension extension : list) {
|
||||
waitForResult(controller.uninstall(extension));
|
||||
}
|
||||
|
||||
// If an extension was still installed, this test should fail
|
||||
assertThat("A WebExtension was left installed during this test.",
|
||||
list.size(), equalTo(0));
|
||||
}
|
||||
|
||||
protected void cleanupStatement() throws Throwable {
|
||||
mWaitScopeDelegates.clear();
|
||||
mTestScopeDelegates.clear();
|
||||
|
||||
|
@ -1200,6 +1216,7 @@ public class GeckoSessionTestRule implements TestRule {
|
|||
}
|
||||
|
||||
cleanupSession(mMainSession);
|
||||
cleanupExtensions();
|
||||
|
||||
if (mIgnoreCrash) {
|
||||
deleteCrashDumps();
|
||||
|
|
|
@ -51,7 +51,13 @@ public class WebExtensionController {
|
|||
mData.remove(id);
|
||||
}
|
||||
|
||||
public void put(final String id, final WebExtension extension) {
|
||||
/**
|
||||
* Add this extension to the store and update it's current value if it's already present.
|
||||
*
|
||||
* @param id the {@link WebExtension} id.
|
||||
* @param extension the {@link WebExtension} to add to the store.
|
||||
*/
|
||||
public void update(final String id, final WebExtension extension) {
|
||||
mData.put(id, extension);
|
||||
}
|
||||
}
|
||||
|
@ -392,14 +398,24 @@ public class WebExtensionController {
|
|||
});
|
||||
}
|
||||
|
||||
// TODO: Bug 1600742 make public
|
||||
GeckoResult<List<WebExtension>> listInstalled() {
|
||||
/**
|
||||
* List installed extensions for this {@link GeckoRuntime}.
|
||||
*
|
||||
* The returned list can be used to set delegates on the {@link WebExtension} objects using
|
||||
* {@link WebExtension#setActionDelegate}, {@link WebExtension#setMessageDelegate}.
|
||||
*
|
||||
* @return a {@link GeckoResult} that will resolve when the list of extensions is available.
|
||||
*/
|
||||
@AnyThread
|
||||
@NonNull
|
||||
public GeckoResult<List<WebExtension>> list() {
|
||||
final CallbackResult<List<WebExtension>> result = new CallbackResult<List<WebExtension>>() {
|
||||
@Override
|
||||
public void sendSuccess(final Object response) {
|
||||
final GeckoBundle[] bundles = ((GeckoBundle) response)
|
||||
.getBundleArray("extensions");
|
||||
final List<WebExtension> list = new ArrayList<>(bundles.length);
|
||||
|
||||
for (GeckoBundle bundle : bundles) {
|
||||
final WebExtension extension = new WebExtension(bundle);
|
||||
registerWebExtension(extension);
|
||||
|
@ -438,7 +454,7 @@ public class WebExtensionController {
|
|||
|
||||
/* package */ void registerWebExtension(final WebExtension webExtension) {
|
||||
webExtension.setDelegateController(new DelegateController(webExtension));
|
||||
mExtensions.put(webExtension.id, webExtension);
|
||||
mExtensions.update(webExtension.id, webExtension);
|
||||
}
|
||||
|
||||
/* package */ void handleMessage(final String event, final GeckoBundle message,
|
||||
|
|
|
@ -29,6 +29,7 @@ exclude: true
|
|||
- ⚠️ [`WebExtension`][69.5]'s constructor now requires a `WebExtensionController`
|
||||
instance.
|
||||
- Added [`GeckoResult.allOf`][73.10] for consuming a list of results.
|
||||
- Added [`WebExtensionController.list`][73.11] to list all installed extensions.
|
||||
|
||||
|
||||
[73.1]: {{javadoc_uri}}/WebExtensionController.html#install-java.lang.String-
|
||||
|
@ -41,6 +42,7 @@ exclude: true
|
|||
[73.8]: {{javadoc_uri}}/LoginStorage.Delegate.html
|
||||
[73.9]: {{javadoc_uri}}/GeckoRuntime.html#setLoginStorageDelegate-org.mozilla.geckoview.LoginStorage.Delegate-
|
||||
[73.10]: {{javadoc_uri}}/GeckoResult.html#allOf-java.util.List-
|
||||
[73.11]: {{javadoc_uri}}/WebExtensionController.html#list--
|
||||
|
||||
## v72
|
||||
- Added [`GeckoSession.NavigationDelegate.LoadRequest#hasUserGesture`][72.1]. This indicates
|
||||
|
@ -508,4 +510,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]: 919027349db09895822846ea63adacb901b4ab40
|
||||
[api-version]: 2d592afef93d47a268448aa5fd3289e03bb1f678
|
||||
|
|
|
@ -240,7 +240,6 @@ class GeckoViewConnection {
|
|||
}
|
||||
|
||||
function exportExtension(aAddon, aPermissions, aSourceURI) {
|
||||
const { origins, permissions } = aPermissions;
|
||||
const {
|
||||
creator,
|
||||
description,
|
||||
|
@ -272,8 +271,8 @@ function exportExtension(aAddon, aPermissions, aSourceURI) {
|
|||
isEnabled: isActive,
|
||||
isBuiltIn: isBuiltin,
|
||||
metaData: {
|
||||
permissions,
|
||||
origins,
|
||||
permissions: aPermissions ? aPermissions.permissions : [],
|
||||
origins: aPermissions ? aPermissions.origins : [],
|
||||
description,
|
||||
version,
|
||||
creatorName,
|
||||
|
@ -642,8 +641,16 @@ var GeckoViewWebExtension = {
|
|||
}
|
||||
|
||||
case "GeckoView:WebExtension:List": {
|
||||
// TODO
|
||||
aCallback.onError(`Not implemented`);
|
||||
try {
|
||||
const addons = await AddonManager.getAddonsByTypes(["extension"]);
|
||||
const extensions = addons.map(addon =>
|
||||
exportExtension(addon, addon.userPermissions, null)
|
||||
);
|
||||
aCallback.onSuccess({ extensions });
|
||||
} catch (ex) {
|
||||
debug`Failed list ${ex}`;
|
||||
aCallback.onError(`Unexpected error: ${ex}`);
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
||||
|
|
Загрузка…
Ссылка в новой задаче