Add generic label mechanism
[conkeror.git] / modules / save.js
blobd648a7671b0dca1d7c884727a179280f03c904bb
1 /**
2 * (C) Copyright 2004-2007 Shawn Betts
3 * (C) Copyright 2007 John J. Foerch
4 * (C) Copyright 2007-2008 Jeremy Maitin-Shepard
6 * Use, modification, and distribution are subject to the terms specified in the
7 * COPYING file.
8 **/
10 require("content-buffer.js");
11 require("load-spec.js");
12 require("suggest-file-name.js");
14 /* buffer is used only to associate with the download */
15 define_keywords("$use_cache", "$buffer", "$prepare_download");
16 function save_uri(lspec, output_file) {
17 keywords(arguments, $use_cache = false);
19 var use_cache = arguments.$use_cache;
21 var buffer = arguments.$buffer;
23 var prepare_download = arguments.$prepare_download;
25 var cache_key = null;
26 var uri = load_spec_uri(lspec);
27 var referrer_uri = load_spec_referrer(lspec);
28 var post_data = load_spec_post_data(lspec);
29 if (use_cache)
30 cache_key = load_spec_cache_key(lspec);
32 var file_uri = makeFileURL(output_file);
34 var persist = Cc["@mozilla.org/embedding/browser/nsWebBrowserPersist;1"].createInstance(Ci.nsIWebBrowserPersist);
36 persist.persistFlags =
37 Ci.nsIWebBrowserPersist.PERSIST_FLAGS_REPLACE_EXISTING_FILES |
38 Ci.nsIWebBrowserPersist.PERSIST_FLAGS_AUTODETECT_APPLY_CONVERSION |
39 Ci.nsIWebBrowserPersist.PERSIST_FLAGS_CLEANUP_ON_FAILURE;
41 if (use_cache)
42 persist.persistFlags |= Ci.nsIWebBrowserPersist.PERSIST_FLAGS_FROM_CACHE;
43 else
44 persist.persistFlags |= Ci.nsIWebBrowserPersist.PERSIST_FLAGS_BYPASS_CACHE;
46 var info = register_download(buffer, uri);
47 if (prepare_download)
48 prepare_download(info);
50 var tr = Cc["@mozilla.org/transfer;1"].createInstance(Ci.nsITransfer);
51 tr.init(uri, file_uri, output_file.leafName,
52 load_spec_mime_info(lspec),
53 null /* start time */,
54 null /* temp file */,
55 persist);
56 persist.progressListener = tr;
57 persist.saveURI(uri, cache_key, referrer_uri, post_data, null /* no extra headers */, file_uri);
59 return info;
63 // We have no DOM, and can only save the URL as is.
64 const SAVEMODE_FILEONLY = 0x00;
65 // We have a DOM and can save as complete.
66 const SAVEMODE_COMPLETE_DOM = 0x01;
67 // We have a DOM which we can serialize as text.
68 const SAVEMODE_COMPLETE_TEXT = 0x02;
70 function get_save_mode_from_content_type(content_type) {
71 var mode = SAVEMODE_FILEONLY;
72 switch (content_type) {
73 case "text/html":
74 case "application/xhtml+xml":
75 mode |= SAVEMODE_COMPLETE_TEXT;
76 // Fall through
77 case "text/xml":
78 case "application/xml":
79 mode |= SAVEMODE_COMPLETE_DOM;
80 break;
82 return mode;
85 define_keywords("$use_cache", "$buffer", "$wrap_column", "$prepare_download");
86 function save_document_as_text(document, output_file)
88 keywords(arguments, $use_cache = true, $wrap_column = 80);
90 var mode = get_save_mode_from_content_type(document.contentType);
91 if (!(mode & SAVEMODE_COMPLETE_TEXT))
92 throw interactive_error("Document cannot be saved as text.");
94 var use_cache = arguments.$use_cache;
96 var prepare_download = arguments.$prepare_download;
98 var buffer = arguments.$buffer;
100 var uri = document.documentURIObject;
102 var file_uri = makeFileURL(output_file);
104 var persist = Cc["@mozilla.org/embedding/browser/nsWebBrowserPersist;1"].createInstance(Ci.nsIWebBrowserPersist);
106 persist.persistFlags =
107 Ci.nsIWebBrowserPersist.PERSIST_FLAGS_REPLACE_EXISTING_FILES |
108 Ci.nsIWebBrowserPersist.PERSIST_FLAGS_AUTODETECT_APPLY_CONVERSION |
109 Ci.nsIWebBrowserPersist.PERSIST_FLAGS_CLEANUP_ON_FAILURE;
111 var encoding_flags =
112 Ci.nsIWebBrowserPersist.ENCODE_FLAGS_FORMATTED |
113 Ci.nsIWebBrowserPersist.ENCODE_FLAGS_ABSOLUTE_LINKS |
114 Ci.nsIWebBrowserPersist.ENCODE_FLAGS_NOFRAMES_CONTENT;
117 if (use_cache)
118 persist.persistFlags |= Ci.nsIWebBrowserPersist.PERSIST_FLAGS_FROM_CACHE;
119 else
120 persist.persistFlags |= Ci.nsIWebBrowserPersist.PERSIST_FLAGS_BYPASS_CACHE;
124 var info = register_download(buffer, uri);
125 if (prepare_download)
126 prepare_download(info);
128 var tr = Cc["@mozilla.org/transfer;1"].createInstance(Ci.nsITransfer);
129 tr.init(uri, file_uri, output_file.leafName,
130 mime_info_from_mime_type("text/plain"),
131 null /* start time */,
132 null /* temp file */,
133 persist);
134 persist.progressListener = tr;
135 persist.saveDocument(document, file_uri, null /* data path */,
136 "text/plain", encoding_flags,
137 arguments.$wrap_column);
138 return info;
141 define_keywords("$use_cache", "$buffer", "$prepare_download");
142 function save_document_complete(document, output_file, output_dir) {
144 var mime_type = document.contentType;
146 var mode = get_save_mode_from_content_type(mime_type);
147 if (!(mode & SAVEMODE_COMPLETE_DOM))
148 throw interactive_error("Complete document cannot be saved.");
150 var use_cache = arguments.$use_cache;
152 var buffer = arguments.$buffer;
154 var prepare_download = arguments.$prepare_download;
156 var uri = document.documentURIObject;
158 var file_uri = makeFileURL(output_file);
160 var persist = Cc["@mozilla.org/embedding/browser/nsWebBrowserPersist;1"].createInstance(Ci.nsIWebBrowserPersist);
162 persist.persistFlags =
163 Ci.nsIWebBrowserPersist.PERSIST_FLAGS_REPLACE_EXISTING_FILES |
164 Ci.nsIWebBrowserPersist.PERSIST_FLAGS_AUTODETECT_APPLY_CONVERSION |
165 Ci.nsIWebBrowserPersist.PERSIST_FLAGS_CLEANUP_ON_FAILURE;
167 var encoding_flags =
168 Ci.nsIWebBrowserPersist.ENCODE_FLAGS_BASIC_ENTITIES;
170 if (use_cache)
171 persist.persistFlags |= Ci.nsIWebBrowserPersist.PERSIST_FLAGS_FROM_CACHE;
172 else
173 persist.persistFlags |= Ci.nsIWebBrowserPersist.PERSIST_FLAGS_BYPASS_CACHE;
176 var info = register_download(buffer, uri);
177 if (prepare_download)
178 prepare_download(info);
180 var tr = Cc["@mozilla.org/transfer;1"].createInstance(Ci.nsITransfer);
181 tr.init(uri, file_uri, output_file.leafName,
182 mime_info_from_mime_type(mime_type),
183 null /* start time */,
184 null /* temp file */,
185 persist);
186 persist.progressListener = tr;
187 persist.saveDocument(document, file_uri, output_dir /* data path */,
188 mime_type, encoding_flags,
190 return info;
193 function download_failed_error() {
194 var e = new Error("Download failed");
195 e.__proto__ = download_failed_error.prototype;
196 return e;
198 download_failed_error.prototype.__proto__ = Error.prototype;
200 /* Returns an array of two elements: the first element is the
201 * nsILocalFile object, the second element is a boolean indicating
202 * whether the file is temporary and should be deleted when the caller is
203 * done with it.
205 define_keywords("$action", "$shell_command", "$shell_command_cwd", "$buffer", "$use_cache");
206 function download_as_temporary(lspec) {
207 keywords(arguments, $use_cache = true);
209 var action_description = arguments.$action;
210 var shell_command = arguments.$shell_command;
211 var shell_command_cwd = arguments.$shell_command_cwd;
213 var uri = load_spec_uri(lspec);
214 // If it is local file, there is no need to download it
215 if (uri.scheme == "file")
217 let file = uri.QueryInterface(Ci.nsIFileURL).file;
219 yield co_return([file, false /* not temporary */]);
223 var file = get_temporary_file(suggest_file_name(lspec));
225 var cc = yield CONTINUATION;
227 function handle_state_change(info) {
228 var state = info.state;
229 switch (state) {
230 case DOWNLOAD_CANCELED:
231 case DOWNLOAD_FAILED:
232 info.remove(); // ensure that the download cannot be retried later
233 try {
234 // Delete the temporary file
235 file.remove(false /*non-recursive*/);
236 } catch (e) {}
237 cc.throw(download_failed_error());
238 break;
239 case DOWNLOAD_FINISHED:
240 cc([file, true /* temporary */]);
241 break;
245 save_uri(lspec, file,
246 $use_cache = arguments.$use_cache,
247 $buffer = arguments.$buffer,
248 $prepare_download = function (info) {
249 if (action_description != null) {
250 info.action_description = action_description;
251 info.temporary_status = DOWNLOAD_TEMPORARY_FOR_ACTION;
252 } else if (shell_command != null) {
253 info.set_shell_command(shell_command, shell_command_cwd);
254 info.temporary_status = DOWNLOAD_TEMPORARY_FOR_COMMAND;
256 add_hook.call(info, "download_state_change_hook", handle_state_change);
259 var result = yield SUSPEND;
260 yield co_return(result);