extensions/pref/autoconfig/src/nsAutoConfig.cpp

Wed, 31 Dec 2014 06:09:35 +0100

author
Michael Schloh von Bennewitz <michael@schloh.com>
date
Wed, 31 Dec 2014 06:09:35 +0100
changeset 0
6474c204b198
permissions
-rw-r--r--

Cloned upstream origin tor-browser at tor-browser-31.3.0esr-4.5-1-build1
revision ID fc1c9ff7c1b2defdbc039f12214767608f46423f for hacking purpose.

michael@0 1 /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
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 #ifdef MOZ_LOGGING
michael@0 7 // sorry, this has to be before the pre-compiled header
michael@0 8 #define FORCE_PR_LOG /* Allow logging in the release build */
michael@0 9 #endif
michael@0 10 #include "nsAutoConfig.h"
michael@0 11 #include "nsIURI.h"
michael@0 12 #include "nsIHttpChannel.h"
michael@0 13 #include "nsIFileStreams.h"
michael@0 14 #include "nsThreadUtils.h"
michael@0 15 #include "nsAppDirectoryServiceDefs.h"
michael@0 16 #include "prmem.h"
michael@0 17 #include "nsIObserverService.h"
michael@0 18 #include "nsLiteralString.h"
michael@0 19 #include "nsIPromptService.h"
michael@0 20 #include "nsIServiceManager.h"
michael@0 21 #include "nsIStringBundle.h"
michael@0 22 #include "nsCRT.h"
michael@0 23 #include "nspr.h"
michael@0 24 #include <algorithm>
michael@0 25
michael@0 26 PRLogModuleInfo *MCD;
michael@0 27
michael@0 28 extern nsresult EvaluateAdminConfigScript(const char *js_buffer, size_t length,
michael@0 29 const char *filename,
michael@0 30 bool bGlobalContext,
michael@0 31 bool bCallbacks,
michael@0 32 bool skipFirstLine);
michael@0 33
michael@0 34 // nsISupports Implementation
michael@0 35
michael@0 36 NS_IMPL_ISUPPORTS(nsAutoConfig, nsIAutoConfig, nsITimerCallback, nsIStreamListener, nsIObserver, nsIRequestObserver, nsISupportsWeakReference)
michael@0 37
michael@0 38 nsAutoConfig::nsAutoConfig()
michael@0 39 {
michael@0 40 }
michael@0 41
michael@0 42 nsresult nsAutoConfig::Init()
michael@0 43 {
michael@0 44 // member initializers and constructor code
michael@0 45
michael@0 46 nsresult rv;
michael@0 47 mLoaded = false;
michael@0 48
michael@0 49 // Registering the object as an observer to the profile-after-change topic
michael@0 50 nsCOMPtr<nsIObserverService> observerService =
michael@0 51 do_GetService("@mozilla.org/observer-service;1", &rv);
michael@0 52 if (NS_FAILED(rv))
michael@0 53 return rv;
michael@0 54
michael@0 55 rv = observerService->AddObserver(this,"profile-after-change", true);
michael@0 56
michael@0 57 return rv;
michael@0 58 }
michael@0 59
michael@0 60 nsAutoConfig::~nsAutoConfig()
michael@0 61 {
michael@0 62 }
michael@0 63
michael@0 64 // attribute string configURL
michael@0 65 NS_IMETHODIMP nsAutoConfig::GetConfigURL(char **aConfigURL)
michael@0 66 {
michael@0 67 if (!aConfigURL)
michael@0 68 return NS_ERROR_NULL_POINTER;
michael@0 69
michael@0 70 if (mConfigURL.IsEmpty()) {
michael@0 71 *aConfigURL = nullptr;
michael@0 72 return NS_OK;
michael@0 73 }
michael@0 74
michael@0 75 *aConfigURL = ToNewCString(mConfigURL);
michael@0 76 if (!*aConfigURL)
michael@0 77 return NS_ERROR_OUT_OF_MEMORY;
michael@0 78 return NS_OK;
michael@0 79 }
michael@0 80 NS_IMETHODIMP nsAutoConfig::SetConfigURL(const char *aConfigURL)
michael@0 81 {
michael@0 82 if (!aConfigURL)
michael@0 83 return NS_ERROR_NULL_POINTER;
michael@0 84 mConfigURL.Assign(aConfigURL);
michael@0 85 return NS_OK;
michael@0 86 }
michael@0 87
michael@0 88 NS_IMETHODIMP
michael@0 89 nsAutoConfig::OnStartRequest(nsIRequest *request, nsISupports *context)
michael@0 90 {
michael@0 91 return NS_OK;
michael@0 92 }
michael@0 93
michael@0 94
michael@0 95 NS_IMETHODIMP
michael@0 96 nsAutoConfig::OnDataAvailable(nsIRequest *request,
michael@0 97 nsISupports *context,
michael@0 98 nsIInputStream *aIStream,
michael@0 99 uint64_t aSourceOffset,
michael@0 100 uint32_t aLength)
michael@0 101 {
michael@0 102 uint32_t amt, size;
michael@0 103 nsresult rv;
michael@0 104 char buf[1024];
michael@0 105
michael@0 106 while (aLength) {
michael@0 107 size = std::min<size_t>(aLength, sizeof(buf));
michael@0 108 rv = aIStream->Read(buf, size, &amt);
michael@0 109 if (NS_FAILED(rv))
michael@0 110 return rv;
michael@0 111 mBuf.Append(buf, amt);
michael@0 112 aLength -= amt;
michael@0 113 }
michael@0 114 return NS_OK;
michael@0 115 }
michael@0 116
michael@0 117
michael@0 118 NS_IMETHODIMP
michael@0 119 nsAutoConfig::OnStopRequest(nsIRequest *request, nsISupports *context,
michael@0 120 nsresult aStatus)
michael@0 121 {
michael@0 122 nsresult rv;
michael@0 123
michael@0 124 // If the request is failed, go read the failover.jsc file
michael@0 125 if (NS_FAILED(aStatus)) {
michael@0 126 PR_LOG(MCD, PR_LOG_DEBUG, ("mcd request failed with status %x\n", aStatus));
michael@0 127 return readOfflineFile();
michael@0 128 }
michael@0 129
michael@0 130 // Checking for the http response, if failure go read the failover file.
michael@0 131 nsCOMPtr<nsIHttpChannel> pHTTPCon(do_QueryInterface(request));
michael@0 132 if (pHTTPCon) {
michael@0 133 uint32_t httpStatus;
michael@0 134 pHTTPCon->GetResponseStatus(&httpStatus);
michael@0 135 if (httpStatus != 200)
michael@0 136 {
michael@0 137 PR_LOG(MCD, PR_LOG_DEBUG, ("mcd http request failed with status %x\n", httpStatus));
michael@0 138 return readOfflineFile();
michael@0 139 }
michael@0 140 }
michael@0 141
michael@0 142 // Send the autoconfig.jsc to javascript engine.
michael@0 143
michael@0 144 rv = EvaluateAdminConfigScript(mBuf.get(), mBuf.Length(),
michael@0 145 nullptr, false,true, false);
michael@0 146 if (NS_SUCCEEDED(rv)) {
michael@0 147
michael@0 148 // Write the autoconfig.jsc to failover.jsc (cached copy)
michael@0 149 rv = writeFailoverFile();
michael@0 150
michael@0 151 if (NS_FAILED(rv))
michael@0 152 NS_WARNING("Error writing failover.jsc file");
michael@0 153
michael@0 154 // Releasing the lock to allow the main thread to start execution
michael@0 155 mLoaded = true;
michael@0 156
michael@0 157 return NS_OK;
michael@0 158 }
michael@0 159 // there is an error in parsing of the autoconfig file.
michael@0 160 NS_WARNING("Error reading autoconfig.jsc from the network, reading the offline version");
michael@0 161 return readOfflineFile();
michael@0 162 }
michael@0 163
michael@0 164 // Notify method as a TimerCallBack function
michael@0 165 NS_IMETHODIMP nsAutoConfig::Notify(nsITimer *timer)
michael@0 166 {
michael@0 167 downloadAutoConfig();
michael@0 168 return NS_OK;
michael@0 169 }
michael@0 170
michael@0 171 /* Observe() is called twice: once at the instantiation time and other
michael@0 172 after the profile is set. It doesn't do anything but return NS_OK during the
michael@0 173 creation time. Second time it calls downloadAutoConfig().
michael@0 174 */
michael@0 175
michael@0 176 NS_IMETHODIMP nsAutoConfig::Observe(nsISupports *aSubject,
michael@0 177 const char *aTopic,
michael@0 178 const char16_t *someData)
michael@0 179 {
michael@0 180 nsresult rv = NS_OK;
michael@0 181 if (!nsCRT::strcmp(aTopic, "profile-after-change")) {
michael@0 182
michael@0 183 // We will be calling downloadAutoConfig even if there is no profile
michael@0 184 // name. Nothing will be passed as a parameter to the URL and the
michael@0 185 // default case will be picked up by the script.
michael@0 186
michael@0 187 rv = downloadAutoConfig();
michael@0 188
michael@0 189 }
michael@0 190
michael@0 191 return rv;
michael@0 192 }
michael@0 193
michael@0 194 nsresult nsAutoConfig::downloadAutoConfig()
michael@0 195 {
michael@0 196 nsresult rv;
michael@0 197 nsAutoCString emailAddr;
michael@0 198 nsXPIDLCString urlName;
michael@0 199 static bool firstTime = true;
michael@0 200
michael@0 201 if (mConfigURL.IsEmpty()) {
michael@0 202 PR_LOG(MCD, PR_LOG_DEBUG, ("global config url is empty - did you set autoadmin.global_config_url?\n"));
michael@0 203 NS_WARNING("AutoConfig called without global_config_url");
michael@0 204 return NS_OK;
michael@0 205 }
michael@0 206
michael@0 207 // If there is an email address appended as an argument to the ConfigURL
michael@0 208 // in the previous read, we need to remove it when timer kicks in and
michael@0 209 // downloads the autoconfig file again.
michael@0 210 // If necessary, the email address will be added again as an argument.
michael@0 211 int32_t index = mConfigURL.RFindChar((char16_t)'?');
michael@0 212 if (index != -1)
michael@0 213 mConfigURL.Truncate(index);
michael@0 214
michael@0 215 // Clean up the previous read, the new read is going to use the same buffer
michael@0 216 if (!mBuf.IsEmpty())
michael@0 217 mBuf.Truncate(0);
michael@0 218
michael@0 219 // Get the preferences branch and save it to the member variable
michael@0 220 if (!mPrefBranch) {
michael@0 221 nsCOMPtr<nsIPrefService> prefs =
michael@0 222 do_GetService(NS_PREFSERVICE_CONTRACTID, &rv);
michael@0 223 if (NS_FAILED(rv))
michael@0 224 return rv;
michael@0 225
michael@0 226 rv = prefs->GetBranch(nullptr,getter_AddRefs(mPrefBranch));
michael@0 227 if (NS_FAILED(rv))
michael@0 228 return rv;
michael@0 229 }
michael@0 230
michael@0 231 // Check to see if the network is online/offline
michael@0 232 nsCOMPtr<nsIIOService> ios = do_GetService(NS_IOSERVICE_CONTRACTID, &rv);
michael@0 233 if (NS_FAILED(rv))
michael@0 234 return rv;
michael@0 235
michael@0 236 bool offline;
michael@0 237 rv = ios->GetOffline(&offline);
michael@0 238 if (NS_FAILED(rv))
michael@0 239 return rv;
michael@0 240
michael@0 241 if (offline) {
michael@0 242 bool offlineFailover;
michael@0 243 rv = mPrefBranch->GetBoolPref("autoadmin.offline_failover",
michael@0 244 &offlineFailover);
michael@0 245 // Read the failover.jsc if the network is offline and the pref says so
michael@0 246 if (NS_SUCCEEDED(rv) && offlineFailover)
michael@0 247 return readOfflineFile();
michael@0 248 }
michael@0 249
michael@0 250 /* Append user's identity at the end of the URL if the pref says so.
michael@0 251 First we are checking for the user's email address but if it is not
michael@0 252 available in the case where the client is used without messenger, user's
michael@0 253 profile name will be used as an unique identifier
michael@0 254 */
michael@0 255 bool appendMail;
michael@0 256 rv = mPrefBranch->GetBoolPref("autoadmin.append_emailaddr", &appendMail);
michael@0 257 if (NS_SUCCEEDED(rv) && appendMail) {
michael@0 258 rv = getEmailAddr(emailAddr);
michael@0 259 if (NS_SUCCEEDED(rv) && emailAddr.get()) {
michael@0 260 /* Adding the unique identifier at the end of autoconfig URL.
michael@0 261 In this case the autoconfig URL is a script and
michael@0 262 emailAddr as passed as an argument
michael@0 263 */
michael@0 264 mConfigURL.Append("?");
michael@0 265 mConfigURL.Append(emailAddr);
michael@0 266 }
michael@0 267 }
michael@0 268
michael@0 269 // create a new url
michael@0 270 nsCOMPtr<nsIURI> url;
michael@0 271 nsCOMPtr<nsIChannel> channel;
michael@0 272
michael@0 273 rv = NS_NewURI(getter_AddRefs(url), mConfigURL.get(), nullptr, nullptr);
michael@0 274 if (NS_FAILED(rv))
michael@0 275 {
michael@0 276 PR_LOG(MCD, PR_LOG_DEBUG, ("failed to create URL - is autoadmin.global_config_url valid? - %s\n", mConfigURL.get()));
michael@0 277 return rv;
michael@0 278 }
michael@0 279
michael@0 280 PR_LOG(MCD, PR_LOG_DEBUG, ("running MCD url %s\n", mConfigURL.get()));
michael@0 281 // open a channel for the url
michael@0 282 rv = NS_NewChannel(getter_AddRefs(channel),url, nullptr, nullptr, nullptr, nsIRequest::INHIBIT_PERSISTENT_CACHING | nsIRequest::LOAD_BYPASS_CACHE);
michael@0 283 if (NS_FAILED(rv))
michael@0 284 return rv;
michael@0 285
michael@0 286 rv = channel->AsyncOpen(this, nullptr);
michael@0 287 if (NS_FAILED(rv)) {
michael@0 288 readOfflineFile();
michael@0 289 return rv;
michael@0 290 }
michael@0 291
michael@0 292 // Set a repeating timer if the pref is set.
michael@0 293 // This is to be done only once.
michael@0 294 // Also We are having the event queue processing only for the startup
michael@0 295 // It is not needed with the repeating timer.
michael@0 296 if (firstTime) {
michael@0 297 firstTime = false;
michael@0 298
michael@0 299 // Getting the current thread. If we start an AsyncOpen, the thread
michael@0 300 // needs to wait before the reading of autoconfig is done
michael@0 301
michael@0 302 nsCOMPtr<nsIThread> thread = do_GetCurrentThread();
michael@0 303 NS_ENSURE_STATE(thread);
michael@0 304
michael@0 305 /* process events until we're finished. AutoConfig.jsc reading needs
michael@0 306 to be finished before the browser starts loading up
michael@0 307 We are waiting for the mLoaded which will be set through
michael@0 308 onStopRequest or readOfflineFile methods
michael@0 309 There is a possibility of deadlock so we need to make sure
michael@0 310 that mLoaded will be set to true in any case (success/failure)
michael@0 311 */
michael@0 312
michael@0 313 while (!mLoaded)
michael@0 314 NS_ENSURE_STATE(NS_ProcessNextEvent(thread));
michael@0 315
michael@0 316 int32_t minutes;
michael@0 317 rv = mPrefBranch->GetIntPref("autoadmin.refresh_interval",
michael@0 318 &minutes);
michael@0 319 if (NS_SUCCEEDED(rv) && minutes > 0) {
michael@0 320 // Create a new timer and pass this nsAutoConfig
michael@0 321 // object as a timer callback.
michael@0 322 mTimer = do_CreateInstance("@mozilla.org/timer;1",&rv);
michael@0 323 if (NS_FAILED(rv))
michael@0 324 return rv;
michael@0 325 rv = mTimer->InitWithCallback(this, minutes * 60 * 1000,
michael@0 326 nsITimer::TYPE_REPEATING_SLACK);
michael@0 327 if (NS_FAILED(rv))
michael@0 328 return rv;
michael@0 329 }
michael@0 330 } //first_time
michael@0 331
michael@0 332 return NS_OK;
michael@0 333 } // nsPref::downloadAutoConfig()
michael@0 334
michael@0 335
michael@0 336
michael@0 337 nsresult nsAutoConfig::readOfflineFile()
michael@0 338 {
michael@0 339 nsresult rv;
michael@0 340
michael@0 341 /* Releasing the lock to allow main thread to start
michael@0 342 execution. At this point we do not need to stall
michael@0 343 the thread since all network activities are done.
michael@0 344 */
michael@0 345 mLoaded = true;
michael@0 346
michael@0 347 bool failCache;
michael@0 348 rv = mPrefBranch->GetBoolPref("autoadmin.failover_to_cached", &failCache);
michael@0 349 if (NS_SUCCEEDED(rv) && !failCache) {
michael@0 350 // disable network connections and return.
michael@0 351
michael@0 352 nsCOMPtr<nsIIOService> ios =
michael@0 353 do_GetService(NS_IOSERVICE_CONTRACTID, &rv);
michael@0 354 if (NS_FAILED(rv))
michael@0 355 return rv;
michael@0 356
michael@0 357 bool offline;
michael@0 358 rv = ios->GetOffline(&offline);
michael@0 359 if (NS_FAILED(rv))
michael@0 360 return rv;
michael@0 361
michael@0 362 if (!offline) {
michael@0 363 rv = ios->SetOffline(true);
michael@0 364 if (NS_FAILED(rv))
michael@0 365 return rv;
michael@0 366 }
michael@0 367
michael@0 368 // lock the "network.online" prference so user cannot toggle back to
michael@0 369 // online mode.
michael@0 370 rv = mPrefBranch->SetBoolPref("network.online", false);
michael@0 371 if (NS_FAILED(rv))
michael@0 372 return rv;
michael@0 373
michael@0 374 mPrefBranch->LockPref("network.online");
michael@0 375 return NS_OK;
michael@0 376 }
michael@0 377
michael@0 378 /* faiover_to_cached is set to true so
michael@0 379 Open the file and read the content.
michael@0 380 execute the javascript file
michael@0 381 */
michael@0 382
michael@0 383 nsCOMPtr<nsIFile> failoverFile;
michael@0 384 rv = NS_GetSpecialDirectory(NS_APP_USER_PROFILE_50_DIR,
michael@0 385 getter_AddRefs(failoverFile));
michael@0 386 if (NS_FAILED(rv))
michael@0 387 return rv;
michael@0 388
michael@0 389 failoverFile->AppendNative(NS_LITERAL_CSTRING("failover.jsc"));
michael@0 390 rv = evaluateLocalFile(failoverFile);
michael@0 391 if (NS_FAILED(rv))
michael@0 392 NS_WARNING("Couldn't open failover.jsc, going back to default prefs");
michael@0 393 return NS_OK;
michael@0 394 }
michael@0 395
michael@0 396 nsresult nsAutoConfig::evaluateLocalFile(nsIFile *file)
michael@0 397 {
michael@0 398 nsresult rv;
michael@0 399 nsCOMPtr<nsIInputStream> inStr;
michael@0 400
michael@0 401 rv = NS_NewLocalFileInputStream(getter_AddRefs(inStr), file);
michael@0 402 if (NS_FAILED(rv))
michael@0 403 return rv;
michael@0 404
michael@0 405 int64_t fileSize;
michael@0 406 file->GetFileSize(&fileSize);
michael@0 407 uint32_t fs = fileSize; // Converting 64 bit structure to unsigned int
michael@0 408 char *buf = (char *)PR_Malloc(fs * sizeof(char));
michael@0 409 if (!buf)
michael@0 410 return NS_ERROR_OUT_OF_MEMORY;
michael@0 411
michael@0 412 uint32_t amt = 0;
michael@0 413 rv = inStr->Read(buf, fs, &amt);
michael@0 414 if (NS_SUCCEEDED(rv)) {
michael@0 415 EvaluateAdminConfigScript(buf, fs, nullptr, false,
michael@0 416 true, false);
michael@0 417 }
michael@0 418 inStr->Close();
michael@0 419 PR_Free(buf);
michael@0 420 return rv;
michael@0 421 }
michael@0 422
michael@0 423 nsresult nsAutoConfig::writeFailoverFile()
michael@0 424 {
michael@0 425 nsresult rv;
michael@0 426 nsCOMPtr<nsIFile> failoverFile;
michael@0 427 nsCOMPtr<nsIOutputStream> outStr;
michael@0 428 uint32_t amt;
michael@0 429
michael@0 430 rv = NS_GetSpecialDirectory(NS_APP_USER_PROFILE_50_DIR,
michael@0 431 getter_AddRefs(failoverFile));
michael@0 432 if (NS_FAILED(rv))
michael@0 433 return rv;
michael@0 434
michael@0 435 failoverFile->AppendNative(NS_LITERAL_CSTRING("failover.jsc"));
michael@0 436
michael@0 437 rv = NS_NewLocalFileOutputStream(getter_AddRefs(outStr), failoverFile);
michael@0 438 if (NS_FAILED(rv))
michael@0 439 return rv;
michael@0 440 rv = outStr->Write(mBuf.get(),mBuf.Length(),&amt);
michael@0 441 outStr->Close();
michael@0 442 return rv;
michael@0 443 }
michael@0 444
michael@0 445 nsresult nsAutoConfig::getEmailAddr(nsACString & emailAddr)
michael@0 446 {
michael@0 447
michael@0 448 nsresult rv;
michael@0 449 nsXPIDLCString prefValue;
michael@0 450
michael@0 451 /* Getting an email address through set of three preferences:
michael@0 452 First getting a default account with
michael@0 453 "mail.accountmanager.defaultaccount"
michael@0 454 second getting an associated id with the default account
michael@0 455 Third getting an email address with id
michael@0 456 */
michael@0 457
michael@0 458 rv = mPrefBranch->GetCharPref("mail.accountmanager.defaultaccount",
michael@0 459 getter_Copies(prefValue));
michael@0 460 if (NS_SUCCEEDED(rv) && !prefValue.IsEmpty()) {
michael@0 461 emailAddr = NS_LITERAL_CSTRING("mail.account.") +
michael@0 462 prefValue + NS_LITERAL_CSTRING(".identities");
michael@0 463 rv = mPrefBranch->GetCharPref(PromiseFlatCString(emailAddr).get(),
michael@0 464 getter_Copies(prefValue));
michael@0 465 if (NS_FAILED(rv) || prefValue.IsEmpty())
michael@0 466 return PromptForEMailAddress(emailAddr);
michael@0 467 int32_t commandIndex = prefValue.FindChar(',');
michael@0 468 if (commandIndex != kNotFound)
michael@0 469 prefValue.Truncate(commandIndex);
michael@0 470 emailAddr = NS_LITERAL_CSTRING("mail.identity.") +
michael@0 471 prefValue + NS_LITERAL_CSTRING(".useremail");
michael@0 472 rv = mPrefBranch->GetCharPref(PromiseFlatCString(emailAddr).get(),
michael@0 473 getter_Copies(prefValue));
michael@0 474 if (NS_FAILED(rv) || prefValue.IsEmpty())
michael@0 475 return PromptForEMailAddress(emailAddr);
michael@0 476 emailAddr = prefValue;
michael@0 477 }
michael@0 478 else {
michael@0 479 // look for 4.x pref in case we just migrated.
michael@0 480 rv = mPrefBranch->GetCharPref("mail.identity.useremail",
michael@0 481 getter_Copies(prefValue));
michael@0 482 if (NS_SUCCEEDED(rv) && !prefValue.IsEmpty())
michael@0 483 emailAddr = prefValue;
michael@0 484 else
michael@0 485 PromptForEMailAddress(emailAddr);
michael@0 486 }
michael@0 487
michael@0 488 return NS_OK;
michael@0 489 }
michael@0 490
michael@0 491 nsresult nsAutoConfig::PromptForEMailAddress(nsACString &emailAddress)
michael@0 492 {
michael@0 493 nsresult rv;
michael@0 494 nsCOMPtr<nsIPromptService> promptService = do_GetService("@mozilla.org/embedcomp/prompt-service;1", &rv);
michael@0 495 NS_ENSURE_SUCCESS(rv, rv);
michael@0 496 nsCOMPtr<nsIStringBundleService> bundleService = do_GetService(NS_STRINGBUNDLE_CONTRACTID, &rv);
michael@0 497 NS_ENSURE_SUCCESS(rv, rv);
michael@0 498
michael@0 499 nsCOMPtr<nsIStringBundle> bundle;
michael@0 500 rv = bundleService->CreateBundle("chrome://autoconfig/locale/autoconfig.properties",
michael@0 501 getter_AddRefs(bundle));
michael@0 502 NS_ENSURE_SUCCESS(rv, rv);
michael@0 503
michael@0 504 nsXPIDLString title;
michael@0 505 rv = bundle->GetStringFromName(MOZ_UTF16("emailPromptTitle"), getter_Copies(title));
michael@0 506 NS_ENSURE_SUCCESS(rv, rv);
michael@0 507
michael@0 508 nsXPIDLString err;
michael@0 509 rv = bundle->GetStringFromName(MOZ_UTF16("emailPromptMsg"), getter_Copies(err));
michael@0 510 NS_ENSURE_SUCCESS(rv, rv);
michael@0 511 bool check = false;
michael@0 512 nsXPIDLString emailResult;
michael@0 513 bool success;
michael@0 514 rv = promptService->Prompt(nullptr, title.get(), err.get(), getter_Copies(emailResult), nullptr, &check, &success);
michael@0 515 if (!success)
michael@0 516 return NS_ERROR_FAILURE;
michael@0 517 NS_ENSURE_SUCCESS(rv, rv);
michael@0 518 LossyCopyUTF16toASCII(emailResult, emailAddress);
michael@0 519 return NS_OK;
michael@0 520 }

mercurial