From f292b1af7b8e8ef6867cbace35bf0b050d23edba Mon Sep 17 00:00:00 2001 From: Jeremy Maitin-Shepard Date: Sat, 5 Apr 2008 12:31:23 -0400 Subject: [PATCH] Revamped and simplified load_spec infrastructure --- modules/content-buffer.js | 14 +- modules/element.js | 247 +++++++++++++--------------------- modules/external-editor.js | 4 +- modules/hints.js | 4 +- modules/history.js | 24 ---- modules/load-spec.js | 268 +++++++++++++++++++++++++------------ modules/media.js | 58 +++----- modules/page-modes/google-video.js | 16 ++- modules/page-modes/youtube.js | 14 +- modules/save.js | 29 ++-- modules/suggest-file-name.js | 119 ++++++---------- 11 files changed, 370 insertions(+), 427 deletions(-) rewrite modules/load-spec.js (64%) rewrite modules/media.js (61%) diff --git a/modules/content-buffer.js b/modules/content-buffer.js index 9dd3c9d..e2236ea 100644 --- a/modules/content-buffer.js +++ b/modules/content-buffer.js @@ -80,15 +80,15 @@ function content_buffer(window, element) this.ignore_initial_blank = true; - var load_spec = arguments.$load; - if (load_spec) { - if (load_spec.url == "about:blank") + var lspec = arguments.$load; + if (lspec) { + if (lspec.url == "about:blank") this.ignore_initial_blank = false; else { /* Ensure that an existing load of about:blank is stopped */ this.web_navigation.stop(Ci.nsIWebNavigation.STOP_ALL); - this.load(load_spec); + this.load(lspec); } } @@ -336,7 +336,7 @@ define_global_mode("overlink_mode", overlink_mode(true); -function open_in_browser(buffer, target, load_spec) +function open_in_browser(buffer, target, lspec) { switch (target) { case OPEN_CURRENT_BUFFER: @@ -344,7 +344,7 @@ function open_in_browser(buffer, target, load_spec) case FOLLOW_CURRENT_FRAME: case FOLLOW_TOP_FRAME: if (buffer instanceof content_buffer) { - apply_load_spec(buffer, load_spec); + apply_load_spec(buffer, lspec); break; } target = OPEN_NEW_BUFFER; @@ -352,7 +352,7 @@ function open_in_browser(buffer, target, load_spec) default: create_buffer(buffer.window, buffer_creator(content_buffer, - $load = load_spec, + $load = lspec, $configuration = buffer.configuration), target); break; diff --git a/modules/element.js b/modules/element.js index 395609a..f5dfb00 100644 --- a/modules/element.js +++ b/modules/element.js @@ -64,23 +64,13 @@ function browser_element_follow(buffer, target, elem) { browser_set_element_focus(buffer, elem, true /* no scroll */); - var load_spec = null; - var current_frame = null; - var no_click = false; - if (elem instanceof media_spec) { - no_click = true; - current_frame = elem.frame; - } else if (elem instanceof Ci.nsIDOMWindow) { - current_frame = elem; - no_click = true; - } else if (elem instanceof Ci.nsIDOMHTMLFrameElement || - elem instanceof Ci.nsIDOMHTMLIFrameElement || - elem instanceof Ci.nsIDOMHTMLLinkElement) { - no_click = true; - } else if (elem instanceof Ci.nsIDOMHTMLImageElement) { - if (!elem.hasAttribute("onmousedown") && !elem.hasAttribute("onclick")) - no_click = true; - } + var no_click = (is_load_spec(elem) || + (elem instanceof Ci.nsIDOMWindow) || + (elem instanceof Ci.nsIDOMHTMLFrameElement) || + (elem instanceof Ci.nsIDOMHTMLIFrameElement) || + (elem instanceof Ci.nsIDOMHTMLLinkElement) || + (elem instanceof Ci.nsIDOMHTMLImageElement && + !elem.hasAttribute("onmousedown") && !elem.hasAttribute("onclick"))); if (target == FOLLOW_DEFAULT && !no_click) { var x = 1, y = 1; @@ -95,42 +85,36 @@ function browser_element_follow(buffer, target, elem) return; } - var load_spec = element_get_load_spec(elem); - if (load_spec == null) { + var spec = element_get_load_spec(elem); + if (spec == null) { throw interactive_error("Element has no associated URL"); return; } - if (load_spec.url.match(/^\s*javascript:/)) { + if (load_spec_uri_string(spec).match(/^\s*javascript:/)) { // This URL won't work throw interactive_error("Can't load javascript URL"); } - var target_obj = null; switch (target) { case FOLLOW_CURRENT_FRAME: - if (current_frame == null) { - if (elem.ownerDocument) - current_frame = elem.ownerDocument.defaultView; - else - current_frame = buffer.top_frame; - } - if (current_frame != buffer.top_frame) { - target_obj = get_web_navigation_for_window(current_frame); - apply_load_spec(target_obj, load_spec); + var current_frame = load_spec_source_frame(spec); + if (current_frame && current_frame != buffer.top_frame) { + var target_obj = get_web_navigation_for_frame(current_frame); + apply_load_spec(target_obj, spec); break; } case FOLLOW_DEFAULT: case FOLLOW_TOP_FRAME: case OPEN_CURRENT_BUFFER: - buffer.load(load_spec); + buffer.load(spec); break; case OPEN_NEW_WINDOW: case OPEN_NEW_BUFFER: case OPEN_NEW_BUFFER_BACKGROUND: create_buffer(buffer.window, buffer_creator(content_buffer, - $load = load_spec, + $load = spec, $configuration = buffer.configuration), target); } @@ -153,76 +137,23 @@ function browser_follow_link_with_click(buffer, elem, x, y) { elem.dispatchEvent(evt); } -function element_get_url(elem) { - var url = null; - - if (elem instanceof media_spec) { - if (elem instanceof media_spec_simple_uri) - return elem.uri; - return null; - } - else if (elem instanceof Ci.nsIDOMWindow) - url = elem.location.href; +function element_get_load_spec(elem) { - else if (elem instanceof Ci.nsIDOMHTMLFrameElement || - elem instanceof Ci.nsIDOMHTMLIFrameElement) - url = elem.contentWindow.location.href; + if (is_load_spec(elem)) + return elem; - else if (elem instanceof Ci.nsIDOMHTMLImageElement) - url = elem.src; + var spec = null; - else if (elem instanceof Ci.nsIDOMHTMLAnchorElement || - elem instanceof Ci.nsIDOMHTMLAreaElement || - elem instanceof Ci.nsIDOMHTMLLinkElement) { - if (elem.hasAttribute("href")) - url = elem.href; - else - return null; // nothing can be done - } else { - var node = elem; - while (node && !(node instanceof Ci.nsIDOMHTMLAnchorElement)) - node = node.parentNode; - if (node && !node.hasAttribute("href")) - node = null; - if (!node) { - // Try simple XLink - node = elem; - while (node) { - if (node.nodeType == Ci.nsIDOMNode.ELEMENT_NODE) { - url = linkNode.getAttributeNS(XLINK_NS, "href"); - break; - } - node = node.parentNode; - } - if (url) - url = makeURLAbsolute(node.baseURI, url); - } else - url = node.href; - } - if (url && url.length == 0) - url = null; - return url; -} - -function element_get_load_spec(elem) { - var load_spec = null; - - if (elem instanceof media_spec) { - if (elem instanceof media_spec_simple_uri) { - load_spec = {url: elem.uri, referrer: make_uri(elem.frame.location.href), - filename: elem.filename, - mime_type: elem.mime_type }; - } - } - else if (elem instanceof Ci.nsIDOMWindow) - load_spec = document_load_spec(elem.document); + if (elem instanceof Ci.nsIDOMWindow) + spec = load_spec({document: elem.document}); else if (elem instanceof Ci.nsIDOMHTMLFrameElement || elem instanceof Ci.nsIDOMHTMLIFrameElement) - load_spec = document_load_spec(elem.contentDocument); + spec = load_spec({document: elem.contentDocument}); else { var url = null; + var title = null; if (elem instanceof Ci.nsIDOMHTMLAnchorElement || elem instanceof Ci.nsIDOMHTMLAreaElement || @@ -230,9 +161,11 @@ function element_get_load_spec(elem) { if (!elem.hasAttribute("href")) return null; // nothing can be done, as no nesting within these elements is allowed url = elem.href; + title = elem.title || elem.textContent; } else if (elem instanceof Ci.nsIDOMHTMLImageElement) { url = elem.src; + title = elem.title || elem.alt; } else { var node = elem; @@ -254,17 +187,16 @@ function element_get_load_spec(elem) { } if (url) url = makeURLAbsolute(node.baseURI, url); + title = node.title || node.textContent; } } if (url && url.length > 0) { - var referrer = null; - try { - referrer = makeURL(elem.ownerDocument.location.href); - } catch (e) {} - load_spec = {url: url, referrer: referrer}; + if (title && title.length == 0) + title = null; + spec = load_spec({uri: url, source_frame: elem.ownerDocument.defaultView, title: title}); } } - return load_spec; + return spec; } define_variable( @@ -319,7 +251,7 @@ interactive_context.prototype.read_hinted_element_with_prompt = function(action, if (object_class != default_class) prompt += " (" + object_class + ")"; prompt += ":"; - + var result = yield this.minibuffer.read_hinted_element( $buffer = this.buffer, $prompt = prompt, @@ -353,8 +285,6 @@ function element_get_load_target_label(element) { return "frame"; if (element instanceof Ci.nsIDOMHTMLIFrameElement) return "iframe"; - if (element instanceof media_spec) - return "media"; return null; } @@ -376,36 +306,39 @@ function element_get_operation_label(element, op_name, suffix) { interactive("save", function (I) { var element = yield I.read_hinted_element_with_prompt("save", "Save", "links"); - var load_spec = element_get_load_spec(element); - if (load_spec == null) + var spec = element_get_load_spec(element); + if (spec == null) throw interactive_error("Element has no associated URI"); var panel; panel = create_info_panel(I.window, "download-panel", [["downloading", element_get_operation_label(element, "Saving"), - uri_string_from_load_spec(load_spec)], - ["mime-type", "Mime type:", mime_type_from_load_spec(load_spec)]]); + load_spec_uri_string(spec)], + ["mime-type", "Mime type:", load_spec_mime_type(spec)]]); try { var file = yield I.minibuffer.read_file_check_overwrite( $prompt = "Save as:", - $initial_value = suggest_save_path_from_file_name(suggest_file_name(load_spec), I.buffer), + $initial_value = suggest_save_path_from_file_name(suggest_file_name(spec), I.buffer), $history = "save"); } finally { panel.destroy(); } - save_uri(load_spec, file, + save_uri(spec, file, $buffer = I.buffer, $use_cache = false); }); function browser_element_copy(buffer, elem) { - var text = element_get_url(elem); - if (text == null) { + var spec = element_get_load_spec(elem); + var text = null; + if (spec) + text = load_spec_uri_string(spec); + else { if (!(elem instanceof Ci.nsIDOMNode)) throw interactive_error("Element has no associated text to copy."); switch (elem.localName) { @@ -417,10 +350,11 @@ function browser_element_copy(buffer, elem) if (elem.selectedIndex >= 0) text = elem.item(elem.selectedIndex).text; break; + default: + text = elem.textContent; + break; } } - if (text == null) - text = elem.textContent; writeToClipboard (text); buffer.window.minibuffer.message ("Copied: " + text); } @@ -436,13 +370,13 @@ function browser_element_view_source(buffer, target, elem) { if (view_source_use_external_editor || view_source_function) { - var load_spec = element_get_load_spec(elem); - if (load_spec == null) { + var spec = element_get_load_spec(elem); + if (spec == null) { throw interactive_error("Element has no associated URL"); return; } - let [file, temp] = yield download_as_temporary(load_spec, + let [file, temp] = yield download_as_temporary(spec, $buffer = buffer, $action = "View source"); if (view_source_use_external_editor) @@ -488,23 +422,23 @@ interactive("view-source", function (I) { interactive("shell-command-on-url", function (I) { var cwd = I.cwd; var element = yield I.read_hinted_element_with_prompt("shell_command_url", "URL shell command target", "links"); - var load_spec = element_get_load_spec(element); - if (load_spec == null) + var spec = element_get_load_spec(element); + if (spec == null) throw interactive_error("Unable to obtain URI from element"); - var uri = uri_string_from_load_spec(load_spec); + var uri = load_spec_uri_string(spec); var panel; panel = create_info_panel(I.window, "download-panel", [["downloading", element_get_operation_label(element, "Running on", "URI"), - uri_string_from_load_spec(load_spec)], - ["mime-type", "Mime type:", mime_type_from_load_spec(load_spec)]]); + load_spec_uri_string(spec)], + ["mime-type", "Mime type:", load_spec_mime_type(spec)]]); try { var cmd = yield I.minibuffer.read_shell_command( $cwd = cwd, - $initial_value = default_shell_command_from_load_spec(load_spec)); + $initial_value = load_spec_default_shell_command(spec)); } finally { panel.destroy(); } @@ -513,12 +447,12 @@ interactive("shell-command-on-url", function (I) { }); function browser_element_shell_command(buffer, elem, command) { - var load_spec = element_get_load_spec(elem); - if (load_spec == null) { + var spec = element_get_load_spec(elem); + if (spec == null) { throw interactive_error("Element has no associated URL"); return; } - yield download_as_temporary(load_spec, + yield download_as_temporary(spec, $buffer = buffer, $shell_command = command, $shell_command_cwd = buffer.cwd); @@ -528,24 +462,24 @@ interactive("shell-command-on-file", function (I) { var cwd = I.cwd; var element = yield I.read_hinted_element_with_prompt("shell_command", "Shell command target", "links"); - var load_spec = element_get_load_spec(element); - if (load_spec == null) + var spec = element_get_load_spec(element); + if (spec == null) throw interactive_error("Unable to obtain URI from element"); - var uri = uri_string_from_load_spec(load_spec); + var uri = load_spec_uri_string(spec); var panel; panel = create_info_panel(I.window, "download-panel", [["downloading", element_get_operation_label(element, "Running on"), - uri_string_from_load_spec(load_spec)], - ["mime-type", "Mime type:", mime_type_from_load_spec(load_spec)]]); + load_spec_uri_string(spec)], + ["mime-type", "Mime type:", load_spec_mime_type(spec)]]); try { var cmd = yield I.minibuffer.read_shell_command( $cwd = cwd, - $initial_value = default_shell_command_from_load_spec(load_spec)); + $initial_value = load_spec_default_shell_command(spec)); } finally { panel.destroy(); } @@ -556,37 +490,38 @@ interactive("shell-command-on-file", function (I) { interactive("bookmark", function (I) { var element = yield I.read_hinted_element_with_prompt("bookmark", "Bookmark", "frames"); - let [uri, suggested_title] = get_element_bookmark_info(element); - + var spec = element_get_load_spec(element); + if (!spec) + throw interactive_error("Element has no associated URI"); + var uri_string = load_spec_uri_string(spec); var panel; panel = create_info_panel(I.window, "bookmark-panel", [["bookmarking", element_get_operation_label(element, "Bookmarking"), - uri]]); + uri_string]]); try { - var title = yield I.minibuffer.read($prompt = "Bookmark with title:", $initial_value = suggested_title); + var title = yield I.minibuffer.read($prompt = "Bookmark with title:", $initial_value = load_spec_title(spec) || ""); } finally { panel.destroy(); } - add_bookmark(uri, title); - I.minibuffer.message("Added bookmark: " + uri + " - " + title); + add_bookmark(uri_string, title); + I.minibuffer.message("Added bookmark: " + uri_string + " - " + title); }); interactive("save-page", function (I) { check_buffer(I.buffer, content_buffer); var element = yield I.read_hinted_element_with_prompt("save_page", "Save page", "frames"); - var load_spec = element_get_load_spec(element); - if (load_spec == null || typeof(load_spec) != "object" || load_spec.document == null) + var spec = element_get_load_spec(element); + if (!spec || !load_spec_document(spec)) throw interactive_error("Element is not associated with a document."); - var doc = load_spec.document; - var suggested_path = suggest_save_path_from_file_name(suggest_file_name(doc), I.buffer); + var suggested_path = suggest_save_path_from_file_name(suggest_file_name(spec), I.buffer); var panel; panel = create_info_panel(I.window, "download-panel", [["downloading", element_get_operation_label(element, "Saving"), - uri_string_from_load_spec(load_spec)], - ["mime-type", "Mime type:", mime_type_from_load_spec(load_spec)]]); + load_spec_uri_string(spec)], + ["mime-type", "Mime type:", load_spec_mime_type(spec)]]); try { var file = yield I.minibuffer.read_file_check_overwrite( @@ -597,24 +532,24 @@ interactive("save-page", function (I) { panel.destroy(); } - save_uri(document_load_spec(doc), file, $buffer = I.buffer); + save_uri(spec, file, $buffer = I.buffer); }); interactive("save-page-as-text", function (I) { check_buffer(I.buffer, content_buffer); var element = yield I.read_hinted_element_with_prompt("save_page_as_text", "Save page as text", "frames"); - var load_spec = element_get_load_spec(element); - if (load_spec == null || typeof(load_spec) != "object" || load_spec.document == null) + var spec = element_get_load_spec(element); + var doc; + if (!spec || !(doc = load_spec_document(spec))) throw interactive_error("Element is not associated with a document."); - var doc = load_spec.document; - var suggested_path = suggest_save_path_from_file_name(suggest_file_name(doc, "txt"), I.buffer); + var suggested_path = suggest_save_path_from_file_name(suggest_file_name(spec, "txt"), I.buffer); var panel; panel = create_info_panel(I.window, "download-panel", [["downloading", element_get_operation_label(element, "Saving", "as text"), - uri_string_from_load_spec(load_spec)], - ["mime-type", "Mime type:", mime_type_from_load_spec(load_spec)]]); + load_spec_uri_string(spec)], + ["mime-type", "Mime type:", load_spec_mime_type(spec)]]); try { var file = yield I.minibuffer.read_file_check_overwrite( @@ -631,18 +566,18 @@ interactive("save-page-as-text", function (I) { interactive("save-page-complete", function (I) { check_buffer(I.buffer, content_buffer); var element = yield I.read_hinted_element_with_prompt("save_page_complete", "Save page complete", "frames"); - var load_spec = element_get_load_spec(element); - if (load_spec == null || typeof(load_spec) != "object" || load_spec.document == null) + var spec = element_get_load_spec(element); + var doc; + if (!spec || !(doc = load_spec_document(spec))) throw interactive_error("Element is not associated with a document."); - var doc = load_spec.document; - var suggested_path = suggest_save_path_from_file_name(suggest_file_name(doc), I.buffer); - + var suggested_path = suggest_save_path_from_file_name(suggest_file_name(spec), I.buffer); + var panel; panel = create_info_panel(I.window, "download-panel", [["downloading", element_get_operation_label(element, "Saving complete"), - uri_string_from_load_spec(load_spec)], - ["mime-type", "Mime type:", mime_type_from_load_spec(load_spec)]]); + load_spec_uri_string(spec)], + ["mime-type", "Mime type:", load_spec_mime_type(spec)]]); try { var file = yield I.minibuffer.read_file_check_overwrite( diff --git a/modules/external-editor.js b/modules/external-editor.js index d98616c..61b9aed 100644 --- a/modules/external-editor.js +++ b/modules/external-editor.js @@ -59,8 +59,8 @@ function create_external_editor_launcher(program, args) { }; } -function open_with_external_editor(load_spec) { +function open_with_external_editor(lspec) { keywords(arguments); - let [file, temp] = yield download_as_temporary(load_spec); + let [file, temp] = yield download_as_temporary(lspec); yield open_file_with_external_editor(file, $line = arguments.$line, $temporary = temp); } diff --git a/modules/hints.js b/modules/hints.js index b7fe3a3..9d14f19 100644 --- a/modules/hints.js +++ b/modules/hints.js @@ -513,8 +513,8 @@ minibuffer.prototype.read_hinted_element = function () { let completer = all_word_completer( $completions = media, - $get_string = function (x) x.uri || "", - $get_description = function (x) x.title); + $get_string = function (x) load_spec_uri_string(x), + $get_description = function (x) load_spec_title(x) || ""); let result = yield this.read( $prompt = "Media", diff --git a/modules/history.js b/modules/history.js index 6772b7b..5e18635 100644 --- a/modules/history.js +++ b/modules/history.js @@ -68,27 +68,3 @@ function add_bookmark(url, title) { nav_bookmarks_service.insertBookmark(nav_bookmarks_service.unfiledBookmarksFolder, makeURL(url), -1, title); } - -function get_element_bookmark_info(elem) { - var uri, title; - var doc = null; - if (elem instanceof Ci.nsIDOMWindow) - doc = elem.document; - else if (elem instanceof Ci.nsIDOMHTMLFrameElement || Ci.nsIDOMHTMLIFrameElement) - doc = elem.contentDocument; - else if (elem instanceof Ci.nsIDOMHTMLAnchorElement) { - uri = elem.getAttribute("href"); - let t = elem.getAttribute("title"); - if (t.length > 0) - title = t; - else - title = elem.textContent; - } else { - throw interactive_error("Invalid element"); - } - if (doc != null) { - uri = doc.location.href; - title = doc.title; - } - return [uri, title]; -} diff --git a/modules/load-spec.js b/modules/load-spec.js dissimilarity index 64% index 35baf16..00155d3 100644 --- a/modules/load-spec.js +++ b/modules/load-spec.js @@ -1,85 +1,183 @@ - -function get_web_navigation_for_frame(frame) { - var ifr = frame.QueryInterface(Ci.nsIInterfaceRequestor); - return ifr.getInterface(Ci.nsIWebNavigation); -} - -function get_SHEntry_for_document(doc) -{ - try - { - var frame = doc.defaultView; - var webNav = get_web_navigation_for_frame(frame); - var pageLoader = webNav.QueryInterface(Ci.nsIWebPageDescriptor); - var desc = pageLoader.currentDescriptor.QueryInterface(Ci.nsISHEntry); - return desc; - } catch (e) { return null; } -} - -function document_load_spec(doc) { - var sh_entry = get_SHEntry_for_document(doc); - var result = {url: doc.location.href, document: doc}; - if (sh_entry != null) { - result.cache_key = sh_entry; - result.referrer = sh_entry.referrerURI; - result.post_data = sh_entry.postData; - } - return result; -} - -function uri_string_from_load_spec(spec) { - if (typeof(spec) == "object") - return spec.url; - return spec; -} - -function uri_from_load_spec(spec) { - if (typeof(spec) == "object" && spec.document != null) - return spec.document.documentURIObject; - return make_uri(uri_string_from_load_spec(spec)); -} - -function mime_type_from_load_spec(spec) { - if (typeof(spec) == "object") { - if (spec.mime_type != null) - return spec.mime_type; - if (spec.document) - return spec.document.contentType || "application/octet-stream"; - } - return mime_type_from_uri(uri_string_from_load_spec(spec)); -} - -function mime_info_from_load_spec(spec) { - var type = mime_type_from_load_spec(spec); - return mime_info_from_mime_type(type); -} - -function default_shell_command_from_load_spec(spec) { - var mime_type = mime_type_from_load_spec(spec); - var handler = get_external_handler_for_mime_type(mime_type); - return handler; -} - -/* Target can be either a content_buffer or an nsIWebNavigation */ -function apply_load_spec(target, load_spec) { - var url, flags, referrer, post_data; - if (typeof(load_spec) == "string") { - url = load_spec; - flags = null; - referrer = null; - post_data = null; - } else { - url = load_spec.url; - flags = load_spec.flags; - referrer = load_spec.referrer; - post_data = load_spec.post_data; - } - if (flags == null) - flags = Ci.nsIWebNavigation.LOAD_FLAGS_NONE; - if (target instanceof content_buffer) { - target._display_URI = url; - target = target.web_navigation; - //buffer_description_change_hook.run(target); - } - target.loadURI(url, flags, referrer, post_data, null /* headers */); -} + +/** + * A load_spec has the following properties: + * + * Name: Required? Type: Description: + * ----- --------- ----- ------------ + * uri required string Specifies the URI of the target. + * + * document optional nsIDOMDocument Specifies a document corresponding to the target. + * Can also provide a default value for the mime_type property, + * the title property, and the source_frame property. + * + * flags optional number Specifies flags to pass to nsIWebNavigation.loadURI + * + * cache_key optional nsISHEntry Specifies a key for accessing the target from the cache. + * + * referrer optional nsIURI Specifies the referrer URI to use to access the target. + * + * post_data optional nsIInputStream Specifies POST data to use to access the target. + * + * mime_type optional string Specifies the MIME type of the target. + * + * title optional string Specifies a title/description text associated with the target. + * + * source_frame optional nsIDOMWindow Specifies the frame from which the link to the target was "obtained". + * Can provide a default value for referrer if document is not specified. + * + * filename optional string Specifies a default filename to use to save the target. + * + * filename_extension + * optional string Specifies a default filename extension to use to save the target. + */ +function load_spec(x) { x.__proto__ = load_spec.prototype; return x; } + +function is_load_spec(x) { + return (typeof(x) == "string") || (x instanceof load_spec); +} + +function load_spec_document(x) { + return x.document; +} + +function load_spec_title(x) { + if (x.title) + return x.title; + if (x.document) + return x.document.title; + return null; +} + +function load_spec_mime_type(x) { + if (typeof(x) == "object") { + if (x.mime_type) + return x.mime_type; + if (x.document) + return x.document.contentType || "application/octet-stream"; + } + return mime_type_from_uri(load_spec_uri(x)); +} + +function load_spec_filename(x) { + return x.filename; +} + +function load_spec_filename_extension(x) { + return x.filename_extension; +} + +function get_web_navigation_for_frame(frame) { + var ifr = frame.QueryInterface(Ci.nsIInterfaceRequestor); + return ifr.getInterface(Ci.nsIWebNavigation); +} + +function get_SHEntry_for_document(doc) +{ + try + { + var frame = doc.defaultView; + var webNav = get_web_navigation_for_frame(frame); + var pageLoader = webNav.QueryInterface(Ci.nsIWebPageDescriptor); + var desc = pageLoader.currentDescriptor.QueryInterface(Ci.nsISHEntry); + return desc; + } catch (e) { return null; } +} + +function load_spec_set_properties_from_sh_entry(x) { + var sh_entry = get_SHEntry_for_document(x.document); + if (sh_entry != null) { + x.cache_key = sh_entry; + x.referrer = sh_entry.referrerURI; + x.post_data = sh_entry.postData; + } +} + +function load_spec_referrer(x) { + if (x.referrer) + return x.referrer; + if (x.document) { + load_spec_set_properties_from_sh_entry(x); + return x.referrer; + } + if (x.source_frame) { + x.referrer = x.source_frame.document.documentURIObject; + return x.referrer; + } + return null; +} + +function load_spec_post_data(x) { + if (x.post_data) + return x.post_data; + if (x.document) { + load_spec_set_properties_from_sh_entry(x); + return x.post_data; + } + return null; +} + +function load_spec_cache_key(x) { + if (x.cache_key) + return x.cache_key; + if (x.document) { + load_spec_set_properties_from_sh_entry(x); + return x.cache_key; + } + return null; +} + +function load_spec_source_frame(x) { + if (x.source_frame) + return x.source_frame; + if (x.document) + return x.document.defaultView; + return null; +} + +function load_spec_uri_string(x) { + if (typeof(x) == "string") + return x; + if (x.uri) + return x.uri; + if (x.document) + return x.document.documentURI; + return null; +} + +function load_spec_uri(x) { + if (x.document) + return x.document.documentURIObject; + return make_uri(load_spec_uri_string(x)); +} + +function load_spec_flags(x) { + return x.load_spec_flags; +} + +function load_spec_mime_info(x) { + var type = load_spec_mime_type(x); + return mime_info_from_mime_type(type); +} + +function load_spec_default_shell_command(x) { + var mime_type = load_spec_mime_type(x); + return get_external_handler_for_mime_type(mime_type); +} + +/* Target can be either a content_buffer or an nsIWebNavigation */ +function apply_load_spec(target, spec) { + var uri = load_spec_uri_string(spec); + var flags = load_spec_flags(spec); + var referrer = load_spec_referrer(spec); + var post_data = load_spec_post_data(spec); + + if (flags == null) + flags = Ci.nsIWebNavigation.LOAD_FLAGS_NONE; + + if (target instanceof content_buffer) { + target._display_URI = uri; + target = target.web_navigation; + //buffer_description_change_hook.run(target); + } + target.loadURI(uri, flags, referrer, post_data, null /* headers */); +} diff --git a/modules/media.js b/modules/media.js dissimilarity index 61% index 0dd233b..648ded0 100644 --- a/modules/media.js +++ b/modules/media.js @@ -1,41 +1,17 @@ -/** - * This module provides convenient facilities for automatically finding embedded media, - * like videos and even flash videos. It is based on code taken from the Flash Video Download - * firefox extension. - */ - - - -function media_spec() {} - -function media_spec_simple_uri(uri, title, filename, frame, mime_type) { - this.uri = uri; - this.title = title; - this.filename = filename; - this.frame = frame; - this.mime_type = mime_type; -} -media_spec_simple_uri.prototype = { - __proto__: media_spec.prototype -} - - - - -function media_scrape(buffer) { - var scraper = buffer.get("media_scraper"); - var arr = []; - if (scraper) - scraper(buffer, arr); - return arr; -} - - -function media_setup_local_object_classes(buffer) { - buffer.local_variables.hints_default_object_classes = { - __proto__: hints_default_object_classes, - save: "media", - shell_command: "media", - shell_command_url: "media" - }; -} + +function media_scrape(buffer) { + var scraper = buffer.get("media_scraper"); + if (scraper) + return scraper(buffer); + return null; +} + + +function media_setup_local_object_classes(buffer) { + buffer.local_variables.hints_default_object_classes = { + __proto__: hints_default_object_classes, + save: "media", + shell_command: "media", + shell_command_url: "media" + }; +} diff --git a/modules/page-modes/google-video.js b/modules/page-modes/google-video.js index 2cdc255..b611f8b 100644 --- a/modules/page-modes/google-video.js +++ b/modules/page-modes/google-video.js @@ -1,12 +1,11 @@ require("content-buffer.js"); require("media.js"); -function media_scrape_google_video(buffer, results) { +function media_scrape_google_video(buffer) { var doc = buffer.top_document; try { - let title = doc.title; let frame_doc = buffer.top_frame.frames[0].document; let mime_type; let ext; @@ -29,15 +28,18 @@ function media_scrape_google_video(buffer, results) { ext = "flv"; mime_type = "video/x-flv"; } else - return; - let filename = title.replace(/^\s+|\s+$/g, ""); - filename = generate_filename_safely_fn(title) + "." + ext; - results.push(new media_spec_simple_uri(target_uri, title, filename, buffer.top_frame, mime_type)); + return null; + return [load_spec({uri: target_uri, + title: doc.title, + filename_extension: ext, + source_frame: buffer.top_frame, + mime_type: mime_type})]; } catch (e if !(e instanceof interactive_error)) {} + return null; } -define_page_mode("google_video_mode", "GoogleVideo", $enable = function (buffer) { +define_page_mode("google_video_mode", "Google Video", $enable = function (buffer) { buffer.local_variables.media_scraper = media_scrape_google_video; media_setup_local_object_classes(buffer); }); diff --git a/modules/page-modes/youtube.js b/modules/page-modes/youtube.js index f8e8136..fea4d72 100644 --- a/modules/page-modes/youtube.js +++ b/modules/page-modes/youtube.js @@ -4,7 +4,7 @@ require("media.js"); const media_youtube_content_key_regexp = /t=[\w-]{10,}/i; const media_youtube_uri_test_regexp = /^http:\/\/youtube\.com\/watch\?v=([A-Za-z0-9\-]+)/; -function media_scrape_youtube(buffer, results) { +function media_scrape_youtube(buffer) { try { var uri = buffer.current_URI.spec; @@ -19,15 +19,15 @@ function media_scrape_youtube(buffer, results) { let code = result[1]; let res = media_youtube_content_key_regexp.exec(text); if (res) { - let key = res[0]; - let target_uri = 'http://youtube.com/get_video?video_id=' + code + '&' + key; - let title_str = title.stringValue; - let filename = title_str.replace(/^\s+|\s+$/g, ""); - filename = generate_filename_safely_fn(title_str) + ".flv"; - results.push(new media_spec_simple_uri(target_uri, title_str, filename, buffer.top_frame, "video/x-flv")); + return [load_spec({uri: 'http://youtube.com/get_video?video_id=' + code + '&' + res[0], + title: title.stringValue, + filename_extension: "flv", + source_frame: buffer.top_frame, + mime_type: "video/x-flv"})]; } } } catch (e if !(e instanceof interactive_error)) {} + return null; } define_page_mode("youtube_mode", "YouTube", $enable = function (buffer) { diff --git a/modules/save.js b/modules/save.js index e04d1f1..51d5a6d 100644 --- a/modules/save.js +++ b/modules/save.js @@ -4,7 +4,7 @@ require("suggest-file-name.js"); /* buffer is used only to associate with the download */ define_keywords("$use_cache", "$buffer", "$prepare_download"); -function save_uri(load_spec, output_file) { +function save_uri(lspec, output_file) { keywords(arguments, $use_cache = false); var use_cache = arguments.$use_cache; @@ -14,18 +14,11 @@ function save_uri(load_spec, output_file) { var prepare_download = arguments.$prepare_download; var cache_key = null; - var post_data = null; - var uri = null; - var referrer_uri = null; - if (typeof(load_spec) == "string") { - uri = make_uri(load_spec); - } else { - uri = make_uri(load_spec.url); - referrer_uri = load_spec.referrer; - post_data = load_spec.post_data; - if (use_cache) - cache_key = load_spec.cache_key; - } + var uri = load_spec_uri(lspec); + var referrer_uri = load_spec_referrer(lspec); + var post_data = load_spec_post_data(lspec); + if (use_cache) + cache_key = load_spec_cache_key(lspec); var file_uri = makeFileURL(output_file); @@ -47,7 +40,7 @@ function save_uri(load_spec, output_file) { var tr = Cc["@mozilla.org/transfer;1"].createInstance(Ci.nsITransfer); tr.init(uri, file_uri, output_file.leafName, - mime_info_from_load_spec(load_spec), + load_spec_mime_info(lspec), null /* start time */, null /* temp file */, persist); @@ -201,14 +194,14 @@ download_failed_error.prototype.__proto__ = Error.prototype; * done with it. */ define_keywords("$action", "$shell_command", "$shell_command_cwd", "$buffer", "$use_cache"); -function download_as_temporary(load_spec) { +function download_as_temporary(lspec) { keywords(arguments, $use_cache = true); var action_description = arguments.$action; var shell_command = arguments.$shell_command; var shell_command_cwd = arguments.$shell_command_cwd; - var uri = uri_from_load_spec(load_spec); + var uri = load_spec_uri(lspec); // If it is local file, there is no need to download it if (uri.scheme == "file") { @@ -218,7 +211,7 @@ function download_as_temporary(load_spec) { } - var file = get_temporary_file(suggest_file_name(load_spec)); + var file = get_temporary_file(suggest_file_name(lspec)); var cc = yield CONTINUATION; @@ -240,7 +233,7 @@ function download_as_temporary(load_spec) { } } - save_uri(load_spec, file, + save_uri(lspec, file, $use_cache = arguments.$use_cache, $buffer = arguments.$buffer, $prepare_download = function (info) { diff --git a/modules/suggest-file-name.js b/modules/suggest-file-name.js index cf5e328..e071f98 100644 --- a/modules/suggest-file-name.js +++ b/modules/suggest-file-name.js @@ -83,7 +83,7 @@ function maybe_get_preferred_url_extension (url_o, content_type) { return ext; } -function getDefaultExtension (file_name_s, url_o, content_type) { +function get_default_extension (file_name_s, url_o, content_type) { if (content_type == "text/plain" || content_type == "application/octet-stream" || url_o.scheme == "ftp") @@ -94,7 +94,7 @@ function getDefaultExtension (file_name_s, url_o, content_type) { maybe_get_preferred_url_extension (url_o, content_type)); } -function getCharsetforSave(aDocument) +function get_charset_for_save(aDocument) { if (aDocument) return aDocument.characterSet; @@ -124,13 +124,12 @@ function maybe_filename_from_content_disposition (aContentDisposition, charset) return null; } -function maybe_filename_from_url (aURI) { +function maybe_filename_from_uri(uri) { try { var url = aURI.QueryInterface(Components.interfaces.nsIURL); if (url.fileName != "") { // 2) Use the actual file name, if present - var textToSubURI = Components.classes["@mozilla.org/intl/texttosuburi;1"] - .getService(Components.interfaces.nsITextToSubURI); + var textToSubURI = Cc["@mozilla.org/intl/texttosuburi;1"].getService(Ci.nsITextToSubURI); return textToSubURI.unEscapeURIForUI(url.originCharset || "UTF-8", url.fileName); } } catch (e) { @@ -139,10 +138,10 @@ function maybe_filename_from_url (aURI) { return null; } -function maybe_filename_from_document_title (aDocument) { - if (aDocument) { - var docTitle = aDocument.title.replace(/^\s+|\s+$/g, ""); - if (docTitle) { +function maybe_filename_from_title(title) { + if (title) { + var docTitle = title.replace(/^\s+|\s+$/g, ""); + if (docTitle && docTitle.length > 0) { // 3) Use the document title return docTitle; } @@ -209,64 +208,6 @@ default: break; } - - -function getDefaultFileName (aURI, aDocument) { - return generate_filename_safely_fn - (maybe_filename_from_content_disposition(aDocument && get_document_content_disposition(aDocument), - getCharsetforSave(aDocument)) || - maybe_filename_from_url (aURI) || - maybe_filename_from_document_title (aDocument) || - maybe_filename_from_url_last_directory (aURI) || - maybe_filename_from_url_host (aURI) || - maybe_filename_from_localization_default () || - "index"); -} - -/** - * Determine what the 'default' path is for operations like save-page. - * Returns an nsILocalFile. - * @param url_o nsIURI of the document being saved. - * @param aDocument The document to be saved - * @param aContentType The content type we're saving, if it could be - * determined by the caller. - * @param aContentDisposition The content-disposition header for the object - * we're saving, if it could be determined by the caller. - * @param dest_extension_s To override the extension of the destination file, - * pass the extension you want here. Otherwise pass null. This is - * used by save_page_as_text. - */ -function suggest_file_name_internal(url, aDocument, aContentType, dest_extension_s) -{ - url = make_uri(url); - - var file_ext_s; - var file_base_name_s; - - file_ext_s = maybe_get_url_extension (url); - - // Get the default filename: - var file_name_s = getDefaultFileName(url, aDocument); - - // If file_ext_s is still blank, and url is a web link (http or - // https), make the extension `.html'. - if (! file_ext_s && !aDocument && !aContentType && (/^http(s?)/i.test(url.scheme))) { - file_ext_s = "html"; - file_base_name_s = file_name_s; - } else { - file_ext_s = getDefaultExtension(file_name_s, url, aContentType); - // related to temporary fix for bug 120327 in getDefaultExtension - if (file_ext_s == "") - file_ext_s = file_name_s.replace (/^.*?\.(?=[^.]*$)/, ""); - file_base_name_s = file_name_s.replace (/\.[^.]*$/, ""); - } - - if (dest_extension_s) - file_ext_s = dest_extension_s; - - return file_base_name_s +'.'+ file_ext_s; -} - /** * spec may be a string (URI), a load spec, or an nsIDOMDocument * @@ -276,22 +217,44 @@ function suggest_file_name(spec, extension) { var document; var uri; var content_type; - if (spec.filename) - return spec.filename; if (spec instanceof Ci.nsIDOMDocument) - document = spec; - else if (typeof(load_spec) == "object" && load_spec.document) - document = spec.document; - else - uri = uri_from_load_spec(spec); + spec = {document: spec}; + + var file_name = load_spec_filename(spec); + + document = load_spec_document(spec); + uri = load_spec_uri(spec); + content_type = load_spec_mime_type(spec); + + if (!file_name) { + file_name = generate_filename_safely_fn( + maybe_filename_from_content_disposition(document && get_document_content_disposition(document), + get_charset_for_save(document)) || + maybe_filename_from_uri(uri) || + maybe_filename_from_title(load_spec_title(spec)) || + maybe_filename_from_url_last_directory(uri) || + maybe_filename_from_url_host(uri) || + maybe_filename_from_localization_default() || + "index"); - if (document) { - uri = document.documentURIObject; - content_type = document.contentType; } + var base_name = file_name.replace(/\.[^.]*$/, ""); + + var file_ext = extension || load_spec_filename_extension(spec); - return suggest_file_name_internal(uri, document, content_type, extension); + if (!file_ext) { + file_ext = get_default_extension(file_name, uri, content_type); + if (file_ext == "") + file_ext = file_name.replace (/^.*?\.(?=[^.]*$)/, ""); + if (!file_ext && (/^http(s?)/i).test(url.scheme) && !content_type) + file_ext = "html"; + } + + if (file_ext != null && file_ext.length > 0) + return base_name + "." + file_ext; + else + return base_name; } function suggest_save_path_from_file_name(file_name, buffer) { -- 2.11.4.GIT