1 : /* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
2 : /* ***** BEGIN LICENSE BLOCK *****
3 : * Version: MPL 1.1/GPL 2.0/LGPL 2.1
4 : *
5 : * The contents of this file are subject to the Mozilla Public License Version
6 : * 1.1 (the "License"); you may not use this file except in compliance with
7 : * the License. You may obtain a copy of the License at
8 : * http://www.mozilla.org/MPL/
9 : *
10 : * Software distributed under the License is distributed on an "AS IS" basis,
11 : * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
12 : * for the specific language governing rights and limitations under the
13 : * License.
14 : *
15 : * The Original Code is Shell Service.
16 : *
17 : * The Initial Developer of the Original Code is mozilla.org.
18 : * Portions created by the Initial Developer are Copyright (C) 2004
19 : * the Initial Developer. All Rights Reserved.
20 : *
21 : * Contributor(s):
22 : *
23 : * Alternatively, the contents of this file may be used under the terms of
24 : * either the GNU General Public License Version 2 or later (the "GPL"), or
25 : * the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
26 : * in which case the provisions of the GPL or the LGPL are applicable instead
27 : * of those above. If you wish to allow use of your version of this file only
28 : * under the terms of either the GPL or the LGPL, and not to allow others to
29 : * use your version of this file under the terms of the MPL, indicate your
30 : * decision by deleting the provisions above and replace them with the notice
31 : * and other provisions required by the GPL or the LGPL. If you do not delete
32 : * the provisions above, a recipient may use your version of this file under
33 : * the terms of any one of the MPL, the GPL or the LGPL.
34 : *
35 : * ***** END LICENSE BLOCK ***** */
36 :
37 : #include "mozilla/Util.h"
38 :
39 : #include "nsCOMPtr.h"
40 : #include "nsGNOMEShellService.h"
41 : #include "nsShellService.h"
42 : #include "nsIServiceManager.h"
43 : #include "nsILocalFile.h"
44 : #include "nsIProperties.h"
45 : #include "nsDirectoryServiceDefs.h"
46 : #include "nsIPrefService.h"
47 : #include "prenv.h"
48 : #include "nsStringAPI.h"
49 : #include "nsIGConfService.h"
50 : #include "nsIGIOService.h"
51 : #include "nsIGSettingsService.h"
52 : #include "nsIStringBundle.h"
53 : #include "nsIOutputStream.h"
54 : #include "nsIProcess.h"
55 : #include "nsNetUtil.h"
56 : #include "nsIDOMHTMLImageElement.h"
57 : #include "nsIImageLoadingContent.h"
58 : #include "imgIRequest.h"
59 : #include "imgIContainer.h"
60 : #include "prprf.h"
61 : #ifdef MOZ_WIDGET_GTK2
62 : #include "nsIImageToPixbuf.h"
63 : #endif
64 :
65 : #include <glib.h>
66 : #include <glib-object.h>
67 : #include <gtk/gtk.h>
68 : #include <gdk/gdk.h>
69 : #include <gdk-pixbuf/gdk-pixbuf.h>
70 : #include <limits.h>
71 : #include <stdlib.h>
72 :
73 : using namespace mozilla;
74 :
75 : struct ProtocolAssociation
76 : {
77 : const char *name;
78 : bool essential;
79 : };
80 :
81 : struct MimeTypeAssociation
82 : {
83 : const char *mimeType;
84 : const char *extensions;
85 : };
86 :
87 : static const ProtocolAssociation appProtocols[] = {
88 : { "http", true },
89 : { "https", true },
90 : { "ftp", false },
91 : { "chrome", false }
92 : };
93 :
94 : static const MimeTypeAssociation appTypes[] = {
95 : { "text/html", "htm html shtml" },
96 : { "application/xhtml+xml", "xhtml xht" }
97 : };
98 :
99 : // GConf registry key constants
100 : #define DG_BACKGROUND "/desktop/gnome/background"
101 :
102 : static const char kDesktopImageKey[] = DG_BACKGROUND "/picture_filename";
103 : static const char kDesktopOptionsKey[] = DG_BACKGROUND "/picture_options";
104 : static const char kDesktopDrawBGKey[] = DG_BACKGROUND "/draw_background";
105 : static const char kDesktopColorKey[] = DG_BACKGROUND "/primary_color";
106 :
107 : static const char kDesktopBGSchema[] = "org.gnome.desktop.background";
108 : static const char kDesktopImageGSKey[] = "picture-uri";
109 : static const char kDesktopOptionGSKey[] = "picture-options";
110 : static const char kDesktopDrawBGGSKey[] = "draw-background";
111 : static const char kDesktopColorGSKey[] = "primary-color";
112 :
113 : nsresult
114 1 : nsGNOMEShellService::Init()
115 : {
116 : nsresult rv;
117 :
118 : // GConf, GSettings or GIO _must_ be available, or we do not allow
119 : // CreateInstance to succeed.
120 :
121 2 : nsCOMPtr<nsIGConfService> gconf = do_GetService(NS_GCONFSERVICE_CONTRACTID);
122 : nsCOMPtr<nsIGIOService> giovfs =
123 2 : do_GetService(NS_GIOSERVICE_CONTRACTID);
124 : nsCOMPtr<nsIGSettingsService> gsettings =
125 2 : do_GetService(NS_GSETTINGSSERVICE_CONTRACTID);
126 :
127 1 : if (!gconf && !giovfs && !gsettings)
128 0 : return NS_ERROR_NOT_AVAILABLE;
129 :
130 : // Check G_BROKEN_FILENAMES. If it's set, then filenames in glib use
131 : // the locale encoding. If it's not set, they use UTF-8.
132 1 : mUseLocaleFilenames = PR_GetEnv("G_BROKEN_FILENAMES") != nsnull;
133 :
134 1 : if (GetAppPathFromLauncher())
135 0 : return NS_OK;
136 :
137 : nsCOMPtr<nsIProperties> dirSvc
138 2 : (do_GetService("@mozilla.org/file/directory_service;1"));
139 1 : NS_ENSURE_TRUE(dirSvc, NS_ERROR_NOT_AVAILABLE);
140 :
141 2 : nsCOMPtr<nsILocalFile> appPath;
142 1 : rv = dirSvc->Get(NS_XPCOM_CURRENT_PROCESS_DIR, NS_GET_IID(nsILocalFile),
143 1 : getter_AddRefs(appPath));
144 1 : NS_ENSURE_SUCCESS(rv, rv);
145 :
146 1 : rv = appPath->AppendNative(NS_LITERAL_CSTRING(MOZ_APP_NAME));
147 1 : NS_ENSURE_SUCCESS(rv, rv);
148 :
149 1 : return appPath->GetNativePath(mAppPath);
150 : }
151 :
152 22 : NS_IMPL_ISUPPORTS1(nsGNOMEShellService, nsIShellService)
153 :
154 : bool
155 1 : nsGNOMEShellService::GetAppPathFromLauncher()
156 : {
157 : gchar *tmp;
158 :
159 1 : const char *launcher = PR_GetEnv("MOZ_APP_LAUNCHER");
160 1 : if (!launcher)
161 1 : return false;
162 :
163 0 : if (g_path_is_absolute(launcher)) {
164 0 : mAppPath = launcher;
165 0 : tmp = g_path_get_basename(launcher);
166 0 : gchar *fullpath = g_find_program_in_path(tmp);
167 0 : if (fullpath && mAppPath.Equals(fullpath))
168 0 : mAppIsInPath = true;
169 0 : g_free(fullpath);
170 : } else {
171 0 : tmp = g_find_program_in_path(launcher);
172 0 : if (!tmp)
173 0 : return false;
174 0 : mAppPath = tmp;
175 0 : mAppIsInPath = true;
176 : }
177 :
178 0 : g_free(tmp);
179 0 : return true;
180 : }
181 :
182 : bool
183 0 : nsGNOMEShellService::KeyMatchesAppName(const char *aKeyValue) const
184 : {
185 :
186 : gchar *commandPath;
187 0 : if (mUseLocaleFilenames) {
188 0 : gchar *nativePath = g_filename_from_utf8(aKeyValue, -1, NULL, NULL, NULL);
189 0 : if (!nativePath) {
190 0 : NS_ERROR("Error converting path to filesystem encoding");
191 0 : return false;
192 : }
193 :
194 0 : commandPath = g_find_program_in_path(nativePath);
195 0 : g_free(nativePath);
196 : } else {
197 0 : commandPath = g_find_program_in_path(aKeyValue);
198 : }
199 :
200 0 : if (!commandPath)
201 0 : return false;
202 :
203 0 : bool matches = mAppPath.Equals(commandPath);
204 0 : g_free(commandPath);
205 0 : return matches;
206 : }
207 :
208 : bool
209 0 : nsGNOMEShellService::CheckHandlerMatchesAppName(const nsACString &handler) const
210 : {
211 : gint argc;
212 : gchar **argv;
213 0 : nsCAutoString command(handler);
214 :
215 : // The string will be something of the form: [/path/to/]browser "%s"
216 : // We want to remove all of the parameters and get just the binary name.
217 :
218 0 : if (g_shell_parse_argv(command.get(), &argc, &argv, NULL) && argc > 0) {
219 0 : command.Assign(argv[0]);
220 0 : g_strfreev(argv);
221 : }
222 :
223 0 : if (!KeyMatchesAppName(command.get()))
224 0 : return false; // the handler is set to another app
225 :
226 0 : return true;
227 : }
228 :
229 : NS_IMETHODIMP
230 0 : nsGNOMEShellService::IsDefaultBrowser(bool aStartupCheck,
231 : bool* aIsDefaultBrowser)
232 : {
233 0 : *aIsDefaultBrowser = false;
234 0 : if (aStartupCheck)
235 0 : mCheckedThisSession = true;
236 :
237 0 : nsCOMPtr<nsIGConfService> gconf = do_GetService(NS_GCONFSERVICE_CONTRACTID);
238 0 : nsCOMPtr<nsIGIOService> giovfs = do_GetService(NS_GIOSERVICE_CONTRACTID);
239 :
240 : bool enabled;
241 0 : nsCAutoString handler;
242 0 : nsCOMPtr<nsIGIOMimeApp> gioApp;
243 :
244 0 : for (unsigned int i = 0; i < ArrayLength(appProtocols); ++i) {
245 0 : if (!appProtocols[i].essential)
246 0 : continue;
247 :
248 0 : if (gconf) {
249 0 : handler.Truncate();
250 0 : gconf->GetAppForProtocol(nsDependentCString(appProtocols[i].name),
251 0 : &enabled, handler);
252 :
253 0 : if (!CheckHandlerMatchesAppName(handler) || !enabled)
254 0 : return NS_OK; // the handler is disabled or set to another app
255 : }
256 :
257 0 : if (giovfs) {
258 0 : handler.Truncate();
259 0 : giovfs->GetAppForURIScheme(nsDependentCString(appProtocols[i].name),
260 0 : getter_AddRefs(gioApp));
261 0 : if (!gioApp)
262 0 : return NS_OK;
263 :
264 0 : gioApp->GetCommand(handler);
265 :
266 0 : if (!CheckHandlerMatchesAppName(handler))
267 0 : return NS_OK; // the handler is set to another app
268 : }
269 : }
270 :
271 0 : *aIsDefaultBrowser = true;
272 :
273 0 : return NS_OK;
274 : }
275 :
276 : NS_IMETHODIMP
277 0 : nsGNOMEShellService::SetDefaultBrowser(bool aClaimAllTypes,
278 : bool aForAllUsers)
279 : {
280 : #ifdef DEBUG
281 0 : if (aForAllUsers)
282 0 : NS_WARNING("Setting the default browser for all users is not yet supported");
283 : #endif
284 :
285 0 : nsCOMPtr<nsIGConfService> gconf = do_GetService(NS_GCONFSERVICE_CONTRACTID);
286 0 : nsCOMPtr<nsIGIOService> giovfs = do_GetService(NS_GIOSERVICE_CONTRACTID);
287 0 : if (gconf) {
288 0 : nsCAutoString appKeyValue;
289 0 : if (mAppIsInPath) {
290 : // mAppPath is in the users path, so use only the basename as the launcher
291 0 : gchar *tmp = g_path_get_basename(mAppPath.get());
292 0 : appKeyValue = tmp;
293 0 : g_free(tmp);
294 : } else {
295 0 : appKeyValue = mAppPath;
296 : }
297 :
298 0 : appKeyValue.AppendLiteral(" %s");
299 :
300 0 : for (unsigned int i = 0; i < ArrayLength(appProtocols); ++i) {
301 0 : if (appProtocols[i].essential || aClaimAllTypes) {
302 0 : gconf->SetAppForProtocol(nsDependentCString(appProtocols[i].name),
303 0 : appKeyValue);
304 : }
305 : }
306 : }
307 :
308 0 : if (giovfs) {
309 : nsresult rv;
310 : nsCOMPtr<nsIStringBundleService> bundleService =
311 0 : do_GetService(NS_STRINGBUNDLE_CONTRACTID, &rv);
312 0 : NS_ENSURE_SUCCESS(rv, rv);
313 :
314 0 : nsCOMPtr<nsIStringBundle> brandBundle;
315 0 : rv = bundleService->CreateBundle(BRAND_PROPERTIES, getter_AddRefs(brandBundle));
316 0 : NS_ENSURE_SUCCESS(rv, rv);
317 :
318 0 : nsString brandShortName;
319 0 : brandBundle->GetStringFromName(NS_LITERAL_STRING("brandShortName").get(),
320 0 : getter_Copies(brandShortName));
321 :
322 : // use brandShortName as the application id.
323 0 : NS_ConvertUTF16toUTF8 id(brandShortName);
324 0 : nsCOMPtr<nsIGIOMimeApp> appInfo;
325 0 : rv = giovfs->CreateAppFromCommand(mAppPath,
326 : id,
327 0 : getter_AddRefs(appInfo));
328 0 : NS_ENSURE_SUCCESS(rv, rv);
329 :
330 : // set handler for the protocols
331 0 : for (unsigned int i = 0; i < ArrayLength(appProtocols); ++i) {
332 0 : if (appProtocols[i].essential || aClaimAllTypes) {
333 0 : appInfo->SetAsDefaultForURIScheme(nsDependentCString(appProtocols[i].name));
334 : }
335 : }
336 :
337 : // set handler for .html and xhtml files and MIME types:
338 0 : if (aClaimAllTypes) {
339 : // Add mime types for html, xhtml extension and set app to just created appinfo.
340 0 : for (unsigned int i = 0; i < ArrayLength(appTypes); ++i) {
341 0 : appInfo->SetAsDefaultForMimeType(nsDependentCString(appTypes[i].mimeType));
342 0 : appInfo->SetAsDefaultForFileExtensions(nsDependentCString(appTypes[i].extensions));
343 : }
344 : }
345 : }
346 :
347 0 : return NS_OK;
348 : }
349 :
350 : NS_IMETHODIMP
351 0 : nsGNOMEShellService::GetShouldCheckDefaultBrowser(bool* aResult)
352 : {
353 : // If we've already checked, the browser has been started and this is a
354 : // new window open, and we don't want to check again.
355 0 : if (mCheckedThisSession) {
356 0 : *aResult = false;
357 0 : return NS_OK;
358 : }
359 :
360 0 : nsCOMPtr<nsIPrefBranch> prefs;
361 0 : nsCOMPtr<nsIPrefService> pserve(do_GetService(NS_PREFSERVICE_CONTRACTID));
362 0 : if (pserve)
363 0 : pserve->GetBranch("", getter_AddRefs(prefs));
364 :
365 0 : if (prefs)
366 0 : prefs->GetBoolPref(PREF_CHECKDEFAULTBROWSER, aResult);
367 :
368 0 : return NS_OK;
369 : }
370 :
371 : NS_IMETHODIMP
372 0 : nsGNOMEShellService::SetShouldCheckDefaultBrowser(bool aShouldCheck)
373 : {
374 0 : nsCOMPtr<nsIPrefBranch> prefs;
375 0 : nsCOMPtr<nsIPrefService> pserve(do_GetService(NS_PREFSERVICE_CONTRACTID));
376 0 : if (pserve)
377 0 : pserve->GetBranch("", getter_AddRefs(prefs));
378 :
379 0 : if (prefs)
380 0 : prefs->SetBoolPref(PREF_CHECKDEFAULTBROWSER, aShouldCheck);
381 :
382 0 : return NS_OK;
383 : }
384 :
385 : static nsresult
386 0 : WriteImage(const nsCString& aPath, imgIContainer* aImage)
387 : {
388 : #ifndef MOZ_WIDGET_GTK2
389 : return NS_ERROR_NOT_AVAILABLE;
390 : #else
391 : nsCOMPtr<nsIImageToPixbuf> imgToPixbuf =
392 0 : do_GetService("@mozilla.org/widget/image-to-gdk-pixbuf;1");
393 0 : if (!imgToPixbuf)
394 0 : return NS_ERROR_NOT_AVAILABLE;
395 :
396 0 : GdkPixbuf* pixbuf = imgToPixbuf->ConvertImageToPixbuf(aImage);
397 0 : if (!pixbuf)
398 0 : return NS_ERROR_NOT_AVAILABLE;
399 :
400 0 : gboolean res = gdk_pixbuf_save(pixbuf, aPath.get(), "png", NULL, NULL);
401 :
402 0 : g_object_unref(pixbuf);
403 0 : return res ? NS_OK : NS_ERROR_FAILURE;
404 : #endif
405 : }
406 :
407 : NS_IMETHODIMP
408 0 : nsGNOMEShellService::SetDesktopBackground(nsIDOMElement* aElement,
409 : PRInt32 aPosition)
410 : {
411 : nsresult rv;
412 0 : nsCOMPtr<nsIImageLoadingContent> imageContent = do_QueryInterface(aElement, &rv);
413 0 : if (!imageContent) return rv;
414 :
415 : // get the image container
416 0 : nsCOMPtr<imgIRequest> request;
417 0 : rv = imageContent->GetRequest(nsIImageLoadingContent::CURRENT_REQUEST,
418 0 : getter_AddRefs(request));
419 0 : if (!request) return rv;
420 0 : nsCOMPtr<imgIContainer> container;
421 0 : rv = request->GetImage(getter_AddRefs(container));
422 0 : if (!container) return rv;
423 :
424 : // Set desktop wallpaper filling style
425 0 : nsCAutoString options;
426 0 : if (aPosition == BACKGROUND_TILE)
427 0 : options.Assign("wallpaper");
428 0 : else if (aPosition == BACKGROUND_STRETCH)
429 0 : options.Assign("stretched");
430 0 : else if (aPosition == BACKGROUND_FILL)
431 0 : options.Assign("zoom");
432 0 : else if (aPosition == BACKGROUND_FIT)
433 0 : options.Assign("scaled");
434 : else
435 0 : options.Assign("centered");
436 :
437 : // Write the background file to the home directory.
438 0 : nsCAutoString filePath(PR_GetEnv("HOME"));
439 :
440 : // get the product brand name from localized strings
441 0 : nsString brandName;
442 0 : nsCID bundleCID = NS_STRINGBUNDLESERVICE_CID;
443 0 : nsCOMPtr<nsIStringBundleService> bundleService(do_GetService(bundleCID));
444 0 : if (bundleService) {
445 0 : nsCOMPtr<nsIStringBundle> brandBundle;
446 0 : rv = bundleService->CreateBundle(BRAND_PROPERTIES,
447 0 : getter_AddRefs(brandBundle));
448 0 : if (NS_SUCCEEDED(rv) && brandBundle) {
449 0 : rv = brandBundle->GetStringFromName(NS_LITERAL_STRING("brandShortName").get(),
450 0 : getter_Copies(brandName));
451 0 : NS_ENSURE_SUCCESS(rv, rv);
452 : }
453 : }
454 :
455 : // build the file name
456 0 : filePath.Append('/');
457 0 : filePath.Append(NS_ConvertUTF16toUTF8(brandName));
458 0 : filePath.Append("_wallpaper.png");
459 :
460 : // write the image to a file in the home dir
461 0 : rv = WriteImage(filePath, container);
462 0 : NS_ENSURE_SUCCESS(rv, rv);
463 :
464 : // Try GSettings first. If we don't have GSettings or the right schema, fall back
465 : // to using GConf instead. Note that if GSettings works ok, the changes get
466 : // mirrored to GConf by the gsettings->gconf bridge in gnome-settings-daemon
467 : nsCOMPtr<nsIGSettingsService> gsettings =
468 0 : do_GetService(NS_GSETTINGSSERVICE_CONTRACTID);
469 0 : if (gsettings) {
470 0 : nsCOMPtr<nsIGSettingsCollection> background_settings;
471 0 : gsettings->GetCollectionForSchema(
472 0 : NS_LITERAL_CSTRING(kDesktopBGSchema), getter_AddRefs(background_settings));
473 0 : if (background_settings) {
474 0 : gchar *file_uri = g_filename_to_uri(filePath.get(), NULL, NULL);
475 0 : if (!file_uri)
476 0 : return NS_ERROR_FAILURE;
477 :
478 0 : background_settings->SetString(NS_LITERAL_CSTRING(kDesktopOptionGSKey),
479 0 : options);
480 :
481 0 : background_settings->SetString(NS_LITERAL_CSTRING(kDesktopImageGSKey),
482 0 : nsDependentCString(file_uri));
483 0 : g_free(file_uri);
484 0 : background_settings->SetBoolean(NS_LITERAL_CSTRING(kDesktopDrawBGGSKey),
485 0 : true);
486 0 : return rv;
487 : }
488 : }
489 :
490 : // if the file was written successfully, set it as the system wallpaper
491 0 : nsCOMPtr<nsIGConfService> gconf = do_GetService(NS_GCONFSERVICE_CONTRACTID);
492 :
493 0 : if (gconf) {
494 0 : gconf->SetString(NS_LITERAL_CSTRING(kDesktopOptionsKey), options);
495 :
496 : // Set the image to an empty string first to force a refresh
497 : // (since we could be writing a new image on top of an existing
498 : // Firefox_wallpaper.png and nautilus doesn't monitor the file for changes)
499 0 : gconf->SetString(NS_LITERAL_CSTRING(kDesktopImageKey),
500 0 : EmptyCString());
501 :
502 0 : gconf->SetString(NS_LITERAL_CSTRING(kDesktopImageKey), filePath);
503 0 : gconf->SetBool(NS_LITERAL_CSTRING(kDesktopDrawBGKey), true);
504 : }
505 :
506 0 : return rv;
507 : }
508 :
509 : #define COLOR_16_TO_8_BIT(_c) ((_c) >> 8)
510 : #define COLOR_8_TO_16_BIT(_c) ((_c) << 8 | (_c))
511 :
512 : NS_IMETHODIMP
513 18 : nsGNOMEShellService::GetDesktopBackgroundColor(PRUint32 *aColor)
514 : {
515 : nsCOMPtr<nsIGSettingsService> gsettings =
516 36 : do_GetService(NS_GSETTINGSSERVICE_CONTRACTID);
517 36 : nsCOMPtr<nsIGSettingsCollection> background_settings;
518 36 : nsCAutoString background;
519 :
520 18 : if (gsettings) {
521 0 : gsettings->GetCollectionForSchema(
522 0 : NS_LITERAL_CSTRING(kDesktopBGSchema), getter_AddRefs(background_settings));
523 0 : if (background_settings) {
524 0 : background_settings->GetString(NS_LITERAL_CSTRING(kDesktopColorGSKey),
525 0 : background);
526 : }
527 : }
528 :
529 18 : if (!background_settings) {
530 36 : nsCOMPtr<nsIGConfService> gconf = do_GetService(NS_GCONFSERVICE_CONTRACTID);
531 18 : if (gconf)
532 18 : gconf->GetString(NS_LITERAL_CSTRING(kDesktopColorKey), background);
533 : }
534 :
535 18 : if (background.IsEmpty()) {
536 0 : *aColor = 0;
537 0 : return NS_OK;
538 : }
539 :
540 : GdkColor color;
541 18 : gboolean success = gdk_color_parse(background.get(), &color);
542 :
543 18 : NS_ENSURE_TRUE(success, NS_ERROR_FAILURE);
544 :
545 : *aColor = COLOR_16_TO_8_BIT(color.red) << 16 |
546 : COLOR_16_TO_8_BIT(color.green) << 8 |
547 18 : COLOR_16_TO_8_BIT(color.blue);
548 18 : return NS_OK;
549 : }
550 :
551 : static void
552 6 : ColorToCString(PRUint32 aColor, nsCString& aResult)
553 : {
554 : // The #rrrrggggbbbb format is used to match gdk_color_to_string()
555 6 : char *buf = aResult.BeginWriting(13);
556 6 : if (!buf)
557 0 : return;
558 :
559 6 : PRUint16 red = COLOR_8_TO_16_BIT((aColor >> 16) & 0xff);
560 6 : PRUint16 green = COLOR_8_TO_16_BIT((aColor >> 8) & 0xff);
561 6 : PRUint16 blue = COLOR_8_TO_16_BIT(aColor & 0xff);
562 :
563 6 : PR_snprintf(buf, 14, "#%04x%04x%04x", red, green, blue);
564 : }
565 :
566 : NS_IMETHODIMP
567 6 : nsGNOMEShellService::SetDesktopBackgroundColor(PRUint32 aColor)
568 : {
569 6 : NS_ASSERTION(aColor <= 0xffffff, "aColor has extra bits");
570 12 : nsCAutoString colorString;
571 6 : ColorToCString(aColor, colorString);
572 :
573 : nsCOMPtr<nsIGSettingsService> gsettings =
574 12 : do_GetService(NS_GSETTINGSSERVICE_CONTRACTID);
575 6 : if (gsettings) {
576 0 : nsCOMPtr<nsIGSettingsCollection> background_settings;
577 0 : gsettings->GetCollectionForSchema(
578 0 : NS_LITERAL_CSTRING(kDesktopBGSchema), getter_AddRefs(background_settings));
579 0 : if (background_settings) {
580 0 : background_settings->SetString(NS_LITERAL_CSTRING(kDesktopColorGSKey),
581 0 : colorString);
582 0 : return NS_OK;
583 : }
584 : }
585 :
586 12 : nsCOMPtr<nsIGConfService> gconf = do_GetService(NS_GCONFSERVICE_CONTRACTID);
587 :
588 6 : if (gconf) {
589 6 : gconf->SetString(NS_LITERAL_CSTRING(kDesktopColorKey), colorString);
590 : }
591 :
592 6 : return NS_OK;
593 : }
594 :
595 : NS_IMETHODIMP
596 0 : nsGNOMEShellService::OpenApplication(PRInt32 aApplication)
597 : {
598 0 : nsCAutoString scheme;
599 0 : if (aApplication == APPLICATION_MAIL)
600 0 : scheme.Assign("mailto");
601 0 : else if (aApplication == APPLICATION_NEWS)
602 0 : scheme.Assign("news");
603 : else
604 0 : return NS_ERROR_NOT_AVAILABLE;
605 :
606 0 : nsCOMPtr<nsIGIOService> giovfs = do_GetService(NS_GIOSERVICE_CONTRACTID);
607 0 : if (giovfs) {
608 0 : nsCOMPtr<nsIGIOMimeApp> gioApp;
609 0 : giovfs->GetAppForURIScheme(scheme, getter_AddRefs(gioApp));
610 0 : if (gioApp)
611 0 : return gioApp->Launch(EmptyCString());
612 : }
613 :
614 0 : nsCOMPtr<nsIGConfService> gconf = do_GetService(NS_GCONFSERVICE_CONTRACTID);
615 0 : if (!gconf)
616 0 : return NS_ERROR_FAILURE;
617 :
618 : bool enabled;
619 0 : nsCAutoString appCommand;
620 0 : gconf->GetAppForProtocol(scheme, &enabled, appCommand);
621 :
622 0 : if (!enabled)
623 0 : return NS_ERROR_FAILURE;
624 :
625 : // XXX we don't currently handle launching a terminal window.
626 : // If the handler requires a terminal, bail.
627 : bool requiresTerminal;
628 0 : gconf->HandlerRequiresTerminal(scheme, &requiresTerminal);
629 0 : if (requiresTerminal)
630 0 : return NS_ERROR_FAILURE;
631 :
632 : // Perform shell argument expansion
633 : int argc;
634 : char **argv;
635 0 : if (!g_shell_parse_argv(appCommand.get(), &argc, &argv, NULL))
636 0 : return NS_ERROR_FAILURE;
637 :
638 0 : char **newArgv = new char*[argc + 1];
639 0 : int newArgc = 0;
640 :
641 : // Run through the list of arguments. Copy all of them to the new
642 : // argv except for %s, which we skip.
643 0 : for (int i = 0; i < argc; ++i) {
644 0 : if (strcmp(argv[i], "%s") != 0)
645 0 : newArgv[newArgc++] = argv[i];
646 : }
647 :
648 0 : newArgv[newArgc] = nsnull;
649 :
650 : gboolean err = g_spawn_async(NULL, newArgv, NULL, G_SPAWN_SEARCH_PATH,
651 0 : NULL, NULL, NULL, NULL);
652 :
653 0 : g_strfreev(argv);
654 0 : delete[] newArgv;
655 :
656 0 : return err ? NS_OK : NS_ERROR_FAILURE;
657 : }
658 :
659 : NS_IMETHODIMP
660 0 : nsGNOMEShellService::OpenApplicationWithURI(nsILocalFile* aApplication, const nsACString& aURI)
661 : {
662 : nsresult rv;
663 : nsCOMPtr<nsIProcess> process =
664 0 : do_CreateInstance("@mozilla.org/process/util;1", &rv);
665 0 : if (NS_FAILED(rv))
666 0 : return rv;
667 :
668 0 : rv = process->Init(aApplication);
669 0 : if (NS_FAILED(rv))
670 0 : return rv;
671 :
672 0 : const nsCString spec(aURI);
673 0 : const char* specStr = spec.get();
674 0 : return process->Run(false, &specStr, 1);
675 : }
676 :
677 : NS_IMETHODIMP
678 0 : nsGNOMEShellService::GetDefaultFeedReader(nsILocalFile** _retval)
679 : {
680 0 : return NS_ERROR_NOT_IMPLEMENTED;
681 : }
|