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

New: Add flag to use default user profile instead #48

Merged
merged 1 commit into from
Nov 27, 2017

Conversation

molant
Copy link
Contributor

@molant molant commented Nov 7, 2017

Add a new property defaultProfile to use the default user's profile in Chrome instead of creating a new one. By default this value is false so it doesn't change the current behavior.

Close #47

Copy link
Collaborator

@patrickhulce patrickhulce left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

thanks very much for the contribution anton! :)

`--remote-debugging-port=${this.port}`,
let flags = DEFAULT_FLAGS.concat([`--remote-debugging-port=${this.port}`]);

if (!this.defaultProfile) {
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

let's also update the logic for conditionally creating/destroying the tmp directory

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I'm still using a tmp directory for the logs and the pid file. If I don't use one, should I write those files into the default profile? It can get messy because then I'll have to guess the path of the default profile and delete each file individually.

README.md Outdated
@@ -50,6 +50,10 @@ npm install chrome-launcher
// * Otherwise, a detected Chrome (stable) will be used
chromePath: string;

// (optional) Uses the default Chrome profile instead of creating a new one
// Default: false
defaultProfile: boolean;
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

to 🚲 🏠 on name, it's not super clear that this will currently ignore whatever is set as userDataDir

some potential others

  • forceDefaultProfile
  • ignoreUserDataDir
  • overrideUserDataDirWithDefault

alternatively, we could make this the behavior when false is explicitly passed to userDataDir and just document that it results in the default profile being used?

Copy link
Contributor Author

@molant molant Nov 8, 2017

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I like forceDefaultProfile.

alternatively, we could make this the behavior when false is explicitly passed to userDataDir and just document that it results in the default profile being used?

Do you want me to add this behavior on top of the current one or instead of the new parameter? userDataDir will probably be a cleaner API for the user, but I was looking into the code and I had to change where the pid files were created, etc. It was starting to get a bit too complicated so I preferred to wait for feedback.

Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Do you want me to add this behavior on top of the current one or instead of the new parameter?

My personal preference would probably be the boolean approach instead of the new flag. I agree it's a cleaner API for consumers. OTOH, forceDefaultProfile is fairly explicit while userDataDir: false is a little more opaque even if the logic tracks of "do not pass in --user-data-dir".

userDataDir will probably be a cleaner API for the user, but I was looking into the code and I had to start changing where the pid files were created, etc. It was starting to get a bit too complicated so I preferred to wait for feedback.

Hmmm, I suppose there's not a clear and obvious alternative for where else to stick the pid file process.cwd() might be ok but permissions and litter could get messy. Keeping the tmp directory for now seems ok to me.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

OTOH, forceDefaultProfile is fairly explicit while userDataDir: false is a little more opaque even if the logic tracks of "do not pass in --user-data-dir".

Been trying to do this and there are some things to take into account. The main problem is "what happens if the users puts true instead of a path or false? Also I need to update the logic in a couple places to validate that userDataDir is a string instead of boolean, otherwise TypeScript will complain.

This is my current code in the constructor:

if (typeof this.opts.userDataDir === 'boolean') {
      if (!this.opts.userDataDir) {
        this.forceDefaultProfile = true;
      } else {
        throw new Error('userDataDir has to be false or a path');
      }
    } else {
      this.forceDefaultProfile = defaults(this.opts.forceDefaultProfile, false);
    }
  }

What do you think? Should I just add the forceDefaultProfile parameter or continue down this path?

@molant
Copy link
Contributor Author

molant commented Nov 8, 2017

@patrickhulce I've created a new PR that just changes the property to forceDefaultProfile in #49
And updated this one to allow userDataString to be false. Let me know what do you prefer.

@patrickhulce
Copy link
Collaborator

I really like the ergonomics of userDataDir: false, but feels like we need a bit of cleanup internally to reflect that the tmp dir is now the logDir, etc

lemme take the temperature of some other folks before having you go down the rabbit hole if I'm alone in preferring this over #49 :)

@brendankenny @samccone any preferences on this?

Copy link
Member

@brendankenny brendankenny left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

userDataDir: false looks good to me.

Can we drop forceDefaultProfile as an external option at the same time? It would be nice to avoid options interfering with each other if possible, and it seems like it's not necessary(?).

@@ -337,7 +350,9 @@ export class Launcher {
delete this.errFile;
}

this.rimraf(this.userDataDir, () => resolve());
if (typeof this.userDataDir === 'string') {
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

maybe just check this.forceDefaultProfile?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Need to do that check or otherwise TypeScript will complain it can be Boolean or string

Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

well we can always keep userDataDir a string inside this class, it's just boolean|string in this.opts


if (typeof this.opts.userDataDir === 'boolean') {
if (!this.opts.userDataDir) {
this.forceDefaultProfile = true;
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

bikeshed: if it's a private property only, something like useDefaultProfile is another possible name

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

OK

if (!this.opts.userDataDir) {
this.forceDefaultProfile = true;
} else {
throw new Error('userDataDir has to be false or a path');
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

nit: maybe userDataDir must be false or a path

@molant
Copy link
Contributor Author

molant commented Nov 10, 2017

Can we drop forceDefaultProfile as an external option at the same time?

Sure, I'll close the other PR and update this one.

@molant
Copy link
Contributor Author

molant commented Nov 10, 2017

OK, I've updated the PR with @brendankenny's feedback. Once everyone is OK I'll squash the commits.

Let me know if there is something else you want me to do here!

README.md Outdated
@@ -50,9 +50,10 @@ npm install chrome-launcher
// * Otherwise, a detected Chrome (stable) will be used
chromePath: string;

// (optional) Chrome profile path to use
// (optional) Chrome profile path to use, if set to `false` then the default profile will be used.
// This is the same as setting `forceDefaultProfile` to `true`
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

let's remove this now that forceDefaultProfile isn't an option anymore

@@ -33,6 +33,7 @@ export interface Options {
handleSIGINT?: boolean;
chromePath?: string;
userDataDir?: string;
forceDefaultProfile?: boolean;
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

remove this now since we're using useDefaultProfile for the same purpose?

@@ -337,7 +350,9 @@ export class Launcher {
delete this.errFile;
}

this.rimraf(this.userDataDir, () => resolve());
if (typeof this.userDataDir === 'string') {
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

well we can always keep userDataDir a string inside this class, it's just boolean|string in this.opts

throw new Error('userDataDir must be false or a path');
}
} else {
this.useDefaultProfile = defaults(this.opts.forceDefaultProfile, false);
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

do we need this now? I guess we could explicitly set this.useDefaultProfile to false now that forceDefaultProfile is gone

@molant molant force-pushed the master branch 3 times, most recently from 9151a2f to a56fe92 Compare November 11, 2017 06:22
@molant
Copy link
Contributor Author

molant commented Nov 11, 2017

I'll take a look at the tests on Monday. Thanks for the feedback!

@molant
Copy link
Contributor Author

molant commented Nov 13, 2017

@patrickhulce I've updated the tests. Had to add a new dev-dependency to mock the makeTmpDir because I've moved that part to the constructor so I didn't have to copy paste the condition again in prepare.

Let me know if I should change something else.

Thanks!

Copy link
Member

@brendankenny brendankenny left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

because I've moved that part to the constructor

hmm, I think placement of that was actually intentional, so that merely constructing ChromeLauncher wouldn't have any side effects (like creating a tmp directory) until instance.launch() was called.

Sorry to make this harder :)

@molant
Copy link
Contributor Author

molant commented Nov 13, 2017

so that merely constructing ChromeLauncher wouldn't have any side effects

I'm just setting the value of userDataDir, no tmp directory gets created.

Do you still want me to change it?

@brendankenny
Copy link
Member

I'm just setting the value of userDataDir, no tmp directory gets created.

doesn't the this.makeTmpDir() call do that?

@molant
Copy link
Contributor Author

molant commented Nov 13, 2017

You are right, I thought the magic was happening in this.fs.openSync

Will change it and try to make it DRY

@molant molant force-pushed the master branch 3 times, most recently from e7d26ac to 3563c51 Compare November 13, 2017 23:19
@molant
Copy link
Contributor Author

molant commented Nov 13, 2017

@brendankenny @patrickhulce 🤞

Copy link
Collaborator

@patrickhulce patrickhulce left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

lgtm % nits! thanks for pushing through on this @molant!

`--remote-debugging-port=${this.port}`,
let flags = DEFAULT_FLAGS.concat([`--remote-debugging-port=${this.port}`]);

if (!this.useDefaultProfile) {
// Place Chrome profile in a custom location we'll rm -rf later
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

let's maybe move this line of the comment down to where we create it with a bit of explanation on the new logic

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Done

yarn.lock Outdated
@@ -1,1494 +1,1494 @@
# THIS IS AN AUTOGENERATED FILE. DO NOT EDIT THIS FILE DIRECTLY.
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

this just seems like noise without any new deps, would you mind reverting this?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Done

Copy link
Member

@brendankenny brendankenny left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

would you mind adding a test for this?

e.g. a new one in the style of this test:

it('removes --disable-extensions from flags on enableExtensions', async () => {
const spawnStub = stub().returns({pid: 'some_pid'});
const chromeInstance = new Launcher(
{enableExtensions: true},
{fs: fsMock as any, rimraf: spy() as any, spawn: spawnStub as any});
stub(chromeInstance, 'waitUntilReady').returns(Promise.resolve());
chromeInstance.prepare();
try {
await chromeInstance.launch();
} catch (err) {
return Promise.reject(err);
}
const chromeFlags = spawnStub.getCall(0).args[1] as string[];
assert.ok(!chromeFlags.includes('--disable-extensions'));
});

could just check that there's no --user-data-dir in the flags when userDataDir is false

@@ -153,7 +155,18 @@ export class Launcher {
throw new Error(`Platform ${platform} is not supported`);
}

this.userDataDir = this.opts.userDataDir || this.makeTmpDir();
if (typeof this.opts.userDataDir === 'boolean') {
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

maybe set this.useDefaultProfile in the profile?

Then in the constructor it would just be something like

if (typeof this.opts.userDataDir === 'boolean') {
  if (!this.opts.userDataDir) {
    this.useDefaultProfile = true;
  } else {
    throw new Error('userDataDir must be false or a path');
  }
} else {
  this.useDefaultProfile = false;
}

That would immediately thrown on an invalid true for userDataDir, and it means that this line could just be
this.userDataDir = this.opts.userDataDir || this.makeTmpDir();

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

that might be too clever for the typescript compiler, I guess. To go with @patrickhulce's suggestion to keep this.userDataDir an optional string, in the constructor could do

if (typeof this.opts.userDataDir === 'boolean') {
  if (!this.opts.userDataDir) {
    this.useDefaultProfile = true;
    this.userDataDir = undefined;
  } else {
    throw new Error('userDataDir must be false or a path');
  }
} else {
  this.useDefaultProfile = false;
  this.userDataDir = this.opts.userDataDir;
}

the compiler seems to understand this.opts.userDataDir would then be string|undefined by the last line there.

Then here in prepare() it would just be

this.userDataDir = this.userDataDir || this.makeTmpDir();

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Used your latest comment for the change.

@molant molant force-pushed the master branch 4 times, most recently from f1d1cda to fe5d8fb Compare November 14, 2017 04:48
@molant
Copy link
Contributor Author

molant commented Nov 14, 2017

would you mind adding a test for this?

Done

@molant
Copy link
Contributor Author

molant commented Nov 14, 2017

@brendankenny @patrickhulce let me know if you want me to change anything else!

@molant
Copy link
Contributor Author

molant commented Nov 16, 2017

@brendankenny @patrickhulce ping. Anything else I should do to get this merged?

Thanks!

@paulirish paulirish merged commit 4cc9c07 into GoogleChrome:master Nov 27, 2017
@paulirish
Copy link
Member

shipped in 0.9.0

@molant
Copy link
Contributor Author

molant commented Nov 28, 2017

Thank you all!

@glebmachine
Copy link

Could you provide any examples of use into documentation?

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

How to use default userDataDir on launch?
5 participants