Back to index

lightning-sunbird  0.9+nobinonly
CHBrowserListener.mm
Go to the documentation of this file.
00001 /* ***** BEGIN LICENSE BLOCK *****
00002  * Version: MPL 1.1/GPL 2.0/LGPL 2.1
00003  *
00004  * The contents of this file are subject to the Mozilla Public License Version
00005  * 1.1 (the "License"); you may not use this file except in compliance with
00006  * the License. You may obtain a copy of the License at
00007  * http://www.mozilla.org/MPL/
00008  *
00009  * Software distributed under the License is distributed on an "AS IS" basis,
00010  * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
00011  * for the specific language governing rights and limitations under the
00012  * License.
00013  *
00014  * The Original Code is Chimera code.
00015  *
00016  * The Initial Developer of the Original Code is
00017  * Netscape Communications Corporation.
00018  * Portions created by the Initial Developer are Copyright (C) 2002
00019  * the Initial Developer. All Rights Reserved.
00020  *
00021  * Contributor(s):
00022  *   Simon Fraser <sfraser@netscape.com>
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 #import <Cocoa/Cocoa.h>
00039 
00040 #import "NSString+Utils.h"
00041 
00042 // Embedding includes
00043 #include "nsIWebBrowser.h"
00044 #include "nsIWebNavigation.h"
00045 #include "nsIURI.h"
00046 #include "nsIDOMWindow.h"
00047 //#include "nsIWidget.h"
00048 
00049 // XPCOM and String includes
00050 #include "nsCRT.h"
00051 #include "nsString.h"
00052 #include "nsCOMPtr.h"
00053 
00054 #import "CHBrowserView.h"
00055 
00056 #include "CHBrowserListener.h"
00057 
00058 
00059 CHBrowserListener::CHBrowserListener(CHBrowserView* aView)
00060   : mView(aView), mContainer(nsnull), mIsModal(PR_FALSE), mChromeFlags(0)
00061 {
00062   mListeners = [[NSMutableArray alloc] init];
00063 }
00064 
00065 CHBrowserListener::~CHBrowserListener()
00066 {
00067   [mListeners release];
00068   mView = nsnull;
00069   if (mContainer) {
00070     [mContainer release];
00071   }
00072 }
00073 
00074 NS_IMPL_ISUPPORTS9(CHBrowserListener,
00075                    nsIInterfaceRequestor,
00076                    nsIWebBrowserChrome,
00077                    nsIWindowCreator,
00078                    nsIEmbeddingSiteWindow,
00079                    nsIEmbeddingSiteWindow2,
00080                    nsIWebProgressListener,
00081                    nsISupportsWeakReference,
00082                    nsIContextMenuListener,
00083                    nsITooltipListener)
00084 
00085 // Implementation of nsIInterfaceRequestor
00086 NS_IMETHODIMP 
00087 CHBrowserListener::GetInterface(const nsIID &aIID, void** aInstancePtr)
00088 {
00089   if (aIID.Equals(NS_GET_IID(nsIDOMWindow))) {
00090     nsCOMPtr<nsIWebBrowser> browser = dont_AddRef([mView getWebBrowser]);
00091     if (browser)
00092       return browser->GetContentDOMWindow((nsIDOMWindow **) aInstancePtr);
00093   }
00094   
00095   return QueryInterface(aIID, aInstancePtr);
00096 }
00097 
00098 // Implementation of nsIWindowCreator.  The CocoaBrowserService forwards requests
00099 // for a new window that have a parent to us, and we take over from there.  
00100 /* nsIWebBrowserChrome createChromeWindow (in nsIWebBrowserChrome parent, in PRUint32 chromeFlags); */
00101 NS_IMETHODIMP 
00102 CHBrowserListener::CreateChromeWindow(nsIWebBrowserChrome *parent, 
00103                                            PRUint32 chromeFlags, 
00104                                            nsIWebBrowserChrome **_retval)
00105 {
00106   if (parent != this) {
00107 #if DEBUG
00108     NSLog(@"Mismatch in CHBrowserListener::CreateChromeWindow.  We should be the owning parent.");
00109 #endif
00110     return NS_ERROR_FAILURE;
00111   }
00112   
00113   CHBrowserView* childView = [mContainer createBrowserWindow: chromeFlags];
00114   if (!childView) {
00115 #if DEBUG
00116     NSLog(@"No CHBrowserView hooked up for a newly created window yet.");
00117 #endif
00118     return NS_ERROR_FAILURE;
00119   }
00120   
00121   CHBrowserListener* listener = [childView getCocoaBrowserListener];
00122   if (!listener) {
00123 #if DEBUG
00124     NSLog(@"Uh-oh! No listener yet for a newly created window (nsCocoaBrowserlistener)");
00125     return NS_ERROR_FAILURE;
00126 #endif
00127   }
00128   
00129 #if DEBUG
00130   NSLog(@"Made a chrome window.");
00131 #endif
00132   
00133   *_retval = listener;
00134   NS_IF_ADDREF(*_retval);
00135   return NS_OK;
00136 }
00137 
00138 // Implementation of nsIContextMenuListener
00139 NS_IMETHODIMP
00140 CHBrowserListener::OnShowContextMenu(PRUint32 aContextFlags, nsIDOMEvent* aEvent, nsIDOMNode* aNode)
00141 {
00142   [mContainer onShowContextMenu: aContextFlags domEvent: aEvent domNode: aNode];
00143   return NS_OK;
00144 }
00145 
00146 // Implementation of nsITooltipListener
00147 NS_IMETHODIMP
00148 CHBrowserListener::OnShowTooltip(PRInt32 aXCoords, PRInt32 aYCoords, const PRUnichar *aTipText)
00149 {
00150   NSPoint where;
00151   where.x = aXCoords; where.y = aYCoords;
00152   [mContainer onShowTooltip:where withText:[NSString stringWithPRUnichars:aTipText]];
00153   return NS_OK;
00154 }
00155 
00156 NS_IMETHODIMP
00157 CHBrowserListener::OnHideTooltip()
00158 {
00159   [mContainer onHideTooltip];
00160   return NS_OK;
00161 }
00162 
00163 // Implementation of nsIWebBrowserChrome
00164 /* void setStatus (in unsigned long statusType, in wstring status); */
00165 NS_IMETHODIMP 
00166 CHBrowserListener::SetStatus(PRUint32 statusType, const PRUnichar *status)
00167 {
00168   if (!mContainer) {
00169     return NS_ERROR_FAILURE;
00170   }
00171 
00172   NSString* str = nsnull;
00173   if (status && (*status != PRUnichar(0))) {
00174     str = [NSString stringWithPRUnichars:status];
00175   }
00176 
00177   [mContainer setStatus:str ofType:(NSStatusType)statusType];
00178 
00179   return NS_OK;
00180 }
00181 
00182 /* attribute nsIWebBrowser webBrowser; */
00183 NS_IMETHODIMP 
00184 CHBrowserListener::GetWebBrowser(nsIWebBrowser * *aWebBrowser)
00185 {
00186   NS_ENSURE_ARG_POINTER(aWebBrowser);
00187   if (!mView) {
00188     return NS_ERROR_FAILURE;
00189   }
00190   *aWebBrowser = [mView getWebBrowser];
00191 
00192   return NS_OK;
00193 }
00194 NS_IMETHODIMP 
00195 CHBrowserListener::SetWebBrowser(nsIWebBrowser * aWebBrowser)
00196 {
00197   if (!mView) {
00198     return NS_ERROR_FAILURE;
00199   }
00200 
00201   [mView setWebBrowser:aWebBrowser];
00202 
00203   return NS_OK;
00204 }
00205 
00206 /* attribute unsigned long chromeFlags; */
00207 NS_IMETHODIMP 
00208 CHBrowserListener::GetChromeFlags(PRUint32 *aChromeFlags)
00209 {
00210   NS_ENSURE_ARG_POINTER(aChromeFlags);
00211   *aChromeFlags = mChromeFlags;
00212   return NS_OK;
00213 }
00214 NS_IMETHODIMP 
00215 CHBrowserListener::SetChromeFlags(PRUint32 aChromeFlags)
00216 {
00217   // XXX Do nothing with them for now
00218   mChromeFlags = aChromeFlags;
00219   return NS_OK;
00220 }
00221 
00222 /* void destroyBrowserWindow (); */
00223 NS_IMETHODIMP 
00224 CHBrowserListener::DestroyBrowserWindow()
00225 {
00226   // XXX Could send this up to the container, but for now,
00227   // we just destroy the enclosing window.
00228   NSWindow* window = [mView window];
00229 
00230   if (window) {
00231     [window close];
00232   }
00233 
00234   return NS_OK;
00235 }
00236 
00237 /* void sizeBrowserTo (in long aCX, in long aCY); */
00238 NS_IMETHODIMP 
00239 CHBrowserListener::SizeBrowserTo(PRInt32 aCX, PRInt32 aCY)
00240 {
00241   if (mContainer) {
00242     NSSize size;
00243     
00244     size.width = (float)aCX;
00245     size.height = (float)aCY;
00246 
00247     [mContainer sizeBrowserTo:size];
00248   }
00249   
00250   return NS_OK;
00251 }
00252 
00253 /* void showAsModal (); */
00254 NS_IMETHODIMP 
00255 CHBrowserListener::ShowAsModal()
00256 {
00257   if (!mView) {
00258     return NS_ERROR_FAILURE;
00259   }
00260 
00261   NSWindow* window = [mView window];
00262 
00263   if (!window) {
00264     return NS_ERROR_FAILURE;
00265   }
00266 
00267   mIsModal = PR_TRUE;
00268   //int result = [NSApp runModalForWindow:window];
00269   mIsModal = PR_FALSE;
00270 
00271   return NS_OK;
00272 }
00273 
00274 /* boolean isWindowModal (); */
00275 NS_IMETHODIMP 
00276 CHBrowserListener::IsWindowModal(PRBool *_retval)
00277 {
00278   NS_ENSURE_ARG_POINTER(_retval);
00279 
00280   *_retval = mIsModal;
00281 
00282   return NS_OK;
00283 }
00284 
00285 /* void exitModalEventLoop (in nsresult aStatus); */
00286 NS_IMETHODIMP 
00287 CHBrowserListener::ExitModalEventLoop(nsresult aStatus)
00288 {
00289 //  [NSApp stopModalWithCode:(int)aStatus];
00290 
00291   return NS_OK;
00292 }
00293 
00294 // Implementation of nsIEmbeddingSiteWindow2
00295 NS_IMETHODIMP
00296 CHBrowserListener::Blur()
00297 {
00298   return NS_OK;
00299 }
00300 
00301 // Implementation of nsIEmbeddingSiteWindow
00302 /* void setDimensions (in unsigned long flags, in long x, in long y, in long cx, in long cy); */
00303 NS_IMETHODIMP 
00304 CHBrowserListener::SetDimensions(PRUint32 flags, PRInt32 x, PRInt32 y, PRInt32 cx, PRInt32 cy)
00305 {
00306   if (!mView)
00307     return NS_ERROR_FAILURE;
00308 
00309   NSWindow* window = [mView window];
00310   if (!window)
00311     return NS_ERROR_FAILURE;
00312 
00313   if (flags & nsIEmbeddingSiteWindow::DIM_FLAGS_POSITION) {
00314     NSPoint origin;
00315     origin.x = (float)x;
00316     origin.y = (float)y;
00317     
00318     // websites assume the origin is the topleft of the window and that the screen origin
00319     // is "topleft" (quickdraw coordinates). As a result, we have to convert it.
00320     GDHandle screenDevice = ::GetMainDevice();
00321     Rect screenRect = (**screenDevice).gdRect;
00322     short screenHeight = screenRect.bottom - screenRect.top;
00323     origin.y = screenHeight - origin.y;
00324     
00325     [window setFrameTopLeftPoint:origin];
00326   }
00327 
00328   if (flags & nsIEmbeddingSiteWindow::DIM_FLAGS_SIZE_OUTER) {
00329     NSRect frame = [window frame];
00330     frame.size.width = (float)cx;
00331     frame.size.height = (float)cy;
00332     [window setFrame:frame display:YES];
00333   }
00334   else if (flags & nsIEmbeddingSiteWindow::DIM_FLAGS_SIZE_INNER) {
00335     NSSize size;
00336     size.width = (float)cx;
00337     size.height = (float)cy;
00338     [window setContentSize:size];
00339   }
00340 
00341   return NS_OK;
00342 }
00343 
00344 /* void getDimensions (in unsigned long flags, out long x, out long y, out long cx, out long cy); */
00345 NS_IMETHODIMP 
00346 CHBrowserListener::GetDimensions(PRUint32 flags,  PRInt32 *x,  PRInt32 *y, PRInt32 *cx, PRInt32 *cy)
00347 {
00348   if (!mView)
00349     return NS_ERROR_FAILURE;
00350 
00351   NSWindow* window = [mView window];
00352   if (!window)
00353     return NS_ERROR_FAILURE;
00354 
00355   NSRect frame = [window frame];
00356   if (flags & nsIEmbeddingSiteWindow::DIM_FLAGS_POSITION) {
00357     if ( x )
00358       *x = (PRInt32)frame.origin.x;
00359     if ( y )
00360       *y = (PRInt32)frame.origin.y;
00361   }
00362   if (flags & nsIEmbeddingSiteWindow::DIM_FLAGS_SIZE_OUTER) {
00363     if ( cx )
00364       *cx = (PRInt32)frame.size.width;
00365     if ( cy )
00366       *cy = (PRInt32)frame.size.height;
00367   }
00368   else if (flags & nsIEmbeddingSiteWindow::DIM_FLAGS_SIZE_INNER) {
00369     NSView* contentView = [window contentView];
00370     NSRect contentFrame = [contentView frame];
00371     if ( cx )
00372       *cx = (PRInt32)contentFrame.size.width;
00373     if ( cy )
00374       *cy = (PRInt32)contentFrame.size.height;    
00375   }
00376 
00377   return NS_OK;
00378 }
00379 
00380 /* void setFocus (); */
00381 NS_IMETHODIMP 
00382 CHBrowserListener::SetFocus()
00383 {
00384   if (!mView) {
00385     return NS_ERROR_FAILURE;
00386   }
00387 
00388   NSWindow* window = [mView window];
00389   if (!window) {
00390     return NS_ERROR_FAILURE;
00391   }
00392 
00393   [window makeKeyAndOrderFront:window];
00394 
00395   return NS_OK;
00396 }
00397 
00398 /* attribute boolean visibility; */
00399 NS_IMETHODIMP 
00400 CHBrowserListener::GetVisibility(PRBool *aVisibility)
00401 {
00402   NS_ENSURE_ARG_POINTER(aVisibility);
00403 
00404   if (!mView) {
00405     return NS_ERROR_FAILURE;
00406   }
00407 
00408   NSWindow* window = [mView window];
00409   if (!window) {
00410     return NS_ERROR_FAILURE;
00411   }
00412 
00413   *aVisibility = [window isMiniaturized];
00414 
00415   return NS_OK;
00416 }
00417 NS_IMETHODIMP 
00418 CHBrowserListener::SetVisibility(PRBool aVisibility)
00419 {
00420   if (!mView) {
00421     return NS_ERROR_FAILURE;
00422   }
00423 
00424   NSWindow* window = [mView window];
00425   if (!window) {
00426     return NS_ERROR_FAILURE;
00427   }
00428 
00429   if (aVisibility) {
00430     [window deminiaturize:window];
00431   }
00432   else {
00433     [window miniaturize:window];
00434   }
00435 
00436   return NS_OK;
00437 }
00438 
00439 /* attribute wstring title; */
00440 NS_IMETHODIMP 
00441 CHBrowserListener::GetTitle(PRUnichar * *aTitle)
00442 {
00443   NS_ENSURE_ARG_POINTER(aTitle);
00444 
00445   if (!mContainer) {
00446     return NS_ERROR_FAILURE;
00447   }
00448 
00449   NSString* title = [mContainer title];
00450   unsigned int length = [title length];
00451   if (length) {
00452     *aTitle = (PRUnichar*)nsMemory::Alloc((length+1)*sizeof(PRUnichar));
00453     if (!*aTitle) {
00454       return NS_ERROR_OUT_OF_MEMORY;
00455     }
00456     [title getCharacters:*aTitle];
00457   }
00458   else {
00459     *aTitle = nsnull;
00460   }
00461   
00462   return NS_OK;
00463 }
00464 NS_IMETHODIMP 
00465 CHBrowserListener::SetTitle(const PRUnichar * aTitle)
00466 {
00467   NS_ENSURE_ARG(aTitle);
00468 
00469   if (!mContainer) {
00470     return NS_ERROR_FAILURE;
00471   }
00472 
00473   NSString* str = [NSString stringWithPRUnichars:aTitle];
00474   [mContainer setTitle:str];
00475 
00476   return NS_OK;
00477 }
00478 
00479 /* [noscript] readonly attribute voidPtr siteWindow; */
00480 NS_IMETHODIMP 
00481 CHBrowserListener::GetSiteWindow(void * *aSiteWindow)
00482 {
00483   NS_ENSURE_ARG_POINTER(aSiteWindow);
00484   *aSiteWindow = nsnull;
00485   if (!mView) {
00486     return NS_ERROR_FAILURE;
00487   }
00488 
00489   NSWindow* window = [mView window];
00490   if (!window) {
00491     return NS_ERROR_FAILURE;
00492   }
00493 
00494   *aSiteWindow = (void*)window;
00495 
00496   return NS_OK;
00497 }
00498 
00499 
00500 //
00501 // Implementation of nsIWebProgressListener
00502 //
00503 
00504 /* void onStateChange (in nsIWebProgress aWebProgress, in nsIRequest aRequest, in unsigned long aStateFlags, in unsigned long aStatus); */
00505 NS_IMETHODIMP 
00506 CHBrowserListener::OnStateChange(nsIWebProgress *aWebProgress, nsIRequest *aRequest, 
00507                                         PRUint32 aStateFlags, PRUint32 aStatus)
00508 {
00509   NSEnumerator* enumerator = [mListeners objectEnumerator];
00510   id<CHBrowserListener> obj;
00511   
00512   if (aStateFlags & nsIWebProgressListener::STATE_IS_NETWORK) {
00513     if (aStateFlags & nsIWebProgressListener::STATE_START) {
00514       while ((obj = [enumerator nextObject]))
00515         [obj onLoadingStarted];
00516     }
00517     else if (aStateFlags & nsIWebProgressListener::STATE_STOP) {
00518       while ((obj = [enumerator nextObject]))
00519         [obj onLoadingCompleted:(NS_SUCCEEDED(aStatus))];
00520     }
00521   }
00522 
00523   return NS_OK;
00524 }
00525 
00526 /* void onProgressChange (in nsIWebProgress aWebProgress, in nsIRequest aRequest, in long aCurSelfProgress, in long aMaxSelfProgress, in long aCurTotalProgress, in long aMaxTotalProgress); */
00527 NS_IMETHODIMP 
00528 CHBrowserListener::OnProgressChange(nsIWebProgress *aWebProgress, nsIRequest *aRequest, 
00529                                           PRInt32 aCurSelfProgress, PRInt32 aMaxSelfProgress, 
00530                                           PRInt32 aCurTotalProgress, PRInt32 aMaxTotalProgress)
00531 {
00532   NSEnumerator* enumerator = [mListeners objectEnumerator];
00533   id<CHBrowserListener> obj;
00534   while ((obj = [enumerator nextObject]))
00535     [obj onProgressChange:aCurTotalProgress outOf:aMaxTotalProgress];
00536   
00537   return NS_OK;
00538 }
00539 
00540 /* void onLocationChange (in nsIWebProgress aWebProgress, in nsIRequest aRequest, in nsIURI location); */
00541 NS_IMETHODIMP 
00542 CHBrowserListener::OnLocationChange(nsIWebProgress *aWebProgress, nsIRequest *aRequest, 
00543                                           nsIURI *location)
00544 {
00545   if (!location)
00546     return NS_ERROR_FAILURE;
00547     
00548   nsCAutoString spec;
00549   location->GetSpec(spec);
00550   NSString* str = [NSString stringWithCString:spec.get()];
00551 
00552   NSEnumerator* enumerator = [mListeners objectEnumerator];
00553   id<CHBrowserListener> obj;
00554   while ((obj = [enumerator nextObject]))
00555     [obj onLocationChange:str];
00556 
00557   return NS_OK;
00558 }
00559 
00560 /* void onStatusChange (in nsIWebProgress aWebProgress, in nsIRequest aRequest, in nsresult aStatus, in wstring aMessage); */
00561 NS_IMETHODIMP 
00562 CHBrowserListener::OnStatusChange(nsIWebProgress *aWebProgress, nsIRequest *aRequest, nsresult aStatus, 
00563                                         const PRUnichar *aMessage)
00564 {
00565   NSString* str = [NSString stringWithPRUnichars:aMessage];
00566   
00567   NSEnumerator* enumerator = [mListeners objectEnumerator];
00568   id<CHBrowserListener> obj; 
00569   while ((obj = [enumerator nextObject]))
00570     [obj onStatusChange: str];
00571 
00572   return NS_OK;
00573 }
00574 
00575 /* void onSecurityChange (in nsIWebProgress aWebProgress, in nsIRequest aRequest, in unsigned long state); */
00576 NS_IMETHODIMP 
00577 CHBrowserListener::OnSecurityChange(nsIWebProgress *aWebProgress, nsIRequest *aRequest, PRUint32 state)
00578 {
00579   NSEnumerator* enumerator = [mListeners objectEnumerator];
00580   id<CHBrowserListener> obj; 
00581   while ((obj = [enumerator nextObject]))
00582     [obj onSecurityStateChange: state];
00583 
00584   return NS_OK;
00585 }
00586 
00587 void 
00588 CHBrowserListener::AddListener(id <CHBrowserListener> aListener)
00589 {
00590   [mListeners addObject:aListener];
00591 }
00592 
00593 void 
00594 CHBrowserListener::RemoveListener(id <CHBrowserListener> aListener)
00595 {
00596   [mListeners removeObject:aListener];
00597 }
00598 
00599 void 
00600 CHBrowserListener::SetContainer(id <CHBrowserContainer> aContainer)
00601 {
00602   [mContainer autorelease];
00603 
00604   mContainer = aContainer;
00605 
00606   [mContainer retain];
00607 }
00608