[debian/patches/deb-webjumps.diff] add new default webjump debpopcon
[conkeror/arlinius.git] / modules / content-handler.js
blob522cc9dccaca2faa5945d41a56ae4d0282956c63
1 /**
2  * (C) Copyright 2008 Jeremy Maitin-Shepard
3  * (C) Copyright 2009 John Foerch
4  *
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.
24  */
25 function content_handler_context () {}
28 /**
29  * The content_handler_* functions below are all things that conkeror
30  * is able to do when Mozilla has invoked download_helper because of an
31  * attempt to navigate to a document of an unsupported mime type.
32  */
33 function content_handler_save (ctx) {
34     var suggested_path = suggest_save_path_from_file_name(
35         ctx.launcher.suggestedFileName, ctx.buffer);
36     var file = yield ctx.window.minibuffer.read_file_check_overwrite(
37         $prompt = "Save to file:",
38         $initial_value = suggested_path,
39         $select);
40     register_download(ctx.buffer, ctx.launcher.source);
41     ctx.launcher.saveToDisk(file, false);
44 function content_handler_open (ctx) {
45     var cwd = with_current_buffer(ctx.buffer, function (I) I.local.cwd);
46     var mime_type = ctx.launcher.MIMEInfo.MIMEType;
47     var suggested_action = external_content_handlers.get(mime_type);
48     var command = yield ctx.window.minibuffer.read_shell_command(
49         $initial_value = suggested_action,
50         $cwd = cwd);
51     var file = get_temporary_file(ctx.launcher.suggestedFileName);
52     var info = register_download(ctx.buffer, ctx.launcher.source);
53     info.temporary_status = DOWNLOAD_TEMPORARY_FOR_COMMAND;
54     info.set_shell_command(command, cwd);
55     ctx.launcher.saveToDisk(file, false);
58 function content_handler_open_default_viewer (ctx) {
59     var cwd = with_current_buffer(ctx.buffer, function (I) I.local.cwd);
60     var mime_type = ctx.launcher.MIMEInfo.MIMEType;
61     var command = external_content_handlers.get(mime_type);
62     if (command == null)
63         command = yield ctx.window.minibuffer.read_shell_command(
64             $initial_value = command,
65             $cwd = cwd);
66     var file = get_temporary_file(ctx.launcher.suggestedFileName);
67     var info = register_download(ctx.buffer, ctx.launcher.source);
68     info.temporary_status = DOWNLOAD_TEMPORARY_FOR_COMMAND;
69     info.set_shell_command(command, cwd);
70     ctx.launcher.saveToDisk(file, false);
73 function content_handler_open_url (ctx) {
74     ctx.abort(); // abort download
75     let mime_type = ctx.launcher.MIMEInfo.MIMEType;
76     let cwd = with_current_buffer(ctx.buffer, function (I) I.local.cwd);
77     let cmd = yield ctx.window.minibuffer.read_shell_command(
78         $cwd = cwd,
79         $initial_value = external_content_handlers.get(mime_type));
80     shell_command_with_argument_blind(cmd, ctx.launcher.source.spec, $cwd = cwd);
83 function content_handler_copy_url (ctx) {
84     ctx.abort(); // abort download
85     let uri = ctx.launcher.source.spec;
86     writeToClipboard(uri);
87     ctx.window.minibuffer.message("Copied: " + uri);
90 function content_handler_view_internally (ctx) {
91     var suggested_type = ctx.launcher.MIMEInfo.MIMEType;
92     if (viewable_mime_type_list.indexOf(suggested_type) == -1)
93         suggested_type = "text/plain";
94     var mime_type = yield ctx.window.minibuffer.read_viewable_mime_type(
95         $prompt = "View internally as",
96         $initial_value = suggested_type,
97         $select);
98     ctx.abort(); // abort before reloading
99     override_mime_type_for_next_load(ctx.launcher.source, mime_type);
100     ctx.frame.location = ctx.launcher.source.spec; // reload
103 function content_handler_view_as_text (ctx) {
104     ctx.abort(); // abort before reloading
105     override_mime_type_for_next_load(ctx.launcher.source, "text/plain");
106     ctx.frame.location = ctx.launcher.source.spec; // reload
109 function content_handler_prompt (ctx) {
110     var action_chosen = false;
111     var can_view_internally = ctx.frame != null &&
112         can_override_mime_type_for_uri(ctx.launcher.source);
113     var panel;
114     try {
115         panel = create_info_panel(ctx.window, "download-panel",
116                                   [["downloading", "Downloading:", ctx.launcher.source.spec],
117                                    ["mime-type", "Mime type:", ctx.launcher.MIMEInfo.MIMEType]]);
118         var action = yield ctx.window.minibuffer.read_single_character_option(
119             $prompt = "Action to perform: (s: save; o: open; O: open URL; c: copy URL; " +
120                 (can_view_internally ? "i: view internally; t: view as text)" : ")"),
121             $options = (can_view_internally ? ["s", "o", "O", "c", "i", "t"] : ["s", "o", "O", "c"]));
122         switch (action) {
123         case "s":
124             yield content_handler_save(ctx);
125             action_chosen = true;
126             break;
127         case "o":
128             yield content_handler_open(ctx);
129             action_chosen = true;
130             break;
131         case "O":
132             yield content_handler_open_url(ctx);
133             action_chosen = true;
134             break;
135         case "c":
136             yield content_handler_copy_url(ctx);
137             action_chosen = true;
138             break;
139         case "i":
140             yield content_handler_view_internally(ctx);
141             action_chosen = true;
142             break;
143         case "t":
144             yield content_handler_view_as_text(ctx);
145             action_chosen = true;
146             break;
147         }
148     } catch (e) {
149         handle_interactive_error(ctx.window, e);
150     } finally {
151         if (! action_chosen)
152             ctx.abort();
153         if (panel)
154             panel.destroy();
155     }
160  * download_helper implements nsIHelperAppLauncherDialog.
162  * Sometimes, like when following a link, the content type of the document
163  * cannot be displayed by Mozilla.  When this happens, Mozilla calls the
164  * `show' method of our download_helper with a handle for the started
165  * download and other contextual information.
166  */
167 function download_helper () {}
168 download_helper.prototype = {
169     QueryInterface: generate_QI(Ci.nsIHelperAppLauncherDialog,
170                                 Ci.nsIWebProgressListener2),
172     show: function (launcher, context, reason) {
173         // content handlers will be passed a context containing references
174         // to the window, buffer, frame, launcher, and an abort method.
175         var ctx = new content_handler_context();
176         ctx.launcher = launcher;
177         ctx.abort = function () {
178             const NS_BINDING_ABORTED = 0x804b0002;
179             launcher.cancel(NS_BINDING_ABORTED);
180         };
181         // then set frame, window, and buffer in the context, so that
182         // action handlers can use them if needed.
183         try {
184             ctx.frame = context.QueryInterface(Ci.nsIInterfaceRequestor)
185                 .getInterface(Ci.nsIDOMWindowInternal);
186             ctx.window = get_window_from_frame(ctx.frame);
187             ctx.buffer = get_buffer_from_frame(ctx.window, ctx.frame);
188         } catch (e) {
189             ctx.window = get_recent_conkeror_window();
190             if (! ctx.window) {
191                 // FIXME: need to handle this case perhaps where no windows exist
192                 ctx.abort(); // for now, just cancel the download
193                 return;
194             }
195             ctx.buffer = ctx.window.buffers.current;
196             ctx.frame = ctx.buffer.focused_frame;
197         }
198         try {
199             // is there anything in content_handlers for this object?
200             var mime_type = launcher.MIMEInfo.MIMEType;
201             var action = content_handlers.get(mime_type) ||
202                 content_handler_prompt;
203             co_call(action(ctx));
204         } catch (e) {
205             handle_interactive_error(ctx.window, e);
206         }
207     },
209     promptForSaveToFile: function (launcher, context, default_file, suggested_file_extension) {
210         return null;
211     }