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