From b9c5e782fe5548d64fd50ad62cc274a1e8088622 Mon Sep 17 00:00:00 2001 From: Brad Lassey Date: Wed, 20 Oct 2010 11:19:24 -0400 Subject: [PATCH] bug 594368 - nsFilePicker is called directly from the child process in e10s r=jdm a=blocking-fennec --- dom/ipc/ContentParent.cpp | 75 ++++++++ dom/ipc/ContentParent.h | 13 +- dom/ipc/PContent.ipdl | 6 + widget/src/android/nsWidgetFactory.cpp | 25 ++- widget/src/qt/nsWidgetFactory.cpp | 27 ++- widget/src/xpwidgets/Makefile.in | 3 +- widget/src/xpwidgets/nsFilePickerProxy.cpp | 204 +++++++++++++++++++++ widget/src/xpwidgets/nsFilePickerProxy.h | 97 ++++++++++ 8 files changed, 446 insertions(+), 4 deletions(-) create mode 100644 widget/src/xpwidgets/nsFilePickerProxy.cpp create mode 100644 widget/src/xpwidgets/nsFilePickerProxy.h diff --git a/dom/ipc/ContentParent.cpp b/dom/ipc/ContentParent.cpp index c2026e577c9..75b28cf9ca8 100644 --- a/dom/ipc/ContentParent.cpp +++ b/dom/ipc/ContentParent.cpp @@ -43,6 +43,9 @@ #include "History.h" #include "mozilla/ipc/TestShellParent.h" #include "mozilla/net/NeckoParent.h" +#include "nsIFilePicker.h" +#include "nsIWindowWatcher.h" +#include "nsIDOMWindow.h" #include "nsIPrefBranch.h" #include "nsIPrefBranch2.h" #include "nsIPrefService.h" @@ -451,6 +454,78 @@ ContentParent::RecvSetURITitle(const IPC::URI& uri, return true; } +bool +ContentParent::RecvShowFilePicker(const PRInt16& mode, + const PRInt16& selectedType, + const nsString& title, + const nsString& defaultFile, + const nsString& defaultExtension, + const nsTArray& filters, + const nsTArray& filterNames, + nsTArray* files, + PRInt16* retValue, + nsresult* result) +{ + nsCOMPtr filePicker = do_CreateInstance("@mozilla.org/filepicker;1"); + if (!filePicker) { + *result = NS_ERROR_NOT_AVAILABLE; + return true; + } + + // as the parent given to the content process would be meaningless in this + // process, always use active window as the parent + nsCOMPtr ww = do_GetService(NS_WINDOWWATCHER_CONTRACTID); + nsCOMPtr window; + ww->GetActiveWindow(getter_AddRefs(window)); + + // initialize the "real" picker with all data given + *result = filePicker->Init(window, title, mode); + if (NS_FAILED(*result)) + return true; + + PRUint32 count = filters.Length(); + for (PRUint32 i = 0; i < count; ++i) { + filePicker->AppendFilter(filterNames[i], filters[i]); + } + + filePicker->SetDefaultString(defaultFile); + filePicker->SetDefaultExtension(defaultExtension); + filePicker->SetFilterIndex(selectedType); + + // and finally open the dialog + *result = filePicker->Show(retValue); + if (NS_FAILED(*result)) + return true; + + if (mode == nsIFilePicker::modeOpenMultiple) { + nsCOMPtr fileIter; + *result = filePicker->GetFiles(getter_AddRefs(fileIter)); + + nsCOMPtr singleFile; + PRBool loop = PR_TRUE; + while (NS_SUCCEEDED(fileIter->HasMoreElements(&loop)) && loop) { + fileIter->GetNext(getter_AddRefs(singleFile)); + if (singleFile) { + nsAutoString filePath; + singleFile->GetPath(filePath); + files->AppendElement(filePath); + } + } + return true; + } + nsCOMPtr file; + filePicker->GetFile(getter_AddRefs(file)); + + // even with NS_OK file can be null if nothing was selected + if (file) { + nsAutoString filePath; + file->GetPath(filePath); + files->AppendElement(filePath); + } + + return true; +} + bool ContentParent::RecvLoadURIExternal(const IPC::URI& uri) { diff --git a/dom/ipc/ContentParent.h b/dom/ipc/ContentParent.h index 7f68862779a..6623e41f86d 100644 --- a/dom/ipc/ContentParent.h +++ b/dom/ipc/ContentParent.h @@ -139,7 +139,18 @@ private: virtual bool RecvSetURITitle(const IPC::URI& uri, const nsString& title); - + + virtual bool RecvShowFilePicker(const PRInt16& mode, + const PRInt16& selectedType, + const nsString& title, + const nsString& defaultFile, + const nsString& defaultExtension, + const nsTArray& filters, + const nsTArray& filterNames, + nsTArray* files, + PRInt16* retValue, + nsresult* result); + virtual bool RecvShowAlertNotification(const nsString& aImageUrl, const nsString& aTitle, const nsString& aText, const PRBool& aTextClickable, const nsString& aCookie, const nsString& aName); diff --git a/dom/ipc/PContent.ipdl b/dom/ipc/PContent.ipdl index eec7a9a0a87..08baaf08fbc 100644 --- a/dom/ipc/PContent.ipdl +++ b/dom/ipc/PContent.ipdl @@ -96,6 +96,12 @@ parent: async StartVisitedQuery(URI uri); async VisitURI(URI uri, URI referrer, PRUint32 flags); async SetURITitle(URI uri, nsString title); + + // filepicker remoting + sync ShowFilePicker(PRInt16 mode, PRInt16 selectedType, + nsString title, nsString defaultFile, nsString defaultExtension, + nsString[] filters, nsString[] filterNames) + returns (nsString[] files, PRInt16 retValue, nsresult result); async LoadURIExternal(URI uri); diff --git a/widget/src/android/nsWidgetFactory.cpp b/widget/src/android/nsWidgetFactory.cpp index 5c61e5f4a4d..c8f8acc56c6 100644 --- a/widget/src/android/nsWidgetFactory.cpp +++ b/widget/src/android/nsWidgetFactory.cpp @@ -54,6 +54,10 @@ #include "nsTransferable.h" #include "nsFilePicker.h" #include "nsHTMLFormatConverter.h" +#ifdef MOZ_IPC +#include "nsFilePickerProxy.h" +#include "nsXULAppAPI.h" +#endif NS_GENERIC_FACTORY_CONSTRUCTOR(nsToolkit) NS_GENERIC_FACTORY_CONSTRUCTOR(nsWindow) @@ -63,9 +67,28 @@ NS_GENERIC_FACTORY_CONSTRUCTOR(nsIdleServiceAndroid) NS_GENERIC_FACTORY_CONSTRUCTOR(nsTransferable) NS_GENERIC_FACTORY_CONSTRUCTOR(nsClipboard) NS_GENERIC_FACTORY_CONSTRUCTOR(nsClipboardHelper) -NS_GENERIC_FACTORY_CONSTRUCTOR(nsFilePicker) NS_GENERIC_FACTORY_CONSTRUCTOR(nsHTMLFormatConverter) +static nsresult +nsFilePickerConstructor(nsISupports *aOuter, REFNSIID aIID, + void **aResult) +{ + *aResult = nsnull; + if (aOuter != nsnull) { + return NS_ERROR_NO_AGGREGATION; + } + nsCOMPtr picker; + +#ifdef MOZ_IPC + if (XRE_GetProcessType() == GeckoProcessType_Content) + picker = new nsFilePickerProxy(); + else +#endif + picker = new nsFilePicker; + + return picker->QueryInterface(aIID, aResult); +} + NS_DEFINE_NAMED_CID(NS_TOOLKIT_CID); NS_DEFINE_NAMED_CID(NS_APPSHELL_CID); NS_DEFINE_NAMED_CID(NS_WINDOW_CID); diff --git a/widget/src/qt/nsWidgetFactory.cpp b/widget/src/qt/nsWidgetFactory.cpp index 47df34e2a8d..b37bebe9747 100644 --- a/widget/src/qt/nsWidgetFactory.cpp +++ b/widget/src/qt/nsWidgetFactory.cpp @@ -67,6 +67,11 @@ #include "nsPrintOptionsQt.h" #include "nsPrintDialogQt.h" #endif +#ifdef MOZ_IPC +#include "nsFilePickerProxy.h" +#include "nsXULAppAPI.h" +#endif + // from nsWindow.cpp extern PRBool gDisableNativeTheme; @@ -84,7 +89,27 @@ NS_GENERIC_FACTORY_CONSTRUCTOR(nsDragService) NS_GENERIC_FACTORY_CONSTRUCTOR(nsBidiKeyboard) NS_GENERIC_FACTORY_CONSTRUCTOR(nsIdleServiceQt) NS_GENERIC_FACTORY_CONSTRUCTOR(nsSound) -NS_GENERIC_FACTORY_CONSTRUCTOR(nsFilePicker) + +static nsresult +nsFilePickerConstructor(nsISupports *aOuter, REFNSIID aIID, + void **aResult) +{ + *aResult = nsnull; + if (aOuter != nsnull) { + return NS_ERROR_NO_AGGREGATION; + } + nsCOMPtr picker; + +#ifdef MOZ_IPC + if (XRE_GetProcessType() == GeckoProcessType_Content) + picker = new nsFilePickerProxy(); + else +#endif + picker = new nsFilePicker; + + return picker->QueryInterface(aIID, aResult); +} + #ifdef NS_PRINTING NS_GENERIC_FACTORY_CONSTRUCTOR(nsDeviceContextSpecQt) diff --git a/widget/src/xpwidgets/Makefile.in b/widget/src/xpwidgets/Makefile.in index 61ef5470e38..c5638400f4f 100644 --- a/widget/src/xpwidgets/Makefile.in +++ b/widget/src/xpwidgets/Makefile.in @@ -73,6 +73,7 @@ CPPSRCS = \ ifdef MOZ_IPC CPPSRCS += \ PuppetWidget.cpp \ + nsFilePickerProxy.cpp \ $(NULL) endif @@ -80,7 +81,7 @@ ifneq (,$(filter beos os2 cocoa windows,$(MOZ_WIDGET_TOOLKIT))) CPPSRCS += nsBaseClipboard.cpp endif -ifneq (,$(filter beos qt gtk2 os2 cocoa windows,$(MOZ_WIDGET_TOOLKIT))) +ifneq (,$(filter beos qt gtk2 os2 cocoa windows android,$(MOZ_WIDGET_TOOLKIT))) CPPSRCS += nsBaseFilePicker.cpp endif diff --git a/widget/src/xpwidgets/nsFilePickerProxy.cpp b/widget/src/xpwidgets/nsFilePickerProxy.cpp new file mode 100644 index 00000000000..9e15fc6b678 --- /dev/null +++ b/widget/src/xpwidgets/nsFilePickerProxy.cpp @@ -0,0 +1,204 @@ +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- + * + * ***** BEGIN LICENSE BLOCK ***** + * Version: MPL 1.1/GPL 2.0/LGPL 2.1 + * + * The contents of this file are subject to the Mozilla Public License Version + * 1.1 (the "License"); you may not use this file except in compliance with + * the License. You may obtain a copy of the License at + * http://www.mozilla.org/MPL/ + * + * Software distributed under the License is distributed on an "AS IS" basis, + * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License + * for the specific language governing rights and limitations under the + * License. + * + * The Original Code is mozilla.org code. + * + * The Initial Developer of the Original Code is + * The Mozilla Foundation + * Portions created by the Initial Developer are Copyright (C) 2004 + * the Initial Developer. All Rights Reserved. + * + * Contributor(s): + * Lars Knoll + * Zack Rusin + * Steffen Imhof + * + * Alternatively, the contents of this file may be used under the terms of + * either the GNU General Public License Version 2 or later (the "GPL"), or + * the GNU Lesser General Public License Version 2.1 or later (the "LGPL"), + * in which case the provisions of the GPL or the LGPL are applicable instead + * of those above. If you wish to allow use of your version of this file only + * under the terms of either the GPL or the LGPL, and not to allow others to + * use your version of this file under the terms of the MPL, indicate your + * decision by deleting the provisions above and replace them with the notice + * and other provisions required by the GPL or the LGPL. If you do not delete + * the provisions above, a recipient may use your version of this file under + * the terms of any one of the MPL, the GPL or the LGPL. + * + * ***** END LICENSE BLOCK ***** */ + +#include "mozilla/dom/ContentChild.h" +#include "nsFilePickerProxy.h" + + +NS_IMPL_ISUPPORTS1(nsFilePickerProxy, nsIFilePicker) + +nsFilePickerProxy::nsFilePickerProxy() +{ +} + +nsFilePickerProxy::~nsFilePickerProxy() +{ +} + +NS_IMETHODIMP +nsFilePickerProxy::Init(nsIDOMWindow* /*aParent*/, const nsAString& aTitle, + PRInt16 aMode) +{ + mTitle = aTitle; + mMode = aMode; + + return NS_OK; +} + +void nsFilePickerProxy::InitNative(nsIWidget* aParent, const nsAString& aTitle, + PRInt16 aMode) +{ +} + + +NS_IMETHODIMP +nsFilePickerProxy::AppendFilter(const nsAString& aTitle, const nsAString& aFilter) +{ + mFilters.AppendElement(aFilter); + mFilterNames.AppendElement(aTitle); + return NS_OK; +} + +NS_IMETHODIMP +nsFilePickerProxy::GetDefaultString(nsAString& aDefaultString) +{ + aDefaultString = mDefault; + return NS_OK; +} + +NS_IMETHODIMP +nsFilePickerProxy::SetDefaultString(const nsAString& aDefaultString) +{ + mDefault = aDefaultString; + return NS_OK; +} + +NS_IMETHODIMP +nsFilePickerProxy::GetDefaultExtension(nsAString& aDefaultExtension) +{ + aDefaultExtension = mDefaultExtension; + return NS_OK; +} + +NS_IMETHODIMP +nsFilePickerProxy::SetDefaultExtension(const nsAString& aDefaultExtension) +{ + mDefaultExtension = aDefaultExtension; + return NS_OK; +} + +NS_IMETHODIMP +nsFilePickerProxy::GetFilterIndex(PRInt32* aFilterIndex) +{ + *aFilterIndex = mSelectedType; + return NS_OK; +} + +NS_IMETHODIMP +nsFilePickerProxy::SetFilterIndex(PRInt32 aFilterIndex) +{ + mSelectedType = aFilterIndex; + return NS_OK; +} + +/* readonly attribute nsILocalFile file; */ +NS_IMETHODIMP +nsFilePickerProxy::GetFile(nsILocalFile** aFile) +{ + NS_ENSURE_ARG_POINTER(aFile); + + *aFile = nsnull; + if (mFile.IsEmpty()) { + return NS_OK; + } + + nsCOMPtr file(do_CreateInstance("@mozilla.org/file/local;1")); + NS_ENSURE_TRUE(file, NS_ERROR_FAILURE); + + file->InitWithPath(mFile); + + file.forget(aFile); + + return NS_OK; +} + +/* readonly attribute nsIFileURL fileURL; */ +NS_IMETHODIMP +nsFilePickerProxy::GetFileURL(nsIURI** aFileURL) +{ + nsCOMPtr file; + GetFile(getter_AddRefs(file)); + + nsCOMPtr uri; + NS_NewFileURI(getter_AddRefs(uri), file); + NS_ENSURE_TRUE(uri, NS_ERROR_FAILURE); + + return CallQueryInterface(uri, aFileURL); +} + +/* readonly attribute nsISimpleEnumerator files; */ +NS_IMETHODIMP +nsFilePickerProxy::GetFiles(nsISimpleEnumerator** aFiles) +{ + NS_ENSURE_ARG_POINTER(aFiles); + + if (mMode == nsIFilePicker::modeOpenMultiple) { + return NS_NewArrayEnumerator(aFiles, mFiles); + } + + return NS_ERROR_FAILURE; +} + +NS_IMETHODIMP nsFilePickerProxy::Show(PRInt16* aReturn) +{ + mozilla::dom::ContentChild *cc = mozilla::dom::ContentChild::GetSingleton(); + NS_ASSERTION(cc, "Content Protocol is NULL!"); + + nsTArray filePaths; + + nsresult rv; + cc->SendShowFilePicker(mMode, mSelectedType, mTitle, + mDefault, mDefaultExtension, + mFilters, mFilterNames, + &filePaths, aReturn, &rv); + + NS_ENSURE_SUCCESS(rv, rv); + + PRUint32 count = filePaths.Length(); + + if (mMode == nsIFilePicker::modeOpenMultiple) { + for (PRUint32 i = 0; i < count; ++i) { + nsCOMPtr file(do_CreateInstance("@mozilla.org/file/local;1")); + NS_ENSURE_TRUE(file, NS_ERROR_FAILURE); + + file->InitWithPath(filePaths[i]); + mFiles.AppendObject(file); + } + return NS_OK; + } + + NS_ASSERTION(count == 1 || count == 0, "we should only have 1 or 0 files"); + + if (count == 1) + mFile = filePaths[0]; + + return NS_OK; +} diff --git a/widget/src/xpwidgets/nsFilePickerProxy.h b/widget/src/xpwidgets/nsFilePickerProxy.h new file mode 100644 index 00000000000..f041ed943a1 --- /dev/null +++ b/widget/src/xpwidgets/nsFilePickerProxy.h @@ -0,0 +1,97 @@ +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- + * + * ***** BEGIN LICENSE BLOCK ***** + * Version: MPL 1.1/GPL 2.0/LGPL 2.1 + * + * The contents of this file are subject to the Mozilla Public License Version + * 1.1 (the "License"); you may not use this file except in compliance with + * the License. You may obtain a copy of the License at + * http://www.mozilla.org/MPL/ + * + * Software distributed under the License is distributed on an "AS IS" basis, + * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License + * for the specific language governing rights and limitations under the + * License. + * + * The Original Code is mozilla.org code. + * + * The Initial Developer of the Original Code is + * The Mozilla Foundation. + * Portions created by the Initial Developer are Copyright (C) 2004 + * the Initial Developer. All Rights Reserved. + * + * Contributor(s): + * Lars Knoll + * Zack Rusin + * Steffen Imhof + * + * Alternatively, the contents of this file may be used under the terms of + * either the GNU General Public License Version 2 or later (the "GPL"), or + * the GNU Lesser General Public License Version 2.1 or later (the "LGPL"), + * in which case the provisions of the GPL or the LGPL are applicable instead + * of those above. If you wish to allow use of your version of this file only + * under the terms of either the GPL or the LGPL, and not to allow others to + * use your version of this file under the terms of the MPL, indicate your + * decision by deleting the provisions above and replace them with the notice + * and other provisions required by the GPL or the LGPL. If you do not delete + * the provisions above, a recipient may use your version of this file under + * the terms of any one of the MPL, the GPL or the LGPL. + * + * ***** END LICENSE BLOCK ***** */ +#ifndef NSFILEPICKERPROXY_H +#define NSFILEPICKERPROXY_H + +#include "nsBaseFilePicker.h" +#include "nsString.h" +#include "nsIURI.h" +#include "nsTArray.h" +#include "nsCOMArray.h" + +class nsIWidget; +class nsILocalFile; + +/** + This class creates a proxy file picker to be used in content processes. + The file picker just collects the initialization data and when Show() is + called, remotes everything to the chrome process which in turn can show a + platform specific file picker. +*/ +class nsFilePickerProxy : public nsBaseFilePicker +{ +public: + nsFilePickerProxy(); + + NS_DECL_ISUPPORTS + + // nsIFilePicker (less what's in nsBaseFilePicker) + NS_IMETHODIMP Init(nsIDOMWindow* parent, const nsAString& title, PRInt16 mode); + NS_IMETHODIMP AppendFilter(const nsAString& aTitle, const nsAString& aFilter); + NS_IMETHODIMP GetDefaultString(nsAString& aDefaultString); + NS_IMETHODIMP SetDefaultString(const nsAString& aDefaultString); + NS_IMETHODIMP GetDefaultExtension(nsAString& aDefaultExtension); + NS_IMETHODIMP SetDefaultExtension(const nsAString& aDefaultExtension); + NS_IMETHODIMP GetFilterIndex(PRInt32* aFilterIndex); + NS_IMETHODIMP SetFilterIndex(PRInt32 aFilterIndex); + NS_IMETHODIMP GetFile(nsILocalFile** aFile); + NS_IMETHODIMP GetFileURL(nsIURI** aFileURL); + NS_IMETHODIMP GetFiles(nsISimpleEnumerator** aFiles); + NS_IMETHODIMP Show(PRInt16* aReturn); + +private: + ~nsFilePickerProxy(); + void InitNative(nsIWidget*, const nsAString&, short int); + + nsCOMArray mFiles; + + PRInt16 mMode; + PRInt16 mSelectedType; + nsString mFile; + nsString mTitle; + nsString mDefault; + nsString mDefaultExtension; + + nsTArray mFilters; + nsTArray mFilterNames; +}; + +#endif // NSFILEPICKERPROXY_H