nsresult nsDOMMenuBar::GetChromeDocument(nsIDOMDocument** _retval) { NS_ENSURE_STATE(mWindow); nsresult rv; nsCOMPtr<nsIWebNavigation> webNav(do_GetInterface(mWindow, &rv)); NS_ENSURE_SUCCESS(rv, rv); nsCOMPtr<nsIDocShellTreeItem> treeItem(do_QueryInterface(webNav, &rv)); NS_ENSURE_SUCCESS(rv, rv); nsCOMPtr<nsIDocShellTreeItem> rootItem; rv = treeItem->GetRootTreeItem(getter_AddRefs(rootItem)); NS_ENSURE_SUCCESS(rv, rv); nsCOMPtr<nsIDOMWindow> chromeWindow(do_GetInterface(rootItem, &rv)); NS_ENSURE_SUCCESS(rv, rv); return chromeWindow->GetDocument(_retval); }
nsresult nsLocation::SetURI(nsIURI* aURI, bool aReplace) { nsCOMPtr<nsIDocShell> docShell(do_QueryReferent(mDocShell)); if (docShell) { nsCOMPtr<nsIDocShellLoadInfo> loadInfo; nsCOMPtr<nsIWebNavigation> webNav(do_QueryInterface(docShell)); if(NS_FAILED(CheckURL(aURI, getter_AddRefs(loadInfo)))) return NS_ERROR_FAILURE; if (aReplace) { loadInfo->SetLoadType(nsIDocShellLoadInfo::loadStopContentAndReplace); } else { loadInfo->SetLoadType(nsIDocShellLoadInfo::loadStopContent); } return docShell->LoadURI(aURI, loadInfo, nsIWebNavigation::LOAD_FLAGS_NONE, true); } return NS_OK; }
nsresult Location::GetURI(nsIURI** aURI, bool aGetInnermostURI) { *aURI = nullptr; nsresult rv; nsCOMPtr<nsIDocShell> docShell(do_QueryReferent(mDocShell)); nsCOMPtr<nsIWebNavigation> webNav(do_QueryInterface(docShell, &rv)); if (NS_FAILED(rv)) { return rv; } nsCOMPtr<nsIURI> uri; rv = webNav->GetCurrentURI(getter_AddRefs(uri)); NS_ENSURE_SUCCESS(rv, rv); // It is valid for docshell to return a null URI. Don't try to fixup // if this happens. if (!uri) { return NS_OK; } if (aGetInnermostURI) { nsCOMPtr<nsIJARURI> jarURI(do_QueryInterface(uri)); while (jarURI) { jarURI->GetJARFile(getter_AddRefs(uri)); jarURI = do_QueryInterface(uri); } } NS_ASSERTION(uri, "nsJARURI screwed up?"); nsCOMPtr<nsIURIFixup> urifixup(do_GetService(NS_URIFIXUP_CONTRACTID, &rv)); NS_ENSURE_SUCCESS(rv, rv); return urifixup->CreateExposableURI(uri, aURI); }
/* boolean canHandleContent (in string aContentType, in PRBool aIsContentPreferred, out string aDesiredContentType); */ NS_IMETHODIMP CWebBrowserContainer::CanHandleContent(const char *aContentType, PRBool aIsContentPreferred, char **aDesiredContentType, PRBool *_retval) { *_retval = PR_FALSE; *aDesiredContentType = nsnull; if (aContentType) { nsCOMPtr<nsIWebNavigation> webNav(do_QueryInterface(mOwner->mWebBrowser)); nsCOMPtr<nsIWebNavigationInfo> webNavInfo( do_GetService("@mozilla.org/webnavigation-info;1")); if (webNavInfo) { PRUint32 canHandle; nsresult rv = webNavInfo->IsTypeSupported(nsDependentCString(aContentType), webNav, &canHandle); NS_ENSURE_SUCCESS(rv, rv); *_retval = (canHandle != nsIWebNavigationInfo::UNSUPPORTED); } } return NS_OK; }
// Check if X-Frame-Options permits this document to be loaded as a subdocument. bool nsDSURIContentListener::CheckFrameOptions(nsIRequest* request) { nsCAutoString xfoHeaderValue; nsCOMPtr<nsIHttpChannel> httpChannel = do_QueryInterface(request); if (!httpChannel) { return true; } httpChannel->GetResponseHeader(NS_LITERAL_CSTRING("X-Frame-Options"), xfoHeaderValue); // return early if header does not have one of the two values with meaning if (!xfoHeaderValue.LowerCaseEqualsLiteral("deny") && !xfoHeaderValue.LowerCaseEqualsLiteral("sameorigin")) return true; if (mDocShell) { // We need to check the location of this window and the location of the top // window, if we're not the top. X-F-O: SAMEORIGIN requires that the // document must be same-origin with top window. X-F-O: DENY requires that // the document must never be framed. nsCOMPtr<nsIDOMWindow> thisWindow = do_GetInterface(static_cast<nsIDocShell*>(mDocShell)); // If we don't have DOMWindow there is no risk of clickjacking if (!thisWindow) return true; nsCOMPtr<nsIDOMWindow> topWindow; thisWindow->GetTop(getter_AddRefs(topWindow)); // if the document is in the top window, it's not in a frame. if (thisWindow == topWindow) return true; // Find the top docshell in our parent chain that doesn't have the system // principal and use it for the principal comparison. Finding the top // content-type docshell doesn't work because some chrome documents are // loaded in content docshells (see bug 593387). nsCOMPtr<nsIDocShellTreeItem> thisDocShellItem(do_QueryInterface( static_cast<nsIDocShell*> (mDocShell))); nsCOMPtr<nsIDocShellTreeItem> parentDocShellItem, curDocShellItem = thisDocShellItem; nsCOMPtr<nsIDocument> topDoc; nsresult rv; nsCOMPtr<nsIScriptSecurityManager> ssm = do_GetService(NS_SCRIPTSECURITYMANAGER_CONTRACTID, &rv); if (!ssm) return false; // Traverse up the parent chain to the top docshell that doesn't have // a system principal while (NS_SUCCEEDED(curDocShellItem->GetParent(getter_AddRefs(parentDocShellItem))) && parentDocShellItem) { bool system = false; topDoc = do_GetInterface(parentDocShellItem); if (topDoc) { if (NS_SUCCEEDED(ssm->IsSystemPrincipal(topDoc->NodePrincipal(), &system)) && system) { break; } } else { return false; } curDocShellItem = parentDocShellItem; } // If this document has the top non-SystemPrincipal docshell it is not being // framed or it is being framed by a chrome document, which we allow. if (curDocShellItem == thisDocShellItem) return true; // If the X-Frame-Options value is SAMEORIGIN, then the top frame in the // parent chain must be from the same origin as this document. if (xfoHeaderValue.LowerCaseEqualsLiteral("sameorigin")) { nsCOMPtr<nsIURI> uri; httpChannel->GetURI(getter_AddRefs(uri)); topDoc = do_GetInterface(curDocShellItem); nsCOMPtr<nsIURI> topUri; topDoc->NodePrincipal()->GetURI(getter_AddRefs(topUri)); rv = ssm->CheckSameOriginURI(uri, topUri, PR_TRUE); if (NS_SUCCEEDED(rv)) return true; } else { // If the value of the header is DENY, then the document // should never be permitted to load as a subdocument. NS_ASSERTION(xfoHeaderValue.LowerCaseEqualsLiteral("deny"), "How did we get here with some random header value?"); } // cancel the load and display about:blank httpChannel->Cancel(NS_BINDING_ABORTED); nsCOMPtr<nsIWebNavigation> webNav(do_QueryObject(mDocShell)); if (webNav) { webNav->LoadURI(NS_LITERAL_STRING("about:blank").get(), 0, nsnull, nsnull, nsnull); } return false; } return true; }
/* void onStateChange (in nsIWebProgress aWebProgress, in nsIRequest request, in unsigned long progressStateFlags, in unsinged long aStatus); */ NS_IMETHODIMP CWebBrowserContainer::OnStateChange(nsIWebProgress* aWebProgress, nsIRequest *aRequest, PRUint32 progressStateFlags, nsresult aStatus) { nsresult rv = NS_OK; NG_TRACE(_T("CWebBrowserContainer::OnStateChange(...)\n")); BOOL doFireCommandStateChange = FALSE; // determine whether or not the document load has started or stopped. if (progressStateFlags & STATE_IS_DOCUMENT) { if (progressStateFlags & STATE_START) { NG_TRACE(_T("CWebBrowserContainer::OnStateChange->Doc Start(..., \"\")\n")); nsCOMPtr<nsIChannel> channel(do_QueryInterface(aRequest)); if (channel) { nsCOMPtr<nsIURI> uri; rv = channel->GetURI(getter_AddRefs(uri)); if (NS_SUCCEEDED(rv)) { nsCAutoString aURI; uri->GetAsciiSpec(aURI); NG_TRACE(_T("CWebBrowserContainer::OnStateChange->Doc Start(..., %s, \"\")\n"), A2CT(aURI.get())); } } //Fire a DownloadBegin mEvents1->Fire_DownloadBegin(); mEvents2->Fire_DownloadBegin(); } else if (progressStateFlags & STATE_STOP) { NG_TRACE(_T("CWebBrowserContainer::OnStateChange->Doc Stop(..., \"\")\n")); if (mOwner->mIERootDocument) { // allow to keep old document around mOwner->mIERootDocument->Release(); mOwner->mIERootDocument = NULL; } //Fire a DownloadComplete mEvents1->Fire_DownloadComplete(); mEvents2->Fire_DownloadComplete(); nsCOMPtr<nsIURI> pURI; nsCOMPtr<nsIChannel> aChannel = do_QueryInterface(aRequest); if (!aChannel) return NS_ERROR_NULL_POINTER; rv = aChannel->GetURI(getter_AddRefs(pURI)); if (NS_FAILED(rv)) return NS_OK; nsCAutoString aURI; rv = pURI->GetAsciiSpec(aURI); if (NS_FAILED(rv)) return NS_OK; USES_CONVERSION; BSTR bstrURI = SysAllocString(A2OLE(aURI.get())); // Fire a DocumentComplete event CComVariant vURI(bstrURI); mEvents2->Fire_DocumentComplete(mOwner, &vURI); SysFreeString(bstrURI); //Fire a StatusTextChange event BSTR bstrStatus = SysAllocString(A2OLE((CHAR *) "Done")); mEvents1->Fire_StatusTextChange(bstrStatus); mEvents2->Fire_StatusTextChange(bstrStatus); SysFreeString(bstrStatus); } // state change notifications doFireCommandStateChange = TRUE; } if (progressStateFlags & STATE_IS_NETWORK) { if (progressStateFlags & STATE_START) { } if (progressStateFlags & STATE_STOP) { nsCAutoString aURI; if (mCurrentURI) { mCurrentURI->GetAsciiSpec(aURI); } // Fire a NavigateComplete event USES_CONVERSION; BSTR bstrURI = SysAllocString(A2OLE(aURI.get())); mEvents1->Fire_NavigateComplete(bstrURI); // Fire a NavigateComplete2 event CComVariant vURI(bstrURI); mEvents2->Fire_NavigateComplete2(mOwner, &vURI); // Cleanup SysFreeString(bstrURI); mOwner->mBusyFlag = FALSE; mCurrentURI = nsnull; } } if (doFireCommandStateChange) { nsCOMPtr<nsIWebNavigation> webNav(do_QueryInterface(mOwner->mWebBrowser)); // Fire the new NavigateForward state VARIANT_BOOL bEnableForward = VARIANT_FALSE; PRBool aCanGoForward = PR_FALSE; webNav->GetCanGoForward(&aCanGoForward); if (aCanGoForward == PR_TRUE) { bEnableForward = VARIANT_TRUE; } mEvents2->Fire_CommandStateChange(CSC_NAVIGATEFORWARD, bEnableForward); // Fire the new NavigateBack state VARIANT_BOOL bEnableBack = VARIANT_FALSE; PRBool aCanGoBack = PR_FALSE; webNav->GetCanGoBack(&aCanGoBack); if (aCanGoBack == PR_TRUE) { bEnableBack = VARIANT_TRUE; } mEvents2->Fire_CommandStateChange(CSC_NAVIGATEBACK, bEnableBack); } return NS_OK; }
nsresult nsWebShellWindow::Initialize(nsIXULWindow* aParent, nsIAppShell* aShell, nsIURI* aUrl, PRInt32 aInitialWidth, PRInt32 aInitialHeight, PRBool aIsHiddenWindow, nsWidgetInitData& widgetInitData) { nsresult rv; nsCOMPtr<nsIWidget> parentWidget; mIsHiddenWindow = aIsHiddenWindow; // XXX: need to get the default window size from prefs... // Doesn't come from prefs... will come from CSS/XUL/RDF nsRect r(0, 0, aInitialWidth, aInitialHeight); // Create top level window mWindow = do_CreateInstance(kWindowCID, &rv); if (NS_OK != rv) { return rv; } /* This next bit is troublesome. We carry two different versions of a pointer to our parent window. One is the parent window's widget, which is passed to our own widget. The other is a weak reference we keep here to our parent WebShellWindow. The former is useful to the widget, and we can't trust its treatment of the parent reference because they're platform- specific. The latter is useful to this class. A better implementation would be one in which the parent keeps strong references to its children and closes them before it allows itself to be closed. This would mimic the behaviour of OSes that support top-level child windows in OSes that do not. Later. */ nsCOMPtr<nsIBaseWindow> parentAsWin(do_QueryInterface(aParent)); if (parentAsWin) { parentAsWin->GetMainWidget(getter_AddRefs(parentWidget)); mParentWindow = do_GetWeakReference(aParent); } mWindow->SetClientData(this); mWindow->Create((nsIWidget *)parentWidget, // Parent nsIWidget r, // Widget dimensions nsWebShellWindow::HandleEvent, // Event handler function nsnull, // Device context aShell, // Application shell nsnull, // nsIToolkit &widgetInitData); // Widget initialization data mWindow->GetClientBounds(r); mWindow->SetBackgroundColor(NS_RGB(192,192,192)); // Create web shell mDocShell = do_CreateInstance("@mozilla.org/webshell;1"); NS_ENSURE_TRUE(mDocShell, NS_ERROR_FAILURE); // Make sure to set the item type on the docshell _before_ calling // Create() so it knows what type it is. nsCOMPtr<nsIDocShellTreeItem> docShellAsItem(do_QueryInterface(mDocShell)); NS_ENSURE_TRUE(docShellAsItem, NS_ERROR_FAILURE); NS_ENSURE_SUCCESS(EnsureChromeTreeOwner(), NS_ERROR_FAILURE); docShellAsItem->SetTreeOwner(mChromeTreeOwner); docShellAsItem->SetItemType(nsIDocShellTreeItem::typeChrome); r.x = r.y = 0; nsCOMPtr<nsIBaseWindow> docShellAsWin(do_QueryInterface(mDocShell)); NS_ENSURE_SUCCESS(docShellAsWin->InitWindow(nsnull, mWindow, r.x, r.y, r.width, r.height), NS_ERROR_FAILURE); NS_ENSURE_SUCCESS(docShellAsWin->Create(), NS_ERROR_FAILURE); // Attach a WebProgress listener.during initialization... nsCOMPtr<nsIWebProgress> webProgress(do_GetInterface(mDocShell, &rv)); if (webProgress) { webProgress->AddProgressListener(this, nsIWebProgress::NOTIFY_STATE_NETWORK); } if (nsnull != aUrl) { nsCAutoString tmpStr; rv = aUrl->GetSpec(tmpStr); if (NS_FAILED(rv)) return rv; NS_ConvertUTF8toUCS2 urlString(tmpStr); nsCOMPtr<nsIWebNavigation> webNav(do_QueryInterface(mDocShell)); NS_ENSURE_TRUE(webNav, NS_ERROR_FAILURE); rv = webNav->LoadURI(urlString.get(), nsIWebNavigation::LOAD_FLAGS_NONE, nsnull, nsnull, nsnull); NS_ENSURE_SUCCESS(rv, rv); } return rv; }
// if the main document URL specified URLs for any content areas, start them loading void nsWebShellWindow::LoadContentAreas() { nsAutoString searchSpec; // fetch the chrome document URL nsCOMPtr<nsIContentViewer> contentViewer; // yes, it's possible for the docshell to be null even this early // see bug 57514. if (mDocShell) mDocShell->GetContentViewer(getter_AddRefs(contentViewer)); if (contentViewer) { nsIDocument* doc = contentViewer->GetDocument(); if (doc) { nsIURI* mainURL = doc->GetDocumentURI(); nsCOMPtr<nsIURL> url = do_QueryInterface(mainURL); if (url) { nsCAutoString search; url->GetQuery(search); AppendUTF8toUTF16(search, searchSpec); } } } // content URLs are specified in the search part of the URL // as <contentareaID>=<escapedURL>[;(repeat)] if (!searchSpec.IsEmpty()) { PRInt32 begPos, eqPos, endPos; nsString contentAreaID, contentURL; char *urlChar; nsresult rv; for (endPos = 0; endPos < (PRInt32)searchSpec.Length(); ) { // extract contentAreaID and URL substrings begPos = endPos; eqPos = searchSpec.FindChar('=', begPos); if (eqPos < 0) break; endPos = searchSpec.FindChar(';', eqPos); if (endPos < 0) endPos = searchSpec.Length(); searchSpec.Mid(contentAreaID, begPos, eqPos-begPos); searchSpec.Mid(contentURL, eqPos+1, endPos-eqPos-1); endPos++; // see if we have a docshell with a matching contentAreaID nsCOMPtr<nsIDocShellTreeItem> content; rv = GetContentShellById(contentAreaID.get(), getter_AddRefs(content)); if (NS_SUCCEEDED(rv) && content) { nsCOMPtr<nsIWebNavigation> webNav(do_QueryInterface(content)); if (webNav) { urlChar = ToNewCString(contentURL); if (urlChar) { nsUnescape(urlChar); contentURL.AssignWithConversion(urlChar); webNav->LoadURI(contentURL.get(), nsIWebNavigation::LOAD_FLAGS_NONE, nsnull, nsnull, nsnull); nsMemory::Free(urlChar); } } } } } }