Annotation of chimera/NSBrowserView.mm, revision 1.4
1.1 hyatt 1: /* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
2: /* ***** BEGIN LICENSE BLOCK *****
3: * Version: NPL 1.1/GPL 2.0/LGPL 2.1
4: *
5: * The contents of this file are subject to the Netscape Public License
6: * Version 1.1 (the "License"); you may not use this file except in
7: * compliance with the License. You may obtain a copy of the License at
8: * http://www.mozilla.org/NPL/
9: *
10: * Software distributed under the License is distributed on an "AS IS" basis,
11: * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
12: * for the specific language governing rights and limitations under the
13: * License.
14: *
15: * The Original Code is mozilla.org code.
16: *
17: * The Initial Developer of the Original Code is
18: * Netscape Communications Corporation.
19: * Portions created by the Initial Developer are Copyright (C) 1998
20: * the Initial Developer. All Rights Reserved.
21: *
22: * Contributor(s):
23: *
24: * Alternatively, the contents of this file may be used under the terms of
25: * either the GNU General Public License Version 2 or later (the "GPL"), or
26: * the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
27: * in which case the provisions of the GPL or the LGPL are applicable instead
28: * of those above. If you wish to allow use of your version of this file only
29: * under the terms of either the GPL or the LGPL, and not to allow others to
30: * use your version of this file under the terms of the NPL, indicate your
31: * decision by deleting the provisions above and replace them with the notice
32: * and other provisions required by the GPL or the LGPL. If you do not delete
33: * the provisions above, a recipient may use your version of this file under
34: * the terms of any one of the NPL, the GPL or the LGPL.
35: *
36: * ***** END LICENSE BLOCK ***** */
37:
38: #import "NSBrowserView.h"
1.2 hyatt 39: #import "ProgressDlgController.h"
1.1 hyatt 40: #import "nsCocoaBrowserService.h"
41:
42: // Embedding includes
43: #include "nsCWebBrowser.h"
44: #include "nsIInterfaceRequestor.h"
45: #include "nsIWebBrowserChrome.h"
46: #include "nsIEmbeddingSiteWindow.h"
47: #include "nsIWebProgressListener.h"
48: #include "nsIWebBrowser.h"
49: #include "nsIWebNavigation.h"
50: #include "nsIURI.h"
51: #include "nsIDOMWindow.h"
52: #include "nsWeakReference.h"
53:
54: // XPCOM and String includes
55: #include "nsCRT.h"
56: #include "nsXPIDLString.h"
57: #include "nsCOMPtr.h"
58:
1.2 hyatt 59: #include "nsIWebBrowserFocus.h"
60: #include "nsIDOMHTMLDocument.h"
61: #include "nsIDocument.h"
62: #include "nsIURL.h"
63: #include "nsIWebBrowserPersist.h"
64: #include "nsIProperties.h"
65: #include "nsIRequest.h"
66: #include "nsIChannel.h"
67: #include "nsIHttpChannel.h"
68: #include "nsIPref.h"
69: #include "nsIMIMEService.h"
70: #include "nsIMIMEInfo.h"
71: #include "nsISHistory.h"
1.3 hyatt 72: #include "nsIHistoryEntry.h"
73: #include "nsISHEntry.h"
1.1 hyatt 74:
1.4 ! hyatt 75: const char* persistContractID = "@mozilla.org/embedding/browser/nsWebBrowserPersist;1";
! 76: const char* dirServiceContractID = "@mozilla.org/file/directory_service;1";
! 77:
1.1 hyatt 78: class nsCocoaBrowserListener : public nsSupportsWeakReference,
79: public nsIInterfaceRequestor,
80: public nsIWebBrowserChrome,
81: public nsIEmbeddingSiteWindow,
82: public nsIWebProgressListener
83: {
84: public:
85: nsCocoaBrowserListener(NSBrowserView* aView);
86: virtual ~nsCocoaBrowserListener();
87:
88: NS_DECL_ISUPPORTS
89: NS_DECL_NSIINTERFACEREQUESTOR
90: NS_DECL_NSIWEBBROWSERCHROME
91: NS_DECL_NSIEMBEDDINGSITEWINDOW
92: NS_DECL_NSIWEBPROGRESSLISTENER
93:
94: void AddListener(id <NSBrowserListener> aListener);
95: void RemoveListener(id <NSBrowserListener> aListener);
96: void SetContainer(id <NSBrowserContainer> aContainer);
97:
98: private:
99: NSBrowserView* mView; // WEAK - it owns us
100: NSMutableArray* mListeners;
101: id <NSBrowserContainer> mContainer;
102: PRBool mIsModal;
103: PRUint32 mChromeFlags;
104: };
105:
106: nsCocoaBrowserListener::nsCocoaBrowserListener(NSBrowserView* aView)
107: : mView(aView), mContainer(nsnull), mIsModal(PR_FALSE), mChromeFlags(0)
108: {
109: NS_INIT_ISUPPORTS();
110: mListeners = [[NSMutableArray alloc] init];
111: }
112:
113: nsCocoaBrowserListener::~nsCocoaBrowserListener()
114: {
115: [mListeners release];
116: mView = nsnull;
117: if (mContainer) {
118: [mContainer release];
119: }
120: }
121:
122: NS_IMPL_ISUPPORTS5(nsCocoaBrowserListener,
123: nsIInterfaceRequestor,
124: nsIWebBrowserChrome,
125: nsIEmbeddingSiteWindow,
126: nsIWebProgressListener,
127: nsISupportsWeakReference)
128:
129: // Implementation of nsIInterfaceRequestor
130: NS_IMETHODIMP
131: nsCocoaBrowserListener::GetInterface(const nsIID &aIID, void** aInstancePtr)
132: {
133: if (aIID.Equals(NS_GET_IID(nsIDOMWindow))) {
134: nsCOMPtr<nsIWebBrowser> browser = dont_AddRef([mView getWebBrowser]);
135: if (browser)
136: return browser->GetContentDOMWindow((nsIDOMWindow **) aInstancePtr);
137: }
138:
139: return QueryInterface(aIID, aInstancePtr);
140: }
141:
142: // Implementation of nsIWebBrowserChrome
143: /* void setStatus (in unsigned long statusType, in wstring status); */
144: NS_IMETHODIMP
145: nsCocoaBrowserListener::SetStatus(PRUint32 statusType, const PRUnichar *status)
146: {
147: if (!mContainer) {
148: return NS_ERROR_FAILURE;
149: }
150:
151: NSString* str = nsnull;
152: if (status && (*status != PRUnichar(0))) {
153: str = [NSString stringWithCharacters:status length:nsCRT::strlen(status)];
154: }
155:
156: [mContainer setStatus:str ofType:(NSStatusType)statusType];
157:
158: return NS_OK;
159: }
160:
161: /* attribute nsIWebBrowser webBrowser; */
162: NS_IMETHODIMP
163: nsCocoaBrowserListener::GetWebBrowser(nsIWebBrowser * *aWebBrowser)
164: {
165: NS_ENSURE_ARG_POINTER(aWebBrowser);
166: if (!mView) {
167: return NS_ERROR_FAILURE;
168: }
169: *aWebBrowser = [mView getWebBrowser];
170:
171: return NS_OK;
172: }
173: NS_IMETHODIMP
174: nsCocoaBrowserListener::SetWebBrowser(nsIWebBrowser * aWebBrowser)
175: {
176: if (!mView) {
177: return NS_ERROR_FAILURE;
178: }
179:
180: [mView setWebBrowser:aWebBrowser];
181:
182: return NS_OK;
183: }
184:
185: /* attribute unsigned long chromeFlags; */
186: NS_IMETHODIMP
187: nsCocoaBrowserListener::GetChromeFlags(PRUint32 *aChromeFlags)
188: {
189: NS_ENSURE_ARG_POINTER(aChromeFlags);
190: *aChromeFlags = mChromeFlags;
191: return NS_OK;
192: }
193: NS_IMETHODIMP
194: nsCocoaBrowserListener::SetChromeFlags(PRUint32 aChromeFlags)
195: {
196: // XXX Do nothing with them for now
197: mChromeFlags = aChromeFlags;
198: return NS_OK;
199: }
200:
201: /* void destroyBrowserWindow (); */
202: NS_IMETHODIMP
203: nsCocoaBrowserListener::DestroyBrowserWindow()
204: {
205: // XXX Could send this up to the container, but for now,
206: // we just destroy the enclosing window.
207: NSWindow* window = [mView window];
208:
209: if (window) {
210: [window close];
211: }
212:
213: return NS_OK;
214: }
215:
216: /* void sizeBrowserTo (in long aCX, in long aCY); */
217: NS_IMETHODIMP
218: nsCocoaBrowserListener::SizeBrowserTo(PRInt32 aCX, PRInt32 aCY)
219: {
220: if (mContainer) {
221: NSSize size;
222:
223: size.width = (float)aCX;
224: size.height = (float)aCY;
225:
226: [mContainer sizeBrowserTo:size];
227: }
228:
229: return NS_OK;
230: }
231:
232: /* void showAsModal (); */
233: NS_IMETHODIMP
234: nsCocoaBrowserListener::ShowAsModal()
235: {
236: if (!mView) {
237: return NS_ERROR_FAILURE;
238: }
239:
240: NSWindow* window = [mView window];
241:
242: if (!window) {
243: return NS_ERROR_FAILURE;
244: }
245:
246: mIsModal = PR_TRUE;
247: int result = [NSApp runModalForWindow:window];
248: mIsModal = PR_FALSE;
249:
250: return (nsresult)result;
251: }
252:
253: /* boolean isWindowModal (); */
254: NS_IMETHODIMP
255: nsCocoaBrowserListener::IsWindowModal(PRBool *_retval)
256: {
257: NS_ENSURE_ARG_POINTER(_retval);
258:
259: *_retval = mIsModal;
260:
261: return NS_OK;
262: }
263:
264: /* void exitModalEventLoop (in nsresult aStatus); */
265: NS_IMETHODIMP
266: nsCocoaBrowserListener::ExitModalEventLoop(nsresult aStatus)
267: {
268: [NSApp stopModalWithCode:(int)aStatus];
269:
270: return NS_OK;
271: }
272:
273: // Implementation of nsIEmbeddingSiteWindow
274: /* void setDimensions (in unsigned long flags, in long x, in long y, in long cx, in long cy); */
275: NS_IMETHODIMP
276: nsCocoaBrowserListener::SetDimensions(PRUint32 flags,
277: PRInt32 x,
278: PRInt32 y,
279: PRInt32 cx,
280: PRInt32 cy)
281: {
282: if (!mView) {
283: return NS_ERROR_FAILURE;
284: }
285:
286: NSWindow* window = [mView window];
287: if (!window) {
288: return NS_ERROR_FAILURE;
289: }
290:
291: if (flags & nsIEmbeddingSiteWindow::DIM_FLAGS_POSITION) {
292: NSPoint origin;
293: origin.x = (float)x;
294: origin.y = (float)y;
295: [window setFrameOrigin:origin];
296: }
297:
298: if (flags & nsIEmbeddingSiteWindow::DIM_FLAGS_SIZE_OUTER) {
299: NSRect frame = [window frame];
300: frame.size.width = (float)cx;
301: frame.size.height = (float)cy;
302: [window setFrame:frame display:YES];
303: }
304: else if (flags & nsIEmbeddingSiteWindow::DIM_FLAGS_SIZE_INNER) {
305: NSSize size;
306: size.width = (float)cx;
307: size.height = (float)cy;
308: [window setContentSize:size];
309: }
310:
311: return NS_OK;
312: }
313:
314: /* void getDimensions (in unsigned long flags, out long x, out long y, out long cx, out long cy); */
315: NS_IMETHODIMP
316: nsCocoaBrowserListener::GetDimensions(PRUint32 flags,
317: PRInt32 *x,
318: PRInt32 *y,
319: PRInt32 *cx,
320: PRInt32 *cy)
321: {
322: NS_ENSURE_ARG_POINTER(x);
323: NS_ENSURE_ARG_POINTER(y);
324: NS_ENSURE_ARG_POINTER(cx);
325: NS_ENSURE_ARG_POINTER(cy);
326:
327: if (!mView) {
328: return NS_ERROR_FAILURE;
329: }
330:
331: NSWindow* window = [mView window];
332: if (!window) {
333: return NS_ERROR_FAILURE;
334: }
335:
336: NSRect frame = [window frame];
337: if (flags & nsIEmbeddingSiteWindow::DIM_FLAGS_POSITION) {
338: *x = (PRInt32)frame.origin.x;
339: *y = (PRInt32)frame.origin.y;
340: }
341: if (flags & nsIEmbeddingSiteWindow::DIM_FLAGS_SIZE_OUTER) {
342: *cx = (PRInt32)frame.size.width;
343: *cy = (PRInt32)frame.size.height;
344: }
345: else if (flags & nsIEmbeddingSiteWindow::DIM_FLAGS_SIZE_INNER) {
346: NSView* contentView = [window contentView];
347: NSRect contentFrame = [contentView frame];
348: *cx = (PRInt32)contentFrame.size.width;
349: *cy = (PRInt32)contentFrame.size.height;
350: }
351:
352: return NS_OK;
353: }
354:
355: /* void setFocus (); */
356: NS_IMETHODIMP
357: nsCocoaBrowserListener::SetFocus()
358: {
359: if (!mView) {
360: return NS_ERROR_FAILURE;
361: }
362:
363: NSWindow* window = [mView window];
364: if (!window) {
365: return NS_ERROR_FAILURE;
366: }
367:
368: [window makeKeyAndOrderFront:window];
369:
370: return NS_OK;
371: }
372:
373: /* attribute boolean visibility; */
374: NS_IMETHODIMP
375: nsCocoaBrowserListener::GetVisibility(PRBool *aVisibility)
376: {
377: NS_ENSURE_ARG_POINTER(aVisibility);
378:
379: if (!mView) {
380: return NS_ERROR_FAILURE;
381: }
382:
383: NSWindow* window = [mView window];
384: if (!window) {
385: return NS_ERROR_FAILURE;
386: }
387:
388: *aVisibility = [window isMiniaturized];
389:
390: return NS_OK;
391: }
392: NS_IMETHODIMP
393: nsCocoaBrowserListener::SetVisibility(PRBool aVisibility)
394: {
395: if (!mView) {
396: return NS_ERROR_FAILURE;
397: }
398:
399: NSWindow* window = [mView window];
400: if (!window) {
401: return NS_ERROR_FAILURE;
402: }
403:
404: if (aVisibility) {
405: [window deminiaturize:window];
406: }
407: else {
408: [window miniaturize:window];
409: }
410:
411: return NS_OK;
412: }
413:
414: /* attribute wstring title; */
415: NS_IMETHODIMP
416: nsCocoaBrowserListener::GetTitle(PRUnichar * *aTitle)
417: {
418: NS_ENSURE_ARG_POINTER(aTitle);
419:
420: if (!mContainer) {
421: return NS_ERROR_FAILURE;
422: }
423:
424: NSString* title = [mContainer title];
425: unsigned int length = [title length];
426: if (length) {
427: *aTitle = (PRUnichar*)nsMemory::Alloc((length+1)*sizeof(PRUnichar));
428: if (!*aTitle) {
429: return NS_ERROR_OUT_OF_MEMORY;
430: }
431: [title getCharacters:*aTitle];
432: }
433: else {
434: *aTitle = nsnull;
435: }
436:
437: return NS_OK;
438: }
439: NS_IMETHODIMP
440: nsCocoaBrowserListener::SetTitle(const PRUnichar * aTitle)
441: {
442: NS_ENSURE_ARG(aTitle);
443:
444: if (!mContainer) {
445: return NS_ERROR_FAILURE;
446: }
447:
448: NSString* str = [NSString stringWithCharacters:aTitle length:nsCRT::strlen(aTitle)];
449: [mContainer setTitle:str];
450:
451: return NS_OK;
452: }
453:
454: /* [noscript] readonly attribute voidPtr siteWindow; */
455: NS_IMETHODIMP
456: nsCocoaBrowserListener::GetSiteWindow(void * *aSiteWindow)
457: {
458: NS_ENSURE_ARG_POINTER(aSiteWindow);
459:
460: if (!mView) {
461: return NS_ERROR_FAILURE;
462: }
463:
464: NSWindow* window = [mView window];
465: if (!window) {
466: return NS_ERROR_FAILURE;
467: }
468:
469: *aSiteWindow = (void*)window;
470:
471: return NS_OK;
472: }
473:
474: // Implementation of nsIWebProgressListener
475: /* void onStateChange (in nsIWebProgress aWebProgress, in nsIRequest aRequest, in long aStateFlags, in unsigned long aStatus); */
476: NS_IMETHODIMP
477: nsCocoaBrowserListener::OnStateChange(nsIWebProgress *aWebProgress,
478: nsIRequest *aRequest,
479: PRInt32 aStateFlags,
480: PRUint32 aStatus)
481: {
482: NSEnumerator* enumerator = [mListeners objectEnumerator];
483: id obj;
484:
485: if (aStateFlags & nsIWebProgressListener::STATE_IS_NETWORK) {
486: if (aStateFlags & nsIWebProgressListener::STATE_START) {
487: while ((obj = [enumerator nextObject])) {
488: [obj onLoadingStarted];
489: }
490: }
491: else if (aStateFlags & nsIWebProgressListener::STATE_STOP) {
492: while ((obj = [enumerator nextObject])) {
493: [obj onLoadingCompleted:(NS_SUCCEEDED(aStatus))];
494: }
495: }
496: }
497:
498:
499: return NS_OK;
500: }
501:
502: /* void onProgressChange (in nsIWebProgress aWebProgress, in nsIRequest aRequest, in long aCurSelfProgress, in long aMaxSelfProgress, in long aCurTotalProgress, in long aMaxTotalProgress); */
503: NS_IMETHODIMP
504: nsCocoaBrowserListener::OnProgressChange(nsIWebProgress *aWebProgress,
505: nsIRequest *aRequest,
506: PRInt32 aCurSelfProgress,
507: PRInt32 aMaxSelfProgress,
508: PRInt32 aCurTotalProgress,
509: PRInt32 aMaxTotalProgress)
510: {
511: NSEnumerator* enumerator = [mListeners objectEnumerator];
512: id obj;
513:
514: while ((obj = [enumerator nextObject])) {
515: [obj onProgressChange:aCurTotalProgress outOf:aMaxTotalProgress];
516: }
517:
518: return NS_OK;
519: }
520:
521: /* void onLocationChange (in nsIWebProgress aWebProgress, in nsIRequest aRequest, in nsIURI location); */
522: NS_IMETHODIMP
523: nsCocoaBrowserListener::OnLocationChange(nsIWebProgress *aWebProgress,
524: nsIRequest *aRequest,
525: nsIURI *location)
526: {
527: nsXPIDLCString spec;
528:
529: location->GetSpec(getter_Copies(spec));
530: if (!spec) {
531: return NS_ERROR_FAILURE;
532: }
533:
534: const char* cstr = spec.get();
535: NSString* str = [NSString stringWithCString:cstr];
536: NSURL* url = [NSURL URLWithString:str];
537:
538: NSEnumerator* enumerator = [mListeners objectEnumerator];
539: id obj;
540:
541: while ((obj = [enumerator nextObject])) {
542: [obj onLocationChange:url];
543: }
544:
545: return NS_OK;
546: }
547:
548: /* void onStatusChange (in nsIWebProgress aWebProgress, in nsIRequest aRequest, in nsresult aStatus, in wstring aMessage); */
549: NS_IMETHODIMP
550: nsCocoaBrowserListener::OnStatusChange(nsIWebProgress *aWebProgress,
551: nsIRequest *aRequest,
552: nsresult aStatus,
553: const PRUnichar *aMessage)
554: {
555: return NS_OK;
556: }
557:
558: /* void onSecurityChange (in nsIWebProgress aWebProgress, in nsIRequest aRequest, in long state); */
559: NS_IMETHODIMP
560: nsCocoaBrowserListener::OnSecurityChange(nsIWebProgress *aWebProgress,
561: nsIRequest *aRequest,
562: PRInt32 state)
563: {
564: return NS_OK;
565: }
566:
567: void
568: nsCocoaBrowserListener::AddListener(id <NSBrowserListener> aListener)
569: {
570: [mListeners addObject:aListener];
571: }
572:
573: void
574: nsCocoaBrowserListener::RemoveListener(id <NSBrowserListener> aListener)
575: {
576: [mListeners removeObject:aListener];
577: }
578:
579: void
580: nsCocoaBrowserListener::SetContainer(id <NSBrowserContainer> aContainer)
581: {
582: [mContainer autorelease];
583:
584: mContainer = aContainer;
585:
586: [mContainer retain];
587: }
588:
1.2 hyatt 589: // Implementation of a header sniffer class that is used when saving Web pages and images.
590: class nsHeaderSniffer : public nsIWebProgressListener
591: {
592: public:
593: nsHeaderSniffer(nsIWebBrowserPersist* aPersist, nsIFile* aFile, nsIURI* aURL,
1.3 hyatt 594: nsIDOMDocument* aDocument, nsIInputStream* aPostData, PRBool aBypassCache,
1.2 hyatt 595: NSView* aFilterView, NSPopUpButton* aFilterList)
596: {
597: NS_INIT_REFCNT();
598: mPersist = aPersist;
599: mTmpFile = aFile;
600: mURL = aURL;
601: mDocument = aDocument;
1.3 hyatt 602: mPostData = aPostData;
1.2 hyatt 603: mBypassCache = aBypassCache;
604: mFilterView = aFilterView;
605: mFilterList = aFilterList;
606: }
607:
1.4 ! hyatt 608: virtual ~nsHeaderSniffer()
! 609: {
! 610: };
1.2 hyatt 611:
612: NS_DECL_ISUPPORTS
613: NS_DECL_NSIWEBPROGRESSLISTENER
614:
615: protected:
616: void PerformSave();
617:
618: private:
619: nsIWebBrowserPersist* mPersist; // Weak. It owns us as a listener.
620: nsCOMPtr<nsIFile> mTmpFile;
621: nsCOMPtr<nsIURI> mURL;
622: nsCOMPtr<nsIDOMDocument> mDocument;
1.3 hyatt 623: nsCOMPtr<nsIInputStream> mPostData;
1.2 hyatt 624: PRBool mBypassCache;
625: nsCString mContentType;
626: nsCString mContentDisposition;
627: NSView* mFilterView;
628: NSPopUpButton* mFilterList;
629: };
630:
631: NS_IMPL_ISUPPORTS1(nsHeaderSniffer, nsIWebProgressListener)
632:
633: // Implementation of nsIWebProgressListener
634: /* void onStateChange (in nsIWebProgress aWebProgress, in nsIRequest aRequest, in long aStateFlags, in unsigned long aStatus); */
635: NS_IMETHODIMP
636: nsHeaderSniffer::OnStateChange(nsIWebProgress *aWebProgress,
637: nsIRequest *aRequest,
638: PRInt32 aStateFlags,
639: PRUint32 aStatus)
640: {
641: if (aStateFlags & nsIWebProgressListener::STATE_START) {
642: nsCOMPtr<nsIChannel> channel(do_QueryInterface(aRequest));
643: nsXPIDLCString contentType;
644: channel->GetContentType(getter_Copies(contentType));
645: mContentType = contentType;
646:
647: // Get the content-disposition if we're an HTTP channel.
648: nsCOMPtr<nsIHttpChannel> httpChannel(do_QueryInterface(channel));
649: if (httpChannel) {
650: nsXPIDLCString disp;
651: httpChannel->GetResponseHeader("content-disposition", getter_Copies(disp));
652: mContentDisposition = disp;
653: }
654:
655: mPersist->CancelSave();
656: PRBool exists;
657: mTmpFile->Exists(&exists);
658: if (exists)
659: mTmpFile->Remove(PR_FALSE);
660: PerformSave();
661: }
662: return NS_OK;
663: }
664:
665: void nsHeaderSniffer::PerformSave()
666: {
667: // Are we an HTML document? If so, we will want to append an accessory view to
668: // the save dialog to provide the user with the option of doing a complete
669: // save vs. a single file save.
670: PRBool isHTML = (mDocument && mContentType.Equals("text/html") ||
671: mContentType.Equals("text/xml") ||
672: mContentType.Equals("application/xhtml+xml"));
673:
674: // Next find out the directory that we should start in.
675: nsCOMPtr<nsIPrefService> prefs(do_GetService("@mozilla.org/preferences-service;1"));
676: if (!prefs)
677: return;
678: nsCOMPtr<nsIPrefBranch> dirBranch;
679: prefs->GetBranch("browser.download.", getter_AddRefs(dirBranch));
680: PRInt32 filterIndex = 0;
681: if (dirBranch) {
682: nsresult rv = dirBranch->GetIntPref("save_converter_index", &filterIndex);
683: if (NS_FAILED(rv))
684: filterIndex = 0;
685: }
686: if (mFilterList)
687: [mFilterList selectItemAtIndex: filterIndex];
688:
689: // We need to figure out what file name to use.
690: nsCAutoString defaultFileName;
691:
692: if (!mContentDisposition.IsEmpty()) {
693: // (1) Use the HTTP header suggestion.
694: PRInt32 index = mContentDisposition.Find("filename=");
695: if (index >= 0) {
696: // Take the substring following the prefix.
697: index += 9;
698: nsCAutoString filename;
699: mContentDisposition.Right(filename, mContentDisposition.Length() - index);
700: defaultFileName = filename;
701: }
702: }
703:
704: if (defaultFileName.IsEmpty()) {
705: nsCOMPtr<nsIURL> url(do_QueryInterface(mURL));
706: if (url) {
707: nsXPIDLCString fileName;
708: url->GetFileName(getter_Copies(fileName));
709: defaultFileName = fileName; // (2) For file URLs, use the file name.
710: }
711: }
712:
713: if (defaultFileName.IsEmpty() && mDocument && isHTML) {
714: nsCOMPtr<nsIDOMHTMLDocument> htmlDoc(do_QueryInterface(mDocument));
715: nsAutoString title;
716: if (htmlDoc)
717: htmlDoc->GetTitle(title); // (3) Use the title of the document.
718: defaultFileName.AssignWithConversion(title);
719: }
720:
721: if (defaultFileName.IsEmpty()) {
722: // (4) Use the caller provided name. XXXdwh
723: }
724:
725: if (defaultFileName.IsEmpty()) {
726: // (5) Use the host.
727: nsXPIDLCString host;
728: mURL->GetHost(getter_Copies(host));
729: defaultFileName = host;
730: }
731:
732: // One last case to handle about:blank and other fruity untitled pages.
733: if (defaultFileName.IsEmpty())
734: defaultFileName = "untitled";
735:
736: // Validate the file name to ensure legality.
737: for (PRUint32 i = 0; i < defaultFileName.Length(); i++)
738: if (defaultFileName[i] == ':' || defaultFileName[i] == '/')
739: defaultFileName.SetCharAt(i, ' ');
740:
741: // Make sure the appropriate extension is appended to the suggested file name.
742: nsCOMPtr<nsIURI> fileURI(do_CreateInstance("@mozilla.org/network/standard-url;1"));
743: nsCOMPtr<nsIURL> fileURL(do_QueryInterface(fileURI));
744: if (!fileURL)
745: return;
746: fileURL->SetFilePath(defaultFileName.get());
747:
748: nsXPIDLCString fileEx;
749: fileURL->GetFileExtension(getter_Copies(fileEx));
750: nsDependentCString fileExtension(fileEx.get());
751:
752: PRBool setExtension = PR_FALSE;
753: if (mContentType.Equals("text/html")) {
754: if (fileExtension.IsEmpty() || (!fileExtension.Equals("htm") && !fileExtension.Equals("html"))) {
755: defaultFileName += ".html";
756: setExtension = PR_TRUE;
757: }
758: }
759:
760: if (!setExtension && fileExtension.IsEmpty()) {
761: nsCOMPtr<nsIMIMEService> mimeService(do_GetService("@mozilla.org/mime;1"));
762: if (!mimeService)
763: return;
764: nsCOMPtr<nsIMIMEInfo> mimeInfo;
765: mimeService->GetFromMIMEType(mContentType.get(), getter_AddRefs(mimeInfo));
766:
767: PRUint32 extCount;
768: char** extList;
769: mimeInfo->GetFileExtensions(&extCount, &extList);
770:
771: if (extCount > 0) {
772: defaultFileName += ".";
773: defaultFileName += extList[0];
774: }
775: }
776:
777: // Now it's time to pose the save dialog.
778: NSSavePanel* savePanel = [NSSavePanel savePanel];
779: NSString* file = nil;
780: if (!defaultFileName.IsEmpty())
781: file = [[NSString alloc] initWithCString: defaultFileName.get()];
782:
783: if (isHTML)
784: [savePanel setAccessoryView: mFilterView];
785:
786: if ([savePanel runModalForDirectory: nil file: file] == NSFileHandlingPanelCancelButton)
787: return;
788:
789: // Release the file string.
790: [file release];
791:
792: // Update the filter index.
793: if (isHTML && mFilterList) {
794: filterIndex = [mFilterList indexOfSelectedItem];
795: dirBranch->SetIntPref("save_converter_index", filterIndex);
796: }
797:
798: // Convert the content type to text/plain if it was selected in the filter.
799: if (isHTML && filterIndex == 2)
800: mContentType = "text/plain";
801:
802: nsCOMPtr<nsISupports> sourceData;
803: if (isHTML && filterIndex != 1)
804: sourceData = do_QueryInterface(mDocument);
805: else
806: sourceData = do_QueryInterface(mURL);
807:
1.4 ! hyatt 808: nsCOMPtr<nsIWebBrowserPersist> webPersist(do_CreateInstance(persistContractID));
1.2 hyatt 809: ProgressDlgController* progressDialog = [[ProgressDlgController alloc] initWithWindowNibName: @"ProgressDialog"];
1.4 ! hyatt 810: [progressDialog setWebPersist: webPersist
1.2 hyatt 811: source: sourceData.get()
812: destination: [savePanel filename]
813: contentType: mContentType.get()
1.3 hyatt 814: postData: mPostData
815: bypassCache: mBypassCache];
816:
1.2 hyatt 817: [progressDialog showWindow: progressDialog];
818: }
819:
820: /* void onProgressChange (in nsIWebProgress aWebProgress, in nsIRequest aRequest, in long aCurSelfProgress, in long aMaxSelfProgress, in long aCurTotalProgress, in long aMaxTotalProgress); */
821: NS_IMETHODIMP
822: nsHeaderSniffer::OnProgressChange(nsIWebProgress *aWebProgress,
823: nsIRequest *aRequest,
824: PRInt32 aCurSelfProgress,
825: PRInt32 aMaxSelfProgress,
826: PRInt32 aCurTotalProgress,
827: PRInt32 aMaxTotalProgress)
828: {
829: return NS_OK;
830: }
831:
832: /* void onLocationChange (in nsIWebProgress aWebProgress, in nsIRequest aRequest, in nsIURI location); */
833: NS_IMETHODIMP
834: nsHeaderSniffer::OnLocationChange(nsIWebProgress *aWebProgress,
835: nsIRequest *aRequest,
836: nsIURI *location)
837: {
838: return NS_OK;
839: }
840:
841: /* void onStatusChange (in nsIWebProgress aWebProgress, in nsIRequest aRequest, in nsresult aStatus, in wstring aMessage); */
842: NS_IMETHODIMP
843: nsHeaderSniffer::OnStatusChange(nsIWebProgress *aWebProgress,
844: nsIRequest *aRequest,
845: nsresult aStatus,
846: const PRUnichar *aMessage)
847: {
848: return NS_OK;
849: }
850:
851: /* void onSecurityChange (in nsIWebProgress aWebProgress, in nsIRequest aRequest, in long state); */
852: NS_IMETHODIMP
853: nsHeaderSniffer::OnSecurityChange(nsIWebProgress *aWebProgress,
854: nsIRequest *aRequest,
855: PRInt32 state)
856: {
857: return NS_OK;
858: }
859:
1.1 hyatt 860:
861: @implementation NSBrowserView
862:
863: - (id)initWithFrame:(NSRect)frame
864: {
865: [super initWithFrame:frame];
866:
867: nsresult rv = nsCocoaBrowserService::InitEmbedding();
868: if (NS_FAILED(rv)) {
869: // XXX need to throw
870: }
871:
872: _listener = new nsCocoaBrowserListener(self);
873: NS_ADDREF(_listener);
874:
875: // Create the web browser instance
876: nsCOMPtr<nsIWebBrowser> browser = do_CreateInstance(NS_WEBBROWSER_CONTRACTID, &rv);
877: if (NS_FAILED(rv)) {
878: // XXX need to throw
879: }
880:
881: _webBrowser = browser;
882: NS_ADDREF(_webBrowser);
883:
884: // Set the container nsIWebBrowserChrome
885: _webBrowser->SetContainerWindow(NS_STATIC_CAST(nsIWebBrowserChrome *,
886: _listener));
887:
888: // Register as a listener for web progress
889: nsCOMPtr<nsIWeakReference> weak = do_GetWeakReference(NS_STATIC_CAST(nsIWebProgressListener*, _listener));
890: _webBrowser->AddWebBrowserListener(weak, NS_GET_IID(nsIWebProgressListener));
891:
892: // Hook up the widget hierarchy with us as the parent
893: nsCOMPtr<nsIBaseWindow> baseWin = do_QueryInterface(_webBrowser);
894: baseWin->InitWindow((NSView*)self, nsnull, 0, 0,
895: frame.size.width, frame.size.height);
896: baseWin->Create();
897:
898: return self;
899: }
900:
901: - (void)dealloc
902: {
903: NS_RELEASE(_listener);
904: NS_IF_RELEASE(_webBrowser);
905: nsCocoaBrowserService::TermEmbedding();
906:
907: [super dealloc];
908: }
909:
910: - (void)setFrame:(NSRect)frameRect
911: {
912: [super setFrame:frameRect];
913: if (_webBrowser) {
914: nsCOMPtr<nsIBaseWindow> window = do_QueryInterface(_webBrowser);
915: window->SetSize((PRInt32)frameRect.size.width,
916: (PRInt32)frameRect.size.height,
917: PR_TRUE);
918: }
919: }
920:
921: - (void)addListener:(id <NSBrowserListener>)listener
922: {
923: _listener->AddListener(listener);
924: }
925:
926: - (void)removeListener:(id <NSBrowserListener>)listener
927: {
928: _listener->RemoveListener(listener);
929: }
930:
931: - (void)setContainer:(id <NSBrowserContainer>)container
932: {
933: _listener->SetContainer(container);
934: }
935:
936: - (nsIDOMWindow*)getContentWindow
937: {
938: nsIDOMWindow* window;
939:
940: _webBrowser->GetContentDOMWindow(&window);
941:
942: return window;
943: }
944:
945: - (void)loadURI:(NSURL *)url flags:(unsigned int)flags
946: {
947: nsCOMPtr<nsIWebNavigation> nav = do_QueryInterface(_webBrowser);
948:
949: NSString* spec = [url absoluteString];
950: int length = [spec length];
951: PRUnichar* specStr = nsMemory::Alloc((length+1) * sizeof(PRUnichar));
952: [spec getCharacters:specStr];
953: specStr[length] = PRUnichar(0);
954:
955:
956: PRUint32 navFlags = nsIWebNavigation::LOAD_FLAGS_NONE;
957: if (flags & NSLoadFlagsDontPutInHistory) {
958: navFlags |= nsIWebNavigation::LOAD_FLAGS_BYPASS_HISTORY;
959: }
960: if (flags & NSLoadFlagsReplaceHistoryEntry) {
961: navFlags |= nsIWebNavigation::LOAD_FLAGS_REPLACE_HISTORY;
962: }
963: if (flags & NSLoadFlagsBypassCacheAndProxy) {
964: navFlags |= nsIWebNavigation::LOAD_FLAGS_BYPASS_CACHE |
965: nsIWebNavigation::LOAD_FLAGS_BYPASS_PROXY;
966: }
967:
968: nsresult rv = nav->LoadURI(specStr, navFlags, nsnull, nsnull, nsnull);
969: if (NS_FAILED(rv)) {
970: // XXX need to throw
971: }
972:
973: nsMemory::Free(specStr);
974: }
975:
976: - (void)reload:(unsigned int)flags
977: {
978: nsCOMPtr<nsIWebNavigation> nav = do_QueryInterface(_webBrowser);
979:
980: PRUint32 navFlags = nsIWebNavigation::LOAD_FLAGS_NONE;
981: if (flags & NSLoadFlagsBypassCacheAndProxy) {
982: navFlags |= nsIWebNavigation::LOAD_FLAGS_BYPASS_CACHE |
983: nsIWebNavigation::LOAD_FLAGS_BYPASS_PROXY;
984: }
985:
986: nsresult rv = nav->Reload(navFlags);
987: if (NS_FAILED(rv)) {
988: // XXX need to throw
989: }
990: }
991:
992: - (BOOL)canGoBack
993: {
994: nsCOMPtr<nsIWebNavigation> nav = do_QueryInterface(_webBrowser);
995:
996: PRBool can;
997: nav->GetCanGoBack(&can);
998:
999: return can ? YES : NO;
1000: }
1001:
1002: - (BOOL)canGoForward
1003: {
1004: nsCOMPtr<nsIWebNavigation> nav = do_QueryInterface(_webBrowser);
1005:
1006: PRBool can;
1007: nav->GetCanGoForward(&can);
1008:
1009: return can ? YES : NO;
1010: }
1011:
1012: - (void)goBack
1013: {
1014: nsCOMPtr<nsIWebNavigation> nav = do_QueryInterface(_webBrowser);
1015:
1016: nsresult rv = nav->GoBack();
1017: if (NS_FAILED(rv)) {
1018: // XXX need to throw
1019: }
1020: }
1021:
1022: - (void)goForward
1023: {
1024: nsCOMPtr<nsIWebNavigation> nav = do_QueryInterface(_webBrowser);
1025:
1026: nsresult rv = nav->GoForward();
1027: if (NS_FAILED(rv)) {
1028: // XXX need to throw
1029: }
1030: }
1031:
1032: - (void)gotoIndex:(int)index
1033: {
1034: nsCOMPtr<nsIWebNavigation> nav = do_QueryInterface(_webBrowser);
1035:
1036: nsresult rv = nav->GotoIndex(index);
1037: if (NS_FAILED(rv)) {
1038: // XXX need to throw
1039: }
1040: }
1041:
1042: - (void)stop:(unsigned int)flags
1043: {
1044: nsCOMPtr<nsIWebNavigation> nav = do_QueryInterface(_webBrowser);
1045:
1046: nsresult rv = nav->Stop(flags);
1047: if (NS_FAILED(rv)) {
1048: // XXX need to throw
1049: }
1050: }
1051:
1052: - (NSURL*)getCurrentURI
1053: {
1054: nsCOMPtr<nsIURI> uri;
1055: nsCOMPtr<nsIWebNavigation> nav = do_QueryInterface(_webBrowser);
1056:
1057: nav->GetCurrentURI(getter_AddRefs(uri));
1058: if (!uri) {
1059: return nsnull;
1060: }
1061:
1062: nsXPIDLCString spec;
1063: uri->GetSpec(getter_Copies(spec));
1064:
1065: const char* cstr = spec.get();
1066: NSString* str = [NSString stringWithCString:cstr];
1067: NSURL* url = [NSURL URLWithString:str];
1068:
1069: return url;
1070: }
1071:
1072: - (nsIWebBrowser*)getWebBrowser
1073: {
1074: NS_IF_ADDREF(_webBrowser);
1075: return _webBrowser;
1076: }
1077:
1078: - (void)setWebBrowser:(nsIWebBrowser*)browser
1079: {
1080: _webBrowser = browser;
1081:
1082: if (_webBrowser) {
1083: // Set the container nsIWebBrowserChrome
1084: _webBrowser->SetContainerWindow(NS_STATIC_CAST(nsIWebBrowserChrome *,
1085: _listener));
1086:
1087: NSRect frame = [self frame];
1088:
1089: // Hook up the widget hierarchy with us as the parent
1090: nsCOMPtr<nsIBaseWindow> baseWin = do_QueryInterface(_webBrowser);
1091: baseWin->InitWindow((NSView*)self, nsnull, 0, 0,
1092: frame.size.width, frame.size.height);
1093: baseWin->Create();
1094: }
1095:
1.2 hyatt 1096: }
1097:
1098: -(void) saveInternal: (nsIURI*)aURI
1099: withDocument: (nsIDOMDocument*)aDocument
1100: bypassCache: (BOOL)aBypassCache
1101: filterView: (NSView*)aFilterView
1102: filterList: (NSPopUpButton*)aFilterList
1103: {
1104: // Create our web browser persist object. This is the object that knows
1105: // how to actually perform the saving of the page (and of the images
1106: // on the page).
1107: nsCOMPtr<nsIWebBrowserPersist> webPersist(do_CreateInstance(persistContractID));
1108: if (!webPersist)
1109: return;
1110:
1111: // Make a temporary file object that we can save to.
1112: nsCOMPtr<nsIProperties> dirService(do_GetService(dirServiceContractID));
1113: if (!dirService)
1114: return;
1115: nsCOMPtr<nsIFile> tmpFile;
1116: dirService->Get("TmpD", NS_GET_IID(nsIFile), getter_AddRefs(tmpFile));
1117: static short unsigned int tmpRandom = 0;
1118: nsCAutoString tmpNo; tmpNo.AssignWithConversion(tmpRandom++);
1119: nsCAutoString saveFile("-sav");
1120: saveFile += tmpNo;
1121: saveFile += "tmp";
1122: tmpFile->Append(saveFile.get());
1123:
1124: // Get the post data if we're an HTML doc.
1125: nsCOMPtr<nsIWebNavigation> webNav(do_QueryInterface(_webBrowser));
1126: nsCOMPtr<nsISHistory> sessionHistory;
1127: webNav->GetSessionHistory(getter_AddRefs(sessionHistory));
1.3 hyatt 1128: nsCOMPtr<nsIHistoryEntry> entry;
1129: PRInt32 sindex;
1130: sessionHistory->GetIndex(&sindex);
1131: sessionHistory->GetEntryAtIndex(sindex, PR_FALSE, getter_AddRefs(entry));
1132: nsCOMPtr<nsISHEntry> shEntry(do_QueryInterface(entry));
1133: nsCOMPtr<nsIInputStream> postData;
1134: if (shEntry)
1135: shEntry->GetPostData(getter_AddRefs(postData));
1136:
1.2 hyatt 1137: nsHeaderSniffer* sniffer = new nsHeaderSniffer(webPersist, tmpFile, aURI,
1.3 hyatt 1138: aDocument, postData, aBypassCache,
1.2 hyatt 1139: aFilterView, aFilterList);
1140: if (!sniffer)
1141: return;
1142: webPersist->SetProgressListener(sniffer);
1143: webPersist->SaveURI(aURI, nsnull, tmpFile);
1144: }
1145:
1146: -(void)saveDocument: (NSView*)aFilterView filterList: (NSPopUpButton*)aFilterList
1147: {
1148: nsCOMPtr<nsIWebBrowserFocus> wbf(do_QueryInterface(_webBrowser));
1149: nsCOMPtr<nsIDOMWindow> domWindow;
1150: wbf->GetFocusedWindow(getter_AddRefs(domWindow));
1151: if (!domWindow)
1152: _webBrowser->GetContentDOMWindow(getter_AddRefs(domWindow));
1153: if (!domWindow)
1154: return;
1155:
1156: nsCOMPtr<nsIDOMDocument> domDocument;
1157: domWindow->GetDocument(getter_AddRefs(domDocument));
1158: if (!domDocument)
1159: return;
1160: nsCOMPtr<nsIDocument> doc(do_QueryInterface(domDocument));
1161: if (!doc)
1162: return;
1163: nsCOMPtr<nsIURI> url;
1164: doc->GetDocumentURL(getter_AddRefs(url));
1165:
1166: [self saveInternal: url.get()
1167: withDocument: domDocument
1168: bypassCache: NO
1169: filterView: aFilterView
1170: filterList: aFilterList];
1.1 hyatt 1171: }
1172:
1173: @end
1174:
FreeBSD-CVSweb <freebsd-cvsweb@FreeBSD.org>