/* -*- 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): * * 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 //#include #include // commdlg.h is needed to build with WIN32_LEAN_AND_MEAN #include #include "MozillaControl.h" #include "MozillaBrowser.h" #include "IEHtmlDocument.h" #include "PropertyDlg.h" #include "PageSetupDlg.h" #include "PromptService.h" #include "HelperAppDlg.h" #include "WindowCreator.h" #include "nsNetUtil.h" #include "nsCWebBrowser.h" #include "nsIAtom.h" #include "nsILocalFile.h" #include "nsIWebBrowserPersist.h" #include "nsIClipboardCommands.h" #include "nsIProfile.h" #include "nsIWidget.h" #include "nsIWebBrowserFocus.h" #include "nsAppDirectoryServiceDefs.h" #include "nsIComponentRegistrar.h" #ifdef NS_PRINTING #include "nsIPrintOptions.h" #include "nsIWebBrowserPrint.h" #endif #include "nsIDOMWindow.h" #include "nsIDOMHTMLAnchorElement.h" #include "nsIDOMNSDocument.h" #include "nsEmbedAPI.h" #include "nsEmbedCID.h" #define HACK_NON_REENTRANCY #ifdef HACK_NON_REENTRANCY static HANDLE s_hHackedNonReentrancy = NULL; #endif #define NS_PROMPTSERVICE_CID \ {0xa2112d6a, 0x0e28, 0x421f, {0xb4, 0x6a, 0x25, 0xc0, 0xb3, 0x8, 0xcb, 0xd0}} #define NS_HELPERAPPLAUNCHERDIALOG_CID \ {0xf68578eb, 0x6ec2, 0x4169, {0xae, 0x19, 0x8c, 0x62, 0x43, 0xf0, 0xab, 0xe1}} static NS_DEFINE_CID(kPromptServiceCID, NS_PROMPTSERVICE_CID); static NS_DEFINE_CID(kHelperAppLauncherDialogCID, NS_HELPERAPPLAUNCHERDIALOG_CID); #ifdef NS_PRINTING class PrintListener : public nsIWebProgressListener { PRBool mComplete; public: NS_DECL_ISUPPORTS NS_DECL_NSIWEBPROGRESSLISTENER PrintListener(); virtual ~PrintListener(); void WaitForComplete(); }; #endif class SimpleDirectoryProvider : public nsIDirectoryServiceProvider { public: SimpleDirectoryProvider(); BOOL IsValid() const; NS_DECL_ISUPPORTS NS_DECL_NSIDIRECTORYSERVICEPROVIDER protected: virtual ~SimpleDirectoryProvider(); nsCOMPtr mApplicationRegistryDir; nsCOMPtr mApplicationRegistryFile; nsCOMPtr mUserProfileDir; }; // Default page in design mode. The data protocol may or may not be supported // so the scheme is checked before the page is loaded. static const char kDesignModeScheme[] = "data"; static const OLECHAR kDesignModeURL[] = L"data:text/html,

Mozilla Control

"; // Registry keys and values static const TCHAR kBrowserHelperObjectRegKey[] = _T("Software\\Mozilla\\ActiveX Control\\Browser Helper Objects"); // Some recent SDKs define these IOleCommandTarget groups, so they're // postfixed with _Moz to prevent linker errors. GUID CGID_IWebBrowser_Moz = { 0xED016940L, 0xBD5B, 0x11cf, {0xBA, 0x4E, 0x00, 0xC0, 0x4F, 0xD7, 0x08, 0x16} }; GUID CGID_MSHTML_Moz = { 0xED016940L, 0xBD5B, 0x11cf, {0xBA, 0x4E, 0x00, 0xC0, 0x4F, 0xD7, 0x08, 0x16} }; ///////////////////////////////////////////////////////////////////////////// // CMozillaBrowser nsVoidArray CMozillaBrowser::sBrowserList; // // Constructor // CMozillaBrowser::CMozillaBrowser() { NG_TRACE_METHOD(CMozillaBrowser::CMozillaBrowser); // ATL flags ensures the control opens with a window m_bWindowOnly = TRUE; m_bWndLess = FALSE; // Initialize layout interfaces mWebBrowserAsWin = nsnull; mValidBrowserFlag = FALSE; // Create the container that handles some things for us mWebBrowserContainer = NULL; // Control starts off in non-edit mode mEditModeFlag = FALSE; // Control starts off without being a drop target mHaveDropTargetFlag = FALSE; // the IHTMLDocument, lazy allocation. mIERootDocument = NULL; // Browser helpers mBrowserHelperList = NULL; mBrowserHelperListCount = 0; // Name of the default profile to use mProfileName.Assign(NS_LITERAL_STRING("MozillaControl")); // Initialise the web browser Initialize(); } // // Destructor // CMozillaBrowser::~CMozillaBrowser() { NG_TRACE_METHOD(CMozillaBrowser::~CMozillaBrowser); // Close the web browser Terminate(); } // See bug 127982: // // Microsoft's InlineIsEqualGUID global function is multiply defined // in ATL and/or SDKs with varying namespace requirements. To save the control // from future grief, this method is used instead. static inline BOOL _IsEqualGUID(REFGUID rguid1, REFGUID rguid2) { return ( ((PLONG) &rguid1)[0] == ((PLONG) &rguid2)[0] && ((PLONG) &rguid1)[1] == ((PLONG) &rguid2)[1] && ((PLONG) &rguid1)[2] == ((PLONG) &rguid2)[2] && ((PLONG) &rguid1)[3] == ((PLONG) &rguid2)[3]); } STDMETHODIMP CMozillaBrowser::InterfaceSupportsErrorInfo(REFIID riid) { static const IID* arr[] = { &IID_IWebBrowser, &IID_IWebBrowser2, &IID_IWebBrowserApp }; for (int i = 0; i < (sizeof(arr) / sizeof(arr[0])); i++) { if (_IsEqualGUID(*arr[i], riid)) return S_OK; } return S_FALSE; } // // ShowContextMenu // void CMozillaBrowser::ShowContextMenu(PRUint32 aContextFlags, nsIDOMEvent *aEvent, nsIDOMNode *aNode) { POINT pt; GetCursorPos(&pt); // Give the client application the chance to show its own menu // in place of the one the control is about to show. CIPtr(IDocHostUIHandler) spIDocHostUIHandler = m_spClientSite; if (spIDocHostUIHandler) { enum IE4MenuContexts { ctxMenuDefault = 0, ctxMenuImage, ctxMenuControl, ctxMenuTable, ctxMenuDebug, ctxMenu1DSelect, ctxMenuAnchor, ctxMenuImgDynSrc }; DWORD dwID = ctxMenuDefault; if (aContextFlags & nsIContextMenuListener::CONTEXT_DOCUMENT) { dwID = ctxMenuDefault; } else if (aContextFlags & nsIContextMenuListener::CONTEXT_LINK) { dwID = ctxMenuAnchor; } else if (aContextFlags & nsIContextMenuListener::CONTEXT_IMAGE) { dwID = ctxMenuImage; } else if (aContextFlags & nsIContextMenuListener::CONTEXT_TEXT) { dwID = ctxMenu1DSelect; } else { dwID = ctxMenuDefault; } HRESULT hr = spIDocHostUIHandler->ShowContextMenu(dwID, &pt, NULL, NULL); if (hr == S_OK) { // Client handled menu return; } } LPTSTR pszMenuResource = NULL; if (aContextFlags & nsIContextMenuListener::CONTEXT_DOCUMENT) { pszMenuResource = MAKEINTRESOURCE(IDR_POPUP_DOCUMENT); } else if (aContextFlags & nsIContextMenuListener::CONTEXT_LINK) { pszMenuResource = MAKEINTRESOURCE(IDR_POPUP_LINK); } else if (aContextFlags & nsIContextMenuListener::CONTEXT_IMAGE) { pszMenuResource = MAKEINTRESOURCE(IDR_POPUP_IMAGE); } else if (aContextFlags & nsIContextMenuListener::CONTEXT_TEXT) { pszMenuResource = MAKEINTRESOURCE(IDR_POPUP_TEXT); } else { pszMenuResource = MAKEINTRESOURCE(IDR_POPUP_DOCUMENT); } if (pszMenuResource) { HMENU hMenu = LoadMenu(_Module.m_hInstResource, pszMenuResource); HMENU hPopupMenu = GetSubMenu(hMenu, 0); mContextNode = do_QueryInterface(aNode); UINT nCmd = TrackPopupMenu(hPopupMenu, TPM_NONOTIFY | TPM_RETURNCMD, pt.x, pt.y, 0, m_hWnd, NULL); DestroyMenu(hMenu); if (nCmd != 0) { SendMessage(WM_COMMAND, nCmd); } mContextNode = nsnull; } } // // ShowURIPropertyDlg // void CMozillaBrowser::ShowURIPropertyDlg(const nsAString &aURI, const nsAString &aContentType) { CPropertyDlg dlg; CPPageDlg linkDlg; dlg.AddPage(&linkDlg); if (!aURI.IsEmpty()) { linkDlg.mType = aContentType; linkDlg.mURL = aURI; } dlg.DoModal(); } // // Displays a message box to the user. If the container provides // a IDocHostShowUI interface we use that to display messages, otherwise // a simple message box is shown. // int CMozillaBrowser::MessageBox(LPCTSTR lpszText, LPCTSTR lpszCaption, UINT nType) { // Let the doc host display it's own message box if it can CIPtr(IDocHostShowUI) spIDocHostShowUI = m_spClientSite; if (spIDocHostShowUI) { USES_CONVERSION; LRESULT lResult = 0; HRESULT hr = spIDocHostShowUI->ShowMessage(m_hWnd, T2OLE(lpszText), T2OLE(lpszCaption), nType, NULL, 0, &lResult); if (hr == S_OK) { return lResult; } } // Do the default message box return CWindow::MessageBox(lpszText, lpszCaption, nType); } // // Sets the startup error message from a resource string // HRESULT CMozillaBrowser::SetStartupErrorMessage(UINT nStringID) { TCHAR szMsg[1024]; ::LoadString(_Module.m_hInstResource, nStringID, szMsg, sizeof(szMsg) / sizeof(szMsg[0])); mStartupErrorMessage = szMsg; return S_OK; } // // Tells the container to change focus to the next control in the dialog. // void CMozillaBrowser::NextDlgControl() { HWND hwndParent = GetParent(); if (::IsWindow(hwndParent)) { ::PostMessage(hwndParent, WM_NEXTDLGCTL, 0, 0); } } // // Tells the container to change focus to the previous control in the dialog. // void CMozillaBrowser::PrevDlgControl() { HWND hwndParent = GetParent(); if (::IsWindow(hwndParent)) { ::PostMessage(hwndParent, WM_NEXTDLGCTL, 1, 0); } } /////////////////////////////////////////////////////////////////////////////// // Message handlers // Handle WM_CREATE windows message LRESULT CMozillaBrowser::OnCreate(UINT uMsg, WPARAM wParam, LPARAM lParam, BOOL& bHandled) { NG_TRACE_METHOD(CMozillaBrowser::OnCreate); // Create the web browser CreateBrowser(); // TODO create and register a drop target // Control is ready mBrowserReadyState = READYSTATE_COMPLETE; FireOnChanged(DISPID_READYSTATE); // Load browser helpers LoadBrowserHelpers(); // Browse to a default page - if in design mode BOOL bUserMode = FALSE; if (SUCCEEDED(GetAmbientUserMode(bUserMode))) { if (!bUserMode) { // Load a page in design mode if the specified page is supported nsCOMPtr ios = do_GetIOService(); if (ios) { // Ensure design page can be loaded by checking for a // registered protocol handler that supports the scheme nsCOMPtr ph; nsCAutoString phScheme; ios->GetProtocolHandler(kDesignModeScheme, getter_AddRefs(ph)); if (ph && NS_SUCCEEDED(ph->GetScheme(phScheme)) && phScheme.Equals(NS_LITERAL_CSTRING(kDesignModeScheme))) { Navigate(const_cast(kDesignModeURL), NULL, NULL, NULL, NULL); } } } else { if (mInitialSrc.Length() > 0) { Navigate(mInitialSrc, NULL, NULL, NULL, NULL); } } } // Clip the child windows out of paint operations SetWindowLong(GWL_STYLE, GetWindowLong(GWL_STYLE) | WS_CLIPCHILDREN | WS_TABSTOP); return 0; } // Handle WM_DESTROY window message LRESULT CMozillaBrowser::OnDestroy(UINT uMsg, WPARAM wParam, LPARAM lParam, BOOL& bHandled) { NG_TRACE_METHOD(CMozillaBrowser::OnDestroy); // Unload browser helpers UnloadBrowserHelpers(); // Clean up the browser DestroyBrowser(); return 0; } // Handle WM_SIZE windows message LRESULT CMozillaBrowser::OnSize(UINT uMsg, WPARAM wParam, LPARAM lParam, BOOL& bHandled) { NG_TRACE_METHOD(CMozillaBrowser::OnSize); RECT rc; rc.top = 0; rc.left = 0; rc.right = LOWORD(lParam); rc.bottom = HIWORD(lParam); AdjustWindowRectEx(&rc, GetWindowLong(GWL_STYLE), FALSE, GetWindowLong(GWL_EXSTYLE)); rc.right -= rc.left; rc.bottom -= rc.top; rc.left = 0; rc.top = 0; // Pass resize information down to the browser... if (mWebBrowserAsWin) { mWebBrowserAsWin->SetPosition(rc.left, rc.top); mWebBrowserAsWin->SetSize(rc.right - rc.left, rc.bottom - rc.top, PR_TRUE); } return 0; } // Handle WM_SETFOCUS LRESULT CMozillaBrowser::OnSetFocus(UINT uMsg, WPARAM wParam, LPARAM lParam, BOOL& bHandled) { ATLTRACE(_T("CMozillaBrowser::OnSetFocus()\n")); nsCOMPtr browserAsFocus = do_QueryInterface(mWebBrowser); if (browserAsFocus) { browserAsFocus->Activate(); } CComQIPtr controlSite = m_spClientSite; if (controlSite) { controlSite->OnFocus(TRUE); } return 0; } // Handle WM_KILLFOCUS LRESULT CMozillaBrowser::OnKillFocus(UINT uMsg, WPARAM wParam, LPARAM lParam, BOOL& bHandled) { ATLTRACE(_T("CMozillaBrowser::OnKillFocus()\n")); nsCOMPtr browserAsFocus = do_QueryInterface(mWebBrowser); if (browserAsFocus) { browserAsFocus->Deactivate(); } CComQIPtr controlSite = m_spClientSite; if (controlSite) { controlSite->OnFocus(FALSE); } return 0; } // Handle WM_MOUSEACTIVATE messages LRESULT CMozillaBrowser::OnMouseActivate(UINT uMsg, WPARAM wParam, LPARAM lParam, BOOL& bHandled) { return MA_ACTIVATE; } // Handle WM_GETDLGCODE to receive keyboard presses LRESULT CMozillaBrowser::OnGetDlgCode(UINT uMsg, WPARAM wParam, LPARAM lParam, BOOL& bHandled) { return DLGC_WANTALLKEYS; } // Handle WM_PAINT windows message (and IViewObject::Draw) HRESULT CMozillaBrowser::OnDraw(ATL_DRAWINFO& di) { NG_TRACE_METHOD(CMozillaBrowser::OnDraw); if (!BrowserIsValid()) { RECT& rc = *(RECT*)di.prcBounds; DrawText(di.hdcDraw, mStartupErrorMessage.c_str(), -1, &rc, DT_TOP | DT_LEFT | DT_WORDBREAK); } return S_OK; } // Handle ID_PAGESETUP command LRESULT CMozillaBrowser::OnPageSetup(WORD wNotifyCode, WORD wID, HWND hWndCtl, BOOL& bHandled) { NG_TRACE_METHOD(CMozillaBrowser::OnPageSetup); #ifdef NS_PRINTING nsCOMPtr print(do_GetInterface(mWebBrowser)); nsCOMPtr printSettings; if(!print || NS_FAILED(print->GetGlobalPrintSettings(getter_AddRefs(printSettings)))) { return 0; } // show the page setup dialog CPageSetupDlg dlg(printSettings); dlg.DoModal(); #endif return 0; } // Handle ID_PRINT command LRESULT CMozillaBrowser::OnPrint(WORD wNotifyCode, WORD wID, HWND hWndCtl, BOOL& bHandled) { NG_TRACE_METHOD(CMozillaBrowser::OnPrint); if (!BrowserIsValid()) { return 0; } PrintDocument(TRUE); return 0; } LRESULT CMozillaBrowser::OnSaveAs(WORD wNotifyCode, WORD wID, HWND hWndCtl, BOOL& bHandled) { NG_TRACE_METHOD(CMozillaBrowser::OnSaveAs); OPENFILENAME SaveFileName; char szFile[_MAX_PATH]; char szFileTitle[256]; //TODO: The IE control allows you to also save as "Web Page, complete" // where all of the page's images are saved in the same directory. // For the moment, we're not allowing this option. memset(&SaveFileName, 0, sizeof(SaveFileName)); SaveFileName.lStructSize = sizeof(SaveFileName); SaveFileName.hwndOwner = m_hWnd; SaveFileName.lpstrFilter = "Web Page, HTML Only (*.htm;*.html)\0*.htm;*.html\0Text File (*.txt)\0*.txt\0"; SaveFileName.nFilterIndex = 1; SaveFileName.lpstrFile = szFile; SaveFileName.nMaxFile = sizeof(szFile); SaveFileName.lpstrFileTitle = szFileTitle; SaveFileName.nMaxFileTitle = sizeof(szFileTitle); SaveFileName.Flags = OFN_HIDEREADONLY | OFN_OVERWRITEPROMPT; SaveFileName.lpstrDefExt = "htm"; //Get the title of the current web page to set as the default filename. char szTmp[_MAX_FNAME] = "untitled"; BSTR pageName = NULL; get_LocationName(&pageName); // Page title if (pageName) { USES_CONVERSION; strncpy(szTmp, OLE2A(pageName), sizeof(szTmp) - 1); SysFreeString(pageName); szTmp[sizeof(szTmp) - 1] = '\0'; } // The SaveAs dialog will fail if szFile contains any "bad" characters. // This hunk of code attempts to mimick the IE way of replacing "bad" // characters with "good" characters. int j = 0; for (int i=0; szTmp[i]!='\0'; i++) { switch(szTmp[i]) { case '\\': case '*': case '|': case ':': case '"': case '>': case '<': case '?': break; case '.': if (szTmp[i+1] != '\0') { szFile[j] = '_'; j++; } break; case '/': szFile[j] = '-'; j++; break; default: szFile[j] = szTmp[i]; j++; } } szFile[j] = '\0'; HRESULT hr = S_OK; if (GetSaveFileName(&SaveFileName)) { nsCOMPtr persist(do_QueryInterface(mWebBrowser)); USES_CONVERSION; char szDataFile[_MAX_PATH]; char szDataPath[_MAX_PATH]; char drive[_MAX_DRIVE]; char dir[_MAX_DIR]; char fname[_MAX_FNAME]; char ext[_MAX_EXT]; _splitpath(szFile, drive, dir, fname, ext); sprintf(szDataFile, "%s_files", fname); _makepath(szDataPath, drive, dir, szDataFile, ""); nsCOMPtr file; NS_NewNativeLocalFile(nsDependentCString(T2A(szFile)), TRUE, getter_AddRefs(file)); nsCOMPtr dataPath; NS_NewNativeLocalFile(nsDependentCString(szDataPath), TRUE, getter_AddRefs(dataPath)); persist->SaveDocument(nsnull, file, dataPath, nsnull, 0, 0); } return hr; } LRESULT CMozillaBrowser::OnProperties(WORD wNotifyCode, WORD wID, HWND hWndCtl, BOOL& bHandled) { NG_TRACE_METHOD(CMozillaBrowser::OnProperties); MessageBox(_T("No Properties Yet!"), _T("Control Message"), MB_OK); // TODO show the properties dialog return 0; } LRESULT CMozillaBrowser::OnCut(WORD wNotifyCode, WORD wID, HWND hWndCtl, BOOL& bHandled) { NG_TRACE_METHOD(CMozillaBrowser::OnCut); nsCOMPtr clipboard(do_GetInterface(mWebBrowser)); if (clipboard) { clipboard->CutSelection(); } return 0; } LRESULT CMozillaBrowser::OnCopy(WORD wNotifyCode, WORD wID, HWND hWndCtl, BOOL& bHandled) { NG_TRACE_METHOD(CMozillaBrowser::OnCopy); nsCOMPtr clipboard(do_GetInterface(mWebBrowser)); if (clipboard) { clipboard->CopySelection(); } return 0; } LRESULT CMozillaBrowser::OnPaste(WORD wNotifyCode, WORD wID, HWND hWndCtl, BOOL& bHandled) { NG_TRACE_METHOD(CMozillaBrowser::OnPaste); nsCOMPtr clipboard(do_GetInterface(mWebBrowser)); if (clipboard) { clipboard->Paste(); } return 0; } LRESULT CMozillaBrowser::OnSelectAll(WORD wNotifyCode, WORD wID, HWND hWndCtl, BOOL& bHandled) { NG_TRACE_METHOD(CMozillaBrowser::OnSelectAll); nsCOMPtr clipboard(do_GetInterface(mWebBrowser)); if (clipboard) { clipboard->SelectAll(); } return 0; } // Handle ID_VIEWSOURCE command LRESULT CMozillaBrowser::OnViewSource(WORD wNotifyCode, WORD wID, HWND hWndCtl, BOOL& bHandled) { NG_TRACE_METHOD(CMozillaBrowser::OnViewSource); if (!mWebBrowser) { // No webbrowser to view! NG_ASSERT(0); return 0; } nsCOMPtr webNav = do_QueryInterface(mWebBrowser); if (!webNav) { // No webnav! NG_ASSERT(0); return 0; } nsCOMPtr uri; webNav->GetCurrentURI(getter_AddRefs(uri)); if (!uri) { // No URI to view! NG_ASSERT(0); return 0; } // Get the current URI nsCAutoString aURI; uri->GetSpec(aURI); NS_ConvertUTF8toUTF16 strURI(aURI); strURI.Insert(NS_LITERAL_STRING("view-source:"), 0); // Ask the client to create a window to view the source in CIPtr(IDispatch) spDispNew; VARIANT_BOOL bCancel = VARIANT_FALSE; Fire_NewWindow2(&spDispNew, &bCancel); // Load the view-source into a new url if ((bCancel == VARIANT_FALSE) && spDispNew) { CIPtr(IWebBrowser2) spOther = spDispNew;; if (spOther) { // tack in the viewsource command CComBSTR bstrURL(strURI.get()); CComVariant vURL(bstrURL); VARIANT vNull; vNull.vt = VT_NULL; spOther->Navigate2(&vURL, &vNull, &vNull, &vNull, &vNull); } } return 0; } /////////////////////////////////////////////////////////////////////////////// // Document handlers LRESULT CMozillaBrowser::OnDocumentBack(WORD wNotifyCode, WORD wID, HWND hWndCtl, BOOL& bHandled) { GoBack(); return 0; } LRESULT CMozillaBrowser::OnDocumentForward(WORD wNotifyCode, WORD wID, HWND hWndCtl, BOOL& bHandled) { GoForward(); return 0; } LRESULT CMozillaBrowser::OnDocumentPrint(WORD wNotifyCode, WORD wID, HWND hWndCtl, BOOL& bHandled) { return OnPrint(wNotifyCode, wID, hWndCtl, bHandled); } LRESULT CMozillaBrowser::OnDocumentRefresh(WORD wNotifyCode, WORD wID, HWND hWndCtl, BOOL& bHandled) { Refresh(); return 0; } LRESULT CMozillaBrowser::OnDocumentProperties(WORD wNotifyCode, WORD wID, HWND hWndCtl, BOOL& bHandled) { nsCOMPtr ownerDoc; if (mContextNode) { mContextNode->GetOwnerDocument(getter_AddRefs(ownerDoc)); } // Get the document URL nsAutoString uri; nsCOMPtr htmlDoc = do_QueryInterface(ownerDoc); if (htmlDoc) { htmlDoc->GetURL(uri); } nsAutoString contentType; nsCOMPtr doc = do_QueryInterface(ownerDoc); if (doc) { doc->GetContentType(contentType); } ShowURIPropertyDlg(uri, contentType); return 0; } /////////////////////////////////////////////////////////////////////////////// // Link handlers LRESULT CMozillaBrowser::OnLinkOpen(WORD wNotifyCode, WORD wID, HWND hWndCtl, BOOL& bHandled) { nsAutoString uri; nsCOMPtr anchorElement = do_QueryInterface(mContextNode); if (anchorElement) { anchorElement->GetHref(uri); } if (!uri.IsEmpty()) { CComBSTR bstrURI(uri.get()); CComVariant vFlags(0); Navigate(bstrURI, &vFlags, NULL, NULL, NULL); } return 0; } LRESULT CMozillaBrowser::OnLinkOpenInNewWindow(WORD wNotifyCode, WORD wID, HWND hWndCtl, BOOL& bHandled) { nsAutoString uri; nsCOMPtr anchorElement = do_QueryInterface(mContextNode); if (anchorElement) { anchorElement->GetHref(uri); } if (!uri.IsEmpty()) { CComBSTR bstrURI(uri.get()); CComVariant vFlags(navOpenInNewWindow); Navigate(bstrURI, &vFlags, NULL, NULL, NULL); } return 0; } LRESULT CMozillaBrowser::OnLinkCopyShortcut(WORD wNotifyCode, WORD wID, HWND hWndCtl, BOOL& bHandled) { nsAutoString uri; nsCOMPtr anchorElement = do_QueryInterface(mContextNode); if (anchorElement) { anchorElement->GetHref(uri); } if (!uri.IsEmpty() && OpenClipboard()) { EmptyClipboard(); NS_ConvertUTF16toUTF8 curi(uri); const char *stringText; PRUint32 stringLen = NS_CStringGetData(curi, &stringText); // CF_TEXT HGLOBAL hmemText = GlobalAlloc(GMEM_MOVEABLE | GMEM_ZEROINIT, stringLen + 1); char *pszText = (char *) GlobalLock(hmemText); strncpy(pszText, stringText, stringLen); pszText[stringLen] = '\0'; GlobalUnlock(hmemText); SetClipboardData(CF_TEXT, hmemText); // UniformResourceLocator - CFSTR_SHELLURL const UINT cfShellURL = RegisterClipboardFormat(CFSTR_SHELLURL); HGLOBAL hmemURL = GlobalAlloc(GMEM_MOVEABLE | GMEM_ZEROINIT, stringLen + 1); char *pszURL = (char *) GlobalLock(hmemURL); strncpy(pszText, stringText, stringLen); pszText[stringLen] = '\0'; GlobalUnlock(hmemURL); SetClipboardData(cfShellURL, hmemURL); // TODO // FileContents - CFSTR_FILECONTENTS // FileGroupDescriptor - CFSTR_FILEDESCRIPTORA // FileGroupDescriptorW - CFSTR_FILEDESCRIPTORW CloseClipboard(); } return 0; } LRESULT CMozillaBrowser::OnLinkProperties(WORD wNotifyCode, WORD wID, HWND hWndCtl, BOOL& bHandled) { nsAutoString uri; nsAutoString type; nsCOMPtr anchorElement = do_QueryInterface(mContextNode); if (anchorElement) { anchorElement->GetHref(uri); anchorElement->GetType(type); // How many anchors implement this I wonder } ShowURIPropertyDlg(uri, type); return 0; } /////////////////////////////////////////////////////////////////////////////// // Initialises the web browser engine HRESULT CMozillaBrowser::Initialize() { #ifdef HACK_NON_REENTRANCY // Attempt to open a named event for this process. If it's not there we // know this is the first time the control has run in this process, so create // the named event and do the initialisation. Otherwise do nothing. TCHAR szHackEvent[255]; _stprintf(szHackEvent, _T("MozCtlEvent%d"), (int) GetCurrentProcessId()); s_hHackedNonReentrancy = OpenEvent(EVENT_ALL_ACCESS, FALSE, szHackEvent); if (s_hHackedNonReentrancy == NULL) { s_hHackedNonReentrancy = CreateEvent(NULL, FALSE, FALSE, szHackEvent); #endif // Extract the bin directory path from the control's filename TCHAR szMozCtlPath[MAX_PATH]; memset(szMozCtlPath, 0, sizeof(szMozCtlPath)); GetModuleFileName(_Module.m_hInst, szMozCtlPath, sizeof(szMozCtlPath) / sizeof(szMozCtlPath[0])); TCHAR szTmpDrive[_MAX_DRIVE]; TCHAR szTmpDir[_MAX_DIR]; TCHAR szTmpFname[_MAX_FNAME]; TCHAR szTmpExt[_MAX_EXT]; TCHAR szBinDirPath[MAX_PATH]; _tsplitpath(szMozCtlPath, szTmpDrive, szTmpDir, szTmpFname, szTmpExt); memset(szBinDirPath, 0, sizeof(szBinDirPath)); _tmakepath(szBinDirPath, szTmpDrive, szTmpDir, NULL, NULL); if (_tcslen(szBinDirPath) == 0) { return E_FAIL; } // Create a simple directory provider. If this fails because the directories are // invalid or whatever then the control will fallback on the default directory // provider. nsCOMPtr directoryProvider; SimpleDirectoryProvider *pDirectoryProvider = new SimpleDirectoryProvider; if (pDirectoryProvider->IsValid()) directoryProvider = do_QueryInterface(pDirectoryProvider); // Create an object to represent the path nsresult rv; nsCOMPtr binDir; USES_CONVERSION; NS_NewNativeLocalFile(nsDependentCString(T2A(szBinDirPath)), TRUE, getter_AddRefs(binDir)); rv = NS_InitEmbedding(binDir, directoryProvider); // Load preferences service mPrefBranch = do_GetService(NS_PREFSERVICE_CONTRACTID, &rv); if (NS_FAILED(rv)) { NG_ASSERT(0); NG_TRACE_ALWAYS(_T("Could not create preference object rv=%08x\n"), (int) rv); SetStartupErrorMessage(IDS_CANNOTCREATEPREFS); return E_FAIL; } // Stuff in here only needs to be done once static BOOL bRegisterComponents = FALSE; if (!bRegisterComponents) { // Register our own native prompting service for message boxes, login // prompts etc. nsCOMPtr promptFactory; rv = NS_NewPromptServiceFactory(getter_AddRefs(promptFactory)); if (NS_FAILED(rv)) return rv; nsCOMPtr registrar; rv = NS_GetComponentRegistrar(getter_AddRefs(registrar)); if (NS_FAILED(rv)) return rv; rv = registrar->RegisterFactory(kPromptServiceCID, "Prompt Service", NS_PROMPTSERVICE_CONTRACTID, promptFactory); if (NS_FAILED(rv)) return rv; // Helper app launcher dialog nsCOMPtr helperAppDlgFactory; rv = NS_NewHelperAppLauncherDlgFactory(getter_AddRefs(helperAppDlgFactory)); if (NS_FAILED(rv)) return rv; rv = registrar->RegisterFactory(kHelperAppLauncherDialogCID, "Helper App Launcher Dialog", "@mozilla.org/helperapplauncherdialog;1", helperAppDlgFactory); if (NS_FAILED(rv)) return rv; // create our local object CWindowCreator *creator = new CWindowCreator(); nsCOMPtr windowCreator; windowCreator = static_cast(creator); // Attach it via the watcher service nsCOMPtr watcher = do_GetService(NS_WINDOWWATCHER_CONTRACTID); if (watcher) watcher->SetWindowCreator(windowCreator); } // Set the profile which the control will use nsCOMPtr profileService = do_GetService(NS_PROFILE_CONTRACTID, &rv); if (NS_FAILED(rv)) { return E_FAIL; } // Make a new default profile PRBool profileExists = PR_FALSE; rv = profileService->ProfileExists(mProfileName.get(), &profileExists); if (NS_FAILED(rv)) { return E_FAIL; } else if (!profileExists) { rv = profileService->CreateNewProfile(mProfileName.get(), nsnull, nsnull, PR_FALSE); if (NS_FAILED(rv)) { return E_FAIL; } } rv = profileService->SetCurrentProfile(mProfileName.get()); if (NS_FAILED(rv)) { return E_FAIL; } #ifdef HACK_NON_REENTRANCY } #endif return S_OK; } // Terminates the web browser engine HRESULT CMozillaBrowser::Terminate() { #ifdef HACK_NON_REENTRANCY if (0) { #endif mPrefBranch = nsnull; NS_TermEmbedding(); #ifdef HACK_NON_REENTRANCY } #endif return S_OK; } // Create and initialise the web browser HRESULT CMozillaBrowser::CreateBrowser() { NG_TRACE_METHOD(CMozillaBrowser::CreateBrowser); if (mWebBrowser != nsnull) { NG_ASSERT(0); NG_TRACE_ALWAYS(_T("CreateBrowser() called more than once!")); return SetErrorInfo(E_UNEXPECTED); } RECT rcLocation; GetClientRect(&rcLocation); if (IsRectEmpty(&rcLocation)) { rcLocation.bottom++; rcLocation.top++; } nsresult rv; // Create the web browser mWebBrowser = do_CreateInstance(NS_WEBBROWSER_CONTRACTID, &rv); if (NS_FAILED(rv)) { NG_ASSERT(0); NG_TRACE_ALWAYS(_T("Could not create webbrowser object rv=%08x\n"), (int) rv); SetStartupErrorMessage(IDS_CANNOTCREATEPREFS); return rv; } // Configure what the web browser can and cannot do nsCOMPtr webBrowserAsSetup(do_QueryInterface(mWebBrowser)); // Allow plugins? const PRBool kAllowPlugins = PR_TRUE; webBrowserAsSetup->SetProperty(nsIWebBrowserSetup::SETUP_ALLOW_PLUGINS, kAllowPlugins); // Host chrome or content? const PRBool kHostChrome = PR_FALSE; // Hardcoded for now webBrowserAsSetup->SetProperty(nsIWebBrowserSetup::SETUP_IS_CHROME_WRAPPER, PR_FALSE); // Create the webbrowser window mWebBrowserAsWin = do_QueryInterface(mWebBrowser); rv = mWebBrowserAsWin->InitWindow(nsNativeWidget(m_hWnd), nsnull, 0, 0, rcLocation.right - rcLocation.left, rcLocation.bottom - rcLocation.top); rv = mWebBrowserAsWin->Create(); // Create the container object mWebBrowserContainer = new CWebBrowserContainer(this); if (mWebBrowserContainer == NULL) { NG_ASSERT(0); NG_TRACE_ALWAYS(_T("Could not create webbrowsercontainer - out of memory\n")); return NS_ERROR_OUT_OF_MEMORY; } mWebBrowserContainer->AddRef(); // Set up the browser with its chrome mWebBrowser->SetContainerWindow(static_cast(mWebBrowserContainer)); mWebBrowser->SetParentURIContentListener(mWebBrowserContainer); // Subscribe for progress notifications nsCOMPtr listener( do_GetWeakReference(static_cast(mWebBrowserContainer))); mWebBrowser->AddWebBrowserListener(listener, NS_GET_IID(nsIWebProgressListener)); // Visible mWebBrowserAsWin->SetVisibility(PR_TRUE); // Activated nsCOMPtr browserAsFocus = do_QueryInterface(mWebBrowser); browserAsFocus->Activate(); // Get an editor session mEditingSession = do_GetInterface(mWebBrowser); mCommandManager = do_GetInterface(mWebBrowser); // Append browser to browser list sBrowserList.AppendElement(this); mValidBrowserFlag = TRUE; return S_OK; } // Clean up the browser HRESULT CMozillaBrowser::DestroyBrowser() { // TODO unregister drop target mValidBrowserFlag = FALSE; // Remove browser from browser list sBrowserList.RemoveElement(this); // Destroy the htmldoc if (mIERootDocument != NULL) { mIERootDocument->Release(); mIERootDocument = NULL; } // Destroy layout... if (mWebBrowserAsWin) { mWebBrowserAsWin->Destroy(); mWebBrowserAsWin = nsnull; } if (mWebBrowserContainer) { mWebBrowserContainer->Release(); mWebBrowserContainer = NULL; } mEditingSession = nsnull; mCommandManager = nsnull; mWebBrowser = nsnull; return S_OK; } // Turns the editor mode on or off HRESULT CMozillaBrowser::SetEditorMode(BOOL bEnabled) { NG_TRACE_METHOD(CMozillaBrowser::SetEditorMode); if (!mEditingSession || !mCommandManager) return E_FAIL; nsCOMPtr domWindow; nsresult rv = GetDOMWindow(getter_AddRefs(domWindow)); if (NS_FAILED(rv)) return E_FAIL; rv = mEditingSession->MakeWindowEditable(domWindow, "html", PR_FALSE, PR_TRUE, PR_FALSE); return S_OK; } HRESULT CMozillaBrowser::OnEditorCommand(DWORD nCmdID) { NG_TRACE_METHOD(CMozillaBrowser::OnEditorCommand); nsCOMPtr domWindow; GetDOMWindow(getter_AddRefs(domWindow)); const char *styleCommand = nsnull; nsICommandParams *commandParams = nsnull; switch (nCmdID) { case IDM_BOLD: styleCommand = "cmd_bold"; break; case IDM_ITALIC: styleCommand = "cmd_italic"; break; case IDM_UNDERLINE: styleCommand = "cmd_underline"; break; // TODO add the rest! default: // DO NOTHING break; } return mCommandManager ? mCommandManager->DoCommand(styleCommand, commandParams, domWindow) : NS_ERROR_FAILURE; } // Return the root DOM document HRESULT CMozillaBrowser::GetDOMDocument(nsIDOMDocument **pDocument) { NG_TRACE_METHOD(CMozillaBrowser::GetDOMDocument); HRESULT hr = E_FAIL; // Test for stupid args if (pDocument == NULL) { NG_ASSERT(0); return E_INVALIDARG; } *pDocument = nsnull; if (!BrowserIsValid()) { NG_ASSERT(0); return E_UNEXPECTED; } // Get the DOM window from the webbrowser nsCOMPtr window; mWebBrowser->GetContentDOMWindow(getter_AddRefs(window)); if (window) { if (NS_SUCCEEDED(window->GetDocument(pDocument)) && *pDocument) { hr = S_OK; } } return hr; } // Load any browser helpers HRESULT CMozillaBrowser::LoadBrowserHelpers() { NG_TRACE_METHOD(CMozillaBrowser::LoadBrowserHelpers); UnloadBrowserHelpers(); // IE loads browser helper objects from a branch of the registry // Search the branch looking for objects to load with the control. CRegKey cKey; if (cKey.Open(HKEY_LOCAL_MACHINE, kBrowserHelperObjectRegKey, KEY_ENUMERATE_SUB_KEYS) != ERROR_SUCCESS) { NG_TRACE(_T("No browser helper key found\n")); return S_FALSE; } // Count the number of browser helper object keys ULONG nHelperKeys = 0; LONG nResult = ERROR_SUCCESS; while (nResult == ERROR_SUCCESS) { TCHAR szCLSID[50]; DWORD dwCLSID = sizeof(szCLSID) / sizeof(TCHAR); FILETIME cLastWrite; // Read next subkey nResult = RegEnumKeyEx(cKey, nHelperKeys, szCLSID, &dwCLSID, NULL, NULL, NULL, &cLastWrite); if (nResult != ERROR_SUCCESS) { break; } nHelperKeys++; } if (nHelperKeys == 0) { NG_TRACE(_T("No browser helper objects found\n")); return S_FALSE; } // Get the CLSID for each browser helper object CLSID *pClassList = new CLSID[nHelperKeys]; DWORD nHelpers = 0; DWORD nKey = 0; nResult = ERROR_SUCCESS; while (nResult == ERROR_SUCCESS) { TCHAR szCLSID[50]; DWORD dwCLSID = sizeof(szCLSID) / sizeof(TCHAR); FILETIME cLastWrite; // Read next subkey nResult = RegEnumKeyEx(cKey, nKey++, szCLSID, &dwCLSID, NULL, NULL, NULL, &cLastWrite); if (nResult != ERROR_SUCCESS) { break; } NG_TRACE(_T("Reading helper object entry \"%s\"\n"), szCLSID); // Turn the key into a CLSID USES_CONVERSION; CLSID clsid; if (CLSIDFromString(T2OLE(szCLSID), &clsid) != NOERROR) { continue; } pClassList[nHelpers++] = clsid; } mBrowserHelperList = new CComUnkPtr[nHelpers]; // Create each object in turn for (ULONG i = 0; i < nHelpers; i++) { CLSID clsid = pClassList[i]; HRESULT hr; CComQIPtr cpObjectWithSite; hr = CoCreateInstance(clsid, NULL, CLSCTX_INPROC_SERVER, IID_IObjectWithSite, (LPVOID *) &cpObjectWithSite); if (FAILED(hr)) { NG_TRACE(_T("Registered browser helper object cannot be created\n"));; } else { // Set the object to point at the browser cpObjectWithSite->SetSite((IWebBrowser2 *) this); // Store in the list CComUnkPtr cpUnk = cpObjectWithSite; mBrowserHelperList[mBrowserHelperListCount++] = cpUnk; } } delete []pClassList; return S_OK; } // Release browser helpers HRESULT CMozillaBrowser::UnloadBrowserHelpers() { NG_TRACE_METHOD(CMozillaBrowser::UnloadBrowserHelpers); if (mBrowserHelperList == NULL) { return S_OK; } // Destroy each helper for (ULONG i = 0; i < mBrowserHelperListCount; i++) { CComUnkPtr cpUnk = mBrowserHelperList[i]; if (cpUnk) { CComQIPtr cpObjectWithSite = cpUnk; if (cpObjectWithSite) { cpObjectWithSite->SetSite(NULL); } } } // Cleanup the array mBrowserHelperListCount = 0; delete []mBrowserHelperList; mBrowserHelperList = NULL; return S_OK; } // Print document HRESULT CMozillaBrowser::PrintDocument(BOOL promptUser) { #ifdef NS_PRINTING // Print the contents nsCOMPtr browserAsPrint = do_GetInterface(mWebBrowser); NS_ASSERTION(browserAsPrint, "No nsIWebBrowserPrint!"); PRBool oldPrintSilent = PR_FALSE; nsCOMPtr printSettings; browserAsPrint->GetGlobalPrintSettings(getter_AddRefs(printSettings)); if (printSettings) { printSettings->GetPrintSilent(&oldPrintSilent); printSettings->SetPrintSilent(promptUser ? PR_FALSE : PR_TRUE); } // Disable print progress dialog (XUL) PRBool oldShowPrintProgress = FALSE; const char *kShowPrintProgressPref = "print.show_print_progress"; mPrefBranch->GetBoolPref(kShowPrintProgressPref, &oldShowPrintProgress); mPrefBranch->SetBoolPref(kShowPrintProgressPref, PR_FALSE); // Print PrintListener *listener = new PrintListener; nsCOMPtr printListener = do_QueryInterface(listener); nsresult rv = browserAsPrint->Print(printSettings, printListener); if (NS_SUCCEEDED(rv)) { listener->WaitForComplete(); } // Cleanup if (printSettings) { printSettings->SetPrintSilent(oldPrintSilent); } mPrefBranch->SetBoolPref(kShowPrintProgressPref, oldShowPrintProgress); #endif return S_OK; } ///////////////////////////////////////////////////////////////////////////// // IOleObject overrides // This is an almost verbatim copy of the standard ATL implementation of // IOleObject::InPlaceActivate but with a few lines commented out. HRESULT CMozillaBrowser::InPlaceActivate(LONG iVerb, const RECT* prcPosRect) { NG_TRACE_METHOD(CMozillaBrowser::InPlaceActivate); HRESULT hr; if (m_spClientSite == NULL) return S_OK; CComPtr pIPO; ControlQueryInterface(IID_IOleInPlaceObject, (void**)&pIPO); _ASSERTE(pIPO != NULL); if (prcPosRect != NULL) pIPO->SetObjectRects(prcPosRect, prcPosRect); if (!m_bNegotiatedWnd) { if (!m_bWindowOnly) // Try for windowless site hr = m_spClientSite->QueryInterface(IID_IOleInPlaceSiteWindowless, (void **)&m_spInPlaceSite); if (m_spInPlaceSite) { m_bInPlaceSiteEx = TRUE; m_bWndLess = SUCCEEDED(m_spInPlaceSite->CanWindowlessActivate()); m_bWasOnceWindowless = TRUE; } else { m_spClientSite->QueryInterface(IID_IOleInPlaceSiteEx, (void **)&m_spInPlaceSite); if (m_spInPlaceSite) m_bInPlaceSiteEx = TRUE; else hr = m_spClientSite->QueryInterface(IID_IOleInPlaceSite, (void **)&m_spInPlaceSite); } } _ASSERTE(m_spInPlaceSite); if (!m_spInPlaceSite) return E_FAIL; m_bNegotiatedWnd = TRUE; if (!m_bInPlaceActive) { BOOL bNoRedraw = FALSE; if (m_bWndLess) m_spInPlaceSite->OnInPlaceActivateEx(&bNoRedraw, ACTIVATE_WINDOWLESS); else { if (m_bInPlaceSiteEx) m_spInPlaceSite->OnInPlaceActivateEx(&bNoRedraw, 0); else { HRESULT hr = m_spInPlaceSite->CanInPlaceActivate(); if (FAILED(hr)) return hr; m_spInPlaceSite->OnInPlaceActivate(); } } } m_bInPlaceActive = TRUE; // get location in the parent window, // as well as some information about the parent // OLEINPLACEFRAMEINFO frameInfo; RECT rcPos, rcClip; CComPtr spInPlaceFrame; CComPtr spInPlaceUIWindow; frameInfo.cb = sizeof(OLEINPLACEFRAMEINFO); HWND hwndParent; if (m_spInPlaceSite->GetWindow(&hwndParent) == S_OK) { m_spInPlaceSite->GetWindowContext(&spInPlaceFrame, &spInPlaceUIWindow, &rcPos, &rcClip, &frameInfo); if (!m_bWndLess) { if (m_hWndCD) { ::ShowWindow(m_hWndCD, SW_SHOW); ::SetFocus(m_hWndCD); } else { HWND h = CreateControlWindow(hwndParent, rcPos); _ASSERTE(h == m_hWndCD); } } pIPO->SetObjectRects(&rcPos, &rcClip); } CComPtr spActiveObject; ControlQueryInterface(IID_IOleInPlaceActiveObject, (void**)&spActiveObject); // Gone active by now, take care of UIACTIVATE if (DoesVerbUIActivate(iVerb)) { if (!m_bUIActive) { m_bUIActive = TRUE; hr = m_spInPlaceSite->OnUIActivate(); if (FAILED(hr)) return hr; SetControlFocus(TRUE); // set ourselves up in the host. // if (spActiveObject) { if (spInPlaceFrame) spInPlaceFrame->SetActiveObject(spActiveObject, NULL); if (spInPlaceUIWindow) spInPlaceUIWindow->SetActiveObject(spActiveObject, NULL); } // These lines are deliberately commented out to demonstrate what breaks certain // control containers. // if (spInPlaceFrame) // spInPlaceFrame->SetBorderSpace(NULL); // if (spInPlaceUIWindow) // spInPlaceUIWindow->SetBorderSpace(NULL); } } m_spClientSite->ShowObject(); return S_OK; } HRESULT STDMETHODCALLTYPE CMozillaBrowser::GetClientSite(IOleClientSite **ppClientSite) { NG_TRACE_METHOD(CMozillaBrowser::GetClientSite); NG_ASSERT(ppClientSite); // This fixes a problem in the base class which asserts if the client // site has not been set when this method is called. HRESULT hRes = E_POINTER; if (ppClientSite != NULL) { *ppClientSite = NULL; if (m_spClientSite == NULL) { return S_OK; } } return IOleObjectImpl::GetClientSite(ppClientSite); } ///////////////////////////////////////////////////////////////////////////// // IMozControlBridge HRESULT STDMETHODCALLTYPE CMozillaBrowser::GetWebBrowser(/* [out] */ void __RPC_FAR *__RPC_FAR *aBrowser) { if (!NgIsValidAddress(aBrowser, sizeof(void *))) { NG_ASSERT(0); return SetErrorInfo(E_INVALIDARG); } *aBrowser = NULL; if (mWebBrowser) { nsIWebBrowser *browser = mWebBrowser.get(); NS_ADDREF(browser); *aBrowser = (void *) browser; } return S_OK; } ///////////////////////////////////////////////////////////////////////////// // IWebBrowserImpl nsresult CMozillaBrowser::GetWebNavigation(nsIWebNavigation **aWebNav) { NS_ENSURE_ARG_POINTER(aWebNav); if (!mWebBrowser) return NS_ERROR_FAILURE; return mWebBrowser->QueryInterface(NS_GET_IID(nsIWebNavigation), (void **) aWebNav); } nsresult CMozillaBrowser::GetDOMWindow(nsIDOMWindow **aDOMWindow) { NS_ENSURE_ARG_POINTER(aDOMWindow); if (!mWebBrowser) return NS_ERROR_FAILURE; return mWebBrowser->GetContentDOMWindow(aDOMWindow); } nsresult CMozillaBrowser::GetPrefs(nsIPrefBranch **aPrefBranch) { if (mPrefBranch) *aPrefBranch = mPrefBranch; NS_IF_ADDREF(*aPrefBranch); return (*aPrefBranch) ? NS_OK : NS_ERROR_FAILURE; } PRBool CMozillaBrowser::BrowserIsValid() { NG_TRACE_METHOD(CMozillaBrowser::BrowserIsValid); return mValidBrowserFlag ? PR_TRUE : PR_FALSE; } // Overrides of IWebBrowser / IWebBrowserApp / IWebBrowser2 methods HRESULT STDMETHODCALLTYPE CMozillaBrowser::get_Parent(IDispatch __RPC_FAR *__RPC_FAR *ppDisp) { NG_TRACE_METHOD(CMozillaBrowser::get_Parent); ENSURE_BROWSER_IS_VALID(); if (!NgIsValidAddress(ppDisp, sizeof(IDispatch *))) { NG_ASSERT(0); return SetErrorInfo(E_INVALIDARG); } // Attempt to get the parent object of this control HRESULT hr = E_FAIL; if (m_spClientSite) { hr = m_spClientSite->QueryInterface(IID_IDispatch, (void **) ppDisp); } return (SUCCEEDED(hr)) ? S_OK : E_NOINTERFACE; } HRESULT STDMETHODCALLTYPE CMozillaBrowser::get_Document(IDispatch __RPC_FAR *__RPC_FAR *ppDisp) { NG_TRACE_METHOD(CMozillaBrowser::get_Document); ENSURE_BROWSER_IS_VALID(); if (!NgIsValidAddress(ppDisp, sizeof(IDispatch *))) { NG_ASSERT(0); return SetErrorInfo(E_UNEXPECTED); } *ppDisp = NULL; // Get hold of the DOM document nsIDOMDocument *pIDOMDocument = nsnull; if (FAILED(GetDOMDocument(&pIDOMDocument)) || pIDOMDocument == nsnull) { return S_OK; // return NULL pointer } if (mIERootDocument == NULL) { nsCOMPtr pIDOMHTMLDocument = do_QueryInterface(pIDOMDocument); if (!pIDOMDocument) { return SetErrorInfo(E_FAIL, L"get_Document: not HTML"); } CIEHtmlDocumentInstance::CreateInstance(&mIERootDocument); if (mIERootDocument == NULL) { return SetErrorInfo(E_OUTOFMEMORY, L"get_Document: can't create IERootDocument"); } // addref it so it doesn't go away on us. mIERootDocument->AddRef(); // give it a pointer to us. note that we shouldn't be addref'd by this call, or it would be // a circular reference. mIERootDocument->SetParent(this); mIERootDocument->SetDOMNode(pIDOMDocument); mIERootDocument->SetNative(pIDOMHTMLDocument); } mIERootDocument->QueryInterface(IID_IDispatch, (void **) ppDisp); pIDOMDocument->Release(); return S_OK; } HRESULT STDMETHODCALLTYPE CMozillaBrowser::get_RegisterAsDropTarget(VARIANT_BOOL __RPC_FAR *pbRegister) { NG_TRACE_METHOD(CMozillaBrowser::get_RegisterAsDropTarget); ENSURE_BROWSER_IS_VALID(); if (pbRegister == NULL) { NG_ASSERT(0); return SetErrorInfo(E_INVALIDARG); } *pbRegister = mHaveDropTargetFlag ? VARIANT_TRUE : VARIANT_FALSE; return S_OK; } static BOOL CALLBACK EnumChildProc(HWND hwnd, LPARAM lParam) { ::RevokeDragDrop(hwnd); return TRUE; } HRESULT STDMETHODCALLTYPE CMozillaBrowser::put_RegisterAsDropTarget(VARIANT_BOOL bRegister) { NG_TRACE_METHOD(CMozillaBrowser::put_RegisterAsDropTarget); ENSURE_BROWSER_IS_VALID(); // Register the window as a drop target if (bRegister == VARIANT_TRUE) { if (!mHaveDropTargetFlag) { CDropTargetInstance *pDropTarget = NULL; CDropTargetInstance::CreateInstance(&pDropTarget); if (pDropTarget) { pDropTarget->AddRef(); pDropTarget->SetOwner(this); // Ask the site if it wants to replace this drop target for another one CIPtr(IDropTarget) spDropTarget; CIPtr(IDocHostUIHandler) spDocHostUIHandler = m_spClientSite; if (spDocHostUIHandler) { //if (spDocHostUIHandler->GetDropTarget(pDropTarget, &spDropTarget) != S_OK) if (spDocHostUIHandler->GetDropTarget(pDropTarget, &spDropTarget) == S_OK) { mHaveDropTargetFlag = TRUE; ::RegisterDragDrop(m_hWnd, spDropTarget); //spDropTarget = pDropTarget; } } else //if (spDropTarget) { mHaveDropTargetFlag = TRUE; ::RegisterDragDrop(m_hWnd, pDropTarget); //::RegisterDragDrop(m_hWnd, spDropTarget); } pDropTarget->Release(); } // Now revoke any child window drop targets and pray they aren't // reset by the layout engine. ::EnumChildWindows(m_hWnd, EnumChildProc, (LPARAM) this); } } else { if (mHaveDropTargetFlag) { mHaveDropTargetFlag = FALSE; ::RevokeDragDrop(m_hWnd); } } return S_OK; } /////////////////////////////////////////////////////////////////////////////// // Ole Command Handlers HRESULT _stdcall CMozillaBrowser::PrintHandler(CMozillaBrowser *pThis, const GUID *pguidCmdGroup, DWORD nCmdID, DWORD nCmdexecopt, VARIANT *pvaIn, VARIANT *pvaOut) { BOOL promptUser = (nCmdexecopt & OLECMDEXECOPT_DONTPROMPTUSER) ? FALSE : TRUE; pThis->PrintDocument(promptUser); return S_OK; } HRESULT _stdcall CMozillaBrowser::EditModeHandler(CMozillaBrowser *pThis, const GUID *pguidCmdGroup, DWORD nCmdID, DWORD nCmdexecopt, VARIANT *pvaIn, VARIANT *pvaOut) { BOOL bEditorMode = (nCmdID == IDM_EDITMODE) ? TRUE : FALSE; pThis->SetEditorMode(bEditorMode); return S_OK; } HRESULT _stdcall CMozillaBrowser::EditCommandHandler(CMozillaBrowser *pThis, const GUID *pguidCmdGroup, DWORD nCmdID, DWORD nCmdexecopt, VARIANT *pvaIn, VARIANT *pvaOut) { pThis->OnEditorCommand(nCmdID); return S_OK; } /////////////////////////////////////////////////////////////////////////////// // SimpleDirectoryProvider implementation SimpleDirectoryProvider::SimpleDirectoryProvider() { nsCOMPtr appDataDir; // Attempt to fill appDataDir with a meaningful value. Any error in the process // will cause the constructor to return and IsValid() to return FALSE, CComPtr shellMalloc; SHGetMalloc(&shellMalloc); if (shellMalloc) { LPITEMIDLIST pitemidList = NULL; SHGetSpecialFolderLocation(NULL, CSIDL_APPDATA, &pitemidList); if (pitemidList) { TCHAR szBuffer[MAX_PATH + 1]; if (SUCCEEDED(SHGetPathFromIDList(pitemidList, szBuffer))) { szBuffer[MAX_PATH] = TCHAR('\0'); USES_CONVERSION; NS_NewNativeLocalFile(nsDependentCString(T2A(szBuffer)), TRUE, getter_AddRefs(appDataDir)); } shellMalloc->Free(pitemidList); } } if (!appDataDir) { return; } // Mozilla control paths are // App data - {Application Data}/MozillaControl // App registry - {Application Data}/MozillaControl/registry.dat // Profiles - {Application Data}/MozillaControl/profiles nsresult rv; // Create the root directory PRBool exists; rv = appDataDir->Exists(&exists); if (NS_FAILED(rv) || !exists) return; // MozillaControl application data rv = appDataDir->AppendRelativePath(NS_LITERAL_STRING("MozillaControl")); if (NS_FAILED(rv)) return; rv = appDataDir->Exists(&exists); if (NS_SUCCEEDED(rv) && !exists) rv = appDataDir->Create(nsIFile::DIRECTORY_TYPE, 0775); if (NS_FAILED(rv)) return; // Registry.dat file nsCOMPtr appDataRegAsFile; rv = appDataDir->Clone(getter_AddRefs(appDataRegAsFile)); if (NS_FAILED(rv)) return; nsCOMPtr appDataRegistry = do_QueryInterface(appDataRegAsFile, &rv); if (NS_FAILED(rv)) return; appDataRegistry->AppendRelativePath(NS_LITERAL_STRING("registry.dat")); // Profiles directory nsCOMPtr profileDirAsFile; rv = appDataDir->Clone(getter_AddRefs(profileDirAsFile)); if (NS_FAILED(rv)) return; nsCOMPtr profileDir = do_QueryInterface(profileDirAsFile, &rv); if (NS_FAILED(rv)) return; profileDir->AppendRelativePath(NS_LITERAL_STRING("profiles")); rv = profileDir->Exists(&exists); if (NS_SUCCEEDED(rv) && !exists) rv = profileDir->Create(nsIFile::DIRECTORY_TYPE, 0775); if (NS_FAILED(rv)) return; // Store the member values mApplicationRegistryDir = appDataDir; mApplicationRegistryFile = appDataRegistry; mUserProfileDir = profileDir; } SimpleDirectoryProvider::~SimpleDirectoryProvider() { } BOOL SimpleDirectoryProvider::IsValid() const { return (mApplicationRegistryDir && mApplicationRegistryFile && mUserProfileDir) ? TRUE : FALSE; } NS_IMPL_ISUPPORTS1(SimpleDirectoryProvider, nsIDirectoryServiceProvider) /////////////////////////////////////////////////////////////////////////////// // nsIDirectoryServiceProvider /* nsIFile getFile (in string prop, out PRBool persistent); */ NS_IMETHODIMP SimpleDirectoryProvider::GetFile(const char *prop, PRBool *persistent, nsIFile **_retval) { NS_ENSURE_ARG_POINTER(prop); NS_ENSURE_ARG_POINTER(persistent); NS_ENSURE_ARG_POINTER(_retval); *_retval = nsnull; *persistent = PR_TRUE; // Only need to support NS_APP_APPLICATION_REGISTRY_DIR, NS_APP_APPLICATION_REGISTRY_FILE, and // NS_APP_USER_PROFILES_ROOT_DIR. Unsupported keys fallback to the default service provider nsCOMPtr localFile; nsresult rv = NS_ERROR_FAILURE; if (strcmp(prop, NS_APP_APPLICATION_REGISTRY_DIR) == 0) { localFile = mApplicationRegistryDir; } else if (strcmp(prop, NS_APP_APPLICATION_REGISTRY_FILE) == 0) { localFile = mApplicationRegistryFile; } else if (strcmp(prop, NS_APP_USER_PROFILES_ROOT_DIR) == 0) { localFile = mUserProfileDir; } if (localFile) return CallQueryInterface(localFile, _retval); return rv; } /////////////////////////////////////////////////////////////////////////////// // PrintListener implementation #ifdef NS_PRINTING NS_IMPL_ISUPPORTS1(PrintListener, nsIWebProgressListener) PrintListener::PrintListener() : mComplete(PR_FALSE) { /* member initializers and constructor code */ } PrintListener::~PrintListener() { /* destructor code */ } void PrintListener::WaitForComplete() { MSG msg; HANDLE hFakeEvent = ::CreateEvent(NULL, TRUE, FALSE, NULL); while (!mComplete) { // Process pending messages while (::PeekMessage(&msg, NULL, 0, 0, PM_NOREMOVE)) { if (!::GetMessage(&msg, NULL, 0, 0)) { ::CloseHandle(hFakeEvent); return; } PRBool wasHandled = PR_FALSE; ::NS_HandleEmbeddingEvent(msg, wasHandled); if (wasHandled) continue; ::TranslateMessage(&msg); ::DispatchMessage(&msg); } if (mComplete) break; // Do idle stuff ::MsgWaitForMultipleObjects(1, &hFakeEvent, FALSE, 500, QS_ALLEVENTS); } ::CloseHandle(hFakeEvent); } /* void onStateChange (in nsIWebProgress aWebProgress, in nsIRequest aRequest, in unsigned long aStateFlags, in nsresult aStatus); */ NS_IMETHODIMP PrintListener::OnStateChange(nsIWebProgress *aWebProgress, nsIRequest *aRequest, PRUint32 aStateFlags, nsresult aStatus) { if (aStateFlags & nsIWebProgressListener::STATE_STOP && aStateFlags & nsIWebProgressListener::STATE_IS_DOCUMENT) { mComplete = PR_TRUE; } return NS_OK; } /* void onProgressChange (in nsIWebProgress aWebProgress, in nsIRequest aRequest, in long aCurSelfProgress, in long aMaxSelfProgress, in long aCurTotalProgress, in long aMaxTotalProgress); */ NS_IMETHODIMP PrintListener::OnProgressChange(nsIWebProgress *aWebProgress, nsIRequest *aRequest, PRInt32 aCurSelfProgress, PRInt32 aMaxSelfProgress, PRInt32 aCurTotalProgress, PRInt32 aMaxTotalProgress) { return NS_OK; } /* void onLocationChange (in nsIWebProgress aWebProgress, in nsIRequest aRequest, in nsIURI location); */ NS_IMETHODIMP PrintListener::OnLocationChange(nsIWebProgress *aWebProgress, nsIRequest *aRequest, nsIURI *location) { return NS_OK; } /* void onStatusChange (in nsIWebProgress aWebProgress, in nsIRequest aRequest, in nsresult aStatus, in wstring aMessage); */ NS_IMETHODIMP PrintListener::OnStatusChange(nsIWebProgress *aWebProgress, nsIRequest *aRequest, nsresult aStatus, const PRUnichar *aMessage) { return NS_OK; } /* void onSecurityChange (in nsIWebProgress aWebProgress, in nsIRequest aRequest, in unsigned long state); */ NS_IMETHODIMP PrintListener::OnSecurityChange(nsIWebProgress *aWebProgress, nsIRequest *aRequest, PRUint32 state) { return NS_OK; } #endif