/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ /* ***** BEGIN LICENSE BLOCK ***** * Version: MPL 1.1/GPL 2.0/LGPL 2.1 * * The contents of this file are subject to the Mozilla Public License Version * 1.1 (the "License"); you may not use this file except in compliance with * the License. You may obtain a copy of the License at * http://www.mozilla.org/MPL/ * * Software distributed under the License is distributed on an "AS IS" basis, * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License * for the specific language governing rights and limitations under the * License. * * The Original Code is mozilla.org code. * * The Initial Developer of the Original Code is * Netscape Communications Corporation. * Portions created by the Initial Developer are Copyright (C) 1998 * the Initial Developer. All Rights Reserved. * * Contributor(s): * Adam Lock * * Alternatively, the contents of this file may be used under the terms of * either the GNU General Public License Version 2 or later (the "GPL"), or * the GNU Lesser General Public License Version 2.1 or later (the "LGPL"), * in which case the provisions of the GPL or the LGPL are applicable instead * of those above. If you wish to allow use of your version of this file only * under the terms of either the GPL or the LGPL, and not to allow others to * use your version of this file under the terms of the MPL, indicate your * decision by deleting the provisions above and replace them with the notice * and other provisions required by the GPL or the LGPL. If you do not delete * the provisions above, a recipient may use your version of this file under * the terms of any one of the MPL, the GPL or the LGPL. * * ***** END LICENSE BLOCK ***** */ #include "stdafx.h" #include #include #include "WebBrowserContainer.h" #include "nsServiceManagerUtils.h" #include "nsIWebNavigationInfo.h" CWebBrowserContainer::CWebBrowserContainer(CMozillaBrowser *pOwner) : mOwner(pOwner), mEvents1(mOwner), mEvents2(mOwner), mVisible(PR_TRUE) { } CWebBrowserContainer::~CWebBrowserContainer() { } /////////////////////////////////////////////////////////////////////////////// // nsISupports implementation NS_IMPL_ADDREF(CWebBrowserContainer) NS_IMPL_RELEASE(CWebBrowserContainer) NS_INTERFACE_MAP_BEGIN(CWebBrowserContainer) NS_INTERFACE_MAP_ENTRY_AMBIGUOUS(nsISupports, nsIWebBrowserChrome) NS_INTERFACE_MAP_ENTRY(nsIInterfaceRequestor) NS_INTERFACE_MAP_ENTRY(nsIWebBrowserChrome) NS_INTERFACE_MAP_ENTRY(nsIURIContentListener) NS_INTERFACE_MAP_ENTRY(nsIEmbeddingSiteWindow) NS_INTERFACE_MAP_ENTRY(nsIEmbeddingSiteWindow2) NS_INTERFACE_MAP_ENTRY(nsIRequestObserver) NS_INTERFACE_MAP_ENTRY(nsIWebProgressListener) NS_INTERFACE_MAP_ENTRY(nsIContextMenuListener) NS_INTERFACE_MAP_ENTRY(nsIWebBrowserChromeFocus) // NS_INTERFACE_MAP_ENTRY(nsICommandHandler) NS_INTERFACE_MAP_ENTRY(nsISupportsWeakReference) NS_INTERFACE_MAP_END /////////////////////////////////////////////////////////////////////////////// // nsIInterfaceRequestor NS_IMETHODIMP CWebBrowserContainer::GetInterface(const nsIID & aIID, void * *result) { *result = 0; if (aIID.Equals(NS_GET_IID(nsIDOMWindow))) { if (mOwner && mOwner->mWebBrowser) { return mOwner->mWebBrowser->GetContentDOMWindow((nsIDOMWindow **) result); } return NS_ERROR_NOT_INITIALIZED; } return QueryInterface(aIID, result); } /////////////////////////////////////////////////////////////////////////////// // nsIContextMenuListener NS_IMETHODIMP CWebBrowserContainer::OnShowContextMenu(PRUint32 aContextFlags, nsIDOMEvent *aEvent, nsIDOMNode *aNode) { mOwner->ShowContextMenu(aContextFlags, aEvent, aNode); return NS_OK; } /////////////////////////////////////////////////////////////////////////////// // nsIWebProgressListener /* void onProgressChange (in nsIWebProgress aProgress, in nsIRequest aRequest, in long curSelfProgress, in long maxSelfProgress, in long curTotalProgress, in long maxTotalProgress); */ NS_IMETHODIMP CWebBrowserContainer::OnProgressChange(nsIWebProgress *aProgress, nsIRequest *aRequest, PRInt32 curSelfProgress, PRInt32 maxSelfProgress, PRInt32 curTotalProgress, PRInt32 maxTotalProgress) { NG_TRACE(_T("CWebBrowserContainer::OnProgressChange(...)\n")); long nProgress = curTotalProgress; long nProgressMax = maxTotalProgress; if (nProgress == 0) { } if (nProgressMax == 0) { nProgressMax = LONG_MAX; } if (nProgress > nProgressMax) { nProgress = nProgressMax; // Progress complete } mEvents1->Fire_ProgressChange(nProgress, nProgressMax); mEvents2->Fire_ProgressChange(nProgress, nProgressMax); return NS_OK; } /* 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 channel(do_QueryInterface(aRequest)); if (channel) { nsCOMPtr 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 pURI; nsCOMPtr 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 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; } /* void onLocationChange (in nsIURI location); */ NS_IMETHODIMP CWebBrowserContainer::OnLocationChange(nsIWebProgress* aWebProgress, nsIRequest* aRequest, nsIURI *location) { // nsCString aPath; // location->GetPath(getter_Copies(aPath)); return NS_OK; } NS_IMETHODIMP CWebBrowserContainer::OnStatusChange(nsIWebProgress* aWebProgress, nsIRequest* aRequest, nsresult aStatus, const PRUnichar* aMessage) { NG_TRACE(_T("CWebBrowserContainer::OnStatusChange(..., \"\")\n")); BSTR bstrStatus = SysAllocString(W2OLE((PRUnichar *) aMessage)); mEvents1->Fire_StatusTextChange(bstrStatus); mEvents2->Fire_StatusTextChange(bstrStatus); SysFreeString(bstrStatus); return NS_OK; } NS_IMETHODIMP CWebBrowserContainer::OnSecurityChange(nsIWebProgress *aWebProgress, nsIRequest *aRequest, PRUint32 state) { return NS_OK; } /////////////////////////////////////////////////////////////////////////////// // nsIURIContentListener /* void onStartURIOpen (in nsIURI aURI, out boolean aAbortOpen); */ NS_IMETHODIMP CWebBrowserContainer::OnStartURIOpen(nsIURI *pURI, PRBool *aAbortOpen) { USES_CONVERSION; NG_TRACE(_T("CWebBrowserContainer::OnStartURIOpen(...)\n")); mCurrentURI = pURI; NG_ASSERT(mCurrentURI); nsCAutoString aURI; mCurrentURI->GetSpec(aURI); // Setup the post data CComVariant vPostDataRef; CComVariant vPostData; vPostDataRef.vt = VT_BYREF | VT_VARIANT; vPostDataRef.pvarVal = &vPostData; // TODO get the post data passed in via the original call to Navigate() // Fire a BeforeNavigate event BSTR bstrURI = SysAllocString(A2OLE(aURI.get())); BSTR bstrTargetFrameName = NULL; BSTR bstrHeaders = NULL; VARIANT_BOOL bCancel = VARIANT_FALSE; long lFlags = 0; mEvents1->Fire_BeforeNavigate(bstrURI, lFlags, bstrTargetFrameName, &vPostDataRef, bstrHeaders, &bCancel); // Fire a BeforeNavigate2 event CComVariant vURI(bstrURI); CComVariant vFlags(lFlags); CComVariant vTargetFrameName(bstrTargetFrameName); CComVariant vHeaders(bstrHeaders); mEvents2->Fire_BeforeNavigate2(mOwner, &vURI, &vFlags, &vTargetFrameName, &vPostDataRef, &vHeaders, &bCancel); // Cleanup SysFreeString(bstrURI); SysFreeString(bstrTargetFrameName); SysFreeString(bstrHeaders); if (bCancel != VARIANT_FALSE) { *aAbortOpen = PR_TRUE; return NS_ERROR_ABORT; } else { mOwner->mBusyFlag = TRUE; } //NOTE: The IE control fires a DownloadBegin after the first BeforeNavigate. // It then fires a DownloadComplete after the engine has made it's // initial connection to the server. It then fires a second // DownloadBegin/DownloadComplete pair around the loading of // everything on the page. These events get fired out of // CWebBrowserContainer::StartDocumentLoad() and // CWebBrowserContainer::EndDocumentLoad(). // We don't appear to distinguish between the initial connection to // the server and the actual transfer of data. Firing these events // here simulates, appeasing applications that are expecting that // initial pair. mEvents1->Fire_DownloadBegin(); mEvents2->Fire_DownloadBegin(); mEvents1->Fire_DownloadComplete(); mEvents2->Fire_DownloadComplete(); return NS_OK; } /* void doContent (in string aContentType, in boolean aIsContentPreferred, in nsIRequest request, out nsIStreamListener aContentHandler, out boolean aAbortProcess); */ NS_IMETHODIMP CWebBrowserContainer::DoContent(const char *aContentType, PRBool aIsContentPreferred, nsIRequest *request, nsIStreamListener **aContentHandler, PRBool *aAbortProcess) { return NS_ERROR_NOT_IMPLEMENTED; } /* boolean isPreferred (in string aContentType, out string aDesiredContentType); */ NS_IMETHODIMP CWebBrowserContainer::IsPreferred(const char *aContentType, char **aDesiredContentType, PRBool *_retval) { return CanHandleContent(aContentType, PR_TRUE, aDesiredContentType, _retval); } /* 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 webNav(do_QueryInterface(mOwner->mWebBrowser)); nsCOMPtr 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; } /* attribute nsISupports loadCookie; */ NS_IMETHODIMP CWebBrowserContainer::GetLoadCookie(nsISupports * *aLoadCookie) { return NS_ERROR_NOT_IMPLEMENTED; } NS_IMETHODIMP CWebBrowserContainer::SetLoadCookie(nsISupports * aLoadCookie) { return NS_ERROR_NOT_IMPLEMENTED; } /* attribute nsIURIContentListener parentContentListener; */ NS_IMETHODIMP CWebBrowserContainer::GetParentContentListener(nsIURIContentListener * *aParentContentListener) { return NS_ERROR_NOT_IMPLEMENTED; } NS_IMETHODIMP CWebBrowserContainer::SetParentContentListener(nsIURIContentListener * aParentContentListener) { return NS_ERROR_NOT_IMPLEMENTED; } /////////////////////////////////////////////////////////////////////////////// // nsIEmbeddingSiteWindow NS_IMETHODIMP CWebBrowserContainer::GetDimensions(PRUint32 aFlags, PRInt32 *x, PRInt32 *y, PRInt32 *cx, PRInt32 *cy) { RECT rc = { 0, 0, 1, 1 }; mOwner->GetClientRect(&rc); if (aFlags & nsIEmbeddingSiteWindow::DIM_FLAGS_POSITION) { if (*x) *x = rc.left; if (*y) *y = rc.top; } if (aFlags & nsIEmbeddingSiteWindow::DIM_FLAGS_SIZE_INNER || aFlags & nsIEmbeddingSiteWindow::DIM_FLAGS_SIZE_OUTER) { if (*cx) *cx = rc.right - rc.left; if (*cy) *cy = rc.bottom - rc.top; } return NS_OK; } NS_IMETHODIMP CWebBrowserContainer::SetDimensions(PRUint32 aFlags, PRInt32 x, PRInt32 y, PRInt32 cx, PRInt32 cy) { // Ignore return NS_OK; } NS_IMETHODIMP CWebBrowserContainer::GetSiteWindow(void **aParentNativeWindow) { NS_ENSURE_ARG_POINTER(aParentNativeWindow); HWND *hwndDest = (HWND *) aParentNativeWindow; *hwndDest = mOwner->m_hWnd; return NS_OK; } NS_IMETHODIMP CWebBrowserContainer::SetFocus(void) { return NS_OK; } NS_IMETHODIMP CWebBrowserContainer::GetTitle(PRUnichar * *aTitle) { NG_ASSERT_POINTER(aTitle, PRUnichar **); if (!aTitle) return E_INVALIDARG; *aTitle = ToNewUnicode(mTitle); return NS_OK; } NS_IMETHODIMP CWebBrowserContainer::SetTitle(const PRUnichar * aTitle) { NG_ASSERT_POINTER(aTitle, PRUnichar *); if (!aTitle) return E_INVALIDARG; mTitle = aTitle; // Fire a TitleChange event BSTR bstrTitle = SysAllocString(aTitle); mEvents1->Fire_TitleChange(bstrTitle); mEvents2->Fire_TitleChange(bstrTitle); SysFreeString(bstrTitle); return NS_OK; } NS_IMETHODIMP CWebBrowserContainer::GetVisibility(PRBool *aVisibility) { NS_ENSURE_ARG_POINTER(aVisibility); *aVisibility = PR_TRUE; return NS_OK; } NS_IMETHODIMP CWebBrowserContainer::SetVisibility(PRBool aVisibility) { VARIANT_BOOL visible = aVisibility ? VARIANT_TRUE : VARIANT_FALSE; mVisible = aVisibility; // Fire an OnVisible event mEvents2->Fire_OnVisible(visible); return NS_OK; } /////////////////////////////////////////////////////////////////////////////// // nsIEmbeddingSiteWindow2 NS_IMETHODIMP CWebBrowserContainer::Blur() { return NS_OK; } /////////////////////////////////////////////////////////////////////////////// // nsIWebBrowserChromeFocus implementation NS_IMETHODIMP CWebBrowserContainer::FocusNextElement() { ATLTRACE(_T("CWebBrowserContainer::FocusNextElement()\n")); mOwner->NextDlgControl(); return NS_OK; } NS_IMETHODIMP CWebBrowserContainer::FocusPrevElement() { ATLTRACE(_T("CWebBrowserContainer::FocusPrevElement()\n")); mOwner->PrevDlgControl(); return NS_OK; } /////////////////////////////////////////////////////////////////////////////// // nsIWebBrowserChrome implementation NS_IMETHODIMP CWebBrowserContainer::SetStatus(PRUint32 statusType, const PRUnichar *status) { //Fire a StatusTextChange event BSTR bstrStatus = SysAllocString(status); mEvents1->Fire_StatusTextChange(bstrStatus); mEvents2->Fire_StatusTextChange(bstrStatus); SysFreeString(bstrStatus); return NS_OK; } NS_IMETHODIMP CWebBrowserContainer::GetWebBrowser(nsIWebBrowser * *aWebBrowser) { return NS_ERROR_FAILURE; } NS_IMETHODIMP CWebBrowserContainer::SetWebBrowser(nsIWebBrowser * aWebBrowser) { return NS_ERROR_FAILURE; } NS_IMETHODIMP CWebBrowserContainer::GetChromeFlags(PRUint32 *aChromeFlags) { return NS_ERROR_FAILURE; } NS_IMETHODIMP CWebBrowserContainer::SetChromeFlags(PRUint32 aChromeFlags) { return NS_ERROR_FAILURE; } NS_IMETHODIMP CWebBrowserContainer::DestroyBrowserWindow(void) { return NS_ERROR_FAILURE; } NS_IMETHODIMP CWebBrowserContainer::SizeBrowserTo(PRInt32 aCX, PRInt32 aCY) { return NS_ERROR_FAILURE; } NS_IMETHODIMP CWebBrowserContainer::ShowAsModal(void) { return NS_ERROR_FAILURE; } NS_IMETHODIMP CWebBrowserContainer::IsWindowModal(PRBool *_retval) { // we're not *_retval = PR_FALSE; return NS_OK; } NS_IMETHODIMP CWebBrowserContainer::ExitModalEventLoop(nsresult aStatus) { // Ignore request to exit modal loop return NS_OK; } /////////////////////////////////////////////////////////////////////////////// // nsIRequestObserver implementation NS_IMETHODIMP CWebBrowserContainer::OnStartRequest(nsIRequest *request, nsISupports* aContext) { USES_CONVERSION; NG_TRACE(_T("CWebBrowserContainer::OnStartRequest(...)\n")); return NS_OK; } NS_IMETHODIMP CWebBrowserContainer::OnStopRequest(nsIRequest *request, nsISupports* aContext, nsresult aStatus) { USES_CONVERSION; NG_TRACE(_T("CWebBrowserContainer::OnStopRequest(..., %d)\n"), (int) aStatus); // Fire a DownloadComplete event mEvents1->Fire_DownloadComplete(); mEvents2->Fire_DownloadComplete(); return NS_OK; } /////////////////////////////////////////////////////////////////////////////// // nsICommandHandler implementation /* void do (in string aCommand, in string aStatus); */ NS_IMETHODIMP CWebBrowserContainer::Exec(const char *aCommand, const char *aStatus, char **aResult) { return NS_OK; } /* void query (in string aCommand, in string aStatus); */ NS_IMETHODIMP CWebBrowserContainer::Query(const char *aCommand, const char *aStatus, char **aResult) { return NS_OK; }