SerializedLoadContext::SerializedLoadContext(nsIChannel* aChannel) { if (!aChannel) { Init(nullptr); return; } nsCOMPtr<nsILoadContext> loadContext; NS_QueryNotificationCallbacks(aChannel, loadContext); Init(loadContext); if (!loadContext) { // Attempt to retrieve the private bit from the channel if it has been // overriden. bool isPrivate = false; bool isOverriden = false; nsCOMPtr<nsIPrivateBrowsingChannel> pbChannel = do_QueryInterface(aChannel); if (pbChannel && NS_SUCCEEDED(pbChannel->IsPrivateModeOverriden(&isPrivate, &isOverriden)) && isOverriden) { mUsePrivateBrowsing = isPrivate; mIsPrivateBitValid = true; } mOriginAttributes.SyncAttributesWithPrivateBrowsing(mUsePrivateBrowsing); } }
NS_IMETHODIMP nsMsgCookiePolicy::CanAccess(nsIURI *aURI, nsIChannel *aChannel, nsCookieAccess *aResult) { // by default we deny all cookies in mail *aResult = ACCESS_DENY; NS_ENSURE_ARG_POINTER(aChannel); nsCOMPtr<nsIDocShellTreeItem> docShellTreeItem; NS_QueryNotificationCallbacks(aChannel, docShellTreeItem); NS_ENSURE_TRUE(docShellTreeItem, NS_OK); PRInt32 itemType; docShellTreeItem->GetItemType(&itemType); // allow chrome docshells to set cookies if (itemType == nsIDocShellTreeItem::typeChrome) *aResult = ACCESS_DEFAULT; else // allow RSS articles in content to access cookies { NS_ENSURE_TRUE(aURI, NS_OK); PRBool isRSS = PR_FALSE; IsRSSArticle(aURI, &isRSS); if (isRSS) *aResult = ACCESS_DEFAULT; } return NS_OK; }
NS_IMETHODIMP FTPChannelChild::AsyncOpen(::nsIStreamListener* listener, nsISupports* aContext) { LOG(("FTPChannelChild::AsyncOpen [this=%x]\n", this)); NS_ENSURE_TRUE((gNeckoChild), NS_ERROR_FAILURE); NS_ENSURE_ARG_POINTER(listener); NS_ENSURE_TRUE(!mIsPending, NS_ERROR_IN_PROGRESS); NS_ENSURE_TRUE(!mWasOpened, NS_ERROR_ALREADY_OPENED); // Port checked in parent, but duplicate here so we can return with error // immediately, as we've done since before e10s. nsresult rv; rv = NS_CheckPortSafety(nsBaseChannel::URI()); // Need to disambiguate, // because in the child ipdl, // a typedef URI is defined... if (NS_FAILED(rv)) return rv; // FIXME: like bug 558623, merge constructor+SendAsyncOpen into 1 IPC msg gNeckoChild->SendPFTPChannelConstructor(this); mListener = listener; mListenerContext = aContext; // add ourselves to the load group. if (mLoadGroup) mLoadGroup->AddRequest(this, nsnull); // Get info from nsILoadContext, if any bool haveLoadContext = false; bool isContent = false; bool usePrivateBrowsing = false; bool isInBrowserElement = false; PRUint32 appId = 0; nsCOMPtr<nsILoadContext> loadContext; NS_QueryNotificationCallbacks(mCallbacks, mLoadGroup, NS_GET_IID(nsILoadContext), getter_AddRefs(loadContext)); if (loadContext) { haveLoadContext = true; loadContext->GetIsContent(&isContent); loadContext->GetUsePrivateBrowsing(&usePrivateBrowsing); loadContext->GetIsInBrowserElement(&isInBrowserElement); loadContext->GetAppId(&appId); } SendAsyncOpen(nsBaseChannel::URI(), mStartPos, mEntityID, IPC::InputStream(mUploadStream), haveLoadContext, isContent, usePrivateBrowsing, isInBrowserElement, appId); // The socket transport layer in the chrome process now has a logical ref to // us until OnStopRequest is called. AddIPDLReference(); mIsPending = true; mWasOpened = true; return rv; }
SerializedLoadContext::SerializedLoadContext(nsIWebSocketChannel* aChannel) { nsCOMPtr<nsILoadContext> loadContext; if (aChannel) { NS_QueryNotificationCallbacks(aChannel, loadContext); } Init(loadContext); }
NS_IMETHODIMP nsWyciwygChannel::SetLoadGroup(nsILoadGroup* aLoadGroup) { mLoadGroup = aLoadGroup; NS_QueryNotificationCallbacks(mCallbacks, mLoadGroup, NS_GET_IID(nsIProgressEventSink), getter_AddRefs(mProgressSink)); return NS_OK; }
NS_IMETHODIMP nsWyciwygChannel::SetNotificationCallbacks(nsIInterfaceRequestor* aNotificationCallbacks) { mCallbacks = aNotificationCallbacks; NS_QueryNotificationCallbacks(mCallbacks, mLoadGroup, NS_GET_IID(nsIProgressEventSink), getter_AddRefs(mProgressSink)); return NS_OK; }
SerializedLoadContext::SerializedLoadContext(nsIWebSocketChannel* aChannel) : mIsContent(false), mUseRemoteTabs(false), mUseRemoteSubframes(false), mUseTrackingProtection(false) { nsCOMPtr<nsILoadContext> loadContext; if (aChannel) { NS_QueryNotificationCallbacks(aChannel, loadContext); } Init(loadContext); }
NS_IMETHODIMP nsWyciwygChannel::SetNotificationCallbacks(nsIInterfaceRequestor* aNotificationCallbacks) { mCallbacks = aNotificationCallbacks; NS_QueryNotificationCallbacks(mCallbacks, mLoadGroup, NS_GET_IID(nsIProgressEventSink), getter_AddRefs(mProgressSink)); // Will never change unless SetNotificationCallbacks called again, so cache mPrivateBrowsing = NS_UsePrivateBrowsing(this); return NS_OK; }
static void GetAppIdAndBrowserStatus(nsIChannel* aChan, uint32_t* aAppId, bool* aInBrowserElem) { nsCOMPtr<nsILoadContext> loadContext; if (aChan) { NS_QueryNotificationCallbacks(aChan, loadContext); } if (!loadContext) { *aAppId = NECKO_NO_APP_ID; *aInBrowserElem = false; } else { loadContext->GetAppId(aAppId); loadContext->GetIsInBrowserElement(aInBrowserElem); } }
/* void asyncOpen (in nsIStreamListener aListener, in nsISupports aContext); */ NS_IMETHODIMP WyciwygChannelChild::AsyncOpen(nsIStreamListener *aListener, nsISupports *aContext) { LOG(("WyciwygChannelChild::AsyncOpen [this=%x]\n", this)); // The only places creating wyciwyg: channels should be // HTMLDocument::OpenCommon and session history. Both should be setting an // owner. NS_PRECONDITION(mOwner, "Must have a principal"); NS_ENSURE_STATE(mOwner); NS_ENSURE_ARG_POINTER(aListener); NS_ENSURE_TRUE(!mIsPending, NS_ERROR_IN_PROGRESS); mListener = aListener; mListenerContext = aContext; mIsPending = true; if (mLoadGroup) mLoadGroup->AddRequest(this, nullptr); // Get info from nsILoadContext, if any bool haveLoadContext = false; bool isContent = false; bool usePrivateBrowsing = false; bool isInBrowserElement = false; PRUint32 appId = 0; nsCAutoString extendedOrigin; nsCOMPtr<nsILoadContext> loadContext; NS_QueryNotificationCallbacks(mCallbacks, mLoadGroup, NS_GET_IID(nsILoadContext), getter_AddRefs(loadContext)); if (loadContext) { haveLoadContext = true; loadContext->GetIsContent(&isContent); loadContext->GetUsePrivateBrowsing(&usePrivateBrowsing); loadContext->GetIsInBrowserElement(&isInBrowserElement); loadContext->GetAppId(&appId); loadContext->GetExtendedOrigin(mURI, extendedOrigin); } SendAsyncOpen(IPC::URI(mOriginalURI), mLoadFlags, haveLoadContext, isContent, usePrivateBrowsing, isInBrowserElement, appId, extendedOrigin); mState = WCC_OPENED; return NS_OK; }
NS_IMETHODIMP nsWyciwygChannel::SetLoadGroup(nsILoadGroup* aLoadGroup) { if (!CanSetLoadGroup(aLoadGroup)) { return NS_ERROR_FAILURE; } mLoadGroup = aLoadGroup; NS_QueryNotificationCallbacks(mCallbacks, mLoadGroup, NS_GET_IID(nsIProgressEventSink), getter_AddRefs(mProgressSink)); mPrivateBrowsing = NS_UsePrivateBrowsing(this); NS_GetAppInfo(this, &mAppId, &mInBrowser); return NS_OK; }
// static nsresult nsChannelClassifier::NotifyTrackingProtectionDisabled(nsIChannel *aChannel) { // Can be called in EITHER the parent or child process. nsCOMPtr<nsIParentChannel> parentChannel; NS_QueryNotificationCallbacks(aChannel, parentChannel); if (parentChannel) { // This channel is a parent-process proxy for a child process request. // Tell the child process channel to do this instead. parentChannel->NotifyTrackingProtectionDisabled(); return NS_OK; } nsresult rv; nsCOMPtr<mozIThirdPartyUtil> thirdPartyUtil = do_GetService(THIRDPARTYUTIL_CONTRACTID, &rv); NS_ENSURE_SUCCESS(rv, rv); nsCOMPtr<mozIDOMWindowProxy> win; rv = thirdPartyUtil->GetTopWindowForChannel(aChannel, getter_AddRefs(win)); NS_ENSURE_SUCCESS(rv, rv); auto* pwin = nsPIDOMWindowOuter::From(win); nsCOMPtr<nsIDocShell> docShell = pwin->GetDocShell(); if (!docShell) { return NS_OK; } nsCOMPtr<nsIDocument> doc = docShell->GetDocument(); NS_ENSURE_TRUE(doc, NS_OK); // Notify nsIWebProgressListeners of this security event. // Can be used to change the UI state. nsCOMPtr<nsISecurityEventSink> eventSink = do_QueryInterface(docShell, &rv); NS_ENSURE_SUCCESS(rv, NS_OK); uint32_t state = 0; nsCOMPtr<nsISecureBrowserUI> securityUI; docShell->GetSecurityUI(getter_AddRefs(securityUI)); if (!securityUI) { return NS_OK; } doc->SetHasTrackingContentLoaded(true); securityUI->GetState(&state); state |= nsIWebProgressListener::STATE_LOADED_TRACKING_CONTENT; eventSink->OnSecurityChange(nullptr, state); return NS_OK; }
NS_IMETHODIMP nsWyciwygChannel::SetLoadGroup(nsILoadGroup* aLoadGroup) { if (!CanSetLoadGroup(aLoadGroup)) { return NS_ERROR_FAILURE; } mLoadGroup = aLoadGroup; NS_QueryNotificationCallbacks(mCallbacks, mLoadGroup, NS_GET_IID(nsIProgressEventSink), getter_AddRefs(mProgressSink)); UpdatePrivateBrowsing(); NS_GetOriginAttributes(this, mOriginAttributes); return NS_OK; }
NS_IMETHODIMP nsWyciwygChannel::SetNotificationCallbacks(nsIInterfaceRequestor* aNotificationCallbacks) { if (!CanSetCallbacks(aNotificationCallbacks)) { return NS_ERROR_FAILURE; } mCallbacks = aNotificationCallbacks; NS_QueryNotificationCallbacks(mCallbacks, mLoadGroup, NS_GET_IID(nsIProgressEventSink), getter_AddRefs(mProgressSink)); UpdatePrivateBrowsing(); NS_GetOriginAttributes(this, mOriginAttributes); return NS_OK; }
NS_IMETHODIMP nsWyciwygChannel::SetNotificationCallbacks(nsIInterfaceRequestor* aNotificationCallbacks) { if (!CanSetCallbacks(aNotificationCallbacks)) { return NS_ERROR_FAILURE; } mCallbacks = aNotificationCallbacks; NS_QueryNotificationCallbacks(mCallbacks, mLoadGroup, NS_GET_IID(nsIProgressEventSink), getter_AddRefs(mProgressSink)); mPrivateBrowsing = NS_UsePrivateBrowsing(this); NS_GetAppInfo(this, &mAppId, &mInBrowser); return NS_OK; }
NS_IMETHODIMP nsJARChannel::AsyncOpen(nsIStreamListener *listener, nsISupports *ctx) { LOG(("nsJARChannel::AsyncOpen [this=%x]\n", this)); NS_ENSURE_ARG_POINTER(listener); NS_ENSURE_TRUE(!mIsPending, NS_ERROR_IN_PROGRESS); mJarFile = nsnull; mIsUnsafe = PR_TRUE; // Initialize mProgressSink NS_QueryNotificationCallbacks(mCallbacks, mLoadGroup, mProgressSink); nsresult rv = EnsureJarInput(PR_FALSE); if (NS_FAILED(rv)) return rv; // These variables must only be set if we're going to trigger an // OnStartRequest, either from AsyncRead or OnDownloadComplete. mListener = listener; mListenerContext = ctx; mIsPending = PR_TRUE; if (mJarInput) { // create input stream pump and call AsyncRead as a block rv = NS_NewInputStreamPump(getter_AddRefs(mPump), mJarInput); if (NS_SUCCEEDED(rv)) rv = mPump->AsyncRead(this, nsnull); // If we failed to create the pump or initiate the AsyncRead, // then we need to clear these variables. if (NS_FAILED(rv)) { mIsPending = PR_FALSE; mListenerContext = nsnull; mListener = nsnull; return rv; } } if (mLoadGroup) mLoadGroup->AddRequest(this, nsnull); return NS_OK; }
NS_IMETHODIMP nsGopherChannel::OnTransportStatus(nsITransport *trans, nsresult status, PRUint64 progress, PRUint64 progressMax) { if (!mProgressSink) NS_QueryNotificationCallbacks(mCallbacks, mLoadGroup, mProgressSink); // suppress status notification if channel is no longer pending! if (mProgressSink && NS_SUCCEEDED(mStatus) && mPump && !(mLoadFlags & LOAD_BACKGROUND)) { NS_ConvertUTF8toUTF16 host(mHost); mProgressSink->OnStatus(this, nsnull, status, host.get()); if (status == nsISocketTransport::STATUS_RECEIVING_FROM || status == nsISocketTransport::STATUS_SENDING_TO) { mProgressSink->OnProgress(this, nsnull, progress, progressMax); } } return NS_OK; }
NS_IMETHODIMP ThirdPartyUtil::GetTopWindowForChannel(nsIChannel* aChannel, nsIDOMWindow** aWin) { NS_ENSURE_ARG(aWin); nsresult rv; // Find the associated window and its parent window. nsCOMPtr<nsILoadContext> ctx; NS_QueryNotificationCallbacks(aChannel, ctx); if (!ctx) { return NS_ERROR_INVALID_ARG; } nsCOMPtr<nsIDOMWindow> window; rv = ctx->GetAssociatedWindow(getter_AddRefs(window)); if (!window) { return NS_ERROR_INVALID_ARG; } rv = window->GetTop(aWin); return rv; }
NS_IMETHODIMP ThirdPartyUtil::GetTopWindowForChannel(nsIChannel* aChannel, nsIDOMWindow** aWin) { NS_ENSURE_ARG(aWin); // Find the associated window and its parent window. nsCOMPtr<nsILoadContext> ctx; NS_QueryNotificationCallbacks(aChannel, ctx); if (!ctx) { return NS_ERROR_INVALID_ARG; } nsCOMPtr<nsIDOMWindow> window; ctx->GetAssociatedWindow(getter_AddRefs(window)); nsCOMPtr<nsPIDOMWindow> top = do_QueryInterface(window); if (!top) { return NS_ERROR_INVALID_ARG; } top = top->GetTop(); top.forget(aWin); return NS_OK; }
NS_IMETHODIMP nsAsyncRedirectVerifyHelper::Run() { /* If the channel got canceled after it fired AsyncOnChannelRedirect * and before we got here, mostly because docloader load has been canceled, * we must completely ignore this notification and prevent any further * notification. */ if (IsOldChannelCanceled()) { ExplicitCallback(NS_BINDING_ABORTED); return NS_OK; } // First, the global observer NS_ASSERTION(gIOService, "Must have an IO service at this point"); LOG(("nsAsyncRedirectVerifyHelper::Run() calling gIOService...")); nsresult rv = gIOService->AsyncOnChannelRedirect(mOldChan, mNewChan, mFlags, this); if (NS_FAILED(rv)) { ExplicitCallback(rv); return NS_OK; } // Now, the per-channel observers nsCOMPtr<nsIChannelEventSink> sink; NS_QueryNotificationCallbacks(mOldChan, sink); if (sink) { LOG(("nsAsyncRedirectVerifyHelper::Run() calling sink...")); rv = DelegateOnChannelRedirect(sink, mOldChan, mNewChan, mFlags); } // All invocations to AsyncOnChannelRedirect has been done - call // InitCallback() to flag this InitCallback(); return NS_OK; }
/** * This function is called when username or password are requested from user. * This function is called in main thread as async request from dbus. * @param mount_op mount operation * @param message message to show to user * @param default_user preffered user * @param default_domain domain name * @param flags what type of information is required * @param user_data nsIChannel */ static void mount_operation_ask_password (GMountOperation *mount_op, const char *message, const char *default_user, const char *default_domain, GAskPasswordFlags flags, gpointer user_data) { nsIChannel *channel = (nsIChannel *) user_data; if (!channel) { g_mount_operation_reply(mount_op, G_MOUNT_OPERATION_ABORTED); return; } // We can't handle request for domain if (flags & G_ASK_PASSWORD_NEED_DOMAIN) { g_mount_operation_reply(mount_op, G_MOUNT_OPERATION_ABORTED); return; } nsCOMPtr<nsIAuthPrompt> prompt; NS_QueryNotificationCallbacks(channel, prompt); // If no auth prompt, then give up. We could failover to using the // WindowWatcher service, but that might defeat a consumer's purposeful // attempt to disable authentication (for whatever reason). if (!prompt) { g_mount_operation_reply(mount_op, G_MOUNT_OPERATION_ABORTED); return; } // Parse out the host and port... nsCOMPtr<nsIURI> uri; channel->GetURI(getter_AddRefs(uri)); if (!uri) { g_mount_operation_reply(mount_op, G_MOUNT_OPERATION_ABORTED); return; } nsAutoCString scheme, hostPort; uri->GetScheme(scheme); uri->GetHostPort(hostPort); // It doesn't make sense for either of these strings to be empty. What kind // of funky URI is this? if (scheme.IsEmpty() || hostPort.IsEmpty()) { g_mount_operation_reply(mount_op, G_MOUNT_OPERATION_ABORTED); return; } // Construct the single signon key. Altering the value of this key will // cause people's remembered passwords to be forgotten. Think carefully // before changing the way this key is constructed. nsAutoString key, realm; NS_ConvertUTF8toUTF16 dispHost(scheme); dispHost.AppendLiteral("://"); dispHost.Append(NS_ConvertUTF8toUTF16(hostPort)); key = dispHost; if (*default_domain != '\0') { // We assume the realm string is ASCII. That might be a bogus assumption, // but we have no idea what encoding GnomeVFS is using, so for now we'll // limit ourselves to ISO-Latin-1. XXX What is a better solution? realm.Append('"'); realm.Append(NS_ConvertASCIItoUTF16(default_domain)); realm.Append('"'); key.Append(' '); key.Append(realm); } // Construct the message string... // // We use Necko's string bundle here. This code really should be encapsulated // behind some Necko API, after all this code is based closely on the code in // nsHttpChannel.cpp. nsCOMPtr<nsIStringBundleService> bundleSvc = do_GetService(NS_STRINGBUNDLE_CONTRACTID); if (!bundleSvc) { g_mount_operation_reply(mount_op, G_MOUNT_OPERATION_ABORTED); return; } nsCOMPtr<nsIStringBundle> bundle; bundleSvc->CreateBundle("chrome://global/locale/commonDialogs.properties", getter_AddRefs(bundle)); if (!bundle) { g_mount_operation_reply(mount_op, G_MOUNT_OPERATION_ABORTED); return; } nsAutoString nsmessage; if (flags & G_ASK_PASSWORD_NEED_PASSWORD) { if (flags & G_ASK_PASSWORD_NEED_USERNAME) { if (!realm.IsEmpty()) { const char16_t *strings[] = { realm.get(), dispHost.get() }; bundle->FormatStringFromName(MOZ_UTF16("EnterLoginForRealm2"), strings, 2, getter_Copies(nsmessage)); } else { const char16_t *strings[] = { dispHost.get() }; bundle->FormatStringFromName(MOZ_UTF16("EnterUserPasswordFor2"), strings, 1, getter_Copies(nsmessage)); } } else { NS_ConvertUTF8toUTF16 userName(default_user); const char16_t *strings[] = { userName.get(), dispHost.get() }; bundle->FormatStringFromName(MOZ_UTF16("EnterPasswordFor"), strings, 2, getter_Copies(nsmessage)); } } else { g_warning("Unknown mount operation request (flags: %x)", flags); } if (nsmessage.IsEmpty()) { g_mount_operation_reply(mount_op, G_MOUNT_OPERATION_ABORTED); return; } // Prompt the user... nsresult rv; bool retval = false; char16_t *user = nullptr, *pass = nullptr; if (default_user) { // user will be freed by PromptUsernameAndPassword user = ToNewUnicode(NS_ConvertUTF8toUTF16(default_user)); } if (flags & G_ASK_PASSWORD_NEED_USERNAME) { rv = prompt->PromptUsernameAndPassword(nullptr, nsmessage.get(), key.get(), nsIAuthPrompt::SAVE_PASSWORD_PERMANENTLY, &user, &pass, &retval); } else { rv = prompt->PromptPassword(nullptr, nsmessage.get(), key.get(), nsIAuthPrompt::SAVE_PASSWORD_PERMANENTLY, &pass, &retval); } if (NS_FAILED(rv) || !retval) { // was || user == '\0' || pass == '\0' g_mount_operation_reply(mount_op, G_MOUNT_OPERATION_ABORTED); free(user); free(pass); return; } /* GIO should accept UTF8 */ g_mount_operation_set_username(mount_op, NS_ConvertUTF16toUTF8(user).get()); g_mount_operation_set_password(mount_op, NS_ConvertUTF16toUTF8(pass).get()); free(user); free(pass); g_mount_operation_reply(mount_op, G_MOUNT_OPERATION_HANDLED); }
bool nsHttpChannelAuthProvider::ConfirmAuth(const nsString &bundleKey, bool doYesNoPrompt) { // skip prompting the user if // 1) we've already prompted the user // 2) we're not a toplevel channel // 3) the userpass length is less than the "phishy" threshold uint32_t loadFlags; nsresult rv = mAuthChannel->GetLoadFlags(&loadFlags); if (NS_FAILED(rv)) return true; if (mSuppressDefensiveAuth || !(loadFlags & nsIChannel::LOAD_INITIAL_DOCUMENT_URI)) return true; nsCAutoString userPass; rv = mURI->GetUserPass(userPass); if (NS_FAILED(rv) || (userPass.Length() < gHttpHandler->PhishyUserPassLength())) return true; // we try to confirm by prompting the user. if we cannot do so, then // assume the user said ok. this is done to keep things working in // embedded builds, where the string bundle might not be present, etc. nsCOMPtr<nsIStringBundleService> bundleService = do_GetService(NS_STRINGBUNDLE_CONTRACTID); if (!bundleService) return true; nsCOMPtr<nsIStringBundle> bundle; bundleService->CreateBundle(NECKO_MSGS_URL, getter_AddRefs(bundle)); if (!bundle) return true; nsCAutoString host; rv = mURI->GetHost(host); if (NS_FAILED(rv)) return true; nsCAutoString user; rv = mURI->GetUsername(user); if (NS_FAILED(rv)) return true; NS_ConvertUTF8toUTF16 ucsHost(host), ucsUser(user); const PRUnichar *strs[2] = { ucsHost.get(), ucsUser.get() }; nsXPIDLString msg; bundle->FormatStringFromName(bundleKey.get(), strs, 2, getter_Copies(msg)); if (!msg) return true; nsCOMPtr<nsIInterfaceRequestor> callbacks; rv = mAuthChannel->GetNotificationCallbacks(getter_AddRefs(callbacks)); if (NS_FAILED(rv)) return true; nsCOMPtr<nsILoadGroup> loadGroup; rv = mAuthChannel->GetLoadGroup(getter_AddRefs(loadGroup)); if (NS_FAILED(rv)) return true; nsCOMPtr<nsIPrompt> prompt; NS_QueryNotificationCallbacks(callbacks, loadGroup, NS_GET_IID(nsIPrompt), getter_AddRefs(prompt)); if (!prompt) return true; // do not prompt again mSuppressDefensiveAuth = true; bool confirmed; if (doYesNoPrompt) { int32_t choice; // The actual value is irrelevant but we shouldn't be handing out // malformed JSBools to XPConnect. bool checkState = false; rv = prompt->ConfirmEx(nullptr, msg, nsIPrompt::BUTTON_POS_1_DEFAULT + nsIPrompt::STD_YES_NO_BUTTONS, nullptr, nullptr, nullptr, nullptr, &checkState, &choice); if (NS_FAILED(rv)) return true; confirmed = choice == 0; } else { rv = prompt->Confirm(nullptr, msg, &confirmed); if (NS_FAILED(rv)) return true; } return confirmed; }
// static nsresult nsChannelClassifier::SetBlockedTrackingContent(nsIChannel *channel) { // Can be called in EITHER the parent or child process. nsCOMPtr<nsIParentChannel> parentChannel; NS_QueryNotificationCallbacks(channel, parentChannel); if (parentChannel) { // This channel is a parent-process proxy for a child process request. The // actual channel will be notified via the status passed to // nsIRequest::Cancel and do this for us. return NS_OK; } nsresult rv; nsCOMPtr<mozIDOMWindowProxy> win; nsCOMPtr<mozIThirdPartyUtil> thirdPartyUtil = do_GetService(THIRDPARTYUTIL_CONTRACTID, &rv); NS_ENSURE_SUCCESS(rv, NS_OK); rv = thirdPartyUtil->GetTopWindowForChannel(channel, getter_AddRefs(win)); NS_ENSURE_SUCCESS(rv, NS_OK); auto* pwin = nsPIDOMWindowOuter::From(win); nsCOMPtr<nsIDocShell> docShell = pwin->GetDocShell(); if (!docShell) { return NS_OK; } nsCOMPtr<nsIDocument> doc = docShell->GetDocument(); NS_ENSURE_TRUE(doc, NS_OK); // This event might come after the user has navigated to another page. // To prevent showing the TrackingProtection UI on the wrong page, we need to // check that the loading URI for the channel is the same as the URI currently // loaded in the document. if (!SameLoadingURI(doc, channel)) { return NS_OK; } // Notify nsIWebProgressListeners of this security event. // Can be used to change the UI state. nsCOMPtr<nsISecurityEventSink> eventSink = do_QueryInterface(docShell, &rv); NS_ENSURE_SUCCESS(rv, NS_OK); uint32_t state = 0; nsCOMPtr<nsISecureBrowserUI> securityUI; docShell->GetSecurityUI(getter_AddRefs(securityUI)); if (!securityUI) { return NS_OK; } doc->SetHasTrackingContentBlocked(true); securityUI->GetState(&state); state |= nsIWebProgressListener::STATE_BLOCKED_TRACKING_CONTENT; eventSink->OnSecurityChange(nullptr, state); // Log a warning to the web console. nsCOMPtr<nsIURI> uri; channel->GetURI(getter_AddRefs(uri)); NS_ConvertUTF8toUTF16 spec(uri->GetSpecOrDefault()); const char16_t* params[] = { spec.get() }; nsContentUtils::ReportToConsole(nsIScriptError::warningFlag, NS_LITERAL_CSTRING("Tracking Protection"), doc, nsContentUtils::eNECKO_PROPERTIES, "TrackingUriBlocked", params, ArrayLength(params)); return NS_OK; }
static void ProxiedAuthCallback(gconstpointer in, gsize in_size, gpointer out, gsize out_size, gpointer callback_data) { GnomeVFSModuleCallbackAuthenticationIn *authIn = (GnomeVFSModuleCallbackAuthenticationIn *) in; GnomeVFSModuleCallbackAuthenticationOut *authOut = (GnomeVFSModuleCallbackAuthenticationOut *) out; LOG(("gnomevfs: ProxiedAuthCallback [uri=%s]\n", authIn->uri)); // Without a channel, we have no way of getting a prompter. nsIChannel *channel = (nsIChannel *) callback_data; if (!channel) return; nsCOMPtr<nsIAuthPrompt> prompt; NS_QueryNotificationCallbacks(channel, prompt); // If no auth prompt, then give up. We could failover to using the // WindowWatcher service, but that might defeat a consumer's purposeful // attempt to disable authentication (for whatever reason). if (!prompt) return; // Parse out the host and port... nsCOMPtr<nsIURI> uri; channel->GetURI(getter_AddRefs(uri)); if (!uri) return; #ifdef DEBUG { // // Make sure authIn->uri is consistent with the channel's URI. // // XXX This check is probably not IDN safe, and it might incorrectly // fire as a result of escaping differences. It's unclear what // kind of transforms GnomeVFS might have applied to the URI spec // that we originally gave to it. In spite of the likelihood of // false hits, this check is probably still valuable. // nsAutoCString spec; uri->GetSpec(spec); int uriLen = strlen(authIn->uri); if (!StringHead(spec, uriLen).Equals(nsDependentCString(authIn->uri, uriLen))) { LOG(("gnomevfs: [spec=%s authIn->uri=%s]\n", spec.get(), authIn->uri)); NS_ERROR("URI mismatch"); } } #endif nsAutoCString scheme, hostPort; uri->GetScheme(scheme); uri->GetHostPort(hostPort); // It doesn't make sense for either of these strings to be empty. What kind // of funky URI is this? if (scheme.IsEmpty() || hostPort.IsEmpty()) return; // Construct the single signon key. Altering the value of this key will // cause people's remembered passwords to be forgotten. Think carefully // before changing the way this key is constructed. nsAutoString key, realm; NS_ConvertUTF8toUTF16 dispHost(scheme); dispHost.AppendLiteral("://"); dispHost.Append(NS_ConvertUTF8toUTF16(hostPort)); key = dispHost; if (authIn->realm) { // We assume the realm string is ASCII. That might be a bogus assumption, // but we have no idea what encoding GnomeVFS is using, so for now we'll // limit ourselves to ISO-Latin-1. XXX What is a better solution? realm.Append('"'); realm.Append(NS_ConvertASCIItoUTF16(authIn->realm)); realm.Append('"'); key.Append(' '); key.Append(realm); } // Construct the message string... // // We use Necko's string bundle here. This code really should be encapsulated // behind some Necko API, after all this code is based closely on the code in // nsHttpChannel.cpp. nsCOMPtr<nsIStringBundleService> bundleSvc = do_GetService(NS_STRINGBUNDLE_CONTRACTID); if (!bundleSvc) return; nsCOMPtr<nsIStringBundle> bundle; bundleSvc->CreateBundle("chrome://global/locale/commonDialogs.properties", getter_AddRefs(bundle)); if (!bundle) return; nsString message; if (!realm.IsEmpty()) { const char16_t *strings[] = { realm.get(), dispHost.get() }; bundle->FormatStringFromName(MOZ_UTF16("EnterUserPasswordForRealm"), strings, 2, getter_Copies(message)); } else { const char16_t *strings[] = { dispHost.get() }; bundle->FormatStringFromName(MOZ_UTF16("EnterUserPasswordFor"), strings, 1, getter_Copies(message)); } if (message.IsEmpty()) return; // Prompt the user... nsresult rv; bool retval = false; char16_t *user = nullptr, *pass = nullptr; rv = prompt->PromptUsernameAndPassword(nullptr, message.get(), key.get(), nsIAuthPrompt::SAVE_PASSWORD_PERMANENTLY, &user, &pass, &retval); if (NS_FAILED(rv)) return; if (!retval || !user || !pass) return; // XXX We need to convert the UTF-16 username and password from our dialog to // strings that GnomeVFS can understand. It's unclear what encoding GnomeVFS // expects, so for now we assume 7-bit ASCII. Hopefully, we can get a better // solution at some point. // One copy is never enough... authOut->username = g_strdup(NS_LossyConvertUTF16toASCII(user).get()); authOut->password = g_strdup(NS_LossyConvertUTF16toASCII(pass).get()); nsMemory::Free(user); nsMemory::Free(pass); }
NS_IMETHODIMP nsCookiePermission::CanSetCookie(nsIURI *aURI, nsIChannel *aChannel, nsICookie2 *aCookie, bool *aIsSession, PRInt64 *aExpiry, bool *aResult) { NS_ASSERTION(aURI, "null uri"); *aResult = kDefaultPolicy; // Lazily initialize ourselves if (!EnsureInitialized()) return NS_ERROR_UNEXPECTED; PRUint32 perm; mPermMgr->TestPermission(aURI, kPermissionType, &perm); switch (perm) { case nsICookiePermission::ACCESS_SESSION: *aIsSession = true; case nsIPermissionManager::ALLOW_ACTION: // ACCESS_ALLOW *aResult = true; break; case nsIPermissionManager::DENY_ACTION: // ACCESS_DENY *aResult = false; break; default: // the permission manager has nothing to say about this cookie - // so, we apply the default prefs to it. NS_ASSERTION(perm == nsIPermissionManager::UNKNOWN_ACTION, "unknown permission"); // now we need to figure out what type of accept policy we're dealing with // if we accept cookies normally, just bail and return if (mCookiesLifetimePolicy == ACCEPT_NORMALLY) { *aResult = true; return NS_OK; } // declare this here since it'll be used in all of the remaining cases PRInt64 currentTime = PR_Now() / PR_USEC_PER_SEC; PRInt64 delta = *aExpiry - currentTime; // check whether the user wants to be prompted if (mCookiesLifetimePolicy == ASK_BEFORE_ACCEPT) { // if it's a session cookie and the user wants to accept these // without asking, or if we are in private browsing mode, just // accept the cookie and return if ((*aIsSession && mCookiesAlwaysAcceptSession) || InPrivateBrowsing()) { *aResult = true; return NS_OK; } // default to rejecting, in case the prompting process fails *aResult = false; nsCAutoString hostPort; aURI->GetHostPort(hostPort); if (!aCookie) { return NS_ERROR_UNEXPECTED; } // If there is no host, use the scheme, and append "://", // to make sure it isn't a host or something. // This is done to make the dialog appear for javascript cookies from // file:// urls, and make the text on it not too weird. (bug 209689) if (hostPort.IsEmpty()) { aURI->GetScheme(hostPort); if (hostPort.IsEmpty()) { // still empty. Just return the default. return NS_OK; } hostPort = hostPort + NS_LITERAL_CSTRING("://"); } // we don't cache the cookiePromptService - it's not used often, so not // worth the memory. nsresult rv; nsCOMPtr<nsICookiePromptService> cookiePromptService = do_GetService(NS_COOKIEPROMPTSERVICE_CONTRACTID, &rv); if (NS_FAILED(rv)) return rv; // try to get a nsIDOMWindow from the channel... nsCOMPtr<nsIDOMWindow> parent; if (aChannel) { nsCOMPtr<nsILoadContext> ctx; NS_QueryNotificationCallbacks(aChannel, ctx); if (ctx) { ctx->GetAssociatedWindow(getter_AddRefs(parent)); } } // get some useful information to present to the user: // whether a previous cookie already exists, and how many cookies this host // has set bool foundCookie = false; PRUint32 countFromHost; nsCOMPtr<nsICookieManager2> cookieManager = do_GetService(NS_COOKIEMANAGER_CONTRACTID, &rv); if (NS_SUCCEEDED(rv)) { nsCAutoString rawHost; aCookie->GetRawHost(rawHost); rv = cookieManager->CountCookiesFromHost(rawHost, &countFromHost); if (NS_SUCCEEDED(rv) && countFromHost > 0) rv = cookieManager->CookieExists(aCookie, &foundCookie); } if (NS_FAILED(rv)) return rv; // check if the cookie we're trying to set is already expired, and return; // but only if there's no previous cookie, because then we need to delete the previous // cookie. we need this check to avoid prompting the user for already-expired cookies. if (!foundCookie && !*aIsSession && delta <= 0) { // the cookie has already expired. accept it, and let the backend figure // out it's expired, so that we get correct logging & notifications. *aResult = true; return rv; } bool rememberDecision = false; PRInt32 dialogRes = nsICookiePromptService::DENY_COOKIE; rv = cookiePromptService->CookieDialog(parent, aCookie, hostPort, countFromHost, foundCookie, &rememberDecision, &dialogRes); if (NS_FAILED(rv)) return rv; *aResult = !!dialogRes; if (dialogRes == nsICookiePromptService::ACCEPT_SESSION_COOKIE) *aIsSession = true; if (rememberDecision) { switch (dialogRes) { case nsICookiePromptService::DENY_COOKIE: mPermMgr->Add(aURI, kPermissionType, (PRUint32) nsIPermissionManager::DENY_ACTION, nsIPermissionManager::EXPIRE_NEVER, 0); break; case nsICookiePromptService::ACCEPT_COOKIE: mPermMgr->Add(aURI, kPermissionType, (PRUint32) nsIPermissionManager::ALLOW_ACTION, nsIPermissionManager::EXPIRE_NEVER, 0); break; case nsICookiePromptService::ACCEPT_SESSION_COOKIE: mPermMgr->Add(aURI, kPermissionType, nsICookiePermission::ACCESS_SESSION, nsIPermissionManager::EXPIRE_NEVER, 0); break; default: break; } } } else { // we're not prompting, so we must be limiting the lifetime somehow // if it's a session cookie, we do nothing if (!*aIsSession && delta > 0) { if (mCookiesLifetimePolicy == ACCEPT_SESSION) { // limit lifetime to session *aIsSession = true; } else if (delta > mCookiesLifetimeSec) { // limit lifetime to specified time *aExpiry = currentTime + mCookiesLifetimeSec; } } } } return NS_OK; }
NS_IMETHODIMP nsCookiePermission::CanAccess(nsIURI *aURI, nsIURI *aFirstURI, nsIChannel *aChannel, nsCookieAccess *aResult) { #ifdef MOZ_MAIL_NEWS // disable cookies in mailnews if user's prefs say so if (mCookiesDisabledForMailNews) { // // try to examine the "app type" of the docshell owning this request. if // we find a docshell in the heirarchy of type APP_TYPE_MAIL, then assume // this URI is being loaded from within mailnews. // // XXX this is a pretty ugly hack at the moment since cookies really // shouldn't have to talk to the docshell directly. ultimately, we want // to talk to some more generic interface, which the docshell would also // implement. but, the basic mechanism here of leveraging the channel's // (or loadgroup's) notification callbacks attribute seems ideal as it // avoids the problem of having to modify all places in the code which // kick off network requests. // PRUint32 appType = nsIDocShell::APP_TYPE_UNKNOWN; if (aChannel) { nsCOMPtr<nsIDocShellTreeItem> item, parent; NS_QueryNotificationCallbacks(aChannel, parent); if (parent) { do { item = parent; nsCOMPtr<nsIDocShell> docshell = do_QueryInterface(item); if (docshell) docshell->GetAppType(&appType); } while (appType != nsIDocShell::APP_TYPE_MAIL && NS_SUCCEEDED(item->GetParent(getter_AddRefs(parent))) && parent); } } if ((appType == nsIDocShell::APP_TYPE_MAIL) || (aFirstURI && IsFromMailNews(aFirstURI)) || IsFromMailNews(aURI)) { *aResult = ACCESS_DENY; return NS_OK; } } #endif // MOZ_MAIL_NEWS // finally, check with permission manager... nsresult rv = mPermMgr->TestPermission(aURI, kPermissionType, (PRUint32 *) aResult); if (NS_SUCCEEDED(rv)) { switch (*aResult) { // if we have one of the publicly-available values, just return it case nsIPermissionManager::UNKNOWN_ACTION: // ACCESS_DEFAULT case nsIPermissionManager::ALLOW_ACTION: // ACCESS_ALLOW case nsIPermissionManager::DENY_ACTION: // ACCESS_DENY break; // ACCESS_SESSION means the cookie can be accepted; the session // downgrade will occur in CanSetCookie(). case nsICookiePermission::ACCESS_SESSION: *aResult = ACCESS_ALLOW; break; // ack, an unknown type! just use the defaults. default: *aResult = ACCESS_DEFAULT; } } return rv; }
nsresult nsGopherChannel::SendRequest() { nsresult rv = NS_OK; // Note - you have to keep this as a class member, because the char input // stream doesn't copy its buffer mRequest.Assign(mSelector); // So, we use the selector as is unless it is a search url if (mType=='7') { // Note that we don't use the "standard" nsIURL parsing stuff here // because the only special character is ?, and its possible to search // for a string containing a #, and so on // XXX - should this find the last or first entry? // '?' is valid in both the search string and the url // so no matter what this does, it may be incorrect // This only affects people codeing the query directly into the URL PRInt32 pos = mRequest.RFindChar('?'); if (pos == -1) { // We require a query string here - if we don't have one, // then we need to ask the user nsCOMPtr<nsIPrompt> prompter; NS_QueryNotificationCallbacks(mCallbacks, mLoadGroup, prompter); if (!prompter) { NS_ERROR("We need a prompter!"); return NS_ERROR_FAILURE; } if (!mStringBundle) { nsCOMPtr<nsIStringBundleService> bundleSvc = do_GetService(NS_STRINGBUNDLE_CONTRACTID, &rv); if (NS_FAILED(rv)) return rv; rv = bundleSvc->CreateBundle(NECKO_MSGS_URL, getter_AddRefs(mStringBundle)); if (NS_FAILED(rv)) return rv; } nsXPIDLString promptTitle; nsXPIDLString promptText; if (mStringBundle) rv = mStringBundle->GetStringFromName(NS_LITERAL_STRING("GopherPromptTitle").get(), getter_Copies(promptTitle)); if (NS_FAILED(rv) || !mStringBundle) promptTitle.AssignLiteral("Search"); if (mStringBundle) rv = mStringBundle->GetStringFromName(NS_LITERAL_STRING("GopherPromptText").get(), getter_Copies(promptText)); if (NS_FAILED(rv) || !mStringBundle) promptText.AssignLiteral("Enter a search term:"); nsXPIDLString search; PRBool res; prompter->Prompt(promptTitle.get(), promptText.get(), getter_Copies(search), NULL, NULL, &res); if (!res || !(*search.get())) return NS_ERROR_FAILURE; mRequest.Append('\t'); AppendUTF16toUTF8(search, mRequest); // XXX Is UTF-8 the right thing? // and update our uri nsCAutoString spec; rv = mUrl->GetAsciiSpec(spec); if (NS_FAILED(rv)) return rv; spec.Append('?'); AppendUTF16toUTF8(search, spec); rv = mUrl->SetSpec(spec); if (NS_FAILED(rv)) return rv; } else { // Just replace it with a tab mRequest.SetCharAt('\t',pos); } } mRequest.Append(CRLF); PR_LOG(gGopherLog,PR_LOG_DEBUG, ("Sending: %s\n", mRequest.get())); // open a buffered, blocking output stream. (it should never block because // the buffer is big enough for our entire request.) nsCOMPtr<nsIOutputStream> output; rv = mTransport->OpenOutputStream(nsITransport::OPEN_BLOCKING, mRequest.Length(), 1, getter_AddRefs(output)); if (NS_FAILED(rv)) return rv; PRUint32 n; rv = output->Write(mRequest.get(), mRequest.Length(), &n); if (NS_FAILED(rv)) return rv; if (n != mRequest.Length()) return NS_ERROR_UNEXPECTED; return NS_OK; }
// Determine if the URI associated with aChannel or any URI of the window // hierarchy associated with the channel is foreign with respect to aSecondURI. // See docs for mozIThirdPartyUtil. NS_IMETHODIMP ThirdPartyUtil::IsThirdPartyChannel(nsIChannel* aChannel, nsIURI* aURI, bool* aResult) { NS_ENSURE_ARG(aChannel); NS_ASSERTION(aResult, "null outparam pointer"); nsresult rv; bool doForce = false; nsCOMPtr<nsIHttpChannelInternal> httpChannelInternal = do_QueryInterface(aChannel); if (httpChannelInternal) { rv = httpChannelInternal->GetForceAllowThirdPartyCookie(&doForce); NS_ENSURE_SUCCESS(rv, rv); // If aURI was not supplied, and we're forcing, then we're by definition // not foreign. If aURI was supplied, we still want to check whether it's // foreign with respect to the channel URI. (The forcing only applies to // whatever window hierarchy exists above the channel.) if (doForce && !aURI) { *aResult = false; return NS_OK; } } // Obtain the URI from the channel, and its base domain. nsCOMPtr<nsIURI> channelURI; aChannel->GetURI(getter_AddRefs(channelURI)); NS_ENSURE_TRUE(channelURI, NS_ERROR_INVALID_ARG); nsCString channelDomain; rv = GetBaseDomain(channelURI, channelDomain); if (NS_FAILED(rv)) return rv; if (aURI) { // Determine whether aURI is foreign with respect to channelURI. bool result; rv = IsThirdPartyInternal(channelDomain, aURI, &result); if (NS_FAILED(rv)) return rv; // If it's foreign, or we're forcing, we're done. if (result || doForce) { *aResult = result; return NS_OK; } } // Find the associated window and its parent window. nsCOMPtr<nsILoadContext> ctx; NS_QueryNotificationCallbacks(aChannel, ctx); if (!ctx) return NS_ERROR_INVALID_ARG; // If there is no window, the consumer kicking off the load didn't provide one // to the channel. This is limited to loads of certain types of resources. If // those loads require cookies, the forceAllowThirdPartyCookie property should // be set on the channel. nsCOMPtr<nsIDOMWindow> ourWin, parentWin; ctx->GetAssociatedWindow(getter_AddRefs(ourWin)); if (!ourWin) return NS_ERROR_INVALID_ARG; // We use GetScriptableParent rather than GetParent because we consider // <iframe mozbrowser/mozapp> to be a top-level frame. ourWin->GetScriptableParent(getter_AddRefs(parentWin)); NS_ENSURE_TRUE(parentWin, NS_ERROR_INVALID_ARG); // Check whether this is the document channel for this window (representing a // load of a new page). In that situation we want to avoid comparing // channelURI to ourWin, since what's in ourWin right now will be replaced as // the channel loads. This covers the case of a freshly kicked-off load // (e.g. the user typing something in the location bar, or clicking on a // bookmark), where the window's URI hasn't yet been set, and will be bogus. // It also covers situations where a subframe is navigated to someting that // is same-origin with all its ancestors. This is a bit of a nasty hack, but // we will hopefully flag these channels better later. nsLoadFlags flags; rv = aChannel->GetLoadFlags(&flags); NS_ENSURE_SUCCESS(rv, rv); if (flags & nsIChannel::LOAD_DOCUMENT_URI) { if (SameCOMIdentity(ourWin, parentWin)) { // We only need to compare aURI to the channel URI -- the window's will be // bogus. We already know the answer. *aResult = false; return NS_OK; } // Make sure to still compare to ourWin's ancestors ourWin = parentWin; } // Check the window hierarchy. This covers most cases for an ordinary page // load from the location bar. return IsThirdPartyWindow(ourWin, channelURI, aResult); }
NS_IMETHODIMP nsBaseChannel::GetInterface(const nsIID &iid, void **result) { NS_QueryNotificationCallbacks(mCallbacks, mLoadGroup, iid, result); return *result ? NS_OK : NS_ERROR_NO_INTERFACE; }
NS_IMETHODIMP nsCookiePermission::GetOriginatingURI(nsIChannel *aChannel, nsIURI **aURI) { /* to find the originating URI, we use the loadgroup of the channel to obtain * the window owning the load, and from there, we find the top same-type * window and its URI. there are several possible cases: * * 1) no channel. * * 2) a channel with the "force allow third party cookies" option set. * since we may not have a window, we return the channel URI in this case. * * 3) a channel, but no window. this can occur when the consumer kicking * off the load doesn't provide one to the channel, and should be limited * to loads of certain types of resources. * * 4) a window equal to the top window of same type, with the channel its * document channel. this covers the case of a freshly kicked-off load * (e.g. the user typing something in the location bar, or clicking on a * bookmark), where the window's URI hasn't yet been set, and will be * bogus. we return the channel URI in this case. * * 5) Anything else. this covers most cases for an ordinary page load from * the location bar, and will catch nested frames within a page, image * loads, etc. we return the URI of the root window's document's principal * in this case. */ *aURI = nullptr; // case 1) if (!aChannel) return NS_ERROR_NULL_POINTER; // case 2) nsCOMPtr<nsIHttpChannelInternal> httpChannelInternal = do_QueryInterface(aChannel); if (httpChannelInternal) { bool doForce = false; if (NS_SUCCEEDED(httpChannelInternal->GetForceAllowThirdPartyCookie(&doForce)) && doForce) { // return the channel's URI (we may not have a window) aChannel->GetURI(aURI); if (!*aURI) return NS_ERROR_NULL_POINTER; return NS_OK; } } // find the associated window and its top window nsCOMPtr<nsILoadContext> ctx; NS_QueryNotificationCallbacks(aChannel, ctx); nsCOMPtr<nsIDOMWindow> topWin, ourWin; if (ctx) { ctx->GetTopWindow(getter_AddRefs(topWin)); ctx->GetAssociatedWindow(getter_AddRefs(ourWin)); } // case 3) if (!topWin) return NS_ERROR_INVALID_ARG; // case 4) if (ourWin == topWin) { // Check whether this is the document channel for this window (representing // a load of a new page). This is a bit of a nasty hack, but we will // hopefully flag these channels better later. nsLoadFlags flags; aChannel->GetLoadFlags(&flags); if (flags & nsIChannel::LOAD_DOCUMENT_URI) { // get the channel URI - the window's will be bogus aChannel->GetURI(aURI); if (!*aURI) return NS_ERROR_NULL_POINTER; return NS_OK; } } // case 5) - get the originating URI from the top window's principal nsCOMPtr<nsIScriptObjectPrincipal> scriptObjPrin = do_QueryInterface(topWin); NS_ENSURE_TRUE(scriptObjPrin, NS_ERROR_UNEXPECTED); nsIPrincipal* prin = scriptObjPrin->GetPrincipal(); NS_ENSURE_TRUE(prin, NS_ERROR_UNEXPECTED); prin->GetURI(aURI); if (!*aURI) return NS_ERROR_NULL_POINTER; // all done! return NS_OK; }