Thu, 15 Jan 2015 21:03:48 +0100
Integrate friendly tips from Tor colleagues to make (or not) 4.5 alpha 3;
This includes removal of overloaded (but unused) methods, and addition of
a overlooked call to DataStruct::SetData(nsISupports, uint32_t, bool.)
michael@0 | 1 | /* This Source Code Form is subject to the terms of the Mozilla Public |
michael@0 | 2 | * License, v. 2.0. If a copy of the MPL was not distributed with this |
michael@0 | 3 | * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ |
michael@0 | 4 | |
michael@0 | 5 | Components.utils.import("resource://gre/modules/XPCOMUtils.jsm"); |
michael@0 | 6 | |
michael@0 | 7 | const Cc = Components.classes; |
michael@0 | 8 | const Ci = Components.interfaces; |
michael@0 | 9 | |
michael@0 | 10 | // This component is used for handling dragover and drop of urls. |
michael@0 | 11 | // |
michael@0 | 12 | // It checks to see whether a drop of a url is allowed. For instance, a url |
michael@0 | 13 | // cannot be dropped if it is not a valid uri or the source of the drag cannot |
michael@0 | 14 | // access the uri. This prevents, for example, a source document from tricking |
michael@0 | 15 | // the user into dragging a chrome url. |
michael@0 | 16 | |
michael@0 | 17 | function ContentAreaDropListener() { }; |
michael@0 | 18 | |
michael@0 | 19 | ContentAreaDropListener.prototype = |
michael@0 | 20 | { |
michael@0 | 21 | classID: Components.ID("{1f34bc80-1bc7-11d6-a384-d705dd0746fc}"), |
michael@0 | 22 | QueryInterface: XPCOMUtils.generateQI([Ci.nsIDroppedLinkHandler, Ci.nsISupports]), |
michael@0 | 23 | |
michael@0 | 24 | _getDropURL : function (dt) |
michael@0 | 25 | { |
michael@0 | 26 | let types = dt.types; |
michael@0 | 27 | for (let t = 0; t < types.length; t++) { |
michael@0 | 28 | let type = types[t]; |
michael@0 | 29 | switch (type) { |
michael@0 | 30 | case "text/uri-list": |
michael@0 | 31 | var url = dt.getData("URL").replace(/^\s+|\s+$/g, ""); |
michael@0 | 32 | return [url, url]; |
michael@0 | 33 | case "text/plain": |
michael@0 | 34 | case "text/x-moz-text-internal": |
michael@0 | 35 | var url = dt.getData(type).replace(/^\s+|\s+$/g, ""); |
michael@0 | 36 | return [url, url]; |
michael@0 | 37 | case "text/x-moz-url": |
michael@0 | 38 | return dt.getData(type).split("\n"); |
michael@0 | 39 | } |
michael@0 | 40 | } |
michael@0 | 41 | |
michael@0 | 42 | // For shortcuts, we want to check for the file type last, so that the |
michael@0 | 43 | // url pointed to in one of the url types is found first before the file |
michael@0 | 44 | // type, which points to the actual file. |
michael@0 | 45 | let file = dt.mozGetDataAt("application/x-moz-file", 0); |
michael@0 | 46 | if (file instanceof Ci.nsIFile) { |
michael@0 | 47 | let ioService = Cc["@mozilla.org/network/io-service;1"]. |
michael@0 | 48 | getService(Ci.nsIIOService); |
michael@0 | 49 | let fileHandler = ioService.getProtocolHandler("file") |
michael@0 | 50 | .QueryInterface(Ci.nsIFileProtocolHandler); |
michael@0 | 51 | return [fileHandler.getURLSpecFromFile(file), file.leafName]; |
michael@0 | 52 | } |
michael@0 | 53 | |
michael@0 | 54 | return [ ]; |
michael@0 | 55 | }, |
michael@0 | 56 | |
michael@0 | 57 | _validateURI: function(dataTransfer, uriString, disallowInherit) |
michael@0 | 58 | { |
michael@0 | 59 | if (!uriString) |
michael@0 | 60 | return ""; |
michael@0 | 61 | |
michael@0 | 62 | // Strip leading and trailing whitespace, then try to create a |
michael@0 | 63 | // URI from the dropped string. If that succeeds, we're |
michael@0 | 64 | // dropping a URI and we need to do a security check to make |
michael@0 | 65 | // sure the source document can load the dropped URI. |
michael@0 | 66 | uriString = uriString.replace(/^\s*|\s*$/g, ''); |
michael@0 | 67 | |
michael@0 | 68 | let uri; |
michael@0 | 69 | let ioService = Cc["@mozilla.org/network/io-service;1"] |
michael@0 | 70 | .getService(Components.interfaces.nsIIOService); |
michael@0 | 71 | try { |
michael@0 | 72 | // Check that the uri is valid first and return an empty string if not. |
michael@0 | 73 | // It may just be plain text and should be ignored here |
michael@0 | 74 | uri = ioService.newURI(uriString, null, null); |
michael@0 | 75 | } catch (ex) { } |
michael@0 | 76 | if (!uri) |
michael@0 | 77 | return uriString; |
michael@0 | 78 | |
michael@0 | 79 | // uriString is a valid URI, so do the security check. |
michael@0 | 80 | let secMan = Cc["@mozilla.org/scriptsecuritymanager;1"]. |
michael@0 | 81 | getService(Ci.nsIScriptSecurityManager); |
michael@0 | 82 | let sourceNode = dataTransfer.mozSourceNode; |
michael@0 | 83 | let flags = secMan.STANDARD; |
michael@0 | 84 | if (disallowInherit) |
michael@0 | 85 | flags |= secMan.DISALLOW_INHERIT_PRINCIPAL; |
michael@0 | 86 | |
michael@0 | 87 | // Use file:/// as the default uri so that drops of file URIs are always allowed |
michael@0 | 88 | let principal = sourceNode ? sourceNode.nodePrincipal |
michael@0 | 89 | : secMan.getSimpleCodebasePrincipal(ioService.newURI("file:///", null, null)); |
michael@0 | 90 | |
michael@0 | 91 | secMan.checkLoadURIStrWithPrincipal(principal, uriString, flags); |
michael@0 | 92 | |
michael@0 | 93 | return uriString; |
michael@0 | 94 | }, |
michael@0 | 95 | |
michael@0 | 96 | canDropLink: function(aEvent, aAllowSameDocument) |
michael@0 | 97 | { |
michael@0 | 98 | if (this._eventTargetIsDisabled(aEvent)) |
michael@0 | 99 | return false; |
michael@0 | 100 | |
michael@0 | 101 | let dataTransfer = aEvent.dataTransfer; |
michael@0 | 102 | let types = dataTransfer.types; |
michael@0 | 103 | if (!types.contains("application/x-moz-file") && |
michael@0 | 104 | !types.contains("text/x-moz-url") && |
michael@0 | 105 | !types.contains("text/uri-list") && |
michael@0 | 106 | !types.contains("text/x-moz-text-internal") && |
michael@0 | 107 | !types.contains("text/plain")) |
michael@0 | 108 | return false; |
michael@0 | 109 | |
michael@0 | 110 | if (aAllowSameDocument) |
michael@0 | 111 | return true; |
michael@0 | 112 | |
michael@0 | 113 | let sourceNode = dataTransfer.mozSourceNode; |
michael@0 | 114 | if (!sourceNode) |
michael@0 | 115 | return true; |
michael@0 | 116 | |
michael@0 | 117 | // don't allow a drop of a node from the same document onto this one |
michael@0 | 118 | let sourceDocument = sourceNode.ownerDocument; |
michael@0 | 119 | let eventDocument = aEvent.originalTarget.ownerDocument; |
michael@0 | 120 | if (sourceDocument == eventDocument) |
michael@0 | 121 | return false; |
michael@0 | 122 | |
michael@0 | 123 | // also check for nodes in other child or sibling frames by checking |
michael@0 | 124 | // if both have the same top window. |
michael@0 | 125 | if (sourceDocument && eventDocument) { |
michael@0 | 126 | let sourceRoot = sourceDocument.defaultView.top; |
michael@0 | 127 | if (sourceRoot && sourceRoot == eventDocument.defaultView.top) |
michael@0 | 128 | return false; |
michael@0 | 129 | } |
michael@0 | 130 | |
michael@0 | 131 | return true; |
michael@0 | 132 | }, |
michael@0 | 133 | |
michael@0 | 134 | dropLink: function(aEvent, aName, aDisallowInherit) |
michael@0 | 135 | { |
michael@0 | 136 | aName.value = ""; |
michael@0 | 137 | if (this._eventTargetIsDisabled(aEvent)) |
michael@0 | 138 | return ""; |
michael@0 | 139 | |
michael@0 | 140 | let dataTransfer = aEvent.dataTransfer; |
michael@0 | 141 | let [url, name] = this._getDropURL(dataTransfer); |
michael@0 | 142 | |
michael@0 | 143 | try { |
michael@0 | 144 | url = this._validateURI(dataTransfer, url, aDisallowInherit); |
michael@0 | 145 | } catch (ex) { |
michael@0 | 146 | aEvent.stopPropagation(); |
michael@0 | 147 | aEvent.preventDefault(); |
michael@0 | 148 | throw ex; |
michael@0 | 149 | } |
michael@0 | 150 | |
michael@0 | 151 | if (name) |
michael@0 | 152 | aName.value = name; |
michael@0 | 153 | |
michael@0 | 154 | return url; |
michael@0 | 155 | }, |
michael@0 | 156 | |
michael@0 | 157 | _eventTargetIsDisabled: function(aEvent) |
michael@0 | 158 | { |
michael@0 | 159 | let ownerDoc = aEvent.originalTarget.ownerDocument; |
michael@0 | 160 | if (!ownerDoc || !ownerDoc.defaultView) |
michael@0 | 161 | return false; |
michael@0 | 162 | |
michael@0 | 163 | return ownerDoc.defaultView |
michael@0 | 164 | .QueryInterface(Components.interfaces.nsIInterfaceRequestor) |
michael@0 | 165 | .getInterface(Components.interfaces.nsIDOMWindowUtils) |
michael@0 | 166 | .isNodeDisabledForEvents(aEvent.originalTarget); |
michael@0 | 167 | } |
michael@0 | 168 | }; |
michael@0 | 169 | |
michael@0 | 170 | var components = [ContentAreaDropListener]; |
michael@0 | 171 | this.NSGetFactory = XPCOMUtils.generateNSGetFactory(components); |