mirror of
https://github.com/mozilla/gecko-dev.git
synced 2025-02-04 13:07:52 +00:00
Bug 1620657 - Add a native impl of nsIExternalHelperAppService for Android r=mattwoodrow,geckoview-reviewers,droeh
This is needed in order to implement `CreateListener()`, which is used when DocumentChannel is enabled. Differential Revision: https://phabricator.services.mozilla.com/D67682 --HG-- extra : moz-landing-system : lando
This commit is contained in:
parent
da72652618
commit
9b0c905638
@ -64,19 +64,6 @@ Classes = [
|
||||
'jsm': 'resource://gre/modules/URIFixup.jsm',
|
||||
'constructor': 'URIFixupInfo',
|
||||
},
|
||||
{
|
||||
'cid': '{a7f800e0-4306-11d4-98d0-001083010e9b}',
|
||||
'contract_ids': [
|
||||
'@mozilla.org/mime;1',
|
||||
'@mozilla.org/uriloader/external-helper-app-service;1',
|
||||
'@mozilla.org/uriloader/external-protocol-service;1',
|
||||
],
|
||||
'type': 'nsExternalHelperAppService',
|
||||
'constructor': 'nsExternalHelperAppService::GetSingleton',
|
||||
'headers': ['nsExternalHelperAppService.h'],
|
||||
'init_method': 'Init',
|
||||
'processes': ProcessSelector.ALLOW_IN_SOCKET_PROCESS,
|
||||
},
|
||||
{
|
||||
'cid': '{56ebedd4-6ccf-48e8-bdae-adc77f044567}',
|
||||
'contract_ids': [
|
||||
@ -165,4 +152,34 @@ if buildconfig.substs['MOZ_WIDGET_TOOLKIT'] == 'android':
|
||||
'type': 'nsExternalURLHandlerService',
|
||||
'headers': ['nsExternalURLHandlerService.h'],
|
||||
},
|
||||
# Android has its own externel-helper-app-service, so we omit
|
||||
# that here for nsExternalHelperAppService.
|
||||
{
|
||||
'cid': '{a7f800e0-4306-11d4-98d0-001083010e9b}',
|
||||
'contract_ids': [
|
||||
'@mozilla.org/mime;1',
|
||||
'@mozilla.org/uriloader/external-protocol-service;1',
|
||||
],
|
||||
'type': 'nsExternalHelperAppService',
|
||||
'constructor': 'nsExternalHelperAppService::GetSingleton',
|
||||
'headers': ['nsExternalHelperAppService.h'],
|
||||
'init_method': 'Init',
|
||||
'processes': ProcessSelector.ALLOW_IN_SOCKET_PROCESS,
|
||||
},
|
||||
]
|
||||
else:
|
||||
Classes += [
|
||||
{
|
||||
'cid': '{a7f800e0-4306-11d4-98d0-001083010e9b}',
|
||||
'contract_ids': [
|
||||
'@mozilla.org/mime;1',
|
||||
'@mozilla.org/uriloader/external-helper-app-service;1',
|
||||
'@mozilla.org/uriloader/external-protocol-service;1',
|
||||
],
|
||||
'type': 'nsExternalHelperAppService',
|
||||
'constructor': 'nsExternalHelperAppService::GetSingleton',
|
||||
'headers': ['nsExternalHelperAppService.h'],
|
||||
'init_method': 'Init',
|
||||
'processes': ProcessSelector.ALLOW_IN_SOCKET_PROCESS,
|
||||
},
|
||||
]
|
@ -30,10 +30,6 @@ contract @mozilla.org/sharepicker;1 {1201d357-8417-4926-a694-e6408fbedcf8} proce
|
||||
component {3d765750-1c3d-11ea-aaef-0800200c9a66} GeckoViewPrompt.js process=main
|
||||
contract @mozilla.org/login-manager/prompter;1 {3d765750-1c3d-11ea-aaef-0800200c9a66} process=main
|
||||
|
||||
# GeckoViewExternalAppService.js
|
||||
component {a89eeec6-6608-42ee-a4f8-04d425992f45} GeckoViewExternalAppService.js
|
||||
contract @mozilla.org/uriloader/external-helper-app-service;1 {a89eeec6-6608-42ee-a4f8-04d425992f45}
|
||||
|
||||
# GeckoViewPush.js
|
||||
component {a54d84d7-98a4-4fec-b664-e42e512ae9cc} GeckoViewPush.js
|
||||
contract @mozilla.org/push/Service;1 {a54d84d7-98a4-4fec-b664-e42e512ae9cc}
|
||||
|
@ -0,0 +1,135 @@
|
||||
/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*-
|
||||
* 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 "GeckoViewExternalAppService.h"
|
||||
|
||||
#include "mozilla/dom/BrowsingContext.h"
|
||||
#include "mozilla/dom/CanonicalBrowsingContext.h"
|
||||
#include "mozilla/dom/WindowGlobalParent.h"
|
||||
|
||||
#include "mozilla/widget/EventDispatcher.h"
|
||||
#include "mozilla/widget/nsWindow.h"
|
||||
|
||||
#include "JavaBuiltins.h"
|
||||
|
||||
static const char16_t kExternalResponseMessage[] =
|
||||
u"GeckoView:ExternalResponse";
|
||||
|
||||
mozilla::StaticRefPtr<GeckoViewExternalAppService>
|
||||
GeckoViewExternalAppService::sService;
|
||||
|
||||
/* static */
|
||||
already_AddRefed<GeckoViewExternalAppService>
|
||||
GeckoViewExternalAppService::GetSingleton() {
|
||||
if (!sService) {
|
||||
sService = new GeckoViewExternalAppService();
|
||||
}
|
||||
RefPtr<GeckoViewExternalAppService> service = sService;
|
||||
return service.forget();
|
||||
}
|
||||
|
||||
GeckoViewExternalAppService::GeckoViewExternalAppService() {}
|
||||
|
||||
NS_IMPL_ISUPPORTS(GeckoViewExternalAppService, nsIExternalHelperAppService);
|
||||
|
||||
NS_IMETHODIMP GeckoViewExternalAppService::DoContent(
|
||||
const nsACString& aMimeContentType, nsIRequest* aRequest,
|
||||
nsIInterfaceRequestor* aContentContext, bool aForceSave,
|
||||
nsIInterfaceRequestor* aWindowContext,
|
||||
nsIStreamListener** aStreamListener) {
|
||||
return NS_ERROR_FAILURE;
|
||||
}
|
||||
|
||||
NS_IMETHODIMP GeckoViewExternalAppService::CreateListener(
|
||||
const nsACString& aMimeContentType, nsIRequest* aRequest,
|
||||
mozilla::dom::BrowsingContext* aContentContext, bool aForceSave,
|
||||
nsIInterfaceRequestor* aWindowContext,
|
||||
nsExternalAppHandler** aStreamListener) {
|
||||
using namespace mozilla;
|
||||
using namespace mozilla::dom;
|
||||
MOZ_ASSERT(XRE_IsParentProcess());
|
||||
|
||||
// We currently never want to read the channel, so cancel it immediately.
|
||||
aRequest->Cancel(NS_ERROR_ABORT);
|
||||
|
||||
nsresult rv;
|
||||
nsCOMPtr<nsIChannel> channel(do_QueryInterface(aRequest, &rv));
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
|
||||
nsCOMPtr<nsIWidget> widget =
|
||||
aContentContext->Canonical()->GetParentProcessWidgetContaining();
|
||||
if (!widget) {
|
||||
return NS_ERROR_ABORT;
|
||||
}
|
||||
|
||||
RefPtr<nsWindow> window = nsWindow::From(widget);
|
||||
MOZ_ASSERT(window);
|
||||
|
||||
widget::EventDispatcher* dispatcher = window->GetEventDispatcher();
|
||||
MOZ_ASSERT(dispatcher);
|
||||
|
||||
if (!dispatcher->HasListener(kExternalResponseMessage)) {
|
||||
return NS_ERROR_ABORT;
|
||||
}
|
||||
|
||||
AutoTArray<jni::String::LocalRef, 4> keys;
|
||||
AutoTArray<jni::Object::LocalRef, 4> values;
|
||||
|
||||
nsCOMPtr<nsIURI> uri;
|
||||
if (NS_WARN_IF(NS_FAILED(channel->GetURI(getter_AddRefs(uri))))) {
|
||||
return NS_ERROR_ABORT;
|
||||
}
|
||||
|
||||
nsAutoCString uriSpec;
|
||||
if (NS_WARN_IF(NS_FAILED(uri->GetDisplaySpec(uriSpec)))) {
|
||||
return NS_ERROR_ABORT;
|
||||
}
|
||||
|
||||
keys.AppendElement(jni::StringParam(NS_LITERAL_STRING("uri")));
|
||||
values.AppendElement(jni::StringParam(uriSpec));
|
||||
|
||||
nsCString contentType;
|
||||
if (NS_WARN_IF(NS_FAILED(channel->GetContentType(contentType)))) {
|
||||
return NS_ERROR_ABORT;
|
||||
}
|
||||
|
||||
keys.AppendElement(jni::StringParam(NS_LITERAL_STRING("contentType")));
|
||||
values.AppendElement(jni::StringParam(contentType));
|
||||
|
||||
int64_t contentLength = 0;
|
||||
if (NS_WARN_IF(NS_FAILED(channel->GetContentLength(&contentLength)))) {
|
||||
return NS_ERROR_ABORT;
|
||||
}
|
||||
|
||||
keys.AppendElement(jni::StringParam(NS_LITERAL_STRING("contentLength")));
|
||||
values.AppendElement(java::sdk::Integer::ValueOf(contentLength));
|
||||
|
||||
nsString filename;
|
||||
if (NS_SUCCEEDED(channel->GetContentDispositionFilename(filename))) {
|
||||
keys.AppendElement(jni::StringParam(NS_LITERAL_STRING("filename")));
|
||||
values.AppendElement(jni::StringParam(filename));
|
||||
}
|
||||
|
||||
auto bundleKeys = jni::ObjectArray::New<jni::String>(keys.Length());
|
||||
auto bundleValues = jni::ObjectArray::New<jni::Object>(values.Length());
|
||||
for (size_t i = 0; i < keys.Length(); ++i) {
|
||||
bundleKeys->SetElement(i, keys[i]);
|
||||
bundleValues->SetElement(i, values[i]);
|
||||
}
|
||||
auto bundle = java::GeckoBundle::New(bundleKeys, bundleValues);
|
||||
|
||||
Unused << NS_WARN_IF(
|
||||
NS_FAILED(dispatcher->Dispatch(kExternalResponseMessage, bundle)));
|
||||
|
||||
return NS_ERROR_ABORT;
|
||||
}
|
||||
|
||||
NS_IMETHODIMP GeckoViewExternalAppService::ApplyDecodingForExtension(
|
||||
const nsACString& aExtension, const nsACString& aEncodingType,
|
||||
bool* aApplyDecoding) {
|
||||
// This currently doesn't matter, because we never read the stream.
|
||||
*aApplyDecoding = true;
|
||||
return NS_OK;
|
||||
}
|
@ -0,0 +1,26 @@
|
||||
/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*-
|
||||
* 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 GeckoViewExternalAppService_h__
|
||||
#define GeckoViewExternalAppService_h__
|
||||
|
||||
#include "nsIExternalHelperAppService.h"
|
||||
#include "mozilla/StaticPtr.h"
|
||||
|
||||
class GeckoViewExternalAppService : public nsIExternalHelperAppService {
|
||||
public:
|
||||
NS_DECL_ISUPPORTS
|
||||
NS_DECL_NSIEXTERNALHELPERAPPSERVICE
|
||||
|
||||
GeckoViewExternalAppService();
|
||||
|
||||
static already_AddRefed<GeckoViewExternalAppService> GetSingleton();
|
||||
|
||||
private:
|
||||
virtual ~GeckoViewExternalAppService() {}
|
||||
static mozilla::StaticRefPtr<GeckoViewExternalAppService> sService;
|
||||
};
|
||||
|
||||
#endif
|
@ -1,65 +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 { XPCOMUtils } = ChromeUtils.import(
|
||||
"resource://gre/modules/XPCOMUtils.jsm"
|
||||
);
|
||||
const { GeckoViewUtils } = ChromeUtils.import(
|
||||
"resource://gre/modules/GeckoViewUtils.jsm"
|
||||
);
|
||||
|
||||
const { debug, warn } = GeckoViewUtils.initLogging("ExternalAppService"); // eslint-disable-line no-unused-vars
|
||||
|
||||
ChromeUtils.defineModuleGetter(
|
||||
this,
|
||||
"EventDispatcher",
|
||||
"resource://gre/modules/Messaging.jsm"
|
||||
);
|
||||
|
||||
function ExternalAppService() {
|
||||
this.wrappedJSObject = this;
|
||||
}
|
||||
|
||||
ExternalAppService.prototype = {
|
||||
classID: Components.ID("{a89eeec6-6608-42ee-a4f8-04d425992f45}"),
|
||||
QueryInterface: ChromeUtils.generateQI([Ci.nsIExternalHelperAppService]),
|
||||
|
||||
doContent(mimeType, request, context, forceSave) {
|
||||
const channel = request.QueryInterface(Ci.nsIChannel);
|
||||
debug`doContent: uri=${channel.URI.displaySpec}
|
||||
contentType=${channel.contentType}`;
|
||||
|
||||
let filename = null;
|
||||
try {
|
||||
filename = channel.contentDispositionFilename;
|
||||
} catch (e) {
|
||||
// This throws NS_ERROR_NOT_AVAILABLE if there is not
|
||||
// Content-disposition header.
|
||||
}
|
||||
|
||||
GeckoViewUtils.getDispatcherForWindow(context).sendRequest({
|
||||
type: "GeckoView:ExternalResponse",
|
||||
uri: channel.URI.displaySpec,
|
||||
contentType: channel.contentType,
|
||||
contentLength: channel.contentLength,
|
||||
filename,
|
||||
});
|
||||
|
||||
request.cancel(Cr.NS_ERROR_ABORT);
|
||||
Components.returnCode = Cr.NS_ERROR_ABORT;
|
||||
},
|
||||
|
||||
applyDecodingForExtension(ext, encoding) {
|
||||
debug`applyDecodingForExtension: extension=${ext}
|
||||
encoding=${encoding}`;
|
||||
|
||||
// This doesn't matter for us right now because
|
||||
// we shouldn't end up reading the stream.
|
||||
return true;
|
||||
},
|
||||
};
|
||||
|
||||
this.NSGetFactory = XPCOMUtils.generateNSGetFactory([ExternalAppService]);
|
@ -13,4 +13,14 @@ Classes = [
|
||||
'headers': ['GeckoViewHistory.h'],
|
||||
'constructor': 'GeckoViewHistory::GetSingleton',
|
||||
},
|
||||
{
|
||||
'cid': '{91455c77-64a1-4c37-be00-f94eb9c7b8e1}',
|
||||
'contract_ids': [
|
||||
'@mozilla.org/uriloader/external-helper-app-service;1',
|
||||
],
|
||||
'type': 'GeckoViewExternalAppService',
|
||||
'constructor': 'GeckoViewExternalAppService::GetSingleton',
|
||||
'headers': ['GeckoViewExternalAppService.h'],
|
||||
'processes': ProcessSelector.ALLOW_IN_SOCKET_PROCESS,
|
||||
},
|
||||
]
|
||||
|
@ -4,6 +4,9 @@
|
||||
# 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/.
|
||||
|
||||
SOURCES += ['GeckoViewExternalAppService.cpp']
|
||||
EXPORTS += ['GeckoViewExternalAppService.h']
|
||||
|
||||
if CONFIG['MOZ_ANDROID_HISTORY']:
|
||||
EXPORTS += [
|
||||
'GeckoViewHistory.h',
|
||||
@ -18,7 +21,6 @@ if CONFIG['MOZ_ANDROID_HISTORY']:
|
||||
|
||||
EXTRA_COMPONENTS += [
|
||||
'GeckoView.manifest',
|
||||
'GeckoViewExternalAppService.js',
|
||||
'GeckoViewPermission.js',
|
||||
'GeckoViewPrompt.js',
|
||||
'GeckoViewPush.js',
|
||||
|
@ -215,7 +215,6 @@
|
||||
|
||||
#ifdef MOZ_GECKOVIEW_JAR
|
||||
@BINPATH@/components/GeckoView.manifest
|
||||
@BINPATH@/components/GeckoViewExternalAppService.js
|
||||
@BINPATH@/components/GeckoViewPrompt.js
|
||||
@BINPATH@/components/GeckoViewPush.js
|
||||
@BINPATH@/components/GeckoViewPermission.js
|
||||
|
Loading…
x
Reference in New Issue
Block a user