mirror of
https://github.com/mozilla/gecko-dev.git
synced 2024-10-09 11:25:00 +00:00
Bug 924702 - Rewrite the app:// protocol handler in c++ r=jduell
This commit is contained in:
parent
aa7f386126
commit
9ec3e78b23
@ -543,9 +543,6 @@
|
||||
@BINPATH@/components/TCPSocketParentIntermediary.js
|
||||
@BINPATH@/components/TCPSocket.manifest
|
||||
|
||||
@BINPATH@/components/AppProtocolHandler.js
|
||||
@BINPATH@/components/AppProtocolHandler.manifest
|
||||
|
||||
@BINPATH@/components/Payment.js
|
||||
@BINPATH@/components/PaymentFlowInfo.js
|
||||
@BINPATH@/components/PaymentRequestInfo.js
|
||||
|
@ -519,9 +519,6 @@
|
||||
@BINPATH@/components/TCPSocketParentIntermediary.js
|
||||
@BINPATH@/components/TCPSocket.manifest
|
||||
|
||||
@BINPATH@/components/AppProtocolHandler.js
|
||||
@BINPATH@/components/AppProtocolHandler.manifest
|
||||
|
||||
@BINPATH@/components/Payment.js
|
||||
@BINPATH@/components/PaymentFlowInfo.js
|
||||
@BINPATH@/components/PaymentRequestInfo.js
|
||||
|
@ -3986,7 +3986,7 @@ MOZ_PDF_PRINTING=
|
||||
MOZ_DISABLE_CRYPTOLEGACY=
|
||||
NSS_DISABLE_DBM=
|
||||
NECKO_COOKIES=1
|
||||
NECKO_PROTOCOLS_DEFAULT="about data file ftp http res viewsource websocket wyciwyg device"
|
||||
NECKO_PROTOCOLS_DEFAULT="about app data file ftp http res viewsource websocket wyciwyg device"
|
||||
USE_ARM_KUSER=
|
||||
BUILD_CTYPES=1
|
||||
MOZ_USE_NATIVE_POPUP_WINDOWS=
|
||||
|
12
dom/webidl/AppInfo.webidl
Normal file
12
dom/webidl/AppInfo.webidl
Normal file
@ -0,0 +1,12 @@
|
||||
/* 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/. */
|
||||
|
||||
/**
|
||||
* This dictionnary holds the parameters supporting the app:// protocol.
|
||||
*/
|
||||
dictionary AppInfo
|
||||
{
|
||||
DOMString path = "";
|
||||
boolean isCoreApp = false;
|
||||
};
|
@ -28,6 +28,7 @@ interface DummyInterface : EventTarget {
|
||||
void WifiOptions(optional WifiCommandOptions arg1,
|
||||
optional WifiResultOptions arg2);
|
||||
void AppNotificationServiceOptions(optional AppNotificationServiceOptions arg);
|
||||
void AppInfo(optional AppInfo arg1);
|
||||
};
|
||||
|
||||
interface DummyInterfaceWorkers {
|
||||
|
@ -19,6 +19,7 @@ WEBIDL_FILES = [
|
||||
'AbstractWorker.webidl',
|
||||
'AnalyserNode.webidl',
|
||||
'AnimationEvent.webidl',
|
||||
'AppInfo.webidl',
|
||||
'AppNotificationServiceOptions.webidl',
|
||||
'ArchiveReader.webidl',
|
||||
'ArchiveRequest.webidl',
|
||||
|
@ -385,8 +385,6 @@
|
||||
@BINPATH@/components/Webapps.manifest
|
||||
@BINPATH@/components/AppsService.js
|
||||
@BINPATH@/components/AppsService.manifest
|
||||
@BINPATH@/components/AppProtocolHandler.js
|
||||
@BINPATH@/components/AppProtocolHandler.manifest
|
||||
|
||||
@BINPATH@/components/Push.js
|
||||
@BINPATH@/components/Push.manifest
|
||||
|
@ -69,6 +69,7 @@ LOCAL_INCLUDES = \
|
||||
-I$(srcdir)/../mime \
|
||||
-I$(srcdir)/../cache \
|
||||
-I$(srcdir)/../protocol/about \
|
||||
-I$(srcdir)/../protocol/app \
|
||||
-I../dns \
|
||||
$(foreach d,$(filter-out about,$(NECKO_PROTOCOLS)), \
|
||||
-I$(srcdir)/../protocol/$(d)) \
|
||||
|
@ -602,6 +602,18 @@
|
||||
{0x93, 0x44, 0x00, 0x10, 0x4b, 0xa0, 0xfd, 0x40} \
|
||||
}
|
||||
|
||||
/******************************************************************************
|
||||
* netwerk/protocol/app/ classes
|
||||
*/
|
||||
|
||||
#define NS_APPPROTOCOLHANDLER_CID \
|
||||
{ /* {B6ED3030-9999-11d3-A178-0050041CAF44} */ \
|
||||
0xb6ed3030, \
|
||||
0x9999, \
|
||||
0x11d3, \
|
||||
{0xa1, 0x78, 0x00, 0x50, 0x04, 0x1c, 0xaf, 0x44} \
|
||||
}
|
||||
|
||||
/******************************************************************************
|
||||
* netwerk/protocol/data/ classes
|
||||
*/
|
||||
|
@ -243,6 +243,7 @@ namespace net {
|
||||
NS_GENERIC_FACTORY_CONSTRUCTOR(Dashboard)
|
||||
}
|
||||
}
|
||||
#include "AppProtocolHandler.h"
|
||||
|
||||
#ifdef NECKO_PROTOCOL_res
|
||||
// resource
|
||||
@ -772,6 +773,7 @@ NS_DEFINE_NAMED_CID(NS_CACHESERVICE_CID);
|
||||
NS_DEFINE_NAMED_CID(NS_APPLICATIONCACHESERVICE_CID);
|
||||
NS_DEFINE_NAMED_CID(NS_APPLICATIONCACHENAMESPACE_CID);
|
||||
NS_DEFINE_NAMED_CID(NS_APPLICATIONCACHE_CID);
|
||||
NS_DEFINE_NAMED_CID(NS_APPPROTOCOLHANDLER_CID);
|
||||
#ifdef NECKO_COOKIES
|
||||
NS_DEFINE_NAMED_CID(NS_COOKIEMANAGER_CID);
|
||||
NS_DEFINE_NAMED_CID(NS_COOKIESERVICE_CID);
|
||||
@ -910,6 +912,7 @@ static const mozilla::Module::CIDEntry kNeckoCIDs[] = {
|
||||
{ &kNS_APPLICATIONCACHESERVICE_CID, false, nullptr, nsApplicationCacheServiceConstructor },
|
||||
{ &kNS_APPLICATIONCACHENAMESPACE_CID, false, nullptr, nsApplicationCacheNamespaceConstructor },
|
||||
{ &kNS_APPLICATIONCACHE_CID, false, nullptr, nsApplicationCacheConstructor },
|
||||
{ &kNS_APPPROTOCOLHANDLER_CID, false, nullptr, AppProtocolHandler::Create },
|
||||
#ifdef NECKO_COOKIES
|
||||
{ &kNS_COOKIEMANAGER_CID, false, nullptr, nsICookieServiceConstructor },
|
||||
{ &kNS_COOKIESERVICE_CID, false, nullptr, nsICookieServiceConstructor },
|
||||
@ -1055,6 +1058,7 @@ static const mozilla::Module::ContractIDEntry kNeckoContracts[] = {
|
||||
{ NS_APPLICATIONCACHESERVICE_CONTRACTID, &kNS_APPLICATIONCACHESERVICE_CID },
|
||||
{ NS_APPLICATIONCACHENAMESPACE_CONTRACTID, &kNS_APPLICATIONCACHENAMESPACE_CID },
|
||||
{ NS_APPLICATIONCACHE_CONTRACTID, &kNS_APPLICATIONCACHE_CID },
|
||||
{ NS_NETWORK_PROTOCOL_CONTRACTID_PREFIX "app", &kNS_APPPROTOCOLHANDLER_CID },
|
||||
#ifdef NECKO_COOKIES
|
||||
{ NS_COOKIEMANAGER_CONTRACTID, &kNS_COOKIEMANAGER_CID },
|
||||
{ NS_COOKIESERVICE_CONTRACTID, &kNS_COOKIESERVICE_CID },
|
||||
|
424
netwerk/protocol/app/AppProtocolHandler.cpp
Normal file
424
netwerk/protocol/app/AppProtocolHandler.cpp
Normal file
@ -0,0 +1,424 @@
|
||||
/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
|
||||
/* vim:set expandtab ts=4 sw=4 sts=4 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 "AppProtocolHandler.h"
|
||||
#include "nsBaseChannel.h"
|
||||
#include "nsJARChannel.h"
|
||||
#include "nsNetCID.h"
|
||||
#include "nsIAppsService.h"
|
||||
#include "nsCxPusher.h"
|
||||
#include "nsXULAppAPI.h"
|
||||
|
||||
/**
|
||||
* This dummy channel implementation only provides enough functionality
|
||||
* to return a fake 404 error when the caller asks for an app:// URL
|
||||
* containing an unknown appId.
|
||||
*/
|
||||
class DummyChannel : public nsIJARChannel
|
||||
, nsRunnable
|
||||
{
|
||||
public:
|
||||
NS_DECL_ISUPPORTS
|
||||
NS_DECL_NSIREQUEST
|
||||
NS_DECL_NSICHANNEL
|
||||
NS_DECL_NSIJARCHANNEL
|
||||
|
||||
DummyChannel();
|
||||
|
||||
NS_IMETHODIMP Run();
|
||||
|
||||
private:
|
||||
bool mPending;
|
||||
uint32_t mSuspendCount;
|
||||
nsCOMPtr<nsISupports> mListenerContext;
|
||||
nsCOMPtr<nsIStreamListener> mListener;
|
||||
nsCOMPtr<nsILoadGroup> mLoadGroup;
|
||||
nsLoadFlags mLoadFlags;
|
||||
};
|
||||
|
||||
NS_IMPL_ISUPPORTS3(DummyChannel, nsIRequest, nsIChannel, nsIJARChannel)
|
||||
|
||||
DummyChannel::DummyChannel() : mPending(false)
|
||||
, mSuspendCount(0)
|
||||
, mLoadFlags(LOAD_NORMAL)
|
||||
{
|
||||
}
|
||||
|
||||
NS_IMETHODIMP DummyChannel::GetName(nsACString &result)
|
||||
{
|
||||
result = "dummy_app_channel";
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
NS_IMETHODIMP DummyChannel::GetStatus(nsresult *aStatus)
|
||||
{
|
||||
*aStatus = NS_ERROR_FILE_NOT_FOUND;
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
NS_IMETHODIMP DummyChannel::IsPending(bool *aResult)
|
||||
{
|
||||
*aResult = mPending;
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
NS_IMETHODIMP DummyChannel::Suspend()
|
||||
{
|
||||
mSuspendCount++;
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
NS_IMETHODIMP DummyChannel::Resume()
|
||||
{
|
||||
if (mSuspendCount <= 0) {
|
||||
return NS_ERROR_UNEXPECTED;
|
||||
}
|
||||
|
||||
if (--mSuspendCount == 0) {
|
||||
NS_DispatchToMainThread(this, NS_DISPATCH_NORMAL);
|
||||
}
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
NS_IMETHODIMP DummyChannel::Open(nsIInputStream**)
|
||||
{
|
||||
return NS_ERROR_NOT_IMPLEMENTED;
|
||||
}
|
||||
|
||||
NS_IMETHODIMP DummyChannel::AsyncOpen(nsIStreamListener* aListener, nsISupports* aContext)
|
||||
{
|
||||
mListener = aListener;
|
||||
mListenerContext = aContext;
|
||||
mPending = true;
|
||||
|
||||
if (mLoadGroup) {
|
||||
mLoadGroup->AddRequest(this, aContext);
|
||||
}
|
||||
|
||||
if (mSuspendCount == 0) {
|
||||
NS_DispatchToMainThread(this, NS_DISPATCH_NORMAL);
|
||||
}
|
||||
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
// nsIJarChannel, needed for XHR to turn NS_ERROR_FILE_NOT_FOUND into
|
||||
// a 404 error.
|
||||
NS_IMETHODIMP DummyChannel::GetIsUnsafe(bool *aResult)
|
||||
{
|
||||
*aResult = false;
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
NS_IMETHODIMP DummyChannel::SetAppURI(nsIURI *aURI)
|
||||
{
|
||||
return NS_ERROR_NOT_IMPLEMENTED;
|
||||
}
|
||||
|
||||
NS_IMETHODIMP DummyChannel::Run()
|
||||
{
|
||||
nsresult rv = mListener->OnStartRequest(this, mListenerContext);
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
mPending = false;
|
||||
rv = mListener->OnStopRequest(this, mListenerContext, NS_ERROR_FILE_NOT_FOUND);
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
if (mLoadGroup) {
|
||||
mLoadGroup->RemoveRequest(this, mListenerContext, NS_ERROR_FILE_NOT_FOUND);
|
||||
}
|
||||
|
||||
mListener = nullptr;
|
||||
mListenerContext = nullptr;
|
||||
rv = SetNotificationCallbacks(nullptr);
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
NS_IMETHODIMP DummyChannel::Cancel(nsresult)
|
||||
{
|
||||
return NS_ERROR_NOT_IMPLEMENTED;
|
||||
}
|
||||
|
||||
NS_IMETHODIMP DummyChannel::GetLoadGroup(nsILoadGroup* *aLoadGroup)
|
||||
{
|
||||
*aLoadGroup = mLoadGroup;
|
||||
NS_IF_ADDREF(*aLoadGroup);
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
NS_IMETHODIMP DummyChannel::SetLoadGroup(nsILoadGroup* aLoadGroup)
|
||||
{
|
||||
mLoadGroup = aLoadGroup;
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
NS_IMETHODIMP DummyChannel::GetLoadFlags(nsLoadFlags *aLoadFlags)
|
||||
{
|
||||
*aLoadFlags = mLoadFlags;
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
NS_IMETHODIMP DummyChannel::SetLoadFlags(nsLoadFlags aLoadFlags)
|
||||
{
|
||||
mLoadFlags = aLoadFlags;
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
NS_IMETHODIMP DummyChannel::GetOriginalURI(nsIURI**)
|
||||
{
|
||||
return NS_ERROR_NOT_IMPLEMENTED;
|
||||
}
|
||||
|
||||
NS_IMETHODIMP DummyChannel::SetOriginalURI(nsIURI*)
|
||||
{
|
||||
return NS_ERROR_NOT_IMPLEMENTED;
|
||||
}
|
||||
|
||||
NS_IMETHODIMP DummyChannel::GetOwner(nsISupports**)
|
||||
{
|
||||
return NS_ERROR_NOT_IMPLEMENTED;
|
||||
}
|
||||
|
||||
NS_IMETHODIMP DummyChannel::SetOwner(nsISupports*)
|
||||
{
|
||||
return NS_ERROR_NOT_IMPLEMENTED;
|
||||
}
|
||||
|
||||
NS_IMETHODIMP DummyChannel::GetNotificationCallbacks(nsIInterfaceRequestor**)
|
||||
{
|
||||
return NS_ERROR_NOT_IMPLEMENTED;
|
||||
}
|
||||
|
||||
NS_IMETHODIMP DummyChannel::SetNotificationCallbacks(nsIInterfaceRequestor*)
|
||||
{
|
||||
return NS_ERROR_NOT_IMPLEMENTED;
|
||||
}
|
||||
|
||||
NS_IMETHODIMP DummyChannel::GetSecurityInfo(nsISupports**)
|
||||
{
|
||||
return NS_ERROR_NOT_IMPLEMENTED;
|
||||
}
|
||||
|
||||
NS_IMETHODIMP DummyChannel::GetContentType(nsACString&)
|
||||
{
|
||||
return NS_ERROR_NOT_IMPLEMENTED;
|
||||
}
|
||||
|
||||
NS_IMETHODIMP DummyChannel::SetContentType(const nsACString&)
|
||||
{
|
||||
return NS_ERROR_NOT_IMPLEMENTED;
|
||||
}
|
||||
|
||||
NS_IMETHODIMP DummyChannel::GetContentCharset(nsACString&)
|
||||
{
|
||||
return NS_ERROR_NOT_IMPLEMENTED;
|
||||
}
|
||||
|
||||
NS_IMETHODIMP DummyChannel::SetContentCharset(const nsACString&)
|
||||
{
|
||||
return NS_ERROR_NOT_IMPLEMENTED;
|
||||
}
|
||||
|
||||
NS_IMETHODIMP DummyChannel::GetContentLength(int64_t*)
|
||||
{
|
||||
return NS_ERROR_NOT_IMPLEMENTED;
|
||||
}
|
||||
|
||||
NS_IMETHODIMP DummyChannel::SetContentLength(int64_t)
|
||||
{
|
||||
return NS_ERROR_NOT_IMPLEMENTED;
|
||||
}
|
||||
|
||||
NS_IMETHODIMP DummyChannel::GetContentDisposition(uint32_t*)
|
||||
{
|
||||
return NS_ERROR_NOT_IMPLEMENTED;
|
||||
}
|
||||
|
||||
NS_IMETHODIMP DummyChannel::SetContentDisposition(uint32_t)
|
||||
{
|
||||
return NS_ERROR_NOT_IMPLEMENTED;
|
||||
}
|
||||
|
||||
NS_IMETHODIMP DummyChannel::GetURI(nsIURI**)
|
||||
{
|
||||
return NS_ERROR_NOT_IMPLEMENTED;
|
||||
}
|
||||
|
||||
NS_IMETHODIMP DummyChannel::GetContentDispositionFilename(nsAString&)
|
||||
{
|
||||
return NS_ERROR_NOT_IMPLEMENTED;
|
||||
}
|
||||
|
||||
NS_IMETHODIMP DummyChannel::SetContentDispositionFilename(nsAString const &)
|
||||
{
|
||||
return NS_ERROR_NOT_IMPLEMENTED;
|
||||
}
|
||||
|
||||
NS_IMETHODIMP DummyChannel::GetContentDispositionHeader(nsACString&)
|
||||
{
|
||||
return NS_ERROR_NOT_IMPLEMENTED;
|
||||
}
|
||||
|
||||
/**
|
||||
* app:// protocol implementation.
|
||||
*/
|
||||
|
||||
AppProtocolHandler::AppProtocolHandler() {
|
||||
}
|
||||
|
||||
AppProtocolHandler::~AppProtocolHandler() {
|
||||
mAppInfoCache.Clear();
|
||||
}
|
||||
|
||||
NS_IMPL_ISUPPORTS1(AppProtocolHandler, nsIProtocolHandler)
|
||||
|
||||
/* static */
|
||||
nsresult
|
||||
AppProtocolHandler::Create(nsISupports* aOuter,
|
||||
const nsIID& aIID,
|
||||
void* *aResult)
|
||||
{
|
||||
AppProtocolHandler* ph = new AppProtocolHandler();
|
||||
if (ph == nullptr) {
|
||||
return NS_ERROR_OUT_OF_MEMORY;
|
||||
}
|
||||
NS_ADDREF(ph);
|
||||
nsresult rv = ph->QueryInterface(aIID, aResult);
|
||||
NS_RELEASE(ph);
|
||||
return rv;
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
AppProtocolHandler::GetScheme(nsACString &aResult)
|
||||
{
|
||||
aResult.AssignLiteral("app");
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
AppProtocolHandler::GetDefaultPort(int32_t *aResult)
|
||||
{
|
||||
// No ports for the app protocol.
|
||||
*aResult = -1;
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
AppProtocolHandler::GetProtocolFlags(uint32_t *aResult)
|
||||
{
|
||||
*aResult = URI_NOAUTH |
|
||||
URI_DANGEROUS_TO_LOAD |
|
||||
URI_CROSS_ORIGIN_NEEDS_WEBAPPS_PERM;
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
AppProtocolHandler::NewURI(const nsACString &aSpec,
|
||||
const char *aCharset, // ignore charset info
|
||||
nsIURI *aBaseURI,
|
||||
nsIURI **result)
|
||||
{
|
||||
nsresult rv;
|
||||
nsCOMPtr<nsIStandardURL> surl(do_CreateInstance(NS_STANDARDURL_CONTRACTID, &rv));
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
|
||||
rv = surl->Init(nsIStandardURL::URLTYPE_STANDARD, -1, aSpec, aCharset, aBaseURI);
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
|
||||
nsCOMPtr<nsIURL> url(do_QueryInterface(surl, &rv));
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
|
||||
surl->SetMutable(false);
|
||||
NS_ADDREF(*result = url);
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
// We map app://ABCDEF/path/to/file.ext to
|
||||
// jar:file:///path/to/profile/webapps/ABCDEF/application.zip!/path/to/file.ext
|
||||
NS_IMETHODIMP
|
||||
AppProtocolHandler::NewChannel(nsIURI* aUri, nsIChannel* *aResult)
|
||||
{
|
||||
NS_ENSURE_ARG_POINTER(aUri);
|
||||
nsJARChannel* channel = new nsJARChannel();
|
||||
if (!channel) {
|
||||
return NS_ERROR_OUT_OF_MEMORY;
|
||||
}
|
||||
|
||||
nsAutoCString host;
|
||||
nsresult rv = aUri->GetHost(host);
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
|
||||
nsAutoCString fileSpec;
|
||||
nsCOMPtr<nsIURL> url = do_QueryInterface(aUri);
|
||||
rv = url->GetFilePath(fileSpec);
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
|
||||
mozilla::dom::AppInfo appInfo;
|
||||
|
||||
if (!mAppInfoCache.Get(host, &appInfo)) {
|
||||
nsCOMPtr<nsIAppsService> appsService = do_GetService(APPS_SERVICE_CONTRACTID);
|
||||
if (!appsService) {
|
||||
return NS_ERROR_FAILURE;
|
||||
}
|
||||
|
||||
JS::Value jsInfo;
|
||||
rv = appsService->GetAppInfo(NS_ConvertUTF8toUTF16(host), &jsInfo);
|
||||
if (NS_FAILED(rv)) {
|
||||
// Return a DummyChannel.
|
||||
delete channel;
|
||||
NS_IF_ADDREF(*aResult = new DummyChannel());
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
mozilla::AutoSafeJSContext cx;
|
||||
if (!appInfo.Init(cx, JS::Handle<JS::Value>::fromMarkedLocation(&jsInfo)) ||
|
||||
appInfo.mPath.IsEmpty()) {
|
||||
printf_stderr("!! No appInfo for %s\n", host.get());
|
||||
// Return a DummyChannel.
|
||||
delete channel;
|
||||
NS_IF_ADDREF(*aResult = new DummyChannel());
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
mAppInfoCache.Put(host, appInfo);
|
||||
}
|
||||
|
||||
bool noRemote = (appInfo.mIsCoreApp ||
|
||||
XRE_GetProcessType() == GeckoProcessType_Default);
|
||||
|
||||
// In-parent and CoreApps can directly access files, so use jar:file://
|
||||
nsAutoCString jarSpec(noRemote ? "jar:file://"
|
||||
: "jar:remoteopenfile://");
|
||||
jarSpec += NS_ConvertUTF16toUTF8(appInfo.mPath) +
|
||||
NS_LITERAL_CSTRING("/application.zip!") +
|
||||
fileSpec;
|
||||
|
||||
nsCOMPtr<nsIURI> jarURI;
|
||||
rv = NS_NewURI(getter_AddRefs(jarURI),
|
||||
jarSpec, nullptr, nullptr);
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
|
||||
rv = channel->Init(jarURI);
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
|
||||
rv = channel->SetAppURI(aUri);
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
|
||||
rv = channel->SetOriginalURI(aUri);
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
|
||||
NS_ADDREF(*aResult = channel);
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
AppProtocolHandler::AllowPort(int32_t aPort, const char *aScheme, bool *aRetval)
|
||||
{
|
||||
// No port allowed for this scheme.
|
||||
*aRetval = false;
|
||||
return NS_OK;
|
||||
}
|
||||
|
35
netwerk/protocol/app/AppProtocolHandler.h
Normal file
35
netwerk/protocol/app/AppProtocolHandler.h
Normal file
@ -0,0 +1,35 @@
|
||||
/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
|
||||
/* vim:set expandtab ts=4 sw=4 sts=4 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 AppProtocolHandler_
|
||||
#define AppProtocolHandler_
|
||||
|
||||
#include "nsIProtocolHandler.h"
|
||||
#include "nsDataHashtable.h"
|
||||
#include "mozilla/dom/AppInfoBinding.h"
|
||||
|
||||
class AppProtocolHandler : public nsIProtocolHandler
|
||||
{
|
||||
public:
|
||||
NS_DECL_ISUPPORTS
|
||||
|
||||
// nsIProtocolHandler methods:
|
||||
NS_DECL_NSIPROTOCOLHANDLER
|
||||
|
||||
// AppProtocolHandler methods:
|
||||
AppProtocolHandler();
|
||||
virtual ~AppProtocolHandler();
|
||||
|
||||
// Define a Create method to be used with a factory:
|
||||
static nsresult Create(nsISupports* aOuter,
|
||||
const nsIID& aIID,
|
||||
void* *aResult);
|
||||
|
||||
private:
|
||||
nsDataHashtable<nsCStringHashKey, mozilla::dom::AppInfo> mAppInfoCache;
|
||||
};
|
||||
|
||||
#endif /* AppProtocolHandler_ */
|
@ -1,197 +0,0 @@
|
||||
/* 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/. */
|
||||
|
||||
"use strict";
|
||||
|
||||
const Cc = Components.classes;
|
||||
const Ci = Components.interfaces;
|
||||
const Cu = Components.utils;
|
||||
const Cr = Components.results;
|
||||
|
||||
Cu.import("resource://gre/modules/XPCOMUtils.jsm");
|
||||
Cu.import("resource://gre/modules/Services.jsm");
|
||||
|
||||
XPCOMUtils.defineLazyServiceGetter(this, "appsService",
|
||||
"@mozilla.org/AppsService;1",
|
||||
"nsIAppsService");
|
||||
|
||||
function AppProtocolHandler() {
|
||||
this._appInfo = [];
|
||||
this._runningInParent = Cc["@mozilla.org/xre/runtime;1"]
|
||||
.getService(Ci.nsIXULRuntime)
|
||||
.processType == Ci.nsIXULRuntime.PROCESS_TYPE_DEFAULT;
|
||||
}
|
||||
|
||||
AppProtocolHandler.prototype = {
|
||||
classID: Components.ID("{b7ad6144-d344-4687-b2d0-b6b9dce1f07f}"),
|
||||
QueryInterface: XPCOMUtils.generateQI([Ci.nsIProtocolHandler]),
|
||||
|
||||
scheme: "app",
|
||||
defaultPort: -1,
|
||||
// Don't allow loading from other protocols, and only from app:// if webapps is granted
|
||||
protocolFlags: Ci.nsIProtocolHandler.URI_NOAUTH |
|
||||
Ci.nsIProtocolHandler.URI_DANGEROUS_TO_LOAD |
|
||||
Ci.nsIProtocolHandler.URI_CROSS_ORIGIN_NEEDS_WEBAPPS_PERM,
|
||||
|
||||
getAppInfo: function app_phGetAppInfo(aId) {
|
||||
|
||||
if (!this._appInfo[aId]) {
|
||||
this._appInfo[aId] = appsService.getAppInfo(aId);
|
||||
}
|
||||
return this._appInfo[aId];
|
||||
},
|
||||
|
||||
newURI: function app_phNewURI(aSpec, aOriginCharset, aBaseURI) {
|
||||
let uri = Cc["@mozilla.org/network/standard-url;1"]
|
||||
.createInstance(Ci.nsIStandardURL);
|
||||
uri.init(Ci.nsIStandardURL.URLTYPE_STANDARD, -1, aSpec, aOriginCharset,
|
||||
aBaseURI);
|
||||
return uri.QueryInterface(Ci.nsIURI);
|
||||
},
|
||||
|
||||
newChannel: function app_phNewChannel(aURI) {
|
||||
// We map app://ABCDEF/path/to/file.ext to
|
||||
// jar:file:///path/to/profile/webapps/ABCDEF/application.zip!/path/to/file.ext
|
||||
let url = aURI.QueryInterface(Ci.nsIURL);
|
||||
let appId = aURI.host;
|
||||
let fileSpec = url.filePath;
|
||||
|
||||
// Build a jar channel and masquerade as an app:// URI.
|
||||
let appInfo = this.getAppInfo(appId);
|
||||
if (!appInfo) {
|
||||
// That should not happen, so dump() inconditionnally.
|
||||
// We create a dummy channel instead of throwing to let the
|
||||
// downstream user get a 404 error.
|
||||
dump("!! got no appInfo for " + appId + "\n");
|
||||
return new DummyChannel();
|
||||
}
|
||||
|
||||
let uri;
|
||||
if (this._runningInParent || appInfo.isCoreApp) {
|
||||
// In-parent and CoreApps can directly access files, so use jar:file://
|
||||
uri = "jar:file://" + appInfo.path + "/application.zip!" + fileSpec;
|
||||
} else {
|
||||
// non-CoreApps in child need to ask parent for file handle, use jar:ipcfile://
|
||||
uri = "jar:remoteopenfile://" + appInfo.path + "/application.zip!" + fileSpec;
|
||||
}
|
||||
let channel = Services.io.newChannel(uri, null, null);
|
||||
channel.QueryInterface(Ci.nsIJARChannel).setAppURI(aURI);
|
||||
channel.QueryInterface(Ci.nsIChannel).originalURI = aURI;
|
||||
|
||||
return channel;
|
||||
},
|
||||
|
||||
allowPort: function app_phAllowPort(aPort, aScheme) {
|
||||
return false;
|
||||
}
|
||||
};
|
||||
|
||||
/**
|
||||
* This dummy channel implementation only provides enough functionality
|
||||
* to return a fake 404 error when the caller asks for an app:// URL
|
||||
* containing an unknown appId.
|
||||
*/
|
||||
function DummyChannel() {
|
||||
this.originalURI = Services.io.newURI("app://unknown/nothing.html", null, null);
|
||||
this.URI = Services.io.newURI("app://unknown/nothing.html", null, null);
|
||||
}
|
||||
|
||||
DummyChannel.prototype = {
|
||||
QueryInterface: XPCOMUtils.generateQI([Ci.nsIRequest,
|
||||
Ci.nsIChannel,
|
||||
Ci.nsIJARChannel]),
|
||||
|
||||
// nsIRequest
|
||||
name: "dummy_app_channel",
|
||||
|
||||
isPending: function dc_isPending() {
|
||||
return this._pending;
|
||||
},
|
||||
|
||||
status: Cr.NS_ERROR_FILE_NOT_FOUND,
|
||||
|
||||
cancel: function dc_cancel() {
|
||||
},
|
||||
|
||||
suspend: function dc_suspend() {
|
||||
this._suspendCount++;
|
||||
},
|
||||
|
||||
resume: function dc_resume() {
|
||||
if (this._suspendCount <= 0)
|
||||
throw Cr.NS_ERROR_UNEXPECTED;
|
||||
|
||||
if (--this._suspendCount == 0 && this._pending) {
|
||||
this._dispatch();
|
||||
}
|
||||
},
|
||||
|
||||
loadGroup: null,
|
||||
loadFlags: Ci.nsIRequest.LOAD_NORMAL,
|
||||
|
||||
// nsIChannel
|
||||
owner: null,
|
||||
notificationCallbacks: null,
|
||||
securityInfo: null,
|
||||
contentType: null,
|
||||
contentCharset: null,
|
||||
contentLength: 0,
|
||||
contentDisposition: Ci.nsIChannel.DISPOSITION_INLINE,
|
||||
contentDispositionFilename: "",
|
||||
|
||||
_pending: false,
|
||||
_suspendCount: 0,
|
||||
_listener: null,
|
||||
_context: null,
|
||||
|
||||
open: function dc_open() {
|
||||
return Cr.NS_ERROR_NOT_IMPLEMENTED;
|
||||
},
|
||||
|
||||
_dispatch: function dc_dispatch() {
|
||||
let request = this;
|
||||
|
||||
Services.tm.currentThread.dispatch(
|
||||
{
|
||||
run: function dc_run() {
|
||||
request._listener.onStartRequest(request, request._context);
|
||||
request._listener.onStopRequest(request, request._context,
|
||||
Cr.NS_ERROR_FILE_NOT_FOUND);
|
||||
if (request.loadGroup) {
|
||||
request.loadGroup.removeRequest(request, request._context,
|
||||
Cr.NS_ERROR_FILE_NOT_FOUND);
|
||||
}
|
||||
request._pending = false;
|
||||
request.notificationCallbacks = null;
|
||||
request._listener = null;
|
||||
request._context = null;
|
||||
}
|
||||
},
|
||||
Ci.nsIThread.DISPATCH_NORMAL);
|
||||
},
|
||||
|
||||
asyncOpen: function dc_asyncopenfunction(aListener, aContext) {
|
||||
if (this.loadGroup) {
|
||||
this.loadGroup.addRequest(this, aContext);
|
||||
}
|
||||
|
||||
this._listener = aListener;
|
||||
this._context = aContext;
|
||||
this._pending = true;
|
||||
|
||||
if (!this._suspended) {
|
||||
this._dispatch();
|
||||
}
|
||||
},
|
||||
|
||||
// nsIJarChannel, needed for XHR to turn NS_ERROR_FILE_NOT_FOUND into
|
||||
// a 404 error.
|
||||
isUnsafe: false,
|
||||
|
||||
setAppURI: function(aURI) {
|
||||
throw Cr.NS_ERROR_NOT_IMPLEMENTED;
|
||||
}
|
||||
};
|
||||
|
||||
this.NSGetFactory = XPCOMUtils.generateNSGetFactory([AppProtocolHandler]);
|
@ -1,3 +0,0 @@
|
||||
# AppProtocolHander.js
|
||||
component {b7ad6144-d344-4687-b2d0-b6b9dce1f07f} AppProtocolHandler.js
|
||||
contract @mozilla.org/network/protocol;1?name=app {b7ad6144-d344-4687-b2d0-b6b9dce1f07f}
|
9
netwerk/protocol/app/Makefile.in
Normal file
9
netwerk/protocol/app/Makefile.in
Normal file
@ -0,0 +1,9 @@
|
||||
#
|
||||
# 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/.
|
||||
|
||||
LOCAL_INCLUDES = \
|
||||
-I$(srcdir)/../../base/src \
|
||||
-I$(srcdir)/../../../modules/libjar \
|
||||
$(NULL)
|
@ -4,7 +4,15 @@
|
||||
# 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/.
|
||||
|
||||
EXTRA_COMPONENTS += [
|
||||
'AppProtocolHandler.js',
|
||||
'AppProtocolHandler.manifest',
|
||||
MODULE = 'necko'
|
||||
|
||||
CPP_SOURCES += [
|
||||
'AppProtocolHandler.cpp',
|
||||
]
|
||||
|
||||
LIBRARY_NAME = 'nkapp_s'
|
||||
|
||||
FAIL_ON_WARNINGS = True
|
||||
|
||||
LIBXUL_LIBRARY = True
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user