toolkit/system/gnome/nsGIOService.cpp

Sat, 03 Jan 2015 20:18:00 +0100

author
Michael Schloh von Bennewitz <michael@schloh.com>
date
Sat, 03 Jan 2015 20:18:00 +0100
branch
TOR_BUG_3246
changeset 7
129ffea94266
permissions
-rw-r--r--

Conditionally enable double key logic according to:
private browsing mode or privacy.thirdparty.isolate preference and
implement in GetCookieStringCommon and FindCookie where it counts...
With some reservations of how to convince FindCookie users to test
condition and pass a nullptr when disabling double key logic.

michael@0 1 /* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
michael@0 2 /* This Source Code Form is subject to the terms of the Mozilla Public
michael@0 3 * License, v. 2.0. If a copy of the MPL was not distributed with this
michael@0 4 * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
michael@0 5
michael@0 6 #include "nsGIOService.h"
michael@0 7 #include "nsStringAPI.h"
michael@0 8 #include "nsIURI.h"
michael@0 9 #include "nsTArray.h"
michael@0 10 #include "nsIStringEnumerator.h"
michael@0 11 #include "nsAutoPtr.h"
michael@0 12
michael@0 13 #include <gio/gio.h>
michael@0 14 #include <gtk/gtk.h>
michael@0 15 #ifdef MOZ_ENABLE_DBUS
michael@0 16 #include <dbus/dbus-glib.h>
michael@0 17 #include <dbus/dbus-glib-lowlevel.h>
michael@0 18 #endif
michael@0 19
michael@0 20
michael@0 21 char *
michael@0 22 get_content_type_from_mime_type(const char *mimeType)
michael@0 23 {
michael@0 24 GList* contentTypes = g_content_types_get_registered();
michael@0 25 GList* ct_ptr = contentTypes;
michael@0 26 char* foundContentType = nullptr;
michael@0 27
michael@0 28 while (ct_ptr) {
michael@0 29 char *mimeTypeFromContentType = g_content_type_get_mime_type((char*)ct_ptr->data);
michael@0 30 if (strcmp(mimeTypeFromContentType, mimeType) == 0) {
michael@0 31 foundContentType = g_strdup((char*)ct_ptr->data);
michael@0 32 g_free(mimeTypeFromContentType);
michael@0 33 break;
michael@0 34 }
michael@0 35 g_free(mimeTypeFromContentType);
michael@0 36 ct_ptr = ct_ptr->next;
michael@0 37 }
michael@0 38 g_list_foreach(contentTypes, (GFunc) g_free, nullptr);
michael@0 39 g_list_free(contentTypes);
michael@0 40 return foundContentType;
michael@0 41 }
michael@0 42
michael@0 43 class nsGIOMimeApp MOZ_FINAL : public nsIGIOMimeApp
michael@0 44 {
michael@0 45 public:
michael@0 46 NS_DECL_ISUPPORTS
michael@0 47 NS_DECL_NSIGIOMIMEAPP
michael@0 48
michael@0 49 nsGIOMimeApp(GAppInfo* aApp) : mApp(aApp) {}
michael@0 50 ~nsGIOMimeApp() { g_object_unref(mApp); }
michael@0 51
michael@0 52 private:
michael@0 53 GAppInfo *mApp;
michael@0 54 };
michael@0 55
michael@0 56 NS_IMPL_ISUPPORTS(nsGIOMimeApp, nsIGIOMimeApp)
michael@0 57
michael@0 58 NS_IMETHODIMP
michael@0 59 nsGIOMimeApp::GetId(nsACString& aId)
michael@0 60 {
michael@0 61 aId.Assign(g_app_info_get_id(mApp));
michael@0 62 return NS_OK;
michael@0 63 }
michael@0 64
michael@0 65 NS_IMETHODIMP
michael@0 66 nsGIOMimeApp::GetName(nsACString& aName)
michael@0 67 {
michael@0 68 aName.Assign(g_app_info_get_name(mApp));
michael@0 69 return NS_OK;
michael@0 70 }
michael@0 71
michael@0 72 NS_IMETHODIMP
michael@0 73 nsGIOMimeApp::GetCommand(nsACString& aCommand)
michael@0 74 {
michael@0 75 const char *cmd = g_app_info_get_commandline(mApp);
michael@0 76 if (!cmd)
michael@0 77 return NS_ERROR_FAILURE;
michael@0 78 aCommand.Assign(cmd);
michael@0 79 return NS_OK;
michael@0 80 }
michael@0 81
michael@0 82 NS_IMETHODIMP
michael@0 83 nsGIOMimeApp::GetExpectsURIs(int32_t* aExpects)
michael@0 84 {
michael@0 85 *aExpects = g_app_info_supports_uris(mApp);
michael@0 86 return NS_OK;
michael@0 87 }
michael@0 88
michael@0 89 NS_IMETHODIMP
michael@0 90 nsGIOMimeApp::Launch(const nsACString& aUri)
michael@0 91 {
michael@0 92 GList uris = { 0 };
michael@0 93 PromiseFlatCString flatUri(aUri);
michael@0 94 uris.data = const_cast<char*>(flatUri.get());
michael@0 95
michael@0 96 GError *error = nullptr;
michael@0 97 gboolean result = g_app_info_launch_uris(mApp, &uris, nullptr, &error);
michael@0 98
michael@0 99 if (!result) {
michael@0 100 g_warning("Cannot launch application: %s", error->message);
michael@0 101 g_error_free(error);
michael@0 102 return NS_ERROR_FAILURE;
michael@0 103 }
michael@0 104
michael@0 105 return NS_OK;
michael@0 106 }
michael@0 107
michael@0 108 class GIOUTF8StringEnumerator MOZ_FINAL : public nsIUTF8StringEnumerator
michael@0 109 {
michael@0 110 public:
michael@0 111 GIOUTF8StringEnumerator() : mIndex(0) { }
michael@0 112 ~GIOUTF8StringEnumerator() { }
michael@0 113
michael@0 114 NS_DECL_ISUPPORTS
michael@0 115 NS_DECL_NSIUTF8STRINGENUMERATOR
michael@0 116
michael@0 117 nsTArray<nsCString> mStrings;
michael@0 118 uint32_t mIndex;
michael@0 119 };
michael@0 120
michael@0 121 NS_IMPL_ISUPPORTS(GIOUTF8StringEnumerator, nsIUTF8StringEnumerator)
michael@0 122
michael@0 123 NS_IMETHODIMP
michael@0 124 GIOUTF8StringEnumerator::HasMore(bool* aResult)
michael@0 125 {
michael@0 126 *aResult = mIndex < mStrings.Length();
michael@0 127 return NS_OK;
michael@0 128 }
michael@0 129
michael@0 130 NS_IMETHODIMP
michael@0 131 GIOUTF8StringEnumerator::GetNext(nsACString& aResult)
michael@0 132 {
michael@0 133 if (mIndex >= mStrings.Length())
michael@0 134 return NS_ERROR_UNEXPECTED;
michael@0 135
michael@0 136 aResult.Assign(mStrings[mIndex]);
michael@0 137 ++mIndex;
michael@0 138 return NS_OK;
michael@0 139 }
michael@0 140
michael@0 141 NS_IMETHODIMP
michael@0 142 nsGIOMimeApp::GetSupportedURISchemes(nsIUTF8StringEnumerator** aSchemes)
michael@0 143 {
michael@0 144 *aSchemes = nullptr;
michael@0 145
michael@0 146 nsRefPtr<GIOUTF8StringEnumerator> array = new GIOUTF8StringEnumerator();
michael@0 147 NS_ENSURE_TRUE(array, NS_ERROR_OUT_OF_MEMORY);
michael@0 148
michael@0 149 GVfs *gvfs = g_vfs_get_default();
michael@0 150
michael@0 151 if (!gvfs) {
michael@0 152 g_warning("Cannot get GVfs object.");
michael@0 153 return NS_ERROR_OUT_OF_MEMORY;
michael@0 154 }
michael@0 155
michael@0 156 const gchar* const * uri_schemes = g_vfs_get_supported_uri_schemes(gvfs);
michael@0 157
michael@0 158 while (*uri_schemes != nullptr) {
michael@0 159 if (!array->mStrings.AppendElement(*uri_schemes)) {
michael@0 160 return NS_ERROR_OUT_OF_MEMORY;
michael@0 161 }
michael@0 162 uri_schemes++;
michael@0 163 }
michael@0 164
michael@0 165 NS_ADDREF(*aSchemes = array);
michael@0 166 return NS_OK;
michael@0 167 }
michael@0 168
michael@0 169 NS_IMETHODIMP
michael@0 170 nsGIOMimeApp::SetAsDefaultForMimeType(nsACString const& aMimeType)
michael@0 171 {
michael@0 172 char *content_type =
michael@0 173 get_content_type_from_mime_type(PromiseFlatCString(aMimeType).get());
michael@0 174 if (!content_type)
michael@0 175 return NS_ERROR_FAILURE;
michael@0 176 GError *error = nullptr;
michael@0 177 g_app_info_set_as_default_for_type(mApp,
michael@0 178 content_type,
michael@0 179 &error);
michael@0 180 if (error) {
michael@0 181 g_warning("Cannot set application as default for MIME type (%s): %s",
michael@0 182 PromiseFlatCString(aMimeType).get(),
michael@0 183 error->message);
michael@0 184 g_error_free(error);
michael@0 185 g_free(content_type);
michael@0 186 return NS_ERROR_FAILURE;
michael@0 187 }
michael@0 188
michael@0 189 g_free(content_type);
michael@0 190 return NS_OK;
michael@0 191 }
michael@0 192 /**
michael@0 193 * Set default application for files with given extensions
michael@0 194 * @param fileExts string of space separated extensions
michael@0 195 * @return NS_OK when application was set as default for given extensions,
michael@0 196 * NS_ERROR_FAILURE otherwise
michael@0 197 */
michael@0 198 NS_IMETHODIMP
michael@0 199 nsGIOMimeApp::SetAsDefaultForFileExtensions(nsACString const& fileExts)
michael@0 200 {
michael@0 201 GError *error = nullptr;
michael@0 202 char *extensions = g_strdup(PromiseFlatCString(fileExts).get());
michael@0 203 char *ext_pos = extensions;
michael@0 204 char *space_pos;
michael@0 205
michael@0 206 while ( (space_pos = strchr(ext_pos, ' ')) || (*ext_pos != '\0') ) {
michael@0 207 if (space_pos) {
michael@0 208 *space_pos = '\0';
michael@0 209 }
michael@0 210 g_app_info_set_as_default_for_extension(mApp, ext_pos, &error);
michael@0 211 if (error) {
michael@0 212 g_warning("Cannot set application as default for extension (%s): %s",
michael@0 213 ext_pos,
michael@0 214 error->message);
michael@0 215 g_error_free(error);
michael@0 216 g_free(extensions);
michael@0 217 return NS_ERROR_FAILURE;
michael@0 218 }
michael@0 219 if (space_pos) {
michael@0 220 ext_pos = space_pos + 1;
michael@0 221 } else {
michael@0 222 *ext_pos = '\0';
michael@0 223 }
michael@0 224 }
michael@0 225 g_free(extensions);
michael@0 226 return NS_OK;
michael@0 227 }
michael@0 228
michael@0 229 /**
michael@0 230 * Set default application for URI's of a particular scheme
michael@0 231 * @param aURIScheme string containing the URI scheme
michael@0 232 * @return NS_OK when application was set as default for URI scheme,
michael@0 233 * NS_ERROR_FAILURE otherwise
michael@0 234 */
michael@0 235 NS_IMETHODIMP
michael@0 236 nsGIOMimeApp::SetAsDefaultForURIScheme(nsACString const& aURIScheme)
michael@0 237 {
michael@0 238 GError *error = nullptr;
michael@0 239 nsAutoCString contentType("x-scheme-handler/");
michael@0 240 contentType.Append(aURIScheme);
michael@0 241
michael@0 242 g_app_info_set_as_default_for_type(mApp,
michael@0 243 contentType.get(),
michael@0 244 &error);
michael@0 245 if (error) {
michael@0 246 g_warning("Cannot set application as default for URI scheme (%s): %s",
michael@0 247 PromiseFlatCString(aURIScheme).get(),
michael@0 248 error->message);
michael@0 249 g_error_free(error);
michael@0 250 return NS_ERROR_FAILURE;
michael@0 251 }
michael@0 252
michael@0 253 return NS_OK;
michael@0 254 }
michael@0 255
michael@0 256 NS_IMPL_ISUPPORTS(nsGIOService, nsIGIOService)
michael@0 257
michael@0 258 NS_IMETHODIMP
michael@0 259 nsGIOService::GetMimeTypeFromExtension(const nsACString& aExtension,
michael@0 260 nsACString& aMimeType)
michael@0 261 {
michael@0 262 nsAutoCString fileExtToUse("file.");
michael@0 263 fileExtToUse.Append(aExtension);
michael@0 264
michael@0 265 gboolean result_uncertain;
michael@0 266 char *content_type = g_content_type_guess(fileExtToUse.get(),
michael@0 267 nullptr,
michael@0 268 0,
michael@0 269 &result_uncertain);
michael@0 270 if (!content_type)
michael@0 271 return NS_ERROR_FAILURE;
michael@0 272
michael@0 273 char *mime_type = g_content_type_get_mime_type(content_type);
michael@0 274 if (!mime_type) {
michael@0 275 g_free(content_type);
michael@0 276 return NS_ERROR_FAILURE;
michael@0 277 }
michael@0 278
michael@0 279 aMimeType.Assign(mime_type);
michael@0 280
michael@0 281 g_free(mime_type);
michael@0 282 g_free(content_type);
michael@0 283
michael@0 284 return NS_OK;
michael@0 285 }
michael@0 286 // used in nsGNOMERegistry
michael@0 287 // -----------------------------------------------------------------------------
michael@0 288 NS_IMETHODIMP
michael@0 289 nsGIOService::GetAppForURIScheme(const nsACString& aURIScheme,
michael@0 290 nsIGIOMimeApp** aApp)
michael@0 291 {
michael@0 292 *aApp = nullptr;
michael@0 293
michael@0 294 GAppInfo *app_info = g_app_info_get_default_for_uri_scheme(
michael@0 295 PromiseFlatCString(aURIScheme).get());
michael@0 296 if (app_info) {
michael@0 297 nsGIOMimeApp *mozApp = new nsGIOMimeApp(app_info);
michael@0 298 NS_ADDREF(*aApp = mozApp);
michael@0 299 } else {
michael@0 300 return NS_ERROR_FAILURE;
michael@0 301 }
michael@0 302 return NS_OK;
michael@0 303 }
michael@0 304
michael@0 305 NS_IMETHODIMP
michael@0 306 nsGIOService::GetAppForMimeType(const nsACString& aMimeType,
michael@0 307 nsIGIOMimeApp** aApp)
michael@0 308 {
michael@0 309 *aApp = nullptr;
michael@0 310 char *content_type =
michael@0 311 get_content_type_from_mime_type(PromiseFlatCString(aMimeType).get());
michael@0 312 if (!content_type)
michael@0 313 return NS_ERROR_FAILURE;
michael@0 314
michael@0 315 GAppInfo *app_info = g_app_info_get_default_for_type(content_type, false);
michael@0 316 if (app_info) {
michael@0 317 nsGIOMimeApp *mozApp = new nsGIOMimeApp(app_info);
michael@0 318 NS_ENSURE_TRUE(mozApp, NS_ERROR_OUT_OF_MEMORY);
michael@0 319 NS_ADDREF(*aApp = mozApp);
michael@0 320 } else {
michael@0 321 g_free(content_type);
michael@0 322 return NS_ERROR_FAILURE;
michael@0 323 }
michael@0 324 g_free(content_type);
michael@0 325 return NS_OK;
michael@0 326 }
michael@0 327
michael@0 328 NS_IMETHODIMP
michael@0 329 nsGIOService::GetDescriptionForMimeType(const nsACString& aMimeType,
michael@0 330 nsACString& aDescription)
michael@0 331 {
michael@0 332 char *content_type =
michael@0 333 get_content_type_from_mime_type(PromiseFlatCString(aMimeType).get());
michael@0 334 if (!content_type)
michael@0 335 return NS_ERROR_FAILURE;
michael@0 336
michael@0 337 char *desc = g_content_type_get_description(content_type);
michael@0 338 if (!desc) {
michael@0 339 g_free(content_type);
michael@0 340 return NS_ERROR_FAILURE;
michael@0 341 }
michael@0 342
michael@0 343 aDescription.Assign(desc);
michael@0 344 g_free(content_type);
michael@0 345 g_free(desc);
michael@0 346 return NS_OK;
michael@0 347 }
michael@0 348
michael@0 349 NS_IMETHODIMP
michael@0 350 nsGIOService::ShowURI(nsIURI* aURI)
michael@0 351 {
michael@0 352 nsAutoCString spec;
michael@0 353 aURI->GetSpec(spec);
michael@0 354 GError *error = nullptr;
michael@0 355 if (!g_app_info_launch_default_for_uri(spec.get(), nullptr, &error)) {
michael@0 356 g_warning("Could not launch default application for URI: %s", error->message);
michael@0 357 g_error_free(error);
michael@0 358 return NS_ERROR_FAILURE;
michael@0 359 }
michael@0 360 return NS_OK;
michael@0 361 }
michael@0 362
michael@0 363 NS_IMETHODIMP
michael@0 364 nsGIOService::ShowURIForInput(const nsACString& aUri)
michael@0 365 {
michael@0 366 GFile *file = g_file_new_for_commandline_arg(PromiseFlatCString(aUri).get());
michael@0 367 char* spec = g_file_get_uri(file);
michael@0 368 nsresult rv = NS_ERROR_FAILURE;
michael@0 369 GError *error = nullptr;
michael@0 370
michael@0 371 g_app_info_launch_default_for_uri(spec, nullptr, &error);
michael@0 372 if (error) {
michael@0 373 g_warning("Cannot launch default application: %s", error->message);
michael@0 374 g_error_free(error);
michael@0 375 } else {
michael@0 376 rv = NS_OK;
michael@0 377 }
michael@0 378 g_object_unref(file);
michael@0 379 g_free(spec);
michael@0 380
michael@0 381 return rv;
michael@0 382 }
michael@0 383
michael@0 384 NS_IMETHODIMP
michael@0 385 nsGIOService::OrgFreedesktopFileManager1ShowItems(const nsACString& aPath)
michael@0 386 {
michael@0 387 #ifndef MOZ_ENABLE_DBUS
michael@0 388 return NS_ERROR_FAILURE;
michael@0 389 #else
michael@0 390 GError* error = nullptr;
michael@0 391 static bool org_freedesktop_FileManager1_exists = true;
michael@0 392
michael@0 393 if (!org_freedesktop_FileManager1_exists) {
michael@0 394 return NS_ERROR_NOT_AVAILABLE;
michael@0 395 }
michael@0 396
michael@0 397 DBusGConnection* dbusGConnection = dbus_g_bus_get(DBUS_BUS_SESSION, &error);
michael@0 398
michael@0 399 if (!dbusGConnection) {
michael@0 400 if (error) {
michael@0 401 g_printerr("Failed to open connection to session bus: %s\n", error->message);
michael@0 402 g_error_free(error);
michael@0 403 }
michael@0 404 return NS_ERROR_FAILURE;
michael@0 405 }
michael@0 406
michael@0 407 char *uri = g_filename_to_uri(PromiseFlatCString(aPath).get(), nullptr, nullptr);
michael@0 408 if (uri == nullptr) {
michael@0 409 return NS_ERROR_FAILURE;
michael@0 410 }
michael@0 411
michael@0 412 DBusConnection* dbusConnection = dbus_g_connection_get_connection(dbusGConnection);
michael@0 413 // Make sure we do not exit the entire program if DBus connection get lost.
michael@0 414 dbus_connection_set_exit_on_disconnect(dbusConnection, false);
michael@0 415
michael@0 416 DBusGProxy* dbusGProxy = dbus_g_proxy_new_for_name(dbusGConnection,
michael@0 417 "org.freedesktop.FileManager1",
michael@0 418 "/org/freedesktop/FileManager1",
michael@0 419 "org.freedesktop.FileManager1");
michael@0 420
michael@0 421 const char *uris[2] = { uri, nullptr };
michael@0 422 gboolean rv_dbus_call = dbus_g_proxy_call (dbusGProxy, "ShowItems", nullptr, G_TYPE_STRV, uris,
michael@0 423 G_TYPE_STRING, "", G_TYPE_INVALID, G_TYPE_INVALID);
michael@0 424
michael@0 425 g_object_unref(dbusGProxy);
michael@0 426 dbus_g_connection_unref(dbusGConnection);
michael@0 427 g_free(uri);
michael@0 428
michael@0 429 if (!rv_dbus_call) {
michael@0 430 org_freedesktop_FileManager1_exists = false;
michael@0 431 return NS_ERROR_NOT_AVAILABLE;
michael@0 432 }
michael@0 433
michael@0 434 return NS_OK;
michael@0 435 #endif
michael@0 436 }
michael@0 437
michael@0 438 /**
michael@0 439 * Create or find already existing application info for specified command
michael@0 440 * and application name.
michael@0 441 * @param cmd command to execute
michael@0 442 * @param appName application name
michael@0 443 * @param appInfo location where created GAppInfo is stored
michael@0 444 * @return NS_OK when object is created, NS_ERROR_FAILURE otherwise.
michael@0 445 */
michael@0 446 NS_IMETHODIMP
michael@0 447 nsGIOService::CreateAppFromCommand(nsACString const& cmd,
michael@0 448 nsACString const& appName,
michael@0 449 nsIGIOMimeApp** appInfo)
michael@0 450 {
michael@0 451 GError *error = nullptr;
michael@0 452 *appInfo = nullptr;
michael@0 453
michael@0 454 GAppInfo *app_info = nullptr, *app_info_from_list = nullptr;
michael@0 455 GList *apps = g_app_info_get_all();
michael@0 456 GList *apps_p = apps;
michael@0 457
michael@0 458 // Try to find relevant and existing GAppInfo in all installed application
michael@0 459 // We do this by comparing each GAppInfo's executable with out own
michael@0 460 while (apps_p) {
michael@0 461 app_info_from_list = (GAppInfo*) apps_p->data;
michael@0 462 if (!app_info) {
michael@0 463 // If the executable is not absolute, get it's full path
michael@0 464 char *executable = g_find_program_in_path(g_app_info_get_executable(app_info_from_list));
michael@0 465
michael@0 466 if (executable && strcmp(executable, PromiseFlatCString(cmd).get()) == 0) {
michael@0 467 g_object_ref (app_info_from_list);
michael@0 468 app_info = app_info_from_list;
michael@0 469 }
michael@0 470 g_free(executable);
michael@0 471 }
michael@0 472
michael@0 473 g_object_unref(app_info_from_list);
michael@0 474 apps_p = apps_p->next;
michael@0 475 }
michael@0 476 g_list_free(apps);
michael@0 477
michael@0 478 if (!app_info) {
michael@0 479 app_info = g_app_info_create_from_commandline(PromiseFlatCString(cmd).get(),
michael@0 480 PromiseFlatCString(appName).get(),
michael@0 481 G_APP_INFO_CREATE_SUPPORTS_URIS,
michael@0 482 &error);
michael@0 483 }
michael@0 484
michael@0 485 if (!app_info) {
michael@0 486 g_warning("Cannot create application info from command: %s", error->message);
michael@0 487 g_error_free(error);
michael@0 488 return NS_ERROR_FAILURE;
michael@0 489 }
michael@0 490 nsGIOMimeApp *mozApp = new nsGIOMimeApp(app_info);
michael@0 491 NS_ENSURE_TRUE(mozApp, NS_ERROR_OUT_OF_MEMORY);
michael@0 492 NS_ADDREF(*appInfo = mozApp);
michael@0 493 return NS_OK;
michael@0 494 }

mercurial