new module to enable editing and deleting of bookmarks
[conkeror/arlinius.git] / modules / content-handler.js
blobe59b55d22d137b76dbe62f83bc68a1573c3c971f
1 /**
2 * (C) Copyright 2008 Jeremy Maitin-Shepard
3 * (C) Copyright 2009-2010 John Foerch
5 * Use, modification, and distribution are subject to the terms specified in the
6 * COPYING file.
7 **/
9 require("mime-type-override.js");
11 define_mime_type_table("content_handlers", {},
12 "A mime type table mapping mime types to content handlers. This table "+
13 "will be checked for a match when a navigation event causes Conkeror "+
14 "to encounter a mime type which is not supported by Mozilla. If no "+
15 "appropriate content handler is found in this table, the user will "+
16 "be prompted to choose from among common actions.");
18 /**
19 * content_handler_context is a datatype for storing contextual information
20 * that can be used by content handlers, such as window, buffer, frame, and
21 * the download launcher object. It will also contain an abort method to
22 * abort the download. Download helper actions are passed an object of this
23 * type.
25 function content_handler_context (launcher, context) {
26 var xulrunner_version = Cc['@mozilla.org/xre/app-info;1']
27 .getService(Ci.nsIXULAppInfo)
28 .platformVersion;
29 var vc = Cc["@mozilla.org/xpcom/version-comparator;1"]
30 .getService(Ci.nsIVersionComparator);
31 this.launcher = launcher;
32 try {
33 this.frame = context.QueryInterface(Ci.nsIInterfaceRequestor)
34 .getInterface((vc.compare(xulrunner_version, "8.0") >= 0) ?
35 Ci.nsIDOMWindow :
36 Ci.nsIDOMWindowInternal)
37 this.window = get_window_from_frame(this.frame);
38 this.buffer = get_buffer_from_frame(this.frame);
39 } catch (e) {
40 this.window = get_recent_conkeror_window();
41 if (this.window) {
42 this.buffer = this.window.buffers.current;
43 this.frame = this.buffer.focused_frame; //doesn't necessarily exist for all buffer types
47 content_handler_context.prototype = {
48 constructor: content_handler_context,
49 launcher: null,
50 window: null,
51 buffer: null,
52 frame: null,
53 abort: function () {
54 const NS_BINDING_ABORTED = 0x804b0002;
55 this.launcher.cancel(NS_BINDING_ABORTED);
60 /**
61 * The content_handler_* functions below are all things that conkeror
62 * is able to do when Mozilla has invoked download_helper because of an
63 * attempt to navigate to a document of an unsupported mime type.
65 function content_handler_save (ctx) {
66 var suggested_path = suggest_save_path_from_file_name(
67 ctx.launcher.suggestedFileName, ctx.buffer);
68 var file = yield ctx.window.minibuffer.read_file_check_overwrite(
69 $prompt = "Save to file:",
70 $initial_value = suggested_path,
71 $select);
72 register_download(ctx.buffer, ctx.launcher.source);
73 ctx.launcher.saveToDisk(file, false);
76 function content_handler_save_in (path, inhibit_prompt) {
77 path = make_file(path);
78 return function (ctx) {
79 var file;
80 var suggested_path = path.clone();
81 suggested_path.append(ctx.launcher.suggestedFileName);
82 if (inhibit_prompt)
83 file = suggested_path;
84 else {
85 file = yield ctx.window.minibuffer.read_file_check_overwrite(
86 $prompt = "Save to file:",
87 $initial_value = suggested_path.path,
88 $select);
90 register_download(ctx.buffer, ctx.launcher.source);
91 ctx.launcher.saveToDisk(file, false);
95 function content_handler_open (ctx) {
96 var cwd = with_current_buffer(ctx.buffer, function (I) I.local.cwd);
97 var mime_type = ctx.launcher.MIMEInfo.MIMEType;
98 var suggested_action = external_content_handlers.get(mime_type);
99 var command = yield ctx.window.minibuffer.read_shell_command(
100 $initial_value = suggested_action,
101 $cwd = cwd);
102 var file = get_temporary_file(ctx.launcher.suggestedFileName);
103 var info = register_download(ctx.buffer, ctx.launcher.source);
104 info.temporary_status = DOWNLOAD_TEMPORARY_FOR_COMMAND;
105 info.set_shell_command(command, cwd);
106 ctx.launcher.saveToDisk(file, false);
109 function content_handler_open_default_viewer (ctx) {
110 var cwd = with_current_buffer(ctx.buffer, function (I) I.local.cwd);
111 var mime_type = ctx.launcher.MIMEInfo.MIMEType;
112 var command = external_content_handlers.get(mime_type);
113 if (command == null)
114 command = yield ctx.window.minibuffer.read_shell_command(
115 $initial_value = command,
116 $cwd = cwd);
117 var file = get_temporary_file(ctx.launcher.suggestedFileName);
118 var info = register_download(ctx.buffer, ctx.launcher.source);
119 info.temporary_status = DOWNLOAD_TEMPORARY_FOR_COMMAND;
120 info.set_shell_command(command, cwd);
121 ctx.launcher.saveToDisk(file, false);
124 function content_handler_open_url (ctx) {
125 ctx.abort(); // abort download
126 let mime_type = ctx.launcher.MIMEInfo.MIMEType;
127 let cwd = with_current_buffer(ctx.buffer, function (I) I.local.cwd);
128 let cmd = yield ctx.window.minibuffer.read_shell_command(
129 $cwd = cwd,
130 $initial_value = external_content_handlers.get(mime_type));
131 shell_command_with_argument_blind(cmd, ctx.launcher.source.spec, $cwd = cwd);
134 function content_handler_copy_url (ctx) {
135 ctx.abort(); // abort download
136 let uri = ctx.launcher.source.spec;
137 writeToClipboard(uri);
138 ctx.window.minibuffer.message("Copied: " + uri);
141 function content_handler_view_internally (ctx) {
142 var suggested_type = ctx.launcher.MIMEInfo.MIMEType;
143 if (viewable_mime_type_list.indexOf(suggested_type) == -1)
144 suggested_type = "text/plain";
145 var mime_type = yield ctx.window.minibuffer.read_viewable_mime_type(
146 $prompt = "View internally as",
147 $initial_value = suggested_type,
148 $select);
149 ctx.abort(); // abort before reloading
150 override_mime_type_for_next_load(ctx.launcher.source, mime_type);
151 ctx.frame.location = ctx.launcher.source.spec; // reload
154 function content_handler_view_as_text (ctx) {
155 ctx.abort(); // abort before reloading
156 override_mime_type_for_next_load(ctx.launcher.source, "text/plain");
157 ctx.frame.location = ctx.launcher.source.spec; // reload
160 function content_handler_prompt (ctx) {
161 var action_chosen = false;
162 var can_view_internally = ctx.frame != null &&
163 can_override_mime_type_for_uri(ctx.launcher.source);
164 var panel;
165 try {
166 panel = create_info_panel(ctx.window, "download-panel",
167 [["downloading", "Downloading:", ctx.launcher.source.spec],
168 ["mime-type", "Mime type:", ctx.launcher.MIMEInfo.MIMEType]]);
169 var action = yield ctx.window.minibuffer.read_single_character_option(
170 $prompt = "Action to perform: (s: save; o: open; O: open URL; c: copy URL; " +
171 (can_view_internally ? "i: view internally; t: view as text)" : ")"),
172 $options = (can_view_internally ? ["s", "o", "O", "c", "i", "t"] : ["s", "o", "O", "c"]));
173 switch (action) {
174 case "s":
175 yield content_handler_save(ctx);
176 action_chosen = true;
177 break;
178 case "o":
179 yield content_handler_open(ctx);
180 action_chosen = true;
181 break;
182 case "O":
183 yield content_handler_open_url(ctx);
184 action_chosen = true;
185 break;
186 case "c":
187 yield content_handler_copy_url(ctx);
188 action_chosen = true;
189 break;
190 case "i":
191 yield content_handler_view_internally(ctx);
192 action_chosen = true;
193 break;
194 case "t":
195 yield content_handler_view_as_text(ctx);
196 action_chosen = true;
197 break;
199 } catch (e) {
200 handle_interactive_error(ctx.window, e);
201 } finally {
202 if (! action_chosen)
203 ctx.abort();
204 if (panel)
205 panel.destroy();
211 * download_helper implements nsIHelperAppLauncherDialog.
213 * Sometimes, like when following a link, the content type of the document
214 * cannot be displayed by Mozilla. When this happens, Mozilla calls the
215 * `show' method of our download_helper with a handle for the started
216 * download and other contextual information.
218 function download_helper () {}
219 download_helper.prototype = {
220 constructor: download_helper,
221 QueryInterface: generate_QI(Ci.nsIHelperAppLauncherDialog,
222 Ci.nsIWebProgressListener2),
223 show: function (launcher, context, reason) {
224 var ctx = new content_handler_context(launcher, context);
225 if (! ctx.window) {
226 ctx.abort(); //XXX: impolite; need better solution.
227 return;
229 try {
230 // is there anything in content_handlers for this object?
231 var mime_type = launcher.MIMEInfo.MIMEType;
232 var action = content_handlers.get(mime_type) ||
233 content_handler_prompt;
234 co_call(action(ctx));
235 } catch (e) {
236 handle_interactive_error(ctx.window, e);
239 promptForSaveToFile: function (launcher, context, default_file, suggested_file_extension) {
240 return null;
244 provide("content-handler");