Back to index

lightning-sunbird  0.9+nobinonly
MozillaBrowser.cpp
Go to the documentation of this file.
00001 /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
00002 /* ***** BEGIN LICENSE BLOCK *****
00003  * Version: MPL 1.1/GPL 2.0/LGPL 2.1
00004  *
00005  * The contents of this file are subject to the Mozilla Public License Version
00006  * 1.1 (the "License"); you may not use this file except in compliance with
00007  * the License. You may obtain a copy of the License at
00008  * http://www.mozilla.org/MPL/
00009  *
00010  * Software distributed under the License is distributed on an "AS IS" basis,
00011  * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
00012  * for the specific language governing rights and limitations under the
00013  * License.
00014  *
00015  * The Original Code is mozilla.org code.
00016  *
00017  * The Initial Developer of the Original Code is
00018  * Netscape Communications Corporation.
00019  * Portions created by the Initial Developer are Copyright (C) 1998
00020  * the Initial Developer. All Rights Reserved.
00021  *
00022  * Contributor(s):
00023  *
00024  * Alternatively, the contents of this file may be used under the terms of
00025  * either the GNU General Public License Version 2 or later (the "GPL"), or
00026  * the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
00027  * in which case the provisions of the GPL or the LGPL are applicable instead
00028  * of those above. If you wish to allow use of your version of this file only
00029  * under the terms of either the GPL or the LGPL, and not to allow others to
00030  * use your version of this file under the terms of the MPL, indicate your
00031  * decision by deleting the provisions above and replace them with the notice
00032  * and other provisions required by the GPL or the LGPL. If you do not delete
00033  * the provisions above, a recipient may use your version of this file under
00034  * the terms of any one of the MPL, the GPL or the LGPL.
00035  *
00036  * ***** END LICENSE BLOCK ***** */
00037 
00038 #include "stdafx.h"
00039 #include <string.h>
00040 #include <string>
00041 #include <objidl.h>
00042 //#include <comdef.h>
00043 #include <shlobj.h>
00044 
00045 // commdlg.h is needed to build with WIN32_LEAN_AND_MEAN
00046 #include <commdlg.h>
00047 
00048 #include "MozillaControl.h"
00049 #include "MozillaBrowser.h"
00050 #include "IEHtmlDocument.h"
00051 #include "PropertyDlg.h"
00052 #include "PageSetupDlg.h"
00053 #include "PromptService.h"
00054 #include "HelperAppDlg.h"
00055 #include "WindowCreator.h"
00056 
00057 #include "nsNetUtil.h"
00058 #include "nsCWebBrowser.h"
00059 #include "nsIAtom.h"
00060 #include "nsILocalFile.h"
00061 #include "nsIWebBrowserPersist.h"
00062 #include "nsIClipboardCommands.h"
00063 #include "nsIProfile.h"
00064 #include "nsIPrintOptions.h"
00065 #include "nsIWebBrowserPrint.h"
00066 #include "nsIWidget.h"
00067 #include "nsIWebBrowserFocus.h"
00068 #include "nsAppDirectoryServiceDefs.h"
00069 #include "nsIComponentRegistrar.h"
00070 
00071 #include "nsIDOMWindow.h"
00072 #include "nsIDOMHTMLAnchorElement.h"
00073 #include "nsIDOMNSDocument.h"
00074 
00075 #include "nsEmbedAPI.h"
00076 #include "nsEmbedCID.h"
00077 
00078 #define HACK_NON_REENTRANCY
00079 #ifdef HACK_NON_REENTRANCY
00080 static HANDLE s_hHackedNonReentrancy = NULL;
00081 #endif
00082 
00083 #define NS_PROMPTSERVICE_CID \
00084   {0xa2112d6a, 0x0e28, 0x421f, {0xb4, 0x6a, 0x25, 0xc0, 0xb3, 0x8, 0xcb, 0xd0}}
00085 
00086 #define NS_HELPERAPPLAUNCHERDIALOG_CID \
00087     {0xf68578eb, 0x6ec2, 0x4169, {0xae, 0x19, 0x8c, 0x62, 0x43, 0xf0, 0xab, 0xe1}}
00088 
00089 static NS_DEFINE_CID(kPromptServiceCID, NS_PROMPTSERVICE_CID);
00090 static NS_DEFINE_CID(kHelperAppLauncherDialogCID, NS_HELPERAPPLAUNCHERDIALOG_CID);
00091 
00092 class PrintListener : public nsIWebProgressListener
00093 {
00094     PRBool mComplete;
00095 public:
00096     NS_DECL_ISUPPORTS
00097     NS_DECL_NSIWEBPROGRESSLISTENER
00098 
00099     PrintListener();
00100     virtual ~PrintListener();
00101 
00102     void WaitForComplete();
00103 };
00104 
00105 class SimpleDirectoryProvider :
00106     public nsIDirectoryServiceProvider
00107 {
00108 public:
00109     SimpleDirectoryProvider();
00110     BOOL IsValid() const;
00111 
00112 
00113     NS_DECL_ISUPPORTS
00114     NS_DECL_NSIDIRECTORYSERVICEPROVIDER
00115 
00116 protected:
00117     virtual ~SimpleDirectoryProvider();
00118 
00119     nsCOMPtr<nsILocalFile> mApplicationRegistryDir;
00120     nsCOMPtr<nsILocalFile> mApplicationRegistryFile;
00121     nsCOMPtr<nsILocalFile> mUserProfileDir;
00122 };
00123 
00124 // Default page in design mode. The data protocol may or may not be supported
00125 // so the scheme is checked before the page is loaded.
00126 
00127 static const char kDesignModeScheme[] = "data";
00128 static const OLECHAR kDesignModeURL[] =
00129     L"data:text/html,<html><body bgcolor=\"#00FF00\"><p>Mozilla Control</p></body></html>";
00130 
00131 // Registry keys and values
00132 
00133 static const TCHAR kBrowserHelperObjectRegKey[] =
00134     _T("Software\\Mozilla\\ActiveX Control\\Browser Helper Objects");
00135 
00136 
00137 // Some recent SDKs define these IOleCommandTarget groups, so they're
00138 // postfixed with _Moz to prevent linker errors.
00139 
00140 GUID CGID_IWebBrowser_Moz =
00141     { 0xED016940L, 0xBD5B, 0x11cf, {0xBA, 0x4E, 0x00, 0xC0, 0x4F, 0xD7, 0x08, 0x16} };
00142 
00143 GUID CGID_MSHTML_Moz =
00144     { 0xED016940L, 0xBD5B, 0x11cf, {0xBA, 0x4E, 0x00, 0xC0, 0x4F, 0xD7, 0x08, 0x16} };
00145 
00147 // CMozillaBrowser
00148 
00149 
00150 nsVoidArray CMozillaBrowser::sBrowserList;
00151 
00152 //
00153 // Constructor
00154 //
00155 CMozillaBrowser::CMozillaBrowser()
00156 {
00157     NG_TRACE_METHOD(CMozillaBrowser::CMozillaBrowser);
00158 
00159     // ATL flags ensures the control opens with a window
00160     m_bWindowOnly = TRUE;
00161     m_bWndLess = FALSE;
00162 
00163     // Initialize layout interfaces
00164     mWebBrowserAsWin = nsnull;
00165     mValidBrowserFlag = FALSE;
00166 
00167     // Create the container that handles some things for us
00168     mWebBrowserContainer = NULL;
00169 
00170     // Control starts off in non-edit mode
00171     mEditModeFlag = FALSE;
00172 
00173     // Control starts off without being a drop target
00174     mHaveDropTargetFlag = FALSE;
00175 
00176      // the IHTMLDocument, lazy allocation.
00177      mIERootDocument = NULL;
00178 
00179     // Browser helpers
00180     mBrowserHelperList = NULL;
00181     mBrowserHelperListCount = 0;
00182 
00183     // Name of the default profile to use
00184     mProfileName.AssignLiteral("MozillaControl");
00185 
00186     // Initialise the web browser
00187     Initialize();
00188 }
00189 
00190 
00191 //
00192 // Destructor
00193 //
00194 CMozillaBrowser::~CMozillaBrowser()
00195 {
00196     NG_TRACE_METHOD(CMozillaBrowser::~CMozillaBrowser);
00197     
00198     // Close the web browser
00199     Terminate();
00200 }
00201 
00202 // See bug 127982:
00203 //
00204 // Microsoft's InlineIsEqualGUID global function is multiply defined
00205 // in ATL and/or SDKs with varying namespace requirements. To save the control
00206 // from future grief, this method is used instead. 
00207 static inline BOOL _IsEqualGUID(REFGUID rguid1, REFGUID rguid2)
00208 {
00209    return (
00210       ((PLONG) &rguid1)[0] == ((PLONG) &rguid2)[0] &&
00211       ((PLONG) &rguid1)[1] == ((PLONG) &rguid2)[1] &&
00212       ((PLONG) &rguid1)[2] == ((PLONG) &rguid2)[2] &&
00213       ((PLONG) &rguid1)[3] == ((PLONG) &rguid2)[3]);
00214 }
00215 
00216 STDMETHODIMP CMozillaBrowser::InterfaceSupportsErrorInfo(REFIID riid)
00217 {
00218     static const IID* arr[] = 
00219     {
00220         &IID_IWebBrowser,
00221         &IID_IWebBrowser2,
00222         &IID_IWebBrowserApp
00223     };
00224     for (int i = 0; i < (sizeof(arr) / sizeof(arr[0])); i++)
00225     {
00226         if (_IsEqualGUID(*arr[i], riid))
00227             return S_OK;
00228     }
00229     return S_FALSE;
00230 }
00231 
00232 //
00233 // ShowContextMenu
00234 //
00235 void CMozillaBrowser::ShowContextMenu(PRUint32 aContextFlags, nsIDOMEvent *aEvent, nsIDOMNode *aNode)
00236 {
00237     POINT pt;
00238     GetCursorPos(&pt);
00239 
00240     // Give the client application the chance to show its own menu
00241     // in place of the one the control is about to show.
00242 
00243     CIPtr(IDocHostUIHandler) spIDocHostUIHandler = m_spClientSite;
00244     if (spIDocHostUIHandler)
00245     {
00246         enum IE4MenuContexts
00247         {
00248             ctxMenuDefault = 0,
00249             ctxMenuImage,
00250             ctxMenuControl,
00251             ctxMenuTable,
00252             ctxMenuDebug,
00253             ctxMenu1DSelect,
00254             ctxMenuAnchor,
00255             ctxMenuImgDynSrc
00256         };
00257 
00258         DWORD dwID = ctxMenuDefault;
00259         if (aContextFlags & nsIContextMenuListener::CONTEXT_DOCUMENT)
00260         {
00261             dwID = ctxMenuDefault;
00262         }
00263         else if (aContextFlags & nsIContextMenuListener::CONTEXT_LINK)
00264         {
00265             dwID = ctxMenuAnchor;
00266         }
00267         else if (aContextFlags & nsIContextMenuListener::CONTEXT_IMAGE)
00268         {
00269             dwID = ctxMenuImage;
00270         }
00271         else if (aContextFlags & nsIContextMenuListener::CONTEXT_TEXT)
00272         {
00273             dwID = ctxMenu1DSelect;
00274         }
00275         else
00276         {
00277             dwID = ctxMenuDefault;
00278         }
00279 
00280         HRESULT hr = spIDocHostUIHandler->ShowContextMenu(dwID, &pt, NULL, NULL);
00281         if (hr == S_OK)
00282         {
00283             // Client handled menu
00284             return;
00285         }
00286     }
00287 
00288     LPTSTR pszMenuResource = NULL;
00289     if (aContextFlags & nsIContextMenuListener::CONTEXT_DOCUMENT)
00290     {
00291         pszMenuResource = MAKEINTRESOURCE(IDR_POPUP_DOCUMENT);
00292     }
00293     else if (aContextFlags & nsIContextMenuListener::CONTEXT_LINK)
00294     {
00295         pszMenuResource = MAKEINTRESOURCE(IDR_POPUP_LINK);
00296     }
00297     else if (aContextFlags & nsIContextMenuListener::CONTEXT_IMAGE)
00298     {
00299         pszMenuResource = MAKEINTRESOURCE(IDR_POPUP_IMAGE);
00300     }
00301     else if (aContextFlags & nsIContextMenuListener::CONTEXT_TEXT)
00302     {
00303         pszMenuResource = MAKEINTRESOURCE(IDR_POPUP_TEXT);
00304     }
00305     else
00306     {
00307         pszMenuResource = MAKEINTRESOURCE(IDR_POPUP_DOCUMENT);
00308     }
00309 
00310     if (pszMenuResource)
00311     {
00312         HMENU hMenu = LoadMenu(_Module.m_hInstResource, pszMenuResource);
00313         HMENU hPopupMenu = GetSubMenu(hMenu, 0);
00314         mContextNode = do_QueryInterface(aNode);
00315         UINT nCmd = TrackPopupMenu(hPopupMenu, TPM_NONOTIFY | TPM_RETURNCMD, pt.x, pt.y, 0, m_hWnd, NULL);
00316         DestroyMenu(hMenu);
00317         if (nCmd != 0)
00318         {
00319             SendMessage(WM_COMMAND, nCmd);
00320         }
00321         mContextNode = nsnull;
00322     }
00323 }
00324 
00325 
00326 //
00327 // ShowURIPropertyDlg
00328 //
00329 void CMozillaBrowser::ShowURIPropertyDlg(const nsAString &aURI, const nsAString &aContentType)
00330 {
00331     CPropertyDlg dlg;
00332     CPPageDlg linkDlg;
00333     dlg.AddPage(&linkDlg);
00334 
00335     if (!aURI.IsEmpty())
00336     {
00337         linkDlg.mType = aContentType;
00338         linkDlg.mURL = aURI;
00339     }
00340 
00341     dlg.DoModal();
00342 }
00343 
00344 
00345 //
00346 // Displays a message box to the user. If the container provides
00347 // a IDocHostShowUI interface we use that to display messages, otherwise
00348 // a simple message box is shown.
00349 //
00350 int CMozillaBrowser::MessageBox(LPCTSTR lpszText, LPCTSTR lpszCaption, UINT nType)
00351 {
00352     // Let the doc host display it's own message box if it can
00353     CIPtr(IDocHostShowUI) spIDocHostShowUI = m_spClientSite;
00354     if (spIDocHostShowUI)
00355     {
00356         USES_CONVERSION;
00357         LRESULT lResult = 0;
00358         HRESULT hr = spIDocHostShowUI->ShowMessage(m_hWnd,
00359                         T2OLE(lpszText), T2OLE(lpszCaption), nType, NULL, 0, &lResult);
00360         if (hr == S_OK)
00361         {
00362             return lResult;
00363         }
00364     }
00365 
00366     // Do the default message box
00367     return CWindow::MessageBox(lpszText, lpszCaption, nType);
00368 }
00369 
00370 
00371 //
00372 // Sets the startup error message from a resource string
00373 //
00374 HRESULT CMozillaBrowser::SetStartupErrorMessage(UINT nStringID)
00375 {
00376     TCHAR szMsg[1024];
00377     ::LoadString(_Module.m_hInstResource, nStringID, szMsg, sizeof(szMsg) / sizeof(szMsg[0]));
00378     mStartupErrorMessage = szMsg;
00379     return S_OK;
00380 }
00381 
00382 //
00383 // Tells the container to change focus to the next control in the dialog.
00384 //
00385 void CMozillaBrowser::NextDlgControl()
00386 {
00387     HWND hwndParent = GetParent();
00388     if (::IsWindow(hwndParent))
00389     {
00390       ::PostMessage(hwndParent, WM_NEXTDLGCTL, 0, 0);
00391     }
00392 }
00393 
00394 
00395 //
00396 // Tells the container to change focus to the previous control in the dialog.
00397 //
00398 void CMozillaBrowser::PrevDlgControl()
00399 {
00400     HWND hwndParent = GetParent();
00401     if (::IsWindow(hwndParent))
00402     {
00403       ::PostMessage(hwndParent, WM_NEXTDLGCTL, 1, 0);
00404     }
00405 }
00406 
00407 
00409 // Message handlers
00410 
00411 
00412 // Handle WM_CREATE windows message
00413 LRESULT CMozillaBrowser::OnCreate(UINT uMsg, WPARAM wParam, LPARAM lParam, BOOL& bHandled)
00414 {
00415     NG_TRACE_METHOD(CMozillaBrowser::OnCreate);
00416 
00417     // Create the web browser
00418     CreateBrowser();
00419 
00420     // TODO create and register a drop target
00421 
00422     // Control is ready
00423     mBrowserReadyState = READYSTATE_COMPLETE;
00424     FireOnChanged(DISPID_READYSTATE);
00425 
00426     // Load browser helpers
00427     LoadBrowserHelpers();
00428 
00429     // Browse to a default page - if in design mode
00430     BOOL bUserMode = FALSE;
00431     if (SUCCEEDED(GetAmbientUserMode(bUserMode)))
00432     {
00433         if (!bUserMode)
00434         {
00435             // Load a page in design mode if the specified page is supported
00436             nsCOMPtr<nsIIOService> ios = do_GetIOService();
00437             if (ios)
00438             {
00439                 // Ensure design page can be loaded by checking for a
00440                 // registered protocol handler that supports the scheme
00441                 nsCOMPtr<nsIProtocolHandler> ph;
00442                 nsCAutoString phScheme;
00443                 ios->GetProtocolHandler(kDesignModeScheme, getter_AddRefs(ph));
00444                 if (ph &&
00445                     NS_SUCCEEDED(ph->GetScheme(phScheme)) &&
00446                     phScheme.LowerCaseEqualsASCII(kDesignModeScheme))
00447                 {
00448                     Navigate(const_cast<BSTR>(kDesignModeURL), NULL, NULL, NULL, NULL);
00449                 }
00450             }
00451         }
00452     }
00453 
00454     // Clip the child windows out of paint operations
00455     SetWindowLong(GWL_STYLE, GetWindowLong(GWL_STYLE) | WS_CLIPCHILDREN | WS_TABSTOP);
00456 
00457     return 0;
00458 }
00459 
00460 
00461 // Handle WM_DESTROY window message
00462 LRESULT CMozillaBrowser::OnDestroy(UINT uMsg, WPARAM wParam, LPARAM lParam, BOOL& bHandled)
00463 {
00464     NG_TRACE_METHOD(CMozillaBrowser::OnDestroy);
00465 
00466     // Unload browser helpers
00467     UnloadBrowserHelpers();
00468 
00469     // Clean up the browser
00470     DestroyBrowser();
00471 
00472     return 0;
00473 }
00474 
00475 
00476 // Handle WM_SIZE windows message
00477 LRESULT CMozillaBrowser::OnSize(UINT uMsg, WPARAM wParam, LPARAM lParam, BOOL& bHandled)
00478 {
00479     NG_TRACE_METHOD(CMozillaBrowser::OnSize);
00480 
00481     RECT rc;
00482     rc.top = 0;
00483     rc.left = 0;
00484     rc.right = LOWORD(lParam);
00485     rc.bottom = HIWORD(lParam);
00486     
00487     AdjustWindowRectEx(&rc, GetWindowLong(GWL_STYLE), FALSE, GetWindowLong(GWL_EXSTYLE));
00488 
00489     rc.right -= rc.left;
00490     rc.bottom -= rc.top;
00491     rc.left = 0;
00492     rc.top = 0;
00493 
00494     // Pass resize information down to the browser...
00495     if (mWebBrowserAsWin)
00496     {
00497         mWebBrowserAsWin->SetPosition(rc.left, rc.top);
00498         mWebBrowserAsWin->SetSize(rc.right - rc.left, rc.bottom - rc.top, PR_TRUE);
00499     }
00500     return 0;
00501 }
00502 
00503 // Handle WM_SETFOCUS
00504 LRESULT CMozillaBrowser::OnSetFocus(UINT uMsg, WPARAM wParam, LPARAM lParam, BOOL& bHandled)
00505 {
00506     ATLTRACE(_T("CMozillaBrowser::OnSetFocus()\n"));
00507     nsCOMPtr<nsIWebBrowserFocus> browserAsFocus = do_QueryInterface(mWebBrowser);
00508     if (browserAsFocus)
00509     {
00510         browserAsFocus->Activate();
00511     }
00512     CComQIPtr<IOleControlSite> controlSite = m_spClientSite;
00513     if (controlSite)
00514     {
00515         controlSite->OnFocus(TRUE);
00516     }
00517     return 0;
00518 }
00519 
00520 // Handle WM_KILLFOCUS
00521 LRESULT CMozillaBrowser::OnKillFocus(UINT uMsg, WPARAM wParam, LPARAM lParam, BOOL& bHandled)
00522 {
00523     ATLTRACE(_T("CMozillaBrowser::OnKillFocus()\n"));
00524     nsCOMPtr<nsIWebBrowserFocus> browserAsFocus = do_QueryInterface(mWebBrowser);
00525     if (browserAsFocus)
00526     {
00527         browserAsFocus->Deactivate();
00528     }
00529     CComQIPtr<IOleControlSite> controlSite = m_spClientSite;
00530     if (controlSite)
00531     {
00532         controlSite->OnFocus(FALSE);
00533     }
00534     return 0;
00535 }
00536 
00537 // Handle WM_MOUSEACTIVATE messages
00538 LRESULT CMozillaBrowser::OnMouseActivate(UINT uMsg, WPARAM wParam, LPARAM lParam, BOOL& bHandled)
00539 {
00540     return MA_ACTIVATE;
00541 }
00542 
00543 // Handle WM_GETDLGCODE to receive keyboard presses
00544 LRESULT CMozillaBrowser::OnGetDlgCode(UINT uMsg, WPARAM wParam, LPARAM lParam, BOOL& bHandled)
00545 {
00546     return DLGC_WANTALLKEYS; 
00547 }
00548 
00549 // Handle WM_PAINT windows message (and IViewObject::Draw) 
00550 HRESULT CMozillaBrowser::OnDraw(ATL_DRAWINFO& di)
00551 {
00552     NG_TRACE_METHOD(CMozillaBrowser::OnDraw);
00553 
00554     if (!BrowserIsValid())
00555     {
00556         RECT& rc = *(RECT*)di.prcBounds;
00557         DrawText(di.hdcDraw, mStartupErrorMessage.c_str(), -1, &rc, DT_TOP | DT_LEFT | DT_WORDBREAK);
00558     }
00559 
00560     return S_OK;
00561 }
00562 
00563 // Handle ID_PAGESETUP command
00564 LRESULT CMozillaBrowser::OnPageSetup(WORD wNotifyCode, WORD wID, HWND hWndCtl, BOOL& bHandled)
00565 {
00566     NG_TRACE_METHOD(CMozillaBrowser::OnPageSetup);
00567 
00568 
00569     nsCOMPtr<nsIWebBrowserPrint> print(do_GetInterface(mWebBrowser));
00570     nsCOMPtr<nsIPrintSettings> printSettings;
00571     if(!print ||
00572         NS_FAILED(print->GetGlobalPrintSettings(getter_AddRefs(printSettings))))
00573     {
00574         return 0;
00575     }
00576 
00577     // show the page setup dialog
00578     CPageSetupDlg dlg(printSettings);
00579     dlg.DoModal();
00580 
00581     return 0;
00582 }
00583 
00584 // Handle ID_PRINT command
00585 LRESULT CMozillaBrowser::OnPrint(WORD wNotifyCode, WORD wID, HWND hWndCtl, BOOL& bHandled)
00586 {
00587     NG_TRACE_METHOD(CMozillaBrowser::OnPrint);
00588     if (!BrowserIsValid())
00589     {
00590         return 0;
00591     }
00592     PrintDocument(TRUE);
00593     return 0;
00594 }
00595 
00596 LRESULT CMozillaBrowser::OnSaveAs(WORD wNotifyCode, WORD wID, HWND hWndCtl, BOOL& bHandled)
00597 {
00598     NG_TRACE_METHOD(CMozillaBrowser::OnSaveAs);
00599 
00600     OPENFILENAME SaveFileName;
00601 
00602     char szFile[_MAX_PATH];
00603     char szFileTitle[256];
00604 
00605     //TODO:    The IE control allows you to also save as "Web Page, complete"
00606     //      where all of the page's images are saved in the same directory.
00607     //      For the moment, we're not allowing this option.
00608 
00609     memset(&SaveFileName, 0, sizeof(SaveFileName));
00610     SaveFileName.lStructSize = sizeof(SaveFileName);
00611     SaveFileName.hwndOwner = m_hWnd;
00612     SaveFileName.lpstrFilter = "Web Page, HTML Only (*.htm;*.html)\0*.htm;*.html\0Text File (*.txt)\0*.txt\0"; 
00613     SaveFileName.nFilterIndex = 1; 
00614     SaveFileName.lpstrFile = szFile; 
00615     SaveFileName.nMaxFile = sizeof(szFile); 
00616     SaveFileName.lpstrFileTitle = szFileTitle;
00617     SaveFileName.nMaxFileTitle = sizeof(szFileTitle); 
00618     SaveFileName.Flags = OFN_HIDEREADONLY | OFN_OVERWRITEPROMPT; 
00619     SaveFileName.lpstrDefExt = "htm"; 
00620 
00621     //Get the title of the current web page to set as the default filename.
00622     char szTmp[_MAX_FNAME] = "untitled";
00623     BSTR pageName = NULL;
00624     get_LocationName(&pageName); // Page title
00625     if (pageName)
00626     {
00627         USES_CONVERSION;
00628         strncpy(szTmp, OLE2A(pageName), sizeof(szTmp) - 1);
00629         SysFreeString(pageName);
00630         szTmp[sizeof(szTmp) - 1] = '\0';
00631     }
00632     
00633     // The SaveAs dialog will fail if szFile contains any "bad" characters.
00634     // This hunk of code attempts to mimick the IE way of replacing "bad"
00635     // characters with "good" characters.
00636     int j = 0;
00637     for (int i=0; szTmp[i]!='\0'; i++)
00638     {        
00639         switch(szTmp[i])
00640         {
00641         case '\\':
00642         case '*':
00643         case '|':
00644         case ':':
00645         case '"':
00646         case '>':
00647         case '<':
00648         case '?':
00649             break;
00650         case '.':
00651             if (szTmp[i+1] != '\0')
00652             {
00653                 szFile[j] = '_';
00654                 j++;
00655             }
00656             break;
00657         case '/':
00658             szFile[j] = '-';
00659             j++;
00660             break;
00661         default:
00662             szFile[j] = szTmp[i];
00663             j++;
00664         }
00665     }
00666     szFile[j] = '\0';
00667 
00668     HRESULT hr = S_OK;
00669     if (GetSaveFileName(&SaveFileName))
00670     {
00671         nsCOMPtr<nsIWebBrowserPersist> persist(do_QueryInterface(mWebBrowser));
00672         USES_CONVERSION;
00673 
00674         char szDataFile[_MAX_PATH];
00675         char szDataPath[_MAX_PATH];
00676         char drive[_MAX_DRIVE];
00677         char dir[_MAX_DIR];
00678         char fname[_MAX_FNAME];
00679         char ext[_MAX_EXT];
00680 
00681         _splitpath(szFile, drive, dir, fname, ext);
00682         sprintf(szDataFile, "%s_files", fname);
00683         _makepath(szDataPath, drive, dir, szDataFile, "");
00684 
00685         nsCOMPtr<nsILocalFile> file;
00686         NS_NewNativeLocalFile(nsDependentCString(T2A(szFile)), TRUE, getter_AddRefs(file));
00687 
00688         nsCOMPtr<nsILocalFile> dataPath;
00689         NS_NewNativeLocalFile(nsDependentCString(szDataPath), TRUE, getter_AddRefs(dataPath));
00690 
00691         persist->SaveDocument(nsnull, file, dataPath, nsnull, 0, 0);
00692     }
00693 
00694     return hr;
00695 }
00696 
00697 LRESULT CMozillaBrowser::OnProperties(WORD wNotifyCode, WORD wID, HWND hWndCtl, BOOL& bHandled)
00698 {
00699     NG_TRACE_METHOD(CMozillaBrowser::OnProperties);
00700     MessageBox(_T("No Properties Yet!"), _T("Control Message"), MB_OK);
00701     // TODO show the properties dialog
00702     return 0;
00703 }
00704 
00705 LRESULT CMozillaBrowser::OnCut(WORD wNotifyCode, WORD wID, HWND hWndCtl, BOOL& bHandled)
00706 {
00707     NG_TRACE_METHOD(CMozillaBrowser::OnCut);
00708     nsCOMPtr<nsIClipboardCommands> clipboard(do_GetInterface(mWebBrowser));
00709     if (clipboard)
00710     {
00711         clipboard->CutSelection();
00712     }
00713     return 0;
00714 }
00715 
00716 LRESULT CMozillaBrowser::OnCopy(WORD wNotifyCode, WORD wID, HWND hWndCtl, BOOL& bHandled)
00717 {
00718     NG_TRACE_METHOD(CMozillaBrowser::OnCopy);
00719     nsCOMPtr<nsIClipboardCommands> clipboard(do_GetInterface(mWebBrowser));
00720     if (clipboard)
00721     {
00722         clipboard->CopySelection();
00723     }
00724     return 0;
00725 }
00726 
00727 LRESULT CMozillaBrowser::OnPaste(WORD wNotifyCode, WORD wID, HWND hWndCtl, BOOL& bHandled)
00728 {
00729     NG_TRACE_METHOD(CMozillaBrowser::OnPaste);
00730     nsCOMPtr<nsIClipboardCommands> clipboard(do_GetInterface(mWebBrowser));
00731     if (clipboard)
00732     {
00733         clipboard->Paste();
00734     }
00735     return 0;
00736 }
00737 
00738 LRESULT CMozillaBrowser::OnSelectAll(WORD wNotifyCode, WORD wID, HWND hWndCtl, BOOL& bHandled)
00739 {
00740     NG_TRACE_METHOD(CMozillaBrowser::OnSelectAll);
00741     nsCOMPtr<nsIClipboardCommands> clipboard(do_GetInterface(mWebBrowser));
00742     if (clipboard)
00743     {
00744         clipboard->SelectAll();
00745     }
00746     return 0;
00747 }
00748 
00749 // Handle ID_VIEWSOURCE command
00750 LRESULT CMozillaBrowser::OnViewSource(WORD wNotifyCode, WORD wID, HWND hWndCtl, BOOL& bHandled)
00751 {
00752     NG_TRACE_METHOD(CMozillaBrowser::OnViewSource);
00753 
00754     if (!mWebBrowser)
00755     {
00756         // No webbrowser to view!
00757         NG_ASSERT(0);
00758         return 0;
00759     }
00760 
00761     nsCOMPtr<nsIWebNavigation> webNav = do_QueryInterface(mWebBrowser);
00762     if (!webNav)
00763     {
00764         // No webnav!
00765         NG_ASSERT(0);
00766         return 0;
00767     }
00768 
00769     nsCOMPtr<nsIURI> uri;
00770     webNav->GetCurrentURI(getter_AddRefs(uri));
00771     if (!uri)
00772     {
00773         // No URI to view!
00774         NG_ASSERT(0);
00775         return 0;
00776     }
00777 
00778     // Get the current URI
00779     nsCAutoString aURI;
00780     uri->GetSpec(aURI);
00781 
00782     nsAutoString strURI(NS_LITERAL_STRING("view-source:"));
00783     AppendUTF8toUTF16(aURI, strURI);
00784 
00785     // Ask the client to create a window to view the source in
00786     CIPtr(IDispatch) spDispNew;
00787     VARIANT_BOOL bCancel = VARIANT_FALSE;
00788     Fire_NewWindow2(&spDispNew, &bCancel);
00789 
00790     // Load the view-source into a new url
00791     if ((bCancel == VARIANT_FALSE) && spDispNew)
00792     {
00793         CIPtr(IWebBrowser2) spOther = spDispNew;;
00794         if (spOther)
00795         {
00796             // tack in the viewsource command
00797             CComBSTR bstrURL(strURI.get());
00798             CComVariant vURL(bstrURL);
00799             VARIANT vNull;
00800             vNull.vt = VT_NULL;
00801             spOther->Navigate2(&vURL, &vNull, &vNull, &vNull, &vNull);            
00802         }
00803     }
00804 
00805     return 0;
00806 }
00807 
00808 
00810 // Document handlers
00811 
00812 
00813 LRESULT CMozillaBrowser::OnDocumentBack(WORD wNotifyCode, WORD wID, HWND hWndCtl, BOOL& bHandled)
00814 {
00815     GoBack();
00816     return 0;
00817 }
00818 
00819 
00820 LRESULT CMozillaBrowser::OnDocumentForward(WORD wNotifyCode, WORD wID, HWND hWndCtl, BOOL& bHandled)
00821 {
00822     GoForward();
00823     return 0;
00824 }
00825 
00826 
00827 LRESULT CMozillaBrowser::OnDocumentPrint(WORD wNotifyCode, WORD wID, HWND hWndCtl, BOOL& bHandled)
00828 {
00829     return OnPrint(wNotifyCode, wID, hWndCtl, bHandled);
00830 }
00831 
00832 
00833 LRESULT CMozillaBrowser::OnDocumentRefresh(WORD wNotifyCode, WORD wID, HWND hWndCtl, BOOL& bHandled)
00834 {
00835     Refresh();
00836     return 0;
00837 }
00838 
00839 
00840 LRESULT CMozillaBrowser::OnDocumentProperties(WORD wNotifyCode, WORD wID, HWND hWndCtl, BOOL& bHandled)
00841 {
00842     nsCOMPtr<nsIDOMDocument> ownerDoc;
00843     if (mContextNode)
00844     {
00845         mContextNode->GetOwnerDocument(getter_AddRefs(ownerDoc));
00846     }
00847 
00848     // Get the document URL
00849     nsAutoString uri;
00850     nsCOMPtr<nsIDOMHTMLDocument> htmlDoc = do_QueryInterface(ownerDoc);
00851     if (htmlDoc)
00852     {
00853         htmlDoc->GetURL(uri);
00854     }
00855     nsAutoString contentType;
00856     nsCOMPtr<nsIDOMNSDocument> doc = do_QueryInterface(ownerDoc);
00857     if (doc)
00858     {
00859         doc->GetContentType(contentType);
00860     }
00861 
00862     ShowURIPropertyDlg(uri, contentType);
00863 
00864     return 0;
00865 }
00866 
00867 
00869 // Link handlers
00870 
00871 
00872 LRESULT CMozillaBrowser::OnLinkOpen(WORD wNotifyCode, WORD wID, HWND hWndCtl, BOOL& bHandled)
00873 {
00874     nsAutoString uri;
00875 
00876     nsCOMPtr<nsIDOMHTMLAnchorElement> anchorElement = do_QueryInterface(mContextNode);
00877     if (anchorElement)
00878     {
00879         anchorElement->GetHref(uri);
00880     }
00881 
00882     if (!uri.IsEmpty())
00883     {
00884         CComBSTR bstrURI(uri.get());
00885         CComVariant vFlags(0);
00886         Navigate(bstrURI, &vFlags, NULL, NULL, NULL);
00887     }
00888 
00889     return 0;
00890 }
00891 
00892 
00893 LRESULT CMozillaBrowser::OnLinkOpenInNewWindow(WORD wNotifyCode, WORD wID, HWND hWndCtl, BOOL& bHandled)
00894 {
00895     nsAutoString uri;
00896 
00897     nsCOMPtr<nsIDOMHTMLAnchorElement> anchorElement = do_QueryInterface(mContextNode);
00898     if (anchorElement)
00899     {
00900         anchorElement->GetHref(uri);
00901     }
00902 
00903     if (!uri.IsEmpty())
00904     {
00905         CComBSTR bstrURI(uri.get());
00906         CComVariant vFlags(navOpenInNewWindow);
00907         Navigate(bstrURI, &vFlags, NULL, NULL, NULL);
00908     }
00909 
00910     return 0;
00911 }
00912 
00913 
00914 LRESULT CMozillaBrowser::OnLinkCopyShortcut(WORD wNotifyCode, WORD wID, HWND hWndCtl, BOOL& bHandled)
00915 {
00916     nsAutoString uri;
00917 
00918     nsCOMPtr<nsIDOMHTMLAnchorElement> anchorElement = do_QueryInterface(mContextNode);
00919     if (anchorElement)
00920     {
00921         anchorElement->GetHref(uri);
00922     }
00923 
00924     if (!uri.IsEmpty() && OpenClipboard())
00925     {
00926         EmptyClipboard();
00927 
00928         // CF_TEXT
00929         HGLOBAL hmemText = GlobalAlloc(GMEM_MOVEABLE | GMEM_ZEROINIT, uri.Length() + 1);
00930         char *pszText = (char *) GlobalLock(hmemText);
00931         uri.ToCString(pszText, uri.Length() + 1);
00932         GlobalUnlock(hmemText);
00933         SetClipboardData(CF_TEXT, hmemText);
00934 
00935         // UniformResourceLocator - CFSTR_SHELLURL
00936         const UINT cfShellURL = RegisterClipboardFormat(CFSTR_SHELLURL);
00937         HGLOBAL hmemURL = GlobalAlloc(GMEM_MOVEABLE | GMEM_ZEROINIT, uri.Length() + 1);
00938         char *pszURL = (char *) GlobalLock(hmemURL);
00939         uri.ToCString(pszURL, uri.Length() + 1);
00940         GlobalUnlock(hmemURL);
00941         SetClipboardData(cfShellURL, hmemURL);
00942 
00943         // TODO
00944         // FileContents - CFSTR_FILECONTENTS
00945         // FileGroupDescriptor - CFSTR_FILEDESCRIPTORA
00946         // FileGroupDescriptorW - CFSTR_FILEDESCRIPTORW
00947 
00948         CloseClipboard();
00949     }
00950     return 0;
00951 }
00952 
00953 
00954 LRESULT CMozillaBrowser::OnLinkProperties(WORD wNotifyCode, WORD wID, HWND hWndCtl, BOOL& bHandled)
00955 {
00956     nsAutoString uri;
00957     nsAutoString type;
00958 
00959     nsCOMPtr<nsIDOMHTMLAnchorElement> anchorElement = do_QueryInterface(mContextNode);
00960     if (anchorElement)
00961     {
00962         anchorElement->GetHref(uri);
00963         anchorElement->GetType(type); // How many anchors implement this I wonder
00964     }
00965 
00966     ShowURIPropertyDlg(uri, type);
00967 
00968     return 0;
00969 }
00970 
00971 
00973 
00974 // Initialises the web browser engine
00975 HRESULT CMozillaBrowser::Initialize()
00976 {
00977 #ifdef HACK_NON_REENTRANCY
00978     // Attempt to open a named event for this process. If it's not there we
00979     // know this is the first time the control has run in this process, so create
00980     // the named event and do the initialisation. Otherwise do nothing.
00981     TCHAR szHackEvent[255];
00982     _stprintf(szHackEvent, _T("MozCtlEvent%d"), (int) GetCurrentProcessId());
00983     s_hHackedNonReentrancy = OpenEvent(EVENT_ALL_ACCESS, FALSE, szHackEvent);
00984     if (s_hHackedNonReentrancy == NULL)
00985     {
00986         s_hHackedNonReentrancy = CreateEvent(NULL, FALSE, FALSE, szHackEvent);
00987 #endif
00988 
00989     // Extract the bin directory path from the control's filename
00990     TCHAR szMozCtlPath[MAX_PATH];
00991     memset(szMozCtlPath, 0, sizeof(szMozCtlPath));
00992     GetModuleFileName(_Module.m_hInst, szMozCtlPath, sizeof(szMozCtlPath) / sizeof(szMozCtlPath[0]));
00993 
00994     TCHAR szTmpDrive[_MAX_DRIVE];
00995     TCHAR szTmpDir[_MAX_DIR];
00996     TCHAR szTmpFname[_MAX_FNAME];
00997     TCHAR szTmpExt[_MAX_EXT];
00998     TCHAR szBinDirPath[MAX_PATH];
00999 
01000     _tsplitpath(szMozCtlPath, szTmpDrive, szTmpDir, szTmpFname, szTmpExt);
01001     memset(szBinDirPath, 0, sizeof(szBinDirPath));
01002     _tmakepath(szBinDirPath, szTmpDrive, szTmpDir, NULL, NULL);
01003     if (_tcslen(szBinDirPath) == 0)
01004     {
01005         return E_FAIL;
01006     }
01007 
01008     // Create a simple directory provider. If this fails because the directories are
01009     // invalid or whatever then the control will fallback on the default directory
01010     // provider.
01011 
01012     nsCOMPtr<nsIDirectoryServiceProvider> directoryProvider;
01013     SimpleDirectoryProvider *pDirectoryProvider = new SimpleDirectoryProvider;
01014     if (pDirectoryProvider->IsValid())
01015         directoryProvider = do_QueryInterface(pDirectoryProvider);
01016 
01017     // Create an object to represent the path
01018     nsresult rv;
01019     nsCOMPtr<nsILocalFile> binDir;
01020     USES_CONVERSION;
01021     NS_NewNativeLocalFile(nsDependentCString(T2A(szBinDirPath)), TRUE, getter_AddRefs(binDir));
01022     rv = NS_InitEmbedding(binDir, directoryProvider);
01023 
01024     // Load preferences service
01025     mPrefBranch = do_GetService(NS_PREFSERVICE_CONTRACTID, &rv);
01026     if (NS_FAILED(rv))
01027     {
01028         NG_ASSERT(0);
01029         NG_TRACE_ALWAYS(_T("Could not create preference object rv=%08x\n"), (int) rv);
01030         SetStartupErrorMessage(IDS_CANNOTCREATEPREFS);
01031         return E_FAIL;
01032     }
01033 
01034     // Stuff in here only needs to be done once
01035     static BOOL bRegisterComponents = FALSE;
01036     if (!bRegisterComponents)
01037     {
01038         // Register our own native prompting service for message boxes, login
01039         // prompts etc.
01040         nsCOMPtr<nsIFactory> promptFactory;
01041         rv = NS_NewPromptServiceFactory(getter_AddRefs(promptFactory));
01042         if (NS_FAILED(rv)) return rv;
01043 
01044         nsCOMPtr<nsIComponentRegistrar> registrar;
01045         rv = NS_GetComponentRegistrar(getter_AddRefs(registrar));
01046         if (NS_FAILED(rv)) return rv;
01047 
01048         rv = registrar->RegisterFactory(kPromptServiceCID,
01049             "Prompt Service",
01050             NS_PROMPTSERVICE_CONTRACTID,
01051             promptFactory);
01052         if (NS_FAILED(rv)) return rv;
01053 
01054         // Helper app launcher dialog
01055         nsCOMPtr<nsIFactory> helperAppDlgFactory;
01056         rv = NS_NewHelperAppLauncherDlgFactory(getter_AddRefs(helperAppDlgFactory));
01057         if (NS_FAILED(rv)) return rv;
01058 
01059         rv = registrar->RegisterFactory(kHelperAppLauncherDialogCID,
01060             "Helper App Launcher Dialog",
01061             "@mozilla.org/helperapplauncherdialog;1",
01062             helperAppDlgFactory);
01063         if (NS_FAILED(rv)) return rv;
01064 
01065         // create our local object
01066         CWindowCreator *creator = new CWindowCreator();
01067         nsCOMPtr<nsIWindowCreator> windowCreator;
01068         windowCreator = NS_STATIC_CAST(nsIWindowCreator *, creator);
01069 
01070         // Attach it via the watcher service
01071         nsCOMPtr<nsIWindowWatcher> watcher =
01072             do_GetService(NS_WINDOWWATCHER_CONTRACTID);
01073         if (watcher)
01074             watcher->SetWindowCreator(windowCreator);
01075     }
01076 
01077     // Set the profile which the control will use
01078     nsCOMPtr<nsIProfile> profileService = 
01079              do_GetService(NS_PROFILE_CONTRACTID, &rv);
01080     if (NS_FAILED(rv))
01081     {
01082         return E_FAIL;
01083     }
01084 
01085     // Make a new default profile
01086     PRBool profileExists = PR_FALSE;
01087     rv = profileService->ProfileExists(mProfileName.get(), &profileExists);
01088     if (NS_FAILED(rv))
01089     {
01090         return E_FAIL;
01091     }
01092     else if (!profileExists)
01093     {
01094         rv = profileService->CreateNewProfile(mProfileName.get(), nsnull, nsnull, PR_FALSE);
01095         if (NS_FAILED(rv))
01096         {
01097             return E_FAIL;
01098         }
01099     }
01100 
01101     rv = profileService->SetCurrentProfile(mProfileName.get());
01102     if (NS_FAILED(rv))
01103     {
01104         return E_FAIL;
01105     }
01106 
01107 #ifdef HACK_NON_REENTRANCY
01108     }
01109 #endif
01110 
01111     return S_OK;
01112 }
01113 
01114 // Terminates the web browser engine
01115 HRESULT CMozillaBrowser::Terminate()
01116 {
01117 #ifdef HACK_NON_REENTRANCY
01118     if (0)
01119     {
01120 #endif
01121 
01122     mPrefBranch = nsnull;
01123     NS_TermEmbedding();
01124 
01125 #ifdef HACK_NON_REENTRANCY
01126     }
01127 #endif
01128 
01129     return S_OK;
01130 }
01131 
01132 
01133 // Create and initialise the web browser
01134 HRESULT CMozillaBrowser::CreateBrowser() 
01135 {    
01136     NG_TRACE_METHOD(CMozillaBrowser::CreateBrowser);
01137     
01138     if (mWebBrowser != nsnull)
01139     {
01140         NG_ASSERT(0);
01141         NG_TRACE_ALWAYS(_T("CreateBrowser() called more than once!"));
01142         return SetErrorInfo(E_UNEXPECTED);
01143     }
01144 
01145     RECT rcLocation;
01146     GetClientRect(&rcLocation);
01147     if (IsRectEmpty(&rcLocation))
01148     {
01149         rcLocation.bottom++;
01150         rcLocation.top++;
01151     }
01152 
01153     nsresult rv;
01154 
01155     // Create the web browser
01156     mWebBrowser = do_CreateInstance(NS_WEBBROWSER_CONTRACTID, &rv);
01157     if (NS_FAILED(rv))
01158     {
01159         NG_ASSERT(0);
01160         NG_TRACE_ALWAYS(_T("Could not create webbrowser object rv=%08x\n"), (int) rv);
01161         SetStartupErrorMessage(IDS_CANNOTCREATEPREFS);
01162         return rv;
01163     }
01164 
01165     // Configure what the web browser can and cannot do
01166     nsCOMPtr<nsIWebBrowserSetup> webBrowserAsSetup(do_QueryInterface(mWebBrowser));
01167 
01168     // Allow plugins?
01169     const PRBool kAllowPlugins = PR_TRUE;
01170     webBrowserAsSetup->SetProperty(nsIWebBrowserSetup::SETUP_ALLOW_PLUGINS, kAllowPlugins);
01171 
01172     // Host chrome or content?
01173     const PRBool kHostChrome = PR_FALSE; // Hardcoded for now
01174     webBrowserAsSetup->SetProperty(nsIWebBrowserSetup::SETUP_IS_CHROME_WRAPPER, PR_FALSE);
01175 
01176     // Create the webbrowser window
01177     mWebBrowserAsWin = do_QueryInterface(mWebBrowser);
01178     rv = mWebBrowserAsWin->InitWindow(nsNativeWidget(m_hWnd), nsnull,
01179         0, 0, rcLocation.right - rcLocation.left, rcLocation.bottom - rcLocation.top);
01180     rv = mWebBrowserAsWin->Create();
01181 
01182     // Create the container object
01183     mWebBrowserContainer = new CWebBrowserContainer(this);
01184     if (mWebBrowserContainer == NULL)
01185     {
01186         NG_ASSERT(0);
01187         NG_TRACE_ALWAYS(_T("Could not create webbrowsercontainer - out of memory\n"));
01188         return NS_ERROR_OUT_OF_MEMORY;
01189     }
01190     mWebBrowserContainer->AddRef();
01191 
01192     // Set up the browser with its chrome
01193     mWebBrowser->SetContainerWindow(NS_STATIC_CAST(nsIWebBrowserChrome*, mWebBrowserContainer));
01194     mWebBrowser->SetParentURIContentListener(mWebBrowserContainer);
01195 
01196     // Subscribe for progress notifications
01197     nsCOMPtr<nsIWeakReference> listener(
01198         do_GetWeakReference(NS_STATIC_CAST(nsIWebProgressListener*, mWebBrowserContainer)));
01199     mWebBrowser->AddWebBrowserListener(listener, NS_GET_IID(nsIWebProgressListener));
01200 
01201     // Visible
01202     mWebBrowserAsWin->SetVisibility(PR_TRUE);
01203 
01204     // Activated
01205     nsCOMPtr<nsIWebBrowserFocus> browserAsFocus = do_QueryInterface(mWebBrowser);
01206     browserAsFocus->Activate();
01207 
01208     // Get an editor session
01209     mEditingSession = do_GetInterface(mWebBrowser);
01210     mCommandManager = do_GetInterface(mWebBrowser);
01211 
01212     // Append browser to browser list
01213     sBrowserList.AppendElement(this);
01214 
01215     mValidBrowserFlag = TRUE;
01216 
01217     return S_OK;
01218 }
01219 
01220 // Clean up the browser
01221 HRESULT CMozillaBrowser::DestroyBrowser()
01222 {
01223     // TODO unregister drop target
01224 
01225     mValidBrowserFlag = FALSE;
01226 
01227     // Remove browser from browser list
01228     sBrowserList.RemoveElement(this);
01229 
01230      // Destroy the htmldoc
01231      if (mIERootDocument != NULL)
01232      {
01233          mIERootDocument->Release();
01234          mIERootDocument = NULL;
01235      }
01236 
01237     // Destroy layout...
01238     if (mWebBrowserAsWin)
01239     {
01240         mWebBrowserAsWin->Destroy();
01241         mWebBrowserAsWin = nsnull;
01242     }
01243 
01244     if (mWebBrowserContainer)
01245     {
01246         mWebBrowserContainer->Release();
01247         mWebBrowserContainer = NULL;
01248     }
01249 
01250     mEditingSession = nsnull;
01251     mCommandManager = nsnull;
01252     mWebBrowser = nsnull;
01253 
01254     return S_OK;
01255 }
01256 
01257 
01258 // Turns the editor mode on or off
01259 HRESULT CMozillaBrowser::SetEditorMode(BOOL bEnabled)
01260 {
01261     NG_TRACE_METHOD(CMozillaBrowser::SetEditorMode);
01262 
01263     if (!mEditingSession || !mCommandManager)
01264         return E_FAIL;
01265   
01266     nsCOMPtr<nsIDOMWindow> domWindow;
01267     nsresult rv = GetDOMWindow(getter_AddRefs(domWindow));
01268     if (NS_FAILED(rv))
01269         return E_FAIL;
01270 
01271     rv = mEditingSession->MakeWindowEditable(domWindow, "html", PR_FALSE);
01272  
01273     return S_OK;
01274 }
01275 
01276 
01277 HRESULT CMozillaBrowser::OnEditorCommand(DWORD nCmdID)
01278 {
01279     NG_TRACE_METHOD(CMozillaBrowser::OnEditorCommand);
01280 
01281     nsCOMPtr<nsIDOMWindow> domWindow;
01282     GetDOMWindow(getter_AddRefs(domWindow));
01283 
01284     const char *styleCommand = nsnull;
01285     nsICommandParams *commandParams = nsnull;
01286 
01287     switch (nCmdID)
01288     {
01289     case IDM_BOLD:
01290         styleCommand = "cmd_bold";
01291         break;
01292     case IDM_ITALIC:
01293         styleCommand = "cmd_italic";
01294         break;
01295     case IDM_UNDERLINE:
01296         styleCommand = "cmd_underline";
01297         break;
01298     
01299     // TODO add the rest!
01300     
01301     default:
01302         // DO NOTHING
01303         break;
01304     }
01305 
01306     return mCommandManager ?
01307         mCommandManager->DoCommand(styleCommand, commandParams, domWindow) :
01308         NS_ERROR_FAILURE;
01309 }
01310 
01311 
01312 // Return the root DOM document
01313 HRESULT CMozillaBrowser::GetDOMDocument(nsIDOMDocument **pDocument)
01314 {
01315     NG_TRACE_METHOD(CMozillaBrowser::GetDOMDocument);
01316 
01317     HRESULT hr = E_FAIL;
01318 
01319     // Test for stupid args
01320     if (pDocument == NULL)
01321     {
01322         NG_ASSERT(0);
01323         return E_INVALIDARG;
01324     }
01325 
01326     *pDocument = nsnull;
01327 
01328     if (!BrowserIsValid())
01329     {
01330         NG_ASSERT(0);
01331         return E_UNEXPECTED;
01332     }
01333 
01334     // Get the DOM window from the webbrowser
01335     nsCOMPtr<nsIDOMWindow> window;
01336     mWebBrowser->GetContentDOMWindow(getter_AddRefs(window));
01337     if (window)
01338     {
01339         if (NS_SUCCEEDED(window->GetDocument(pDocument)) && *pDocument)
01340         {
01341             hr = S_OK;
01342         }
01343     }
01344 
01345     return hr;
01346 }
01347 
01348 
01349 // Load any browser helpers
01350 HRESULT CMozillaBrowser::LoadBrowserHelpers()
01351 {
01352     NG_TRACE_METHOD(CMozillaBrowser::LoadBrowserHelpers);
01353 
01354     UnloadBrowserHelpers();
01355 
01356     // IE loads browser helper objects from a branch of the registry
01357     // Search the branch looking for objects to load with the control.
01358 
01359     CRegKey cKey;
01360     if (cKey.Open(HKEY_LOCAL_MACHINE, kBrowserHelperObjectRegKey, KEY_ENUMERATE_SUB_KEYS) != ERROR_SUCCESS)
01361     {
01362         NG_TRACE(_T("No browser helper key found\n"));
01363         return S_FALSE;
01364     }
01365 
01366     // Count the number of browser helper object keys
01367     ULONG nHelperKeys = 0;
01368     LONG nResult = ERROR_SUCCESS;
01369     while (nResult == ERROR_SUCCESS)
01370     {
01371         TCHAR szCLSID[50];
01372         DWORD dwCLSID = sizeof(szCLSID) / sizeof(TCHAR);
01373         FILETIME cLastWrite;
01374         
01375         // Read next subkey
01376         nResult = RegEnumKeyEx(cKey, nHelperKeys, szCLSID, &dwCLSID, NULL, NULL, NULL, &cLastWrite);
01377         if (nResult != ERROR_SUCCESS)
01378         {
01379             break;
01380         }
01381         nHelperKeys++;
01382     }
01383     if (nHelperKeys == 0)
01384     {
01385          NG_TRACE(_T("No browser helper objects found\n"));
01386         return S_FALSE;
01387     }
01388 
01389     // Get the CLSID for each browser helper object
01390     CLSID *pClassList = new CLSID[nHelperKeys];
01391     DWORD nHelpers = 0;
01392     DWORD nKey = 0;
01393     nResult = ERROR_SUCCESS;
01394     while (nResult == ERROR_SUCCESS)
01395     {
01396         TCHAR szCLSID[50];
01397         DWORD dwCLSID = sizeof(szCLSID) / sizeof(TCHAR);
01398         FILETIME cLastWrite;
01399         
01400         // Read next subkey
01401         nResult = RegEnumKeyEx(cKey, nKey++, szCLSID, &dwCLSID, NULL, NULL, NULL, &cLastWrite);
01402         if (nResult != ERROR_SUCCESS)
01403         {
01404             break;
01405         }
01406 
01407         NG_TRACE(_T("Reading helper object entry \"%s\"\n"), szCLSID);
01408 
01409         // Turn the key into a CLSID
01410         USES_CONVERSION;
01411         CLSID clsid;
01412         if (CLSIDFromString(T2OLE(szCLSID), &clsid) != NOERROR)
01413         {
01414             continue;
01415         }
01416 
01417         pClassList[nHelpers++] = clsid;
01418     }
01419 
01420     mBrowserHelperList = new CComUnkPtr[nHelpers];
01421 
01422     // Create each object in turn
01423     for (ULONG i = 0; i < nHelpers; i++)
01424     {
01425         CLSID clsid = pClassList[i];
01426         HRESULT hr;
01427         CComQIPtr<IObjectWithSite, &IID_IObjectWithSite> cpObjectWithSite;
01428 
01429         hr = CoCreateInstance(clsid, NULL, CLSCTX_INPROC_SERVER, IID_IObjectWithSite, (LPVOID *) &cpObjectWithSite);
01430         if (FAILED(hr))
01431         {
01432             NG_TRACE(_T("Registered browser helper object cannot be created\n"));;
01433         }
01434         else
01435         {
01436             // Set the object to point at the browser
01437             cpObjectWithSite->SetSite((IWebBrowser2 *) this);
01438 
01439             // Store in the list
01440             CComUnkPtr cpUnk = cpObjectWithSite;
01441             mBrowserHelperList[mBrowserHelperListCount++] = cpUnk;
01442         }
01443     }
01444 
01445     delete []pClassList;
01446         
01447     return S_OK;
01448 }
01449 
01450 // Release browser helpers
01451 HRESULT CMozillaBrowser::UnloadBrowserHelpers()
01452 {
01453     NG_TRACE_METHOD(CMozillaBrowser::UnloadBrowserHelpers);
01454 
01455     if (mBrowserHelperList == NULL)
01456     {
01457         return S_OK;
01458     }
01459 
01460     // Destroy each helper    
01461     for (ULONG i = 0; i < mBrowserHelperListCount; i++)
01462     {
01463         CComUnkPtr cpUnk = mBrowserHelperList[i];
01464         if (cpUnk)
01465         {
01466             CComQIPtr<IObjectWithSite, &IID_IObjectWithSite> cpObjectWithSite = cpUnk;
01467             if (cpObjectWithSite)
01468             {
01469                 cpObjectWithSite->SetSite(NULL);
01470             }
01471         }
01472     }
01473 
01474     // Cleanup the array
01475     mBrowserHelperListCount = 0;
01476     delete []mBrowserHelperList;
01477     mBrowserHelperList = NULL;
01478 
01479     return S_OK;
01480 }
01481 
01482 // Print document
01483 HRESULT CMozillaBrowser::PrintDocument(BOOL promptUser)
01484 {
01485     // Print the contents
01486     nsCOMPtr<nsIWebBrowserPrint> browserAsPrint = do_GetInterface(mWebBrowser);
01487     NS_ASSERTION(browserAsPrint, "No nsIWebBrowserPrint!");
01488 
01489     PRBool oldPrintSilent = PR_FALSE;
01490     nsCOMPtr<nsIPrintSettings> printSettings;
01491     browserAsPrint->GetGlobalPrintSettings(getter_AddRefs(printSettings));
01492     if (printSettings) 
01493     {
01494         printSettings->GetPrintSilent(&oldPrintSilent);
01495         printSettings->SetPrintSilent(promptUser ? PR_FALSE : PR_TRUE);
01496     }
01497 
01498     // Disable print progress dialog (XUL)
01499     PRBool oldShowPrintProgress = FALSE;
01500     const char *kShowPrintProgressPref = "print.show_print_progress";
01501     mPrefBranch->GetBoolPref(kShowPrintProgressPref, &oldShowPrintProgress);
01502     mPrefBranch->SetBoolPref(kShowPrintProgressPref, PR_FALSE);
01503 
01504     // Print
01505     PrintListener *listener = new PrintListener;
01506     nsCOMPtr<nsIWebProgressListener> printListener = do_QueryInterface(listener);
01507     nsresult rv = browserAsPrint->Print(printSettings, printListener);
01508     if (NS_SUCCEEDED(rv))
01509     {
01510         listener->WaitForComplete();
01511     }
01512 
01513     // Cleanup
01514     if (printSettings)
01515     {
01516         printSettings->SetPrintSilent(oldPrintSilent);
01517     }
01518     mPrefBranch->SetBoolPref(kShowPrintProgressPref, oldShowPrintProgress);
01519 
01520     return S_OK;
01521 }
01522 
01524 // IOleObject overrides
01525 
01526 // This is an almost verbatim copy of the standard ATL implementation of
01527 // IOleObject::InPlaceActivate but with a few lines commented out.
01528 
01529 HRESULT CMozillaBrowser::InPlaceActivate(LONG iVerb, const RECT* prcPosRect)
01530 {
01531     NG_TRACE_METHOD(CMozillaBrowser::InPlaceActivate);
01532 
01533     HRESULT hr;
01534 
01535     if (m_spClientSite == NULL)
01536         return S_OK;
01537 
01538     CComPtr<IOleInPlaceObject> pIPO;
01539     ControlQueryInterface(IID_IOleInPlaceObject, (void**)&pIPO);
01540     _ASSERTE(pIPO != NULL);
01541     if (prcPosRect != NULL)
01542         pIPO->SetObjectRects(prcPosRect, prcPosRect);
01543 
01544     if (!m_bNegotiatedWnd)
01545     {
01546         if (!m_bWindowOnly)
01547             // Try for windowless site
01548             hr = m_spClientSite->QueryInterface(IID_IOleInPlaceSiteWindowless, (void **)&m_spInPlaceSite);
01549 
01550         if (m_spInPlaceSite)
01551         {
01552             m_bInPlaceSiteEx = TRUE;
01553             m_bWndLess = SUCCEEDED(m_spInPlaceSite->CanWindowlessActivate());
01554             m_bWasOnceWindowless = TRUE;
01555         }
01556         else
01557         {
01558             m_spClientSite->QueryInterface(IID_IOleInPlaceSiteEx, (void **)&m_spInPlaceSite);
01559             if (m_spInPlaceSite)
01560                 m_bInPlaceSiteEx = TRUE;
01561             else
01562                 hr = m_spClientSite->QueryInterface(IID_IOleInPlaceSite, (void **)&m_spInPlaceSite);
01563         }
01564     }
01565 
01566     _ASSERTE(m_spInPlaceSite);
01567     if (!m_spInPlaceSite)
01568         return E_FAIL;
01569 
01570     m_bNegotiatedWnd = TRUE;
01571 
01572     if (!m_bInPlaceActive)
01573     {
01574 
01575         BOOL bNoRedraw = FALSE;
01576         if (m_bWndLess)
01577             m_spInPlaceSite->OnInPlaceActivateEx(&bNoRedraw, ACTIVATE_WINDOWLESS);
01578         else
01579         {
01580             if (m_bInPlaceSiteEx)
01581                 m_spInPlaceSite->OnInPlaceActivateEx(&bNoRedraw, 0);
01582             else
01583             {
01584                 HRESULT hr = m_spInPlaceSite->CanInPlaceActivate();
01585                 if (FAILED(hr))
01586                     return hr;
01587                 m_spInPlaceSite->OnInPlaceActivate();
01588             }
01589         }
01590     }
01591 
01592     m_bInPlaceActive = TRUE;
01593 
01594     // get location in the parent window,
01595     // as well as some information about the parent
01596     //
01597     OLEINPLACEFRAMEINFO frameInfo;
01598     RECT rcPos, rcClip;
01599     CComPtr<IOleInPlaceFrame> spInPlaceFrame;
01600     CComPtr<IOleInPlaceUIWindow> spInPlaceUIWindow;
01601     frameInfo.cb = sizeof(OLEINPLACEFRAMEINFO);
01602     HWND hwndParent;
01603     if (m_spInPlaceSite->GetWindow(&hwndParent) == S_OK)
01604     {
01605         m_spInPlaceSite->GetWindowContext(&spInPlaceFrame,
01606             &spInPlaceUIWindow, &rcPos, &rcClip, &frameInfo);
01607 
01608         if (!m_bWndLess)
01609         {
01610             if (m_hWndCD)
01611             {
01612                 ::ShowWindow(m_hWndCD, SW_SHOW);
01613                 ::SetFocus(m_hWndCD);
01614             }
01615             else
01616             {
01617                 HWND h = CreateControlWindow(hwndParent, rcPos);
01618                 _ASSERTE(h == m_hWndCD);
01619             }
01620         }
01621 
01622         pIPO->SetObjectRects(&rcPos, &rcClip);
01623     }
01624 
01625     CComPtr<IOleInPlaceActiveObject> spActiveObject;
01626     ControlQueryInterface(IID_IOleInPlaceActiveObject, (void**)&spActiveObject);
01627 
01628     // Gone active by now, take care of UIACTIVATE
01629     if (DoesVerbUIActivate(iVerb))
01630     {
01631         if (!m_bUIActive)
01632         {
01633             m_bUIActive = TRUE;
01634             hr = m_spInPlaceSite->OnUIActivate();
01635             if (FAILED(hr))
01636                 return hr;
01637 
01638             SetControlFocus(TRUE);
01639             // set ourselves up in the host.
01640             //
01641             if (spActiveObject)
01642             {
01643                 if (spInPlaceFrame)
01644                     spInPlaceFrame->SetActiveObject(spActiveObject, NULL);
01645                 if (spInPlaceUIWindow)
01646                     spInPlaceUIWindow->SetActiveObject(spActiveObject, NULL);
01647             }
01648 
01649 // These lines are deliberately commented out to demonstrate what breaks certain
01650 // control containers.
01651 
01652 //            if (spInPlaceFrame)
01653 //                spInPlaceFrame->SetBorderSpace(NULL);
01654 //            if (spInPlaceUIWindow)
01655 //                spInPlaceUIWindow->SetBorderSpace(NULL);
01656         }
01657     }
01658 
01659     m_spClientSite->ShowObject();
01660 
01661     return S_OK;
01662 }
01663 
01664 
01665 HRESULT STDMETHODCALLTYPE CMozillaBrowser::GetClientSite(IOleClientSite **ppClientSite)
01666 {
01667     NG_TRACE_METHOD(CMozillaBrowser::GetClientSite);
01668 
01669     NG_ASSERT(ppClientSite);
01670 
01671     // This fixes a problem in the base class which asserts if the client
01672     // site has not been set when this method is called. 
01673 
01674     HRESULT hRes = E_POINTER;
01675     if (ppClientSite != NULL)
01676     {
01677         *ppClientSite = NULL;
01678         if (m_spClientSite == NULL)
01679         {
01680             return S_OK;
01681         }
01682     }
01683 
01684     return IOleObjectImpl<CMozillaBrowser>::GetClientSite(ppClientSite);
01685 }
01686 
01687 
01689 // IMozControlBridge
01690 
01691 
01692 HRESULT STDMETHODCALLTYPE CMozillaBrowser::GetWebBrowser(/* [out] */ void __RPC_FAR *__RPC_FAR *aBrowser)
01693 {
01694     if (!NgIsValidAddress(aBrowser, sizeof(void *)))
01695     {
01696         NG_ASSERT(0);
01697         return SetErrorInfo(E_INVALIDARG);
01698     }
01699 
01700     *aBrowser = NULL;
01701     if (mWebBrowser)
01702     {
01703         nsIWebBrowser *browser = mWebBrowser.get();
01704         NS_ADDREF(browser);
01705         *aBrowser = (void *) browser;
01706     }
01707     return S_OK;
01708 }
01709 
01711 // IWebBrowserImpl
01712 
01713 nsresult CMozillaBrowser::GetWebNavigation(nsIWebNavigation **aWebNav)
01714 {
01715     NS_ENSURE_ARG_POINTER(aWebNav);
01716     if (!mWebBrowser) return NS_ERROR_FAILURE;
01717     return mWebBrowser->QueryInterface(NS_GET_IID(nsIWebNavigation), (void **) aWebNav);
01718 }
01719 
01720 nsresult CMozillaBrowser::GetDOMWindow(nsIDOMWindow **aDOMWindow)
01721 {
01722     NS_ENSURE_ARG_POINTER(aDOMWindow);
01723     if (!mWebBrowser) return NS_ERROR_FAILURE;
01724     return mWebBrowser->GetContentDOMWindow(aDOMWindow);
01725 }
01726 
01727 nsresult CMozillaBrowser::GetPrefs(nsIPrefBranch **aPrefBranch)
01728 {
01729     if (mPrefBranch)
01730         *aPrefBranch = mPrefBranch;
01731     NS_IF_ADDREF(*aPrefBranch);
01732     return (*aPrefBranch) ? NS_OK : NS_ERROR_FAILURE;
01733 }
01734 
01735 PRBool CMozillaBrowser::BrowserIsValid()
01736 {
01737     NG_TRACE_METHOD(CMozillaBrowser::BrowserIsValid);
01738     return mValidBrowserFlag ? PR_TRUE : PR_FALSE;
01739 }
01740 
01741 // Overrides of IWebBrowser / IWebBrowserApp / IWebBrowser2 methods
01742 
01743 HRESULT STDMETHODCALLTYPE CMozillaBrowser::get_Parent(IDispatch __RPC_FAR *__RPC_FAR *ppDisp)
01744 {
01745     NG_TRACE_METHOD(CMozillaBrowser::get_Parent);
01746     ENSURE_BROWSER_IS_VALID();
01747 
01748     if (!NgIsValidAddress(ppDisp, sizeof(IDispatch *)))
01749     {
01750         NG_ASSERT(0);
01751         return SetErrorInfo(E_INVALIDARG);
01752     }
01753 
01754     // Attempt to get the parent object of this control
01755     HRESULT hr = E_FAIL;
01756     if (m_spClientSite)
01757     {
01758         hr = m_spClientSite->QueryInterface(IID_IDispatch, (void **) ppDisp);
01759     }
01760 
01761     return (SUCCEEDED(hr)) ? S_OK : E_NOINTERFACE;
01762 }
01763 
01764 HRESULT STDMETHODCALLTYPE CMozillaBrowser::get_Document(IDispatch __RPC_FAR *__RPC_FAR *ppDisp)
01765 {
01766     NG_TRACE_METHOD(CMozillaBrowser::get_Document);
01767     ENSURE_BROWSER_IS_VALID();
01768 
01769     if (!NgIsValidAddress(ppDisp, sizeof(IDispatch *)))
01770     {
01771         NG_ASSERT(0);
01772         return SetErrorInfo(E_UNEXPECTED);
01773     }
01774 
01775     *ppDisp = NULL;
01776 
01777     // Get hold of the DOM document
01778     nsIDOMDocument *pIDOMDocument = nsnull;
01779     if (FAILED(GetDOMDocument(&pIDOMDocument)) || pIDOMDocument == nsnull)
01780     {
01781         return S_OK; // return NULL pointer
01782     }
01783 
01784     if (mIERootDocument == NULL)
01785      {    
01786         nsCOMPtr <nsIDOMHTMLDocument> pIDOMHTMLDocument =
01787                 do_QueryInterface(pIDOMDocument);
01788 
01789         if (!pIDOMDocument)
01790         {
01791             return SetErrorInfo(E_FAIL, L"get_Document: not HTML");
01792         }
01793 
01794          CIEHtmlDocumentInstance::CreateInstance(&mIERootDocument);
01795           if (mIERootDocument == NULL)
01796          {
01797             return SetErrorInfo(E_OUTOFMEMORY, L"get_Document: can't create IERootDocument");
01798          }
01799          
01800         // addref it so it doesn't go away on us.
01801          mIERootDocument->AddRef();
01802  
01803          // give it a pointer to us.  note that we shouldn't be addref'd by this call, or it would be 
01804          // a circular reference.
01805          mIERootDocument->SetParent(this);
01806         mIERootDocument->SetDOMNode(pIDOMDocument);
01807         mIERootDocument->SetNative(pIDOMHTMLDocument);
01808     }
01809 
01810     mIERootDocument->QueryInterface(IID_IDispatch, (void **) ppDisp);
01811     pIDOMDocument->Release();
01812 
01813     return S_OK;
01814 }
01815 
01816 HRESULT STDMETHODCALLTYPE CMozillaBrowser::get_RegisterAsDropTarget(VARIANT_BOOL __RPC_FAR *pbRegister)
01817 {
01818     NG_TRACE_METHOD(CMozillaBrowser::get_RegisterAsDropTarget);
01819     ENSURE_BROWSER_IS_VALID();
01820 
01821     if (pbRegister == NULL)
01822     {
01823         NG_ASSERT(0);
01824         return SetErrorInfo(E_INVALIDARG);
01825     }
01826 
01827     *pbRegister = mHaveDropTargetFlag ? VARIANT_TRUE : VARIANT_FALSE;
01828     return S_OK;
01829 }
01830 
01831 
01832 
01833 static BOOL CALLBACK EnumChildProc(HWND hwnd, LPARAM lParam)
01834 {
01835     ::RevokeDragDrop(hwnd);
01836     return TRUE;
01837 }
01838  
01839 
01840 HRESULT STDMETHODCALLTYPE CMozillaBrowser::put_RegisterAsDropTarget(VARIANT_BOOL bRegister)
01841 {
01842     NG_TRACE_METHOD(CMozillaBrowser::put_RegisterAsDropTarget);
01843     ENSURE_BROWSER_IS_VALID();
01844 
01845     // Register the window as a drop target
01846     if (bRegister == VARIANT_TRUE)
01847     {
01848         if (!mHaveDropTargetFlag)
01849         {
01850             CDropTargetInstance *pDropTarget = NULL;
01851             CDropTargetInstance::CreateInstance(&pDropTarget);
01852             if (pDropTarget)
01853             {
01854                 pDropTarget->AddRef();
01855                 pDropTarget->SetOwner(this);
01856 
01857 
01858                 // Ask the site if it wants to replace this drop target for another one
01859                 CIPtr(IDropTarget) spDropTarget;
01860                 CIPtr(IDocHostUIHandler) spDocHostUIHandler = m_spClientSite;
01861                 if (spDocHostUIHandler)
01862                 {
01863                     //if (spDocHostUIHandler->GetDropTarget(pDropTarget, &spDropTarget) != S_OK)
01864                     if (spDocHostUIHandler->GetDropTarget(pDropTarget, &spDropTarget) == S_OK)
01865                     {
01866                         mHaveDropTargetFlag = TRUE;
01867                         ::RegisterDragDrop(m_hWnd, spDropTarget);
01868                         //spDropTarget = pDropTarget;
01869                     }
01870                 }
01871                 else
01872                 //if (spDropTarget)
01873                 {
01874                     mHaveDropTargetFlag = TRUE;
01875                     ::RegisterDragDrop(m_hWnd, pDropTarget);
01876                     //::RegisterDragDrop(m_hWnd, spDropTarget);
01877                 }
01878                 pDropTarget->Release();
01879             }
01880             // Now revoke any child window drop targets and pray they aren't
01881             // reset by the layout engine.
01882             ::EnumChildWindows(m_hWnd, EnumChildProc, (LPARAM) this);
01883         }
01884     }
01885     else
01886     {
01887         if (mHaveDropTargetFlag)
01888         {
01889             mHaveDropTargetFlag = FALSE;
01890             ::RevokeDragDrop(m_hWnd);
01891         }
01892     }
01893 
01894     return S_OK;
01895 }
01896 
01897 
01899 // Ole Command Handlers
01900 
01901 
01902 HRESULT _stdcall CMozillaBrowser::PrintHandler(CMozillaBrowser *pThis, const GUID *pguidCmdGroup, DWORD nCmdID, DWORD nCmdexecopt, VARIANT *pvaIn, VARIANT *pvaOut)
01903 {
01904     BOOL promptUser = (nCmdexecopt & OLECMDEXECOPT_DONTPROMPTUSER) ? FALSE : TRUE;
01905     pThis->PrintDocument(promptUser);
01906     return S_OK;
01907 }
01908 
01909 
01910 HRESULT _stdcall CMozillaBrowser::EditModeHandler(CMozillaBrowser *pThis, const GUID *pguidCmdGroup, DWORD nCmdID, DWORD nCmdexecopt, VARIANT *pvaIn, VARIANT *pvaOut)
01911 {
01912     BOOL bEditorMode = (nCmdID == IDM_EDITMODE) ? TRUE : FALSE;
01913     pThis->SetEditorMode(bEditorMode);
01914     return S_OK;
01915 }
01916 
01917 
01918 HRESULT _stdcall CMozillaBrowser::EditCommandHandler(CMozillaBrowser *pThis, const GUID *pguidCmdGroup, DWORD nCmdID, DWORD nCmdexecopt, VARIANT *pvaIn, VARIANT *pvaOut)
01919 {
01920     pThis->OnEditorCommand(nCmdID);
01921     return S_OK;
01922 }
01923 
01924 
01926 // SimpleDirectoryProvider implementation
01927 
01928 SimpleDirectoryProvider::SimpleDirectoryProvider()
01929 {
01930     nsCOMPtr<nsILocalFile> appDataDir;
01931 
01932     // Attempt to fill appDataDir with a meaningful value. Any error in the process
01933     // will cause the constructor to return and IsValid() to return FALSE,
01934 
01935     CComPtr<IMalloc> shellMalloc;
01936     SHGetMalloc(&shellMalloc);
01937     if (shellMalloc)
01938     {
01939         LPITEMIDLIST pitemidList = NULL;
01940         SHGetSpecialFolderLocation(NULL, CSIDL_APPDATA, &pitemidList);
01941         if (pitemidList)
01942         {
01943             TCHAR szBuffer[MAX_PATH + 1];
01944             if (SUCCEEDED(SHGetPathFromIDList(pitemidList, szBuffer)))
01945             {
01946                 szBuffer[MAX_PATH] = TCHAR('\0');
01947                 USES_CONVERSION;
01948                 NS_NewNativeLocalFile(nsDependentCString(T2A(szBuffer)), TRUE, getter_AddRefs(appDataDir));
01949             }
01950             shellMalloc->Free(pitemidList);
01951         }
01952     }
01953     if (!appDataDir)
01954     {
01955         return;
01956     }
01957 
01958     // Mozilla control paths are
01959     // App data     - {Application Data}/MozillaControl
01960     // App registry - {Application Data}/MozillaControl/registry.dat
01961     // Profiles     - {Application Data}/MozillaControl/profiles
01962 
01963     nsresult rv;
01964 
01965     // Create the root directory
01966     PRBool exists;
01967     rv = appDataDir->Exists(&exists);
01968     if (NS_FAILED(rv) || !exists) return;
01969 
01970     // MozillaControl application data
01971     rv = appDataDir->AppendRelativePath(NS_LITERAL_STRING("MozillaControl"));
01972     if (NS_FAILED(rv)) return;
01973     rv = appDataDir->Exists(&exists);
01974     if (NS_SUCCEEDED(rv) && !exists)
01975         rv = appDataDir->Create(nsIFile::DIRECTORY_TYPE, 0775);
01976     if (NS_FAILED(rv)) return;
01977 
01978     // Registry.dat file
01979     nsCOMPtr<nsIFile> appDataRegAsFile;
01980     rv = appDataDir->Clone(getter_AddRefs(appDataRegAsFile));
01981     if (NS_FAILED(rv)) return;
01982     nsCOMPtr<nsILocalFile> appDataRegistry = do_QueryInterface(appDataRegAsFile, &rv);
01983     if (NS_FAILED(rv)) return;
01984     appDataRegistry->AppendRelativePath(NS_LITERAL_STRING("registry.dat"));
01985 
01986     // Profiles directory
01987     nsCOMPtr<nsIFile> profileDirAsFile;
01988     rv = appDataDir->Clone(getter_AddRefs(profileDirAsFile));
01989     if (NS_FAILED(rv)) return;
01990     nsCOMPtr<nsILocalFile> profileDir = do_QueryInterface(profileDirAsFile, &rv);
01991     if (NS_FAILED(rv)) return;
01992     profileDir->AppendRelativePath(NS_LITERAL_STRING("profiles"));
01993     rv = profileDir->Exists(&exists);
01994     if (NS_SUCCEEDED(rv) && !exists)
01995         rv = profileDir->Create(nsIFile::DIRECTORY_TYPE, 0775);
01996     if (NS_FAILED(rv)) return;
01997 
01998     // Store the member values
01999     mApplicationRegistryDir = appDataDir;
02000     mApplicationRegistryFile = appDataRegistry;
02001     mUserProfileDir = profileDir;
02002 }
02003 
02004 SimpleDirectoryProvider::~SimpleDirectoryProvider()
02005 {
02006 }
02007 
02008 BOOL
02009 SimpleDirectoryProvider::IsValid() const
02010 {
02011     return (mApplicationRegistryDir && mApplicationRegistryFile && mUserProfileDir) ?
02012         TRUE : FALSE;
02013 }
02014 
02015 NS_IMPL_ISUPPORTS1(SimpleDirectoryProvider, nsIDirectoryServiceProvider)
02016 
02017 
02018 // nsIDirectoryServiceProvider
02019 
02020 /* nsIFile getFile (in string prop, out PRBool persistent); */
02021 NS_IMETHODIMP SimpleDirectoryProvider::GetFile(const char *prop, PRBool *persistent, nsIFile **_retval)
02022 {
02023     NS_ENSURE_ARG_POINTER(prop);
02024     NS_ENSURE_ARG_POINTER(persistent);
02025     NS_ENSURE_ARG_POINTER(_retval);
02026 
02027     *_retval = nsnull;
02028     *persistent = PR_TRUE;
02029 
02030     // Only need to support NS_APP_APPLICATION_REGISTRY_DIR, NS_APP_APPLICATION_REGISTRY_FILE, and
02031     // NS_APP_USER_PROFILES_ROOT_DIR. Unsupported keys fallback to the default service provider
02032     
02033     nsCOMPtr<nsILocalFile> localFile;
02034     nsresult rv = NS_ERROR_FAILURE;
02035 
02036     if (nsCRT::strcmp(prop, NS_APP_APPLICATION_REGISTRY_DIR) == 0)
02037     {
02038         localFile = mApplicationRegistryDir;
02039     }
02040     else if (nsCRT::strcmp(prop, NS_APP_APPLICATION_REGISTRY_FILE) == 0)
02041     {
02042         localFile = mApplicationRegistryFile;
02043     }
02044     else if (nsCRT::strcmp(prop, NS_APP_USER_PROFILES_ROOT_DIR) == 0)
02045     {
02046         localFile = mUserProfileDir;
02047     }
02048     
02049     if (localFile)
02050         return CallQueryInterface(localFile, _retval);
02051         
02052     return rv;
02053 }
02054 
02055 
02057 // PrintListener implementation
02058 
02059 
02060 NS_IMPL_ISUPPORTS1(PrintListener, nsIWebProgressListener)
02061 
02062 PrintListener::PrintListener() : mComplete(PR_FALSE)
02063 {
02064     /* member initializers and constructor code */
02065 }
02066 
02067 PrintListener::~PrintListener()
02068 {
02069     /* destructor code */
02070 }
02071 
02072 void PrintListener::WaitForComplete()
02073 {
02074     MSG msg;
02075     HANDLE hFakeEvent = ::CreateEvent(NULL, TRUE, FALSE, NULL);
02076 
02077     while (!mComplete)
02078     {
02079         // Process pending messages
02080         while (::PeekMessage(&msg, NULL, 0, 0, PM_NOREMOVE))
02081         {
02082             if (!::GetMessage(&msg, NULL, 0, 0))
02083             {
02084                 ::CloseHandle(hFakeEvent);
02085                 return;
02086             }
02087 
02088             PRBool wasHandled = PR_FALSE;
02089             ::NS_HandleEmbeddingEvent(msg, wasHandled);
02090             if (wasHandled)
02091                 continue;
02092 
02093             ::TranslateMessage(&msg);
02094             ::DispatchMessage(&msg);
02095         }
02096 
02097         if (mComplete)
02098             break;
02099         
02100         // Do idle stuff
02101         ::MsgWaitForMultipleObjects(1, &hFakeEvent, FALSE, 500, QS_ALLEVENTS);
02102     }
02103 
02104     ::CloseHandle(hFakeEvent);
02105 }
02106 
02107 /* void onStateChange (in nsIWebProgress aWebProgress, in nsIRequest aRequest, in unsigned long aStateFlags, in nsresult aStatus); */
02108 NS_IMETHODIMP PrintListener::OnStateChange(nsIWebProgress *aWebProgress, nsIRequest *aRequest, PRUint32 aStateFlags, nsresult aStatus)
02109 {
02110     if (aStateFlags & nsIWebProgressListener::STATE_STOP &&
02111         aStateFlags & nsIWebProgressListener::STATE_IS_DOCUMENT)
02112     {
02113         mComplete = PR_TRUE;
02114     }
02115     return NS_OK;
02116 }
02117 
02118 /* void onProgressChange (in nsIWebProgress aWebProgress, in nsIRequest aRequest, in long aCurSelfProgress, in long aMaxSelfProgress, in long aCurTotalProgress, in long aMaxTotalProgress); */
02119 NS_IMETHODIMP PrintListener::OnProgressChange(nsIWebProgress *aWebProgress, nsIRequest *aRequest, PRInt32 aCurSelfProgress, PRInt32 aMaxSelfProgress, PRInt32 aCurTotalProgress, PRInt32 aMaxTotalProgress)
02120 {
02121     return NS_OK;
02122 }
02123 
02124 /* void onLocationChange (in nsIWebProgress aWebProgress, in nsIRequest aRequest, in nsIURI location); */
02125 NS_IMETHODIMP PrintListener::OnLocationChange(nsIWebProgress *aWebProgress, nsIRequest *aRequest, nsIURI *location)
02126 {
02127     return NS_OK;
02128 }
02129 
02130 /* void onStatusChange (in nsIWebProgress aWebProgress, in nsIRequest aRequest, in nsresult aStatus, in wstring aMessage); */
02131 NS_IMETHODIMP PrintListener::OnStatusChange(nsIWebProgress *aWebProgress, nsIRequest *aRequest, nsresult aStatus, const PRUnichar *aMessage)
02132 {
02133     return NS_OK;
02134 }
02135 
02136 /* void onSecurityChange (in nsIWebProgress aWebProgress, in nsIRequest aRequest, in unsigned long state); */
02137 NS_IMETHODIMP PrintListener::OnSecurityChange(nsIWebProgress *aWebProgress, nsIRequest *aRequest, PRUint32 state)
02138 {
02139     return NS_OK;
02140 }