mirror of
https://gitlab.winehq.org/wine/wine-gecko.git
synced 2024-09-13 09:24:08 -07:00
Bug 837199 - Write interface to query application reputation (r=paolo,sr=mossop)
This commit is contained in:
parent
662c1a77ce
commit
f6dc469869
@ -763,6 +763,12 @@ pref("browser.safebrowsing.reportMalwareErrorURL", "http://%LOCALE%.malware-erro
|
||||
|
||||
pref("browser.safebrowsing.warning.infoURL", "https://www.mozilla.org/%LOCALE%/firefox/phishing-protection/");
|
||||
pref("browser.safebrowsing.malware.reportURL", "http://safebrowsing.clients.google.com/safebrowsing/diagnostic?client=%NAME%&hl=%LOCALE%&site=");
|
||||
// Since the application reputation query isn't hooked in anywhere yet, this
|
||||
// preference does not matter. To be extra safe, don't turn this preference on
|
||||
// for official builds without whitelisting (bug 842828).
|
||||
#ifndef MOZILLA_OFFICIAL
|
||||
pref("browser.safebrowsing.appRepURL", "https://sb-ssl.google.com/safebrowsing/clientreport/download");
|
||||
#endif
|
||||
|
||||
#ifdef MOZILLA_OFFICIAL
|
||||
// Normally the "client ID" sent in updates is appinfo.name, but for
|
||||
|
@ -168,3 +168,15 @@
|
||||
#define NS_UPDATEPROCESSOR_CID \
|
||||
{ 0xf3dcf644, 0x79e8, 0x4f59, { 0xa1, 0xbb, 0x87, 0x84, 0x54, 0x48, 0x8e, 0xf9 } }
|
||||
#endif
|
||||
|
||||
#define NS_APPLICATION_REPUTATION_QUERY_CONTRACTID \
|
||||
"@mozilla.org/downloads/application-reputation-query;1"
|
||||
|
||||
#define NS_APPLICATION_REPUTATION_QUERY_CID \
|
||||
{ 0x857da2c0, 0xcfe5, 0x11e2, { 0x8b, 0x8b, 0x08, 0x00, 0x20, 0x0c, 0x9a, 0x66 } }
|
||||
|
||||
#define NS_APPLICATION_REPUTATION_SERVICE_CONTRACTID \
|
||||
"@mozilla.org/downloads/application-reputation-service;1"
|
||||
|
||||
#define NS_APPLICATION_REPUTATION_SERVICE_CID \
|
||||
{ 0x8576c950, 0xf4a2, 0x11e2, { 0xb7, 0x78, 0x08, 0x00, 0x20, 0x0c, 0x9a, 0x66 } }
|
||||
|
@ -32,6 +32,7 @@
|
||||
#endif
|
||||
|
||||
#include "nsBrowserStatusFilter.h"
|
||||
#include "ApplicationReputation.h"
|
||||
|
||||
/////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
@ -46,7 +47,7 @@ NS_GENERIC_FACTORY_CONSTRUCTOR(nsParentalControlsServiceWin)
|
||||
NS_GENERIC_FACTORY_CONSTRUCTOR(nsAlertsService)
|
||||
|
||||
NS_GENERIC_FACTORY_SINGLETON_CONSTRUCTOR(nsDownloadManager,
|
||||
nsDownloadManager::GetSingleton)
|
||||
nsDownloadManager::GetSingleton)
|
||||
NS_GENERIC_FACTORY_CONSTRUCTOR(nsDownloadProxy)
|
||||
|
||||
NS_GENERIC_FACTORY_CONSTRUCTOR(nsTypeAheadFind)
|
||||
@ -76,11 +77,16 @@ nsUrlClassifierDBServiceConstructor(nsISupports *aOuter, REFNSIID aIID,
|
||||
}
|
||||
#endif
|
||||
|
||||
NS_GENERIC_FACTORY_CONSTRUCTOR(ApplicationReputationQuery)
|
||||
NS_GENERIC_FACTORY_SINGLETON_CONSTRUCTOR(ApplicationReputationService,
|
||||
ApplicationReputationService::GetSingleton)
|
||||
NS_GENERIC_FACTORY_CONSTRUCTOR(nsBrowserStatusFilter)
|
||||
#if defined(USE_MOZ_UPDATER)
|
||||
NS_GENERIC_FACTORY_CONSTRUCTOR(nsUpdateProcessor)
|
||||
#endif
|
||||
|
||||
NS_DEFINE_NAMED_CID(NS_APPLICATION_REPUTATION_QUERY_CID);
|
||||
NS_DEFINE_NAMED_CID(NS_APPLICATION_REPUTATION_SERVICE_CID);
|
||||
NS_DEFINE_NAMED_CID(NS_TOOLKIT_APPSTARTUP_CID);
|
||||
NS_DEFINE_NAMED_CID(NS_USERINFO_CID);
|
||||
NS_DEFINE_NAMED_CID(NS_ALERTSSERVICE_CID);
|
||||
@ -104,6 +110,8 @@ NS_DEFINE_NAMED_CID(NS_UPDATEPROCESSOR_CID);
|
||||
#endif
|
||||
|
||||
static const mozilla::Module::CIDEntry kToolkitCIDs[] = {
|
||||
{ &kNS_APPLICATION_REPUTATION_QUERY_CID, false, NULL, ApplicationReputationQueryConstructor },
|
||||
{ &kNS_APPLICATION_REPUTATION_SERVICE_CID, false, NULL, ApplicationReputationServiceConstructor },
|
||||
{ &kNS_TOOLKIT_APPSTARTUP_CID, false, NULL, nsAppStartupConstructor },
|
||||
{ &kNS_USERINFO_CID, false, NULL, nsUserInfoConstructor },
|
||||
{ &kNS_ALERTSSERVICE_CID, false, NULL, nsAlertsServiceConstructor },
|
||||
@ -129,6 +137,8 @@ static const mozilla::Module::CIDEntry kToolkitCIDs[] = {
|
||||
};
|
||||
|
||||
static const mozilla::Module::ContractIDEntry kToolkitContracts[] = {
|
||||
{ NS_APPLICATION_REPUTATION_QUERY_CONTRACTID, &kNS_APPLICATION_REPUTATION_QUERY_CID },
|
||||
{ NS_APPLICATION_REPUTATION_SERVICE_CONTRACTID, &kNS_APPLICATION_REPUTATION_SERVICE_CID },
|
||||
{ NS_APPSTARTUP_CONTRACTID, &kNS_TOOLKIT_APPSTARTUP_CID },
|
||||
{ NS_USERINFO_CONTRACTID, &kNS_USERINFO_CID },
|
||||
{ NS_ALERTSERVICE_CONTRACTID, &kNS_ALERTSSERVICE_CID },
|
||||
|
339
toolkit/components/downloads/ApplicationReputation.cpp
Normal file
339
toolkit/components/downloads/ApplicationReputation.cpp
Normal file
@ -0,0 +1,339 @@
|
||||
/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
|
||||
/* vim: set ts=2 et sw=2 tw=80: */
|
||||
/* 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 "ApplicationReputation.h"
|
||||
#include "csd.pb.h"
|
||||
|
||||
#include "nsIApplicationReputation.h"
|
||||
#include "nsIChannel.h"
|
||||
#include "nsIHttpChannel.h"
|
||||
#include "nsIIOService.h"
|
||||
#include "nsIObserverService.h"
|
||||
#include "nsIPrefService.h"
|
||||
#include "nsIStreamListener.h"
|
||||
#include "nsIStringStream.h"
|
||||
#include "nsIUploadChannel2.h"
|
||||
#include "nsIURI.h"
|
||||
|
||||
#include "mozilla/Preferences.h"
|
||||
#include "mozilla/Services.h"
|
||||
|
||||
#include "nsCOMPtr.h"
|
||||
#include "nsDebug.h"
|
||||
#include "nsError.h"
|
||||
#include "nsNetCID.h"
|
||||
#include "nsServiceManagerUtils.h"
|
||||
#include "nsString.h"
|
||||
#include "nsThreadUtils.h"
|
||||
#include "nsXPCOMStrings.h"
|
||||
|
||||
using mozilla::Preferences;
|
||||
|
||||
// Preferences that we need to initialize the query. We may need another
|
||||
// preference than browser.safebrowsing.malware.enabled, or simply use
|
||||
// browser.safebrowsing.appRepURL. See bug 887041.
|
||||
#define PREF_SB_APP_REP_URL "browser.safebrowsing.appRepURL"
|
||||
#define PREF_SB_MALWARE_ENABLED "browser.safebrowsing.malware.enabled"
|
||||
#define PREF_GENERAL_LOCALE "general.useragent.locale"
|
||||
|
||||
NS_IMPL_ISUPPORTS1(ApplicationReputationService, nsIApplicationReputationService)
|
||||
|
||||
ApplicationReputationService* ApplicationReputationService::gApplicationReputationService = nullptr;
|
||||
|
||||
ApplicationReputationService *
|
||||
ApplicationReputationService::GetSingleton()
|
||||
{
|
||||
if (gApplicationReputationService) {
|
||||
NS_ADDREF(gApplicationReputationService);
|
||||
return gApplicationReputationService;
|
||||
}
|
||||
|
||||
gApplicationReputationService = new ApplicationReputationService();
|
||||
if (gApplicationReputationService) {
|
||||
NS_ADDREF(gApplicationReputationService);
|
||||
}
|
||||
|
||||
return gApplicationReputationService;
|
||||
}
|
||||
|
||||
ApplicationReputationService::ApplicationReputationService() { }
|
||||
ApplicationReputationService::~ApplicationReputationService() { }
|
||||
|
||||
NS_IMETHODIMP
|
||||
ApplicationReputationService::QueryReputation(
|
||||
nsIApplicationReputationQuery* aQuery,
|
||||
nsIApplicationReputationCallback* aCallback) {
|
||||
NS_ENSURE_ARG_POINTER(aQuery);
|
||||
NS_ENSURE_ARG_POINTER(aCallback);
|
||||
|
||||
nsresult rv = QueryReputationInternal(aQuery, aCallback);
|
||||
if (NS_FAILED(rv)) {
|
||||
aCallback->OnComplete(false, rv);
|
||||
aCallback = nullptr;
|
||||
}
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
nsresult
|
||||
ApplicationReputationService::QueryReputationInternal(
|
||||
nsIApplicationReputationQuery* aQuery,
|
||||
nsIApplicationReputationCallback* aCallback) {
|
||||
nsresult rv;
|
||||
aQuery->SetCallback(aCallback);
|
||||
|
||||
// If malware checks aren't enabled, don't query application reputation.
|
||||
if (!Preferences::GetBool(PREF_SB_MALWARE_ENABLED, false)) {
|
||||
return NS_ERROR_NOT_AVAILABLE;
|
||||
}
|
||||
|
||||
// If there is no service URL for querying application reputation, abort.
|
||||
nsCString serviceUrl;
|
||||
NS_ENSURE_SUCCESS(Preferences::GetCString(PREF_SB_APP_REP_URL, &serviceUrl),
|
||||
NS_ERROR_NOT_AVAILABLE);
|
||||
if (serviceUrl.EqualsLiteral("")) {
|
||||
return NS_ERROR_NOT_AVAILABLE;
|
||||
}
|
||||
|
||||
safe_browsing::ClientDownloadRequest req;
|
||||
|
||||
nsCString spec;
|
||||
nsCOMPtr<nsIURI> aURI;
|
||||
rv = aQuery->GetSourceURI(getter_AddRefs(aURI));
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
// If the URI hasn't been set, bail
|
||||
NS_ENSURE_STATE(aURI);
|
||||
rv = aURI->GetSpec(spec);
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
|
||||
req.set_url(spec.get());
|
||||
uint32_t fileSize;
|
||||
rv = aQuery->GetFileSize(&fileSize);
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
req.set_length(fileSize);
|
||||
// We have no way of knowing whether or not a user initiated the download.
|
||||
req.set_user_initiated(false);
|
||||
|
||||
nsCString locale;
|
||||
NS_ENSURE_SUCCESS(Preferences::GetCString(PREF_GENERAL_LOCALE, &locale),
|
||||
NS_ERROR_NOT_AVAILABLE);
|
||||
req.set_locale(locale.get());
|
||||
nsCString sha256Hash;
|
||||
rv = aQuery->GetSha256Hash(sha256Hash);
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
req.mutable_digests()->set_sha256(sha256Hash.Data());
|
||||
nsString fileName;
|
||||
rv = aQuery->GetSuggestedFileName(fileName);
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
req.set_file_basename(NS_ConvertUTF16toUTF8(fileName).get());
|
||||
|
||||
// Serialize the protocol buffer to a string. This can only fail if we are
|
||||
// out of memory, or if the protocol buffer req is missing required fields
|
||||
// (only the URL for now).
|
||||
std::string serialized;
|
||||
if (!req.SerializeToString(&serialized)) {
|
||||
return NS_ERROR_UNEXPECTED;
|
||||
}
|
||||
|
||||
// Set the input stream to the serialized protocol buffer
|
||||
nsCOMPtr<nsIStringInputStream> sstream =
|
||||
do_CreateInstance("@mozilla.org/io/string-input-stream;1", &rv);
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
|
||||
rv = sstream->SetData(serialized.c_str(), serialized.length());
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
|
||||
nsCOMPtr<nsIIOService> ios = do_GetService(NS_IOSERVICE_CONTRACTID, &rv);
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
|
||||
// Set up the channel to transmit the request to the service.
|
||||
nsCOMPtr<nsIChannel> channel;
|
||||
rv = ios->NewChannel(serviceUrl, nullptr, nullptr, getter_AddRefs(channel));
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
|
||||
nsCOMPtr<nsIHttpChannel> httpChannel(do_QueryInterface(channel, &rv));
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
|
||||
// See bug 887044 for finalizing the user agent.
|
||||
const nsCString userAgent = NS_LITERAL_CSTRING("CsdTesting/Mozilla");
|
||||
rv = httpChannel->SetRequestHeader(
|
||||
NS_LITERAL_CSTRING("User-Agent"), userAgent, false);
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
|
||||
// Upload the protobuf to the application reputation service.
|
||||
nsCOMPtr<nsIUploadChannel2> uploadChannel = do_QueryInterface(channel, &rv);
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
|
||||
rv = uploadChannel->ExplicitSetUploadStream(sstream,
|
||||
NS_LITERAL_CSTRING("application/octet-stream"), serialized.size(),
|
||||
NS_LITERAL_CSTRING("POST"), false);
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
|
||||
nsCOMPtr<nsIStreamListener> listener = do_QueryInterface(aQuery, &rv);
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
rv = channel->AsyncOpen(listener, nullptr);
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
NS_IMPL_ISUPPORTS3(ApplicationReputationQuery,
|
||||
nsIApplicationReputationQuery,
|
||||
nsIStreamListener,
|
||||
nsIRequestObserver)
|
||||
|
||||
ApplicationReputationQuery::ApplicationReputationQuery() :
|
||||
mURI(nullptr),
|
||||
mFileSize(0),
|
||||
mCallback(nullptr) {
|
||||
}
|
||||
|
||||
ApplicationReputationQuery::~ApplicationReputationQuery() {
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
ApplicationReputationQuery::GetSourceURI(nsIURI** aURI) {
|
||||
*aURI = mURI;
|
||||
NS_IF_ADDREF(*aURI);
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
ApplicationReputationQuery::SetSourceURI(nsIURI* aURI) {
|
||||
mURI = aURI;
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
ApplicationReputationQuery::GetSuggestedFileName(
|
||||
nsAString& aSuggestedFileName) {
|
||||
aSuggestedFileName = mSuggestedFileName;
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
ApplicationReputationQuery::SetSuggestedFileName(
|
||||
const nsAString& aSuggestedFileName) {
|
||||
mSuggestedFileName = aSuggestedFileName;
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
ApplicationReputationQuery::GetFileSize(uint32_t* aFileSize) {
|
||||
*aFileSize = mFileSize;
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
ApplicationReputationQuery::SetFileSize(uint32_t aFileSize) {
|
||||
mFileSize = aFileSize;
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
ApplicationReputationQuery::GetSha256Hash(nsACString& aSha256Hash) {
|
||||
aSha256Hash = mSha256Hash;
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
ApplicationReputationQuery::SetSha256Hash(const nsACString& aSha256Hash) {
|
||||
mSha256Hash = aSha256Hash;
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
ApplicationReputationQuery::GetCallback(
|
||||
nsIApplicationReputationCallback** aCallback) {
|
||||
*aCallback = mCallback;
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
ApplicationReputationQuery::SetCallback(
|
||||
nsIApplicationReputationCallback* aCallback) {
|
||||
mCallback = aCallback;
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
//// nsIStreamListener
|
||||
|
||||
static NS_METHOD
|
||||
AppendSegmentToString(nsIInputStream* inputStream,
|
||||
void *closure,
|
||||
const char *rawSegment,
|
||||
uint32_t toOffset,
|
||||
uint32_t count,
|
||||
uint32_t *writeCount) {
|
||||
nsAutoCString* decodedData = static_cast<nsAutoCString*>(closure);
|
||||
decodedData->Append(rawSegment, count);
|
||||
*writeCount = count;
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
ApplicationReputationQuery::OnDataAvailable(nsIRequest *aRequest,
|
||||
nsISupports *aContext,
|
||||
nsIInputStream *aStream,
|
||||
uint64_t offset,
|
||||
uint32_t count) {
|
||||
uint32_t read;
|
||||
return aStream->ReadSegments(AppendSegmentToString, &mResponse, count, &read);
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
ApplicationReputationQuery::OnStartRequest(nsIRequest *aRequest,
|
||||
nsISupports *aContext) {
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
ApplicationReputationQuery::OnStopRequest(nsIRequest *aRequest,
|
||||
nsISupports *aContext,
|
||||
nsresult aResult) {
|
||||
NS_ENSURE_STATE(mCallback);
|
||||
|
||||
bool shouldBlock = false;
|
||||
nsresult rv = OnStopRequestInternal(aRequest, aContext, aResult,
|
||||
&shouldBlock);
|
||||
mCallback->OnComplete(shouldBlock, rv);
|
||||
mCallback = nullptr;
|
||||
return rv;
|
||||
}
|
||||
|
||||
nsresult
|
||||
ApplicationReputationQuery::OnStopRequestInternal(nsIRequest *aRequest,
|
||||
nsISupports *aContext,
|
||||
nsresult aResult,
|
||||
bool* aShouldBlock) {
|
||||
*aShouldBlock = false;
|
||||
nsresult rv;
|
||||
nsCOMPtr<nsIHttpChannel> channel = do_QueryInterface(aRequest, &rv);
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
|
||||
uint32_t status = 0;
|
||||
rv = channel->GetResponseStatus(&status);
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
|
||||
if (status != 200) {
|
||||
return NS_ERROR_NOT_AVAILABLE;
|
||||
}
|
||||
|
||||
std::string buf(mResponse.Data(), mResponse.Length());
|
||||
safe_browsing::ClientDownloadResponse response;
|
||||
if (!response.ParseFromString(buf)) {
|
||||
NS_WARNING("Could not parse protocol buffer");
|
||||
return NS_ERROR_CANNOT_CONVERT_DATA;
|
||||
}
|
||||
|
||||
// There are several more verdicts, but we only respect one for now and treat
|
||||
// everything else as SAFE.
|
||||
if (response.verdict() == safe_browsing::ClientDownloadResponse::DANGEROUS) {
|
||||
*aShouldBlock = true;
|
||||
}
|
||||
|
||||
return NS_OK;
|
||||
}
|
98
toolkit/components/downloads/ApplicationReputation.h
Normal file
98
toolkit/components/downloads/ApplicationReputation.h
Normal file
@ -0,0 +1,98 @@
|
||||
/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
|
||||
/* vim: set ts=2 et sw=2 tw=80: */
|
||||
/* 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 ApplicationReputation_h__
|
||||
#define ApplicationReputation_h__
|
||||
|
||||
#include "nsIApplicationReputation.h"
|
||||
#include "nsIRequestObserver.h"
|
||||
#include "nsIStreamListener.h"
|
||||
#include "nsISupports.h"
|
||||
|
||||
#include "nsCOMPtr.h"
|
||||
#include "nsString.h"
|
||||
|
||||
class nsIApplicationReputationListener;
|
||||
class nsIChannel;
|
||||
class nsIObserverService;
|
||||
class nsIRequest;
|
||||
class PRLogModuleInfo;
|
||||
|
||||
class ApplicationReputationService MOZ_FINAL :
|
||||
public nsIApplicationReputationService {
|
||||
public:
|
||||
NS_DECL_ISUPPORTS
|
||||
NS_DECL_NSIAPPLICATIONREPUTATIONSERVICE
|
||||
|
||||
public:
|
||||
static ApplicationReputationService* GetSingleton();
|
||||
|
||||
private:
|
||||
/**
|
||||
* Global singleton object for holding this factory service.
|
||||
*/
|
||||
static ApplicationReputationService* gApplicationReputationService;
|
||||
|
||||
ApplicationReputationService();
|
||||
~ApplicationReputationService();
|
||||
|
||||
/**
|
||||
* Wrapper function for QueryReputation that makes it easier to ensure the
|
||||
* callback is called.
|
||||
*/
|
||||
nsresult QueryReputationInternal(nsIApplicationReputationQuery* aQuery,
|
||||
nsIApplicationReputationCallback* aCallback);
|
||||
};
|
||||
|
||||
/**
|
||||
* This class implements nsIApplicationReputation. See the
|
||||
* nsIApplicationReputation.idl for details. ApplicationReputation also
|
||||
* implements nsIStreamListener because it calls nsIChannel->AsyncOpen.
|
||||
*/
|
||||
class ApplicationReputationQuery MOZ_FINAL :
|
||||
public nsIApplicationReputationQuery,
|
||||
public nsIStreamListener {
|
||||
public:
|
||||
NS_DECL_ISUPPORTS
|
||||
NS_DECL_NSIREQUESTOBSERVER
|
||||
NS_DECL_NSISTREAMLISTENER
|
||||
NS_DECL_NSIAPPLICATIONREPUTATIONQUERY
|
||||
|
||||
ApplicationReputationQuery();
|
||||
~ApplicationReputationQuery();
|
||||
|
||||
private:
|
||||
/**
|
||||
* Corresponding member variables for the attributes in the IDL.
|
||||
*/
|
||||
nsString mSuggestedFileName;
|
||||
nsCOMPtr<nsIURI> mURI;
|
||||
uint32_t mFileSize;
|
||||
nsCString mSha256Hash;
|
||||
|
||||
/**
|
||||
* The callback for the request.
|
||||
*/
|
||||
nsCOMPtr<nsIApplicationReputationCallback> mCallback;
|
||||
|
||||
/**
|
||||
* The response from the application reputation query. This is read in chunks
|
||||
* as part of our nsIStreamListener implementation and may contain embedded
|
||||
* NULLs.
|
||||
*/
|
||||
nsCString mResponse;
|
||||
|
||||
/**
|
||||
* Wrapper function for nsIStreamListener.onStopRequest to make it easy to
|
||||
* guarantee calling the callback
|
||||
*/
|
||||
nsresult OnStopRequestInternal(nsIRequest *aRequest,
|
||||
nsISupports *aContext,
|
||||
nsresult aResult,
|
||||
bool* aShouldBlock);
|
||||
};
|
||||
|
||||
#endif /* ApplicationReputation_h__ */
|
@ -16,4 +16,8 @@ FAIL_ON_WARNINGS = 1
|
||||
|
||||
include $(topsrcdir)/config/rules.mk
|
||||
|
||||
CXXFLAGS += $(TK_CFLAGS)
|
||||
CXXFLAGS += $(TK_CFLAGS) -DGOOGLE_PROTOBUF_NO_RTTI
|
||||
|
||||
LOCAL_INCLUDES += \
|
||||
-I$(srcdir)/../protobuf \
|
||||
$(NULL)
|
||||
|
4309
toolkit/components/downloads/csd.pb.cc
Normal file
4309
toolkit/components/downloads/csd.pb.cc
Normal file
File diff suppressed because it is too large
Load Diff
4077
toolkit/components/downloads/csd.pb.h
Normal file
4077
toolkit/components/downloads/csd.pb.h
Normal file
File diff suppressed because it is too large
Load Diff
23
toolkit/components/downloads/generate_csd.sh
Executable file
23
toolkit/components/downloads/generate_csd.sh
Executable file
@ -0,0 +1,23 @@
|
||||
#!/bin/bash
|
||||
# A script to generate toolkit/components/downloads/csd.pb.{cc,h} for use in
|
||||
# nsIApplicationReputationQuery. This script assumes you have downloaded and
|
||||
# installed the protocol buffer compiler.
|
||||
|
||||
if [ -n $PROTOC_PATH ]; then
|
||||
PROTOC_PATH=/usr/local/bin/protoc
|
||||
fi
|
||||
|
||||
echo "Using $PROTOC_PATH as protocol compiler"
|
||||
|
||||
if [ ! -e $PROTOC_PATH ]; then
|
||||
echo "You must install the protocol compiler from " \
|
||||
"https://code.google.com/p/protobuf/downloads/list"
|
||||
exit 1
|
||||
fi
|
||||
|
||||
# Get the protocol buffer and compile it
|
||||
CMD='wget http://src.chromium.org/chrome/trunk/src/chrome/common/safe_browsing/csd.proto -O csd.proto'
|
||||
OUTPUT_PATH=toolkit/components/downloads
|
||||
|
||||
$CMD
|
||||
$PROTOC_PATH csd.proto --cpp_out=$OUTPUT_PATH
|
@ -7,6 +7,7 @@
|
||||
TEST_DIRS += ['test']
|
||||
|
||||
XPIDL_SOURCES += [
|
||||
'nsIApplicationReputation.idl',
|
||||
'nsIDownload.idl',
|
||||
'nsIDownloadManager.idl',
|
||||
'nsIDownloadManagerUI.idl',
|
||||
@ -18,6 +19,8 @@ MODULE = 'downloads'
|
||||
CPP_SOURCES += [
|
||||
'SQLFunctions.cpp',
|
||||
'nsDownloadManager.cpp',
|
||||
'ApplicationReputation.cpp',
|
||||
'csd.pb.cc'
|
||||
]
|
||||
|
||||
if CONFIG['OS_ARCH'] == 'WINNT':
|
||||
|
94
toolkit/components/downloads/nsIApplicationReputation.idl
Normal file
94
toolkit/components/downloads/nsIApplicationReputation.idl
Normal file
@ -0,0 +1,94 @@
|
||||
/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
|
||||
/* vim: set ts=2 et sw=2 tw=80: */
|
||||
/* 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 "nsISupports.idl"
|
||||
|
||||
interface nsIApplicationReputationCallback;
|
||||
interface nsIApplicationReputationQuery;
|
||||
interface nsIURI;
|
||||
|
||||
/*
|
||||
* A service for asynchronously querying an application reputation service
|
||||
* based on metadata of the downloaded file.
|
||||
*/
|
||||
[scriptable, uuid(9c12a510-eb1c-11e2-a98a-fa916188709b)]
|
||||
interface nsIApplicationReputationService : nsISupports {
|
||||
/**
|
||||
* Start querying the application reputation service.
|
||||
*
|
||||
* @param aQuery
|
||||
* The nsIApplicationReputationQuery containing metadata of the
|
||||
* downloaded file.
|
||||
*
|
||||
* @param aCallback
|
||||
* The callback for receiving the results of the query.
|
||||
*
|
||||
* @remarks aCallback may not be null. onComplete is guaranteed to be called
|
||||
* on aCallback. This function may not be called more than once with
|
||||
* the same query object. If any of the attributes of aQuery have
|
||||
* not been set or have been set with empty data (with the exception
|
||||
* of sourceURI), then a valid request can still be constructed and
|
||||
* will solicit a valid response, but won't produce any useful
|
||||
* information.
|
||||
*/
|
||||
void queryReputation(in nsIApplicationReputationQuery aQuery,
|
||||
in nsIApplicationReputationCallback aCallback);
|
||||
};
|
||||
|
||||
/**
|
||||
* A single-use, write-once interface for recording the metadata of the
|
||||
* downloaded file. nsIApplicationReputationService.Start() may only be called
|
||||
* once with a single query.
|
||||
*/
|
||||
[scriptable, uuid(857da2c0-cfe5-11e2-8b8b-0800200c9a66)]
|
||||
interface nsIApplicationReputationQuery : nsISupports {
|
||||
/*
|
||||
* The nsIURI from which the file was downloaded. This may not be null.
|
||||
*/
|
||||
attribute nsIURI sourceURI;
|
||||
|
||||
/*
|
||||
* The target filename for the downloaded file, as inferred from the source
|
||||
* URI or provided by the Content-Disposition attachment file name. If this
|
||||
* is not set by the caller, it will be passed as an empty string but the
|
||||
* query won't produce any useful information.
|
||||
*/
|
||||
attribute AString suggestedFileName;
|
||||
|
||||
/*
|
||||
* The size of the downloaded file in bytes.
|
||||
*/
|
||||
attribute unsigned long fileSize;
|
||||
|
||||
/*
|
||||
* The SHA256 hash of the downloaded file in raw bytes. If this is not set by
|
||||
* the caller, it will be passed as an empty string but the query won't
|
||||
* produce any useful information.
|
||||
*/
|
||||
attribute ACString sha256Hash;
|
||||
|
||||
/**
|
||||
* The callback object listening to this query.
|
||||
*/
|
||||
attribute nsIApplicationReputationCallback callback;
|
||||
};
|
||||
|
||||
[scriptable, function, uuid(9a228470-cfe5-11e2-8b8b-0800200c9a66)]
|
||||
interface nsIApplicationReputationCallback : nsISupports {
|
||||
/**
|
||||
* Callback for the result of the application reputation query.
|
||||
* @param aStatus
|
||||
* NS_OK if and only if the query succeeded. If it did, then
|
||||
* shouldBlock is meaningful (otherwise it defaults to false). This
|
||||
* may be NS_ERROR_FAILURE if the response cannot be parsed, or
|
||||
* NS_ERROR_NOT_AVAILABLE if the service has been disabled or is not
|
||||
* reachable.
|
||||
* @param aShouldBlock
|
||||
* Whether or not the download should be blocked.
|
||||
*/
|
||||
void onComplete(in bool aShouldBlock,
|
||||
in nsresult aStatus);
|
||||
};
|
@ -0,0 +1,24 @@
|
||||
/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
|
||||
/* vim: set ts=2 et sw=2 tw=80: */
|
||||
/* 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/. */
|
||||
|
||||
/**
|
||||
* Provides infrastructure for automated download components tests.
|
||||
*/
|
||||
|
||||
"use strict";
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
//// Termination functions common to all tests
|
||||
|
||||
add_task(function test_common_terminate()
|
||||
{
|
||||
// Stop the HTTP server. We must do this inside a task in "tail.js" until the
|
||||
// xpcshell testing framework supports asynchronous termination functions.
|
||||
let deferred = Promise.defer();
|
||||
gHttpServer.stop(deferred.resolve);
|
||||
yield deferred.promise;
|
||||
});
|
||||
|
132
toolkit/components/downloads/test/unit/test_app_rep.js
Normal file
132
toolkit/components/downloads/test/unit/test_app_rep.js
Normal file
@ -0,0 +1,132 @@
|
||||
/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
|
||||
/* vim: set ts=2 et sw=2 tw=80: */
|
||||
/* 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/. */
|
||||
|
||||
Cu.import('resource://gre/modules/NetUtil.jsm');
|
||||
Cu.import("resource://gre/modules/XPCOMUtils.jsm");
|
||||
|
||||
const ApplicationReputationQuery = Components.Constructor(
|
||||
"@mozilla.org/downloads/application-reputation-query;1",
|
||||
"nsIApplicationReputationQuery");
|
||||
|
||||
const gAppRep = Cc["@mozilla.org/downloads/application-reputation-service;1"].
|
||||
getService(Ci.nsIApplicationReputationService);
|
||||
let gHttpServ = null;
|
||||
|
||||
function run_test() {
|
||||
// Set up a local HTTP server to return bad verdicts.
|
||||
Services.prefs.setCharPref("browser.safebrowsing.appRepURL",
|
||||
"http://localhost:4444/download");
|
||||
gHttpServ = new HttpServer();
|
||||
gHttpServ.registerDirectory("/", do_get_cwd());
|
||||
|
||||
function createVerdict(aShouldBlock) {
|
||||
// We can't programmatically create a protocol buffer here, so just
|
||||
// hardcode some already serialized ones.
|
||||
blob = String.fromCharCode(parseInt(0x08, 16));
|
||||
if (aShouldBlock) {
|
||||
// A safe_browsing::ClientDownloadRequest with a DANGEROUS verdict
|
||||
blob += String.fromCharCode(parseInt(0x01, 16));
|
||||
} else {
|
||||
// A safe_browsing::ClientDownloadRequest with a SAFE verdict
|
||||
blob += String.fromCharCode(parseInt(0x00, 16));
|
||||
}
|
||||
return blob;
|
||||
}
|
||||
|
||||
gHttpServ.registerPathHandler("/download", function(request, response) {
|
||||
response.setHeader("Content-Type", "application/octet-stream", false);
|
||||
let buf = NetUtil.readInputStreamToString(
|
||||
request.bodyInputStream,
|
||||
request.bodyInputStream.available());
|
||||
do_print("Request length: " + buf.length);
|
||||
// A garbage response.
|
||||
let blob = "this is not a serialized protocol buffer";
|
||||
// We can't actually parse the protocol buffer here, so just switch on the
|
||||
// length instead of inspecting the contents.
|
||||
if (buf.length == 35) {
|
||||
blob = createVerdict(true);
|
||||
} else if (buf.length == 38) {
|
||||
blob = createVerdict(false);
|
||||
}
|
||||
response.bodyOutputStream.write(blob, blob.length);
|
||||
});
|
||||
|
||||
gHttpServ.start(4444);
|
||||
|
||||
run_next_test();
|
||||
}
|
||||
|
||||
add_test(function test_shouldBlock() {
|
||||
let query = new ApplicationReputationQuery();
|
||||
query.sourceURI = createURI("http://evil.com");
|
||||
query.fileSize = 12;
|
||||
|
||||
gAppRep.queryReputation(query, function onComplete(aShouldBlock, aStatus) {
|
||||
do_check_true(aShouldBlock);
|
||||
do_check_eq(Cr.NS_OK, aStatus);
|
||||
run_next_test();
|
||||
});
|
||||
});
|
||||
|
||||
add_test(function test_shouldNotBlock() {
|
||||
let query = new ApplicationReputationQuery();
|
||||
query.sourceURI = createURI("http://mozilla.com");
|
||||
query.fileSize = 12;
|
||||
|
||||
gAppRep.queryReputation(query, function onComplete(aShouldBlock, aStatus) {
|
||||
do_check_eq(Cr.NS_OK, aStatus);
|
||||
do_check_false(aShouldBlock);
|
||||
run_next_test();
|
||||
});
|
||||
});
|
||||
|
||||
add_test(function test_garbage() {
|
||||
let query = new ApplicationReputationQuery();
|
||||
query.sourceURI = createURI("http://thisisagarbageurl.com");
|
||||
query.fileSize = 12;
|
||||
|
||||
gAppRep.queryReputation(query, function onComplete(aShouldBlock, aStatus) {
|
||||
// We should be getting the garbage response.
|
||||
do_check_eq(Cr.NS_ERROR_CANNOT_CONVERT_DATA, aStatus);
|
||||
do_check_false(aShouldBlock);
|
||||
run_next_test();
|
||||
});
|
||||
});
|
||||
|
||||
add_test(function test_nullSourceURI() {
|
||||
let query = new ApplicationReputationQuery();
|
||||
query.fileSize = 12;
|
||||
// No source URI
|
||||
gAppRep.queryReputation(query, function onComplete(aShouldBlock, aStatus) {
|
||||
do_check_eq(Cr.NS_ERROR_UNEXPECTED, aStatus);
|
||||
do_check_false(aShouldBlock);
|
||||
run_next_test();
|
||||
});
|
||||
});
|
||||
|
||||
add_test(function test_nullCallback() {
|
||||
let query = new ApplicationReputationQuery();
|
||||
query.fileSize = 12;
|
||||
try {
|
||||
gAppRep.queryReputation(query, null);
|
||||
do_throw("Callback cannot be null");
|
||||
} catch (ex if ex.result == Cr.NS_ERROR_INVALID_POINTER) {
|
||||
run_next_test();
|
||||
}
|
||||
});
|
||||
|
||||
add_test(function test_disabled() {
|
||||
Services.prefs.setCharPref("browser.safebrowsing.appRepURL", "");
|
||||
let query = new ApplicationReputationQuery();
|
||||
query.sourceURI = createURI("http://example.com");
|
||||
query.fileSize = 12;
|
||||
gAppRep.queryReputation(query, function onComplete(aShouldBlock, aStatus) {
|
||||
// We should be getting NS_ERROR_NOT_AVAILABLE if the service is disabled
|
||||
do_check_eq(Cr.NS_ERROR_NOT_AVAILABLE, aStatus);
|
||||
do_check_false(aShouldBlock);
|
||||
run_next_test();
|
||||
});
|
||||
});
|
@ -1,8 +1,9 @@
|
||||
[DEFAULT]
|
||||
head = head_download_manager.js
|
||||
tail =
|
||||
tail = tail_download_manager.js
|
||||
firefox-appdir = browser
|
||||
|
||||
[test_app_rep.js]
|
||||
[test_bug_382825.js]
|
||||
[test_bug_384744.js]
|
||||
[test_bug_395092.js]
|
||||
|
@ -26,4 +26,4 @@ LOCAL_INCLUDES = \
|
||||
|
||||
include $(topsrcdir)/config/rules.mk
|
||||
|
||||
CXXFLAGS += $(TK_CFLAGS)
|
||||
CXXFLAGS += $(TK_CFLAGS) -DGOOGLE_PROTOBUF_NO_RTTI
|
||||
|
Loading…
Reference in New Issue
Block a user