/* 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 "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 "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_ISUPPORTS1(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 = NULL; g_file_set_attributes_finish(G_FILE(source_obj), res, NULL, &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(), NULL, NULL); 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, NULL, gio_set_metadata_done, NULL); 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, NULL, TRUE); ::CFRelease(observedObject); #endif #ifdef MOZ_WIDGET_ANDROID if (!aContentType.IsEmpty()) { mozilla::AndroidBridge::Bridge()->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; }