NS_IMETHODIMP
nsInstallTrigger::UpdateEnabled(nsIScriptGlobalObject* aGlobalObject, PRBool aUseWhitelist, PRBool* aReturn)
{
    nsCOMPtr<nsIURI> uri;
    nsresult rv = GetOriginatingURI(aGlobalObject, getter_AddRefs(uri));
    NS_ENSURE_SUCCESS(rv, rv);
    return UpdateEnabled(uri, aUseWhitelist, aReturn);
}
nsresult
ThirdPartyUtil::GetFirstPartyURIInternal(nsIChannel *aChannel,
                                         nsIDocument *aDoc,
                                         bool aLogErrors,
                                         nsIURI **aOutput)
{
  nsresult rv = NS_ERROR_NULL_POINTER;
  nsCOMPtr<nsIURI> srcURI;

  if (!aOutput)
    return rv;

  *aOutput = nullptr;

  if (!aChannel && aDoc) {
    aChannel = aDoc->GetChannel();
  }

  // If aChannel is specified or available, use the official route
  // for sure
  if (aChannel) {
    rv = GetOriginatingURI(aChannel, aOutput);
    aChannel->GetURI(getter_AddRefs(srcURI));
    if (NS_SUCCEEDED(rv) && *aOutput) {
      // At this point, about: and chrome: URLs have been mapped to file: or
      // jar: URLs.  Try to recover the original URL.
      nsAutoCString scheme;
      nsresult rv2 = (*aOutput)->GetScheme(scheme);
      NS_ENSURE_SUCCESS(rv2, rv2);
      if (scheme.Equals("file") || scheme.Equals("jar")) {
        nsCOMPtr<nsIURI> originalURI;
        rv2 = aChannel->GetOriginalURI(getter_AddRefs(originalURI));
        if (NS_SUCCEEDED(rv2) && originalURI) {
          NS_RELEASE(*aOutput);
          NS_ADDREF(*aOutput = originalURI);
        }
      }
    }
  }

  // If the channel was missing, closed or broken, try the
  // window hierarchy directly.
  //
  // This might fail to work for first-party loads themselves, but
  // we don't need this codepath for that case.
  if (NS_FAILED(rv) && aDoc) {
    nsCOMPtr<nsIDOMWindow> top;
    nsCOMPtr<nsIDOMDocument> topDDoc;
    nsIURI *docURI = nullptr;
    srcURI = aDoc->GetDocumentURI();

    if (aDoc->GetWindow()) {
      aDoc->GetWindow()->GetTop(getter_AddRefs(top));
      top->GetDocument(getter_AddRefs(topDDoc));

      nsCOMPtr<nsIDocument> topDoc(do_QueryInterface(topDDoc));
      docURI = topDoc->GetOriginalURI();
      if (docURI) {
        // Give us a mutable URI and also addref
        rv = NS_EnsureSafeToReturn(docURI, aOutput);
      }
    } else {
      // XXX: Chrome callers (such as NoScript) can end up here
      // through getImageData/canvas usage with no document state
      // (no Window and a document URI of about:blank). Propogate
      // rv fail (by doing nothing), and hope caller recovers.
    }

    if (*aOutput)
      rv = NS_OK;
  }

  if (*aOutput && !SchemeIsWhiteListed(*aOutput)) {
    // If URI scheme is not whitelisted and the URI lacks a hostname, force a
    // failure.
    nsAutoCString host;
    rv = (*aOutput)->GetHost(host);
    if (NS_SUCCEEDED(rv) && (host.Length() == 0)) {
      rv = NS_ERROR_FAILURE;
    }
  }

  // Log failure to error console.
  if (aLogErrors && NS_FAILED(rv)) {
    nsCOMPtr<nsIConsoleService> console
                              (do_GetService(NS_CONSOLESERVICE_CONTRACTID));
    if (console) {
      nsCString spec;
      nsCString srcSpec("unknown");

      if (srcURI)
        srcURI->GetSpec(srcSpec);

      if (*aOutput)
        (*aOutput)->GetSpec(spec);
      if (spec.Length() > 0) {
        nsPrintfCString msg("getFirstPartyURI failed for %s: no host in first party URI %s",
                            srcSpec.get(), spec.get()); // TODO: L10N
        console->LogStringMessage(NS_ConvertUTF8toUTF16(msg).get());
      } else {
        nsPrintfCString msg("getFirstPartyURI failed for %s: 0x%x", srcSpec.get(), rv);
        console->LogStringMessage(NS_ConvertUTF8toUTF16(msg).get());
      }
    }

    if (*aOutput) {
      // discard return object.
      (*aOutput)->Release();
      *aOutput = nullptr;
    }
  }

  // TODO: We could provide a route through the loadgroup + notification
  // callbacks too, but either channel or document was always available
  // in the cases where this function was originally needed (the image cache).
  // The notification callbacks also appear to suffers from the same limitation
  // as the document path. See nsICookiePermissions.GetOriginatingURI() for
  // details.

  return rv;
}