toolkit/components/filepicker/nsFilePicker.js

Sat, 03 Jan 2015 20:18:00 +0100

author
Michael Schloh von Bennewitz <michael@schloh.com>
date
Sat, 03 Jan 2015 20:18:00 +0100
branch
TOR_BUG_3246
changeset 7
129ffea94266
permissions
-rw-r--r--

Conditionally enable double key logic according to:
private browsing mode or privacy.thirdparty.isolate preference and
implement in GetCookieStringCommon and FindCookie where it counts...
With some reservations of how to convince FindCookie users to test
condition and pass a nullptr when disabling double key logic.

     1 /* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
     2 /* This Source Code Form is subject to the terms of the Mozilla Public
     3  * License, v. 2.0. If a copy of the MPL was not distributed with this
     4  * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
     6 /*
     7  * No magic constructor behaviour, as is de rigeur for XPCOM.
     8  * If you must perform some initialization, and it could possibly fail (even
     9  * due to an out-of-memory condition), you should use an Init method, which
    10  * can convey failure appropriately (thrown exception in JS,
    11  * NS_FAILED(nsresult) return in C++).
    12  *
    13  * In JS, you can actually cheat, because a thrown exception will cause the
    14  * CreateInstance call to fail in turn, but not all languages are so lucky.
    15  * (Though ANSI C++ provides exceptions, they are verboten in Mozilla code
    16  * for portability reasons -- and even when you're building completely
    17  * platform-specific code, you can't throw across an XPCOM method boundary.)
    18  */
    20 Components.utils.import("resource://gre/modules/XPCOMUtils.jsm");
    22 const DEBUG = false; /* set to true to enable debug messages */
    24 const LOCAL_FILE_CONTRACTID = "@mozilla.org/file/local;1";
    25 const APPSHELL_SERV_CONTRACTID  = "@mozilla.org/appshell/appShellService;1";
    26 const STRBUNDLE_SERV_CONTRACTID = "@mozilla.org/intl/stringbundle;1";
    28 const nsIAppShellService    = Components.interfaces.nsIAppShellService;
    29 const nsILocalFile          = Components.interfaces.nsILocalFile;
    30 const nsIFileURL            = Components.interfaces.nsIFileURL;
    31 const nsISupports           = Components.interfaces.nsISupports;
    32 const nsIFactory            = Components.interfaces.nsIFactory;
    33 const nsIFilePicker         = Components.interfaces.nsIFilePicker;
    34 const nsIInterfaceRequestor = Components.interfaces.nsIInterfaceRequestor;
    35 const nsIDOMWindow          = Components.interfaces.nsIDOMWindow;
    36 const nsIStringBundleService = Components.interfaces.nsIStringBundleService;
    37 const nsIWebNavigation      = Components.interfaces.nsIWebNavigation;
    38 const nsIDocShellTreeItem   = Components.interfaces.nsIDocShellTreeItem;
    39 const nsIBaseWindow         = Components.interfaces.nsIBaseWindow;
    41 var   titleBundle           = null;
    42 var   filterBundle          = null;
    43 var   lastDirectory         = null;
    45 function nsFilePicker()
    46 {
    47   if (!titleBundle)
    48     titleBundle = srGetStrBundle("chrome://global/locale/filepicker.properties");
    49   if (!filterBundle)
    50     filterBundle = srGetStrBundle("chrome://global/content/filepicker.properties");
    52   /* attributes */
    53   this.mDefaultString = "";
    54   this.mFilterIndex = 0;
    55   this.mFilterTitles = new Array();
    56   this.mFilters = new Array();
    57   this.mDisplayDirectory = null;
    58   if (lastDirectory) {
    59     try {
    60       var dir = Components.classes[LOCAL_FILE_CONTRACTID].createInstance(nsILocalFile);
    61       dir.initWithPath(lastDirectory);
    62       this.mDisplayDirectory = dir;
    63     } catch (e) {}
    64   }
    65 }
    67 nsFilePicker.prototype = {
    68   classID: Components.ID("{54ae32f8-1dd2-11b2-a209-df7c505370f8}"),
    70   QueryInterface: function(iid) {
    71     if (iid.equals(nsIFilePicker) ||
    72         iid.equals(nsISupports))
    73       return this;
    75     throw Components.results.NS_ERROR_NO_INTERFACE;
    76   },
    79   /* attribute nsILocalFile displayDirectory; */
    80   set displayDirectory(a) {
    81     this.mDisplayDirectory = a &&
    82       a.clone().QueryInterface(nsILocalFile);
    83   },
    84   get displayDirectory()  {
    85     return this.mDisplayDirectory &&
    86            this.mDisplayDirectory.clone()
    87                .QueryInterface(nsILocalFile);
    88   },
    90   /* readonly attribute nsILocalFile file; */
    91   get file()  { return this.mFilesEnumerator.mFiles[0]; },
    93   /* readonly attribute nsISimpleEnumerator files; */
    94   get files()  { return this.mFilesEnumerator; },
    96   /* readonly attribute nsIDOMFile domfile; */
    97   get domfile()  {
    98     let enumerator = this.domfiles;
    99     return enumerator ? enumerator.mFiles[0] : null;
   100   },
   102   /* readonly attribute nsISimpleEnumerator domfiles; */
   103   get domfiles()  {
   104     if (!this.mFilesEnumerator) {
   105       return null;
   106     }
   108     if (!this.mDOMFilesEnumerator) {
   109       this.mDOMFilesEnumerator = {
   110         QueryInterface: XPCOMUtils.generateQI([Components.interfaces.nsISimpleEnumerator]),
   112         mFiles: [],
   113         mIndex: 0,
   115         hasMoreElements: function() {
   116           return (this.mIndex < this.mFiles.length);
   117         },
   119         getNext: function() {
   120           if (this.mIndex >= this.mFiles.length) {
   121             throw Components.results.NS_ERROR_FAILURE;
   122           }
   123           return this.mFiles[this.mIndex++];
   124         }
   125       };
   127       var utils = this.mParentWindow.QueryInterface(Components.interfaces.nsIInterfaceRequestor)
   128                                     .getInterface(Components.interfaces.nsIDOMWindowUtils);
   130       for (var i = 0; i < this.mFilesEnumerator.mFiles.length; ++i) {
   131         var file = utils.wrapDOMFile(this.mFilesEnumerator.mFiles[i]);
   132         this.mDOMFilesEnumerator.mFiles.push(file);
   133       }
   134     }
   136     return this.mDOMFilesEnumerator;
   137   },
   139   /* readonly attribute nsIURI fileURL; */
   140   get fileURL()  {
   141     if (this.mFileURL)
   142       return this.mFileURL;
   144     if (!this.mFilesEnumerator)
   145       return null;
   147       var ioService = Components.classes["@mozilla.org/network/io-service;1"]
   148                     .getService(Components.interfaces.nsIIOService);
   150     return this.mFileURL = ioService.newFileURI(this.file);
   151   },
   153   /* attribute wstring defaultString; */
   154   set defaultString(a) { this.mDefaultString = a; },
   155   get defaultString()  { return this.mDefaultString; },
   157   /* attribute wstring defaultExtension */
   158   set defaultExtension(ext) { },
   159   get defaultExtension() { return ""; },
   161   /* attribute long filterIndex; */
   162   set filterIndex(a) { this.mFilterIndex = a; },
   163   get filterIndex() { return this.mFilterIndex; },
   165   /* attribute boolean addToRecentDocs; */
   166   set addToRecentDocs(a) {},
   167   get addToRecentDocs()  { return false; },
   169   /* readonly attribute short mode; */
   170   get mode() { return this.mMode; },
   172   /* members */
   173   mFilesEnumerator: undefined,
   174   mDOMFilesEnumerator: undefined,
   175   mParentWindow: null,
   177   /* methods */
   178   init: function(parent, title, mode) {
   179     this.mParentWindow = parent;
   180     this.mTitle = title;
   181     this.mMode = mode;
   182   },
   184   appendFilters: function(filterMask) {
   185     if (filterMask & nsIFilePicker.filterHTML) {
   186       this.appendFilter(titleBundle.GetStringFromName("htmlTitle"),
   187                         filterBundle.GetStringFromName("htmlFilter"));
   188     }
   189     if (filterMask & nsIFilePicker.filterText) {
   190       this.appendFilter(titleBundle.GetStringFromName("textTitle"),
   191                         filterBundle.GetStringFromName("textFilter"));
   192     }
   193     if (filterMask & nsIFilePicker.filterImages) {
   194       this.appendFilter(titleBundle.GetStringFromName("imageTitle"),
   195                         filterBundle.GetStringFromName("imageFilter"));
   196     }
   197     if (filterMask & nsIFilePicker.filterXML) {
   198       this.appendFilter(titleBundle.GetStringFromName("xmlTitle"),
   199                         filterBundle.GetStringFromName("xmlFilter"));
   200     }
   201     if (filterMask & nsIFilePicker.filterXUL) {
   202       this.appendFilter(titleBundle.GetStringFromName("xulTitle"),
   203                         filterBundle.GetStringFromName("xulFilter"));
   204     }
   205     this.mAllowURLs = !!(filterMask & nsIFilePicker.filterAllowURLs);
   206     if (filterMask & nsIFilePicker.filterApps) {
   207       // We use "..apps" as a special filter for executable files
   208       this.appendFilter(titleBundle.GetStringFromName("appsTitle"),
   209                         "..apps");
   210     }
   211     if (filterMask & nsIFilePicker.filterAudio) {
   212       this.appendFilter(titleBundle.GetStringFromName("audioTitle"),
   213                         filterBundle.GetStringFromName("audioFilter"));
   214     }
   215     if (filterMask & nsIFilePicker.filterVideo) {
   216       this.appendFilter(titleBundle.GetStringFromName("videoTitle"),
   217                         filterBundle.GetStringFromName("videoFilter"));
   218     }
   219     if (filterMask & nsIFilePicker.filterAll) {
   220       this.appendFilter(titleBundle.GetStringFromName("allTitle"),
   221                         filterBundle.GetStringFromName("allFilter"));
   222     }
   223   },
   225   appendFilter: function(title, extensions) {
   226     this.mFilterTitles.push(title);
   227     this.mFilters.push(extensions);
   228   },
   230   open: function(aFilePickerShownCallback) {
   231     var tm = Components.classes["@mozilla.org/thread-manager;1"]
   232                        .getService(Components.interfaces.nsIThreadManager);
   233     tm.mainThread.dispatch(function() {
   234       let result = Components.interfaces.nsIFilePicker.returnCancel;
   235       try {
   236         result = this.show();
   237       } catch(ex) {
   238       }
   239       if (aFilePickerShownCallback) {
   240         aFilePickerShownCallback.done(result);
   241       }
   242     }.bind(this), Components.interfaces.nsIThread.DISPATCH_NORMAL);
   243   },
   245   show: function() {
   246     var o = new Object();
   247     o.title = this.mTitle;
   248     o.mode = this.mMode;
   249     o.displayDirectory = this.mDisplayDirectory;
   250     o.defaultString = this.mDefaultString;
   251     o.filterIndex = this.mFilterIndex;
   252     o.filters = new Object();
   253     o.filters.titles = this.mFilterTitles;
   254     o.filters.types = this.mFilters;
   255     o.allowURLs = this.mAllowURLs;
   256     o.retvals = new Object();
   258     var parent;
   259     if (this.mParentWindow) {
   260       parent = this.mParentWindow;
   261     } else if (typeof(window) == "object" && window != null) {
   262       parent = window;
   263     } else {
   264       try {
   265         var appShellService = Components.classes[APPSHELL_SERV_CONTRACTID].getService(nsIAppShellService);
   266         parent = appShellService.hiddenDOMWindow;
   267       } catch(ex) {
   268         debug("Can't get parent.  xpconnect hates me so we can't get one from the appShellService.\n");
   269         debug(ex + "\n");
   270       }
   271     }
   273     var parentWin = null;
   274     try {
   275       parentWin = parent.QueryInterface(nsIInterfaceRequestor)
   276                         .getInterface(nsIWebNavigation)
   277                         .QueryInterface(nsIDocShellTreeItem)
   278                         .treeOwner
   279                         .QueryInterface(nsIInterfaceRequestor)
   280                         .getInterface(nsIBaseWindow);
   281     } catch(ex) {
   282       dump("file picker couldn't get base window\n"+ex+"\n");
   283     }
   284     try {
   285       parent.openDialog("chrome://global/content/filepicker.xul",
   286                         "",
   287                         "chrome,modal,titlebar,resizable=yes,dependent=yes",
   288                         o);
   290       this.mFilterIndex = o.retvals.filterIndex;
   291       this.mFilesEnumerator = o.retvals.files;
   292       this.mFileURL = o.retvals.fileURL;
   293       lastDirectory = o.retvals.directory;
   294       return o.retvals.buttonStatus;
   295     } catch(ex) { dump("unable to open file picker\n" + ex + "\n"); }
   297     return null;
   298   }
   299 }
   301 if (DEBUG)
   302   debug = function (s) { dump("-*- filepicker: " + s + "\n"); };
   303 else
   304   debug = function (s) {};
   306 this.NSGetFactory = XPCOMUtils.generateNSGetFactory([nsFilePicker]);
   308 /* crap from strres.js that I want to use for string bundles since I can't include another .js file.... */
   310 var strBundleService = null;
   312 function srGetStrBundle(path)
   313 {
   314   var strBundle = null;
   316   if (!strBundleService) {
   317     try {
   318       strBundleService = Components.classes[STRBUNDLE_SERV_CONTRACTID].getService(nsIStringBundleService);
   319     } catch (ex) {
   320       dump("\n--** strBundleService createInstance failed **--\n");
   321       return null;
   322     }
   323   }
   325   strBundle = strBundleService.createBundle(path);
   326   if (!strBundle) {
   327 	dump("\n--** strBundle createInstance failed **--\n");
   328   }
   329   return strBundle;
   330 }

mercurial