Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

fix: Can't run with specified profile name and --keep-profile-changes #968

Closed
wants to merge 17 commits into from
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
61 changes: 60 additions & 1 deletion src/firefox/index.js
Original file line number Diff line number Diff line change
Expand Up @@ -239,8 +239,38 @@ export type UseProfileParams = {
app?: PreferencesAppName,
configureThisProfile?: ConfigureProfileFn,
customPrefs?: FirefoxPreferences,
createProfileFinder?: typeof defaultCreateProfileFinder,
};

export interface IProfileFinder {
getPath(string): Promise<string>;
}

export function defaultCreateProfileFinder(userDirectoryPath?: string) {
const finder = new FirefoxProfile.Finder(userDirectoryPath);
const readProfiles = promisify(finder.readProfiles, finder);
const getPath = promisify(finder.getPath, finder);
return async (profileName: string) => {
const profilesIniPath = path.join(
userDirectoryPath || FirefoxProfile.Finder.locateUserDirectory(),
'profiles.ini');
try {
await fs.stat(profilesIniPath);
} catch (error) {
if (isErrorWithCode('ENOENT', error)) {
log.warn('No firefox profiles exist');
}
}
await readProfiles();
const hasProfileName = finder.profiles.filter(
(profileDef) => profileDef.Name === profileName).length !== 0;
if (hasProfileName) {
return await getPath(profileName);
}
};
}


// Use the target path as a Firefox profile without cloning it

export async function useProfile(
Expand All @@ -249,9 +279,38 @@ export async function useProfile(
app,
configureThisProfile = configureProfile,
customPrefs = {},
createProfileFinder = defaultCreateProfileFinder,
}: UseProfileParams = {},
): Promise<FirefoxProfile> {
const profile = new FirefoxProfile({destinationDirectory: profilePath});
let destinationDirectory;
const getProfilePath = createProfileFinder();
const dirExists = await isDirectory(profilePath);
if (dirExists) {
log.debug(`Using profile directory from "${profilePath}"`);
if (profilePath === getProfilePath('default') ||
profilePath === getProfilePath('dev-edition-default')) {
throw new WebExtError(
`Cannot use profile at "${profilePath}"`
);
}
destinationDirectory = profilePath;
} else {
log.debug(`Assuming ${profilePath} is a named profile`);
if (profilePath === 'default' ||
profilePath === 'dev-edition-default') {
throw new WebExtError(
`Cannot use the blacklisted named profile "${profilePath}"`
);
}
destinationDirectory = getProfilePath(profilePath);
if (!destinationDirectory) {
throw new UsageError(
`The request "${profilePath}" profile name
cannot be resolved to a profile path`
);
}
}
const profile = new FirefoxProfile({destinationDirectory});
return await configureThisProfile(profile, {app, customPrefs});
}

Expand Down
259 changes: 242 additions & 17 deletions tests/unit/test-firefox/test.firefox.js
Original file line number Diff line number Diff line change
Expand Up @@ -300,30 +300,220 @@ describe('firefox', () => {
describe('useProfile', () => {

it('resolves to a FirefoxProfile instance', () => withBaseProfile(
(baseProfile) => {
const configureThisProfile = (profile) => Promise.resolve(profile);
return firefox.useProfile(baseProfile.path(), {configureThisProfile})
.then((profile) => {
assert.instanceOf(profile, FirefoxProfile);
async (baseProfile) => {
try {
const app = 'fennec';
const configureThisProfile = (profile) => Promise.resolve(profile);
const createProfileFinder = () => {
return (profilePath) => Promise.resolve(profilePath);
};
const profile = await firefox.useProfile(baseProfile.path(), {
app,
configureThisProfile,
createProfileFinder,
});
assert.instanceOf(profile, FirefoxProfile);
} catch (error) {
throw error;
}
}
));
));

it('configures a profile', () => withBaseProfile(
(baseProfile) => {
const configureThisProfile =
sinon.spy((profile) => Promise.resolve(profile));
const app = 'fennec';
const profilePath = baseProfile.path();
return firefox.useProfile(profilePath, {app, configureThisProfile})
.then((profile) => {
assert.equal(configureThisProfile.called, true);
assert.equal(configureThisProfile.firstCall.args[0], profile);
assert.equal(configureThisProfile.firstCall.args[1].app, app);
});
async (baseProfile) => {
try {
const app = 'fennec';
const configureThisProfile =
sinon.spy((profile) => Promise.resolve(profile));
const createProfileFinder = () => {
return (profilePath) => Promise.resolve(profilePath);
};
const profilePath = baseProfile.path();
const profile = await firefox.useProfile(profilePath,
{
app,
configureThisProfile,
createProfileFinder,
});
assert.equal(configureThisProfile.called, true);
assert.equal(configureThisProfile.firstCall.args[0], profile);
assert.equal(configureThisProfile.firstCall.args[1].app, app);
} catch (error) {
throw error;
}
}
));

// it('configures a named profile', async () => {
// try {
// const app = 'fennec';
// const configureThisProfile =
// sinon.spy((profile) => Promise.resolve(profile));
// const profileName = 'test';
// const profileFinder = {
// getPath: sinon.spy((name) =>
// Promise.resolve(name)),
// hasProfileName: () => Promise.resolve(true),
// };
// const createProfileFinder = () => profileFinder;
// const profile = await firefox.useProfile(profileName,
// {
// app,
// configureThisProfile,
// createProfileFinder,
// });
// assert.equal(configureThisProfile.called, true);
// assert.equal(configureThisProfile.firstCall.args[0], profile);
// assert.equal(configureThisProfile.firstCall.args[1].app, app);
// assert.equal(profileFinder.getPath.callCount, 3);
// } catch (error) {
// throw error;
// }
// }
// );
//
// it('configures a profile with given path', () => withTempDir(
// async (tmpDir) => {
// try {
// const app = 'fennec';
// const configureThisProfile =
// sinon.spy((profile) => Promise.resolve(profile));
// const profilePath = tmpDir.path();
// const profileFinder = {
// getPath: sinon.spy((pathToProfile) =>
// Promise.resolve(pathToProfile)),
// hasProfileName: () => Promise.resolve(true),
// };
// const createProfileFinder = () => profileFinder;
// const profile = await firefox.useProfile(profilePath,
// {
// app,
// configureThisProfile,
// createProfileFinder,
// });
// assert.equal(configureThisProfile.called, true);
// assert.equal(configureThisProfile.firstCall.args[0], profile);
// assert.equal(configureThisProfile.firstCall.args[1].app, app);
// assert.equal(profileFinder.getPath.callCount, 2);
// } catch (error) {
// throw error;
// }
// }
// ));
//
// it('does not configure named profile default', async () => {
// try {
// const app = 'fennec';
// const configureThisProfile =
// sinon.spy((profile) => Promise.resolve(profile));
// const createProfileFinder = () => {
// return {
// getPath: () => Promise.resolve(),
// hasProfileName: () => Promise.resolve(true),
// };
// };
// const profile = await firefox.useProfile('default',
// {
// app,
// configureThisProfile,
// createProfileFinder,
// });
// assert.equal(configureThisProfile.called, true);
// assert.equal(configureThisProfile.firstCall.args[0], profile);
// assert.equal(configureThisProfile.firstCall.args[1].app, app);
// } catch (error) {
// assert.instanceOf(error, WebExtError);
// assert.match(error.message,
// /Cannot use the blacklisted named profile "default"+/);
// }
// });
//
// it('does not configure named profile dev-edition-default', async () => {
// try {
// const app = 'fennec';
// const configureThisProfile =
// sinon.spy((profile) => Promise.resolve(profile));
// const createProfileFinder = () => {
// return {
// getPath: () => Promise.resolve(),
// hasProfileName: () => Promise.resolve(true),
// };
// };
// const profile = await firefox.useProfile('dev-edition-default',
// {
// app,
// configureThisProfile,
// createProfileFinder,
// });
// assert.equal(configureThisProfile.called, true);
// assert.equal(configureThisProfile.firstCall.args[0], profile);
// assert.equal(configureThisProfile.firstCall.args[1].app, app);
// } catch (error) {
// assert.instanceOf(error, WebExtError);
// assert.match(error.message,
// /Cannot use the blacklisted named profile "dev-edition-default"+/);
// }
// });
//
// it('does not configure profile at default', () => withTempDir(
// async (tmpDir) => {
// try {
// const app = 'fennec';
// const configureThisProfile =
// sinon.spy((profile) => Promise.resolve(profile));
// const defaultPath = tmpDir.path();
// const createProfileFinder = () => {
// return {
// getPath: () => Promise.resolve(defaultPath),
// hasProfileName: () => Promise.resolve(true),
// };
// };
// const profile = await firefox.useProfile(defaultPath,
// {
// app,
// configureThisProfile,
// createProfileFinder,
// });
// assert.equal(configureThisProfile.called, true);
// assert.equal(configureThisProfile.firstCall.args[0], profile);
// assert.equal(configureThisProfile.firstCall.args[1].app, app);
// } catch (error) {
// assert.instanceOf(error, WebExtError);
// assert.match(error.message,
// /Cannot use profile at+/);
// }
// }
// ));
//
// it('does not configure profile at dev-edition-default', () => withTempDir(
// async (tmpDir) => {
// try {
// const app = 'fennec';
// const configureThisProfile =
// sinon.spy((profile) => Promise.resolve(profile));
// const defaultDevPath = tmpDir.path();
// const createProfileFinder = () => {
// return {
// getPath: () => Promise.resolve(defaultDevPath),
// hasProfileName: () => Promise.resolve(true),
// };
// };
// const profile = await firefox.useProfile(defaultDevPath,
// {
// app,
// configureThisProfile,
// createProfileFinder,
// });
// assert.equal(configureThisProfile.called, true);
// assert.equal(configureThisProfile.firstCall.args[0], profile);
// assert.equal(configureThisProfile.firstCall.args[1].app, app);
// } catch (error) {
// assert.instanceOf(error, WebExtError);
// assert.match(error.message,
// /Cannot use profile at+/);
// }
// }
// ));
});

describe('configureProfile', () => {
Expand Down Expand Up @@ -585,4 +775,39 @@ describe('firefox', () => {
});

});

// describe('defaultCreateProfileFinder', () => {
// it('gives a warning if no firefox profiles exist', () => withTempDir(
// async (tmpDir) => {
// try {
// const profilesPath = tmpDir.path();
// const profileFinder = firefox.defaultCreateProfileFinder(
// profilesPath);
// const profileExists = await profileFinder.hasProfileName('test');
// assert.equal(profileExists, false);
// } catch (e) {
// throw e;
// }
// }
// ));
// it('gives a warning if no firefox profiles exist', () => withTempDir(
// async (tmpDir) => {
// try {
// const profilesPath = tmpDir.path();
// const profileFinder = firefox.defaultCreateProfileFinder(
// profilesPath);
// const profilesIniPath = path.join(profilesPath, 'profiles.ini');
// const profileContents = `[Profile0]
// Name=test
// IsRelative=1
// Path=fake-profile.test`;
// await fs.writeFile(profilesIniPath, profileContents);
// const profileExists = await profileFinder.hasProfileName('test');
// assert.equal(profileExists, true);
// } catch (e) {
// throw e;
// }
// }
// ));
// });
});