/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */ /* ***** BEGIN LICENSE BLOCK ***** * Version: NPL 1.1/GPL 2.0/LGPL 2.1 * * The contents of this file are subject to the Netscape Public License * Version 1.1 (the "License"); you may not use this file except in * compliance with the License. You may obtain a copy of the License at * http://www.mozilla.org/NPL/ * * Software distributed under the License is distributed on an "AS IS" basis, * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License * for the specific language governing rights and limitations under the * License. * * The Original Code is mozilla.org code. * * The Initial Developer of the Original Code is * Netscape Communications Corporation. * Portions created by the Initial Developer are Copyright (C) 1998 * the Initial Developer. All Rights Reserved. * * Contributor(s): * * Alternatively, the contents of this file may be used under the terms of * either the GNU General Public License Version 2 or later (the "GPL"), or * the GNU Lesser General Public License Version 2.1 or later (the "LGPL"), * in which case the provisions of the GPL or the LGPL are applicable instead * of those above. If you wish to allow use of your version of this file only * under the terms of either the GPL or the LGPL, and not to allow others to * use your version of this file under the terms of the NPL, indicate your * decision by deleting the provisions above and replace them with the notice * and other provisions required by the GPL or the LGPL. If you do not delete * the provisions above, a recipient may use your version of this file under * the terms of any one of the NPL, the GPL or the LGPL. * * ***** END LICENSE BLOCK ***** */ #import "NSBrowserView.h" #import "ProgressDlgController.h" #import "nsCocoaBrowserService.h" // Embedding includes #include "nsCWebBrowser.h" #include "nsIInterfaceRequestor.h" #include "nsIWebBrowserChrome.h" #include "nsIEmbeddingSiteWindow.h" #include "nsIWebProgressListener.h" #include "nsIWebBrowser.h" #include "nsIWebNavigation.h" #include "nsIURI.h" #include "nsIDOMWindow.h" #include "nsWeakReference.h" // XPCOM and String includes #include "nsCRT.h" #include "nsXPIDLString.h" #include "nsCOMPtr.h" #include "nsIWebBrowserFocus.h" #include "nsIDOMHTMLDocument.h" #include "nsIDocument.h" #include "nsIURL.h" #include "nsIWebBrowserPersist.h" #include "nsIProperties.h" #include "nsIRequest.h" #include "nsIChannel.h" #include "nsIHttpChannel.h" #include "nsIPref.h" #include "nsIMIMEService.h" #include "nsIMIMEInfo.h" #include "nsISHistory.h" #include "nsIHistoryEntry.h" #include "nsISHEntry.h" const char* persistContractID = "@mozilla.org/embedding/browser/nsWebBrowserPersist;1"; const char* dirServiceContractID = "@mozilla.org/file/directory_service;1"; class nsCocoaBrowserListener : public nsSupportsWeakReference, public nsIInterfaceRequestor, public nsIWebBrowserChrome, public nsIEmbeddingSiteWindow, public nsIWebProgressListener { public: nsCocoaBrowserListener(NSBrowserView* aView); virtual ~nsCocoaBrowserListener(); NS_DECL_ISUPPORTS NS_DECL_NSIINTERFACEREQUESTOR NS_DECL_NSIWEBBROWSERCHROME NS_DECL_NSIEMBEDDINGSITEWINDOW NS_DECL_NSIWEBPROGRESSLISTENER void AddListener(id aListener); void RemoveListener(id aListener); void SetContainer(id aContainer); private: NSBrowserView* mView; // WEAK - it owns us NSMutableArray* mListeners; id mContainer; PRBool mIsModal; PRUint32 mChromeFlags; }; nsCocoaBrowserListener::nsCocoaBrowserListener(NSBrowserView* aView) : mView(aView), mContainer(nsnull), mIsModal(PR_FALSE), mChromeFlags(0) { NS_INIT_ISUPPORTS(); mListeners = [[NSMutableArray alloc] init]; } nsCocoaBrowserListener::~nsCocoaBrowserListener() { [mListeners release]; mView = nsnull; if (mContainer) { [mContainer release]; } } NS_IMPL_ISUPPORTS5(nsCocoaBrowserListener, nsIInterfaceRequestor, nsIWebBrowserChrome, nsIEmbeddingSiteWindow, nsIWebProgressListener, nsISupportsWeakReference) // Implementation of nsIInterfaceRequestor NS_IMETHODIMP nsCocoaBrowserListener::GetInterface(const nsIID &aIID, void** aInstancePtr) { if (aIID.Equals(NS_GET_IID(nsIDOMWindow))) { nsCOMPtr browser = dont_AddRef([mView getWebBrowser]); if (browser) return browser->GetContentDOMWindow((nsIDOMWindow **) aInstancePtr); } return QueryInterface(aIID, aInstancePtr); } // Implementation of nsIWebBrowserChrome /* void setStatus (in unsigned long statusType, in wstring status); */ NS_IMETHODIMP nsCocoaBrowserListener::SetStatus(PRUint32 statusType, const PRUnichar *status) { if (!mContainer) { return NS_ERROR_FAILURE; } NSString* str = nsnull; if (status && (*status != PRUnichar(0))) { str = [NSString stringWithCharacters:status length:nsCRT::strlen(status)]; } [mContainer setStatus:str ofType:(NSStatusType)statusType]; return NS_OK; } /* attribute nsIWebBrowser webBrowser; */ NS_IMETHODIMP nsCocoaBrowserListener::GetWebBrowser(nsIWebBrowser * *aWebBrowser) { NS_ENSURE_ARG_POINTER(aWebBrowser); if (!mView) { return NS_ERROR_FAILURE; } *aWebBrowser = [mView getWebBrowser]; return NS_OK; } NS_IMETHODIMP nsCocoaBrowserListener::SetWebBrowser(nsIWebBrowser * aWebBrowser) { if (!mView) { return NS_ERROR_FAILURE; } [mView setWebBrowser:aWebBrowser]; return NS_OK; } /* attribute unsigned long chromeFlags; */ NS_IMETHODIMP nsCocoaBrowserListener::GetChromeFlags(PRUint32 *aChromeFlags) { NS_ENSURE_ARG_POINTER(aChromeFlags); *aChromeFlags = mChromeFlags; return NS_OK; } NS_IMETHODIMP nsCocoaBrowserListener::SetChromeFlags(PRUint32 aChromeFlags) { // XXX Do nothing with them for now mChromeFlags = aChromeFlags; return NS_OK; } /* void destroyBrowserWindow (); */ NS_IMETHODIMP nsCocoaBrowserListener::DestroyBrowserWindow() { // XXX Could send this up to the container, but for now, // we just destroy the enclosing window. NSWindow* window = [mView window]; if (window) { [window close]; } return NS_OK; } /* void sizeBrowserTo (in long aCX, in long aCY); */ NS_IMETHODIMP nsCocoaBrowserListener::SizeBrowserTo(PRInt32 aCX, PRInt32 aCY) { if (mContainer) { NSSize size; size.width = (float)aCX; size.height = (float)aCY; [mContainer sizeBrowserTo:size]; } return NS_OK; } /* void showAsModal (); */ NS_IMETHODIMP nsCocoaBrowserListener::ShowAsModal() { if (!mView) { return NS_ERROR_FAILURE; } NSWindow* window = [mView window]; if (!window) { return NS_ERROR_FAILURE; } mIsModal = PR_TRUE; int result = [NSApp runModalForWindow:window]; mIsModal = PR_FALSE; return (nsresult)result; } /* boolean isWindowModal (); */ NS_IMETHODIMP nsCocoaBrowserListener::IsWindowModal(PRBool *_retval) { NS_ENSURE_ARG_POINTER(_retval); *_retval = mIsModal; return NS_OK; } /* void exitModalEventLoop (in nsresult aStatus); */ NS_IMETHODIMP nsCocoaBrowserListener::ExitModalEventLoop(nsresult aStatus) { [NSApp stopModalWithCode:(int)aStatus]; return NS_OK; } // Implementation of nsIEmbeddingSiteWindow /* void setDimensions (in unsigned long flags, in long x, in long y, in long cx, in long cy); */ NS_IMETHODIMP nsCocoaBrowserListener::SetDimensions(PRUint32 flags, PRInt32 x, PRInt32 y, PRInt32 cx, PRInt32 cy) { if (!mView) { return NS_ERROR_FAILURE; } NSWindow* window = [mView window]; if (!window) { return NS_ERROR_FAILURE; } if (flags & nsIEmbeddingSiteWindow::DIM_FLAGS_POSITION) { NSPoint origin; origin.x = (float)x; origin.y = (float)y; [window setFrameOrigin:origin]; } if (flags & nsIEmbeddingSiteWindow::DIM_FLAGS_SIZE_OUTER) { NSRect frame = [window frame]; frame.size.width = (float)cx; frame.size.height = (float)cy; [window setFrame:frame display:YES]; } else if (flags & nsIEmbeddingSiteWindow::DIM_FLAGS_SIZE_INNER) { NSSize size; size.width = (float)cx; size.height = (float)cy; [window setContentSize:size]; } return NS_OK; } /* void getDimensions (in unsigned long flags, out long x, out long y, out long cx, out long cy); */ NS_IMETHODIMP nsCocoaBrowserListener::GetDimensions(PRUint32 flags, PRInt32 *x, PRInt32 *y, PRInt32 *cx, PRInt32 *cy) { NS_ENSURE_ARG_POINTER(x); NS_ENSURE_ARG_POINTER(y); NS_ENSURE_ARG_POINTER(cx); NS_ENSURE_ARG_POINTER(cy); if (!mView) { return NS_ERROR_FAILURE; } NSWindow* window = [mView window]; if (!window) { return NS_ERROR_FAILURE; } NSRect frame = [window frame]; if (flags & nsIEmbeddingSiteWindow::DIM_FLAGS_POSITION) { *x = (PRInt32)frame.origin.x; *y = (PRInt32)frame.origin.y; } if (flags & nsIEmbeddingSiteWindow::DIM_FLAGS_SIZE_OUTER) { *cx = (PRInt32)frame.size.width; *cy = (PRInt32)frame.size.height; } else if (flags & nsIEmbeddingSiteWindow::DIM_FLAGS_SIZE_INNER) { NSView* contentView = [window contentView]; NSRect contentFrame = [contentView frame]; *cx = (PRInt32)contentFrame.size.width; *cy = (PRInt32)contentFrame.size.height; } return NS_OK; } /* void setFocus (); */ NS_IMETHODIMP nsCocoaBrowserListener::SetFocus() { if (!mView) { return NS_ERROR_FAILURE; } NSWindow* window = [mView window]; if (!window) { return NS_ERROR_FAILURE; } [window makeKeyAndOrderFront:window]; return NS_OK; } /* attribute boolean visibility; */ NS_IMETHODIMP nsCocoaBrowserListener::GetVisibility(PRBool *aVisibility) { NS_ENSURE_ARG_POINTER(aVisibility); if (!mView) { return NS_ERROR_FAILURE; } NSWindow* window = [mView window]; if (!window) { return NS_ERROR_FAILURE; } *aVisibility = [window isMiniaturized]; return NS_OK; } NS_IMETHODIMP nsCocoaBrowserListener::SetVisibility(PRBool aVisibility) { if (!mView) { return NS_ERROR_FAILURE; } NSWindow* window = [mView window]; if (!window) { return NS_ERROR_FAILURE; } if (aVisibility) { [window deminiaturize:window]; } else { [window miniaturize:window]; } return NS_OK; } /* attribute wstring title; */ NS_IMETHODIMP nsCocoaBrowserListener::GetTitle(PRUnichar * *aTitle) { NS_ENSURE_ARG_POINTER(aTitle); if (!mContainer) { return NS_ERROR_FAILURE; } NSString* title = [mContainer title]; unsigned int length = [title length]; if (length) { *aTitle = (PRUnichar*)nsMemory::Alloc((length+1)*sizeof(PRUnichar)); if (!*aTitle) { return NS_ERROR_OUT_OF_MEMORY; } [title getCharacters:*aTitle]; } else { *aTitle = nsnull; } return NS_OK; } NS_IMETHODIMP nsCocoaBrowserListener::SetTitle(const PRUnichar * aTitle) { NS_ENSURE_ARG(aTitle); if (!mContainer) { return NS_ERROR_FAILURE; } NSString* str = [NSString stringWithCharacters:aTitle length:nsCRT::strlen(aTitle)]; [mContainer setTitle:str]; return NS_OK; } /* [noscript] readonly attribute voidPtr siteWindow; */ NS_IMETHODIMP nsCocoaBrowserListener::GetSiteWindow(void * *aSiteWindow) { NS_ENSURE_ARG_POINTER(aSiteWindow); if (!mView) { return NS_ERROR_FAILURE; } NSWindow* window = [mView window]; if (!window) { return NS_ERROR_FAILURE; } *aSiteWindow = (void*)window; return NS_OK; } // Implementation of nsIWebProgressListener /* void onStateChange (in nsIWebProgress aWebProgress, in nsIRequest aRequest, in long aStateFlags, in unsigned long aStatus); */ NS_IMETHODIMP nsCocoaBrowserListener::OnStateChange(nsIWebProgress *aWebProgress, nsIRequest *aRequest, PRInt32 aStateFlags, PRUint32 aStatus) { NSEnumerator* enumerator = [mListeners objectEnumerator]; id obj; if (aStateFlags & nsIWebProgressListener::STATE_IS_NETWORK) { if (aStateFlags & nsIWebProgressListener::STATE_START) { while ((obj = [enumerator nextObject])) { [obj onLoadingStarted]; } } else if (aStateFlags & nsIWebProgressListener::STATE_STOP) { while ((obj = [enumerator nextObject])) { [obj onLoadingCompleted:(NS_SUCCEEDED(aStatus))]; } } } return NS_OK; } /* void onProgressChange (in nsIWebProgress aWebProgress, in nsIRequest aRequest, in long aCurSelfProgress, in long aMaxSelfProgress, in long aCurTotalProgress, in long aMaxTotalProgress); */ NS_IMETHODIMP nsCocoaBrowserListener::OnProgressChange(nsIWebProgress *aWebProgress, nsIRequest *aRequest, PRInt32 aCurSelfProgress, PRInt32 aMaxSelfProgress, PRInt32 aCurTotalProgress, PRInt32 aMaxTotalProgress) { NSEnumerator* enumerator = [mListeners objectEnumerator]; id obj; while ((obj = [enumerator nextObject])) { [obj onProgressChange:aCurTotalProgress outOf:aMaxTotalProgress]; } return NS_OK; } /* void onLocationChange (in nsIWebProgress aWebProgress, in nsIRequest aRequest, in nsIURI location); */ NS_IMETHODIMP nsCocoaBrowserListener::OnLocationChange(nsIWebProgress *aWebProgress, nsIRequest *aRequest, nsIURI *location) { nsXPIDLCString spec; location->GetSpec(getter_Copies(spec)); if (!spec) { return NS_ERROR_FAILURE; } const char* cstr = spec.get(); NSString* str = [NSString stringWithCString:cstr]; NSURL* url = [NSURL URLWithString:str]; NSEnumerator* enumerator = [mListeners objectEnumerator]; id obj; while ((obj = [enumerator nextObject])) { [obj onLocationChange:url]; } return NS_OK; } /* void onStatusChange (in nsIWebProgress aWebProgress, in nsIRequest aRequest, in nsresult aStatus, in wstring aMessage); */ NS_IMETHODIMP nsCocoaBrowserListener::OnStatusChange(nsIWebProgress *aWebProgress, nsIRequest *aRequest, nsresult aStatus, const PRUnichar *aMessage) { return NS_OK; } /* void onSecurityChange (in nsIWebProgress aWebProgress, in nsIRequest aRequest, in long state); */ NS_IMETHODIMP nsCocoaBrowserListener::OnSecurityChange(nsIWebProgress *aWebProgress, nsIRequest *aRequest, PRInt32 state) { return NS_OK; } void nsCocoaBrowserListener::AddListener(id aListener) { [mListeners addObject:aListener]; } void nsCocoaBrowserListener::RemoveListener(id aListener) { [mListeners removeObject:aListener]; } void nsCocoaBrowserListener::SetContainer(id aContainer) { [mContainer autorelease]; mContainer = aContainer; [mContainer retain]; } // Implementation of a header sniffer class that is used when saving Web pages and images. class nsHeaderSniffer : public nsIWebProgressListener { public: nsHeaderSniffer(nsIWebBrowserPersist* aPersist, nsIFile* aFile, nsIURI* aURL, nsIDOMDocument* aDocument, nsIInputStream* aPostData, PRBool aBypassCache, NSView* aFilterView, NSPopUpButton* aFilterList) { NS_INIT_REFCNT(); mPersist = aPersist; mTmpFile = aFile; mURL = aURL; mDocument = aDocument; mPostData = aPostData; mBypassCache = aBypassCache; mFilterView = aFilterView; mFilterList = aFilterList; } virtual ~nsHeaderSniffer() { }; NS_DECL_ISUPPORTS NS_DECL_NSIWEBPROGRESSLISTENER protected: void PerformSave(); private: nsIWebBrowserPersist* mPersist; // Weak. It owns us as a listener. nsCOMPtr mTmpFile; nsCOMPtr mURL; nsCOMPtr mDocument; nsCOMPtr mPostData; PRBool mBypassCache; nsCString mContentType; nsCString mContentDisposition; NSView* mFilterView; NSPopUpButton* mFilterList; }; NS_IMPL_ISUPPORTS1(nsHeaderSniffer, nsIWebProgressListener) // Implementation of nsIWebProgressListener /* void onStateChange (in nsIWebProgress aWebProgress, in nsIRequest aRequest, in long aStateFlags, in unsigned long aStatus); */ NS_IMETHODIMP nsHeaderSniffer::OnStateChange(nsIWebProgress *aWebProgress, nsIRequest *aRequest, PRInt32 aStateFlags, PRUint32 aStatus) { if (aStateFlags & nsIWebProgressListener::STATE_START) { nsCOMPtr channel(do_QueryInterface(aRequest)); nsXPIDLCString contentType; channel->GetContentType(getter_Copies(contentType)); mContentType = contentType; // Get the content-disposition if we're an HTTP channel. nsCOMPtr httpChannel(do_QueryInterface(channel)); if (httpChannel) { nsXPIDLCString disp; httpChannel->GetResponseHeader("content-disposition", getter_Copies(disp)); mContentDisposition = disp; } mPersist->CancelSave(); PRBool exists; mTmpFile->Exists(&exists); if (exists) mTmpFile->Remove(PR_FALSE); PerformSave(); } return NS_OK; } void nsHeaderSniffer::PerformSave() { // Are we an HTML document? If so, we will want to append an accessory view to // the save dialog to provide the user with the option of doing a complete // save vs. a single file save. PRBool isHTML = (mDocument && mContentType.Equals("text/html") || mContentType.Equals("text/xml") || mContentType.Equals("application/xhtml+xml")); // Next find out the directory that we should start in. nsCOMPtr prefs(do_GetService("@mozilla.org/preferences-service;1")); if (!prefs) return; nsCOMPtr dirBranch; prefs->GetBranch("browser.download.", getter_AddRefs(dirBranch)); PRInt32 filterIndex = 0; if (dirBranch) { nsresult rv = dirBranch->GetIntPref("save_converter_index", &filterIndex); if (NS_FAILED(rv)) filterIndex = 0; } if (mFilterList) [mFilterList selectItemAtIndex: filterIndex]; // We need to figure out what file name to use. nsCAutoString defaultFileName; if (!mContentDisposition.IsEmpty()) { // (1) Use the HTTP header suggestion. PRInt32 index = mContentDisposition.Find("filename="); if (index >= 0) { // Take the substring following the prefix. index += 9; nsCAutoString filename; mContentDisposition.Right(filename, mContentDisposition.Length() - index); defaultFileName = filename; } } if (defaultFileName.IsEmpty()) { nsCOMPtr url(do_QueryInterface(mURL)); if (url) { nsXPIDLCString fileName; url->GetFileName(getter_Copies(fileName)); defaultFileName = fileName; // (2) For file URLs, use the file name. } } if (defaultFileName.IsEmpty() && mDocument && isHTML) { nsCOMPtr htmlDoc(do_QueryInterface(mDocument)); nsAutoString title; if (htmlDoc) htmlDoc->GetTitle(title); // (3) Use the title of the document. defaultFileName.AssignWithConversion(title); } if (defaultFileName.IsEmpty()) { // (4) Use the caller provided name. XXXdwh } if (defaultFileName.IsEmpty()) { // (5) Use the host. nsXPIDLCString host; mURL->GetHost(getter_Copies(host)); defaultFileName = host; } // One last case to handle about:blank and other fruity untitled pages. if (defaultFileName.IsEmpty()) defaultFileName = "untitled"; // Validate the file name to ensure legality. for (PRUint32 i = 0; i < defaultFileName.Length(); i++) if (defaultFileName[i] == ':' || defaultFileName[i] == '/') defaultFileName.SetCharAt(i, ' '); // Make sure the appropriate extension is appended to the suggested file name. nsCOMPtr fileURI(do_CreateInstance("@mozilla.org/network/standard-url;1")); nsCOMPtr fileURL(do_QueryInterface(fileURI)); if (!fileURL) return; fileURL->SetFilePath(defaultFileName.get()); nsXPIDLCString fileEx; fileURL->GetFileExtension(getter_Copies(fileEx)); nsDependentCString fileExtension(fileEx.get()); PRBool setExtension = PR_FALSE; if (mContentType.Equals("text/html")) { if (fileExtension.IsEmpty() || (!fileExtension.Equals("htm") && !fileExtension.Equals("html"))) { defaultFileName += ".html"; setExtension = PR_TRUE; } } if (!setExtension && fileExtension.IsEmpty()) { nsCOMPtr mimeService(do_GetService("@mozilla.org/mime;1")); if (!mimeService) return; nsCOMPtr mimeInfo; mimeService->GetFromMIMEType(mContentType.get(), getter_AddRefs(mimeInfo)); PRUint32 extCount; char** extList; mimeInfo->GetFileExtensions(&extCount, &extList); if (extCount > 0) { defaultFileName += "."; defaultFileName += extList[0]; } } // Now it's time to pose the save dialog. NSSavePanel* savePanel = [NSSavePanel savePanel]; NSString* file = nil; if (!defaultFileName.IsEmpty()) file = [[NSString alloc] initWithCString: defaultFileName.get()]; if (isHTML) [savePanel setAccessoryView: mFilterView]; if ([savePanel runModalForDirectory: nil file: file] == NSFileHandlingPanelCancelButton) return; // Release the file string. [file release]; // Update the filter index. if (isHTML && mFilterList) { filterIndex = [mFilterList indexOfSelectedItem]; dirBranch->SetIntPref("save_converter_index", filterIndex); } // Convert the content type to text/plain if it was selected in the filter. if (isHTML && filterIndex == 2) mContentType = "text/plain"; nsCOMPtr sourceData; if (isHTML && filterIndex != 1) sourceData = do_QueryInterface(mDocument); else sourceData = do_QueryInterface(mURL); nsCOMPtr webPersist(do_CreateInstance(persistContractID)); ProgressDlgController* progressDialog = [[ProgressDlgController alloc] initWithWindowNibName: @"ProgressDialog"]; [progressDialog setWebPersist: webPersist source: sourceData.get() destination: [savePanel filename] contentType: mContentType.get() postData: mPostData bypassCache: mBypassCache]; [progressDialog showWindow: progressDialog]; } /* void onProgressChange (in nsIWebProgress aWebProgress, in nsIRequest aRequest, in long aCurSelfProgress, in long aMaxSelfProgress, in long aCurTotalProgress, in long aMaxTotalProgress); */ NS_IMETHODIMP nsHeaderSniffer::OnProgressChange(nsIWebProgress *aWebProgress, nsIRequest *aRequest, PRInt32 aCurSelfProgress, PRInt32 aMaxSelfProgress, PRInt32 aCurTotalProgress, PRInt32 aMaxTotalProgress) { return NS_OK; } /* void onLocationChange (in nsIWebProgress aWebProgress, in nsIRequest aRequest, in nsIURI location); */ NS_IMETHODIMP nsHeaderSniffer::OnLocationChange(nsIWebProgress *aWebProgress, nsIRequest *aRequest, nsIURI *location) { return NS_OK; } /* void onStatusChange (in nsIWebProgress aWebProgress, in nsIRequest aRequest, in nsresult aStatus, in wstring aMessage); */ NS_IMETHODIMP nsHeaderSniffer::OnStatusChange(nsIWebProgress *aWebProgress, nsIRequest *aRequest, nsresult aStatus, const PRUnichar *aMessage) { return NS_OK; } /* void onSecurityChange (in nsIWebProgress aWebProgress, in nsIRequest aRequest, in long state); */ NS_IMETHODIMP nsHeaderSniffer::OnSecurityChange(nsIWebProgress *aWebProgress, nsIRequest *aRequest, PRInt32 state) { return NS_OK; } @implementation NSBrowserView - (id)initWithFrame:(NSRect)frame { [super initWithFrame:frame]; nsresult rv = nsCocoaBrowserService::InitEmbedding(); if (NS_FAILED(rv)) { // XXX need to throw } _listener = new nsCocoaBrowserListener(self); NS_ADDREF(_listener); // Create the web browser instance nsCOMPtr browser = do_CreateInstance(NS_WEBBROWSER_CONTRACTID, &rv); if (NS_FAILED(rv)) { // XXX need to throw } _webBrowser = browser; NS_ADDREF(_webBrowser); // Set the container nsIWebBrowserChrome _webBrowser->SetContainerWindow(NS_STATIC_CAST(nsIWebBrowserChrome *, _listener)); // Register as a listener for web progress nsCOMPtr weak = do_GetWeakReference(NS_STATIC_CAST(nsIWebProgressListener*, _listener)); _webBrowser->AddWebBrowserListener(weak, NS_GET_IID(nsIWebProgressListener)); // Hook up the widget hierarchy with us as the parent nsCOMPtr baseWin = do_QueryInterface(_webBrowser); baseWin->InitWindow((NSView*)self, nsnull, 0, 0, frame.size.width, frame.size.height); baseWin->Create(); return self; } - (void)dealloc { NSLog(@"NSBrowserView got dealloced."); NS_RELEASE(_listener); NS_IF_RELEASE(_webBrowser); nsCocoaBrowserService::TermEmbedding(); [super dealloc]; } - (void)setFrame:(NSRect)frameRect { [super setFrame:frameRect]; if (_webBrowser) { nsCOMPtr window = do_QueryInterface(_webBrowser); window->SetSize((PRInt32)frameRect.size.width, (PRInt32)frameRect.size.height, PR_TRUE); } } - (void)addListener:(id )listener { _listener->AddListener(listener); } - (void)removeListener:(id )listener { _listener->RemoveListener(listener); } - (void)setContainer:(id )container { _listener->SetContainer(container); } - (nsIDOMWindow*)getContentWindow { nsIDOMWindow* window; _webBrowser->GetContentDOMWindow(&window); return window; } - (void)loadURI:(NSURL *)url flags:(unsigned int)flags { nsCOMPtr nav = do_QueryInterface(_webBrowser); NSString* spec = [url absoluteString]; int length = [spec length]; PRUnichar* specStr = nsMemory::Alloc((length+1) * sizeof(PRUnichar)); [spec getCharacters:specStr]; specStr[length] = PRUnichar(0); PRUint32 navFlags = nsIWebNavigation::LOAD_FLAGS_NONE; if (flags & NSLoadFlagsDontPutInHistory) { navFlags |= nsIWebNavigation::LOAD_FLAGS_BYPASS_HISTORY; } if (flags & NSLoadFlagsReplaceHistoryEntry) { navFlags |= nsIWebNavigation::LOAD_FLAGS_REPLACE_HISTORY; } if (flags & NSLoadFlagsBypassCacheAndProxy) { navFlags |= nsIWebNavigation::LOAD_FLAGS_BYPASS_CACHE | nsIWebNavigation::LOAD_FLAGS_BYPASS_PROXY; } nsresult rv = nav->LoadURI(specStr, navFlags, nsnull, nsnull, nsnull); if (NS_FAILED(rv)) { // XXX need to throw } nsMemory::Free(specStr); } - (void)reload:(unsigned int)flags { nsCOMPtr nav = do_QueryInterface(_webBrowser); PRUint32 navFlags = nsIWebNavigation::LOAD_FLAGS_NONE; if (flags & NSLoadFlagsBypassCacheAndProxy) { navFlags |= nsIWebNavigation::LOAD_FLAGS_BYPASS_CACHE | nsIWebNavigation::LOAD_FLAGS_BYPASS_PROXY; } nsresult rv = nav->Reload(navFlags); if (NS_FAILED(rv)) { // XXX need to throw } } - (BOOL)canGoBack { nsCOMPtr nav = do_QueryInterface(_webBrowser); PRBool can; nav->GetCanGoBack(&can); return can ? YES : NO; } - (BOOL)canGoForward { nsCOMPtr nav = do_QueryInterface(_webBrowser); PRBool can; nav->GetCanGoForward(&can); return can ? YES : NO; } - (void)goBack { nsCOMPtr nav = do_QueryInterface(_webBrowser); nsresult rv = nav->GoBack(); if (NS_FAILED(rv)) { // XXX need to throw } } - (void)goForward { nsCOMPtr nav = do_QueryInterface(_webBrowser); nsresult rv = nav->GoForward(); if (NS_FAILED(rv)) { // XXX need to throw } } - (void)gotoIndex:(int)index { nsCOMPtr nav = do_QueryInterface(_webBrowser); nsresult rv = nav->GotoIndex(index); if (NS_FAILED(rv)) { // XXX need to throw } } - (void)stop:(unsigned int)flags { nsCOMPtr nav = do_QueryInterface(_webBrowser); nsresult rv = nav->Stop(flags); if (NS_FAILED(rv)) { // XXX need to throw } } - (NSURL*)getCurrentURI { nsCOMPtr uri; nsCOMPtr nav = do_QueryInterface(_webBrowser); nav->GetCurrentURI(getter_AddRefs(uri)); if (!uri) { return nsnull; } nsXPIDLCString spec; uri->GetSpec(getter_Copies(spec)); const char* cstr = spec.get(); NSString* str = [NSString stringWithCString:cstr]; NSURL* url = [NSURL URLWithString:str]; return url; } - (nsIWebBrowser*)getWebBrowser { NS_IF_ADDREF(_webBrowser); return _webBrowser; } - (void)setWebBrowser:(nsIWebBrowser*)browser { _webBrowser = browser; if (_webBrowser) { // Set the container nsIWebBrowserChrome _webBrowser->SetContainerWindow(NS_STATIC_CAST(nsIWebBrowserChrome *, _listener)); NSRect frame = [self frame]; // Hook up the widget hierarchy with us as the parent nsCOMPtr baseWin = do_QueryInterface(_webBrowser); baseWin->InitWindow((NSView*)self, nsnull, 0, 0, frame.size.width, frame.size.height); baseWin->Create(); } } -(void) saveInternal: (nsIURI*)aURI withDocument: (nsIDOMDocument*)aDocument bypassCache: (BOOL)aBypassCache filterView: (NSView*)aFilterView filterList: (NSPopUpButton*)aFilterList { // Create our web browser persist object. This is the object that knows // how to actually perform the saving of the page (and of the images // on the page). nsCOMPtr webPersist(do_CreateInstance(persistContractID)); if (!webPersist) return; // Make a temporary file object that we can save to. nsCOMPtr dirService(do_GetService(dirServiceContractID)); if (!dirService) return; nsCOMPtr tmpFile; dirService->Get("TmpD", NS_GET_IID(nsIFile), getter_AddRefs(tmpFile)); static short unsigned int tmpRandom = 0; nsCAutoString tmpNo; tmpNo.AssignWithConversion(tmpRandom++); nsCAutoString saveFile("-sav"); saveFile += tmpNo; saveFile += "tmp"; tmpFile->Append(saveFile.get()); // Get the post data if we're an HTML doc. nsCOMPtr webNav(do_QueryInterface(_webBrowser)); nsCOMPtr sessionHistory; webNav->GetSessionHistory(getter_AddRefs(sessionHistory)); nsCOMPtr entry; PRInt32 sindex; sessionHistory->GetIndex(&sindex); sessionHistory->GetEntryAtIndex(sindex, PR_FALSE, getter_AddRefs(entry)); nsCOMPtr shEntry(do_QueryInterface(entry)); nsCOMPtr postData; if (shEntry) shEntry->GetPostData(getter_AddRefs(postData)); nsHeaderSniffer* sniffer = new nsHeaderSniffer(webPersist, tmpFile, aURI, aDocument, postData, aBypassCache, aFilterView, aFilterList); if (!sniffer) return; webPersist->SetProgressListener(sniffer); webPersist->SaveURI(aURI, nsnull, tmpFile); } -(void)saveDocument: (NSView*)aFilterView filterList: (NSPopUpButton*)aFilterList { nsCOMPtr wbf(do_QueryInterface(_webBrowser)); nsCOMPtr domWindow; wbf->GetFocusedWindow(getter_AddRefs(domWindow)); if (!domWindow) _webBrowser->GetContentDOMWindow(getter_AddRefs(domWindow)); if (!domWindow) return; nsCOMPtr domDocument; domWindow->GetDocument(getter_AddRefs(domDocument)); if (!domDocument) return; nsCOMPtr doc(do_QueryInterface(domDocument)); if (!doc) return; nsCOMPtr url; doc->GetDocumentURL(getter_AddRefs(url)); [self saveInternal: url.get() withDocument: domDocument bypassCache: NO filterView: aFilterView filterList: aFilterList]; } @end