Open
Bug 837989
Opened 11 years ago
Updated 11 months ago
Use IOUtils for gLastOpenDirectory
Categories
(Firefox :: General, defect)
Firefox
General
Tracking
()
NEW
Performance Impact | low |
People
(Reporter: marco, Unassigned)
References
(Blocks 1 open bug)
Details
(Keywords: main-thread-io, perf:frontend, Whiteboard: [Snappy] p=0)
Attachments
(1 file, 3 obsolete files)
12.55 KB,
patch
|
Yoric
:
feedback+
|
Details | Diff | Splinter Review |
Instead of checking for file existence on the main thread, we can use OS.File's stat. The attached patch is just a draft, I'm still learning how promises work. And I think there are some tests that I need to fix (because they expect an immediate result).
Attachment #710007 -
Flags: feedback?(dteller)
Comment 1•11 years ago
|
||
Comment on attachment 710007 [details] [diff] [review] Patch Review of attachment 710007 [details] [diff] [review]: ----------------------------------------------------------------- ::: browser/base/content/browser.js @@ +2171,5 @@ > _lastDir: null, > get path() { > + return this._lastDir; > + }, > + set path(val) { Shouldn't |path| accept a path instead of a |nsIFile|? @@ +2187,5 @@ > + } > + }, > + function onFailure(reason) { > + if (!(reason instanceof OS.File.Error && reason.becauseNoSuchFile)) { > + throw reason; This won't report the error, ever. You should add some form of error reporting here. @@ +2193,4 @@ > } > + ); > + }, > + loadPath: function() { For improved readability, you may want to use Task.jsm. Your call. @@ +2217,5 @@ > + }, > + checkExists: function() { > + let promise = OS.File.stat(this._lastDir.path); > + return promise; > + }, Method |checkExists| doesn't look very useful. I would just inline it. @@ +2237,2 @@ > } > + Nit: What's that empty line? @@ +2250,5 @@ > + promise.then( > + function onSuccess() { > + fp.displayDirectory = gLastOpenDirectory.path; > + fp.open(fpCallback); > + } Could you add a comment to explain that you are ignoring errors deliberately?
Attachment #710007 -
Flags: feedback?(dteller) → feedback+
Reporter | ||
Updated•11 years ago
|
Whiteboard: [Snappy]
Reporter | ||
Updated•11 years ago
|
Assignee: nobody → mar.castelluccio
Reporter | ||
Updated•11 years ago
|
Status: NEW → ASSIGNED
Reporter | ||
Comment 2•11 years ago
|
||
https://tbpl.mozilla.org/?tree=Try&rev=49599e3d30af
Attachment #710007 -
Attachment is obsolete: true
Reporter | ||
Comment 3•11 years ago
|
||
Looks like my fix for the test doesn't work. The test is timing out.
Updated•11 years ago
|
Keywords: main-thread-io
Reporter | ||
Comment 4•11 years ago
|
||
Attachment #711572 -
Attachment is obsolete: true
Attachment #784458 -
Flags: review?(dteller)
Comment 5•11 years ago
|
||
Comment on attachment 784458 [details] [diff] [review] Patch v3 >diff --git a/browser/base/content/browser.js b/browser/base/content/browser.js > var gLastOpenDirectory = { >+ setPath: function(val) { Can we just get rid of the isDirectory check, rather than forcing setPath to be synchronous? Having it not be synchronous seems like a footgun and probably overly complicates tests and some consumers.
Reporter | ||
Comment 6•11 years ago
|
||
(In reply to :Gavin Sharp (use gavin@gavinsharp.com for email) from comment #5) > Comment on attachment 784458 [details] [diff] [review] > Patch v3 > > >diff --git a/browser/base/content/browser.js b/browser/base/content/browser.js > > > var gLastOpenDirectory = { > > >+ setPath: function(val) { > > Can we just get rid of the isDirectory check, rather than forcing setPath to > be synchronous? Having it not be synchronous seems like a footgun and > probably overly complicates tests and some consumers. I didn't want to modify the behavior of the code, but I guess we could safely move the isDirectory check in getPath (so we don't even need to call exists). What do you say?
Reporter | ||
Comment 7•11 years ago
|
||
The only problem is that if the directory doesn't exist, we don't want to set the pref.
Comment 8•11 years ago
|
||
I'm suggesting a change in behavior, yes - I was hoping you could tell me whether that would break anything :) What's the harm in setting the pref to a bogus value, if someone passes one in? What's the likelihood that anyone would do that - do we really need to defend against it?
Reporter | ||
Comment 9•11 years ago
|
||
(In reply to :Gavin Sharp (use gavin@gavinsharp.com for email) from comment #8) > I'm suggesting a change in behavior, yes - I was hoping you could tell me > whether that would break anything :) What's the harm in setting the pref to > a bogus value, if someone passes one in? What's the likelihood that anyone > would do that - do we really need to defend against it? I think it's highly unlikely. The only consumer is using a file picker and I think it's highly unlikely that the directory just chosen by the user would be removed in such a short time. Moreover between the setPath and getPath everything could happen, so there's already no guarantee that the file is a directory when getPath is called.
Comment on attachment 784458 [details] [diff] [review] Patch v3 Review of attachment 784458 [details] [diff] [review]: ----------------------------------------------------------------- ::: browser/base/content/browser.js @@ +1854,5 @@ > postData: aPostData, > inBackground: false, > allowThirdPartyFixup: aAllowThirdPartyFixup}); > } > Since you're improving that code, could you please the opportunity to add some documentation? @@ +1862,5 @@ > get path() { > + return this._lastDir; > + }, > + > + setPath: function(val) { For my understanding: why did you replace |set path| with |setPath|? Also, while you're here, some name more meaningful than |val| might be nice. Also, since |val| is a |nsIFile|, |setDir| might be a better name. @@ +1884,5 @@ > + }.bind(this)).then(null, function onError(reason) { > + if (!(reason instanceof OS.File.Error && reason.becauseNoSuchFile)) { > + Cu.reportError("Checking for directory existence failed: " + reason); > + } > + }); Since you're already using Task.spawn, you should replace this onError with a use of try/catch, this will be easier to read. @@ +1887,5 @@ > + } > + }); > + }, > + > + loadPath: function() { It's not clear to me what |loadPath| intends to do, who should call it and when. @@ +1893,5 @@ > + if (!this._lastDir) { > + try { > + this._lastDir = gPrefService.getComplexValue("browser.open.lastDir", > + Ci.nsIFile); > + } catch(e) {} Please document this catch-all. @@ +1897,5 @@ > + } catch(e) {} > + } > + > + if (this._lastDir) { > + let fileExists = yield OS.File.exists(this._lastDir.path); So, if we are calling |stat| in |setPath|, why not here? @@ +1923,4 @@ > if (fp.file) { > + yield gLastOpenDirectory.setPath(fp.file > + .parent > + .QueryInterface(Ci.nsIFile)); This |yield| won't do anything interesting. What was your objective here? @@ +1937,5 @@ > + > + yield gLastOpenDirectory.loadPath(); > + fp.displayDirectory = gLastOpenDirectory.path; > + fp.open(fpCallback); > + } catch (ex) {} Here, too, could you please document the catch-all?
Attachment #784458 -
Flags: review?(dteller) → feedback+
Reporter | ||
Comment 11•11 years ago
|
||
I've changed the behavior of the object. Now all the checks are made in loadDir. > > @@ +1923,4 @@ > > if (fp.file) { > > + yield gLastOpenDirectory.setPath(fp.file > > + .parent > > + .QueryInterface(Ci.nsIFile)); > > This |yield| won't do anything interesting. What was your objective here? I've removed it, but it was here to wait for the async operations executed by setPath (setPath returned a promise). > @@ +1937,5 @@ > > + > > + yield gLastOpenDirectory.loadPath(); > > + fp.displayDirectory = gLastOpenDirectory.path; > > + fp.open(fpCallback); > > + } catch (ex) {} > > Here, too, could you please document the catch-all? Actually I don't know why here we're ignoring errors.
Attachment #784458 -
Attachment is obsolete: true
Attachment #785451 -
Flags: review?(dteller)
Comment on attachment 785451 [details] [diff] [review] gLastOpenDirectory_OS.File Review of attachment 785451 [details] [diff] [review]: ----------------------------------------------------------------- ::: browser/base/content/browser.js @@ +1874,5 @@ > + } > + } > + }, > + > + // This function reads the last open directory from the browser.open.lastDir Ok, but what is it for? Also, nit: Remove "this function." @@ +1884,5 @@ > + // lastDir value. > + try { > + this._lastDir = gPrefService.getComplexValue("browser.open.lastDir", > + Ci.nsIFile); > + } catch(e) {} Please move your comment "if for some reason [...]" inside the {}. @@ +1895,2 @@ > try { > + let stat = yield OS.File.stat(this._lastDir.path); I still don't quite understand the role of this function. Looks like you're doing this call to |stat| at each call to |loadDir|. Shouldn't you do it only if |this._lastDir| has been modified? Also, would it be better/worse if |loadDir| were replaced by a preference observer and/or were part of |set dir| or |get dir|? ::: browser/components/privatebrowsing/test/browser/browser_privatebrowsing_opendir.js @@ +123,5 @@ > > + // cleanup > + file.remove(false); > + finish(); > + }); Why did you remove Test 5?
Attachment #785451 -
Flags: review?(dteller) → feedback+
Reporter | ||
Comment 13•11 years ago
|
||
(In reply to David Rajchenbach Teller [:Yoric] from comment #12) > @@ +1895,2 @@ > > try { > > + let stat = yield OS.File.stat(this._lastDir.path); > > I still don't quite understand the role of this function. Looks like you're > doing this call to |stat| at each call to |loadDir|. Shouldn't you do it > only if |this._lastDir| has been modified? We need to check if the directory is still there since the last time we've used it. The directory could also be removed while Firefox isn't running. > ::: > browser/components/privatebrowsing/test/browser/ > browser_privatebrowsing_opendir.js > @@ +123,5 @@ > > > > + // cleanup > > + file.remove(false); > > + finish(); > > + }); > > Why did you remove Test 5? Because I changed the behavior of the object. Now we check if the directory exists and is a directory only when we load the pref, not when we save it (because it's highly unlikely that it's set to an non existent file, as it's set through a file picker).
Any progress here?
Flags: needinfo?(mar.castelluccio)
In the absence of news, de-assigning.
Flags: needinfo?(mar.castelluccio)
Updated•10 years ago
|
Blocks: fxdesktopbacklog
Whiteboard: [Snappy] → [Snappy] [feature] p=0
Updated•10 years ago
|
No longer blocks: fxdesktopbacklog
Flags: firefox-backlog+
Whiteboard: [Snappy] [feature] p=0 → [Snappy] p=0
Updated•6 years ago
|
Whiteboard: [Snappy] p=0 → [Snappy] p=0 [fxperf]
Comment 16•6 years ago
|
||
This code is only used when using the 'open file' dialog directly from the File menu, the 'open file' button, or via an app command (sent via the OS), so doesn't seem worth prioritizing higher than p3. I'm unassigning Marco because given that it's been 5 years I assume he's not working on this at the moment. :-)
Assignee: mcastelluccio → nobody
Status: ASSIGNED → NEW
OS: Linux → All
Hardware: x86_64 → All
Whiteboard: [Snappy] p=0 [fxperf] → [Snappy] p=0 [fxperf:p3]
Reporter | ||
Updated•2 years ago
|
Summary: Use OS.File for gLastOpenDirectory → Use IOUtils for gLastOpenDirectory
Updated•2 years ago
|
Severity: normal → S3
Updated•11 months ago
|
Performance Impact: --- → low
Keywords: perf:frontend
Whiteboard: [Snappy] p=0 [fxperf:p3] → [Snappy] p=0
You need to log in
before you can comment on or make changes to this bug.
Description
•