mirror of
https://gitlab.winehq.org/wine/wine-gecko.git
synced 2024-09-13 09:24:08 -07:00
Bug 1197379 - Remove support for intercepting app:// URIs using service workers; r=jdm
This commit is contained in:
parent
99925bf95f
commit
dc29e5f515
1
dom/cache/CacheStorage.cpp
vendored
1
dom/cache/CacheStorage.cpp
vendored
@ -119,7 +119,6 @@ IsTrusted(const PrincipalInfo& aPrincipalInfo, bool aTestingPrefEnabled)
|
||||
|
||||
nsAutoCString scheme(Substring(flatURL, schemePos, schemeLen));
|
||||
if (scheme.LowerCaseEqualsLiteral("https") ||
|
||||
scheme.LowerCaseEqualsLiteral("app") ||
|
||||
scheme.LowerCaseEqualsLiteral("file")) {
|
||||
return true;
|
||||
}
|
||||
|
3
dom/cache/TypeUtils.cpp
vendored
3
dom/cache/TypeUtils.cpp
vendored
@ -417,8 +417,7 @@ TypeUtils::ProcessURL(nsACString& aUrl, bool* aSchemeValidOut,
|
||||
if (aSchemeValidOut) {
|
||||
nsAutoCString scheme(Substring(flatURL, schemePos, schemeLen));
|
||||
*aSchemeValidOut = scheme.LowerCaseEqualsLiteral("http") ||
|
||||
scheme.LowerCaseEqualsLiteral("https") ||
|
||||
scheme.LowerCaseEqualsLiteral("app");
|
||||
scheme.LowerCaseEqualsLiteral("https");
|
||||
}
|
||||
|
||||
uint32_t queryPos;
|
||||
|
@ -13,8 +13,6 @@
|
||||
#include "nsSerializationHelper.h"
|
||||
#include "mozilla/net/HttpBaseChannel.h"
|
||||
#include "mozilla/ipc/ChannelInfo.h"
|
||||
#include "nsIJARChannel.h"
|
||||
#include "nsJARChannel.h"
|
||||
#include "nsNetUtil.h"
|
||||
|
||||
using namespace mozilla;
|
||||
@ -90,33 +88,21 @@ ChannelInfo::ResurrectInfoOnChannel(nsIChannel* aChannel)
|
||||
MOZ_ASSERT(NS_IsMainThread());
|
||||
MOZ_ASSERT(mInited);
|
||||
|
||||
// These pointers may be null at this point. They must be checked before
|
||||
// being dereferenced.
|
||||
nsCOMPtr<nsIHttpChannel> httpChannel =
|
||||
do_QueryInterface(aChannel);
|
||||
nsCOMPtr<nsIJARChannel> jarChannel =
|
||||
do_QueryInterface(aChannel);
|
||||
|
||||
if (!mSecurityInfo.IsEmpty()) {
|
||||
nsCOMPtr<nsISupports> infoObj;
|
||||
nsresult rv = NS_DeserializeObject(mSecurityInfo, getter_AddRefs(infoObj));
|
||||
if (NS_WARN_IF(NS_FAILED(rv))) {
|
||||
return rv;
|
||||
}
|
||||
if (httpChannel) {
|
||||
nsCOMPtr<nsIHttpChannel> httpChannel =
|
||||
do_QueryInterface(aChannel);
|
||||
MOZ_ASSERT(httpChannel);
|
||||
net::HttpBaseChannel* httpBaseChannel =
|
||||
static_cast<net::HttpBaseChannel*>(httpChannel.get());
|
||||
rv = httpBaseChannel->OverrideSecurityInfo(infoObj);
|
||||
if (NS_WARN_IF(NS_FAILED(rv))) {
|
||||
return rv;
|
||||
}
|
||||
} else {
|
||||
if (NS_WARN_IF(!jarChannel)) {
|
||||
return NS_ERROR_FAILURE;
|
||||
}
|
||||
static_cast<nsJARChannel*>(jarChannel.get())->
|
||||
OverrideSecurityInfo(infoObj);
|
||||
}
|
||||
}
|
||||
|
||||
return NS_OK;
|
||||
|
@ -14,7 +14,6 @@
|
||||
#include "nsIHttpChannel.h"
|
||||
#include "nsIHttpChannelInternal.h"
|
||||
#include "nsIHttpHeaderVisitor.h"
|
||||
#include "nsIJARChannel.h"
|
||||
#include "nsIScriptSecurityManager.h"
|
||||
#include "nsIThreadRetargetableRequest.h"
|
||||
#include "nsIUploadChannel2.h"
|
||||
@ -463,7 +462,6 @@ FetchDriver::OnStartRequest(nsIRequest* aRequest,
|
||||
RefPtr<InternalResponse> response;
|
||||
nsCOMPtr<nsIChannel> channel = do_QueryInterface(aRequest);
|
||||
nsCOMPtr<nsIHttpChannel> httpChannel = do_QueryInterface(aRequest);
|
||||
nsCOMPtr<nsIJARChannel> jarChannel = do_QueryInterface(aRequest);
|
||||
|
||||
// On a successful redirect we perform the following substeps of HTTP Fetch,
|
||||
// step 5, "redirect status", step 11.
|
||||
@ -508,18 +506,6 @@ FetchDriver::OnStartRequest(nsIRequest* aRequest,
|
||||
if (NS_WARN_IF(NS_FAILED(rv))) {
|
||||
NS_WARNING("Failed to visit all headers.");
|
||||
}
|
||||
} else if (jarChannel) {
|
||||
// We simulate the http protocol for jar/app requests
|
||||
uint32_t responseStatus = 200;
|
||||
nsAutoCString statusText;
|
||||
response = new InternalResponse(responseStatus, NS_LITERAL_CSTRING("OK"));
|
||||
ErrorResult result;
|
||||
nsAutoCString contentType;
|
||||
jarChannel->GetContentType(contentType);
|
||||
response->Headers()->Append(NS_LITERAL_CSTRING("content-type"),
|
||||
contentType,
|
||||
result);
|
||||
MOZ_ASSERT(!result.Failed());
|
||||
} else {
|
||||
response = new InternalResponse(200, NS_LITERAL_CSTRING("OK"));
|
||||
|
||||
|
@ -306,14 +306,6 @@ InternalRequest::MapChannelToRequestMode(nsIChannel* aChannel)
|
||||
|
||||
// TODO: remove following code once securityMode is fully implemented (bug 1189945)
|
||||
|
||||
// We only support app:// protocol interception in non-release builds.
|
||||
#ifndef RELEASE_BUILD
|
||||
nsCOMPtr<nsIJARChannel> jarChannel = do_QueryInterface(aChannel);
|
||||
if (jarChannel) {
|
||||
return RequestMode::No_cors;
|
||||
}
|
||||
#endif
|
||||
|
||||
nsCOMPtr<nsIHttpChannelInternal> httpChannel = do_QueryInterface(aChannel);
|
||||
|
||||
uint32_t corsMode;
|
||||
|
@ -36,8 +36,6 @@ IPDL_SOURCES += [
|
||||
|
||||
LOCAL_INCLUDES += [
|
||||
'../workers',
|
||||
# For nsJARChannel.h
|
||||
'/modules/libjar',
|
||||
# For HttpBaseChannel.h dependencies
|
||||
'/netwerk/base',
|
||||
# For nsDataHandler.h
|
||||
|
@ -14,7 +14,6 @@
|
||||
#include "nsIHttpChannel.h"
|
||||
#include "nsIHttpChannelInternal.h"
|
||||
#include "nsIHttpHeaderVisitor.h"
|
||||
#include "nsIJARChannel.h"
|
||||
#include "nsINetworkInterceptController.h"
|
||||
#include "nsIMutableArray.h"
|
||||
#include "nsIScriptError.h"
|
||||
@ -1766,15 +1765,7 @@ ServiceWorkerManager::Register(nsIDOMWindow* aWindow,
|
||||
aScriptURI->SchemeIs("http", &isHttp);
|
||||
aScriptURI->SchemeIs("https", &isHttps);
|
||||
if (NS_WARN_IF(!isHttp && !isHttps)) {
|
||||
#ifdef RELEASE_BUILD
|
||||
return NS_ERROR_DOM_SECURITY_ERR;
|
||||
#else
|
||||
bool isApp = false;
|
||||
aScriptURI->SchemeIs("app", &isApp);
|
||||
if (NS_WARN_IF(!isApp)) {
|
||||
return NS_ERROR_DOM_SECURITY_ERR;
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
||||
nsCString cleanedScope;
|
||||
|
@ -998,7 +998,6 @@ class FetchEventRunnable : public ExtendableFunctionalEventWorkerRunnable
|
||||
nsCString mMethod;
|
||||
nsString mClientId;
|
||||
bool mIsReload;
|
||||
DebugOnly<bool> mIsHttpChannel;
|
||||
RequestMode mRequestMode;
|
||||
RequestRedirect mRequestRedirect;
|
||||
RequestCredentials mRequestCredentials;
|
||||
@ -1021,7 +1020,6 @@ public:
|
||||
, mScriptSpec(aScriptSpec)
|
||||
, mClientId(aDocumentId)
|
||||
, mIsReload(aIsReload)
|
||||
, mIsHttpChannel(false)
|
||||
, mRequestMode(RequestMode::No_cors)
|
||||
, mRequestRedirect(RequestRedirect::Follow)
|
||||
// By default we set it to same-origin since normal HTTP fetches always
|
||||
@ -1070,16 +1068,14 @@ public:
|
||||
|
||||
nsCOMPtr<nsIURI> referrerURI;
|
||||
rv = NS_GetReferrerFromChannel(channel, getter_AddRefs(referrerURI));
|
||||
// We can't bail on failure since certain non-http channels like JAR
|
||||
// channels are intercepted but don't have referrers.
|
||||
if (NS_SUCCEEDED(rv) && referrerURI) {
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
if (referrerURI) {
|
||||
rv = referrerURI->GetSpec(mReferrer);
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
}
|
||||
|
||||
nsCOMPtr<nsIHttpChannel> httpChannel = do_QueryInterface(channel);
|
||||
if (httpChannel) {
|
||||
mIsHttpChannel = true;
|
||||
MOZ_ASSERT(httpChannel, "How come we don't have an HTTP channel?");
|
||||
|
||||
rv = httpChannel->GetRequestMethod(mMethod);
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
@ -1114,19 +1110,6 @@ public:
|
||||
mUploadStream = uploadStream;
|
||||
}
|
||||
}
|
||||
} else {
|
||||
nsCOMPtr<nsIJARChannel> jarChannel = do_QueryInterface(channel);
|
||||
// If it is not an HTTP channel it must be a JAR one.
|
||||
NS_ENSURE_TRUE(jarChannel, NS_ERROR_NOT_AVAILABLE);
|
||||
|
||||
mMethod = "GET";
|
||||
|
||||
mRequestMode = InternalRequest::MapChannelToRequestMode(channel);
|
||||
|
||||
if (loadFlags & nsIRequest::LOAD_ANONYMOUS) {
|
||||
mRequestCredentials = RequestCredentials::Omit;
|
||||
}
|
||||
}
|
||||
|
||||
return NS_OK;
|
||||
}
|
||||
@ -1213,9 +1196,7 @@ private:
|
||||
}
|
||||
RefPtr<Request> request = new Request(global, internalReq);
|
||||
|
||||
// TODO: remove conditional on http here once app protocol support is
|
||||
// removed from service worker interception
|
||||
MOZ_ASSERT_IF(mIsHttpChannel && internalReq->IsNavigationRequest(),
|
||||
MOZ_ASSERT_IF(internalReq->IsNavigationRequest(),
|
||||
request->Redirect() == RequestRedirect::Manual);
|
||||
|
||||
RootedDictionary<FetchEventInit> init(aCx);
|
||||
|
@ -724,7 +724,8 @@ CompareNetwork::OnStreamComplete(nsIStreamLoader* aLoader, nsISupports* aContext
|
||||
}
|
||||
|
||||
nsCOMPtr<nsIHttpChannel> httpChannel = do_QueryInterface(request);
|
||||
if (httpChannel) {
|
||||
MOZ_ASSERT(httpChannel, "How come we don't have an HTTP channel?");
|
||||
|
||||
bool requestSucceeded;
|
||||
rv = httpChannel->GetRequestSucceeded(&requestSucceeded);
|
||||
if (NS_WARN_IF(NS_FAILED(rv))) {
|
||||
@ -772,36 +773,6 @@ CompareNetwork::OnStreamComplete(nsIStreamLoader* aLoader, nsISupports* aContext
|
||||
mManager->NetworkFinished(NS_ERROR_DOM_SECURITY_ERR);
|
||||
return rv;
|
||||
}
|
||||
}
|
||||
else {
|
||||
// The only supported request schemes are http, https, and app.
|
||||
// Above, we check to ensure that the request is http or https
|
||||
// based on the channel qi. Here we test the scheme to ensure
|
||||
// that it is app. Otherwise, bail.
|
||||
nsCOMPtr<nsIChannel> channel = do_QueryInterface(request);
|
||||
if (NS_WARN_IF(!channel)) {
|
||||
mManager->NetworkFinished(NS_ERROR_FAILURE);
|
||||
return NS_OK;
|
||||
}
|
||||
nsCOMPtr<nsIURI> uri;
|
||||
rv = channel->GetURI(getter_AddRefs(uri));
|
||||
if (NS_WARN_IF(NS_FAILED(rv))) {
|
||||
mManager->NetworkFinished(rv);
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
nsAutoCString scheme;
|
||||
rv = uri->GetScheme(scheme);
|
||||
if (NS_WARN_IF(NS_FAILED(rv))) {
|
||||
mManager->NetworkFinished(rv);
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
if (NS_WARN_IF(!scheme.LowerCaseEqualsLiteral("app"))) {
|
||||
mManager->NetworkFinished(NS_ERROR_FAILURE);
|
||||
return NS_OK;
|
||||
}
|
||||
}
|
||||
|
||||
char16_t* buffer = nullptr;
|
||||
size_t len = 0;
|
||||
|
@ -1,3 +0,0 @@
|
||||
application.list contains a list of files that are in application.zip.
|
||||
|
||||
To update application.zip when changing one of those files, run makezip.sh.
|
@ -1,8 +0,0 @@
|
||||
controlled.html
|
||||
foo.txt
|
||||
index.html
|
||||
manifest.webapp
|
||||
sw.js
|
||||
test.js
|
||||
test_doc_load_interception.js
|
||||
unregister.html
|
Binary file not shown.
@ -1,36 +0,0 @@
|
||||
<!DOCTYPE html>
|
||||
<html>
|
||||
<head>
|
||||
<title>Test app for bug 1161684</title>
|
||||
<script src='test.js'></script>
|
||||
<script src='test_doc_load_interception.js'></script>
|
||||
<script type='application/javascript;version=1.7'>
|
||||
|
||||
function runTests() {
|
||||
return Promise.resolve()
|
||||
.then(navigator.serviceWorker.ready)
|
||||
.then(() => {
|
||||
return testFetchAppResource('foo.txt',
|
||||
'swresponse', 'text/plain');
|
||||
})
|
||||
.then(() => {
|
||||
return testFetchAppResource('foo.txt?fetch=1',
|
||||
'networkresponse', 'text/plain');
|
||||
})
|
||||
.then(() => {
|
||||
return testFetchAppResource('test_custom_content_type',
|
||||
'customContentType', 'text/html');
|
||||
})
|
||||
// XXX: Cross-origin interceptions without CORS result in opaque responses
|
||||
// which are illegal for navigations like iframes. (bug 1183313)
|
||||
//.then(testRedirectedResponse)
|
||||
//.then(testRedirectedHttpsResponse)
|
||||
//.then(testCachedRedirectedResponse)
|
||||
//.then(testCachedRedirectedHttpsResponse)
|
||||
.then(done);
|
||||
}
|
||||
</script>
|
||||
</head>
|
||||
<body onload='runTests()'>
|
||||
</body>
|
||||
</html>
|
@ -1 +0,0 @@
|
||||
networkresponse
|
@ -1,31 +0,0 @@
|
||||
<!DOCTYPE html>
|
||||
<html>
|
||||
<head>
|
||||
<title>Test app for bug 1161684</title>
|
||||
<script src='test.js'></script>
|
||||
<script type='application/javascript;version=1.7'>
|
||||
function registerServiceWorker() {
|
||||
return new Promise((resolve, reject) => {
|
||||
navigator.serviceWorker.ready.then(() => {
|
||||
resolve();
|
||||
});
|
||||
navigator.serviceWorker.register('sw.js', {scope: '.'})
|
||||
.then(registration => {
|
||||
ok(true, 'service worker registered');
|
||||
})
|
||||
.catch(reject);
|
||||
});
|
||||
}
|
||||
|
||||
function runTests() {
|
||||
return Promise.resolve()
|
||||
.then(() => { return testFetchAppResource('foo.txt',
|
||||
'networkresponse'); })
|
||||
.then(registerServiceWorker)
|
||||
.then(ready);
|
||||
}
|
||||
</script>
|
||||
</head>
|
||||
<body onload='runTests()'>
|
||||
</body>
|
||||
</html>
|
@ -1,4 +0,0 @@
|
||||
#!/bin/sh
|
||||
|
||||
rm application.zip
|
||||
zip application.zip `cat application.list`
|
@ -1,5 +0,0 @@
|
||||
{
|
||||
"name": "App",
|
||||
"launch_path": "/index.html",
|
||||
"description": "Test app for bug 1161684"
|
||||
}
|
@ -1,2 +0,0 @@
|
||||
<!DOCTYPE html>
|
||||
real index
|
@ -1 +0,0 @@
|
||||
Access-Control-Allow-Origin: *
|
@ -1,5 +0,0 @@
|
||||
function handleRequest(request, response) {
|
||||
response.setStatusLine(null, 308, "Permanent Redirect");
|
||||
response.setHeader("Access-Control-Allow-Origin", "*", false);
|
||||
response.setHeader("Location", "https://example.org/tests/dom/workers/test/serviceworkers/app-protocol/realindex.html", false);
|
||||
}
|
@ -1,5 +0,0 @@
|
||||
function handleRequest(request, response) {
|
||||
response.setStatusLine(null, 308, "Permanent Redirect");
|
||||
response.setHeader("Access-Control-Allow-Origin", "*", false);
|
||||
response.setHeader("Location", "http://example.org/tests/dom/workers/test/serviceworkers/app-protocol/realindex.html", false);
|
||||
}
|
@ -1,69 +0,0 @@
|
||||
const kHTTPRedirect = "http://example.com/tests/dom/workers/test/serviceworkers/app-protocol/redirect.sjs";
|
||||
const kHTTPSRedirect = "https://example.com/tests/dom/workers/test/serviceworkers/app-protocol/redirect-https.sjs";
|
||||
|
||||
self.addEventListener('install', (event) => {
|
||||
event.waitUntil(
|
||||
self.caches.open("origin-app-cache")
|
||||
.then(c => {
|
||||
return Promise.all(
|
||||
[
|
||||
c.add(kHTTPRedirect),
|
||||
c.add(kHTTPSRedirect),
|
||||
]
|
||||
);
|
||||
})
|
||||
);
|
||||
});
|
||||
|
||||
self.addEventListener('fetch', (event) => {
|
||||
if (event.request.url.indexOf('foo.txt') >= 0) {
|
||||
var url = new URL(event.request.url);
|
||||
var shouldFetch = url.searchParams.get('fetch');
|
||||
if (shouldFetch) {
|
||||
event.respondWith(fetch(event.request));
|
||||
return;
|
||||
}
|
||||
event.respondWith(new Response('swresponse', {
|
||||
headers: {'Content-Type': 'text/plain'}
|
||||
}));
|
||||
}
|
||||
|
||||
if (event.request.url.indexOf('test_doc_load_interception.js') >= 0 ) {
|
||||
var scriptContent = 'alert("OK: Script modified by service worker")';
|
||||
event.respondWith(new Response(scriptContent, {
|
||||
headers: {'Content-Type': 'application/javascript'}
|
||||
}));
|
||||
}
|
||||
|
||||
if (event.request.url.indexOf('test_custom_content_type') >= 0) {
|
||||
event.respondWith(new Response('customContentType', {
|
||||
headers: {'Content-Type': 'text/html'}
|
||||
}));
|
||||
}
|
||||
|
||||
if (event.request.url.indexOf('redirected.html') >= 0) {
|
||||
event.respondWith(fetch(kHTTPRedirect));
|
||||
}
|
||||
|
||||
if (event.request.url.indexOf('redirected-https.html') >= 0) {
|
||||
event.respondWith(fetch(kHTTPSRedirect));
|
||||
}
|
||||
|
||||
if (event.request.url.indexOf('redirected-cached.html') >= 0) {
|
||||
event.respondWith(
|
||||
self.caches.open("origin-app-cache")
|
||||
.then(c => {
|
||||
return c.match(kHTTPRedirect);
|
||||
})
|
||||
);
|
||||
}
|
||||
|
||||
if (event.request.url.indexOf('redirected-https-cached.html') >= 0) {
|
||||
event.respondWith(
|
||||
self.caches.open("origin-app-cache")
|
||||
.then(c => {
|
||||
return c.match(kHTTPSRedirect);
|
||||
})
|
||||
);
|
||||
}
|
||||
});
|
@ -1,72 +0,0 @@
|
||||
function ok(aCondition, aMessage) {
|
||||
if (aCondition) {
|
||||
alert('OK: ' + aMessage);
|
||||
} else {
|
||||
alert('KO: ' + aMessage);
|
||||
}
|
||||
}
|
||||
|
||||
function ready() {
|
||||
alert('READY');
|
||||
}
|
||||
|
||||
function done() {
|
||||
alert('DONE');
|
||||
}
|
||||
|
||||
function testFetchAppResource(aUrl,
|
||||
aExpectedResponse,
|
||||
aExpectedContentType) {
|
||||
return fetch(aUrl).then(res => {
|
||||
ok(true, 'fetch should resolve for ' + aUrl);
|
||||
if (res.type == 'error') {
|
||||
ok(false, 'fetch failed');
|
||||
}
|
||||
ok(res.status == 200, 'status should be 200');
|
||||
ok(res.statusText == 'OK', 'statusText should be OK');
|
||||
if (aExpectedContentType) {
|
||||
var headers = res.headers.getAll('Content-Type');
|
||||
ok(headers.length, "Headers length");
|
||||
var contentType = res.headers.get('Content-Type');
|
||||
ok(contentType == aExpectedContentType, ('content type ' +
|
||||
contentType + ' should match with ' + aExpectedContentType));
|
||||
}
|
||||
return res.text().then(body => {
|
||||
ok(body == aExpectedResponse, 'body ' + body +
|
||||
' should match with ' + aExpectedResponse);
|
||||
});
|
||||
});
|
||||
}
|
||||
|
||||
function testRedirectedResponse() {
|
||||
return testRedirectedResponseWorker("redirected", "IFRAMELOADED");
|
||||
}
|
||||
|
||||
function testRedirectedHttpsResponse() {
|
||||
return testRedirectedResponseWorker("redirected-https", "HTTPSIFRAMELOADED");
|
||||
}
|
||||
|
||||
function testCachedRedirectedResponse() {
|
||||
return testRedirectedResponseWorker("redirected-cached", "IFRAMELOADED");
|
||||
}
|
||||
|
||||
function testCachedRedirectedHttpsResponse() {
|
||||
return testRedirectedResponseWorker("redirected-https-cached", "HTTPSIFRAMELOADED");
|
||||
}
|
||||
|
||||
function testRedirectedResponseWorker(aFrameId, aAlert) {
|
||||
// Because of the CSP policies applied to privileged apps, we cannot run
|
||||
// inline script inside realindex.html, and loading a script from the app://
|
||||
// URI is also not an option, so we let the parent iframe which has access
|
||||
// to the SpecialPowers API use those privileges to access the document.
|
||||
var iframe = document.createElement("iframe");
|
||||
document.body.appendChild(iframe);
|
||||
iframe.src = aFrameId + ".html";
|
||||
iframe.id = aFrameId;
|
||||
return new Promise(resolve => {
|
||||
iframe.addEventListener("load", event => {
|
||||
alert(aAlert);
|
||||
resolve();
|
||||
}, false);
|
||||
});
|
||||
}
|
@ -1 +0,0 @@
|
||||
alert('KO: Should not load this file, but the sw modified version instead');
|
@ -1,24 +0,0 @@
|
||||
<!DOCTYPE html>
|
||||
<html>
|
||||
<head>
|
||||
<script src='test.js'></script>
|
||||
<script type='application/javascript;version=1.7'>
|
||||
function unregisterServiceWorker() {
|
||||
return new Promise((resolve, reject) => {
|
||||
navigator.serviceWorker.getRegistration(".").then((reg) => {
|
||||
reg.unregister().then(resolve);
|
||||
})
|
||||
.catch(reject);
|
||||
});
|
||||
}
|
||||
|
||||
function onLoad() {
|
||||
return Promise.resolve()
|
||||
.then(unregisterServiceWorker)
|
||||
.then(done);
|
||||
}
|
||||
</script>
|
||||
</head>
|
||||
<body onload='onLoad()'>
|
||||
</body>
|
||||
</html>
|
@ -1,6 +0,0 @@
|
||||
{
|
||||
"name": "App",
|
||||
"launch_path": "/index.html",
|
||||
"description": "Test app for bug 1161684",
|
||||
"package_path": "application.zip"
|
||||
}
|
@ -1 +0,0 @@
|
||||
Content-Type: application/manifest+json
|
@ -1,41 +0,0 @@
|
||||
<!DOCTYPE html>
|
||||
<html>
|
||||
<head>
|
||||
<title>Test app for bug 1169249</title>
|
||||
<script type='application/javascript;version=1.7'>
|
||||
function ok(aCondition, aMessage) {
|
||||
if (aCondition) {
|
||||
alert('OK: ' + aMessage);
|
||||
} else {
|
||||
alert('KO: ' + aMessage);
|
||||
}
|
||||
}
|
||||
|
||||
function ready() {
|
||||
alert('READY');
|
||||
}
|
||||
|
||||
function registerServiceWorker() {
|
||||
return new Promise((resolve, reject) => {
|
||||
navigator.serviceWorker.ready.then(() => {
|
||||
ready();
|
||||
resolve();
|
||||
});
|
||||
navigator.serviceWorker.register('sw.js', {scope: '.'})
|
||||
.then(registration => {
|
||||
ok(true, 'service worker registered');
|
||||
})
|
||||
.catch(reject);
|
||||
});
|
||||
}
|
||||
|
||||
function runTests() {
|
||||
return Promise.resolve()
|
||||
.then(registerServiceWorker)
|
||||
.then(ready)
|
||||
}
|
||||
</script>
|
||||
</head>
|
||||
<body onload='runTests()'>
|
||||
</body>
|
||||
</html>
|
@ -1,5 +0,0 @@
|
||||
{
|
||||
"name": "App",
|
||||
"launch_path": "/index.html",
|
||||
"description": "Test app for bug 1169249"
|
||||
}
|
@ -1 +0,0 @@
|
||||
Content-Type: application/manifest+json
|
@ -1 +0,0 @@
|
||||
// Useless service worker.
|
@ -1,17 +0,0 @@
|
||||
<!DOCTYPE HTML>
|
||||
<html>
|
||||
<head>
|
||||
<title>Test app for bug 1178233</title>
|
||||
<script type='application/javascript;version=1.7'>
|
||||
|
||||
function onLoad() {
|
||||
navigator.serviceWorker.ready.then(function(swr) {
|
||||
parent.postMessage({status: "callback", data: "done"}, '*');
|
||||
});
|
||||
}
|
||||
|
||||
</script>
|
||||
</head>
|
||||
<body onload='onLoad()'>
|
||||
</body>
|
||||
</html>
|
@ -1,81 +0,0 @@
|
||||
<!DOCTYPE html>
|
||||
<html>
|
||||
<head>
|
||||
<title>Test app for bug 1178233</title>
|
||||
<script type='application/javascript;version=1.7'>
|
||||
|
||||
function ok(aCondition, aMessage) {
|
||||
if (aCondition) {
|
||||
alert('OK: ' + aMessage);
|
||||
} else {
|
||||
alert('KO: ' + aMessage);
|
||||
}
|
||||
}
|
||||
|
||||
function done() {
|
||||
alert('DONE');
|
||||
}
|
||||
|
||||
function testFrame(src) {
|
||||
return new Promise(function(resolve, reject) {
|
||||
var iframe = document.createElement("iframe");
|
||||
iframe.src = src;
|
||||
window.onmessage = function(e) {
|
||||
if (e.data.status == "callback") {
|
||||
window.onmessage = null;
|
||||
var result = e.data.data;
|
||||
iframe.src = "about:blank";
|
||||
document.body.removeChild(iframe);
|
||||
iframe = null;
|
||||
resolve(result);
|
||||
}
|
||||
};
|
||||
document.body.appendChild(iframe);
|
||||
});
|
||||
}
|
||||
|
||||
function registerServiceWorker() {
|
||||
return navigator.serviceWorker.register('sw.sjs', {scope: '.'});
|
||||
}
|
||||
|
||||
function runTests() {
|
||||
var lastSeenVersion;
|
||||
return Promise.resolve()
|
||||
.then(function() {
|
||||
// Check whether the service worker is already registered and save its
|
||||
// version.
|
||||
return navigator.serviceWorker.getRegistration(".").then(function(swr) {
|
||||
if (!swr) {
|
||||
lastSeenVersion = 0;
|
||||
return registerServiceWorker();
|
||||
}
|
||||
return testFrame('version.html').then(function(body) {
|
||||
lastSeenVersion = parseInt(body);
|
||||
return Promise.resolve();
|
||||
});
|
||||
});
|
||||
})
|
||||
.then(function() {
|
||||
// Wait until the service worker start controlling the client.
|
||||
return testFrame('client.html');
|
||||
})
|
||||
.then(function() {
|
||||
return new Promise((resolve, reject) => {
|
||||
testFrame('wait_for_update.html').then(function() {
|
||||
// Fetch current version. It should be greater than the last seen version.
|
||||
testFrame('version.html').then(function(body) {
|
||||
var currentVersion = parseInt(body);
|
||||
ok(lastSeenVersion < currentVersion, "New service worker version seen");
|
||||
resolve();
|
||||
});
|
||||
});
|
||||
});
|
||||
})
|
||||
.then(done);
|
||||
}
|
||||
|
||||
</script>
|
||||
</head>
|
||||
<body onload='runTests()'>
|
||||
</body>
|
||||
</html>
|
@ -1,5 +0,0 @@
|
||||
{
|
||||
"name": "App",
|
||||
"launch_path": "/index.html",
|
||||
"description": "Test app for bug 1178233"
|
||||
}
|
@ -1 +0,0 @@
|
||||
Content-Type: application/manifest+json
|
@ -1,22 +0,0 @@
|
||||
function handleRequest(request, response) {
|
||||
var stateName = request.scheme + 'counter';
|
||||
if (!getState(stateName)) {
|
||||
setState(stateName, '1');
|
||||
} else {
|
||||
// Make sure that we pass a string value to setState!
|
||||
setState(stateName, "" + (parseInt(getState(stateName)) + 1));
|
||||
}
|
||||
response.setHeader("Content-Type", "application/javascript", false);
|
||||
response.write(getScript(stateName));
|
||||
}
|
||||
|
||||
function getScript(stateName) {
|
||||
return "oninstall = function(evt) {" +
|
||||
"evt.waitUntil(self.skipWaiting());" +
|
||||
"}; " +
|
||||
"onfetch = function(evt) {" +
|
||||
"if (evt.request.url.indexOf('get-sw-version') > -1) {" +
|
||||
"evt.respondWith(new Response('" + getState(stateName) + "'));" +
|
||||
"}" +
|
||||
"};";
|
||||
}
|
@ -1,19 +0,0 @@
|
||||
<!DOCTYPE HTML>
|
||||
<html>
|
||||
<head>
|
||||
<title>Test app for bug 1178233</title>
|
||||
<script type='application/javascript;version=1.7'>
|
||||
|
||||
function onLoad() {
|
||||
fetch("get-sw-version").then(function(r) {
|
||||
return r.text();
|
||||
}).then(function(body) {
|
||||
parent.postMessage({status: "callback", data: body}, "*");
|
||||
});
|
||||
}
|
||||
|
||||
</script>
|
||||
</head>
|
||||
<body onload='onLoad()'>
|
||||
</body>
|
||||
</html>
|
@ -1,25 +0,0 @@
|
||||
<!DOCTYPE html>
|
||||
<html>
|
||||
<head>
|
||||
<title>Test app for bug 1178233</title>
|
||||
<script type='application/javascript;version=1.7'>
|
||||
|
||||
function update() {
|
||||
alert('UPDATE');
|
||||
}
|
||||
|
||||
function onLoad() {
|
||||
navigator.serviceWorker.getRegistration(".").then(function(swr) {
|
||||
swr.onupdatefound = function() {
|
||||
swr.onupdatefound = null;
|
||||
parent.postMessage({status: "callback", data: "done"}, "*");
|
||||
};
|
||||
update();
|
||||
});
|
||||
}
|
||||
|
||||
</script>
|
||||
</head>
|
||||
<body onload='onLoad()'>
|
||||
</body>
|
||||
</html>
|
@ -1,51 +0,0 @@
|
||||
<!DOCTYPE html>
|
||||
<html>
|
||||
<head>
|
||||
<title>Test app for bug 1169249</title>
|
||||
<script type='application/javascript;version=1.7'>
|
||||
function ok(aCondition, aMessage) {
|
||||
if (aCondition) {
|
||||
alert('OK: ' + aMessage);
|
||||
} else {
|
||||
alert('KO: ' + aMessage);
|
||||
}
|
||||
}
|
||||
|
||||
function ready() {
|
||||
alert('READY');
|
||||
}
|
||||
|
||||
function registerServiceWorker() {
|
||||
return new Promise((resolve, reject) => {
|
||||
navigator.serviceWorker.ready.then(() => {
|
||||
ready();
|
||||
resolve();
|
||||
});
|
||||
navigator.serviceWorker.register('../empty.js', {scope: '.'})
|
||||
.then(registration => {
|
||||
ok(true, 'service worker registered');
|
||||
})
|
||||
.catch(reject);
|
||||
});
|
||||
}
|
||||
|
||||
function AddIframe() {
|
||||
return new Promise((resolve, reject) => {
|
||||
let iframe = document.createElement('iframe');
|
||||
iframe.setAttribute('mozbrowser', 'true');
|
||||
iframe.setAttribute('src', "http://test/chrome/dom/workers/test/serviceworkers/serviceworker.html");
|
||||
document.body.appendChild(iframe);
|
||||
iframe.addEventListener("mozbrowserloadend", resolve);
|
||||
});
|
||||
}
|
||||
function runTests() {
|
||||
return Promise.resolve()
|
||||
.then(AddIframe)
|
||||
.then(registerServiceWorker)
|
||||
.then(ready)
|
||||
}
|
||||
</script>
|
||||
</head>
|
||||
<body onload='runTests()'>
|
||||
</body>
|
||||
</html>
|
@ -1,5 +0,0 @@
|
||||
{
|
||||
"name": "App",
|
||||
"launch_path": "/index.html",
|
||||
"description": "Test app for bug 1169249"
|
||||
}
|
@ -1 +0,0 @@
|
||||
Content-Type: application/manifest+json
|
@ -1,9 +1,6 @@
|
||||
[DEFAULT]
|
||||
skip-if = buildapp == 'b2g' || os == 'android'
|
||||
support-files =
|
||||
app/*
|
||||
app2/*
|
||||
app3/*
|
||||
chrome_helpers.js
|
||||
empty.js
|
||||
serviceworker.html
|
||||
@ -13,10 +10,6 @@ support-files =
|
||||
worker.js
|
||||
worker2.js
|
||||
|
||||
[test_aboutserviceworkers.html]
|
||||
skip-if = true #bug 1193319
|
||||
[test_clear_origin_data.html]
|
||||
[test_app_installation.html]
|
||||
[test_privateBrowsing.html]
|
||||
[test_serviceworkerinfo.xul]
|
||||
[test_serviceworkermanager.xul]
|
||||
|
@ -161,7 +161,6 @@ support-files =
|
||||
claim_worker_2.js
|
||||
claim_clients/client.html
|
||||
claim_fetch_worker.js
|
||||
app-protocol/*
|
||||
force_refresh_worker.js
|
||||
sw_clients/refresher.html
|
||||
sw_clients/refresher_compressed.html
|
||||
@ -199,8 +198,6 @@ support-files =
|
||||
redirect.sjs
|
||||
open_window/client.html
|
||||
|
||||
[test_app_protocol.html]
|
||||
skip-if = release_build || (e10s && debug && os == 'win')
|
||||
[test_bug1151916.html]
|
||||
skip-if = e10s && debug && os == 'win'
|
||||
[test_claim.html]
|
||||
|
@ -1,164 +0,0 @@
|
||||
<!DOCTYPE HTML>
|
||||
<html>
|
||||
<!--
|
||||
https://bugzilla.mozilla.org/show_bug.cgi?id=1178233
|
||||
-->
|
||||
<head>
|
||||
<meta charset="utf-8">
|
||||
<title>Test for Bug 1178233</title>
|
||||
<script type="application/javascript" src="chrome://mochikit/content/tests/SimpleTest/SimpleTest.js"></script>
|
||||
<link rel="stylesheet" type="text/css" href="chrome://mochikit/content/tests/SimpleTest/test.css"/>
|
||||
<script type="application/javascript;version=1.7">
|
||||
|
||||
const { classes: Cc, interfaces: Ci, utils: Cu } = Components;
|
||||
|
||||
Cu.import("resource://gre/modules/XPCOMUtils.jsm");
|
||||
XPCOMUtils.defineLazyServiceGetter(this, "gServiceWorkerManager",
|
||||
"@mozilla.org/serviceworkers/manager;1",
|
||||
"nsIServiceWorkerManager");
|
||||
|
||||
XPCOMUtils.defineLazyServiceGetter(this, "gAppsService",
|
||||
"@mozilla.org/AppsService;1",
|
||||
"nsIAppsService");
|
||||
|
||||
SimpleTest.waitForExplicitFinish();
|
||||
|
||||
const gOrigin = 'http://test/chrome/dom/workers/test/serviceworkers/app2';
|
||||
const appManifestURL = gOrigin + '/manifest.webapp';
|
||||
let gApp;
|
||||
|
||||
function uninstallApp() {
|
||||
return new Promise((resolve, reject) => {
|
||||
if (!gApp) {
|
||||
return reject();
|
||||
}
|
||||
let req = navigator.mozApps.mgmt.uninstall(gApp);
|
||||
req.onsuccess = resolve;
|
||||
req.onerror = reject;
|
||||
});
|
||||
}
|
||||
|
||||
function update() {
|
||||
return new Promise((resolve, reject) => {
|
||||
let registrations = [];
|
||||
registrations = gServiceWorkerManager.getAllRegistrations();
|
||||
|
||||
ok(registrations.length === 1, "The registration shows up in about:serviceworker page");
|
||||
|
||||
for (let i = 0; i < registrations.length; i++) {
|
||||
let registration = registrations.queryElementAt(i, Ci.nsIServiceWorkerRegistrationInfo);
|
||||
if (!registration) {
|
||||
reject();
|
||||
return;
|
||||
}
|
||||
info('Update service worker registration');
|
||||
gServiceWorkerManager.propagateSoftUpdate(
|
||||
registration.principal.originAttributes,
|
||||
registration.scope
|
||||
);
|
||||
}
|
||||
resolve();
|
||||
});
|
||||
}
|
||||
|
||||
function testApp() {
|
||||
if (!gApp) {
|
||||
ok(false, 'No test application to launch');
|
||||
return Promise.reject();
|
||||
}
|
||||
return new Promise((resolve, reject) => {
|
||||
let iframe = document.createElement('iframe');
|
||||
let domParent = document.getElementById('container');
|
||||
iframe.setAttribute('mozbrowser', 'true');
|
||||
iframe.setAttribute('mozapp', gApp.manifestURL);
|
||||
iframe.addEventListener('mozbrowsershowmodalprompt', function listener(e) {
|
||||
let message = e.detail.message;
|
||||
if (/OK/.exec(message)) {
|
||||
ok(true, "Message from app: " + message);
|
||||
} else if (/UPDATE/.exec(message)) {
|
||||
ok(true, "Message from app: " + message);
|
||||
update();
|
||||
} else if (/KO/.exec(message)) {
|
||||
ok(false, "Message from app: " + message);
|
||||
} else if (/DONE/.exec(message)) {
|
||||
ok(true, "Message from app: " + message);
|
||||
iframe.src = "about:blank";
|
||||
domParent.removeChild(iframe);
|
||||
iframe = null;
|
||||
resolve();
|
||||
}
|
||||
}, false);
|
||||
domParent.appendChild(iframe);
|
||||
ok(true, "origin " + gOrigin + gApp.manifest.launch_path);
|
||||
SpecialPowers.wrap(iframe.contentWindow).location =
|
||||
gOrigin + gApp.manifest.launch_path;
|
||||
});
|
||||
}
|
||||
|
||||
function installApp() {
|
||||
return new Promise((resolve, reject) => {
|
||||
let req = navigator.mozApps.install(appManifestURL);
|
||||
req.onsuccess = function() {
|
||||
gApp = req.result;
|
||||
is(req.result.manifestURL, appManifestURL, 'app installed');
|
||||
if (req.result.installState == 'installed') {
|
||||
is(req.result.installState, 'installed', 'app downloaded');
|
||||
resolve()
|
||||
} else {
|
||||
req.result.ondownloadapplied = function() {
|
||||
is(req.result.installState, 'installed', 'app downloaded');
|
||||
resolve();
|
||||
}
|
||||
}
|
||||
}
|
||||
req.onerror = reject;
|
||||
});
|
||||
}
|
||||
|
||||
function setup() {
|
||||
info('Setting up');
|
||||
return new Promise((resolve, reject) => {
|
||||
SpecialPowers.setAllAppsLaunchable(true);
|
||||
SpecialPowers.pushPrefEnv({'set': [
|
||||
['dom.mozBrowserFramesEnabled', true],
|
||||
['dom.serviceWorkers.exemptFromPerDomainMax', true],
|
||||
['dom.serviceWorkers.enabled', true],
|
||||
['dom.serviceWorkers.testing.enabled', true],
|
||||
['dom.serviceWorkers.interception.enabled', true]
|
||||
]}, () => {
|
||||
SpecialPowers.pushPermissions([
|
||||
{ 'type': 'webapps-manage', 'allow': 1, 'context': document },
|
||||
{ 'type': 'browser', 'allow': 1, 'context': document },
|
||||
{ 'type': 'embed-apps', 'allow': 1, 'context': document }
|
||||
], () => {
|
||||
SpecialPowers.autoConfirmAppInstall(() => {
|
||||
SpecialPowers.autoConfirmAppUninstall(resolve);
|
||||
});
|
||||
});
|
||||
});
|
||||
});
|
||||
}
|
||||
|
||||
function go() {
|
||||
setup()
|
||||
.then(installApp)
|
||||
.then(testApp)
|
||||
.then(uninstallApp)
|
||||
.then(SimpleTest.finish)
|
||||
.catch(function(e) {
|
||||
ok(false, 'Unexpected error ' + e);
|
||||
SimpleTest.finish();
|
||||
});
|
||||
}
|
||||
</script>
|
||||
</head>
|
||||
<body onload="go()">
|
||||
<a target="_blank" href="https://bugzilla.mozilla.org/show_bug.cgi?id=1171917">Mozilla Bug 1178233</a>
|
||||
<p id="display"></p>
|
||||
<div id="content" style="display: none">
|
||||
</div>
|
||||
<pre id="test">
|
||||
</pre>
|
||||
<div id="container"></div>
|
||||
</body>
|
||||
</html>
|
@ -1,168 +0,0 @@
|
||||
<!DOCTYPE html>
|
||||
<html>
|
||||
<!--
|
||||
https://bugzilla.mozilla.org/show_bug.cgi?id={1169249}
|
||||
-->
|
||||
<head>
|
||||
<title>Test for Bug {1169249}</title>
|
||||
<script type="application/javascript"
|
||||
src="chrome://mochikit/content/tests/SimpleTest/SimpleTest.js"></script>
|
||||
<script type="application/javascript"
|
||||
src="chrome://mochikit/content/chrome-harness.js"></script>
|
||||
<link rel="stylesheet" type="text/css" href="chrome://mochikit/content/tests/SimpleTest/test.css"/>
|
||||
</head>
|
||||
<body>
|
||||
|
||||
<a target="_blank" href="https://bugzilla.mozilla.org/show_bug.cgi?id={1169249}">Mozilla Bug {1169249}</a>
|
||||
<p id="display"></p>
|
||||
<div id="content" style="display: none">
|
||||
|
||||
</div>
|
||||
<pre id="test">
|
||||
<script class="testbody" type="application/javascript;version=1.7">
|
||||
|
||||
const { classes: Cc, interfaces: Ci, utils: Cu, results: Cr } = Components;
|
||||
|
||||
Cu.import("resource://gre/modules/XPCOMUtils.jsm");
|
||||
XPCOMUtils.defineLazyServiceGetter(this, "gServiceWorkerManager",
|
||||
"@mozilla.org/serviceworkers/manager;1",
|
||||
"nsIServiceWorkerManager");
|
||||
|
||||
XPCOMUtils.defineLazyServiceGetter(this, "gAppsService",
|
||||
"@mozilla.org/AppsService;1",
|
||||
"nsIAppsService");
|
||||
SimpleTest.waitForExplicitFinish();
|
||||
|
||||
const gOrigin = 'http://test/chrome/dom/workers/test/serviceworkers/app';
|
||||
const appManifestURL = gOrigin + '/manifest.webapp';
|
||||
let gApp;
|
||||
|
||||
addLoadEvent(go);
|
||||
|
||||
function setup() {
|
||||
info('Setting up');
|
||||
return new Promise((resolve, reject) => {
|
||||
SpecialPowers.setAllAppsLaunchable(true);
|
||||
SpecialPowers.pushPrefEnv({'set': [
|
||||
['dom.mozBrowserFramesEnabled', true],
|
||||
['dom.serviceWorkers.exemptFromPerDomainMax', true],
|
||||
['dom.serviceWorkers.enabled', true],
|
||||
['dom.serviceWorkers.testing.enabled', true],
|
||||
['dom.serviceWorkers.interception.enabled', true],
|
||||
]}, () => {
|
||||
SpecialPowers.pushPermissions([
|
||||
{ 'type': 'webapps-manage', 'allow': 1, 'context': document },
|
||||
{ 'type': 'browser', 'allow': 1, 'context': document },
|
||||
{ 'type': 'embed-apps', 'allow': 1, 'context': document }
|
||||
], () => {
|
||||
SpecialPowers.autoConfirmAppInstall(() => {
|
||||
SpecialPowers.autoConfirmAppUninstall(resolve);
|
||||
});
|
||||
});
|
||||
});
|
||||
});
|
||||
}
|
||||
|
||||
function installApp() {
|
||||
return new Promise((resolve, reject) => {
|
||||
let req = navigator.mozApps.install(appManifestURL);
|
||||
req.onsuccess = function() {
|
||||
gApp = req.result;
|
||||
is(req.result.manifestURL, appManifestURL, 'app installed');
|
||||
if (req.result.installState == 'installed') {
|
||||
is(req.result.installState, 'installed', 'app downloaded');
|
||||
resolve()
|
||||
} else {
|
||||
req.result.ondownloadapplied = function() {
|
||||
is(req.result.installState, 'installed', 'app downloaded');
|
||||
resolve();
|
||||
}
|
||||
}
|
||||
}
|
||||
req.onerror = reject;
|
||||
});
|
||||
}
|
||||
|
||||
function checkSwRegistration(aExpectedRegistrations) {
|
||||
return new Promise((resolve, reject) => {
|
||||
let registrations = [];
|
||||
registrations = gServiceWorkerManager.getAllRegistrations();
|
||||
is(registrations.length, aExpectedRegistrations.length,
|
||||
"There should be " + aExpectedRegistrations.length + " registrations");
|
||||
|
||||
for (let i = 0; i < registrations.length; i++) {
|
||||
let registration = registrations.queryElementAt(i, Ci.nsIServiceWorkerRegistrationInfo);
|
||||
if (!registration) {
|
||||
reject();
|
||||
return;
|
||||
}
|
||||
is(registration.principal.origin, aExpectedRegistrations[i].origin,
|
||||
"Registration principal should be as expected");
|
||||
}
|
||||
resolve();
|
||||
});
|
||||
}
|
||||
|
||||
|
||||
function launchApp() {
|
||||
if (!gApp) {
|
||||
ok(false, 'No test application to launch');
|
||||
return Promise.reject();
|
||||
}
|
||||
return new Promise((resolve, reject) => {
|
||||
let iframe = document.createElement('iframe');
|
||||
iframe.setAttribute('mozbrowser', 'true');
|
||||
iframe.setAttribute('mozapp', gApp.manifestURL);
|
||||
iframe.addEventListener('mozbrowsershowmodalprompt', function listener(e) {
|
||||
let message = e.detail.message;
|
||||
if (/OK/.exec(message)) {
|
||||
ok(true, "Message from app: " + message);
|
||||
} else if (/READY/.exec(message)) {
|
||||
ok(true, 'Message from app: ' + message);
|
||||
resolve();
|
||||
}
|
||||
}, false);
|
||||
let domParent = document.getElementById('container');
|
||||
domParent.appendChild(iframe);
|
||||
ok(true, "origin " + gOrigin + gApp.manifest.launch_path);
|
||||
SpecialPowers.wrap(iframe.contentWindow).location =
|
||||
gOrigin + gApp.manifest.launch_path;
|
||||
});
|
||||
}
|
||||
|
||||
function uninstallApp() {
|
||||
return new Promise((resolve, reject) => {
|
||||
if (!gApp) {
|
||||
return reject();
|
||||
}
|
||||
let req = navigator.mozApps.mgmt.uninstall(gApp);
|
||||
req.onsuccess = resolve;
|
||||
req.onerror = reject;
|
||||
});
|
||||
}
|
||||
|
||||
function go() {
|
||||
setup()
|
||||
.then(installApp)
|
||||
.then(launchApp)
|
||||
.then(() => {
|
||||
app = gAppsService.getAppByManifestURL(gApp.manifestURL);
|
||||
return checkSwRegistration([{
|
||||
origin: app.principal.origin
|
||||
}]);
|
||||
})
|
||||
.then(uninstallApp)
|
||||
.then(() => {
|
||||
return checkSwRegistration([]);
|
||||
})
|
||||
.then(SimpleTest.finish)
|
||||
.catch((e) => {
|
||||
ok(false, 'Unexpected error ' + e);
|
||||
SimpleTest.finish();
|
||||
});
|
||||
}
|
||||
</script>
|
||||
</pre>
|
||||
<div id="container"></div>
|
||||
</body>
|
||||
</html>
|
@ -1,193 +0,0 @@
|
||||
<!--
|
||||
Any copyright is dedicated to the Public Domain.
|
||||
http://creativecommons.org/publicdomain/zero/1.0/
|
||||
-->
|
||||
<!DOCTYPE HTML>
|
||||
<html>
|
||||
<head>
|
||||
<title>Bug 1161684 - Allow JAR channels to be intercepted by service workers</title>
|
||||
<script type='text/javascript' src='/tests/SimpleTest/SimpleTest.js'></script>
|
||||
<link rel='stylesheet' type='text/css' href='/tests/SimpleTest/test.css' />
|
||||
</head>
|
||||
<body onload='runTests()'>
|
||||
<p id='display'></p>
|
||||
<div id='content' style='display: none'></div>
|
||||
<pre id='test'></pre>
|
||||
<script class='testbody' type='application/javascript;version=1.7'>
|
||||
|
||||
SimpleTest.waitForExplicitFinish();
|
||||
|
||||
const appManifestURL =
|
||||
'http://mochi.test:8888/tests/dom/workers/test/serviceworkers/app-protocol/update.webapp';
|
||||
let gApp;
|
||||
|
||||
function setup() {
|
||||
return new Promise((resolve, reject) => {
|
||||
SpecialPowers.setAllAppsLaunchable(true);
|
||||
SpecialPowers.pushPrefEnv({'set': [
|
||||
['dom.mozBrowserFramesEnabled', true],
|
||||
['dom.serviceWorkers.exemptFromPerDomainMax', true],
|
||||
["dom.serviceWorkers.interception.enabled", true],
|
||||
['dom.serviceWorkers.enabled', true],
|
||||
['dom.serviceWorkers.testing.enabled', true],
|
||||
['dom.caches.enabled', true],
|
||||
]}, () => {
|
||||
SpecialPowers.pushPermissions([
|
||||
{ 'type': 'webapps-manage', 'allow': 1, 'context': document },
|
||||
{ 'type': 'browser', 'allow': 1, 'context': document },
|
||||
{ 'type': 'embed-apps', 'allow': 1, 'context': document }
|
||||
], () => {
|
||||
SpecialPowers.autoConfirmAppInstall(() => {
|
||||
SpecialPowers.autoConfirmAppUninstall(resolve);
|
||||
});
|
||||
});
|
||||
});
|
||||
});
|
||||
}
|
||||
|
||||
function installApp() {
|
||||
return new Promise((resolve, reject) => {
|
||||
let req = navigator.mozApps.installPackage(appManifestURL);
|
||||
req.onsuccess = function() {
|
||||
gApp = req.result;
|
||||
is(req.result.manifestURL, appManifestURL, 'app installed');
|
||||
if (req.result.installState == 'installed') {
|
||||
is(req.result.installState, 'installed', 'app downloaded');
|
||||
resolve()
|
||||
} else {
|
||||
req.result.ondownloadapplied = function() {
|
||||
is(req.result.installState, 'installed', 'app downloaded');
|
||||
resolve();
|
||||
}
|
||||
}
|
||||
}
|
||||
req.onerror = reject;
|
||||
});
|
||||
}
|
||||
|
||||
function launchApp() {
|
||||
if (!gApp) {
|
||||
ok(false, 'No test application to launch');
|
||||
return Promise.reject();
|
||||
}
|
||||
return new Promise((resolve, reject) => {
|
||||
let iframe = document.createElement('iframe');
|
||||
iframe.setAttribute('mozbrowser', 'true');
|
||||
iframe.setAttribute('mozapp', gApp.manifestURL);
|
||||
iframe.addEventListener('mozbrowsershowmodalprompt', function listener(e) {
|
||||
let message = e.detail.message;
|
||||
if (/OK/.exec(message)) {
|
||||
ok(true, "Message from app: " + message);
|
||||
} else if (/KO/.exec(message)) {
|
||||
ok(false, "Message from app: " + message);
|
||||
} else if (/READY/.exec(message)) {
|
||||
ok(true, "Message from app: " + message);
|
||||
resolve();
|
||||
} else {
|
||||
ok(false, "Unexpected message received: " + message);
|
||||
}
|
||||
}, false);
|
||||
let domParent = document.getElementById('container');
|
||||
domParent.appendChild(iframe);
|
||||
SpecialPowers.wrap(iframe.contentWindow).location =
|
||||
gApp.origin + gApp.manifest.launch_path;
|
||||
});
|
||||
}
|
||||
|
||||
function loadControlled() {
|
||||
return new Promise((resolve, reject) => {
|
||||
let iframe = document.createElement('iframe');
|
||||
iframe.setAttribute('mozbrowser', 'true');
|
||||
iframe.setAttribute('mozapp', gApp.manifestURL);
|
||||
iframe.addEventListener('mozbrowsershowmodalprompt', function listener(e) {
|
||||
let message = e.detail.message;
|
||||
if (/OK/.exec(message)) {
|
||||
ok(true, "Message from app: " + message);
|
||||
} else if (/KO/.exec(message)) {
|
||||
ok(false, "Message from app: " + message);
|
||||
} else if (/HTTPSIFRAMELOADED/.exec(message)) {
|
||||
let doc = SpecialPowers.wrap(iframe).contentDocument;
|
||||
let innerDoc = SpecialPowers.wrap(doc.getElementById("redirected-https").contentDocument);
|
||||
let innerLocation = innerDoc.defaultView.location;
|
||||
is(innerDoc.domain, "example.org", "Correct domain expected (https)");
|
||||
is(innerLocation.origin, "https://example.org", "Correct origin expected (https)");
|
||||
} else if (/IFRAMELOADED/.exec(message)) {
|
||||
let doc = SpecialPowers.wrap(iframe).contentDocument;
|
||||
let innerDoc = SpecialPowers.wrap(doc.getElementById("redirected").contentDocument);
|
||||
let innerLocation = innerDoc.defaultView.location;
|
||||
is(innerDoc.domain, "example.org", "Correct domain expected");
|
||||
is(innerLocation.origin, "http://example.org", "Correct origin expected");
|
||||
} else if (/DONE/.exec(message)) {
|
||||
ok(true, "Messaging from app complete");
|
||||
iframe.removeEventListener('mozbrowsershowmodalprompt', listener);
|
||||
let domParent = document.getElementById('container');
|
||||
domParent.removeChild(iframe);
|
||||
resolve();
|
||||
} else {
|
||||
ok(false, "Unexpected message received: " + message);
|
||||
}
|
||||
}, false);
|
||||
let domParent = document.getElementById('container');
|
||||
domParent.appendChild(iframe);
|
||||
SpecialPowers.wrap(iframe.contentWindow).location =
|
||||
gApp.origin + '/controlled.html';
|
||||
});
|
||||
}
|
||||
|
||||
function loadUnregister() {
|
||||
return new Promise((resolve, reject) => {
|
||||
let iframe = document.createElement('iframe');
|
||||
iframe.setAttribute('mozbrowser', 'true');
|
||||
iframe.setAttribute('mozapp', gApp.manifestURL);
|
||||
iframe.addEventListener('mozbrowsershowmodalprompt', function listener(e) {
|
||||
let message = e.detail.message;
|
||||
if (/OK/.exec(message)) {
|
||||
ok(true, "Message from app: " + message);
|
||||
} else if (/KO/.exec(message)) {
|
||||
ok(false, "Message from app: " + message);
|
||||
} else if (/DONE/.exec(message)) {
|
||||
ok(true, "Messaging from app complete");
|
||||
iframe.removeEventListener('mozbrowsershowmodalprompt', listener);
|
||||
let domParent = document.getElementById('container');
|
||||
domParent.removeChild(iframe);
|
||||
resolve();
|
||||
} else {
|
||||
ok(false, "Unexpected message received: " + message);
|
||||
}
|
||||
}, false);
|
||||
let domParent = document.getElementById('container');
|
||||
domParent.appendChild(iframe);
|
||||
SpecialPowers.wrap(iframe.contentWindow).location =
|
||||
gApp.origin + '/unregister.html';
|
||||
});
|
||||
}
|
||||
|
||||
function uninstallApp() {
|
||||
return new Promise((resolve, reject) => {
|
||||
if (!gApp) {
|
||||
return reject();
|
||||
}
|
||||
let req = navigator.mozApps.mgmt.uninstall(gApp);
|
||||
req.onsuccess = resolve;
|
||||
req.onerror = reject;
|
||||
});
|
||||
}
|
||||
|
||||
function runTests() {
|
||||
setup()
|
||||
.then(installApp)
|
||||
.then(launchApp)
|
||||
.then(loadControlled)
|
||||
.then(loadUnregister)
|
||||
.then(uninstallApp)
|
||||
.then(SimpleTest.finish)
|
||||
.catch((e) => {
|
||||
ok(false, 'Unexpected error ' + e);
|
||||
SimpleTest.finish();
|
||||
});
|
||||
}
|
||||
|
||||
</script>
|
||||
<div id='container'></div>
|
||||
</body>
|
||||
</html>
|
@ -1,152 +0,0 @@
|
||||
<!DOCTYPE html>
|
||||
<html>
|
||||
<!--
|
||||
https://bugzilla.mozilla.org/show_bug.cgi?id={1233644}
|
||||
-->
|
||||
<head>
|
||||
<title>Test for Bug {1233644}</title>
|
||||
<script type="application/javascript"
|
||||
src="chrome://mochikit/content/tests/SimpleTest/SimpleTest.js"></script>
|
||||
<script type="application/javascript"
|
||||
src="chrome://mochikit/content/chrome-harness.js"></script>
|
||||
<link rel="stylesheet" type="text/css" href="chrome://mochikit/content/tests/SimpleTest/test.css"/>
|
||||
</head>
|
||||
<body>
|
||||
|
||||
<a target="_blank" href="https://bugzilla.mozilla.org/show_bug.cgi?id={1233644}">Mozilla Bug {1233644}</a>
|
||||
<p id="display"></p>
|
||||
<div id="content" style="display: none">
|
||||
|
||||
</div>
|
||||
<pre id="test">
|
||||
<script class="testbody" type="application/javascript;version=1.7">
|
||||
|
||||
const { classes: Cc, interfaces: Ci, utils: Cu, results: Cr } = Components;
|
||||
|
||||
Cu.import("resource://gre/modules/XPCOMUtils.jsm");
|
||||
XPCOMUtils.defineLazyServiceGetter(this, "gServiceWorkerManager",
|
||||
"@mozilla.org/serviceworkers/manager;1",
|
||||
"nsIServiceWorkerManager");
|
||||
|
||||
SimpleTest.waitForExplicitFinish();
|
||||
|
||||
const gOrigin = 'http://test/chrome/dom/workers/test/serviceworkers/app3';
|
||||
const appManifestURL = gOrigin + '/manifest.webapp';
|
||||
let gApp;
|
||||
|
||||
addLoadEvent(go);
|
||||
|
||||
function setup() {
|
||||
info('Setting up');
|
||||
return new Promise((resolve, reject) => {
|
||||
SpecialPowers.setAllAppsLaunchable(true);
|
||||
SpecialPowers.pushPrefEnv({'set': [
|
||||
['dom.mozBrowserFramesEnabled', true],
|
||||
['dom.serviceWorkers.exemptFromPerDomainMax', true],
|
||||
['dom.serviceWorkers.enabled', true],
|
||||
['dom.serviceWorkers.testing.enabled', true],
|
||||
['dom.serviceWorkers.interception.enabled', true],
|
||||
]}, () => {
|
||||
SpecialPowers.pushPermissions([
|
||||
{ 'type': 'webapps-manage', 'allow': 1, 'context': document },
|
||||
{ 'type': 'browser', 'allow': 1, 'context': document },
|
||||
{ 'type': 'embed-apps', 'allow': 1, 'context': document }
|
||||
], () => {
|
||||
SpecialPowers.autoConfirmAppInstall(() => {
|
||||
SpecialPowers.autoConfirmAppUninstall(resolve);
|
||||
});
|
||||
});
|
||||
});
|
||||
});
|
||||
}
|
||||
|
||||
function installApp() {
|
||||
return new Promise((resolve, reject) => {
|
||||
let req = navigator.mozApps.install(appManifestURL);
|
||||
req.onsuccess = function() {
|
||||
gApp = req.result;
|
||||
is(req.result.manifestURL, appManifestURL, 'app installed');
|
||||
if (req.result.installState == 'installed') {
|
||||
is(req.result.installState, 'installed', 'app downloaded');
|
||||
resolve()
|
||||
} else {
|
||||
req.result.ondownloadapplied = function() {
|
||||
is(req.result.installState, 'installed', 'app downloaded');
|
||||
resolve();
|
||||
}
|
||||
}
|
||||
}
|
||||
req.onerror = reject;
|
||||
});
|
||||
}
|
||||
|
||||
function pushPermission() {
|
||||
return new Promise((resolve, reject) => {
|
||||
SpecialPowers.pushPermissions([
|
||||
{'type': 'browser', 'allow': 1, 'context': {manifestURL: appManifestURL}}], resolve);
|
||||
});
|
||||
}
|
||||
|
||||
function checkSwRegistration() {
|
||||
return new Promise((resolve, reject) => {
|
||||
let registrations = gServiceWorkerManager.getAllRegistrations();
|
||||
is(registrations.length, 0, "All registrations should be removed.");
|
||||
|
||||
resolve();
|
||||
});
|
||||
}
|
||||
|
||||
function launchApp() {
|
||||
if (!gApp) {
|
||||
ok(false, 'No test application to launch');
|
||||
return Promise.reject();
|
||||
}
|
||||
return new Promise((resolve, reject) => {
|
||||
let iframe = document.createElement('iframe');
|
||||
iframe.setAttribute('mozbrowser', 'true');
|
||||
iframe.setAttribute('mozapp', gApp.manifestURL);
|
||||
iframe.addEventListener('mozbrowsershowmodalprompt', function listener(e) {
|
||||
let message = e.detail.message;
|
||||
if (/OK/.exec(message)) {
|
||||
ok(true, "Message from app: " + message);
|
||||
} else if (/READY/.exec(message)) {
|
||||
ok(true, 'Message from app: ' + message);
|
||||
resolve();
|
||||
}
|
||||
}, false);
|
||||
let domParent = document.getElementById('container');
|
||||
domParent.appendChild(iframe);
|
||||
SpecialPowers.wrap(iframe.contentWindow).location =
|
||||
gOrigin + gApp.manifest.launch_path;
|
||||
});
|
||||
}
|
||||
|
||||
function uninstallApp() {
|
||||
return new Promise((resolve, reject) => {
|
||||
if (!gApp) {
|
||||
return reject();
|
||||
}
|
||||
let req = navigator.mozApps.mgmt.uninstall(gApp);
|
||||
req.onsuccess = resolve;
|
||||
req.onerror = reject;
|
||||
});
|
||||
}
|
||||
|
||||
function go() {
|
||||
setup()
|
||||
.then(installApp)
|
||||
.then(pushPermission)
|
||||
.then(launchApp)
|
||||
.then(uninstallApp)
|
||||
.then(checkSwRegistration)
|
||||
.then(SimpleTest.finish)
|
||||
.catch((e) => {
|
||||
ok(false, 'Unexpected error ' + e);
|
||||
SimpleTest.finish();
|
||||
});
|
||||
}
|
||||
</script>
|
||||
</pre>
|
||||
<div id="container"></div>
|
||||
</body>
|
||||
</html>
|
@ -1,166 +0,0 @@
|
||||
/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
|
||||
/* vim:set expandtab ts=2 sw=2 sts=2 cin: */
|
||||
/* This Source Code Form is subject to the terms of the Mozilla Public
|
||||
* License, v. 2.0. If a copy of the MPL was not distributed with this
|
||||
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
|
||||
|
||||
#include "InterceptedJARChannel.h"
|
||||
#include "nsIPipe.h"
|
||||
#include "mozilla/dom/ChannelInfo.h"
|
||||
|
||||
using namespace mozilla::net;
|
||||
|
||||
NS_IMPL_ISUPPORTS(InterceptedJARChannel, nsIInterceptedChannel)
|
||||
|
||||
InterceptedJARChannel::InterceptedJARChannel(nsJARChannel* aChannel,
|
||||
nsINetworkInterceptController* aController)
|
||||
: mController(aController)
|
||||
, mChannel(aChannel)
|
||||
{
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
InterceptedJARChannel::GetResponseBody(nsIOutputStream** aStream)
|
||||
{
|
||||
NS_IF_ADDREF(*aStream = mResponseBody);
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
InterceptedJARChannel::GetInternalContentPolicyType(nsContentPolicyType* aPolicyType)
|
||||
{
|
||||
NS_ENSURE_ARG(aPolicyType);
|
||||
nsCOMPtr<nsILoadInfo> loadInfo;
|
||||
nsresult rv = mChannel->GetLoadInfo(getter_AddRefs(loadInfo));
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
|
||||
*aPolicyType = loadInfo->InternalContentPolicyType();
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
InterceptedJARChannel::GetChannel(nsIChannel** aChannel)
|
||||
{
|
||||
NS_IF_ADDREF(*aChannel = mChannel);
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
InterceptedJARChannel::GetSecureUpgradedChannelURI(nsIURI** aURI)
|
||||
{
|
||||
return mChannel->GetURI(aURI);
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
InterceptedJARChannel::ResetInterception()
|
||||
{
|
||||
if (!mChannel) {
|
||||
return NS_ERROR_NOT_AVAILABLE;
|
||||
}
|
||||
|
||||
mResponseBody = nullptr;
|
||||
mSynthesizedInput = nullptr;
|
||||
|
||||
mChannel->ResetInterception();
|
||||
mReleaseHandle = nullptr;
|
||||
mChannel = nullptr;
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
InterceptedJARChannel::SynthesizeStatus(uint16_t aStatus,
|
||||
const nsACString& aReason)
|
||||
{
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
InterceptedJARChannel::SynthesizeHeader(const nsACString& aName,
|
||||
const nsACString& aValue)
|
||||
{
|
||||
if (aName.LowerCaseEqualsLiteral("content-type")) {
|
||||
mContentType = aValue;
|
||||
}
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
InterceptedJARChannel::FinishSynthesizedResponse(const nsACString& aFinalURLSpec)
|
||||
{
|
||||
if (NS_WARN_IF(!mChannel)) {
|
||||
return NS_ERROR_NOT_AVAILABLE;
|
||||
}
|
||||
|
||||
if (!aFinalURLSpec.IsEmpty()) {
|
||||
// We don't support rewriting responses for JAR channels where the principal
|
||||
// needs to be modified.
|
||||
return NS_ERROR_NOT_IMPLEMENTED;
|
||||
}
|
||||
|
||||
mChannel->OverrideWithSynthesizedResponse(mSynthesizedInput, mContentType);
|
||||
|
||||
mResponseBody = nullptr;
|
||||
mReleaseHandle = nullptr;
|
||||
mChannel = nullptr;
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
InterceptedJARChannel::Cancel(nsresult aStatus)
|
||||
{
|
||||
MOZ_ASSERT(NS_FAILED(aStatus));
|
||||
|
||||
if (!mChannel) {
|
||||
return NS_ERROR_FAILURE;
|
||||
}
|
||||
|
||||
nsresult rv = mChannel->Cancel(aStatus);
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
mResponseBody = nullptr;
|
||||
mReleaseHandle = nullptr;
|
||||
mChannel = nullptr;
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
InterceptedJARChannel::SetChannelInfo(mozilla::dom::ChannelInfo* aChannelInfo)
|
||||
{
|
||||
if (!mChannel) {
|
||||
return NS_ERROR_FAILURE;
|
||||
}
|
||||
|
||||
return aChannelInfo->ResurrectInfoOnChannel(mChannel);
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
InterceptedJARChannel::GetConsoleReportCollector(nsIConsoleReportCollector**)
|
||||
{
|
||||
return NS_ERROR_NOT_AVAILABLE;
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
InterceptedJARChannel::SetReleaseHandle(nsISupports* aHandle)
|
||||
{
|
||||
MOZ_ASSERT(NS_IsMainThread());
|
||||
MOZ_ASSERT(!mReleaseHandle);
|
||||
MOZ_ASSERT(aHandle);
|
||||
mReleaseHandle = aHandle;
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
void
|
||||
InterceptedJARChannel::NotifyController()
|
||||
{
|
||||
nsresult rv = NS_NewPipe(getter_AddRefs(mSynthesizedInput),
|
||||
getter_AddRefs(mResponseBody),
|
||||
0, UINT32_MAX, true, true);
|
||||
NS_ENSURE_SUCCESS_VOID(rv);
|
||||
|
||||
rv = mController->ChannelIntercepted(this);
|
||||
if (NS_WARN_IF(NS_FAILED(rv))) {
|
||||
rv = ResetInterception();
|
||||
NS_WARN_IF_FALSE(NS_SUCCEEDED(rv),
|
||||
"Failed to resume intercepted network request");
|
||||
}
|
||||
mController = nullptr;
|
||||
}
|
@ -1,63 +0,0 @@
|
||||
/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
|
||||
/* vim:set expandtab ts=2 sw=2 sts=2 cin: */
|
||||
/* This Source Code Form is subject to the terms of the Mozilla Public
|
||||
* License, v. 2.0. If a copy of the MPL was not distributed with this
|
||||
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
|
||||
|
||||
#ifndef InterceptedJARChannel_h
|
||||
#define InterceptedJARChannel_h
|
||||
|
||||
#include "nsJAR.h"
|
||||
#include "nsJARChannel.h"
|
||||
#include "nsIInputStream.h"
|
||||
#include "nsIInputStreamPump.h"
|
||||
#include "nsINetworkInterceptController.h"
|
||||
#include "nsIOutputStream.h"
|
||||
#include "mozilla/RefPtr.h"
|
||||
|
||||
#include "mozilla/Maybe.h"
|
||||
|
||||
class nsIStreamListener;
|
||||
class nsJARChannel;
|
||||
|
||||
namespace mozilla {
|
||||
namespace net {
|
||||
|
||||
// An object representing a channel that has been intercepted. This avoids
|
||||
// complicating the actual channel implementation with the details of
|
||||
// synthesizing responses.
|
||||
class InterceptedJARChannel : public nsIInterceptedChannel
|
||||
{
|
||||
// The interception controller to notify about the successful channel
|
||||
// interception.
|
||||
nsCOMPtr<nsINetworkInterceptController> mController;
|
||||
|
||||
// The actual channel being intercepted.
|
||||
RefPtr<nsJARChannel> mChannel;
|
||||
|
||||
// Reader-side of the synthesized response body.
|
||||
nsCOMPtr<nsIInputStream> mSynthesizedInput;
|
||||
|
||||
// The stream to write the body of the synthesized response.
|
||||
nsCOMPtr<nsIOutputStream> mResponseBody;
|
||||
|
||||
nsCOMPtr<nsISupports> mReleaseHandle;
|
||||
|
||||
// The content type of the synthesized response.
|
||||
nsCString mContentType;
|
||||
|
||||
virtual ~InterceptedJARChannel() {};
|
||||
public:
|
||||
InterceptedJARChannel(nsJARChannel* aChannel,
|
||||
nsINetworkInterceptController* aController);
|
||||
|
||||
NS_DECL_ISUPPORTS
|
||||
NS_DECL_NSIINTERCEPTEDCHANNEL
|
||||
|
||||
void NotifyController();
|
||||
};
|
||||
|
||||
} // namespace net
|
||||
} // namespace mozilla
|
||||
|
||||
#endif // InterceptedJARChannel_h
|
@ -23,14 +23,12 @@ XPIDL_SOURCES += [
|
||||
XPIDL_MODULE = 'jar'
|
||||
|
||||
EXPORTS += [
|
||||
'InterceptedJARChannel.h',
|
||||
'nsJARURI.h',
|
||||
'nsZipArchive.h',
|
||||
'zipstruct.h',
|
||||
]
|
||||
|
||||
UNIFIED_SOURCES += [
|
||||
'InterceptedJARChannel.cpp',
|
||||
'nsJARProtocolHandler.cpp',
|
||||
'nsJARURI.cpp',
|
||||
]
|
||||
|
@ -25,8 +25,6 @@
|
||||
#include "mozilla/net/RemoteOpenFileChild.h"
|
||||
#include "nsITabChild.h"
|
||||
#include "private/pprio.h"
|
||||
#include "nsINetworkInterceptController.h"
|
||||
#include "InterceptedJARChannel.h"
|
||||
#include "nsInputStreamPump.h"
|
||||
|
||||
using namespace mozilla;
|
||||
@ -203,7 +201,6 @@ nsJARChannel::nsJARChannel()
|
||||
, mIsPending(false)
|
||||
, mIsUnsafe(true)
|
||||
, mOpeningRemote(false)
|
||||
, mSynthesizedStreamLength(0)
|
||||
, mBlockRemoteFiles(false)
|
||||
{
|
||||
if (!gJarProtocolLog)
|
||||
@ -521,8 +518,6 @@ nsJARChannel::GetStatus(nsresult *status)
|
||||
{
|
||||
if (mPump && NS_SUCCEEDED(mStatus))
|
||||
mPump->GetStatus(status);
|
||||
else if (mSynthesizedResponsePump && NS_SUCCEEDED(mStatus))
|
||||
mSynthesizedResponsePump->GetStatus(status);
|
||||
else
|
||||
*status = mStatus;
|
||||
return NS_OK;
|
||||
@ -534,8 +529,6 @@ nsJARChannel::Cancel(nsresult status)
|
||||
mStatus = status;
|
||||
if (mPump)
|
||||
return mPump->Cancel(status);
|
||||
if (mSynthesizedResponsePump)
|
||||
return mSynthesizedResponsePump->Cancel(status);
|
||||
|
||||
NS_ASSERTION(!mIsPending, "need to implement cancel when downloading");
|
||||
return NS_OK;
|
||||
@ -546,8 +539,6 @@ nsJARChannel::Suspend()
|
||||
{
|
||||
if (mPump)
|
||||
return mPump->Suspend();
|
||||
if (mSynthesizedResponsePump)
|
||||
return mSynthesizedResponsePump->Suspend();
|
||||
|
||||
NS_ASSERTION(!mIsPending, "need to implement suspend when downloading");
|
||||
return NS_OK;
|
||||
@ -558,8 +549,6 @@ nsJARChannel::Resume()
|
||||
{
|
||||
if (mPump)
|
||||
return mPump->Resume();
|
||||
if (mSynthesizedResponsePump)
|
||||
return mSynthesizedResponsePump->Resume();
|
||||
|
||||
NS_ASSERTION(!mIsPending, "need to implement resume when downloading");
|
||||
return NS_OK;
|
||||
@ -863,78 +852,6 @@ nsJARChannel::Open2(nsIInputStream** aStream)
|
||||
return Open(aStream);
|
||||
}
|
||||
|
||||
bool
|
||||
nsJARChannel::BypassServiceWorker() const
|
||||
{
|
||||
return mLoadFlags & LOAD_BYPASS_SERVICE_WORKER;
|
||||
}
|
||||
|
||||
bool
|
||||
nsJARChannel::ShouldIntercept()
|
||||
{
|
||||
LOG(("nsJARChannel::ShouldIntercept [this=%x]\n", this));
|
||||
// We only intercept app:// requests
|
||||
if (!mAppURI) {
|
||||
return false;
|
||||
}
|
||||
|
||||
nsCOMPtr<nsINetworkInterceptController> controller;
|
||||
NS_QueryNotificationCallbacks(mCallbacks, mLoadGroup,
|
||||
NS_GET_IID(nsINetworkInterceptController),
|
||||
getter_AddRefs(controller));
|
||||
bool shouldIntercept = false;
|
||||
if (controller && !BypassServiceWorker() && mLoadInfo) {
|
||||
nsresult rv = controller->ShouldPrepareForIntercept(mAppURI,
|
||||
nsContentUtils::IsNonSubresourceRequest(this),
|
||||
&shouldIntercept);
|
||||
NS_ENSURE_SUCCESS(rv, false);
|
||||
}
|
||||
|
||||
return shouldIntercept;
|
||||
}
|
||||
|
||||
void nsJARChannel::ResetInterception()
|
||||
{
|
||||
LOG(("nsJARChannel::ResetInterception [this=%x]\n", this));
|
||||
|
||||
// Continue with the original request.
|
||||
nsresult rv = ContinueAsyncOpen();
|
||||
NS_ENSURE_SUCCESS_VOID(rv);
|
||||
}
|
||||
|
||||
void
|
||||
nsJARChannel::OverrideWithSynthesizedResponse(nsIInputStream* aSynthesizedInput,
|
||||
const nsACString& aContentType)
|
||||
{
|
||||
// In our current implementation, the FetchEvent handler will copy the
|
||||
// response stream completely into the pipe backing the input stream so we
|
||||
// can treat the available as the length of the stream.
|
||||
uint64_t available;
|
||||
nsresult rv = aSynthesizedInput->Available(&available);
|
||||
if (NS_WARN_IF(NS_FAILED(rv))) {
|
||||
mSynthesizedStreamLength = -1;
|
||||
} else {
|
||||
mSynthesizedStreamLength = int64_t(available);
|
||||
}
|
||||
|
||||
rv = nsInputStreamPump::Create(getter_AddRefs(mSynthesizedResponsePump),
|
||||
aSynthesizedInput,
|
||||
int64_t(-1), int64_t(-1), 0, 0, true);
|
||||
if (NS_WARN_IF(NS_FAILED(rv))) {
|
||||
aSynthesizedInput->Close();
|
||||
return;
|
||||
}
|
||||
|
||||
SetContentType(aContentType);
|
||||
|
||||
mIsUnsafe = false;
|
||||
|
||||
FinishAsyncOpen();
|
||||
|
||||
rv = mSynthesizedResponsePump->AsyncRead(this, nullptr);
|
||||
NS_ENSURE_SUCCESS_VOID(rv);
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
nsJARChannel::AsyncOpen(nsIStreamListener *listener, nsISupports *ctx)
|
||||
{
|
||||
@ -961,48 +878,6 @@ nsJARChannel::AsyncOpen(nsIStreamListener *listener, nsISupports *ctx)
|
||||
mListenerContext = ctx;
|
||||
mIsPending = true;
|
||||
|
||||
// Bug 1171651 - Disable the interception of app:// URIs in service workers
|
||||
// on release builds
|
||||
#ifndef RELEASE_BUILD
|
||||
// Check if this channel should intercept the network request and prepare
|
||||
// for a possible synthesized response instead.
|
||||
if (ShouldIntercept()) {
|
||||
nsCOMPtr<nsINetworkInterceptController> controller;
|
||||
NS_QueryNotificationCallbacks(mCallbacks, mLoadGroup,
|
||||
NS_GET_IID(nsINetworkInterceptController),
|
||||
getter_AddRefs(controller));
|
||||
|
||||
RefPtr<InterceptedJARChannel> intercepted =
|
||||
new InterceptedJARChannel(this, controller);
|
||||
intercepted->NotifyController();
|
||||
|
||||
// We get the JAREntry so we can infer the content type later in case
|
||||
// that it isn't provided along with the synthesized response.
|
||||
nsresult rv = mJarURI->GetJAREntry(mJarEntry);
|
||||
if (NS_FAILED(rv)) {
|
||||
return rv;
|
||||
}
|
||||
|
||||
return NS_OK;
|
||||
}
|
||||
#endif
|
||||
|
||||
return ContinueAsyncOpen();
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
nsJARChannel::AsyncOpen2(nsIStreamListener *aListener)
|
||||
{
|
||||
nsCOMPtr<nsIStreamListener> listener = aListener;
|
||||
nsresult rv = nsContentSecurityManager::doContentSecurityCheck(this, listener);
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
return AsyncOpen(listener, nullptr);
|
||||
}
|
||||
|
||||
nsresult
|
||||
nsJARChannel::ContinueAsyncOpen()
|
||||
{
|
||||
LOG(("nsJARChannel::ContinueAsyncOpen [this=%x]\n", this));
|
||||
nsresult rv = LookupFile(true);
|
||||
if (NS_FAILED(rv)) {
|
||||
mIsPending = false;
|
||||
@ -1057,19 +932,21 @@ nsJARChannel::ContinueAsyncOpen()
|
||||
return rv;
|
||||
}
|
||||
|
||||
|
||||
FinishAsyncOpen();
|
||||
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
void
|
||||
nsJARChannel::FinishAsyncOpen()
|
||||
{
|
||||
if (mLoadGroup)
|
||||
mLoadGroup->AddRequest(this, nullptr);
|
||||
|
||||
mOpened = true;
|
||||
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
nsJARChannel::AsyncOpen2(nsIStreamListener *aListener)
|
||||
{
|
||||
nsCOMPtr<nsIStreamListener> listener = aListener;
|
||||
nsresult rv = nsContentSecurityManager::doContentSecurityCheck(this, listener);
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
return AsyncOpen(listener, nullptr);
|
||||
}
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
|
@ -10,7 +10,6 @@
|
||||
#include "nsIJARChannel.h"
|
||||
#include "nsIJARURI.h"
|
||||
#include "nsIInputStreamPump.h"
|
||||
#include "InterceptedJARChannel.h"
|
||||
#include "nsIInterfaceRequestor.h"
|
||||
#include "nsIProgressEventSink.h"
|
||||
#include "nsIStreamListener.h"
|
||||
@ -30,12 +29,6 @@
|
||||
class nsJARInputThunk;
|
||||
class nsInputStreamPump;
|
||||
|
||||
namespace mozilla {
|
||||
namespace net {
|
||||
class InterceptedJARChannel;
|
||||
} // namespace net
|
||||
} // namespace mozilla
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
|
||||
class nsJARChannel final : public nsIJARChannel
|
||||
@ -80,23 +73,6 @@ private:
|
||||
mozilla::net::MemoryDownloader::Data aData)
|
||||
override;
|
||||
|
||||
bool BypassServiceWorker() const;
|
||||
|
||||
// Returns true if this channel should intercept the network request and
|
||||
// prepare for a possible synthesized response instead.
|
||||
bool ShouldIntercept();
|
||||
|
||||
nsresult ContinueAsyncOpen();
|
||||
void FinishAsyncOpen();
|
||||
|
||||
// Discard the prior interception and continue with the original network
|
||||
// request.
|
||||
void ResetInterception();
|
||||
// Override this channel's pending response with a synthesized one. The
|
||||
// content will be asynchronously read from the pump.
|
||||
void OverrideWithSynthesizedResponse(nsIInputStream* aSynthesizedInput,
|
||||
const nsACString& aContentType);
|
||||
|
||||
nsCString mSpec;
|
||||
|
||||
bool mOpened;
|
||||
@ -135,12 +111,8 @@ private:
|
||||
nsCString mJarEntry;
|
||||
nsCString mInnerJarEntry;
|
||||
|
||||
RefPtr<nsInputStreamPump> mSynthesizedResponsePump;
|
||||
int64_t mSynthesizedStreamLength;
|
||||
|
||||
// True if this channel should not download any remote files.
|
||||
bool mBlockRemoteFiles;
|
||||
friend class mozilla::net::InterceptedJARChannel;
|
||||
};
|
||||
|
||||
#endif // nsJARChannel_h__
|
||||
|
@ -15,6 +15,7 @@
|
||||
#include "nsXULAppAPI.h"
|
||||
#include "nsPrincipal.h"
|
||||
#include "nsContentSecurityManager.h"
|
||||
#include "nsContentUtils.h"
|
||||
|
||||
#include "mozilla/dom/ScriptSettings.h"
|
||||
#include "mozilla/Preferences.h"
|
||||
|
Loading…
Reference in New Issue
Block a user