diff options
Diffstat (limited to 'toolkit/content')
-rw-r--r-- | toolkit/content/dialogOverlay.js | 107 | ||||
-rw-r--r-- | toolkit/content/dialogOverlay.xul | 101 | ||||
-rw-r--r-- | toolkit/content/globalOverlay.xul | 38 | ||||
-rw-r--r-- | toolkit/content/inlineSpellCheckUI.js | 7 | ||||
-rw-r--r-- | toolkit/content/jar.mn | 8 | ||||
-rw-r--r-- | toolkit/content/nsClipboard.js | 64 | ||||
-rw-r--r-- | toolkit/content/nsDragAndDrop.js | 604 | ||||
-rw-r--r-- | toolkit/content/nsUserSettings.js | 108 | ||||
-rw-r--r-- | toolkit/content/strres.js | 28 |
9 files changed, 1065 insertions, 0 deletions
diff --git a/toolkit/content/dialogOverlay.js b/toolkit/content/dialogOverlay.js new file mode 100644 index 000000000..4b03f268f --- /dev/null +++ b/toolkit/content/dialogOverlay.js @@ -0,0 +1,107 @@ +/* This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ + +var doOKFunction = 0; +var doCancelFunction = 0; +var doButton2Function = 0; +var doButton3Function = 0; + +// call this from dialog onload() to allow ok and cancel to call your code +// functions should return true if they want the dialog to close +function doSetOKCancel(okFunc, cancelFunc, button2Func, button3Func ) +{ + //dump("top.window.navigator.platform: " + top.window.navigator.platform + "\n"); + + doOKFunction = okFunc; + doCancelFunction = cancelFunc; + doButton2Function = button2Func; + doButton3Function = button3Func; +} + +function doOKButton() +{ + var close = true; + + if ( doOKFunction ) + close = doOKFunction(); + + if (close && top) + top.window.close(); +} + +function doCancelButton() +{ + var close = true; + + if ( doCancelFunction ) + close = doCancelFunction(); + + if (close && top) + top.window.close(); +} + +function doButton2() +{ + var close = true; + + if ( doButton2Function ) + close = doButton2Function(); + + if (close && top) + top.window.close(); +} + +function doButton3() +{ + var close = true; + + if ( doButton3Function ) + close = doButton3Function(); + + if (close && top) + top.window.close(); +} + +function moveToAlertPosition() +{ + // hack. we need this so the window has something like its final size + if (window.outerWidth == 1) { + dump("Trying to position a sizeless window; caller should have called sizeToContent() or sizeTo(). See bug 75649.\n"); + sizeToContent(); + } + + if (opener) { + var xOffset = (opener.outerWidth - window.outerWidth) / 2; + var yOffset = opener.outerHeight / 5; + + var newX = opener.screenX + xOffset; + var newY = opener.screenY + yOffset; + } else { + newX = (screen.availWidth - window.outerWidth) / 2; + newY = (screen.availHeight - window.outerHeight) / 2; + } + + // ensure the window is fully onscreen (if smaller than the screen) + if (newX < screen.availLeft) + newX = screen.availLeft + 20; + if ((newX + window.outerWidth) > (screen.availLeft + screen.availWidth)) + newX = (screen.availLeft + screen.availWidth) - window.outerWidth - 20; + + if (newY < screen.availTop) + newY = screen.availTop + 20; + if ((newY + window.outerHeight) > (screen.availTop + screen.availHeight)) + newY = (screen.availTop + screen.availHeight) - window.outerHeight - 60; + + window.moveTo( newX, newY ); +} + +function centerWindowOnScreen() +{ + var xOffset = screen.availWidth/2 - window.outerWidth/2; + var yOffset = screen.availHeight/2 - window.outerHeight/2; //(opener.outerHeight *2)/10; + + xOffset = ( xOffset > 0 ) ? xOffset : 0; + yOffset = ( yOffset > 0 ) ? yOffset : 0; + window.moveTo( xOffset, yOffset); +} diff --git a/toolkit/content/dialogOverlay.xul b/toolkit/content/dialogOverlay.xul new file mode 100644 index 000000000..09e00613e --- /dev/null +++ b/toolkit/content/dialogOverlay.xul @@ -0,0 +1,101 @@ +<?xml version="1.0"?> +# -*- Mode: HTML -*- +# This Source Code Form is subject to the terms of the Mozilla Public +# License, v. 2.0. If a copy of the MPL was not distributed with this +# file, You can obtain one at http://mozilla.org/MPL/2.0/. +# +# WARNING!!! This file is obsoleted by the dialog.xml widget +# + +<!DOCTYPE overlay SYSTEM "chrome://global/locale/dialogOverlay.dtd"> + +<overlay id="dialogOverlay" + xmlns="http://www.mozilla.org/keymaster/gatekeeper/there.is.only.xul"> + + <script type="application/javascript" src="chrome://global/content/dialogOverlay.js"/> + +#ifdef XP_MACOSX +# + <hbox id="okCancelButtons"> + <spacer flex="1"/> + <button class="exit-dialog" id="Button3" label="" collapsed="true" oncommand="doButton3();"/> + <button class="exit-dialog" id="Button2" label="" collapsed="true" oncommand="doButton2();"/> + <button class="exit-dialog" id="cancel" label="&cancelButton.label;" oncommand="doCancelButton();"/> + <button class="right exit-dialog" id="ok" default="true" label="&okButton.label;" oncommand="doOKButton();"/> + </hbox> + + <hbox id="okCancelHelpButtons"> + <button class="exit-dialog" id="help" label="&helpButton.label;" oncommand="doHelpButton();"/> + <spacer flex="1"/> + <button class="exit-dialog" id="Button3" label="" collapsed="true" oncommand="doButton3();"/> + <button class="exit-dialog" id="Button2" label="" collapsed="true" oncommand="doButton2();"/> + <button class="exit-dialog" id="cancel" label="&cancelButton.label;" oncommand="doCancelButton();"/> + <button class="right exit-dialog" id="ok" default="true" label="&okButton.label;" oncommand="doOKButton();"/> + </hbox> + + <hbox id="okCancelButtonsRight"> + <spacer flex="1"/> + <button class="exit-dialog" id="Button3" label="" collapsed="true" oncommand="doButton3();"/> + <button class="exit-dialog" id="Button2" label="" collapsed="true" oncommand="doButton2();"/> + <button class="exit-dialog" id="cancel" label="&cancelButton.label;" oncommand="doCancelButton();"/> + <button class="right exit-dialog" id="ok" default="true" label="&okButton.label;" oncommand="doOKButton();"/> + </hbox> + + <hbox id="okCancelHelpButtonsRight"> + <button class="exit-dialog" id="help" label="&helpButton.label;" oncommand="doHelpButton();"/> + <spacer flex="1"/> + <button class="exit-dialog" id="Button3" label="" collapsed="true" oncommand="doButton3();"/> + <button class="exit-dialog" id="Button2" label="" collapsed="true" oncommand="doButton2();"/> + <button class="exit-dialog" id="cancel" label="&cancelButton.label;" oncommand="doCancelButton();"/> + <button class="right exit-dialog" id="ok" default="true" label="&okButton.label;" oncommand="doOKButton();"/> + </hbox> +# +#else +# + <hbox id="okCancelButtons"> + <spacer flex="1"/> + <button class="right exit-dialog" id="ok" label="&okButton.label;" default="true" oncommand="doOKButton();"/> + <button class="exit-dialog" id="Button2" label="&cancelButton.label;" collapsed="true" oncommand="doButton2();"/> + <button class="exit-dialog" id="Button3" label="&cancelButton.label;" collapsed="true" oncommand="doButton3();"/> + <button class="exit-dialog" id="cancel" label="&cancelButton.label;" oncommand="doCancelButton();"/> + <spacer flex="1"/> + </hbox> + + <hbox id="okCancelHelpButtons"> + <spacer flex="1"/> + <button class="right exit-dialog" id="ok" label="&okButton.label;" default="true" oncommand="doOKButton();"/> + <button class="exit-dialog" id="Button2" label="&cancelButton.label;" collapsed="true" oncommand="doButton2();"/> + <button class="exit-dialog" id="Button3" label="&cancelButton.label;" collapsed="true" oncommand="doButton3();"/> + <button class="exit-dialog" id="cancel" label="&cancelButton.label;" oncommand="doCancelButton();"/> + <button class="exit-dialog" id="help" label="&helpButton.label;" oncommand="doHelpButton();"/> + <spacer flex="1"/> + </hbox> + + <hbox id="okCancelButtonsRight"> + <spacer flex="1"/> + <button class="right exit-dialog" id="ok" label="&okButton.label;" default="true" oncommand="doOKButton();"/> + <button class="exit-dialog" id="Button2" label="&cancelButton.label;" collapsed="true" oncommand="doButton2();"/> + <button class="exit-dialog" id="Button3" label="&cancelButton.label;" collapsed="true" oncommand="doButton3();"/> + <button class="exit-dialog" id="cancel" label="&cancelButton.label;" oncommand="doCancelButton();"/> + </hbox> + + <hbox id="okCancelHelpButtonsRight"> + <spacer flex="1"/> + <button class="right exit-dialog" id="ok" label="&okButton.label;" default="true" oncommand="doOKButton();"/> + <button class="exit-dialog" id="Button2" label="&cancelButton.label;" collapsed="true" oncommand="doButton2();"/> + <button class="exit-dialog" id="Button3" label="&cancelButton.label;" collapsed="true" oncommand="doButton3();"/> + <button class="exit-dialog" id="cancel" label="&cancelButton.label;" oncommand="doCancelButton();"/> + <button class="exit-dialog" id="help" label="&helpButton.label;" oncommand="doHelpButton();"/> + </hbox> +#endif + + <keyset id="dialogKeys"> + <key keycode="VK_RETURN" oncommand="if (!document.getElementById('ok').disabled) doOKButton();"/> + <key keycode="VK_ESCAPE" oncommand="doCancelButton();"/> +#ifdef XP_MACOSX + <key key="." modifiers="meta" oncommand="doCancelButton();"/> +# +#endif + </keyset> + +</overlay> diff --git a/toolkit/content/globalOverlay.xul b/toolkit/content/globalOverlay.xul new file mode 100644 index 000000000..90268a8e4 --- /dev/null +++ b/toolkit/content/globalOverlay.xul @@ -0,0 +1,38 @@ +<?xml version="1.0"?> +<!-- This Source Code Form is subject to the terms of the Mozilla Public + - License, v. 2.0. If a copy of the MPL was not distributed with this + - file, You can obtain one at http://mozilla.org/MPL/2.0/. --> + + +<overlay id="globalOverlay" + xmlns="http://www.mozilla.org/keymaster/gatekeeper/there.is.only.xul"> + + <script type="application/javascript" src="chrome://global/content/globalOverlay.js"/> + <script type="application/javascript"><![CDATA[ + + function FillInTooltip ( tipElement ) + { + var retVal = false; + var textNode = document.getElementById("TOOLTIP-tooltipText"); + if (textNode) { + while (textNode.hasChildNodes()) + textNode.removeChild(textNode.firstChild); + var tipText = tipElement.getAttribute("tooltiptext"); + if (tipText) { + var node = document.createTextNode(tipText); + textNode.appendChild(node); + retVal = true; + } + } + return retVal; + } + + ]]></script> + + <popupset id="aTooltipSet"> + <tooltip id="aTooltip" class="tooltip" onpopupshowing="return FillInTooltip(document.tooltipNode);"> + <label id="TOOLTIP-tooltipText" class="tooltip-label" flex="1"/> + </tooltip> + </popupset> + +</overlay> diff --git a/toolkit/content/inlineSpellCheckUI.js b/toolkit/content/inlineSpellCheckUI.js new file mode 100644 index 000000000..177ce90cd --- /dev/null +++ b/toolkit/content/inlineSpellCheckUI.js @@ -0,0 +1,7 @@ +/* This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ + +Components.utils.import("resource://gre/modules/InlineSpellChecker.jsm"); + +var InlineSpellCheckerUI = new InlineSpellChecker(); diff --git a/toolkit/content/jar.mn b/toolkit/content/jar.mn index 590356b64..b4eec241c 100644 --- a/toolkit/content/jar.mn +++ b/toolkit/content/jar.mn @@ -65,6 +65,14 @@ toolkit.jar: content/global/timepicker.xhtml content/global/treeUtils.js content/global/viewZoomOverlay.js + content/global/globalOverlay.xul +* content/global/dialogOverlay.xul + content/global/dialogOverlay.js + content/global/inlineSpellCheckUI.js + content/global/nsClipboard.js + content/global/nsDragAndDrop.js + content/global/nsUserSettings.js + content/global/strres.js content/global/bindings/autocomplete.xml (widgets/autocomplete.xml) content/global/bindings/browser.xml (widgets/browser.xml) content/global/bindings/button.xml (widgets/button.xml) diff --git a/toolkit/content/nsClipboard.js b/toolkit/content/nsClipboard.js new file mode 100644 index 000000000..d9f7c4589 --- /dev/null +++ b/toolkit/content/nsClipboard.js @@ -0,0 +1,64 @@ +/* -*- indent-tabs-mode: nil; js-indent-level: 2 -*- */ +/* This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ + +/** + * nsClipboard - wrapper around nsIClipboard and nsITransferable + * that simplifies access to the clipboard. + **/ +var nsClipboard = { + _CB: null, + get mClipboard() + { + if (!this._CB) + { + const kCBContractID = "@mozilla.org/widget/clipboard;1"; + const kCBIID = Components.interfaces.nsIClipboard; + this._CB = Components.classes[kCBContractID].getService(kCBIID); + } + return this._CB; + }, + + currentClipboard: null, + /** + * Array/Object read (Object aFlavourList, long aClipboard, Bool aAnyFlag) ; + * + * returns the data in the clipboard + * + * @param FlavourSet aFlavourSet + * formatted list of desired flavours + * @param long aClipboard + * the clipboard to read data from (kSelectionClipboard/kGlobalClipboard) + * @param Bool aAnyFlag + * should be false. + **/ + read: function (aFlavourList, aClipboard, aAnyFlag) + { + this.currentClipboard = aClipboard; + var data = nsTransferable.get(aFlavourList, this.getClipboardTransferable, aAnyFlag); + return data.first.first; // only support one item + }, + + /** + * nsISupportsArray getClipboardTransferable (Object aFlavourList) ; + * + * returns a nsISupportsArray of the item on the clipboard + * + * @param Object aFlavourList + * formatted list of desired flavours. + **/ + getClipboardTransferable: function (aFlavourList) + { + const supportsContractID = "@mozilla.org/supports-array;1"; + const supportsIID = Components.interfaces.nsISupportsArray; + var supportsArray = Components.classes[supportsContractID].createInstance(supportsIID); + var trans = nsTransferable.createTransferable(); + for (var flavour in aFlavourList) + trans.addDataFlavor(flavour); + nsClipboard.mClipboard.getData(trans, nsClipboard.currentClipboard) + supportsArray.AppendElement(trans); + return supportsArray; + } +}; + diff --git a/toolkit/content/nsDragAndDrop.js b/toolkit/content/nsDragAndDrop.js new file mode 100644 index 000000000..40e96f9d1 --- /dev/null +++ b/toolkit/content/nsDragAndDrop.js @@ -0,0 +1,604 @@ +// -*- indent-tabs-mode: nil; js-indent-level: 2 -*- + +/* This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ + +//////////////////////////////////////////////////////////////////////// +// +// USE OF THIS API FOR DRAG AND DROP IS DEPRECATED! +// Do not use this file for new code. +// +// For documentation about what to use instead, see: +// http://developer.mozilla.org/En/DragDrop/Drag_and_Drop +// +//////////////////////////////////////////////////////////////////////// + + +/** + * nsTransferable - a wrapper for nsITransferable that simplifies + * javascript clipboard and drag&drop. for use in + * these situations you should use the nsClipboard + * and nsDragAndDrop wrappers for more convenience + **/ + +var nsTransferable = { + /** + * nsITransferable set (TransferData aTransferData) ; + * + * Creates a transferable with data for a list of supported types ("flavours") + * + * @param TransferData aTransferData + * a javascript object in the format described above + **/ + set: function (aTransferDataSet) + { + var trans = this.createTransferable(); + for (var i = 0; i < aTransferDataSet.dataList.length; ++i) + { + var currData = aTransferDataSet.dataList[i]; + var currFlavour = currData.flavour.contentType; + trans.addDataFlavor(currFlavour); + var supports = null; // nsISupports data + var length = 0; + if (currData.flavour.dataIIDKey == "nsISupportsString") + { + supports = Components.classes["@mozilla.org/supports-string;1"] + .createInstance(Components.interfaces.nsISupportsString); + + supports.data = currData.supports; + length = supports.data.length; + } + else + { + // non-string data. + supports = currData.supports; + length = 0; // kFlavorHasDataProvider + } + trans.setTransferData(currFlavour, supports, length * 2); + } + return trans; + }, + + /** + * TransferData/TransferDataSet get (FlavourSet aFlavourSet, + * Function aRetrievalFunc, Boolean aAnyFlag) ; + * + * Retrieves data from the transferable provided in aRetrievalFunc, formatted + * for more convenient access. + * + * @param FlavourSet aFlavourSet + * a FlavourSet object that contains a list of supported flavours. + * @param Function aRetrievalFunc + * a reference to a function that returns a nsISupportsArray of nsITransferables + * for each item from the specified source (clipboard/drag&drop etc) + * @param Boolean aAnyFlag + * a flag specifying whether or not a specific flavour is requested. If false, + * data of the type of the first flavour in the flavourlist parameter is returned, + * otherwise the best flavour supported will be returned. + **/ + get: function (aFlavourSet, aRetrievalFunc, aAnyFlag) + { + if (!aRetrievalFunc) + throw "No data retrieval handler provided!"; + + var supportsArray = aRetrievalFunc(aFlavourSet); + var dataArray = []; + var count = supportsArray.Count(); + + // Iterate over the number of items returned from aRetrievalFunc. For + // clipboard operations, this is 1, for drag and drop (where multiple + // items may have been dragged) this could be >1. + for (var i = 0; i < count; i++) + { + var trans = supportsArray.GetElementAt(i); + if (!trans) continue; + trans = trans.QueryInterface(Components.interfaces.nsITransferable); + + var data = { }; + var length = { }; + + var currData = null; + if (aAnyFlag) + { + var flavour = { }; + trans.getAnyTransferData(flavour, data, length); + if (data && flavour) + { + var selectedFlavour = aFlavourSet.flavourTable[flavour.value]; + if (selectedFlavour) + dataArray[i] = FlavourToXfer(data.value, length.value, selectedFlavour); + } + } + else + { + var firstFlavour = aFlavourSet.flavours[0]; + trans.getTransferData(firstFlavour, data, length); + if (data && firstFlavour) + dataArray[i] = FlavourToXfer(data.value, length.value, firstFlavour); + } + } + return new TransferDataSet(dataArray); + }, + + /** + * nsITransferable createTransferable (void) ; + * + * Creates and returns a transferable object. + **/ + createTransferable: function () + { + const kXferableContractID = "@mozilla.org/widget/transferable;1"; + const kXferableIID = Components.interfaces.nsITransferable; + var trans = Components.classes[kXferableContractID].createInstance(kXferableIID); + trans.init(null); + return trans; + } +}; + +/** + * A FlavourSet is a simple type that represents a collection of Flavour objects. + * FlavourSet is constructed from an array of Flavours, and stores this list as + * an array and a hashtable. The rationale for the dual storage is as follows: + * + * Array: Ordering is important when adding data flavours to a transferable. + * Flavours added first are deemed to be 'preferred' by the client. + * Hash: Convenient lookup of flavour data using the content type (MIME type) + * of data as a key. + */ +function FlavourSet(aFlavourList) +{ + this.flavours = aFlavourList || []; + this.flavourTable = { }; + + this._XferID = "FlavourSet"; + + for (var i = 0; i < this.flavours.length; ++i) + this.flavourTable[this.flavours[i].contentType] = this.flavours[i]; +} + +FlavourSet.prototype = { + appendFlavour: function (aFlavour, aFlavourIIDKey) + { + var flavour = new Flavour (aFlavour, aFlavourIIDKey); + this.flavours.push(flavour); + this.flavourTable[flavour.contentType] = flavour; + } +}; + +/** + * A Flavour is a simple type that represents a data type that can be handled. + * It takes a content type (MIME type) which is used when storing data on the + * system clipboard/drag and drop, and an IIDKey (string interface name + * which is used to QI data to an appropriate form. The default interface is + * assumed to be wide-string. + */ +function Flavour(aContentType, aDataIIDKey) +{ + this.contentType = aContentType; + this.dataIIDKey = aDataIIDKey || "nsISupportsString"; + + this._XferID = "Flavour"; +} + +function TransferDataBase() {} +TransferDataBase.prototype = { + push: function (aItems) + { + this.dataList.push(aItems); + }, + + get first () + { + return "dataList" in this && this.dataList.length ? this.dataList[0] : null; + } +}; + +/** + * TransferDataSet is a list (array) of TransferData objects, which represents + * data dragged from one or more elements. + */ +function TransferDataSet(aTransferDataList) +{ + this.dataList = aTransferDataList || []; + + this._XferID = "TransferDataSet"; +} +TransferDataSet.prototype = TransferDataBase.prototype; + +/** + * TransferData is a list (array) of FlavourData for all the applicable content + * types associated with a drag from a single item. + */ +function TransferData(aFlavourDataList) +{ + this.dataList = aFlavourDataList || []; + + this._XferID = "TransferData"; +} +TransferData.prototype = { + __proto__: TransferDataBase.prototype, + + addDataForFlavour: function (aFlavourString, aData, aLength, aDataIIDKey) + { + this.dataList.push(new FlavourData(aData, aLength, + new Flavour(aFlavourString, aDataIIDKey))); + } +}; + +/** + * FlavourData is a type that represents data retrieved from the system + * clipboard or drag and drop. It is constructed internally by the Transferable + * using the raw (nsISupports) data from the clipboard, the length of the data, + * and an object of type Flavour representing the type. Clients implementing + * IDragDropObserver receive an object of this type in their implementation of + * onDrop. They access the 'data' property to retrieve data, which is either data + * QI'ed to a usable form, or unicode string. + */ +function FlavourData(aData, aLength, aFlavour) +{ + this.supports = aData; + this.contentLength = aLength; + this.flavour = aFlavour || null; + + this._XferID = "FlavourData"; +} + +FlavourData.prototype = { + get data () + { + if (this.flavour && + this.flavour.dataIIDKey != "nsISupportsString") + return this.supports.QueryInterface(Components.interfaces[this.flavour.dataIIDKey]); + + var supports = this.supports; + if (supports instanceof Components.interfaces.nsISupportsString) + return supports.data.substring(0, this.contentLength/2); + + return supports; + } +} + +/** + * Create a TransferData object with a single FlavourData entry. Used when + * unwrapping data of a specific flavour from the drag service. + */ +function FlavourToXfer(aData, aLength, aFlavour) +{ + return new TransferData([new FlavourData(aData, aLength, aFlavour)]); +} + +var transferUtils = { + + retrieveURLFromData: function (aData, flavour) + { + switch (flavour) { + case "text/unicode": + case "text/plain": + case "text/x-moz-text-internal": + return aData.replace(/^\s+|\s+$/g, ""); + case "text/x-moz-url": + return ((aData instanceof Components.interfaces.nsISupportsString) ? aData.toString() : aData).split("\n")[0]; + case "application/x-moz-file": + var ioService = Components.classes["@mozilla.org/network/io-service;1"] + .getService(Components.interfaces.nsIIOService); + var fileHandler = ioService.getProtocolHandler("file") + .QueryInterface(Components.interfaces.nsIFileProtocolHandler); + return fileHandler.getURLSpecFromFile(aData); + } + return null; + } + +} + +/** + * nsDragAndDrop - a convenience wrapper for nsTransferable, nsITransferable + * and nsIDragService/nsIDragSession. + * + * Use: map the handler functions to the 'ondraggesture', 'ondragover' and + * 'ondragdrop' event handlers on your XML element, e.g. + * <xmlelement ondraggesture="nsDragAndDrop.startDrag(event, observer);" + * ondragover="nsDragAndDrop.dragOver(event, observer);" + * ondragdrop="nsDragAndDrop.drop(event, observer);"/> + * + * You need to create an observer js object with the following member + * functions: + * Object onDragStart (event) // called when drag initiated, + * // returns flavour list with data + * // to stuff into transferable + * void onDragOver (Object flavour) // called when element is dragged + * // over, so that it can perform + * // any drag-over feedback for provided + * // flavour + * void onDrop (Object data) // formatted data object dropped. + * Object getSupportedFlavours () // returns a flavour list so that + * // nsTransferable can determine + * // whether or not to accept drop. + **/ + +var nsDragAndDrop = { + + _mDS: null, + get mDragService() + { + if (!this._mDS) + { + const kDSContractID = "@mozilla.org/widget/dragservice;1"; + const kDSIID = Components.interfaces.nsIDragService; + this._mDS = Components.classes[kDSContractID].getService(kDSIID); + } + return this._mDS; + }, + + /** + * void startDrag (DOMEvent aEvent, Object aDragDropObserver) ; + * + * called when a drag on an element is started. + * + * @param DOMEvent aEvent + * the DOM event fired by the drag init + * @param Object aDragDropObserver + * javascript object of format described above that specifies + * the way in which the element responds to drag events. + **/ + startDrag: function (aEvent, aDragDropObserver) + { + if (!("onDragStart" in aDragDropObserver)) + return; + + const kDSIID = Components.interfaces.nsIDragService; + var dragAction = { action: kDSIID.DRAGDROP_ACTION_COPY + kDSIID.DRAGDROP_ACTION_MOVE + kDSIID.DRAGDROP_ACTION_LINK }; + + var transferData = { data: null }; + try + { + aDragDropObserver.onDragStart(aEvent, transferData, dragAction); + } + catch (e) + { + return; // not a draggable item, bail! + } + + if (!transferData.data) return; + transferData = transferData.data; + + var dt = aEvent.dataTransfer; + var count = 0; + do { + var tds = transferData._XferID == "TransferData" + ? transferData + : transferData.dataList[count] + for (var i = 0; i < tds.dataList.length; ++i) + { + var currData = tds.dataList[i]; + var currFlavour = currData.flavour.contentType; + var value = currData.supports; + if (value instanceof Components.interfaces.nsISupportsString) + value = value.toString(); + dt.mozSetDataAt(currFlavour, value, count); + } + + count++; + } + while (transferData._XferID == "TransferDataSet" && + count < transferData.dataList.length); + + dt.effectAllowed = "all"; + // a drag targeted at a tree should instead use the treechildren so that + // the current selection is used as the drag feedback + dt.addElement(aEvent.originalTarget.localName == "treechildren" ? + aEvent.originalTarget : aEvent.target); + aEvent.stopPropagation(); + }, + + /** + * void dragOver (DOMEvent aEvent, Object aDragDropObserver) ; + * + * called when a drag passes over this element + * + * @param DOMEvent aEvent + * the DOM event fired by passing over the element + * @param Object aDragDropObserver + * javascript object of format described above that specifies + * the way in which the element responds to drag events. + **/ + dragOver: function (aEvent, aDragDropObserver) + { + if (!("onDragOver" in aDragDropObserver)) + return; + if (!this.checkCanDrop(aEvent, aDragDropObserver)) + return; + var flavourSet = aDragDropObserver.getSupportedFlavours(); + for (var flavour in flavourSet.flavourTable) + { + if (this.mDragSession.isDataFlavorSupported(flavour)) + { + aDragDropObserver.onDragOver(aEvent, + flavourSet.flavourTable[flavour], + this.mDragSession); + aEvent.stopPropagation(); + aEvent.preventDefault(); + break; + } + } + }, + + mDragSession: null, + + /** + * void drop (DOMEvent aEvent, Object aDragDropObserver) ; + * + * called when the user drops on the element + * + * @param DOMEvent aEvent + * the DOM event fired by the drop + * @param Object aDragDropObserver + * javascript object of format described above that specifies + * the way in which the element responds to drag events. + **/ + drop: function (aEvent, aDragDropObserver) + { + if (!("onDrop" in aDragDropObserver)) + return; + if (!this.checkCanDrop(aEvent, aDragDropObserver)) + return; + + var flavourSet = aDragDropObserver.getSupportedFlavours(); + + var dt = aEvent.dataTransfer; + var dataArray = []; + var count = dt.mozItemCount; + for (var i = 0; i < count; ++i) { + var types = dt.mozTypesAt(i); + for (var j = 0; j < flavourSet.flavours.length; j++) { + var type = flavourSet.flavours[j].contentType; + // dataTransfer uses text/plain but older code used text/unicode, so + // switch this for compatibility + var modtype = (type == "text/unicode") ? "text/plain" : type; + if (Array.indexOf(types, modtype) >= 0) { + var data = dt.mozGetDataAt(modtype, i); + if (data) { + // Non-strings need some non-zero value used for their data length. + const kNonStringDataLength = 4; + + var length = (typeof data == "string") ? data.length : kNonStringDataLength; + dataArray[i] = FlavourToXfer(data, length, flavourSet.flavourTable[type]); + break; + } + } + } + } + + var transferData = new TransferDataSet(dataArray) + + // hand over to the client to respond to dropped data + var multiple = "canHandleMultipleItems" in aDragDropObserver && aDragDropObserver.canHandleMultipleItems; + var dropData = multiple ? transferData : transferData.first.first; + aDragDropObserver.onDrop(aEvent, dropData, this.mDragSession); + aEvent.stopPropagation(); + }, + + /** + * void dragExit (DOMEvent aEvent, Object aDragDropObserver) ; + * + * called when a drag leaves this element + * + * @param DOMEvent aEvent + * the DOM event fired by leaving the element + * @param Object aDragDropObserver + * javascript object of format described above that specifies + * the way in which the element responds to drag events. + **/ + dragExit: function (aEvent, aDragDropObserver) + { + if (!this.checkCanDrop(aEvent, aDragDropObserver)) + return; + if ("onDragExit" in aDragDropObserver) + aDragDropObserver.onDragExit(aEvent, this.mDragSession); + }, + + /** + * void dragEnter (DOMEvent aEvent, Object aDragDropObserver) ; + * + * called when a drag enters in this element + * + * @param DOMEvent aEvent + * the DOM event fired by entering in the element + * @param Object aDragDropObserver + * javascript object of format described above that specifies + * the way in which the element responds to drag events. + **/ + dragEnter: function (aEvent, aDragDropObserver) + { + if (!this.checkCanDrop(aEvent, aDragDropObserver)) + return; + if ("onDragEnter" in aDragDropObserver) + aDragDropObserver.onDragEnter(aEvent, this.mDragSession); + }, + + /** + * Boolean checkCanDrop (DOMEvent aEvent, Object aDragDropObserver) ; + * + * Sets the canDrop attribute for the drag session. + * returns false if there is no current drag session. + * + * @param DOMEvent aEvent + * the DOM event fired by the drop + * @param Object aDragDropObserver + * javascript object of format described above that specifies + * the way in which the element responds to drag events. + **/ + checkCanDrop: function (aEvent, aDragDropObserver) + { + if (!this.mDragSession) + this.mDragSession = this.mDragService.getCurrentSession(); + if (!this.mDragSession) + return false; + this.mDragSession.canDrop = this.mDragSession.sourceNode != aEvent.target; + if ("canDrop" in aDragDropObserver) + this.mDragSession.canDrop &= aDragDropObserver.canDrop(aEvent, this.mDragSession); + return true; + }, + + /** + * Do a security check for drag n' drop. Make sure the source document + * can load the dragged link. + * + * @param DOMEvent aEvent + * the DOM event fired by leaving the element + * @param Object aDragDropObserver + * javascript object of format described above that specifies + * the way in which the element responds to drag events. + * @param String aDraggedText + * the text being dragged + **/ + dragDropSecurityCheck: function (aEvent, aDragSession, aDraggedText) + { + // Strip leading and trailing whitespace, then try to create a + // URI from the dropped string. If that succeeds, we're + // dropping a URI and we need to do a security check to make + // sure the source document can load the dropped URI. We don't + // so much care about creating the real URI here + // (i.e. encoding differences etc don't matter), we just want + // to know if aDraggedText really is a URI. + + aDraggedText = aDraggedText.replace(/^\s*|\s*$/g, ''); + + var uri; + var ioService = Components.classes["@mozilla.org/network/io-service;1"] + .getService(Components.interfaces.nsIIOService); + try { + uri = ioService.newURI(aDraggedText, null, null); + } catch (e) { + } + + if (!uri) + return; + + // aDraggedText is a URI, do the security check. + const nsIScriptSecurityManager = Components.interfaces + .nsIScriptSecurityManager; + var secMan = Components.classes["@mozilla.org/scriptsecuritymanager;1"] + .getService(nsIScriptSecurityManager); + + if (!aDragSession) + aDragSession = this.mDragService.getCurrentSession(); + + var sourceDoc = aDragSession.sourceDocument; + // Use "file:///" as the default sourceURI so that drops of file:// URIs + // are always allowed. + var principal = sourceDoc ? sourceDoc.nodePrincipal + : secMan.getSimpleCodebasePrincipal(ioService.newURI("file:///", null, null)); + + try { + secMan.checkLoadURIStrWithPrincipal(principal, aDraggedText, + nsIScriptSecurityManager.STANDARD); + } catch (e) { + // Stop event propagation right here. + aEvent.stopPropagation(); + + throw "Drop of " + aDraggedText + " denied."; + } + } +}; + diff --git a/toolkit/content/nsUserSettings.js b/toolkit/content/nsUserSettings.js new file mode 100644 index 000000000..e0c378caf --- /dev/null +++ b/toolkit/content/nsUserSettings.js @@ -0,0 +1,108 @@ +/* This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ + + +/** + * nsPreferences - a wrapper around nsIPrefService. Provides built in + * exception handling to make preferences access simpler. + **/ +var nsPreferences = { + get mPrefService() + { + return Components.classes["@mozilla.org/preferences-service;1"] + .getService(Components.interfaces.nsIPrefBranch); + }, + + setBoolPref: function (aPrefName, aPrefValue) + { + try + { + this.mPrefService.setBoolPref(aPrefName, aPrefValue); + } + catch (e) + { + } + }, + + getBoolPref: function (aPrefName, aDefVal) + { + try + { + return this.mPrefService.getBoolPref(aPrefName); + } + catch (e) + { + return aDefVal != undefined ? aDefVal : null; + } + return null; // quiet warnings + }, + + setUnicharPref: function (aPrefName, aPrefValue) + { + try + { + var str = Components.classes["@mozilla.org/supports-string;1"] + .createInstance(Components.interfaces.nsISupportsString); + str.data = aPrefValue; + this.mPrefService.setComplexValue(aPrefName, + Components.interfaces.nsISupportsString, str); + } + catch (e) + { + } + }, + + copyUnicharPref: function (aPrefName, aDefVal) + { + try + { + return this.mPrefService.getComplexValue(aPrefName, + Components.interfaces.nsISupportsString).data; + } + catch (e) + { + return aDefVal != undefined ? aDefVal : null; + } + return null; // quiet warnings + }, + + setIntPref: function (aPrefName, aPrefValue) + { + try + { + this.mPrefService.setIntPref(aPrefName, aPrefValue); + } + catch (e) + { + } + }, + + getIntPref: function (aPrefName, aDefVal) + { + try + { + return this.mPrefService.getIntPref(aPrefName); + } + catch (e) + { + return aDefVal != undefined ? aDefVal : null; + } + return null; // quiet warnings + }, + + getLocalizedUnicharPref: function (aPrefName, aDefVal) + { + try + { + return this.mPrefService.getComplexValue(aPrefName, + Components.interfaces.nsIPrefLocalizedString).data; + } + catch (e) + { + return aDefVal != undefined ? aDefVal : null; + } + return null; // quiet warnings + } +}; + diff --git a/toolkit/content/strres.js b/toolkit/content/strres.js new file mode 100644 index 000000000..928c8f75f --- /dev/null +++ b/toolkit/content/strres.js @@ -0,0 +1,28 @@ +/* This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ + +var strBundleService = null; + +function srGetStrBundle(path) +{ + var strBundle = null; + + if (!strBundleService) { + try { + strBundleService = + Components.classes["@mozilla.org/intl/stringbundle;1"].getService(); + strBundleService = + strBundleService.QueryInterface(Components.interfaces.nsIStringBundleService); + } catch (ex) { + dump("\n--** strBundleService failed: " + ex + "\n"); + return null; + } + } + + strBundle = strBundleService.createBundle(path); + if (!strBundle) { + dump("\n--** strBundle createInstance failed **--\n"); + } + return strBundle; +} |