NS_IMETHODIMP
InterceptedChannelChrome::FinishSynthesizedResponse(const nsACString& aFinalURLSpec)
{
  if (!mChannel) {
    return NS_ERROR_NOT_AVAILABLE;
  }

  EnsureSynthesizedResponse();

  // If the synthesized response is a redirect, then we want to respect
  // the encoding of whatever is loaded as a result.
  if (WillRedirect(mSynthesizedResponseHead.ref())) {
    nsresult rv = mChannel->SetApplyConversion(mOldApplyConversion);
    NS_ENSURE_SUCCESS(rv, rv);
  }

  mChannel->MarkIntercepted();

  // First we ensure the appropriate metadata is set on the synthesized cache entry
  // (i.e. the flattened response head)

  nsCOMPtr<nsISupports> securityInfo;
  nsresult rv = mChannel->GetSecurityInfo(getter_AddRefs(securityInfo));
  NS_ENSURE_SUCCESS(rv, rv);

  rv = DoAddCacheEntryHeaders(mChannel, mSynthesizedCacheEntry,
                              mChannel->GetRequestHead(),
                              mSynthesizedResponseHead.ref(), securityInfo);
  NS_ENSURE_SUCCESS(rv, rv);

  nsCOMPtr<nsIURI> originalURI;
  mChannel->GetURI(getter_AddRefs(originalURI));

  nsCOMPtr<nsIURI> responseURI;
  if (!aFinalURLSpec.IsEmpty()) {
    nsresult rv = NS_NewURI(getter_AddRefs(responseURI), aFinalURLSpec);
    NS_ENSURE_SUCCESS(rv, rv);
  } else {
    responseURI = originalURI;
  }

  bool equal = false;
  originalURI->Equals(responseURI, &equal);
  if (!equal) {
    nsresult rv =
        mChannel->StartRedirectChannelToURI(responseURI, nsIChannelEventSink::REDIRECT_INTERNAL);
    NS_ENSURE_SUCCESS(rv, rv);
  } else {
    bool usingSSL = false;
    responseURI->SchemeIs("https", &usingSSL);

    // Then we open a real cache entry to read the synthesized response from.
    rv = mChannel->OpenCacheEntry(usingSSL);
    NS_ENSURE_SUCCESS(rv, rv);

    mSynthesizedCacheEntry = nullptr;

    if (!mChannel->AwaitingCacheCallbacks()) {
      rv = mChannel->ContinueConnect();
      NS_ENSURE_SUCCESS(rv, rv);
    }
  }
  mChannel = nullptr;
  return NS_OK;
}
nsresult
nsMsgQuote::QuoteMessage(const char *msgURI, bool quoteHeaders,
                         nsIMsgQuotingOutputStreamListener * aQuoteMsgStreamListener,
                         const char * aMsgCharSet, bool headersOnly,
                         nsIMsgDBHdr *aMsgHdr)
{
  nsresult  rv;
  if (!msgURI)
    return NS_ERROR_INVALID_ARG;

  mQuoteHeaders = quoteHeaders;
  mStreamListener = aQuoteMsgStreamListener;

  nsAutoCString msgUri(msgURI);
  bool fileUrl = !strncmp(msgURI, "file:", 5);
  bool forwardedMessage = PL_strstr(msgURI, "&realtype=message/rfc822") != nullptr;
  nsCOMPtr<nsIURI> aURL;
  if (fileUrl)
  {
    msgUri.Replace(0, 5, NS_LITERAL_CSTRING("mailbox:"));
    msgUri.AppendLiteral("?number=0");
    rv = NS_NewURI(getter_AddRefs(aURL), msgUri);
    nsCOMPtr<nsIMsgMessageUrl> mailUrl(do_QueryInterface(aURL));
    if (mailUrl)
      mailUrl->SetMessageHeader(aMsgHdr);
  }
  else if (forwardedMessage)
    rv = NS_NewURI(getter_AddRefs(aURL), msgURI);
  else
  {
    nsCOMPtr <nsIMsgMessageService> msgService;
    rv = GetMessageServiceFromURI(nsDependentCString(msgURI), getter_AddRefs(msgService));
    if (NS_FAILED(rv)) return rv;
    rv = msgService->GetUrlForUri(msgURI, getter_AddRefs(aURL), nullptr);
  }
  if (NS_FAILED(rv)) return rv;

  nsCOMPtr <nsIURL> mailNewsUrl = do_QueryInterface(aURL, &rv);
  NS_ENSURE_SUCCESS(rv,rv);

  nsAutoCString queryPart;
  rv = mailNewsUrl->GetQuery(queryPart);
  if (!queryPart.IsEmpty())
    queryPart.Append('&');

  if (headersOnly) /* We don't need to quote the message body but we still need to extract the headers */
    queryPart.Append("header=only");
  else if (quoteHeaders)
    queryPart.Append("header=quote");
  else
    queryPart.Append("header=quotebody");
  rv = mailNewsUrl->SetQuery(queryPart);
  NS_ENSURE_SUCCESS(rv,rv);

  // if we were given a non empty charset, then use it
  if (aMsgCharSet && *aMsgCharSet)
  {
    nsCOMPtr<nsIMsgI18NUrl> i18nUrl (do_QueryInterface(aURL));
    if (i18nUrl)
      i18nUrl->SetCharsetOverRide(aMsgCharSet);
  }

  mQuoteListener = do_CreateInstance(NS_MSGQUOTELISTENER_CONTRACTID, &rv);
  if (NS_FAILED(rv)) return rv;
  mQuoteListener->SetMsgQuote(this);

  // funky magic go get the isupports for this class which inherits from multiple interfaces.
  nsISupports * supports;
  QueryInterface(NS_GET_IID(nsISupports), (void **) &supports);
  nsCOMPtr<nsISupports> quoteSupport = supports;
  NS_IF_RELEASE(supports);

  // now we want to create a necko channel for this url and we want to open it
  mQuoteChannel = nullptr;
  nsCOMPtr<nsIIOService> netService =
    mozilla::services::GetIOService();
  NS_ENSURE_TRUE(netService, NS_ERROR_UNEXPECTED);
  rv = netService->NewChannelFromURI(aURL, getter_AddRefs(mQuoteChannel));
  if (NS_FAILED(rv)) return rv;
  nsCOMPtr<nsISupports> ctxt = do_QueryInterface(aURL);

  nsCOMPtr<nsIStreamConverterService> streamConverterService = 
           do_GetService("@mozilla.org/streamConverters;1", &rv);
  NS_ENSURE_SUCCESS(rv,rv);

  nsCOMPtr<nsIStreamListener> convertedListener;
  rv = streamConverterService->AsyncConvertData("message/rfc822",
                                                "application/vnd.mozilla.xul+xml",
                                                mStreamListener,
                                                quoteSupport,
                                                getter_AddRefs(convertedListener));
  if (NS_FAILED(rv)) return rv;

  //  now try to open the channel passing in our display consumer as the listener 
  rv = mQuoteChannel->AsyncOpen(convertedListener, ctxt);
  return rv;
}
NS_IMETHODIMP
sbLocalDatabaseMediaListBase::GetName(nsAString& aName)
{
  nsAutoString unlocalizedName;
  nsresult rv = GetProperty(NS_LITERAL_STRING(SB_PROPERTY_MEDIALISTNAME),
                            unlocalizedName);
  NS_ENSURE_SUCCESS(rv, rv);

  // If the property doesn't exist just return an empty string.
  if (unlocalizedName.IsEmpty()) {
    aName.Assign(unlocalizedName);
    return NS_OK;
  }

  // See if this string should be localized. The basic format we're looking for
  // is:
  //
  //   &[chrome://songbird/songbird.properties#]library.name
  //
  // The url (followed by '#') is optional.

  const PRUnichar *start, *end;
  PRUint32 length = unlocalizedName.BeginReading(&start, &end);

  static const PRUnichar sAmp = '&';

  // Bail out if this can't be a localizable string.
  if (length <= 1 || *start != sAmp) {
    aName.Assign(unlocalizedName);
    return NS_OK;
  }

  // Skip the ampersand
  start++;
  nsDependentSubstring stringKey(start, end - start), propertiesURL;

  static const PRUnichar sHash = '#';

  for (const PRUnichar* current = start; current < end; current++) {
    if (*current == sHash) {
      stringKey.Rebind(current + 1, end - current - 1);
      propertiesURL.Rebind(start, current - start);

      break;
    }
  }

  nsCOMPtr<nsIStringBundleService> bundleService =
    do_GetService("@mozilla.org/intl/stringbundle;1", &rv);
  NS_ENSURE_SUCCESS(rv, rv);

  nsCOMPtr<nsIStringBundle> bundle;

  if (!propertiesURL.IsEmpty()) {
    nsCOMPtr<nsIURI> propertiesURI;
    rv = NS_NewURI(getter_AddRefs(propertiesURI), propertiesURL);

    if (NS_SUCCEEDED(rv)) {
      bool schemeIsChrome;
      rv = propertiesURI->SchemeIs("chrome", &schemeIsChrome);

      if (NS_SUCCEEDED(rv) && schemeIsChrome) {
        nsCAutoString propertiesSpec;
        rv = propertiesURI->GetSpec(propertiesSpec);

        if (NS_SUCCEEDED(rv)) {
          rv = bundleService->CreateBundle(propertiesSpec.get(),
                                           getter_AddRefs(bundle));
        }
      }
    }
  }

  if (!bundle) {
    rv = bundleService->CreateBundle(DEFAULT_PROPERTIES_URL,
                                     getter_AddRefs(bundle));
  }

  if (NS_SUCCEEDED(rv)) {
    nsAutoString localizedName;
    rv = bundle->GetStringFromName(stringKey.BeginReading(),
                                   getter_Copies(localizedName));
    if (NS_SUCCEEDED(rv)) {
      aName.Assign(localizedName);
      return NS_OK;
    }
  }

  aName.Assign(unlocalizedName);
  return NS_OK;
}
NS_IMETHODIMP
HttpBaseChannel::SetReferrer(nsIURI *referrer)
{
    ENSURE_CALLED_BEFORE_ASYNC_OPEN();

    // clear existing referrer, if any
    mReferrer = nsnull;
    mRequestHead.ClearHeader(nsHttp::Referer);

    if (!referrer)
        return NS_OK;

    // check referrer blocking pref
    PRUint32 referrerLevel;
    if (mLoadFlags & LOAD_INITIAL_DOCUMENT_URI)
        referrerLevel = 1; // user action
    else
        referrerLevel = 2; // inline content
    if (gHttpHandler->ReferrerLevel() < referrerLevel)
        return NS_OK;

    nsCOMPtr<nsIURI> referrerGrip;
    nsresult rv;
    bool match;

    //
    // Strip off "wyciwyg://123/" from wyciwyg referrers.
    //
    // XXX this really belongs elsewhere since wyciwyg URLs aren't part of necko.
    //     perhaps some sort of generic nsINestedURI could be used.  then, if an URI
    //     fails the whitelist test, then we could check for an inner URI and try
    //     that instead.  though, that might be too automatic.
    //
    rv = referrer->SchemeIs("wyciwyg", &match);
    if (NS_FAILED(rv)) return rv;
    if (match) {
        nsCAutoString path;
        rv = referrer->GetPath(path);
        if (NS_FAILED(rv)) return rv;

        PRUint32 pathLength = path.Length();
        if (pathLength <= 2) return NS_ERROR_FAILURE;

        // Path is of the form "//123/http://foo/bar", with a variable number of digits.
        // To figure out where the "real" URL starts, search path for a '/', starting at
        // the third character.
        PRInt32 slashIndex = path.FindChar('/', 2);
        if (slashIndex == kNotFound) return NS_ERROR_FAILURE;

        // Get the charset of the original URI so we can pass it to our fixed up URI.
        nsCAutoString charset;
        referrer->GetOriginCharset(charset);

        // Replace |referrer| with a URI without wyciwyg://123/.
        rv = NS_NewURI(getter_AddRefs(referrerGrip),
                       Substring(path, slashIndex + 1, pathLength - slashIndex - 1),
                       charset.get());
        if (NS_FAILED(rv)) return rv;

        referrer = referrerGrip.get();
    }

    //
    // block referrer if not on our white list...
    //
    static const char *const referrerWhiteList[] = {
        "http",
        "https",
        "ftp",
        "gopher",
        nsnull
    };
    match = false;
    const char *const *scheme = referrerWhiteList;
    for (; *scheme && !match; ++scheme) {
        rv = referrer->SchemeIs(*scheme, &match);
        if (NS_FAILED(rv)) return rv;
    }
    if (!match)
        return NS_OK; // kick out....

    //
    // Handle secure referrals.
    //
    // Support referrals from a secure server if this is a secure site
    // and (optionally) if the host names are the same.
    //
    rv = referrer->SchemeIs("https", &match);
    if (NS_FAILED(rv)) return rv;
    if (match) {
        rv = mURI->SchemeIs("https", &match);
        if (NS_FAILED(rv)) return rv;
        if (!match)
            return NS_OK;

        if (!gHttpHandler->SendSecureXSiteReferrer()) {
            nsCAutoString referrerHost;
            nsCAutoString host;

            rv = referrer->GetAsciiHost(referrerHost);
            if (NS_FAILED(rv)) return rv;

            rv = mURI->GetAsciiHost(host);
            if (NS_FAILED(rv)) return rv;

            // GetAsciiHost returns lowercase hostname.
            if (!referrerHost.Equals(host))
                return NS_OK;
        }
    }

    nsCOMPtr<nsIURI> clone;
    //
    // we need to clone the referrer, so we can:
    //  (1) modify it
    //  (2) keep a reference to it after returning from this function
    //
    // Use CloneIgnoringRef to strip away any fragment per RFC 2616 section 14.36
    rv = referrer->CloneIgnoringRef(getter_AddRefs(clone));
    if (NS_FAILED(rv)) return rv;

    // strip away any userpass; we don't want to be giving out passwords ;-)
    rv = clone->SetUserPass(EmptyCString());
    if (NS_FAILED(rv)) return rv;

    nsCAutoString spec;
    rv = clone->GetAsciiSpec(spec);
    if (NS_FAILED(rv)) return rv;

    // finally, remember the referrer URI and set the Referer header.
    mReferrer = clone;
    mRequestHead.SetHeader(nsHttp::Referer, spec);
    return NS_OK;
}
Beispiel #5
0
nsresult
nsChannelClassifier::IsTrackerWhitelisted()
{
  nsresult rv;
  nsCOMPtr<nsIURIClassifier> uriClassifier =
    do_GetService(NS_URICLASSIFIERSERVICE_CONTRACTID, &rv);
  NS_ENSURE_SUCCESS(rv, rv);

  nsAutoCString tables;
  Preferences::GetCString("urlclassifier.trackingWhitelistTable", &tables);

  if (tables.IsEmpty()) {
    LOG(("nsChannelClassifier[%p]:IsTrackerWhitelisted whitelist disabled",
         this));
    return NS_ERROR_TRACKING_URI;
  }

  nsCOMPtr<nsIHttpChannelInternal> chan = do_QueryInterface(mChannel, &rv);
  NS_ENSURE_SUCCESS(rv, rv);

  nsCOMPtr<nsIURI> topWinURI;
  rv = chan->GetTopWindowURI(getter_AddRefs(topWinURI));
  NS_ENSURE_SUCCESS(rv, rv);
  if (!topWinURI) {
    LOG(("nsChannelClassifier[%p]: No window URI", this));
    return NS_ERROR_TRACKING_URI;
  }

  nsCOMPtr<nsIScriptSecurityManager> securityManager =
    do_GetService(NS_SCRIPTSECURITYMANAGER_CONTRACTID, &rv);
  NS_ENSURE_SUCCESS(rv, rv);
  nsCOMPtr<nsIPrincipal> chanPrincipal;
  rv = securityManager->GetChannelURIPrincipal(mChannel,
                                               getter_AddRefs(chanPrincipal));
  NS_ENSURE_SUCCESS(rv, rv);

  // Craft a whitelist URL like "toplevel.page/?resource=third.party.domain"
  nsAutoCString pageHostname, resourceDomain;
  rv = topWinURI->GetHost(pageHostname);
  NS_ENSURE_SUCCESS(rv, rv);
  rv = chanPrincipal->GetBaseDomain(resourceDomain);
  NS_ENSURE_SUCCESS(rv, rv);
  nsAutoCString whitelistEntry = NS_LITERAL_CSTRING("http://") +
    pageHostname + NS_LITERAL_CSTRING("/?resource=") + resourceDomain;
  LOG(("nsChannelClassifier[%p]: Looking for %s in the whitelist",
       this, whitelistEntry.get()));

  nsCOMPtr<nsIURI> whitelistURI;
  rv = NS_NewURI(getter_AddRefs(whitelistURI), whitelistEntry);
  NS_ENSURE_SUCCESS(rv, rv);

  // Check whether or not the tracker is in the entity whitelist
  nsTArray<nsCString> results;
  rv = uriClassifier->ClassifyLocalWithTables(whitelistURI, tables, results);
  NS_ENSURE_SUCCESS(rv, rv);
  if (!results.IsEmpty()) {
    return NS_OK; // found it on the whitelist, must not be blocked
  }

  LOG(("nsChannelClassifier[%p]: %s is not in the whitelist",
       this, whitelistEntry.get()));
  return NS_ERROR_TRACKING_URI;
}
NS_IMETHODIMP nsXPInstallManager::DownloadNext()
{
    nsresult rv = NS_OK;
    mContentLength = 0;

    if (mCancelled)
    {
        // Don't download any more if we were cancelled
        Shutdown();
        return NS_OK;
    }

    if ( mNextItem < mTriggers->Size() )
    {
        //-------------------------------------------------
        // There are items to download, get the next one
        //-------------------------------------------------
        mItem = (nsXPITriggerItem*)mTriggers->Get(mNextItem++);

        NS_ASSERTION( mItem, "bogus Trigger slipped through" );
        NS_ASSERTION( !mItem->mURL.IsEmpty(), "bogus trigger");
        if ( !mItem || mItem->mURL.IsEmpty() )
        {
            // serious problem with trigger! Can't notify anyone of the
            // error without the URL, just try to carry on.
            return DownloadNext();
        }

        // --- Tell the dialog we're starting a download
        if (mDlg)
            mDlg->OnStateChange( mNextItem-1, nsIXPIProgressDialog::DOWNLOAD_START, 0 );

        if ( mItem->IsFileURL() && mChromeType == NOT_CHROME )
        {
            //--------------------------------------------------
            // Already local, we can open it where it is
            //--------------------------------------------------
            nsCOMPtr<nsIURI> pURL;
            rv = NS_NewURI(getter_AddRefs(pURL), mItem->mURL);

            if (NS_SUCCEEDED(rv))
            {
                nsCOMPtr<nsIFileURL> fileURL = do_QueryInterface(pURL,&rv);
                if (fileURL)
                {
                    nsCOMPtr<nsIFile> localFile;
                    rv = fileURL->GetFile(getter_AddRefs(localFile));
                    if (NS_SUCCEEDED(rv))
                    {
                        mItem->mFile = do_QueryInterface(localFile,&rv);
                    }
                }
            }

            if ( NS_FAILED(rv) || !mItem->mFile )
            {
                // send error status back
                if (mDlg)
                    mDlg->OnStateChange( mNextItem-1,
                                         nsIXPIProgressDialog::INSTALL_DONE,
                                         nsInstall::UNEXPECTED_ERROR );
                mTriggers->SendStatus( mItem->mURL.get(),
                                       nsInstall::UNEXPECTED_ERROR );
                mItem->mFile = 0;
            }
            else if (mDlg)
            {
                mDlg->OnStateChange( mNextItem-1,
                                     nsIXPIProgressDialog::DOWNLOAD_DONE, 0);
            }

            // --- on to the next one
            return DownloadNext();
        }
        else
        {
            //--------------------------------------------------
            // We have one to download
            //--------------------------------------------------
            rv = GetDestinationFile(mItem->mURL, getter_AddRefs(mItem->mFile));
            if (NS_SUCCEEDED(rv))
            {
                nsCOMPtr<nsIURI> pURL;
                rv = NS_NewURI(getter_AddRefs(pURL), mItem->mURL);
                if (NS_SUCCEEDED(rv))
                {
                    nsCOMPtr<nsIChannel> channel;

                    rv = NS_NewChannel(getter_AddRefs(channel), pURL, nsnull, mLoadGroup, this);
                    if (NS_SUCCEEDED(rv))
                    {
                        rv = channel->AsyncOpen(this, nsnull);
                    }
                }
            }

            if (NS_FAILED(rv))
            {
                // announce failure
                if (mDlg)
                    mDlg->OnStateChange( mNextItem-1,
                                         nsIXPIProgressDialog::INSTALL_DONE,
                                         nsInstall::DOWNLOAD_ERROR );
                mTriggers->SendStatus( mItem->mURL.get(),
                                       nsInstall::DOWNLOAD_ERROR );
                mItem->mFile = 0;

                // We won't get Necko callbacks so start the next one now
                return DownloadNext();
            }
        }
    }
    else
    {
        //------------------------------------------------------
        // all downloaded, install them
        //------------------------------------------------------
        InstallItems();
        Shutdown();
    }

    return rv;
}
Beispiel #7
0
nsresult
nsJSON::DecodeInternal(JSContext* cx,
                       nsIInputStream *aStream,
                       int32_t aContentLength,
                       bool aNeedsConverter,
                       JS::Value* aRetval,
                       DecodingMode mode /* = STRICT */)
{
  JSAutoRequest ar(cx);

  // Consume the stream
  nsCOMPtr<nsIChannel> jsonChannel;
  if (!mURI) {
    NS_NewURI(getter_AddRefs(mURI), NS_LITERAL_CSTRING("about:blank"), 0, 0 );
    if (!mURI)
      return NS_ERROR_OUT_OF_MEMORY;
  }

  nsresult rv =
    NS_NewInputStreamChannel(getter_AddRefs(jsonChannel), mURI, aStream,
                             NS_LITERAL_CSTRING("application/json"));
  if (!jsonChannel || NS_FAILED(rv))
    return NS_ERROR_FAILURE;

  nsRefPtr<nsJSONListener> jsonListener =
    new nsJSONListener(cx, aRetval, aNeedsConverter, mode);

  //XXX this stream pattern should be consolidated in netwerk
  rv = jsonListener->OnStartRequest(jsonChannel, nullptr);
  if (NS_FAILED(rv)) {
    jsonChannel->Cancel(rv);
    return rv;
  }

  nsresult status;
  jsonChannel->GetStatus(&status);
  uint64_t offset = 0;
  while (NS_SUCCEEDED(status)) {
    uint64_t available;
    rv = aStream->Available(&available);
    if (rv == NS_BASE_STREAM_CLOSED) {
      rv = NS_OK;
      break;
    }
    if (NS_FAILED(rv)) {
      jsonChannel->Cancel(rv);
      break;
    }
    if (!available)
      break; // blocking input stream has none available when done

    if (available > UINT32_MAX)
      available = UINT32_MAX;

    rv = jsonListener->OnDataAvailable(jsonChannel, nullptr,
                                       aStream,
                                       offset,
                                       (uint32_t)available);
    if (NS_FAILED(rv)) {
      jsonChannel->Cancel(rv);
      break;
    }

    offset += available;
    jsonChannel->GetStatus(&status);
  }
  NS_ENSURE_SUCCESS(rv, rv);

  rv = jsonListener->OnStopRequest(jsonChannel, nullptr, status);
  NS_ENSURE_SUCCESS(rv, rv);

  return NS_OK;
}
already_AddRefed<nsIPrincipal>
PrincipalInfoToPrincipal(const PrincipalInfo& aPrincipalInfo,
                         nsresult* aOptionalResult)
{
  MOZ_ASSERT(NS_IsMainThread());
  MOZ_ASSERT(aPrincipalInfo.type() != PrincipalInfo::T__None);

  nsresult stackResult;
  nsresult& rv = aOptionalResult ? *aOptionalResult : stackResult;

  nsCOMPtr<nsIScriptSecurityManager> secMan =
    do_GetService(NS_SCRIPTSECURITYMANAGER_CONTRACTID, &rv);
  if (NS_WARN_IF(NS_FAILED(rv))) {
    return nullptr;
  }

  nsCOMPtr<nsIPrincipal> principal;

  switch (aPrincipalInfo.type()) {
    case PrincipalInfo::TSystemPrincipalInfo: {
      rv = secMan->GetSystemPrincipal(getter_AddRefs(principal));
      if (NS_WARN_IF(NS_FAILED(rv))) {
        return nullptr;
      }

      return principal.forget();
    }

    case PrincipalInfo::TNullPrincipalInfo: {
      principal = do_CreateInstance(NS_NULLPRINCIPAL_CONTRACTID, &rv);
      if (NS_WARN_IF(NS_FAILED(rv))) {
        return nullptr;
      }

      return principal.forget();
    }

    case PrincipalInfo::TContentPrincipalInfo: {
      const ContentPrincipalInfo& info =
        aPrincipalInfo.get_ContentPrincipalInfo();

      nsCOMPtr<nsIURI> uri;
      rv = NS_NewURI(getter_AddRefs(uri), info.spec());
      if (NS_WARN_IF(NS_FAILED(rv))) {
        return nullptr;
      }

      if (info.attrs().mAppId == nsIScriptSecurityManager::UNKNOWN_APP_ID) {
        rv = secMan->GetSimpleCodebasePrincipal(uri, getter_AddRefs(principal));
      } else {
        principal = BasePrincipal::CreateCodebasePrincipal(uri, info.attrs());
        rv = principal ? NS_OK : NS_ERROR_FAILURE;
      }
      if (NS_WARN_IF(NS_FAILED(rv))) {
        return nullptr;
      }

      return principal.forget();
    }

    case PrincipalInfo::TExpandedPrincipalInfo: {
      const ExpandedPrincipalInfo& info = aPrincipalInfo.get_ExpandedPrincipalInfo();

      nsTArray< nsCOMPtr<nsIPrincipal> > whitelist;
      nsCOMPtr<nsIPrincipal> wlPrincipal;

      for (uint32_t i = 0; i < info.whitelist().Length(); i++) {
        wlPrincipal = PrincipalInfoToPrincipal(info.whitelist()[i], &rv);
        if (NS_WARN_IF(NS_FAILED(rv))) {
          return nullptr;
        }
        // append that principal to the whitelist
        whitelist.AppendElement(wlPrincipal);
      }

      RefPtr<nsExpandedPrincipal> expandedPrincipal = new nsExpandedPrincipal(whitelist);
      if (!expandedPrincipal) {
        NS_WARNING("could not instantiate expanded principal");
        return nullptr;
      }

      principal = expandedPrincipal;
      return principal.forget();
    }

    default:
      MOZ_CRASH("Unknown PrincipalInfo type!");
  }

  MOZ_CRASH("Should never get here!");
}
NS_IMETHODIMP
nsSiteSecurityService::IsSecureURI(uint32_t aType, nsIURI* aURI,
                                   uint32_t aFlags, bool* aResult)
{
  // Should be called on the main thread (or via proxy) since the permission
  // manager is used and it's not threadsafe.
  NS_ENSURE_TRUE(NS_IsMainThread(), NS_ERROR_UNEXPECTED);
  // Only HSTS is supported at the moment.
  NS_ENSURE_TRUE(aType == nsISiteSecurityService::HEADER_HSTS,
                 NS_ERROR_NOT_IMPLEMENTED);

  // set default in case if we can't find any STS information
  *aResult = false;

  nsAutoCString host;
  nsresult rv = GetHost(aURI, host);
  NS_ENSURE_SUCCESS(rv, rv);

  /* An IP address never qualifies as a secure URI. */
  if (HostIsIPAddress(host.BeginReading())) {
    return NS_OK;
  }

  const nsSTSPreload *preload = nullptr;
  nsSSSHostEntry *pbEntry = nullptr;

  bool isPrivate = aFlags & nsISocketProvider::NO_PERMANENT_STORAGE;
  if (isPrivate) {
    pbEntry = mPrivateModeHostTable.GetEntry(host.get());
  }

  nsCOMPtr<nsIPrincipal> principal;
  rv = GetPrincipalForURI(aURI, getter_AddRefs(principal));
  NS_ENSURE_SUCCESS(rv, rv);

  uint32_t permMgrPermission;
  rv = mPermMgr->TestExactPermissionFromPrincipal(principal, STS_PERMISSION,
                                                  &permMgrPermission);
  NS_ENSURE_SUCCESS(rv, rv);

  // First check the exact host. This involves first checking for an entry in
  // the private browsing table. If that entry exists, we don't want to check
  // in either the permission manager or the preload list. We only want to use
  // the stored permission if it is not a knockout entry, however.
  // Additionally, if it is a knockout entry, we want to stop looking for data
  // on the host, because the knockout entry indicates "we have no information
  // regarding the sts status of this host".
  if (pbEntry && pbEntry->mStsPermission != STS_UNSET) {
    SSSLOG(("Found private browsing table entry for %s", host.get()));
    if (!pbEntry->IsExpired() && pbEntry->mStsPermission == STS_SET) {
      *aResult = true;
      return NS_OK;
    }
  }
  // Next we look in the permission manager. Same story here regarding
  // knockout entries.
  else if (permMgrPermission != STS_UNSET) {
    SSSLOG(("Found permission manager entry for %s", host.get()));
    if (permMgrPermission == STS_SET) {
      *aResult = true;
      return NS_OK;
    }
  }
  // Finally look in the preloaded list. This is the exact host,
  // so if an entry exists at all, this host is sts.
  else if (GetPreloadListEntry(host.get())) {
    SSSLOG(("%s is a preloaded STS host", host.get()));
    *aResult = true;
    return NS_OK;
  }

  // Used for testing permissions as we walk up the domain tree.
  nsCOMPtr<nsIURI> domainWalkURI;
  nsCOMPtr<nsIPrincipal> domainWalkPrincipal;
  const char *subdomain;

  SSSLOG(("no HSTS data for %s found, walking up domain", host.get()));
  uint32_t offset = 0;
  for (offset = host.FindChar('.', offset) + 1;
       offset > 0;
       offset = host.FindChar('.', offset) + 1) {

    subdomain = host.get() + offset;

    // If we get an empty string, don't continue.
    if (strlen(subdomain) < 1) {
      break;
    }

    if (isPrivate) {
      pbEntry = mPrivateModeHostTable.GetEntry(subdomain);
    }

    // normalize all URIs with https://
    rv = NS_NewURI(getter_AddRefs(domainWalkURI),
                   NS_LITERAL_CSTRING("https://") + Substring(host, offset));
    NS_ENSURE_SUCCESS(rv, rv);

    rv = GetPrincipalForURI(domainWalkURI, getter_AddRefs(domainWalkPrincipal));
    NS_ENSURE_SUCCESS(rv, rv);

    rv = mPermMgr->TestExactPermissionFromPrincipal(domainWalkPrincipal,
                                                    STS_PERMISSION,
                                                    &permMgrPermission);
    NS_ENSURE_SUCCESS(rv, rv);

    // Do the same thing as with the exact host, except now we're looking at
    // ancestor domains of the original host. So, we have to look at the
    // include subdomains permissions (although we still have to check for the
    // STS_PERMISSION first to check that this is an sts host and not a
    // knockout entry - and again, if it is a knockout entry, we stop looking
    // for data on it and skip to the next higher up ancestor domain).
    if (pbEntry && pbEntry->mStsPermission != STS_UNSET) {
      SSSLOG(("Found private browsing table entry for %s", subdomain));
      if (!pbEntry->IsExpired() && pbEntry->mStsPermission == STS_SET) {
        *aResult = pbEntry->mIncludeSubdomains;
        break;
      }
    }
    else if (permMgrPermission != STS_UNSET) {
      SSSLOG(("Found permission manager entry for %s", subdomain));
      if (permMgrPermission == STS_SET) {
        uint32_t subdomainPermission;
        rv = mPermMgr->TestExactPermissionFromPrincipal(domainWalkPrincipal,
                                                        STS_SUBDOMAIN_PERMISSION,
                                                        &subdomainPermission);
        NS_ENSURE_SUCCESS(rv, rv);
        *aResult = (subdomainPermission == STS_SET);
        break;
      }
    }
    // This is an ancestor, so if we get a match, we have to check if the
    // preloaded entry includes subdomains.
    else if ((preload = GetPreloadListEntry(subdomain)) != nullptr) {
      if (preload->mIncludeSubdomains) {
        SSSLOG(("%s is a preloaded STS host", subdomain));
        *aResult = true;
        break;
      }
    }

    SSSLOG(("no HSTS data for %s found, walking up domain", subdomain));
  }

  // Use whatever we ended up with, which defaults to false.
  return NS_OK;
}
Beispiel #10
0
nsresult runTest(uint32_t aExpectedPolicyCount, // this should be 0 for policies which should fail to parse
                 const char* aPolicy,
                 const char* aExpextedResult) {

  nsresult rv;
  nsCOMPtr<nsIScriptSecurityManager> secman =
    do_GetService(NS_SCRIPTSECURITYMANAGER_CONTRACTID, &rv);
  NS_ENSURE_SUCCESS(rv, rv);

  // we init the csp with http://www.selfuri.com
  nsCOMPtr<nsIURI> selfURI;
  rv = NS_NewURI(getter_AddRefs(selfURI), "http://www.selfuri.com");
  NS_ENSURE_SUCCESS(rv, rv);

  nsCOMPtr<nsIPrincipal> selfURIPrincipal;
  // Can't use BasePrincipal::CreateCodebasePrincipal here
  // because the symbol is not visible here
  rv = secman->GetCodebasePrincipal(selfURI, getter_AddRefs(selfURIPrincipal));
  NS_ENSURE_SUCCESS(rv, rv);

  // create a CSP object
  nsCOMPtr<nsIContentSecurityPolicy> csp =
    do_CreateInstance(NS_CSPCONTEXT_CONTRACTID, &rv);
  NS_ENSURE_SUCCESS(rv, rv);

  // for testing the parser we only need to set a principal which is needed
  // to translate the keyword 'self' into an actual URI.
  rv = csp->SetRequestContext(nullptr, selfURIPrincipal);
  NS_ENSURE_SUCCESS(rv, rv);

  // append a policy
  nsString policyStr;
  policyStr.AssignASCII(aPolicy);
  rv = csp->AppendPolicy(policyStr, false, false);
  NS_ENSURE_SUCCESS(rv, rv);

  // when executing fuzzy tests we do not care about the actual output
  // of the parser, we just want to make sure that the parser is not crashing.
  if (aExpectedPolicyCount == kFuzzyExpectedPolicyCount) {
    return NS_OK;
  }

  // verify that the expected number of policies exists
  uint32_t actualPolicyCount;
  rv = csp->GetPolicyCount(&actualPolicyCount);
  NS_ENSURE_SUCCESS(rv, rv);
  if (actualPolicyCount != aExpectedPolicyCount) {
    fail("Actual policy count not equal to expected policy count (%d != %d) for policy: %s",
          actualPolicyCount, aExpectedPolicyCount, aPolicy);
    return NS_ERROR_UNEXPECTED;
  }

  // if the expected policy count is 0, we can return, because
  // we can not compare any output anyway. Used when parsing
  // errornous policies.
  if (aExpectedPolicyCount == 0) {
    return NS_OK;
  }

  // compare the parsed policy against the expected result
  nsString parsedPolicyStr;
  // checking policy at index 0, which is the one what we appended.
  rv = csp->GetPolicy(0, parsedPolicyStr);
  NS_ENSURE_SUCCESS(rv, rv);

  if (!NS_ConvertUTF16toUTF8(parsedPolicyStr).EqualsASCII(aExpextedResult)) {
    fail("Actual policy does not match expected policy  (%s != %s)",
          NS_ConvertUTF16toUTF8(parsedPolicyStr).get(), aExpextedResult);
    return NS_ERROR_UNEXPECTED;
  }

  return NS_OK;
}
//
// Native method StartSoftwareUpdate
//
static JSBool
InstallTriggerGlobalStartSoftwareUpdate(JSContext *cx, JSObject *obj, uintN argc, jsval *argv, jsval *rval)
{
  nsIDOMInstallTriggerGlobal *nativeThis = getTriggerNative(cx, obj);
  if (!nativeThis)
    return JS_FALSE;

  PRBool       nativeRet;
  PRInt32      flags = 0;

  *rval = JSVAL_FALSE;

  nsIScriptGlobalObject *globalObject = nsnull;
  nsIScriptContext *scriptContext = GetScriptContextFromJSContext(cx);
  if (scriptContext)
      globalObject = scriptContext->GetGlobalObject();

  if (!globalObject)
      return JS_TRUE;

  // get window.location to construct relative URLs
  nsCOMPtr<nsIURI> baseURL;
  JSObject* global = JS_GetGlobalObject(cx);
  if (global)
  {
    jsval v;
    if (JS_GetProperty(cx,global,"location",&v))
    {
      nsAutoString location;
      ConvertJSValToStr( location, cx, v );
      NS_NewURI(getter_AddRefs(baseURL), location);
    }
  }


  if ( argc >= 1 )
  {
    nsAutoString xpiURL;
    ConvertJSValToStr(xpiURL, cx, argv[0]);
    if (baseURL)
    {
        nsCAutoString resolvedURL;
        baseURL->Resolve(NS_ConvertUTF16toUTF8(xpiURL), resolvedURL);
        xpiURL = NS_ConvertUTF8toUTF16(resolvedURL);
    }

    // Make sure caller is allowed to load this url.
    nsresult rv = InstallTriggerCheckLoadURIFromScript(cx, xpiURL);
    if (NS_FAILED(rv))
        return JS_FALSE;

    if (argc >= 2 && !JS_ValueToInt32(cx, argv[1], (int32 *)&flags))
    {
        JS_ReportError(cx, "StartSoftwareUpdate() 2nd parameter must be a number");
        return JS_FALSE;
    }

    nsCOMPtr<nsIURI> checkuri;
    rv = nativeThis->GetOriginatingURI(globalObject, getter_AddRefs(checkuri));
    if (NS_SUCCEEDED(rv))
    {
        nsAutoPtr<nsXPITriggerInfo> trigger(new nsXPITriggerInfo());
        nsAutoPtr<nsXPITriggerItem> item(new nsXPITriggerItem(0,
                                                              xpiURL.get(),
                                                              nsnull));
        if (trigger && item)
        {
            // trigger will free item when complete
            trigger->Add(item.forget());
            nsCOMPtr<nsIDOMWindowInternal> win(do_QueryInterface(globalObject));
            nsCOMPtr<nsIXPIInstallInfo> installInfo =
                                new nsXPIInstallInfo(win, checkuri, trigger, 0);
            if (installInfo)
            {
                // From here trigger is owned by installInfo until passed on to nsXPInstallManager
                trigger.forget();
                PRBool enabled = PR_FALSE;
                nativeThis->UpdateEnabled(checkuri, XPI_WHITELIST, &enabled);
                if (!enabled)
                {
                    nsCOMPtr<nsIObserverService> os =
                      mozilla::services::GetObserverService();
                    if (os)
                        os->NotifyObservers(installInfo,
                                            "xpinstall-install-blocked",
                                            nsnull);
                }
                else
                {
                    nativeThis->StartInstall(installInfo, &nativeRet);
                    *rval = BOOLEAN_TO_JSVAL(nativeRet);
                }
            }
        }
    }
  }
  else
  {
    JS_ReportError(cx, "Function StartSoftwareUpdate requires 1 parameters");
    return JS_FALSE;
  }

  return JS_TRUE;
}
//
// Native method InstallChrome
//
static JSBool
InstallTriggerGlobalInstallChrome(JSContext *cx, JSObject *obj, uintN argc, jsval *argv, jsval *rval)
{
  nsIDOMInstallTriggerGlobal *nativeThis = getTriggerNative(cx, obj);
  if (!nativeThis)
    return JS_FALSE;

  uint32       chromeType = NOT_CHROME;
  nsAutoString sourceURL;
  nsAutoString name;

  *rval = JSVAL_FALSE;

  // get chromeType first, the update enabled check for skins skips whitelisting
  if (argc >=1)
  {
      if (!JS_ValueToECMAUint32(cx, argv[0], &chromeType))
          return JS_FALSE;
  }

  // make sure XPInstall is enabled, return if not
  nsIScriptGlobalObject *globalObject = nsnull;
  nsIScriptContext *scriptContext = GetScriptContextFromJSContext(cx);
  if (scriptContext)
      globalObject = scriptContext->GetGlobalObject();

  if (!globalObject)
      return JS_TRUE;

  // get window.location to construct relative URLs
  nsCOMPtr<nsIURI> baseURL;
  JSObject* global = JS_GetGlobalObject(cx);
  if (global)
  {
    jsval v;
    if (JS_GetProperty(cx,global,"location",&v))
    {
      nsAutoString location;
      ConvertJSValToStr( location, cx, v );
      NS_NewURI(getter_AddRefs(baseURL), location);
    }
  }


  if ( argc >= 3 )
  {
    ConvertJSValToStr(sourceURL, cx, argv[1]);
    ConvertJSValToStr(name, cx, argv[2]);

    if (baseURL)
    {
        nsCAutoString resolvedURL;
        baseURL->Resolve(NS_ConvertUTF16toUTF8(sourceURL), resolvedURL);
        sourceURL = NS_ConvertUTF8toUTF16(resolvedURL);
    }

    // Make sure caller is allowed to load this url.
    nsresult rv = InstallTriggerCheckLoadURIFromScript(cx, sourceURL);
    if (NS_FAILED(rv))
        return JS_FALSE;

    if ( chromeType & CHROME_ALL )
    {
        // there's at least one known chrome type
        nsCOMPtr<nsIURI> checkuri;
        nsresult rv = nativeThis->GetOriginatingURI(globalObject,
                                                    getter_AddRefs(checkuri));
        if (NS_SUCCEEDED(rv))
        {
            nsAutoPtr<nsXPITriggerInfo> trigger(new nsXPITriggerInfo());
            nsAutoPtr<nsXPITriggerItem> item(new nsXPITriggerItem(name.get(),
                                                                  sourceURL.get(),
                                                                  nsnull));
            if (trigger && item)
            {
                // trigger will free item when complete
                trigger->Add(item.forget());
                nsCOMPtr<nsIDOMWindowInternal> win(do_QueryInterface(globalObject));
                nsCOMPtr<nsIXPIInstallInfo> installInfo =
                    new nsXPIInstallInfo(win, checkuri, trigger, chromeType);
                if (installInfo)
                {
                    // installInfo owns trigger now
                    trigger.forget();
                    PRBool enabled = PR_FALSE;
                    nativeThis->UpdateEnabled(checkuri, XPI_WHITELIST,
                                              &enabled);
                    if (!enabled)
                    {
                        nsCOMPtr<nsIObserverService> os =
                          mozilla::services::GetObserverService();
                        if (os)
                            os->NotifyObservers(installInfo,
                                                "xpinstall-install-blocked",
                                                nsnull);
                    }
                    else
                    {
                        PRBool nativeRet = PR_FALSE;
                        nativeThis->StartInstall(installInfo, &nativeRet);
                        *rval = BOOLEAN_TO_JSVAL(nativeRet);
                    }
                }
            }
        }
    }
  }
  return JS_TRUE;
}
//
// Native method Install
//
static JSBool
InstallTriggerGlobalInstall(JSContext *cx, JSObject *obj, uintN argc, jsval *argv, jsval *rval)
{
  nsIDOMInstallTriggerGlobal *nativeThis = getTriggerNative(cx, obj);
  if (!nativeThis)
    return JS_FALSE;

  *rval = JSVAL_FALSE;

  // make sure XPInstall is enabled, return false if not
  nsIScriptGlobalObject *globalObject = nsnull;
  nsIScriptContext *scriptContext = GetScriptContextFromJSContext(cx);
  if (scriptContext)
    globalObject = scriptContext->GetGlobalObject();

  if (!globalObject)
      return JS_TRUE;

  nsCOMPtr<nsIScriptSecurityManager> secman(do_GetService(NS_SCRIPTSECURITYMANAGER_CONTRACTID));
  if (!secman)
  {
    JS_ReportError(cx, "Could not the script security manager service.");
    return JS_FALSE;
  }
  // get the principal.  if it doesn't exist, die.
  nsCOMPtr<nsIPrincipal> principal;
  secman->GetSubjectPrincipal(getter_AddRefs(principal));
  if (!principal)
  {
    JS_ReportError(cx, "Could not get the Subject Principal during InstallTrigger.Install()");
    return JS_FALSE;
  }

  // get window.location to construct relative URLs
  nsCOMPtr<nsIURI> baseURL;
  JSObject* global = JS_GetGlobalObject(cx);
  if (global)
  {
    jsval v;
    if (JS_GetProperty(cx,global,"location",&v))
    {
      nsAutoString location;
      ConvertJSValToStr( location, cx, v );
      NS_NewURI(getter_AddRefs(baseURL), location);
    }
  }

  PRBool abortLoad = PR_FALSE;

  // parse associative array of installs
  if ( argc >= 1 && JSVAL_IS_OBJECT(argv[0]) && JSVAL_TO_OBJECT(argv[0]) )
  {
    nsXPITriggerInfo *trigger = new nsXPITriggerInfo();
    if (!trigger)
      return JS_FALSE;

    trigger->SetPrincipal(principal);

    JSIdArray *ida = JS_Enumerate( cx, JSVAL_TO_OBJECT(argv[0]) );
    if ( ida )
    {
      jsval v;
      const PRUnichar *name, *URL;
      const PRUnichar *iconURL = nsnull;

      for (int i = 0; i < ida->length && !abortLoad; i++ )
      {
        JS_IdToValue( cx, ida->vector[i], &v );
        JSString * str = JS_ValueToString( cx, v );
        if (!str)
        {
          abortLoad = PR_TRUE;
          break;
        }

        name = reinterpret_cast<const PRUnichar*>(JS_GetStringChars( str ));

        URL = iconURL = nsnull;
        JSAutoByteString hash;
        JS_GetUCProperty( cx, JSVAL_TO_OBJECT(argv[0]), reinterpret_cast<const jschar*>(name), nsCRT::strlen(name), &v );
        if ( JSVAL_IS_OBJECT(v) && JSVAL_TO_OBJECT(v) )
        {
          jsval v2;
          if (JS_GetProperty( cx, JSVAL_TO_OBJECT(v), "URL", &v2 ) && !JSVAL_IS_VOID(v2)) {
            JSString *str = JS_ValueToString(cx, v2);
            if (!str) {
              abortLoad = PR_TRUE;
              break;
            }
            URL = reinterpret_cast<const PRUnichar*>(JS_GetStringChars(str));
          }

          if (JS_GetProperty( cx, JSVAL_TO_OBJECT(v), "IconURL", &v2 ) && !JSVAL_IS_VOID(v2)) {
            JSString *str = JS_ValueToString(cx, v2);
            if (!str) {
              abortLoad = PR_TRUE;
              break;
            }
            iconURL = reinterpret_cast<const PRUnichar*>(JS_GetStringChars(str));
          }

          if (JS_GetProperty( cx, JSVAL_TO_OBJECT(v), "Hash", &v2) && !JSVAL_IS_VOID(v2)) {
            JSString *str = JS_ValueToString(cx, v2);
            if (!str || !hash.encode(cx, str)) {
              abortLoad = PR_TRUE;
              break;
            }
          }
        }
        else
        {
          JSString *str = JS_ValueToString(cx, v);
          if (!str) {
            abortLoad = PR_TRUE;
            break;
          }
          URL = reinterpret_cast<const PRUnichar*>(JS_GetStringChars(str));
        }

        if ( URL )
        {
            // Get relative URL to load
            nsAutoString xpiURL(URL);
            if (baseURL)
            {
                nsCAutoString resolvedURL;
                baseURL->Resolve(NS_ConvertUTF16toUTF8(xpiURL), resolvedURL);
                xpiURL = NS_ConvertUTF8toUTF16(resolvedURL);
            }

            nsAutoString icon(iconURL);
            if (iconURL && baseURL)
            {
                nsCAutoString resolvedIcon;
                baseURL->Resolve(NS_ConvertUTF16toUTF8(icon), resolvedIcon);
                icon = NS_ConvertUTF8toUTF16(resolvedIcon);
            }

            // Make sure we're allowed to load this URL and the icon URL
            nsresult rv = InstallTriggerCheckLoadURIFromScript(cx, xpiURL);
            if (NS_FAILED(rv))
                abortLoad = PR_TRUE;

            if (!abortLoad && iconURL)
            {
                rv = InstallTriggerCheckLoadURIFromScript(cx, icon);
                if (NS_FAILED(rv))
                    abortLoad = PR_TRUE;
            }

            if (!abortLoad)
            {
                // Add the install item to the trigger collection
                nsXPITriggerItem *item =
                    new nsXPITriggerItem( name, xpiURL.get(), icon.get(), hash );
                if ( item )
                {
                    trigger->Add( item );
                }
                else
                    abortLoad = PR_TRUE;
            }
        }
        else
            abortLoad = PR_TRUE;
      }
      JS_DestroyIdArray( cx, ida );
    }


    // pass on only if good stuff found
    if (!abortLoad && trigger->Size() > 0)
    {
        nsCOMPtr<nsIURI> checkuri;
        nsresult rv = nativeThis->GetOriginatingURI(globalObject,
                                                    getter_AddRefs(checkuri));
        if (NS_SUCCEEDED(rv))
        {
            nsCOMPtr<nsIDOMWindowInternal> win(do_QueryInterface(globalObject));
            nsCOMPtr<nsIXPIInstallInfo> installInfo =
                new nsXPIInstallInfo(win, checkuri, trigger, 0);
            if (installInfo)
            {
                // installInfo now owns triggers
                PRBool enabled = PR_FALSE;
                nativeThis->UpdateEnabled(checkuri, XPI_WHITELIST, &enabled);
                if (!enabled)
                {
                    nsCOMPtr<nsIObserverService> os =
                      mozilla::services::GetObserverService();
                    if (os)
                        os->NotifyObservers(installInfo,
                                            "xpinstall-install-blocked",
                                            nsnull);
                }
                else
                {
                    // save callback function if any (ignore bad args for now)
                    if ( argc >= 2 && JS_TypeOfValue(cx,argv[1]) == JSTYPE_FUNCTION )
                    {
                        trigger->SaveCallback( cx, argv[1] );
                    }

                    PRBool result;
                    nativeThis->StartInstall(installInfo, &result);
                    *rval = BOOLEAN_TO_JSVAL(result);
                }
                return JS_TRUE;
            }
        }
    }
    // didn't pass it on so we must delete trigger
    delete trigger;
  }

  JS_ReportError(cx, "Incorrect arguments to InstallTrigger.Install()");
  return JS_FALSE;
}
nsresult
sbLocalDatabaseLibraryFactory::InitalizeLibrary(nsIFile* aDatabaseFile,
                                                const nsAString &aResourceGUID)
{
  nsresult rv;
  PRInt32 dbOk;

  nsCOMPtr<nsIFile> parentDirectory;
  rv = aDatabaseFile->GetParent(getter_AddRefs(parentDirectory));
  NS_ENSURE_SUCCESS(rv, rv);

  bool parentExists;
  rv = parentDirectory->Exists(&parentExists);
  NS_ENSURE_SUCCESS(rv, rv);

  if (!parentExists) {
    rv = CreateDirectory(parentDirectory);
    NS_ENSURE_SUCCESS(rv, rv);
  }

  bool parentIsWritable = IsDirectoryWritable(parentDirectory);
  NS_ENSURE_TRUE(parentIsWritable, NS_ERROR_FILE_ACCESS_DENIED);

  // Now that we know we have appropriate permissions make a new query.
  nsCOMPtr<sbIDatabaseQuery> query =
    do_CreateInstance(SONGBIRD_DATABASEQUERY_CONTRACTID, &rv);
  NS_ENSURE_SUCCESS(rv, rv);

  rv = query->SetAsyncQuery(PR_FALSE);
  NS_ENSURE_SUCCESS(rv, rv);

  rv = SetQueryDatabaseFile(query, aDatabaseFile);
  NS_ENSURE_SUCCESS(rv, rv);

  nsCOMPtr<nsIURI> schemaURI;
  rv = NS_NewURI(getter_AddRefs(schemaURI), NS_LITERAL_CSTRING(SCHEMA_URL));
  NS_ENSURE_SUCCESS(rv, rv);

  nsCOMPtr<nsIInputStream> input;
  rv = NS_OpenURI(getter_AddRefs(input), schemaURI);
  NS_ENSURE_SUCCESS(rv, rv);

  nsCOMPtr<nsIConverterInputStream> converterStream =
    do_CreateInstance("@mozilla.org/intl/converter-input-stream;1", &rv);
  NS_ENSURE_SUCCESS(rv, rv);

  rv = converterStream->Init(input,
                             "UTF-8",
                             CONVERTER_BUFFER_SIZE,
                             nsIConverterInputStream::
                               DEFAULT_REPLACEMENT_CHARACTER);
  NS_ENSURE_SUCCESS(rv, rv);

  nsCOMPtr<nsIUnicharInputStream> unichar =
    do_QueryInterface(converterStream, &rv);
  NS_ENSURE_SUCCESS(rv, rv);

  PRUint32 read;
  nsString response, result;
  rv = unichar->ReadString(PR_UINT32_MAX, result, &read);
  NS_ENSURE_SUCCESS(rv, rv);
  NS_ASSERTION(read, "Schema file zero bytes?");
  while (read > 0) {
    response.Append(result);
    rv = unichar->ReadString(PR_UINT32_MAX, result, &read);
    NS_ENSURE_SUCCESS(rv, rv);
  }

  rv = unichar->Close();
  NS_ENSURE_SUCCESS(rv, rv);

  NS_NAMED_LITERAL_STRING(colonNewline, ";\n");
  PRInt32 posStart = 0;
  PRInt32 posEnd = response.Find(colonNewline, posStart);
  while (posEnd >= 0) {
    rv = query->AddQuery(Substring(response, posStart, posEnd - posStart));
    NS_ENSURE_SUCCESS(rv, rv);
    posStart = posEnd + 2;
    posEnd = response.Find(colonNewline, posStart);
  }

  rv = query->Execute(&dbOk);
  NS_ENSURE_SUCCESS(rv, rv);
  NS_ENSURE_TRUE(dbOk == 0, NS_ERROR_FAILURE);

  nsString guid(aResourceGUID);
  if(guid.IsEmpty()) {
    // Create a resource guid for this database.
    nsCOMPtr<nsIUUIDGenerator> uuidGen =
      do_GetService("@mozilla.org/uuid-generator;1", &rv);
    NS_ENSURE_SUCCESS(rv, rv);

    nsID id;
    rv = uuidGen->GenerateUUIDInPlace(&id);
    NS_ENSURE_SUCCESS(rv, rv);

    char guidChars[NSID_LENGTH];
    id.ToProvidedString(guidChars);

    guid = NS_ConvertASCIItoUTF16(nsDependentCString(guidChars + 1,
                                                     NSID_LENGTH - 3));
  }

  // Insert the guid into the database.
  nsCOMPtr<sbISQLInsertBuilder> insert =
    do_CreateInstance(SB_SQLBUILDER_INSERT_CONTRACTID, &rv);
  NS_ENSURE_SUCCESS(rv, rv);

  rv = insert->SetIntoTableName(NS_LITERAL_STRING("library_metadata"));
  NS_ENSURE_SUCCESS(rv, rv);

  rv = insert->AddColumn(NS_LITERAL_STRING("name"));
  NS_ENSURE_SUCCESS(rv, rv);

  rv = insert->AddColumn(NS_LITERAL_STRING("value"));
  NS_ENSURE_SUCCESS(rv, rv);

  rv = insert->AddValueString(NS_LITERAL_STRING("resource-guid"));
  NS_ENSURE_SUCCESS(rv, rv);

  rv = insert->AddValueString(guid);
  NS_ENSURE_SUCCESS(rv, rv);

  nsAutoString sql;
  rv = insert->ToString(sql);
  NS_ENSURE_SUCCESS(rv, rv);

  rv = query->ResetQuery();
  NS_ENSURE_SUCCESS(rv, rv);

  rv = query->AddQuery(sql);
  NS_ENSURE_SUCCESS(rv, rv);

  rv = query->Execute(&dbOk);
  NS_ENSURE_SUCCESS(rv, rv);
  NS_ENSURE_TRUE(dbOk == 0, NS_ERROR_FAILURE);

  nsString now;
  sbLocalDatabaseLibrary::GetNowString(now);

  nsCOMPtr<nsIURI> fileURI;
  rv = NS_NewFileURI(getter_AddRefs(fileURI), aDatabaseFile);
  NS_ENSURE_SUCCESS(rv, rv);

  nsCString uriSpec;
  rv = fileURI->GetSpec(uriSpec);
  NS_ENSURE_SUCCESS(rv, rv);

  // Add the default library media item properties
  insert = do_CreateInstance(SB_SQLBUILDER_INSERT_CONTRACTID, &rv);
  NS_ENSURE_SUCCESS(rv, rv);

  rv = insert->SetIntoTableName(NS_LITERAL_STRING("library_media_item"));
  NS_ENSURE_SUCCESS(rv, rv);

  rv = insert->AddColumn(NS_LITERAL_STRING("guid"));
  NS_ENSURE_SUCCESS(rv, rv);

  rv = insert->AddValueString(guid);
  NS_ENSURE_SUCCESS(rv, rv);

  rv = insert->AddColumn(NS_LITERAL_STRING("created"));
  NS_ENSURE_SUCCESS(rv, rv);

  rv = insert->AddValueString(now);
  NS_ENSURE_SUCCESS(rv, rv);

  rv = insert->AddColumn(NS_LITERAL_STRING("updated"));
  NS_ENSURE_SUCCESS(rv, rv);

  rv = insert->AddValueString(now);
  NS_ENSURE_SUCCESS(rv, rv);

  rv = insert->AddColumn(NS_LITERAL_STRING("content_url"));
  NS_ENSURE_SUCCESS(rv, rv);

  rv = insert->AddValueString(NS_ConvertUTF8toUTF16(uriSpec));
  NS_ENSURE_SUCCESS(rv, rv);

  rv = insert->AddColumn(NS_LITERAL_STRING("hidden"));
  NS_ENSURE_SUCCESS(rv, rv);

  rv = insert->AddValueLong(0);
  NS_ENSURE_SUCCESS(rv, rv);

  rv = insert->AddColumn(NS_LITERAL_STRING("is_list"));
  NS_ENSURE_SUCCESS(rv, rv);

  rv = insert->AddValueLong(0);
  NS_ENSURE_SUCCESS(rv, rv);

  rv = insert->ToString(sql);
  NS_ENSURE_SUCCESS(rv, rv);

  rv = query->ResetQuery();
  NS_ENSURE_SUCCESS(rv, rv);

  rv = query->AddQuery(sql);
  NS_ENSURE_SUCCESS(rv, rv);

  rv = query->Execute(&dbOk);
  NS_ENSURE_SUCCESS(rv, rv);
  NS_ENSURE_TRUE(dbOk == 0, NS_ERROR_FAILURE);

  return NS_OK;
}
nsresult
nsContextMenuInfo::GetBackgroundImageRequestInternal(nsIDOMNode *aDOMNode, imgRequestProxy **aRequest)
{
  NS_ENSURE_ARG_POINTER(aDOMNode);

  nsCOMPtr<nsIDOMNode> domNode = aDOMNode;
  nsCOMPtr<nsIDOMNode> parentNode;

  nsCOMPtr<nsIDOMDocument> document;
  domNode->GetOwnerDocument(getter_AddRefs(document));
  NS_ENSURE_TRUE(document, NS_ERROR_FAILURE);

  nsCOMPtr<nsIDOMWindow> window;
  document->GetDefaultView(getter_AddRefs(window));
  NS_ENSURE_TRUE(window, NS_ERROR_FAILURE);

  nsCOMPtr<nsIDOMCSSPrimitiveValue> primitiveValue;
  nsAutoString bgStringValue;

  // get Content Security Policy to pass to LoadImage
  nsCOMPtr<nsIDocument> doc(do_QueryInterface(document));
  nsCOMPtr<nsIPrincipal> principal;
  nsCOMPtr<nsIChannelPolicy> channelPolicy;
  nsCOMPtr<nsIContentSecurityPolicy> csp;
  if (doc) {
    principal = doc->NodePrincipal();
    nsresult rv = principal->GetCsp(getter_AddRefs(csp));
    NS_ENSURE_SUCCESS(rv, rv);
    if (csp) {
      channelPolicy = do_CreateInstance("@mozilla.org/nschannelpolicy;1");
      channelPolicy->SetContentSecurityPolicy(csp);
      channelPolicy->SetLoadType(nsIContentPolicy::TYPE_IMAGE);
    }
  }
  
  while (true) {
    nsCOMPtr<nsIDOMElement> domElement(do_QueryInterface(domNode));
    // bail for the parent node of the root element or null argument
    if (!domElement)
      break;
    
    nsCOMPtr<nsIDOMCSSStyleDeclaration> computedStyle;
    window->GetComputedStyle(domElement, EmptyString(),
                             getter_AddRefs(computedStyle));
    if (computedStyle) {
      nsCOMPtr<nsIDOMCSSValue> cssValue;
      computedStyle->GetPropertyCSSValue(NS_LITERAL_STRING("background-image"),
                                         getter_AddRefs(cssValue));
      primitiveValue = do_QueryInterface(cssValue);
      if (primitiveValue) {
        primitiveValue->GetStringValue(bgStringValue);
        if (!bgStringValue.EqualsLiteral("none")) {
          nsCOMPtr<nsIURI> bgUri;
          NS_NewURI(getter_AddRefs(bgUri), bgStringValue);
          NS_ENSURE_TRUE(bgUri, NS_ERROR_FAILURE);

          nsRefPtr<imgLoader> il = imgLoader::GetInstance();
          NS_ENSURE_TRUE(il, NS_ERROR_FAILURE);

          return il->LoadImage(bgUri, nullptr, nullptr, principal, nullptr,
                               nullptr, nullptr, nsIRequest::LOAD_NORMAL,
                               nullptr, channelPolicy, EmptyString(), aRequest);
        }
      }

      // bail if we encounter non-transparent background-color
      computedStyle->GetPropertyCSSValue(NS_LITERAL_STRING("background-color"),
                                         getter_AddRefs(cssValue));
      primitiveValue = do_QueryInterface(cssValue);
      if (primitiveValue) {
        primitiveValue->GetStringValue(bgStringValue);
        if (!bgStringValue.EqualsLiteral("transparent"))
          return NS_ERROR_FAILURE;
      }
    }

    domNode->GetParentNode(getter_AddRefs(parentNode));
    domNode = parentNode;
  }

  return NS_ERROR_FAILURE;
}