Changed EphyHistoryWindow to use the new backend, some things still remain (selected_...
[ephy-soc.git] / embed / mozilla / EphyHeaderSniffer.cpp
blob2e3608442147e18adcb5c5fa811a1fde11d7ff62
1 /* ***** BEGIN LICENSE BLOCK *****
2 * Version: MPL 1.1/GPL 2.0/LGPL 2.1
4 * The contents of this file are subject to the Mozilla Public License Version
5 * 1.1 (the "License"); you may not use this file except in compliance with
6 * the License. You may obtain a copy of the License at
7 * http://www.mozilla.org/MPL/
9 * Software distributed under the License is distributed on an "AS IS" basis,
10 * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
11 * for the specific language governing rights and limitations under the
12 * License.
14 * The Original Code is Chimera code.
16 * The Initial Developer of the Original Code is
17 * Netscape Communications Corporation.
18 * Portions created by the Initial Developer are Copyright © 2002
19 * the Initial Developer. All Rights Reserved.
21 * Contributor(s):
22 * David Hyatt <hyatt@netscape.com>
23 * Simon Fraser <sfraser@netscape.com>
25 * Alternatively, the contents of this file may be used under the terms of
26 * either the GNU General Public License Version 2 or later (the "GPL"), or
27 * the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
28 * in which case the provisions of the GPL or the LGPL are applicable instead
29 * of those above. If you wish to allow use of your version of this file only
30 * under the terms of either the GPL or the LGPL, and not to allow others to
31 * use your version of this file under the terms of the MPL, indicate your
32 * decision by deleting the provisions above and replace them with the notice
33 * and other provisions required by the GPL or the LGPL. If you do not delete
34 * the provisions above, a recipient may use your version of this file under
35 * the terms of any one of the MPL, the GPL or the LGPL.
37 * ***** END LICENSE BLOCK *****
39 * $Id: EphyHeaderSniffer.cpp 6588 2006-09-13 11:34:25Z chpe $
42 #include "mozilla-config.h"
43 #include "config.h"
45 #include <glib/gi18n.h>
46 #include <libgnomevfs/gnome-vfs-utils.h>
48 #include <nsStringAPI.h>
50 #include <nsComponentManagerUtils.h>
51 #include <nsIChannel.h>
52 #include <nsIDOMDocument.h>
53 #include <nsIDOMHTMLDocument.h>
54 #include <nsIDownload.h>
55 #include <nsIHttpChannel.h>
56 #include <nsIInputStream.h>
57 #include <nsILocalFile.h>
58 #include <nsIMIMEHeaderParam.h>
59 #include <nsIMIMEInfo.h>
60 #include <nsIMIMEService.h>
61 #include <nsIPrefService.h>
62 #include <nsIPromptService.h>
63 #include <nsIURI.h>
64 #include <nsIURL.h>
65 #include <nsIWebBrowserPersist.h>
66 #include <nsIWindowWatcher.h>
67 #include <nsServiceManagerUtils.h>
68 #include <nsXPCOMCID.h>
70 #include "eel-gconf-extensions.h"
71 #include "ephy-debug.h"
72 #include "ephy-file-chooser.h"
73 #include "ephy-gui.h"
74 #include "ephy-prefs.h"
76 #include "EphyBadCertRejector.h"
77 #include "MozDownload.h"
79 #include "EphyHeaderSniffer.h"
81 EphyHeaderSniffer::EphyHeaderSniffer (nsIWebBrowserPersist* aPersist, MozillaEmbedPersist *aEmbedPersist,
82 nsIFile* aFile, nsIURI* aURL, nsIDOMDocument* aDocument, nsIInputStream* aPostData,
83 EphyEmbedSingle *single)
84 : mPersist(aPersist)
85 , mEmbedPersist(aEmbedPersist)
86 , mTmpFile(aFile)
87 , mURL(aURL)
88 , mOriginalURI(nsnull)
89 , mDocument(aDocument)
90 , mPostData(aPostData)
92 LOG ("EphyHeaderSniffer ctor (%p)", this);
94 nsCOMPtr<nsIWindowWatcher> watcher
95 (do_GetService("@mozilla.org/embedcomp/window-watcher;1"));
96 if (!watcher) return;
98 watcher->GetNewAuthPrompter (nsnull, getter_AddRefs (mAuthPrompt));
100 mSingle = single;
101 g_object_add_weak_pointer (G_OBJECT (mSingle),
102 (gpointer *)&mSingle);
105 EphyHeaderSniffer::~EphyHeaderSniffer()
107 LOG ("EphyHeaderSniffer dtor (%p)", this);
109 if (mSingle)
111 g_object_remove_weak_pointer (G_OBJECT (mSingle),
112 (gpointer *)&mSingle);
116 NS_IMPL_ISUPPORTS3 (EphyHeaderSniffer,
117 nsIWebProgressListener,
118 nsIInterfaceRequestor,
119 nsIAuthPrompt)
121 NS_IMETHODIMP
122 EphyHeaderSniffer::HandleContent ()
124 gboolean handled = FALSE;
125 nsCString uriSpec;
127 if (mPostData || !mSingle) return NS_ERROR_FAILURE;
129 mURL->GetSpec (uriSpec);
131 g_signal_emit_by_name (mSingle, "handle_content", mContentType.get(),
132 uriSpec.get(), &handled);
134 return handled ? NS_OK : NS_ERROR_FAILURE;
137 NS_IMETHODIMP
138 EphyHeaderSniffer::OnStateChange (nsIWebProgress *aWebProgress, nsIRequest *aRequest, PRUint32 aStateFlags,
139 PRUint32 aStatus)
141 if (aStateFlags & nsIWebProgressListener::STATE_START)
143 /* be sure to keep it alive while we save since it owns
144 us as a listener and keep ourselves alive */
145 nsCOMPtr<nsIWebBrowserPersist> kungFuDeathGrip(mPersist);
146 nsCOMPtr<nsIWebProgressListener> kungFuSuicideGrip(this);
148 nsresult rv;
149 nsCOMPtr<nsIChannel> channel = do_QueryInterface(aRequest, &rv);
150 if (!channel) return rv;
151 channel->GetContentType(mContentType);
153 nsCOMPtr<nsIURI> origURI;
154 channel->GetOriginalURI(getter_AddRefs(origURI));
156 nsCOMPtr<nsIHttpChannel> httpChannel(do_QueryInterface(channel));
157 if (httpChannel)
159 httpChannel->GetResponseHeader(nsCString("content-disposition"),
160 mContentDisposition);
163 mPersist->CancelSave();
165 PRBool exists;
166 mTmpFile->Exists(&exists);
167 if (exists)
169 mTmpFile->Remove(PR_FALSE);
172 rv = HandleContent ();
173 if (NS_SUCCEEDED (rv)) return NS_OK;
175 rv = PerformSave(origURI);
176 if (NS_FAILED(rv))
178 /* FIXME put up some UI */
183 return NS_OK;
186 NS_IMETHODIMP
187 EphyHeaderSniffer::OnProgressChange (nsIWebProgress *aWebProgress,
188 nsIRequest *aRequest,
189 PRInt32 aCurSelfProgress,
190 PRInt32 aMaxSelfProgress,
191 PRInt32 aCurTotalProgress,
192 PRInt32 aMaxTotalProgress)
194 return NS_OK;
197 NS_IMETHODIMP
198 EphyHeaderSniffer::OnLocationChange (nsIWebProgress *aWebProgress,
199 nsIRequest *aRequest,
200 nsIURI *location)
202 return NS_OK;
205 NS_IMETHODIMP
206 EphyHeaderSniffer::OnStatusChange (nsIWebProgress *aWebProgress,
207 nsIRequest *aRequest,
208 nsresult aStatus,
209 const PRUnichar *aMessage)
211 return NS_OK;
214 NS_IMETHODIMP
215 EphyHeaderSniffer::OnSecurityChange (nsIWebProgress *aWebProgress, nsIRequest *aRequest, PRUint32 state)
217 return NS_OK;
220 /* void getInterface (in nsIIDRef uuid, [iid_is (uuid), retval] out nsQIResult result); */
221 NS_IMETHODIMP
222 EphyHeaderSniffer::GetInterface(const nsIID & uuid, void * *result)
224 if (uuid.Equals (NS_GET_IID (nsIBadCertListener)) &&
225 mEmbedPersist)
227 EphyEmbedPersistFlags flags;
229 g_object_get (mEmbedPersist, "flags", &flags, (char *) NULL);
231 if (flags & EPHY_EMBED_PERSIST_NO_CERTDIALOGS)
233 EphyBadCertRejector *badCertRejector = new EphyBadCertRejector ();
234 if (!badCertRejector) return NS_ERROR_OUT_OF_MEMORY;
236 *result = NS_STATIC_CAST(nsIBadCertListener*, badCertRejector);
237 NS_ADDREF (badCertRejector);
239 return NS_OK;
243 return NS_ERROR_NO_INTERFACE;
246 static void
247 filechooser_response_cb (GtkWidget *dialog,
248 gint response,
249 EphyHeaderSniffer* sniffer)
251 if (response == GTK_RESPONSE_ACCEPT)
253 char *filename;
255 filename = gtk_file_chooser_get_filename (GTK_FILE_CHOOSER (dialog));
257 if (ephy_gui_check_location_writable (dialog, filename) == FALSE)
259 g_free (filename);
260 return;
263 nsCOMPtr<nsILocalFile> destFile = do_CreateInstance (NS_LOCAL_FILE_CONTRACTID);
264 if (destFile)
266 destFile->InitWithNativePath (nsCString (filename));
268 sniffer->InitiateDownload (destFile);
271 g_free (filename);
274 // FIXME how to inform user of failed save ?
276 gtk_widget_destroy (GTK_WIDGET (dialog));
279 nsresult EphyHeaderSniffer::PerformSave (nsIURI* inOriginalURI)
281 nsresult rv;
282 EphyEmbedPersistFlags flags;
283 PRBool askDownloadDest;
285 mOriginalURI = inOriginalURI;
287 flags = ephy_embed_persist_get_flags (EPHY_EMBED_PERSIST (mEmbedPersist));
288 askDownloadDest = flags & EPHY_EMBED_PERSIST_ASK_DESTINATION;
290 nsString defaultFileName;
292 if (!defaultFileName.Length() && mContentDisposition.Length())
294 /* 1 Use the HTTP header suggestion. */
295 nsCOMPtr<nsIMIMEHeaderParam> mimehdrpar =
296 do_GetService("@mozilla.org/network/mime-hdrparam;1");
298 if (mimehdrpar)
300 nsCString fallbackCharset;
301 if (mURL)
303 mURL->GetOriginCharset(fallbackCharset);
306 nsString fileName;
308 rv = mimehdrpar->GetParameter (mContentDisposition, "filename",
309 fallbackCharset, PR_TRUE, nsnull,
310 fileName);
311 if (NS_FAILED(rv) || !fileName.Length())
313 rv = mimehdrpar->GetParameter (mContentDisposition, "name",
314 fallbackCharset, PR_TRUE, nsnull,
315 fileName);
318 if (NS_SUCCEEDED(rv) && fileName.Length())
320 defaultFileName = fileName;
325 if (!defaultFileName.Length())
327 /* 2 For file URLs, use the file name. */
329 nsCOMPtr<nsIURL> url(do_QueryInterface(mURL));
330 if (url)
332 nsCString fileNameCString;
333 url->GetFileName(fileNameCString);
334 NS_CStringToUTF16 (fileNameCString, NS_CSTRING_ENCODING_UTF8,
335 defaultFileName);
339 if (!defaultFileName.Length() && mDocument)
341 /* 3 Use the title of the document. */
343 nsCOMPtr<nsIDOMHTMLDocument> htmlDoc(do_QueryInterface(mDocument));
344 if (htmlDoc)
346 htmlDoc->GetTitle(defaultFileName);
350 if (!defaultFileName.Length() && mURL)
352 /* 4 Use the host. */
353 nsCString hostName;
354 mURL->GetHost(hostName);
355 NS_CStringToUTF16 (hostName, NS_CSTRING_ENCODING_UTF8,
356 defaultFileName);
359 /* 5 One last case to handle about:blank and other untitled pages. */
360 if (!defaultFileName.Length())
362 NS_CStringToUTF16 (nsCString(_("Untitled")),
363 NS_CSTRING_ENCODING_UTF8, defaultFileName);
366 /* Validate the file name to ensure legality. */
367 nsCString cDefaultFileName;
368 NS_UTF16ToCString (defaultFileName, NS_CSTRING_ENCODING_UTF8,
369 cDefaultFileName);
370 char *default_name = g_strdup (cDefaultFileName.get());
371 default_name = g_strdelimit (default_name, "/\\:", ' ');
373 const char *key;
374 key = ephy_embed_persist_get_persist_key (EPHY_EMBED_PERSIST (mEmbedPersist));
376 /* FIXME: do better here by using nsITextToSubURI service, like in
377 * http://lxr.mozilla.org/seamonkey/source/xpfe/communicator/resources/content/contentAreaUtils.js#763
379 char *filename;
380 filename = gnome_vfs_unescape_string (default_name, NULL);
382 if (!g_utf8_validate (filename, -1, NULL))
384 g_free (filename);
385 filename = g_strdup (default_name);
388 g_free (default_name);
390 if (askDownloadDest)
392 EphyFileChooser *dialog;
393 GtkWindow *window;
394 const char *title;
395 guint32 user_time;
397 title = ephy_embed_persist_get_fc_title (EPHY_EMBED_PERSIST (mEmbedPersist));
398 window = ephy_embed_persist_get_fc_parent (EPHY_EMBED_PERSIST (mEmbedPersist));
400 user_time = ephy_embed_persist_get_user_time (EPHY_EMBED_PERSIST (mEmbedPersist));
401 if (user_time == 0)
403 g_warning ("EphyHeaderSniffer::PerformSave without valid user time!\n");
406 dialog = ephy_file_chooser_new (title ? title: _("Save"),
407 GTK_WIDGET (window),
408 GTK_FILE_CHOOSER_ACTION_SAVE,
409 key ? key : CONF_STATE_SAVE_DIR,
410 EPHY_FILE_FILTER_ALL_SUPPORTED);
411 gtk_file_chooser_set_do_overwrite_confirmation (GTK_FILE_CHOOSER (dialog), TRUE);
413 gtk_file_chooser_set_current_name (GTK_FILE_CHOOSER (dialog),
414 filename);
416 g_signal_connect (dialog, "response",
417 G_CALLBACK (filechooser_response_cb), this);
419 ephy_gui_window_update_user_time (GTK_WIDGET (dialog), user_time);
420 gtk_widget_show (GTK_WIDGET (dialog));
422 g_free (filename);
423 return NS_OK;
425 /* FIXME: how to inform user of failed save ? */
427 nsCOMPtr<nsILocalFile> destFile;
428 BuildDownloadPath (filename, getter_AddRefs (destFile));
429 g_free (filename);
430 NS_ENSURE_TRUE (destFile, NS_ERROR_FAILURE);
432 return InitiateDownload (destFile);
435 nsresult EphyHeaderSniffer::InitiateDownload (nsILocalFile *aDestFile)
437 LOG ("Initiating download");
439 return InitiateMozillaDownload (mDocument, mURL, aDestFile,
440 mContentType.get(), mOriginalURI, mEmbedPersist,
441 mPostData, nsnull, -1);