fune/toolkit/components/downloads/DownloadPlatform.cpp
Paolo Amadini d8a9df9c85 Bug 1363061 - Rename toolkit/components/jsdownloads to toolkit/components/downloads. r=mak
MozReview-Commit-ID: GuWeax0ubv3

--HG--
rename : toolkit/components/jsdownloads/src/DownloadCore.jsm => toolkit/components/downloads/DownloadCore.jsm
rename : toolkit/components/jsdownloads/src/DownloadHistory.jsm => toolkit/components/downloads/DownloadHistory.jsm
rename : toolkit/components/jsdownloads/src/DownloadIntegration.jsm => toolkit/components/downloads/DownloadIntegration.jsm
rename : toolkit/components/jsdownloads/src/DownloadLegacy.js => toolkit/components/downloads/DownloadLegacy.js
rename : toolkit/components/jsdownloads/src/DownloadList.jsm => toolkit/components/downloads/DownloadList.jsm
rename : toolkit/components/jsdownloads/src/DownloadPaths.jsm => toolkit/components/downloads/DownloadPaths.jsm
rename : toolkit/components/jsdownloads/src/DownloadPlatform.cpp => toolkit/components/downloads/DownloadPlatform.cpp
rename : toolkit/components/jsdownloads/src/DownloadPlatform.h => toolkit/components/downloads/DownloadPlatform.h
rename : toolkit/components/jsdownloads/src/DownloadStore.jsm => toolkit/components/downloads/DownloadStore.jsm
rename : toolkit/components/jsdownloads/src/DownloadUIHelper.jsm => toolkit/components/downloads/DownloadUIHelper.jsm
rename : toolkit/components/jsdownloads/src/Downloads.jsm => toolkit/components/downloads/Downloads.jsm
rename : toolkit/components/jsdownloads/src/Downloads.manifest => toolkit/components/downloads/Downloads.manifest
rename : toolkit/components/jsdownloads/src/moz.build => toolkit/components/downloads/moz.build
rename : toolkit/components/jsdownloads/public/mozIDownloadPlatform.idl => toolkit/components/downloads/mozIDownloadPlatform.idl
rename : toolkit/components/jsdownloads/test/browser/.eslintrc.js => toolkit/components/downloads/test/browser/.eslintrc.js
rename : toolkit/components/jsdownloads/test/browser/browser.ini => toolkit/components/downloads/test/browser/browser.ini
rename : toolkit/components/jsdownloads/test/browser/browser_DownloadPDFSaver.js => toolkit/components/downloads/test/browser/browser_DownloadPDFSaver.js
rename : toolkit/components/jsdownloads/test/browser/head.js => toolkit/components/downloads/test/browser/head.js
rename : toolkit/components/jsdownloads/test/browser/testFile.html => toolkit/components/downloads/test/browser/testFile.html
rename : toolkit/components/jsdownloads/test/data/.eslintrc.js => toolkit/components/downloads/test/data/.eslintrc.js
rename : toolkit/components/jsdownloads/test/data/empty.txt => toolkit/components/downloads/test/data/empty.txt
rename : toolkit/components/jsdownloads/test/data/source.txt => toolkit/components/downloads/test/data/source.txt
rename : toolkit/components/jsdownloads/test/unit/.eslintrc.js => toolkit/components/downloads/test/unit/.eslintrc.js
rename : toolkit/components/jsdownloads/test/unit/common_test_Download.js => toolkit/components/downloads/test/unit/common_test_Download.js
rename : toolkit/components/jsdownloads/test/unit/head.js => toolkit/components/downloads/test/unit/head.js
rename : toolkit/components/jsdownloads/test/unit/test_DownloadCore.js => toolkit/components/downloads/test/unit/test_DownloadCore.js
rename : toolkit/components/jsdownloads/test/unit/test_DownloadHistory.js => toolkit/components/downloads/test/unit/test_DownloadHistory.js
rename : toolkit/components/jsdownloads/test/unit/test_DownloadIntegration.js => toolkit/components/downloads/test/unit/test_DownloadIntegration.js
rename : toolkit/components/jsdownloads/test/unit/test_DownloadLegacy.js => toolkit/components/downloads/test/unit/test_DownloadLegacy.js
rename : toolkit/components/jsdownloads/test/unit/test_DownloadList.js => toolkit/components/downloads/test/unit/test_DownloadList.js
rename : toolkit/components/jsdownloads/test/unit/test_DownloadPaths.js => toolkit/components/downloads/test/unit/test_DownloadPaths.js
rename : toolkit/components/jsdownloads/test/unit/test_DownloadStore.js => toolkit/components/downloads/test/unit/test_DownloadStore.js
rename : toolkit/components/jsdownloads/test/unit/test_Downloads.js => toolkit/components/downloads/test/unit/test_Downloads.js
rename : toolkit/components/jsdownloads/test/unit/test_PrivateTemp.js => toolkit/components/downloads/test/unit/test_PrivateTemp.js
rename : toolkit/components/jsdownloads/test/unit/xpcshell.ini => toolkit/components/downloads/test/unit/xpcshell.ini
extra : rebase_source : 7062bc9278460abf0da3f1ae2ba02daa3c4f6abc
2018-03-06 17:40:59 +00:00

275 lines
8.4 KiB
C++

/* 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 "DownloadPlatform.h"
#include "nsAutoPtr.h"
#include "nsNetUtil.h"
#include "nsString.h"
#include "nsINestedURI.h"
#include "nsIProtocolHandler.h"
#include "nsIURI.h"
#include "nsIFile.h"
#include "nsIObserverService.h"
#include "nsISupportsPrimitives.h"
#include "nsDirectoryServiceDefs.h"
#include "mozilla/Preferences.h"
#include "mozilla/Services.h"
#define PREF_BDM_ADDTORECENTDOCS "browser.download.manager.addToRecentDocs"
#ifdef XP_WIN
#include <shlobj.h>
#include <urlmon.h>
#include "nsILocalFileWin.h"
#endif
#ifdef XP_MACOSX
#include <CoreFoundation/CoreFoundation.h>
#include "../../../xpcom/io/CocoaFileUtils.h"
#endif
#ifdef MOZ_WIDGET_ANDROID
#include "FennecJNIWrappers.h"
#endif
#ifdef MOZ_WIDGET_GTK
#include <gtk/gtk.h>
#endif
using namespace mozilla;
DownloadPlatform *DownloadPlatform::gDownloadPlatformService = nullptr;
NS_IMPL_ISUPPORTS(DownloadPlatform, mozIDownloadPlatform);
DownloadPlatform* DownloadPlatform::GetDownloadPlatform()
{
if (!gDownloadPlatformService) {
gDownloadPlatformService = new DownloadPlatform();
}
NS_ADDREF(gDownloadPlatformService);
#if defined(MOZ_WIDGET_GTK)
g_type_init();
#endif
return gDownloadPlatformService;
}
#ifdef MOZ_WIDGET_GTK
static void gio_set_metadata_done(GObject *source_obj, GAsyncResult *res, gpointer user_data)
{
GError *err = nullptr;
g_file_set_attributes_finish(G_FILE(source_obj), res, nullptr, &err);
if (err) {
#ifdef DEBUG
NS_DebugBreak(NS_DEBUG_WARNING, "Set file metadata failed: ", err->message, __FILE__, __LINE__);
#endif
g_error_free(err);
}
}
#endif
#ifdef XP_MACOSX
// Caller is responsible for freeing any result (CF Create Rule)
CFURLRef CreateCFURLFromNSIURI(nsIURI *aURI) {
nsAutoCString spec;
if (aURI) {
aURI->GetSpec(spec);
}
CFStringRef urlStr = ::CFStringCreateWithCString(kCFAllocatorDefault,
spec.get(),
kCFStringEncodingUTF8);
if (!urlStr) {
return NULL;
}
CFURLRef url = ::CFURLCreateWithString(kCFAllocatorDefault,
urlStr,
NULL);
::CFRelease(urlStr);
return url;
}
#endif
nsresult DownloadPlatform::DownloadDone(nsIURI* aSource, nsIURI* aReferrer, nsIFile* aTarget,
const nsACString& aContentType, bool aIsPrivate)
{
#if defined(XP_WIN) || defined(XP_MACOSX) || defined(MOZ_WIDGET_ANDROID) \
|| defined(MOZ_WIDGET_GTK)
nsAutoString path;
if (aTarget && NS_SUCCEEDED(aTarget->GetPath(path))) {
#if defined(XP_WIN) || defined(MOZ_WIDGET_GTK) || defined(MOZ_WIDGET_ANDROID)
// On Windows and Gtk, add the download to the system's "recent documents"
// list, with a pref to disable.
{
bool addToRecentDocs = Preferences::GetBool(PREF_BDM_ADDTORECENTDOCS);
#ifdef MOZ_WIDGET_ANDROID
if (jni::IsFennec() && addToRecentDocs) {
java::DownloadsIntegration::ScanMedia(path, aContentType);
}
#else
if (addToRecentDocs && !aIsPrivate) {
#ifdef XP_WIN
::SHAddToRecentDocs(SHARD_PATHW, path.get());
#elif defined(MOZ_WIDGET_GTK)
GtkRecentManager* manager = gtk_recent_manager_get_default();
gchar* uri = g_filename_to_uri(NS_ConvertUTF16toUTF8(path).get(),
nullptr, nullptr);
if (uri) {
gtk_recent_manager_add_item(manager, uri);
g_free(uri);
}
#endif
}
#endif
#ifdef MOZ_WIDGET_GTK
// Use GIO to store the source URI for later display in the file manager.
GFile* gio_file = g_file_new_for_path(NS_ConvertUTF16toUTF8(path).get());
nsCString source_uri;
nsresult rv = aSource->GetSpec(source_uri);
NS_ENSURE_SUCCESS(rv, rv);
GFileInfo *file_info = g_file_info_new();
g_file_info_set_attribute_string(file_info, "metadata::download-uri", source_uri.get());
g_file_set_attributes_async(gio_file,
file_info,
G_FILE_QUERY_INFO_NONE,
G_PRIORITY_DEFAULT,
nullptr, gio_set_metadata_done, nullptr);
g_object_unref(file_info);
g_object_unref(gio_file);
#endif
}
#endif
#ifdef XP_MACOSX
// On OS X, make the downloads stack bounce.
CFStringRef observedObject = ::CFStringCreateWithCString(kCFAllocatorDefault,
NS_ConvertUTF16toUTF8(path).get(),
kCFStringEncodingUTF8);
CFNotificationCenterRef center = ::CFNotificationCenterGetDistributedCenter();
::CFNotificationCenterPostNotification(center, CFSTR("com.apple.DownloadFileFinished"),
observedObject, nullptr, TRUE);
::CFRelease(observedObject);
// Add OS X origin and referrer file metadata
CFStringRef pathCFStr = NULL;
if (!path.IsEmpty()) {
pathCFStr = ::CFStringCreateWithCharacters(kCFAllocatorDefault,
(const UniChar*)path.get(),
path.Length());
}
if (pathCFStr && !aIsPrivate) {
bool isFromWeb = IsURLPossiblyFromWeb(aSource);
CFURLRef sourceCFURL = CreateCFURLFromNSIURI(aSource);
CFURLRef referrerCFURL = CreateCFURLFromNSIURI(aReferrer);
CocoaFileUtils::AddOriginMetadataToFile(pathCFStr,
sourceCFURL,
referrerCFURL);
CocoaFileUtils::AddQuarantineMetadataToFile(pathCFStr,
sourceCFURL,
referrerCFURL,
isFromWeb);
::CFRelease(pathCFStr);
if (sourceCFURL) {
::CFRelease(sourceCFURL);
}
if (referrerCFURL) {
::CFRelease(referrerCFURL);
}
}
#endif
}
#endif
return NS_OK;
}
nsresult DownloadPlatform::MapUrlToZone(const nsAString& aURL,
uint32_t* aZone)
{
#ifdef XP_WIN
RefPtr<IInternetSecurityManager> inetSecMgr;
if (FAILED(CoCreateInstance(CLSID_InternetSecurityManager, NULL,
CLSCTX_ALL, IID_IInternetSecurityManager,
getter_AddRefs(inetSecMgr)))) {
return NS_ERROR_UNEXPECTED;
}
DWORD zone;
if (inetSecMgr->MapUrlToZone(PromiseFlatString(aURL).get(),
&zone, 0) != S_OK) {
return NS_ERROR_UNEXPECTED;
} else {
*aZone = zone;
}
return NS_OK;
#else
return NS_ERROR_NOT_IMPLEMENTED;
#endif
}
// Check if a URI is likely to be web-based, by checking its URI flags.
// If in doubt (e.g. if anything fails during the check) claims things
// are from the web.
bool DownloadPlatform::IsURLPossiblyFromWeb(nsIURI* aURI)
{
nsCOMPtr<nsIIOService> ios = do_GetIOService();
nsCOMPtr<nsIURI> uri = aURI;
if (!ios) {
return true;
}
while (uri) {
// We're not using nsIIOService::ProtocolHasFlags because it doesn't
// take per-URI flags into account. We're also not using
// NS_URIChainHasFlags because we're checking for *any* of 3 flags
// to be present on *all* of the nested URIs, which it can't do.
nsAutoCString scheme;
nsresult rv = uri->GetScheme(scheme);
if (NS_FAILED(rv)) {
return true;
}
nsCOMPtr<nsIProtocolHandler> ph;
rv = ios->GetProtocolHandler(scheme.get(), getter_AddRefs(ph));
if (NS_FAILED(rv)) {
return true;
}
uint32_t flags;
rv = ph->DoGetProtocolFlags(uri, &flags);
if (NS_FAILED(rv)) {
return true;
}
// If not dangerous to load, not a UI resource and not a local file,
// assume this is from the web:
if (!(flags & nsIProtocolHandler::URI_DANGEROUS_TO_LOAD) &&
!(flags & nsIProtocolHandler::URI_IS_UI_RESOURCE) &&
!(flags & nsIProtocolHandler::URI_IS_LOCAL_FILE)) {
return true;
}
// Otherwise, check if the URI is nested, and if so go through
// the loop again:
nsCOMPtr<nsINestedURI> nestedURI = do_QueryInterface(uri);
uri = nullptr;
if (nestedURI) {
rv = nestedURI->GetInnerURI(getter_AddRefs(uri));
if (NS_FAILED(rv)) {
return true;
}
}
}
return false;
}