isearch-backspace, isearch-done: docstrings
[conkeror.git] / modules / content-handler.js
blobe59b55d22d137b76dbe62f83bc68a1573c3c971f
1 /**
2  * (C) Copyright 2008 Jeremy Maitin-Shepard
3  * (C) Copyright 2009-2010 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 (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
44         }
45     }
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);
56     }
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.
64  */
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);
89         }
90         register_download(ctx.buffer, ctx.launcher.source);
91         ctx.launcher.saveToDisk(file, false);
92     };
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;
198         }
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();
206     }
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.
217  */
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;
228         }
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);
237         }
238     },
239     promptForSaveToFile: function (launcher, context, default_file, suggested_file_extension) {
240         return null;
241     }
244 provide("content-handler");