berstend / puppeteer-extra

💯 Teach puppeteer new tricks through plugins.
https://extra.community
MIT License
6.39k stars 738 forks source link

[Feature] Ability to write other preference files (i.e. "Local State") #548

Open maiux opened 3 years ago

maiux commented 3 years ago

Feature request Trying to customize Chrome preferences I saw that puppeteer-extra-plugin-user-preferences and puppeteer-extra-plugin-user-data-dir plugins allow to save "Preferences" in Profile/Default folder. Some Chrome references like browser.confirm_to_quit are saved to "Local State" in the user data dir. If I'm not wrong, at the time of writing, puppeteer-extra-plugin-user-data-dir will fail if you try to use a target different from "Preferences". Can you consider to allow "Local State" writing? This is specially needed on macOS. Thank you

VSilantyev commented 2 years ago

Agreed, that will be a good feature.

For now I wrote a small plugin to implement this feature, almost entirely copy-pasted from the user-prefs plugin. Save as puppeteer-extra-plugin-local-state.js

'use strict'

const merge = require('deepmerge')

const { PuppeteerExtraPlugin } = require('puppeteer-extra-plugin')

/**
 * Launch puppeteer with arbitrary local state preferences.
 *
 * Overview:
 * https://chromium.googlesource.com/chromium/src/+/master/chrome/common/pref_names.cc
 *
 * @param {Object} opts - Options
 * @param {Object} [opts.localState={}] - An object containing the preferences.
 *
 * @example
 * const puppeteer = require('puppeteer-extra')
 * puppeteer.use(require('puppeteer-extra-plugin-local-state')({localState: {
 *   browser: {
 *     confirm_to_quit: false
 *   }
 * }}))
 * const browser = await puppeteer.launch()
 */
class Plugin extends PuppeteerExtraPlugin {
  constructor(opts = {}) {
    super(opts)

    const defaults = {
      localState: {}
    }

    this._opts = Object.assign(defaults, opts)
  }

  get name() {
    return 'local-state'
  }

  get requirements() {
    return new Set(['runLast'])
  }

  get dependencies() {
    return new Set(['user-data-dir'])
  }

  get data() {
    if (Object.keys(this._opts.localState).length === 0) {
        return []
    }

    return [
      {
        name: 'userDataDirFile',
        value: {
          target: 'Profile',
          file: '../Local State',
          contents: JSON.stringify(this._opts.localState, null, 2)
        }
      }
    ]
  }

}

module.exports = function(pluginConfig) {
  return new Plugin(pluginConfig)
}