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.AppFileLocProvider;
14 
15 version(Tango){
16     import tango.sys.Environment;
17 } else { // Phobos
18     import std.process: Environment = environment;
19 }
20 
21 import java.lang.all;
22 import java.util.Vector;
23 
24 import org.eclipse.swt.browser.Mozilla;
25 import org.eclipse.swt.browser.SimpleEnumerator;
26 
27 import org.eclipse.swt.internal.Compatibility;
28 
29 import XPCOM = org.eclipse.swt.internal.mozilla.XPCOM;
30 
31 import org.eclipse.swt.internal.mozilla.Common;
32 import org.eclipse.swt.internal.mozilla.nsISimpleEnumerator;
33 import org.eclipse.swt.internal.mozilla.nsEmbedString;
34 import org.eclipse.swt.internal.mozilla.nsID;
35 import org.eclipse.swt.internal.mozilla.nsIDirectoryService;
36 import org.eclipse.swt.internal.mozilla.nsIFile;
37 import org.eclipse.swt.internal.mozilla.nsILocalFile;
38 import org.eclipse.swt.internal.mozilla.nsISupports;
39 import org.eclipse.swt.internal.mozilla.nsStringAPI;
40 
41 class AppFileLocProvider : nsIDirectoryServiceProvider2 { 
42     int refCount = 0;
43     String mozillaPath, profilePath;
44     String[] pluginDirs;
45     bool isXULRunner;
46     
47     static       String SEPARATOR_OS;
48     static const String CHROME_DIR = "chrome"; //$NON-NLS-1$
49     static const String COMPONENTS_DIR = "components"; //$NON-NLS-1$
50     static const String HISTORY_FILE = "history.dat"; //$NON-NLS-1$
51     static const String LOCALSTORE_FILE = "localstore.rdf"; //$NON-NLS-1$
52     static const String MIMETYPES_FILE = "mimeTypes.rdf"; //$NON-NLS-1$
53     static const String PLUGINS_DIR = "plugins"; //$NON-NLS-1$
54     static       String USER_PLUGINS_DIR;
55     static const String PREFERENCES_FILE = "prefs.js"; //$NON-NLS-1$
56 
57 static this () {
58     SEPARATOR_OS = System.getProperty ("file.separator");
59     USER_PLUGINS_DIR = ".mozilla" ~ SEPARATOR_OS ~ "plugins";
60 }
61 
62 this (String path) {
63     mozillaPath = path ~ SEPARATOR_OS;
64 }
65 
66 extern(System)
67 nsrefcnt AddRef () {
68     refCount++;
69     return refCount;
70 }
71 
72 extern(System)
73 nsresult QueryInterface (in cnsID* riid, void** ppvObject) {
74     if (riid is null || ppvObject is null) return XPCOM.NS_ERROR_NO_INTERFACE;
75 
76     if (*riid == nsISupports.IID) {
77         *ppvObject = cast(void*)cast(nsISupports)this;
78         AddRef ();
79         return XPCOM.NS_OK;
80     }
81     if (*riid == nsIDirectoryServiceProvider.IID) {
82         *ppvObject = cast(void*)cast(nsIDirectoryServiceProvider)this;
83         AddRef ();
84         return XPCOM.NS_OK;
85     }
86     if (*riid == nsIDirectoryServiceProvider2.IID) {
87         *ppvObject = cast(void*)cast(nsIDirectoryServiceProvider2)this;
88         AddRef ();
89         return XPCOM.NS_OK;
90     }
91     
92     *ppvObject = null;
93     return XPCOM.NS_ERROR_NO_INTERFACE;
94 }
95 
96 extern(System)
97 nsrefcnt Release () {
98     refCount--;
99     if (refCount is 0) return 0;
100     return refCount;
101 }
102 
103 void setProfilePath (String path) {
104     profilePath = path;
105     if (!Compatibility.fileExists (path, "")) { //$NON-NLS-1$
106         nsILocalFile file;
107         scope nsEmbedString pathString = new nsEmbedString (toWCharArray(path));
108         int rc = XPCOM.NS_NewLocalFile (cast(nsAString*)pathString, 1, &file);
109         if (rc !is XPCOM.NS_OK) Mozilla.error (rc);
110         if (file is null) Mozilla.error (XPCOM.NS_ERROR_NULL_POINTER);
111 
112         rc = file.Create (nsILocalFile.DIRECTORY_TYPE, 0700);
113         if (rc !is XPCOM.NS_OK) Mozilla.error (rc);
114         file.Release ();
115     }
116 }
117 
118 /* nsIDirectoryServiceProvider2 */
119 extern(System)
120 nsresult GetFiles (char* prop, nsISimpleEnumerator* _retval) {
121     String propertyName = fromStringz(prop)._idup();
122     String[] propertyValues = null;
123 
124     if (propertyName == XPCOM.NS_APP_PLUGINS_DIR_LIST) {
125         if (pluginDirs is null) {
126             int index = 0;
127             /* set the first value(s) to the MOZ_PLUGIN_PATH environment variable value if it's defined */
128             String value = Environment.get (XPCOM.MOZILLA_PLUGIN_PATH);
129             if (value !is null) {
130                 if (value.length > 0) {
131                     String separator = System.getProperty ("path.separator"); // $NON-NLS-1$
132                     Vector segments = new Vector ();
133                     int start, end = -1;
134                     do {
135                         start = end + 1;
136                         end = value.indexOf (separator, start);
137                         String segment;
138                         if (end is -1) {
139                             segment = value.substring (start);
140                         } else {
141                             segment = value.substring (start, end);
142                         }
143                         if (segment.length () > 0) segments.addElement (stringcast(segment));
144                     } while (end !is -1);
145                     int segmentsSize = segments.size ();
146                     pluginDirs = new String [segmentsSize + 2];
147                     for (index = 0; index < segmentsSize; index++) {
148                         pluginDirs[index] = stringcast(segments.elementAt (index));
149                     }
150                 }
151             }
152             if (pluginDirs is null) {
153                 pluginDirs = new String[2];
154             }
155 
156             /* set the next value to the GRE path + "plugins" */
157             pluginDirs[ index++ ] = mozillaPath ~ PLUGINS_DIR;
158 
159             /* set the next value to the home directory + "/.mozilla/plugins" */
160             pluginDirs[ index++ ] = System.getProperty("user.home") ~ SEPARATOR_OS ~ USER_PLUGINS_DIR;
161         }
162         propertyValues = pluginDirs;
163     }
164 
165     *_retval = null;
166     //XPCOM.memmove(_retval, new ptrdiff_t[] {0}, C.PTR_SIZEOF);
167     if (propertyValues !is null) {
168         nsILocalFile localFile;
169         nsIFile file;
170         nsISupports[] files = new nsISupports [propertyValues.length];
171         int index = 0;
172         for (int i = 0; i < propertyValues.length; i++) {
173             scope auto pathString = new nsEmbedString (toWCharArray(propertyValues[i]));
174             int rc = XPCOM.NS_NewLocalFile (cast(nsAString*)pathString, 1, &localFile);
175             if (rc !is XPCOM.NS_ERROR_FILE_UNRECOGNIZED_PATH) {
176                 /* value appears to be a valid pathname */
177                 if (rc !is XPCOM.NS_OK) Mozilla.error (rc);
178                 if (localFile is null) Mozilla.error (XPCOM.NS_ERROR_NULL_POINTER);
179 
180                 rc = localFile.QueryInterface (&nsIFile.IID, cast(void**)&file); 
181                 if (rc !is XPCOM.NS_OK) Mozilla.error (rc);
182                 if (file is null) Mozilla.error (XPCOM.NS_ERROR_NO_INTERFACE);
183                 localFile.Release ();
184 
185                 files[index++] = cast(nsISupports)file;
186             }
187         }
188 
189         if (index < propertyValues.length) {
190             /* there were some invalid values so remove the trailing empty array slots */
191             files = files[0..index];
192         }
193 
194         auto enumerator = new SimpleEnumerator (files);
195         enumerator.AddRef ();
196         *_retval = cast(nsISimpleEnumerator)enumerator;
197         return XPCOM.NS_OK;
198     }
199 
200     return XPCOM.NS_ERROR_FAILURE;
201 }   
202     
203 /* nsIDirectoryServiceProvider implementation */
204 extern(System)
205 nsresult GetFile(char* prop, PRBool* persistent, nsIFile* _retval) {
206     String propertyName = fromStringz( prop )._idup();
207     String propertyValue = null;
208 
209     if (propertyName == (XPCOM.NS_APP_HISTORY_50_FILE)) {
210         propertyValue = profilePath ~ HISTORY_FILE;
211     } else if (propertyName == (XPCOM.NS_APP_USER_MIMETYPES_50_FILE)) {
212         propertyValue = profilePath ~ MIMETYPES_FILE;
213     } else if (propertyName == (XPCOM.NS_APP_PREFS_50_FILE)) {
214         propertyValue = profilePath ~ PREFERENCES_FILE;
215     } else if (propertyName == (XPCOM.NS_APP_PREFS_50_DIR)) {
216         propertyValue = profilePath;
217     } else if (propertyName == (XPCOM.NS_APP_USER_CHROME_DIR)) {
218         propertyValue = profilePath ~ CHROME_DIR;
219     } else if (propertyName == (XPCOM.NS_APP_USER_PROFILE_50_DIR)) {
220         propertyValue = profilePath;
221     } else if (propertyName == (XPCOM.NS_APP_LOCALSTORE_50_FILE)) {
222         propertyValue = profilePath ~ LOCALSTORE_FILE;
223     } else if (propertyName == (XPCOM.NS_APP_CACHE_PARENT_DIR)) {
224         propertyValue = profilePath;
225     } else if (propertyName == (XPCOM.NS_OS_HOME_DIR)) {
226         propertyValue = System.getProperty("user.home");    //$NON-NLS-1$
227     } else if (propertyName == (XPCOM.NS_OS_TEMP_DIR)) {
228         propertyValue = System.getProperty("java.io.tmpdir");   //$NON-NLS-1$
229     } else if (propertyName == (XPCOM.NS_GRE_DIR)) {
230         propertyValue = mozillaPath;
231     } else if (propertyName == (XPCOM.NS_GRE_COMPONENT_DIR)) {
232         propertyValue = mozillaPath ~ COMPONENTS_DIR;
233     } else if (propertyName == (XPCOM.NS_XPCOM_INIT_CURRENT_PROCESS_DIR)) {
234         propertyValue = mozillaPath;
235     } else if (propertyName == (XPCOM.NS_OS_CURRENT_PROCESS_DIR)) {
236         propertyValue = mozillaPath;
237     } else if (propertyName == (XPCOM.NS_XPCOM_COMPONENT_DIR)) {
238         propertyValue = mozillaPath ~ COMPONENTS_DIR;
239     } else if (propertyName == (XPCOM.NS_XPCOM_CURRENT_PROCESS_DIR)) {
240         propertyValue = mozillaPath;
241     } else if (propertyName == (XPCOM.NS_APP_PREF_DEFAULTS_50_DIR)) {
242         /*
243         * Answering a value for this property causes problems in Mozilla versions
244         * < 1.7.  Unfortunately this property is queried early enough in the
245         * Browser creation process that the Mozilla version being used is not
246         * yet determined.  However it is known if XULRunner is being used or not.
247         * 
248         * For now answer a value for this property iff XULRunner is the GRE.
249         * If the range of Mozilla versions supported by the Browser is changed
250         * in the future to be >= 1.7 then this value can always be answered.  
251         */
252         if (isXULRunner) propertyValue = profilePath;
253     }
254 
255     *persistent = true; /* PRBool */
256     *_retval = null;
257     if (propertyValue !is null && propertyValue.length > 0) {
258         nsILocalFile localFile;
259         scope auto pathString = new nsEmbedString (propertyValue.toWCharArray());
260         int rc = XPCOM.NS_NewLocalFile (cast(nsAString*)pathString, 1, &localFile);
261         if (rc !is XPCOM.NS_OK) Mozilla.error (rc);
262         if (localFile is null) Mozilla.error (XPCOM.NS_ERROR_NULL_POINTER);
263         
264         nsIFile file;
265         rc = localFile.QueryInterface (&nsIFile.IID, cast(void**)&file); 
266         if (rc !is XPCOM.NS_OK) Mozilla.error (rc);
267         if (file is null) Mozilla.error (XPCOM.NS_ERROR_NO_INTERFACE);
268 
269         *_retval = file;
270         localFile.Release ();
271         return XPCOM.NS_OK;
272     }
273 
274     return XPCOM.NS_ERROR_FAILURE;
275 }       
276 }