Back to index

lightning-sunbird  0.9+nobinonly
CHBrowserView.mm
Go to the documentation of this file.
00001 /* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
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 #import "NSString+Utils.h"
00039 #import "CHClickListener.h"
00040 
00041 #include "nsCWebBrowser.h"
00042 #include "nsIBaseWindow.h"
00043 #include "nsIWebNavigation.h"
00044 #include "nsComponentManagerUtils.h"
00045 
00046 #include "nsIURI.h"
00047 #include "nsIDOMWindow.h"
00048 #include "nsPIDOMWindow.h"
00049 #include "nsIChromeEventHandler.h"
00050 #include "nsIDOMEventReceiver.h"
00051 #include "nsIWidget.h"
00052 
00053 // Printing
00054 #include "nsIWebBrowserPrint.h"
00055 //#include "nsIPrintSettings.h"
00056 
00057 // Saving of links/images/docs
00058 #include "nsIWebBrowserFocus.h"
00059 #include "nsIDOMNSDocument.h"
00060 #include "nsIDOMLocation.h"
00061 #include "nsIWebBrowserPersist.h"
00062 #include "nsIProperties.h"
00063 //#include "nsIRequest.h"
00064 //#include "nsIPrefService.h"
00065 #include "nsISHistory.h"
00066 #include "nsIHistoryEntry.h"
00067 #include "nsISHEntry.h"
00068 #include "nsNetUtil.h"
00069 #include "SaveHeaderSniffer.h"
00070 #include "nsIWebBrowserFind.h"
00071 
00072 #import "CHBrowserView.h"
00073 
00074 #import "CHBrowserService.h"
00075 #import "CHBrowserListener.h"
00076 
00077 #import "mozView.h"
00078 
00079 typedef unsigned int DragReference;
00080 #include "nsIDragHelperService.h"
00081 
00082 // Cut/copy/paste
00083 #include "nsIClipboardCommands.h"
00084 #include "nsIInterfaceRequestorUtils.h"
00085 
00086 // Undo/redo
00087 #include "nsICommandManager.h"
00088 #include "nsICommandParams.h"
00089 
00090 
00091 const char kPersistContractID[] = "@mozilla.org/embedding/browser/nsWebBrowserPersist;1";
00092 const char kDirServiceContractID[] = "@mozilla.org/file/directory_service;1";
00093 
00094 @implementation CHBrowserView
00095 
00096 - (id)initWithFrame:(NSRect)frame andWindow:(NSWindow*)aWindow
00097 {
00098   mWindow = aWindow;
00099   return [self initWithFrame:frame];
00100 }
00101 
00102 - (id)initWithFrame:(NSRect)frame
00103 {
00104   if ( (self = [super initWithFrame:frame]) )
00105   {
00106     nsresult rv = CHBrowserService::InitEmbedding();
00107     if (NS_FAILED(rv)) {
00108 // XXX need to throw
00109     }
00110 
00111     _listener = new CHBrowserListener(self);
00112     NS_ADDREF(_listener);
00113     
00114 // Create the web browser instance
00115     nsCOMPtr<nsIWebBrowser> browser = do_CreateInstance(NS_WEBBROWSER_CONTRACTID, &rv);
00116     if (NS_FAILED(rv)) {
00117 // XXX need to throw
00118     }
00119 
00120     _webBrowser = browser;
00121     NS_ADDREF(_webBrowser);
00122     
00123 // Set the container nsIWebBrowserChrome
00124     _webBrowser->SetContainerWindow(NS_STATIC_CAST(nsIWebBrowserChrome *, _listener));
00125     
00126 // Register as a listener for web progress
00127     nsCOMPtr<nsIWeakReference> weak = do_GetWeakReference(NS_STATIC_CAST(nsIWebProgressListener*, _listener));
00128     _webBrowser->AddWebBrowserListener(weak, NS_GET_IID(nsIWebProgressListener));
00129     
00130 // Hook up the widget hierarchy with us as the parent
00131     nsCOMPtr<nsIBaseWindow> baseWin = do_QueryInterface(_webBrowser);
00132     baseWin->InitWindow((NSView*)self, nsnull, 0, 0,
00133                         frame.size.width, frame.size.height);
00134     baseWin->Create();
00135     
00136 // register the view as a drop site for text, files, and urls. 
00137     [self registerForDraggedTypes: [NSArray arrayWithObjects:
00138               @"MozURLType", NSStringPboardType, NSURLPboardType, NSFilenamesPboardType, nil]];
00139 
00140     // hookup the listener for creating our own native menus on <SELECTS>
00141     CHClickListener* clickListener = new CHClickListener();
00142     if (!clickListener)
00143       return nil;
00144     
00145     nsCOMPtr<nsIDOMWindow> contentWindow = getter_AddRefs([self getContentWindow]);
00146     nsCOMPtr<nsPIDOMWindow> piWindow(do_QueryInterface(contentWindow));
00147     nsCOMPtr<nsIDOMEventReceiver> rec(do_QueryInterface(piWindow->GetChromeEventHandler()));
00148     if ( rec )
00149       rec->AddEventListenerByIID(clickListener, NS_GET_IID(nsIDOMMouseListener));
00150   }
00151   return self;
00152 }
00153 
00154 - (void)destroyWebBrowser
00155 {
00156   nsCOMPtr<nsIBaseWindow> baseWin = do_QueryInterface(_webBrowser);
00157   if ( baseWin ) {
00158     // clean up here rather than in the dtor so that if anyone tries to get our
00159     // web browser, it won't get a garbage object that's past its prime. As a result,
00160     // this routine MUST be called otherwise we will leak.
00161     baseWin->Destroy();
00162     NS_RELEASE(_webBrowser);
00163   }
00164 }
00165 
00166 - (void)dealloc 
00167 {
00168   NS_RELEASE(_listener);
00169   
00170   // it is imperative that |destroyWebBrowser()| be called before we get here, otherwise
00171   // we will leak the webBrowser.
00172        NS_ASSERTION(!_webBrowser, "BrowserView going away, destroyWebBrowser not called; leaking webBrowser!");
00173   
00174   CHBrowserService::BrowserClosed();
00175   
00176 #if DEBUG
00177   NSLog(@"CHBrowserView died.");
00178 #endif
00179 
00180   [super dealloc];
00181 }
00182 
00183 - (void)setFrame:(NSRect)frameRect 
00184 {
00185   [super setFrame:frameRect];
00186   if (_webBrowser) {
00187     nsCOMPtr<nsIBaseWindow> window = do_QueryInterface(_webBrowser);
00188     window->SetSize((PRInt32)frameRect.size.width, 
00189         (PRInt32)frameRect.size.height,
00190         PR_TRUE);
00191   }
00192 }
00193 
00194 - (void)addListener:(id <CHBrowserListener>)listener
00195 {
00196   _listener->AddListener(listener);
00197 }
00198 
00199 - (void)removeListener:(id <CHBrowserListener>)listener
00200 {
00201   _listener->RemoveListener(listener);
00202 }
00203 
00204 - (void)setContainer:(id <CHBrowserContainer>)container
00205 {
00206   _listener->SetContainer(container);
00207 }
00208 
00209 - (nsIDOMWindow*)getContentWindow
00210 {
00211   nsIDOMWindow* window = nsnull;
00212 
00213   if ( _webBrowser )
00214     _webBrowser->GetContentDOMWindow(&window);
00215 
00216   return window;
00217 }
00218 
00219 - (void)loadURI:(NSString *)urlSpec referrer:(NSString*)referrer flags:(unsigned int)flags
00220 {
00221   nsCOMPtr<nsIWebNavigation> nav = do_QueryInterface(_webBrowser);
00222   
00223   int length = [urlSpec length];
00224   PRUnichar* specStr = nsMemory::Alloc((length+1) * sizeof(PRUnichar));
00225   [urlSpec getCharacters:specStr];
00226   specStr[length] = PRUnichar(0);
00227   
00228   nsCOMPtr<nsIURI> referrerURI;
00229   if ( referrer )
00230     NS_NewURI(getter_AddRefs(referrerURI), [referrer UTF8String]);
00231 
00232   PRUint32 navFlags = nsIWebNavigation::LOAD_FLAGS_NONE;
00233   if (flags & NSLoadFlagsDontPutInHistory) {
00234     navFlags |= nsIWebNavigation::LOAD_FLAGS_BYPASS_HISTORY;
00235   }
00236   if (flags & NSLoadFlagsReplaceHistoryEntry) {
00237     navFlags |= nsIWebNavigation::LOAD_FLAGS_REPLACE_HISTORY;
00238   }
00239   if (flags & NSLoadFlagsBypassCacheAndProxy) {
00240     navFlags |= nsIWebNavigation::LOAD_FLAGS_BYPASS_CACHE | 
00241                 nsIWebNavigation::LOAD_FLAGS_BYPASS_PROXY;
00242   }
00243 
00244   nsresult rv = nav->LoadURI(specStr, navFlags, referrerURI, nsnull, nsnull);
00245   if (NS_FAILED(rv)) {
00246     // XXX need to throw
00247   }
00248 
00249   nsMemory::Free(specStr);
00250 }
00251 
00252 - (void)reload:(unsigned int)flags
00253 {
00254   nsCOMPtr<nsIWebNavigation> nav = do_QueryInterface(_webBrowser);
00255   if ( !nav )
00256     return;
00257 
00258   PRUint32 navFlags = nsIWebNavigation::LOAD_FLAGS_NONE;
00259   if (flags & NSLoadFlagsBypassCacheAndProxy) {
00260     navFlags |= nsIWebNavigation::LOAD_FLAGS_BYPASS_CACHE | 
00261                 nsIWebNavigation::LOAD_FLAGS_BYPASS_PROXY;
00262   }
00263   
00264   nsresult rv = nav->Reload(navFlags);
00265   if (NS_FAILED(rv)) {
00266     // XXX need to throw
00267   }  
00268 }
00269 
00270 - (BOOL)canGoBack
00271 {
00272   nsCOMPtr<nsIWebNavigation> nav = do_QueryInterface(_webBrowser);
00273   if ( !nav )
00274     return NO;
00275 
00276   PRBool can;
00277   nav->GetCanGoBack(&can);
00278 
00279   return can ? YES : NO;
00280 }
00281 
00282 - (BOOL)canGoForward
00283 {
00284   nsCOMPtr<nsIWebNavigation> nav = do_QueryInterface(_webBrowser);
00285   if ( !nav )
00286     return NO;
00287 
00288   PRBool can;
00289   nav->GetCanGoForward(&can);
00290 
00291   return can ? YES : NO;
00292 }
00293 
00294 - (void)goBack
00295 {
00296   nsCOMPtr<nsIWebNavigation> nav = do_QueryInterface(_webBrowser);
00297   if ( !nav )
00298     return;
00299 
00300   nsresult rv = nav->GoBack();
00301   if (NS_FAILED(rv)) {
00302     // XXX need to throw
00303   }  
00304 }
00305 
00306 - (void)goForward
00307 {
00308   nsCOMPtr<nsIWebNavigation> nav = do_QueryInterface(_webBrowser);
00309   if ( !nav )
00310     return;
00311 
00312   nsresult rv = nav->GoForward();
00313   if (NS_FAILED(rv)) {
00314     // XXX need to throw
00315   }  
00316 }
00317 
00318 - (void)gotoIndex:(int)index
00319 {
00320   nsCOMPtr<nsIWebNavigation> nav = do_QueryInterface(_webBrowser);
00321   if ( !nav )
00322     return;
00323 
00324   nsresult rv = nav->GotoIndex(index);
00325   if (NS_FAILED(rv)) {
00326     // XXX need to throw
00327   }    
00328 }
00329 
00330 - (void)stop:(unsigned int)flags
00331 {
00332   nsCOMPtr<nsIWebNavigation> nav = do_QueryInterface(_webBrowser);
00333   if ( !nav )
00334     return;
00335 
00336   nsresult rv = nav->Stop(flags);
00337   if (NS_FAILED(rv)) {
00338     // XXX need to throw
00339   }    
00340 }
00341 
00342 // XXXbryner This isn't used anywhere. how is it different from getCurrentURLSpec?
00343 - (NSString*)getCurrentURI
00344 {
00345   nsCOMPtr<nsIURI> uri;
00346   nsCOMPtr<nsIWebNavigation> nav = do_QueryInterface(_webBrowser);
00347   if ( !nav )
00348     return nsnull;
00349 
00350   nav->GetCurrentURI(getter_AddRefs(uri));
00351   if (!uri) {
00352     return nsnull;
00353   }
00354 
00355   nsCAutoString spec;
00356   uri->GetSpec(spec);
00357   
00358   const char* cstr = spec.get();
00359   NSString* str = [NSString stringWithCString:cstr];
00360   
00361   return str;
00362 }
00363 
00364 - (CHBrowserListener*)getCocoaBrowserListener
00365 {
00366   return _listener;
00367 }
00368 
00369 - (nsIWebBrowser*)getWebBrowser
00370 {
00371   NS_IF_ADDREF(_webBrowser);
00372   return _webBrowser;
00373 }
00374 
00375 - (void)setWebBrowser:(nsIWebBrowser*)browser
00376 {
00377   NS_IF_ADDREF(browser);                         // prevents destroying |browser| if |browser| == |_webBrowser|
00378   NS_IF_RELEASE(_webBrowser);
00379   _webBrowser = browser;
00380 
00381   if (_webBrowser) {
00382     // Set the container nsIWebBrowserChrome
00383     _webBrowser->SetContainerWindow(NS_STATIC_CAST(nsIWebBrowserChrome *, 
00384                _listener));
00385 
00386     NSRect frame = [self frame];
00387  
00388     // Hook up the widget hierarchy with us as the parent
00389     nsCOMPtr<nsIBaseWindow> baseWin = do_QueryInterface(_webBrowser);
00390     baseWin->InitWindow((NSView*)self, nsnull, 0, 0, 
00391       frame.size.width, frame.size.height);
00392     baseWin->Create();
00393   }
00394 
00395 }
00396 
00397 -(void) saveInternal: (nsIURI*)aURI
00398         withDocument: (nsIDOMDocument*)aDocument
00399         suggestedFilename: (const char*)aFilename
00400         bypassCache: (BOOL)aBypassCache
00401         filterView: (NSView*)aFilterView
00402         filterList: (NSPopUpButton*)aFilterList
00403 {
00404     // Create our web browser persist object.  This is the object that knows
00405     // how to actually perform the saving of the page (and of the images
00406     // on the page).
00407     nsCOMPtr<nsIWebBrowserPersist> webPersist(do_CreateInstance(kPersistContractID));
00408     if (!webPersist)
00409         return;
00410     
00411     // Make a temporary file object that we can save to.
00412     nsCOMPtr<nsIProperties> dirService(do_GetService(kDirServiceContractID));
00413     if (!dirService)
00414         return;
00415     nsCOMPtr<nsIFile> tmpFile;
00416     dirService->Get("TmpD", NS_GET_IID(nsIFile), getter_AddRefs(tmpFile));
00417     static short unsigned int tmpRandom = 0;
00418     nsAutoString tmpNo; tmpNo.AppendInt(tmpRandom++);
00419     nsAutoString saveFile(NS_LITERAL_STRING("-sav"));
00420     saveFile += tmpNo;
00421     saveFile += NS_LITERAL_STRING("tmp");
00422     tmpFile->Append(saveFile); 
00423     
00424     // Get the post data if we're an HTML doc.
00425     nsCOMPtr<nsIInputStream> postData;
00426     if (aDocument) {
00427       nsCOMPtr<nsIWebNavigation> webNav(do_QueryInterface(_webBrowser));
00428       if (webNav) {
00429         nsCOMPtr<nsISHistory> sessionHistory;
00430         webNav->GetSessionHistory(getter_AddRefs(sessionHistory));
00431         nsCOMPtr<nsIHistoryEntry> entry;
00432         PRInt32 sindex;
00433         sessionHistory->GetIndex(&sindex);
00434         sessionHistory->GetEntryAtIndex(sindex, PR_FALSE, getter_AddRefs(entry));
00435         nsCOMPtr<nsISHEntry> shEntry(do_QueryInterface(entry));
00436         if (shEntry)
00437             shEntry->GetPostData(getter_AddRefs(postData));
00438       }
00439     }
00440 
00441     // when saving, we first fire off a save with a nsHeaderSniffer as a progress
00442     // listener. This allows us to look for the content-disposition header, which
00443     // can supply a filename, and maybe has something to do with CGI-generated
00444     // content (?)
00445     nsCAutoString fileName(aFilename);
00446     nsHeaderSniffer* sniffer = new nsHeaderSniffer(webPersist, tmpFile, aURI, 
00447                                                    aDocument, postData, fileName, aBypassCache,
00448                                                    aFilterView, aFilterList);
00449     if (!sniffer)
00450         return;
00451     webPersist->SetProgressListener(sniffer);  // owned
00452     webPersist->SaveURI(aURI, nsnull, nsnull, nsnull, nsnull, tmpFile);
00453 }
00454 
00455 -(void)printDocument
00456 {
00457   if (!_webBrowser)
00458     return;
00459   nsCOMPtr<nsIDOMWindow> domWindow;
00460   _webBrowser->GetContentDOMWindow(getter_AddRefs(domWindow));
00461   nsCOMPtr<nsIInterfaceRequestor> ir(do_QueryInterface(domWindow));
00462   nsCOMPtr<nsIWebBrowserPrint> print;
00463   ir->GetInterface(NS_GET_IID(nsIWebBrowserPrint), getter_AddRefs(print));
00464   print->Print(nsnull, nsnull);
00465 }
00466 
00467 - (BOOL)findInPageWithPattern:(NSString*)inText caseSensitive:(BOOL)inCaseSensitive
00468     wrap:(BOOL)inWrap backwards:(BOOL)inBackwards
00469 {
00470     if (!_webBrowser)
00471       return NO;
00472     PRBool found =  PR_FALSE;
00473     
00474     nsCOMPtr<nsIWebBrowserFocus> wbf(do_QueryInterface(_webBrowser));
00475     nsCOMPtr<nsIDOMWindow> rootWindow;
00476     nsCOMPtr<nsIDOMWindow> focusedWindow;
00477     _webBrowser->GetContentDOMWindow(getter_AddRefs(rootWindow));
00478     wbf->GetFocusedWindow(getter_AddRefs(focusedWindow));
00479     if (!focusedWindow)
00480         focusedWindow = rootWindow;
00481     nsCOMPtr<nsIWebBrowserFind> webFind(do_GetInterface(_webBrowser));
00482     if ( webFind ) {
00483       nsCOMPtr<nsIWebBrowserFindInFrames> framesFind(do_QueryInterface(webFind));
00484       framesFind->SetRootSearchFrame(rootWindow);
00485       framesFind->SetCurrentSearchFrame(focusedWindow);
00486       
00487       webFind->SetMatchCase(inCaseSensitive ? PR_TRUE : PR_FALSE);
00488       webFind->SetWrapFind(inWrap ? PR_TRUE : PR_FALSE);
00489       webFind->SetFindBackwards(inBackwards ? PR_TRUE : PR_FALSE);
00490     
00491       PRUnichar* text = (PRUnichar*)nsMemory::Alloc(([inText length]+1)*sizeof(PRUnichar));
00492       if ( text ) {
00493         [inText getCharacters:text];
00494         text[[inText length]] = 0;
00495         webFind->SetSearchString(text);
00496         webFind->FindNext(&found);
00497         nsMemory::Free(text);
00498       }
00499     }
00500     return found;
00501 }
00502 
00503 - (void)saveURL: (NSView*)aFilterView filterList: (NSPopUpButton*)aFilterList
00504             url: (NSString*)aURLSpec suggestedFilename: (NSString*)aFilename
00505 {
00506   nsCOMPtr<nsIURI> url;
00507   nsresult rv = NS_NewURI(getter_AddRefs(url), [aURLSpec UTF8String]);
00508   if (NS_FAILED(rv))
00509     return;
00510   
00511   [self saveInternal: url.get()
00512         withDocument: nsnull
00513    suggestedFilename: (([aFilename length] > 0) ? [aFilename fileSystemRepresentation] : "")
00514          bypassCache: YES
00515           filterView: aFilterView
00516           filterList: aFilterList];
00517 }
00518 
00519 -(NSString*)getFocusedURLString
00520 {
00521   if (!_webBrowser)
00522     return @"";
00523   nsCOMPtr<nsIWebBrowserFocus> wbf(do_QueryInterface(_webBrowser));
00524   nsCOMPtr<nsIDOMWindow> domWindow;
00525   wbf->GetFocusedWindow(getter_AddRefs(domWindow));
00526   if (!domWindow)
00527     _webBrowser->GetContentDOMWindow(getter_AddRefs(domWindow));
00528   if (!domWindow)
00529     return @"";
00530 
00531   nsCOMPtr<nsIDOMDocument> domDocument;
00532   domWindow->GetDocument(getter_AddRefs(domDocument));
00533   if (!domDocument)
00534     return @"";
00535   nsCOMPtr<nsIDOMNSDocument> nsDoc(do_QueryInterface(domDocument));
00536   if (!nsDoc)
00537     return @"";
00538   nsCOMPtr<nsIDOMLocation> location;
00539   nsDoc->GetLocation(getter_AddRefs(location));
00540   if (!location)
00541     return @"";
00542   nsAutoString urlStr;
00543   location->GetHref(urlStr);
00544   return [NSString stringWith_nsAString: urlStr];
00545 }
00546 
00547 - (void)saveDocument: (NSView*)aFilterView filterList: (NSPopUpButton*)aFilterList
00548 {
00549     if (!_webBrowser)
00550       return;
00551     nsCOMPtr<nsIWebBrowserFocus> wbf(do_QueryInterface(_webBrowser));
00552     nsCOMPtr<nsIDOMWindow> domWindow;
00553     wbf->GetFocusedWindow(getter_AddRefs(domWindow));
00554     if (!domWindow)
00555         _webBrowser->GetContentDOMWindow(getter_AddRefs(domWindow));
00556     if (!domWindow)
00557         return;
00558     
00559     nsCOMPtr<nsIDOMDocument> domDocument;
00560     domWindow->GetDocument(getter_AddRefs(domDocument));
00561     if (!domDocument)
00562         return;
00563     nsCOMPtr<nsIDOMNSDocument> nsDoc(do_QueryInterface(domDocument));
00564     if (!nsDoc)
00565         return;
00566     nsCOMPtr<nsIDOMLocation> location;
00567     nsDoc->GetLocation(getter_AddRefs(location));
00568     if (!location)
00569         return;
00570     nsAutoString urlStr;
00571     location->GetHref(urlStr);
00572 #warning fix me
00573     nsCOMPtr<nsIURI> url;
00574     nsresult rv = NS_NewURI(getter_AddRefs(url), urlStr);
00575     if (NS_FAILED(rv))
00576         return;
00577     
00578     [self saveInternal: url.get()
00579           withDocument: domDocument
00580           suggestedFilename: ""
00581           bypassCache: NO
00582           filterView: aFilterView
00583           filterList: aFilterList];
00584 }
00585 
00586 -(void)doCommand:(const char*)commandName
00587 {
00588   nsCOMPtr<nsICommandManager> commandMgr(do_GetInterface(_webBrowser));
00589   if (commandMgr) {
00590     nsresult rv = commandMgr->DoCommand(commandName, nsnull, nsnull);
00591 #if DEBUG
00592       if (NS_FAILED(rv))
00593         NSLog(@"DoCommand failed");
00594 #endif
00595   }
00596   else {
00597 #if DEBUG
00598     NSLog(@"No command manager");
00599 #endif
00600   }
00601 }
00602 
00603 -(BOOL)isCommandEnabled:(const char*)commandName
00604 {
00605   PRBool      isEnabled = PR_FALSE;
00606   nsCOMPtr<nsICommandManager> commandMgr(do_GetInterface(_webBrowser));
00607   if (commandMgr) {
00608     nsresult rv = commandMgr->IsCommandEnabled(commandName, nsnull, &isEnabled);
00609 #if DEBUG
00610     if (NS_FAILED(rv))
00611       NSLog(@"IsCommandEnabled failed");
00612 #endif
00613   }
00614   else {
00615 #if DEBUG
00616     NSLog(@"No command manager");
00617 #endif
00618   }
00619   
00620   return (isEnabled) ? YES : NO;
00621 }
00622 
00623 
00624 -(IBAction)cut:(id)aSender
00625 {
00626   nsCOMPtr<nsIClipboardCommands> clipboard(do_GetInterface(_webBrowser));
00627   if ( clipboard )
00628     clipboard->CutSelection();
00629 }
00630 
00631 -(BOOL)canCut
00632 {
00633   PRBool canCut = PR_FALSE;
00634   nsCOMPtr<nsIClipboardCommands> clipboard(do_GetInterface(_webBrowser));
00635   if ( clipboard )
00636     clipboard->CanCutSelection(&canCut);
00637   return canCut;
00638 }
00639 
00640 -(IBAction)copy:(id)aSender
00641 {
00642   nsCOMPtr<nsIClipboardCommands> clipboard(do_GetInterface(_webBrowser));
00643   if ( clipboard )
00644     clipboard->CopySelection();
00645 }
00646 
00647 -(BOOL)canCopy
00648 {
00649   PRBool canCut = PR_FALSE;
00650   nsCOMPtr<nsIClipboardCommands> clipboard(do_GetInterface(_webBrowser));
00651   if ( clipboard )
00652     clipboard->CanCopySelection(&canCut);
00653   return canCut;
00654 }
00655 
00656 -(IBAction)paste:(id)aSender
00657 {
00658   nsCOMPtr<nsIClipboardCommands> clipboard(do_GetInterface(_webBrowser));
00659   if ( clipboard )
00660     clipboard->Paste();
00661 }
00662 
00663 -(BOOL)canPaste
00664 {
00665   PRBool canCut = PR_FALSE;
00666   nsCOMPtr<nsIClipboardCommands> clipboard(do_GetInterface(_webBrowser));
00667   if ( clipboard )
00668     clipboard->CanPaste(&canCut);
00669   return canCut;
00670 }
00671 
00672 -(IBAction)delete:(id)aSender
00673 {
00674   [self doCommand: "cmd_delete"];
00675 }
00676 
00677 -(BOOL)canDelete
00678 {
00679   return [self isCommandEnabled: "cmd_delete"];
00680 }
00681 
00682 -(IBAction)selectAll:(id)aSender
00683 {
00684   nsCOMPtr<nsIClipboardCommands> clipboard(do_GetInterface(_webBrowser));
00685   if ( clipboard )
00686     clipboard->SelectAll();
00687 }
00688 
00689 -(IBAction)undo:(id)aSender
00690 {
00691   [self doCommand: "cmd_undo"];
00692 }
00693 
00694 -(IBAction)redo:(id)aSender
00695 {
00696   [self doCommand: "cmd_redo"];
00697 }
00698 
00699 - (BOOL)canUndo
00700 {
00701   return [self isCommandEnabled: "cmd_undo"];
00702 }
00703 
00704 - (BOOL)canRedo
00705 {
00706   return [self isCommandEnabled: "cmd_redo"];
00707 }
00708 
00709 -(NSString*)getCurrentURLSpec
00710 {
00711   NSString* empty = @"";
00712   if (!_webBrowser)
00713     return empty;
00714   nsCOMPtr<nsIDOMWindow> domWindow;
00715   _webBrowser->GetContentDOMWindow(getter_AddRefs(domWindow));
00716   if (!domWindow)
00717     return empty;
00718   
00719   nsCOMPtr<nsIDOMDocument> domDocument;
00720   domWindow->GetDocument(getter_AddRefs(domDocument));
00721   if (!domDocument)
00722     return empty;
00723 
00724   nsCOMPtr<nsIDOMNSDocument> nsDoc(do_QueryInterface(domDocument));
00725   if (!nsDoc)
00726     return empty;
00727 
00728   nsCOMPtr<nsIDOMLocation> location;
00729   nsDoc->GetLocation(getter_AddRefs(location));
00730   if (!location)
00731     return empty;
00732 
00733   nsAutoString urlStr;
00734   location->GetHref(urlStr);
00735   return [NSString stringWith_nsAString: urlStr];
00736 }
00737 
00738 - (void)setActive: (BOOL)aIsActive
00739 {
00740   nsCOMPtr<nsIWebBrowserFocus> wbf(do_QueryInterface(_webBrowser));
00741   if (wbf) {
00742     if (aIsActive)
00743       wbf->Activate();
00744     else
00745       wbf->Deactivate();
00746   }
00747 }
00748 
00749 -(NSMenu*)getContextMenu
00750 {
00751   if ([[self superview] conformsToProtocol:@protocol(CHBrowserContainer)])
00752   {
00753     id<CHBrowserContainer> browserContainer = [self superview];
00754        return [browserContainer getContextMenu];
00755   }
00756   
00757   return nil;
00758 }
00759 
00760 -(NSWindow*)getNativeWindow
00761 {
00762   NSWindow* window = [self window];
00763   if (window)
00764     return window; // We're visible.  Just hand the window back.
00765 
00766   // We're invisible.  It's likely that we're in a Cocoa tab view.
00767   // First see if we have a cached window.
00768   if (mWindow)
00769     return mWindow;
00770   
00771   // Finally, see if our parent responds to the getNativeWindow selector,
00772   // and if they do, let them handle it.
00773   if ([[self superview] conformsToProtocol:@protocol(CHBrowserContainer)])
00774   {
00775     id<CHBrowserContainer> browserContainer = [self superview];
00776     return [browserContainer getNativeWindow];
00777   }
00778     
00779   return nil;
00780 }
00781 
00782 
00783 //
00784 // -findEventSink:forPoint:inWindow:
00785 //
00786 // Given a point in window coordinates, find the Gecko event sink of the ChildView
00787 // the point is over. This involves first converting the point to this view's
00788 // coordinate system and using hitTest: to get the subview. Then we get
00789 // that view's widget and QI it to an event sink
00790 //
00791 - (void) findEventSink:(nsIEventSink**)outSink forPoint:(NSPoint)inPoint inWindow:(NSWindow*)inWind
00792 {
00793   NSPoint localPoint = [self convertPoint:inPoint fromView:[inWind contentView]];
00794   NSView<mozView>* hitView = [self hitTest:localPoint];
00795   if ( [hitView conformsToProtocol:@protocol(mozView)] ) {
00796     nsCOMPtr<nsIEventSink> sink (do_QueryInterface([hitView widget]));
00797     *outSink = sink.get();
00798     NS_IF_ADDREF(*outSink);
00799   }
00800 }
00801 
00802 #pragma mark -
00803 
00804 - (BOOL)shouldAcceptDrag:(id <NSDraggingInfo>)sender
00805 {
00806   if ([[self superview] conformsToProtocol:@protocol(CHBrowserContainer)])
00807   {
00808     id<CHBrowserContainer> browserContainer = [self superview];
00809     return [browserContainer shouldAcceptDragFromSource:[sender draggingSource]];
00810   }
00811   return YES;
00812 }
00813 
00814 - (unsigned int)draggingEntered:(id <NSDraggingInfo>)sender
00815 {
00816   if (![self shouldAcceptDrag:sender])
00817     return NSDragOperationNone;
00818 
00819 //  NSLog(@"draggingEntered");  
00820   nsCOMPtr<nsIDragHelperService> helper(do_GetService("@mozilla.org/widget/draghelperservice;1"));
00821   mDragHelper = helper.get();
00822   NS_IF_ADDREF(mDragHelper);
00823   NS_ASSERTION ( mDragHelper, "Couldn't get a drag service, we're in big trouble" );
00824   
00825   if ( mDragHelper ) {
00826     mLastTrackedLocation = [sender draggingLocation];
00827     mLastTrackedWindow   = [sender draggingDestinationWindow];
00828     nsCOMPtr<nsIEventSink> sink;
00829     [self findEventSink:getter_AddRefs(sink) forPoint:mLastTrackedLocation inWindow:mLastTrackedWindow];
00830     if (sink)
00831       mDragHelper->Enter ( [sender draggingSequenceNumber], sink );
00832   }
00833   
00834   return NSDragOperationCopy;
00835 }
00836 
00837 - (void)draggingExited:(id <NSDraggingInfo>)sender
00838 {
00839 //  NSLog(@"draggingExited");
00840   if ( mDragHelper ) {
00841     nsCOMPtr<nsIEventSink> sink;
00842     
00843     /* [sender draggingLocation] *//* [sender draggingDestinationWindow] */[self findEventSink:getter_AddRefs(sink)
00844             forPoint:mLastTrackedLocation 
00845             inWindow:mLastTrackedWindow   
00846             ];
00847     if (sink)
00848       mDragHelper->Leave( [sender draggingSequenceNumber], sink );
00849     NS_RELEASE(mDragHelper);     
00850   }
00851 }
00852 
00853 - (unsigned int)draggingUpdated:(id <NSDraggingInfo>)sender
00854 {
00855   if (![self shouldAcceptDrag:sender])
00856     return NSDragOperationNone;
00857 
00858 //  NSLog(@"draggingUpdated");
00859   PRBool dropAllowed = PR_FALSE;
00860   if ( mDragHelper ) {
00861     mLastTrackedLocation = [sender draggingLocation];
00862     mLastTrackedWindow   = [sender draggingDestinationWindow];
00863     nsCOMPtr<nsIEventSink> sink;
00864     [self findEventSink:getter_AddRefs(sink) forPoint:mLastTrackedLocation inWindow:mLastTrackedWindow];
00865     if (sink)
00866       mDragHelper->Tracking([sender draggingSequenceNumber], sink, &dropAllowed);
00867   }
00868   
00869   return dropAllowed ? NSDragOperationCopy : NSDragOperationNone;
00870 }
00871 
00872 - (BOOL)prepareForDragOperation:(id <NSDraggingInfo>)sender
00873 {
00874   return YES;
00875 }
00876 
00877 - (BOOL)performDragOperation:(id <NSDraggingInfo>)sender
00878 {
00879   if (![self shouldAcceptDrag:sender])
00880     return NO;
00881 
00882   PRBool dragAccepted = PR_FALSE;
00883     
00884   if ( mDragHelper ) {
00885     nsCOMPtr<nsIEventSink> sink;
00886     [self findEventSink:getter_AddRefs(sink) forPoint:[sender draggingLocation]
00887             inWindow:[sender draggingDestinationWindow]];
00888     if (sink)
00889       mDragHelper->Drop([sender draggingSequenceNumber], sink, &dragAccepted);
00890   }
00891   
00892   return dragAccepted ? YES : NO;
00893 }
00894 
00895 #pragma mark -
00896 
00897 -(BOOL)validateMenuItem: (NSMenuItem*)aMenuItem
00898 {
00899   // update first responder items based on the selection
00900   SEL action = [aMenuItem action];
00901   if (action == @selector(cut:))
00902     return [self canCut];    
00903   else if (action == @selector(copy:))
00904     return [self canCopy];
00905   else if (action == @selector(paste:))
00906     return [self canPaste];
00907   else if (action == @selector(delete:))
00908     return [self canDelete];
00909   else if (action == @selector(undo:))
00910     return [self canUndo];
00911   else if (action == @selector(redo:))
00912     return [self canRedo];
00913   else if (action == @selector(selectAll:))
00914     return YES;
00915   
00916   return NO;
00917 }
00918 
00919 @end