Back to index

lightning-sunbird  0.9+nobinonly
CBrowserChrome.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) 2002
00020  * the Initial Developer. All Rights Reserved.
00021  *
00022  * Contributor(s):
00023  *  Conrad Carlen <ccarlen@netscape.com>
00024  *
00025  * Alternatively, the contents of this file may be used under the terms of
00026  * either the GNU General Public License Version 2 or later (the "GPL"), or
00027  * the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
00028  * in which case the provisions of the GPL or the LGPL are applicable instead
00029  * of those above. If you wish to allow use of your version of this file only
00030  * under the terms of either the GPL or the LGPL, and not to allow others to
00031  * use your version of this file under the terms of the MPL, indicate your
00032  * decision by deleting the provisions above and replace them with the notice
00033  * and other provisions required by the GPL or the LGPL. If you do not delete
00034  * the provisions above, a recipient may use your version of this file under
00035  * the terms of any one of the MPL, the GPL or the LGPL.
00036  *
00037  * ***** END LICENSE BLOCK ***** */
00038 
00039 // Local Includes
00040 #include "CBrowserChrome.h"
00041 #include "CBrowserShell.h"
00042 #include "CBrowserMsgDefs.h"
00043 
00044 #include "nsIGenericFactory.h"
00045 #include "nsString.h"
00046 #include "nsXPIDLString.h"
00047 #include "nsReadableUtils.h"
00048 #include "nsIURI.h"
00049 #include "nsIWebProgress.h"
00050 #include "nsIDocShellTreeItem.h"
00051 #include "nsIRequest.h"
00052 #include "nsIChannel.h"
00053 #include "nsIDOMWindow.h"
00054 #include "nsIDOMDocument.h"
00055 #include "nsIDOMElement.h"
00056 #include "nsIWindowWatcher.h"
00057 #include "nsServiceManagerUtils.h"
00058 
00059 #include "UMacUnicode.h"
00060 #include "ApplIDs.h"
00061 
00062 #include <LStaticText.h>
00063 #include <LCheckBox.h>
00064 #include <LEditText.h>
00065 #include <UModalDialogs.h>
00066 #include <LPushButton.h>
00067 
00068 // Interfaces needed to be included
00069 
00070 // Defines
00071 
00072 // Constants
00073 const PRInt32     kGrowIconSize = 15;
00074 
00075 //*****************************************************************************
00076 //***    CBrowserChrome:
00077 //*****************************************************************************
00078 
00079 CBrowserChrome::CBrowserChrome(CBrowserShell *aShell,
00080                                UInt32 aChromeFlags,
00081                                Boolean aIsMainContent) :
00082     mBrowserShell(aShell), mBrowserWindow(nsnull),
00083     mChromeFlags(aChromeFlags), mIsMainContent(aIsMainContent),
00084     mSizeToContent(false),    
00085     mInModalLoop(false), mWindowVisible(false),
00086     mInitialLoadComplete(false)
00087 {
00088        ThrowIfNil_(mBrowserShell);
00089        mBrowserWindow = LWindow::FetchWindowObject(mBrowserShell->GetMacWindow());
00090        StartListening();
00091 }
00092 
00093 CBrowserChrome::~CBrowserChrome()
00094 {
00095 }
00096 
00097 void CBrowserChrome::SetBrowserShell(CBrowserShell *aShell)
00098 {
00099     mBrowserShell = aShell;
00100     if (mBrowserShell)
00101            mBrowserWindow = LWindow::FetchWindowObject(mBrowserShell->GetMacWindow());
00102     else
00103         mBrowserWindow = nsnull;    
00104 }
00105 
00106 //*****************************************************************************
00107 // CBrowserChrome::nsISupports
00108 //*****************************************************************************   
00109 
00110 NS_IMPL_ISUPPORTS8(CBrowserChrome,
00111                    nsIWebBrowserChrome,
00112                    nsIInterfaceRequestor,
00113                    nsIWebBrowserChromeFocus,
00114                    nsIEmbeddingSiteWindow,
00115                    nsIEmbeddingSiteWindow2,
00116                    nsIContextMenuListener2,
00117                    nsITooltipListener,
00118                    nsISupportsWeakReference);
00119                    
00120 //*****************************************************************************
00121 // CBrowserChrome::nsIInterfaceRequestor
00122 //*****************************************************************************   
00123 
00124 NS_IMETHODIMP CBrowserChrome::GetInterface(const nsIID &aIID, void** aInstancePtr)
00125 {
00126    if (aIID.Equals(NS_GET_IID(nsIDOMWindow)))
00127    {
00128       nsCOMPtr<nsIWebBrowser> browser;
00129       GetWebBrowser(getter_AddRefs(browser));
00130       if (browser)
00131          return browser->GetContentDOMWindow((nsIDOMWindow **) aInstancePtr);
00132       return NS_ERROR_NOT_INITIALIZED;
00133    }
00134 
00135    return QueryInterface(aIID, aInstancePtr);
00136 }
00137 
00138 //*****************************************************************************
00139 // CBrowserChrome::nsIWebBrowserChrome
00140 //*****************************************************************************   
00141 
00142 NS_IMETHODIMP CBrowserChrome::SetStatus(PRUint32 statusType, const PRUnichar *status)
00143 {
00144      NS_ENSURE_TRUE(mBrowserShell, NS_ERROR_NOT_INITIALIZED);
00145 
00146      MsgChromeStatusChangeInfo info(mBrowserShell, statusType, status);
00147      mBrowserShell->BroadcastMessage(msg_OnChromeStatusChange, &info);
00148   
00149      return NS_OK;
00150 }
00151 
00152 NS_IMETHODIMP CBrowserChrome::GetWebBrowser(nsIWebBrowser** aWebBrowser)
00153 {
00154     NS_ENSURE_ARG_POINTER(aWebBrowser);
00155     NS_ENSURE_TRUE(mBrowserShell, NS_ERROR_NOT_INITIALIZED);
00156 
00157     mBrowserShell->GetWebBrowser(aWebBrowser);
00158     return NS_OK;
00159 }
00160 
00161 NS_IMETHODIMP CBrowserChrome::SetWebBrowser(nsIWebBrowser* aWebBrowser)
00162 {
00163     NS_ENSURE_ARG(aWebBrowser);   // Passing nsnull is NOT OK
00164     NS_ENSURE_TRUE(mBrowserShell, NS_ERROR_NOT_INITIALIZED);
00165 
00166     mBrowserShell->SetWebBrowser(aWebBrowser);
00167     return NS_OK;
00168 }
00169 
00170 NS_IMETHODIMP CBrowserChrome::GetChromeFlags(PRUint32* aChromeMask)
00171 {
00172     NS_ENSURE_ARG_POINTER(aChromeMask);
00173    
00174     *aChromeMask = mChromeFlags;
00175     return NS_OK;
00176 }
00177 
00178 NS_IMETHODIMP CBrowserChrome::SetChromeFlags(PRUint32 aChromeMask)
00179 {
00180     // Yuck - our window would have to be rebuilt to do this.
00181     NS_ERROR("Haven't implemented this yet!");
00182     return NS_ERROR_NOT_IMPLEMENTED;
00183 }
00184 
00185 NS_IMETHODIMP CBrowserChrome::DestroyBrowserWindow()
00186 {
00187     NS_ENSURE_TRUE(mBrowserShell, NS_ERROR_NOT_INITIALIZED);
00188 
00189     mInModalLoop = false;
00190     delete mBrowserWindow;
00191     return NS_OK;
00192 }
00193 
00194 NS_IMETHODIMP CBrowserChrome::IsWindowModal(PRBool *_retval)
00195 {
00196     *_retval = PR_FALSE;
00197     return NS_OK;
00198 }
00199 
00200 NS_IMETHODIMP CBrowserChrome::SizeBrowserTo(PRInt32 aCX, PRInt32 aCY)
00201 {
00202    SDimension16 curSize;
00203    mBrowserShell->GetFrameSize(curSize);
00204    mBrowserWindow->ResizeWindowBy((aCX - curSize.width), (aCY - curSize.height));
00205    return NS_OK;
00206 }
00207 
00208 
00209 NS_IMETHODIMP CBrowserChrome::ShowAsModal(void)
00210 {
00211     // We need this override because StDialogHandler deletes
00212     // its window in its destructor. We don't want that here. 
00213     class CChromeDialogHandler : public StDialogHandler
00214     {
00215         public:
00216                                           CChromeDialogHandler(LWindow*             inWindow,
00217                                                                      LCommander*    inSuper) :
00218                                            StDialogHandler(inWindow, inSuper)
00219                                        { }
00220                                            
00221            virtual         ~CChromeDialogHandler()
00222                            { mDialog = nil; }
00223     };
00224     
00225     CChromeDialogHandler     theHandler(mBrowserWindow, mBrowserWindow->GetSuperCommander());
00226        
00227        // Set to false by ExitModalEventLoop or DestroyBrowserWindow
00228        mInModalLoop = true;
00229        while (mInModalLoop) 
00230            theHandler.DoDialog();
00231 
00232     return NS_OK;
00233 
00234 }
00235 
00236 NS_IMETHODIMP CBrowserChrome::ExitModalEventLoop(nsresult aStatus)
00237 {
00238    mInModalLoop = false;
00239    return NS_OK;
00240 }
00241 
00242 
00243 //*****************************************************************************
00244 // CBrowserChrome::nsIWebBrowserChromeFocus
00245 //*****************************************************************************
00246 
00247 NS_IMETHODIMP CBrowserChrome::FocusNextElement()
00248 {
00249   return NS_ERROR_NOT_IMPLEMENTED;
00250 }
00251 
00252 NS_IMETHODIMP CBrowserChrome::FocusPrevElement()
00253 {
00254   return NS_ERROR_NOT_IMPLEMENTED;
00255 }
00256 
00257 
00258 //*****************************************************************************
00259 // CBrowserChrome::nsIEmbeddingSiteWindow
00260 //*****************************************************************************   
00261 
00262 NS_IMETHODIMP CBrowserChrome::SetDimensions(PRUint32 flags, PRInt32 x, PRInt32 y, PRInt32 cx, PRInt32 cy)
00263 {
00264     NS_ENSURE_STATE(mBrowserWindow);
00265     NS_ENSURE_STATE(mBrowserShell);
00266     
00267     if ((flags & nsIEmbeddingSiteWindow::DIM_FLAGS_SIZE_INNER) &&
00268         (flags & nsIEmbeddingSiteWindow::DIM_FLAGS_SIZE_OUTER))
00269         return NS_ERROR_INVALID_ARG;
00270     
00271     if (flags & nsIEmbeddingSiteWindow::DIM_FLAGS_POSITION)
00272     {
00273         mBrowserWindow->MoveWindowTo(x, y);
00274     }        
00275     
00276     if (flags & nsIEmbeddingSiteWindow::DIM_FLAGS_SIZE_INNER)
00277     {
00278         // Don't resize the inner view independently from the window. Keep them in
00279         // proportion by resizing the window and letting that affect the inner view.
00280         SDimension16 curSize;
00281         mBrowserShell->GetFrameSize(curSize);
00282         mBrowserWindow->ResizeWindowBy(cx - curSize.width, cy - curSize.height);
00283     }
00284     else if (flags & nsIEmbeddingSiteWindow::DIM_FLAGS_SIZE_OUTER)
00285     {
00286         if (mBrowserWindow->HasAttribute(windAttr_Resizable /*windAttr_SizeBox*/))
00287             cy += 15;
00288         mBrowserWindow->ResizeWindowTo(cx, cy);
00289     }
00290     
00291     return NS_OK;
00292 }
00293 
00294 NS_IMETHODIMP CBrowserChrome::GetDimensions(PRUint32 flags, PRInt32 *x, PRInt32 *y, PRInt32 *cx, PRInt32 *cy)
00295 {
00296     NS_ENSURE_STATE(mBrowserWindow);
00297     NS_ENSURE_STATE(mBrowserShell);
00298      
00299     if ((flags & nsIEmbeddingSiteWindow::DIM_FLAGS_SIZE_INNER) &&
00300         (flags & nsIEmbeddingSiteWindow::DIM_FLAGS_SIZE_OUTER))
00301         return NS_ERROR_INVALID_ARG;
00302 
00303     Rect outerBounds;
00304     if ((flags & nsIEmbeddingSiteWindow::DIM_FLAGS_POSITION) ||
00305         (flags & nsIEmbeddingSiteWindow::DIM_FLAGS_SIZE_OUTER))    
00306         mBrowserWindow->GetGlobalBounds(outerBounds);
00307     
00308     if (flags & nsIEmbeddingSiteWindow::DIM_FLAGS_POSITION)
00309     {
00310         if (x)
00311             *x = outerBounds.left;
00312         if (y)
00313             *y = outerBounds.top;
00314     }        
00315     
00316     if (flags & nsIEmbeddingSiteWindow::DIM_FLAGS_SIZE_INNER)
00317     {
00318         SDimension16 curSize;
00319         mBrowserShell->GetFrameSize(curSize);
00320         if (cx)
00321             *cx = curSize.width;
00322         if (cy)
00323             *cy = curSize.height;
00324     }
00325     else if (flags & nsIEmbeddingSiteWindow::DIM_FLAGS_SIZE_OUTER)
00326     {
00327         if (cx)
00328             *cx = outerBounds.right - outerBounds.left;
00329         if (cy)
00330         {
00331             *cy = outerBounds.bottom - outerBounds.top;
00332             if (mBrowserWindow->HasAttribute(windAttr_Resizable /*windAttr_SizeBox*/))
00333                 *cy -= 15;
00334         }
00335     }
00336 
00337     return NS_OK;
00338 }
00339 
00340 NS_IMETHODIMP CBrowserChrome::SetFocus()
00341 {
00342     mBrowserWindow->Select();
00343     return NS_OK;
00344 }
00345 
00346 NS_IMETHODIMP CBrowserChrome::GetVisibility(PRBool *aVisibility)
00347 {
00348     NS_ENSURE_STATE(mBrowserWindow);
00349     NS_ENSURE_ARG_POINTER(aVisibility);
00350     
00351     *aVisibility = mWindowVisible;
00352     
00353     return NS_OK;
00354 }
00355 
00356 NS_IMETHODIMP CBrowserChrome::SetVisibility(PRBool aVisibility)
00357 {
00358     NS_ENSURE_STATE(mBrowserWindow);
00359     
00360     if (aVisibility == mWindowVisible)
00361         return NS_OK;
00362         
00363     mWindowVisible = aVisibility;
00364     
00365     // If we are being told to become visible but we need to wait for
00366     // content to load so that we can size ourselves to it,
00367     // don't actually show it now. That will be done after the
00368     // load completes.
00369     PRBool sizingToContent = mIsMainContent &&
00370                              (mChromeFlags & CHROME_OPENAS_CHROME) &&
00371                              (mChromeFlags & CHROME_OPENAS_DIALOG);
00372     if (sizingToContent && mWindowVisible && !mInitialLoadComplete)
00373         return NS_OK;    
00374     aVisibility ? mBrowserWindow->Show() : mBrowserWindow->Hide();
00375     
00376     return NS_OK;
00377 }
00378 
00379 NS_IMETHODIMP CBrowserChrome::GetTitle(PRUnichar * *aTitle)
00380 {
00381    NS_ENSURE_STATE(mBrowserWindow);
00382    NS_ENSURE_ARG_POINTER(aTitle);
00383 
00384    Str255         pStr;
00385    nsAutoString   titleStr;
00386    
00387    mBrowserWindow->GetDescriptor(pStr);
00388    CPlatformUCSConversion::GetInstance()->PlatformToUCS(pStr, titleStr);
00389    *aTitle = ToNewUnicode(titleStr);
00390    
00391    return NS_OK;
00392 }
00393 
00394 NS_IMETHODIMP CBrowserChrome::SetTitle(const PRUnichar * aTitle)
00395 {
00396     NS_ENSURE_STATE(mBrowserWindow);
00397     NS_ENSURE_ARG(aTitle);
00398     
00399     Str255          pStr;
00400        
00401     CPlatformUCSConversion::GetInstance()->UCSToPlatform(nsDependentString(aTitle), pStr);
00402     mBrowserWindow->SetDescriptor(pStr);
00403     
00404     return NS_OK;
00405 }
00406 
00407 NS_IMETHODIMP CBrowserChrome::GetSiteWindow(void * *aSiteWindow)
00408 {
00409     NS_ENSURE_ARG(aSiteWindow);
00410     NS_ENSURE_STATE(mBrowserWindow);
00411 
00412     *aSiteWindow = mBrowserWindow->GetMacWindow();
00413     
00414     return NS_OK;
00415 }
00416 
00417 
00418 //*****************************************************************************
00419 // CBrowserChrome::nsIEmbeddingSiteWindow2
00420 //*****************************************************************************   
00421 
00422 NS_IMETHODIMP CBrowserChrome::Blur(void)
00423 {    
00424     WindowPtr   currWindow = ::GetWindowList();
00425     WindowPtr   nextWindow;
00426 
00427     // Find the rearmost window and put ourselves behind it
00428     while (currWindow && ((nextWindow = ::MacGetNextWindow(currWindow)) != nsnull))
00429         currWindow = nextWindow;
00430 
00431     WindowPtr ourWindow = mBrowserWindow->GetMacWindow();
00432     if (ourWindow != currWindow)
00433         ::SendBehind(ourWindow, currWindow);
00434     
00435     return NS_OK;
00436 }
00437 
00438 //*****************************************************************************
00439 // CBrowserChrome::nsIContextMenuListener2
00440 //*****************************************************************************   
00441 
00442 NS_IMETHODIMP CBrowserChrome::OnShowContextMenu(PRUint32 aContextFlags, nsIContextMenuInfo *aInfo)
00443 {
00444     nsresult rv;
00445     
00446     try
00447     {
00448         rv = mBrowserShell->OnShowContextMenu(aContextFlags, aInfo);
00449     }
00450     catch (...)
00451     {
00452         rv = NS_ERROR_FAILURE;
00453     }
00454     return rv;
00455 }
00456 
00457 //*****************************************************************************
00458 // CBrowserChrome::nsITooltipListener
00459 //*****************************************************************************
00460 
00461 NS_IMETHODIMP CBrowserChrome::OnShowTooltip(PRInt32 aXCoords, PRInt32 aYCoords, const PRUnichar *aTipText)
00462 {
00463     nsresult rv;
00464     
00465     try
00466     {
00467         rv = mBrowserShell->OnShowTooltip(aXCoords, aYCoords, aTipText);
00468     }
00469     catch (...)
00470     {
00471         rv = NS_ERROR_FAILURE;
00472     }
00473     return rv;
00474 }
00475 
00476 NS_IMETHODIMP CBrowserChrome::OnHideTooltip()
00477 {
00478     nsresult rv;
00479     
00480     try
00481     {
00482         rv = mBrowserShell->OnHideTooltip();
00483     }
00484     catch (...)
00485     {
00486         rv = NS_ERROR_FAILURE;
00487     }
00488     return rv;
00489 }
00490 
00491 //*****************************************************************************
00492 // CBrowserChrome::LListener
00493 //*****************************************************************************
00494 
00495 void CBrowserChrome::ListenToMessage(MessageT inMessage, void* ioParam)
00496 {
00497     switch (inMessage)
00498     {
00499         case msg_OnNetStopChange:
00500             {
00501                 mInitialLoadComplete = true;
00502 
00503                 // See if we need to size it and show it
00504                 if (mIsMainContent &&
00505                     (mChromeFlags & nsIWebBrowserChrome::CHROME_OPENAS_CHROME) &&
00506                     (mChromeFlags & nsIWebBrowserChrome::CHROME_OPENAS_DIALOG))
00507                 {
00508                     nsCOMPtr<nsIDOMWindow> domWindow;
00509                     (void)GetInterface(NS_GET_IID(nsIDOMWindow), getter_AddRefs(domWindow));
00510                     if (domWindow)
00511                         domWindow->SizeToContent();
00512                     if (mWindowVisible != mBrowserWindow->IsVisible())
00513                         mBrowserWindow->Show();
00514                 }
00515                 
00516                 // If we are chrome, get the window title from the DOM
00517                 if (mChromeFlags & nsIWebBrowserChrome::CHROME_OPENAS_CHROME)
00518                 {
00519                     nsresult rv;
00520                     nsCOMPtr<nsIDOMWindow> domWindow;
00521                     rv = GetInterface(NS_GET_IID(nsIDOMWindow), getter_AddRefs(domWindow));
00522                     if (NS_FAILED(rv)) return;
00523                     nsCOMPtr<nsIDOMDocument> domDoc;
00524                     rv = domWindow->GetDocument(getter_AddRefs(domDoc));
00525                     if (NS_FAILED(rv)) return;
00526                     nsCOMPtr<nsIDOMElement> domDocElem;
00527                     rv = domDoc->GetDocumentElement(getter_AddRefs(domDocElem));
00528                     if (NS_FAILED(rv)) return;
00529 
00530                     nsAutoString windowTitle;
00531                     domDocElem->GetAttribute(NS_LITERAL_STRING("title"), windowTitle);
00532                     if (!windowTitle.IsEmpty()) {
00533                         Str255 pStr;
00534                         CPlatformUCSConversion::GetInstance()->UCSToPlatform(windowTitle, pStr);
00535                         mBrowserWindow->SetDescriptor(pStr);
00536                     }
00537                 }
00538             }
00539             break;
00540     }
00541 }
00542 
00543 //*****************************************************************************
00544 // Static Utility Method
00545 //*****************************************************************************
00546 
00547 LWindow* CBrowserChrome::GetLWindowForDOMWindow(nsIDOMWindow* aDOMWindow)
00548 {
00549     if (!aDOMWindow)
00550         return nsnull;
00551         
00552     nsCOMPtr<nsIWindowWatcher> windowWatcher(do_GetService(NS_WINDOWWATCHER_CONTRACTID));
00553     if (!windowWatcher)
00554         return nsnull;
00555     nsCOMPtr<nsIWebBrowserChrome> windowChrome;
00556     windowWatcher->GetChromeForWindow(aDOMWindow, getter_AddRefs(windowChrome));
00557     if (!windowChrome)
00558         return nsnull;        
00559     nsCOMPtr<nsIEmbeddingSiteWindow> siteWindow(do_QueryInterface(windowChrome));
00560     if (!siteWindow)
00561         return nsnull;
00562     WindowPtr macWindow = nsnull;
00563     siteWindow->GetSiteWindow((void **)&macWindow);
00564     if (!macWindow)
00565         return nsnull;
00566     
00567     return LWindow::FetchWindowObject(macWindow);
00568 }
00569