diff -r 000000000000 -r 6474c204b198 toolkit/components/jsdownloads/src/DownloadPlatform.cpp --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/toolkit/components/jsdownloads/src/DownloadPlatform.cpp Wed Dec 31 06:09:35 2014 +0100 @@ -0,0 +1,175 @@ +/* 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 "nsString.h" +#include "nsIURI.h" +#include "nsIFile.h" +#include "nsDirectoryServiceDefs.h" + +#include "mozilla/Preferences.h" + +#define PREF_BDM_ADDTORECENTDOCS "browser.download.manager.addToRecentDocs" + +#ifdef XP_WIN +#include +#include +#include "nsILocalFileWin.h" +#endif + +#ifdef XP_MACOSX +#include +#endif + +#ifdef MOZ_WIDGET_ANDROID +#include "AndroidBridge.h" +#endif + +#ifdef MOZ_WIDGET_GTK +#include +#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_ENABLE_GIO +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 + +nsresult DownloadPlatform::DownloadDone(nsIURI* aSource, 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) + // 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); + 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 + } +#ifdef MOZ_ENABLE_GIO + // 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; + aSource->GetSpec(source_uri); + 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); +#endif +#ifdef MOZ_WIDGET_ANDROID + if (!aContentType.IsEmpty()) { + mozilla::widget::android::GeckoAppShell::ScanMedia(path, NS_ConvertUTF8toUTF16(aContentType)); + } +#endif + } + +#ifdef XP_WIN + // Adjust file attributes so that by default, new files are indexed by + // desktop search services. Skip off those that land in the temp folder. + nsCOMPtr tempDir, fileDir; + nsresult rv = NS_GetSpecialDirectory(NS_OS_TEMP_DIR, getter_AddRefs(tempDir)); + NS_ENSURE_SUCCESS(rv, rv); + aTarget->GetParent(getter_AddRefs(fileDir)); + + bool isTemp = false; + if (fileDir) { + fileDir->Equals(tempDir, &isTemp); + } + + nsCOMPtr localFileWin(do_QueryInterface(aTarget)); + if (!isTemp && localFileWin) { + localFileWin->SetFileAttributesWin(nsILocalFileWin::WFA_SEARCH_INDEXED); + } +#endif + +#endif + + return NS_OK; +} + +nsresult DownloadPlatform::MapUrlToZone(const nsAString& aURL, + uint32_t* aZone) +{ +#ifdef XP_WIN + nsRefPtr 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 +}