Bug 1553371 - Load moz-extension pages in extension principal. r=snorp

WebExtension can always open their respective WebExtension pages even when the
WebExtension page is not content accessible.

However, this is not true for `tabs.update`, which couldn't link to
WebExtension pages at all.

Similarly, a user should be able to open a WebExtension page directly by typing
the URL.

To fix the above problems we pass the correct `triggeringPrincipal` when
loading such URIs. This change also makes URI typed by the user not use the
`systemPrincipal` anymore but a more restrictive codebase principal local to
the page that's being typed to avoid unintended side-effects. This also makes
the triggering URI always the page for these privileged pages, so we need to
adjust some tests to account for that by loading unprivileged `http` pages
instead.

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

--HG--
extra : moz-landing-system : lando
This commit is contained in:
Agi Sferro 2019-05-22 19:20:54 +00:00
Родитель 29c7c2b8d3
Коммит 92c0a96191
4 изменённых файлов: 35 добавлений и 10 удалений

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

@ -330,7 +330,10 @@ this.tabs = class extends ExtensionAPI {
return Promise.reject({message: `Illegal URL: ${url}`}); return Promise.reject({message: `Illegal URL: ${url}`});
} }
nativeTab.browser.loadURI(url); let options = {
triggeringPrincipal: context.principal,
};
nativeTab.browser.loadURI(url, options);
} }
if (updateProperties.active !== null) { if (updateProperties.active !== null) {

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

@ -12,9 +12,6 @@
"run_at": "document_idle" "run_at": "document_idle"
} }
], ],
"web_accessible_resources": [
"tab.html"
],
"permissions": [ "permissions": [
"geckoViewAddons", "geckoViewAddons",
"nativeMessaging", "nativeMessaging",

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

@ -4,6 +4,9 @@
package org.mozilla.geckoview.test package org.mozilla.geckoview.test
import android.os.Handler
import android.os.Looper
import android.support.test.InstrumentationRegistry
import org.mozilla.geckoview.AllowOrDeny import org.mozilla.geckoview.AllowOrDeny
import org.mozilla.geckoview.ContentBlocking import org.mozilla.geckoview.ContentBlocking
import org.mozilla.geckoview.GeckoResult import org.mozilla.geckoview.GeckoResult
@ -23,13 +26,33 @@ import org.mozilla.geckoview.test.util.Callbacks
import android.support.test.filters.MediumTest import android.support.test.filters.MediumTest
import android.support.test.runner.AndroidJUnit4 import android.support.test.runner.AndroidJUnit4
import org.hamcrest.Matchers.* import org.hamcrest.Matchers.*
import org.junit.After
import org.junit.Before
import org.junit.Test import org.junit.Test
import org.junit.runner.RunWith import org.junit.runner.RunWith
import org.mozilla.geckoview.test.util.HttpBin
import java.net.URI
@RunWith(AndroidJUnit4::class) @RunWith(AndroidJUnit4::class)
@MediumTest @MediumTest
@ReuseSession(false) @ReuseSession(false)
class NavigationDelegateTest : BaseSessionTest() { 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, fun testLoadErrorWithErrorPage(testUri: String, expectedCategory: Int,
expectedError: Int, expectedError: Int,
@ -579,7 +602,7 @@ class NavigationDelegateTest : BaseSessionTest() {
} }
@Test fun load() { @Test fun load() {
sessionRule.session.loadTestPath(HELLO_HTML_PATH) sessionRule.session.loadUri("$TEST_ENDPOINT$HELLO_HTML_PATH")
sessionRule.waitForPageStop() sessionRule.waitForPageStop()
sessionRule.forCallbacksDuringWait(object : Callbacks.NavigationDelegate { sessionRule.forCallbacksDuringWait(object : Callbacks.NavigationDelegate {
@ -773,7 +796,7 @@ class NavigationDelegateTest : BaseSessionTest() {
} }
@Test fun reload() { @Test fun reload() {
sessionRule.session.loadTestPath(HELLO_HTML_PATH) sessionRule.session.loadUri("$TEST_ENDPOINT$HELLO_HTML_PATH")
sessionRule.waitForPageStop() sessionRule.waitForPageStop()
sessionRule.session.reload() sessionRule.session.reload()
@ -815,10 +838,10 @@ class NavigationDelegateTest : BaseSessionTest() {
} }
@Test fun goBackAndForward() { @Test fun goBackAndForward() {
sessionRule.session.loadTestPath(HELLO_HTML_PATH) sessionRule.session.loadUri("$TEST_ENDPOINT$HELLO_HTML_PATH")
sessionRule.waitForPageStop() sessionRule.waitForPageStop()
sessionRule.session.loadTestPath(HELLO2_HTML_PATH) sessionRule.session.loadUri("$TEST_ENDPOINT$HELLO2_HTML_PATH")
sessionRule.waitForPageStop() sessionRule.waitForPageStop()
sessionRule.forCallbacksDuringWait(object : Callbacks.NavigationDelegate { sessionRule.forCallbacksDuringWait(object : Callbacks.NavigationDelegate {

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

@ -115,9 +115,11 @@ class GeckoViewNavigation extends GeckoViewModule {
try { try {
parsedUri = Services.io.newURI(uri); parsedUri = Services.io.newURI(uri);
if (parsedUri.schemeIs("about") || parsedUri.schemeIs("data") || if (parsedUri.schemeIs("about") || parsedUri.schemeIs("data") ||
parsedUri.schemeIs("file") || parsedUri.schemeIs("resource")) { parsedUri.schemeIs("file") || parsedUri.schemeIs("resource") ||
parsedUri.schemeIs("moz-extension")) {
// Only allow privileged loading for certain URIs. // Only allow privileged loading for certain URIs.
triggeringPrincipal = Services.scriptSecurityManager.getSystemPrincipal(); triggeringPrincipal = Services.scriptSecurityManager
.createCodebasePrincipal(parsedUri, {});
} }
} catch (ignored) { } catch (ignored) {
} }