fix: Prevent --keep-profile-changes on default Firefox profiles#1007
Conversation
ea4c214 to
778757a
Compare
778757a to
cc10673
Compare
|
@kumar303 This should be ready to be reviewed now. (I'm going to also test it manually on Windows as I did on Linux in the meantime). @saintsebastian I've also added you as a reviewer, because I'm touching files that could probably impact some of your open pull requests, and a pair of additional eyes are always appreciated ;-) |
saintsebastian
left a comment
There was a problem hiding this comment.
Since I wrote useProfile() this bug is kinda on me, so thanks for fixing it!
|
|
||
| // isDefaultProfile types and implementation. | ||
|
|
||
| const DEFAULT_PROFILES_NAMES = [ |
There was a problem hiding this comment.
I'm no expert on firefox profiles, but could that be that those names are misleading? As in I could have created a profile which i called default but don't actually use if as default.
There was a problem hiding this comment.
I would prefer to keep this as strict as "you can use a different profile name instead of these ones"
mostly because the incorrect usage can be implemented in a script (like the react-devtools automation script mentioned in #1005) and so the user could be not in charge of that "potentially harmful" decision.
| customPrefs = {}, | ||
| }: UseProfileParams = {}, | ||
| ): Promise<FirefoxProfile> { | ||
| const isForbiddenProfile = await isFirefoxDefaultProfile(profilePath); |
There was a problem hiding this comment.
Kumar proposed option like --allow-web-ext-to-completely-break-my-profile, i think that might be a good idea if we show a warning first, since if users want to do something potentially dangerous that's on them.
There was a problem hiding this comment.
@saintsebastian @kumar303 I'm open to implement such option if we decide to go for it, but I vote against it :-)
There was a problem hiding this comment.
I thought about it more (especially when reviewing this patch) and I don't know that introducing the --allow-web-ext-to-completely-break-my-profile option is the right thing to do.
It's nice because it gives a clear indication of not only keeping profile changes but also letting web-ext save its own settings. However, it will just be annoying to those who know what they are doing. Plus, there is really no valid use case (other than laziness) that requires someone to use their default profile with web-ext.
| for (const [idx, profile] of profilesDefs.entries()) { | ||
| content += `[Profile${idx}]\n`; | ||
| for (const k of Object.keys(profile)) { | ||
| // $FLOW_FIXME: test123 |
There was a problem hiding this comment.
I want to do that very often. Maybe a more descriptive reason for why fixme is needed would make it easier to fix it later.
kumar303
left a comment
There was a problem hiding this comment.
Looking good! Thanks for starting a patch so quickly.
| } catch (error) { | ||
| if (isErrorWithCode('ENOENT', error)) { | ||
| // No profiles exist yet, default to false (the default profile name contains a | ||
| // random generated component). |
There was a problem hiding this comment.
I'd like to see some debug logging here that shows profilesIniPath and error because there could be a bug upstream in guessing the path to this file.
src/firefox/index.js
Outdated
| for (const profile of finder.profiles) { | ||
| // Check if the profile dir path or name is one of the default profiles | ||
| // defined in the profiles.ini file. | ||
| if (DEFAULT_PROFILES_NAMES.indexOf(profile.Name) >= 0 || |
There was a problem hiding this comment.
Would this work as two if statements?
if (DEFAULT_PROFILES_NAMES.indexOf(profile.Name) >= 0) {
return true;
}
if (profile.Default === '1') {
// ...
}There was a problem hiding this comment.
It could be less noisy to use .includes(), then it seems simple enough to keep together if it makes sense.
There was a problem hiding this comment.
@mstriemer 👍 yeah, I did it mostly for compatibility, but to be fair we are already transpiling this files with babel and it is completely possible that the polyfill is already there and supported across the nodejs versions, I'll change it to use .includes().
There was a problem hiding this comment.
@kumar303 if I'm not wrong, we would miss the default profiles when specified by path and not marked as Default in the profiles.ini file
There was a problem hiding this comment.
we would miss the default profiles when specified by path and not marked as Default in the profiles.ini file
Oh, right! In that case, should the early return statement be removed?
There was a problem hiding this comment.
@kumar303 the early return should ensure that the usage error with the "Cannot use default profile with --keep-profile-changes..." message is logged also when the profiles.ini file doesn't exist yet and the user is using "default" or "dev-edition-default" as the firefox profile parameter.
src/firefox/index.js
Outdated
| const isForbiddenProfile = await isFirefoxDefaultProfile(profilePath); | ||
| if (isForbiddenProfile) { | ||
| throw new UsageError( | ||
| 'Using --keep-profile-changes' + |
There was a problem hiding this comment.
How about this to explain the problem better?
`Cannot use --keep-profile-changes on a default profile ("${profilePath}")` +
' because web-ext will make it insecure and unsuitable for daily use.' +
'\nSee https://github.com/mozilla/web-ext/issues/1005'| } | ||
|
|
||
| // Re-throw any unexpected exception. | ||
| throw error; |
There was a problem hiding this comment.
This doesn't appear to have test coverage. The tests still pass if I comment it out.
There was a problem hiding this comment.
you are right... "never trust the coverage report" :-) it is not marked as missed (nor executed actually) in the html report generated locally.
| return FakeProfileFinder; | ||
| } | ||
|
|
||
| async function createFakeProfilesIni(dirPath, profilesDefs) { // eslint-disable-line |
There was a problem hiding this comment.
I was curious about the lint error but when I removed this comment, yarn lint passed just fine. Maybe it's no longer needed?
There was a problem hiding this comment.
definitely not needed, it is a leftover from when I was rewriting some of the new tests.
| async () => { | ||
| return withTempDir(async (tmpDir) => { | ||
| const profilesDirPath = tmpDir.path(); | ||
| const FakeProfileFinder = createFakeProfileFinder(profilesDirPath); |
There was a problem hiding this comment.
Instead of using a fake ProfileFinder, could you just pass in an explicit baseProfileDir value to firefox.isDefaultProfile()? That would bypass ProfileFinder.locateUserDirectory() but continue to use a real ProfileFinder which would provide better test coverage.
There was a problem hiding this comment.
we are actually overriding only locateUserDirectory static method (which is only used directly in our helper, because we manually pass it to the created ProfileFinder and so it will never be discovered again), all the other methods are the real ones.
I also remembered right now that I added the sinon spies to add some additional assertion... that I should add :-)
| const isDefault = await firefox.isDefaultProfile( | ||
| 'manually-set-default', FakeProfileFinder | ||
| ); | ||
| const isNotDefault = await firefox.isDefaultProfile( |
There was a problem hiding this comment.
This seems like it should be in a separate unit test (unless it's sharing the same setup?) to make test failures easier to deal with
| }); | ||
| }); | ||
|
|
||
| it('allows profile path if is not listed as default in profiles.ini', |
There was a problem hiding this comment.
nit: allows profile path if it is not ...
| assert.equal(isDevEditionDefault, true); | ||
| }); | ||
|
|
||
| it('allows profile name if is not listed as default in profiles.ini', |
There was a problem hiding this comment.
nit: allows profile name if it is not ...
| ); | ||
| assert.equal(isManuallyDefault, true); | ||
|
|
||
| const isNotDefault = await firefox.isDefaultProfile( |
There was a problem hiding this comment.
This case looks like it's covered up above. Is there something different about testing it again here?
There was a problem hiding this comment.
you are right, it is a leftover of the rewrite
…ith a new test case
|
@kumar303 this should be ready now, it can also help to have a second pair of eyes that check the new behavior locally |
kumar303
left a comment
There was a problem hiding this comment.
Thanks, looks great. I had one minor comment but it's not necessary to block this patch on. I tested this out and got the error :)
| try { | ||
| await firefox.isDefaultProfile( | ||
| '/tmp/my-custom-profile-dir', | ||
| FakeProfileFinder, |
There was a problem hiding this comment.
I prefer to see optional function parameters passed as an object, like:
firefox.isDefaultProfile('/tmp/my-custom-profile-dir', {
profileFinder: FakeProfileFinder,
fsStat: fakeFsStat,
}); However, this preference was born in a world without Flow so I can see how it's not such a big deal anymore. Anyway, I just wanted to point it out since it would be the first time we have a function in web-ext that does optional params like this.
This PR extracts (and expands) the "checks for the Firefox default profile" pieces that we are working on in #968 to fix #1005