1 /*******************************************************************************
2  * Copyright (c) 2003, 2007 IBM Corporation and others.
3  * All rights reserved. This program and the accompanying materials
4  * are made available under the terms of the Eclipse Public License v1.0
5  * which accompanies this distribution, and is available at
6  * http://www.eclipse.org/legal/epl-v10.html
7  *
8  * Contributors:
9  *     IBM Corporation - initial API and implementation
10  * Port to the D programming language:
11  *      John Reimer <terminal.node@gmail.com>
12  *******************************************************************************/
13 module org.eclipse.swt.browser.HelperAppLauncherDialog;
14 
15 import java.lang.all;
16 
17 import org.eclipse.swt.SWT;
18 
19 import XPCOM = org.eclipse.swt.internal.mozilla.XPCOM;
20 
21 import org.eclipse.swt.internal.mozilla.Common;
22 import org.eclipse.swt.internal.mozilla.nsEmbedString;
23 import org.eclipse.swt.internal.mozilla.nsID;
24 import org.eclipse.swt.internal.mozilla.nsIHelperAppLauncher;
25 import org.eclipse.swt.internal.mozilla.nsIHelperAppLauncherDialog;
26 import org.eclipse.swt.internal.mozilla.nsIHelperAppLauncher_1_8;
27 import org.eclipse.swt.internal.mozilla.nsISupports;
28 import org.eclipse.swt.internal.mozilla.nsILocalFile;
29 import org.eclipse.swt.internal.mozilla.nsStringAPI;
30 
31 import org.eclipse.swt.browser.Mozilla;
32 
33 import org.eclipse.swt.widgets.FileDialog;
34 import org.eclipse.swt.widgets.Shell;
35 
36 /**
37  * This class implements the HelperAppLauncherDialog interface for mozilla
38  * versions 1.4 - 1.8.x.  For mozilla versions >= 1.9 this interface is
39  * implemented by class HelperAppLauncherDialog_1_9.  HelperAppLauncherDialogFactory
40  * determines at runtime which of these classes to instantiate. 
41  */
42 
43 class HelperAppLauncherDialog : nsIHelperAppLauncherDialog {
44     int refCount = 0;
45 
46 this() {
47 }
48 
49 extern(System)
50 nsrefcnt AddRef () {
51     refCount++;
52     return refCount;
53 }
54 
55 extern(System)
56 nsresult QueryInterface (in nsID* riid, void** ppvObject) {
57     if (riid is null || ppvObject is null) return XPCOM.NS_ERROR_NO_INTERFACE;
58     
59     if (*riid == nsISupports.IID) {
60         *ppvObject = cast(void*)cast(nsISupports)this;
61         AddRef ();
62         return XPCOM.NS_OK;
63     }
64     if (*riid == nsIHelperAppLauncherDialog.IID) {
65         *ppvObject = cast(void*)cast(nsIHelperAppLauncherDialog)this;
66         AddRef ();
67         return XPCOM.NS_OK;
68     }
69     
70     *ppvObject = null;
71     return XPCOM.NS_ERROR_NO_INTERFACE;
72 }
73 
74 extern(System)
75 nsrefcnt Release () {
76     refCount--;
77     /*
78     * Note.  This instance lives as long as the download it is binded to.
79     * Its reference count is expected to go down to 0 when the download
80     * has completed or when it has been cancelled. E.g. when the user
81     * cancels the File Dialog, cancels or closes the Download Dialog
82     * and when the Download Dialog goes away after the download is completed.
83     */
84     if (refCount is 0) return 0;
85     return refCount;
86 }
87 
88 /* nsIHelperAppLauncherDialog */
89 
90 extern(System)
91 nsresult Show(nsIHelperAppLauncher aLauncher, nsISupports aContext, PRUint32 aReason) {
92      /*
93      * The interface for nsIHelperAppLauncher changed as of mozilla 1.8.  Query the received
94      * nsIHelperAppLauncher for the new interface, and if it is not found then fall back to
95      * the old interface. 
96      */
97 
98     nsISupports supports = cast(nsISupports)aLauncher;
99     nsIHelperAppLauncher_1_8 helperAppLauncher;
100     nsresult rc = supports.QueryInterface (&nsIHelperAppLauncher_1_8.IID, cast(void**)&helperAppLauncher);
101     if (rc is 0) {
102         rc = helperAppLauncher.SaveToDisk (null, 0);
103         helperAppLauncher.Release ();
104         return rc;
105     }
106 
107     /* < 1.8 */
108     return aLauncher.SaveToDisk (null, 0);
109     // no Release for this? -JJR
110 }
111 
112 extern(System)
113 nsresult PromptForSaveToFile (nsIHelperAppLauncher aLauncher, nsISupports aWindowContext, PRUnichar* aDefaultFile, PRUnichar* aSuggestedFileExtension, nsILocalFile* _retval) {
114     bool hasLauncher = false;
115 
116     /*
117     * The interface for nsIHelperAppLauncherDialog changed as of mozilla 1.5 when an
118     * extra argument was added to the PromptForSaveToFile method (this resulted in all
119     * subsequent arguments shifting right).  The workaround is to provide an XPCOMObject 
120     * that fits the newer API, and to use the first argument's type to infer whether
121     * the old or new nsIHelperAppLauncherDialog interface is being used (and by extension
122     * the ordering of the arguments).  In mozilla >= 1.5 the first argument is an
123     * nsIHelperAppLauncher. 
124     */
125     /*
126      * The interface for nsIHelperAppLauncher changed as of mozilla 1.8, so the first
127      * argument must be queried for both the old and new nsIHelperAppLauncher interfaces. 
128      */
129     bool using_1_8 = false;
130     nsISupports support = cast(nsISupports)aLauncher; 
131     
132     if (aLauncher is null)
133         assert(0);
134 
135     nsIHelperAppLauncher_1_8 helperAppLauncher1;
136     int rc = support.QueryInterface (&nsIHelperAppLauncher_1_8.IID, cast(void**)&helperAppLauncher1);
137     if (rc is XPCOM.NS_OK) {
138         using_1_8 = true;
139         hasLauncher = true;
140         helperAppLauncher1.Release ();
141     } else {
142         nsIHelperAppLauncher helperAppLauncher;
143         rc = support.QueryInterface (&nsIHelperAppLauncher.IID, cast(void**)&helperAppLauncher);
144         if (rc is XPCOM.NS_OK) {
145             hasLauncher = true;
146             helperAppLauncher.Release;
147         }
148     }
149 
150 /+
151     // In D port, no suppport for version >1.4 yet
152     if (hasLauncher) {  /* >= 1.5 */
153         aDefaultFile = arg2;
154         aSuggestedFileExtension = arg3;
155         _retval = arg4;
156     } else {            /* 1.4 */  
157     // This call conversion probablywon't work for non-Java
158     // and shouldn't get called; fix it later. -JJR
159         aDefaultFile = arg1;
160         aSuggestedFileExtension = arg2;
161         _retval = arg3;
162     }
163 +/
164     //int span = XPCOM.strlen_PRUnichar (aDefaultFile);
165     // XPCOM.memmove (dest, aDefaultFile, length * 2);
166     String defaultFile = String_valueOf(fromString16z(aDefaultFile));
167 
168     //span = XPCOM.strlen_PRUnichar (aSuggestedFileExtension);
169     //dest = new char[length];
170     //XPCOM.memmove (dest, aSuggestedFileExtension, length * 2);
171     String suggestedFileExtension =  String_valueOf(fromString16z(aSuggestedFileExtension));
172 
173     Shell shell = new Shell ();
174     FileDialog fileDialog = new FileDialog (shell, SWT.SAVE);
175     fileDialog.setFileName (defaultFile);
176     String[] tmp;
177     tmp ~= suggestedFileExtension; 
178     fileDialog.setFilterExtensions (tmp);
179     String name = fileDialog.open ();
180     shell.close ();
181     if (name is null) {
182         if (hasLauncher) {
183             if (using_1_8) {
184                 rc = (cast(nsIHelperAppLauncher_1_8)aLauncher).Cancel (XPCOM.NS_BINDING_ABORTED);
185             } else {
186                 rc = aLauncher.Cancel ();
187             }
188             if (rc !is XPCOM.NS_OK) Mozilla.error (rc,__FILE__,__LINE__); 
189             return XPCOM.NS_OK;
190         }
191         return XPCOM.NS_ERROR_FAILURE;
192     }
193     scope auto path = new nsEmbedString (name.toWCharArray());
194     nsILocalFile localFile;
195     rc = XPCOM.NS_NewLocalFile (cast(nsAString*)path, 1, &localFile);
196     //path.dispose ();
197     if (rc !is XPCOM.NS_OK) Mozilla.error (rc,__FILE__,__LINE__);
198     if (localFile is null) Mozilla.error (XPCOM.NS_ERROR_NULL_POINTER,__FILE__,__LINE__);
199     /* Our own nsIDownload has been registered during the Browser initialization. It will be invoked by Mozilla. */
200     *_retval = localFile; 
201     //XPCOM.memmove (_retval, result, C.PTR_SIZEOF);  
202     return XPCOM.NS_OK;
203 }
204 }