1#!/usr/bin/env python
2
3# This Source Code Form is subject to the terms of the Mozilla Public
4# License, v. 2.0. If a copy of the MPL was not distributed with this file,
5# You can obtain one at http://mozilla.org/MPL/2.0/.
6
7"""
8Creates and/or modifies a Firefox profile.
9The profile can be modified by passing in addons to install or preferences to set.
10If no profile is specified, a new profile is created and the path of the
11resulting profile is printed.
12"""
13from __future__ import absolute_import, print_function
14
15import sys
16from optparse import OptionParser
17from .prefs import Preferences
18from .profile import FirefoxProfile
19from .profile import Profile
20
21__all__ = ['MozProfileCLI', 'cli']
22
23
24class MozProfileCLI(object):
25    """The Command Line Interface for ``mozprofile``."""
26
27    module = 'mozprofile'
28    profile_class = Profile
29
30    def __init__(self, args=sys.argv[1:], add_options=None):
31        self.parser = OptionParser(description=__doc__)
32        self.add_options(self.parser)
33        if add_options:
34            add_options(self.parser)
35        (self.options, self.args) = self.parser.parse_args(args)
36
37    def add_options(self, parser):
38
39        parser.add_option("-p", "--profile", dest="profile",
40                          help="The path to the profile to operate on. "
41                          "If none, creates a new profile in temp directory")
42        parser.add_option("-a", "--addon", dest="addons",
43                          action="append", default=[],
44                          help="Addon paths to install. Can be a filepath, "
45                          "a directory containing addons, or a url")
46        parser.add_option("--addon-manifests", dest="addon_manifests",
47                          action="append",
48                          help="An addon manifest to install")
49        parser.add_option("--pref", dest="prefs",
50                          action='append', default=[],
51                          help="A preference to set. "
52                          "Must be a key-value pair separated by a ':'")
53        parser.add_option("--preferences", dest="prefs_files",
54                          action='append', default=[],
55                          metavar="FILE",
56                          help="read preferences from a JSON or INI file. "
57                          "For INI, use 'file.ini:section' to specify a particular section.")
58
59    def profile_args(self):
60        """arguments to instantiate the profile class"""
61        return dict(profile=self.options.profile,
62                    addons=self.options.addons,
63                    addon_manifests=self.options.addon_manifests,
64                    preferences=self.preferences())
65
66    def preferences(self):
67        """profile preferences"""
68
69        # object to hold preferences
70        prefs = Preferences()
71
72        # add preferences files
73        for prefs_file in self.options.prefs_files:
74            prefs.add_file(prefs_file)
75
76        # change CLI preferences into 2-tuples
77        separator = ':'
78        cli_prefs = []
79        for pref in self.options.prefs:
80            if separator not in pref:
81                self.parser.error("Preference must be a key-value pair separated by "
82                                  "a ':' (You gave: %s)" % pref)
83            cli_prefs.append(pref.split(separator, 1))
84
85        # string preferences
86        prefs.add(cli_prefs, cast=True)
87
88        return prefs()
89
90    def profile(self, restore=False):
91        """create the profile"""
92
93        kwargs = self.profile_args()
94        kwargs['restore'] = restore
95        return self.profile_class(**kwargs)
96
97
98def cli(args=sys.argv[1:]):
99    """ Handles the command line arguments for ``mozprofile`` via ``sys.argv``"""
100
101    # add a view method for this cli method only
102    def add_options(parser):
103        parser.add_option('--view', dest='view',
104                          action='store_true', default=False,
105                          help="view summary of profile following invocation")
106        parser.add_option('--firefox', dest='firefox_profile',
107                          action='store_true', default=False,
108                          help="use FirefoxProfile defaults")
109
110    # process the command line
111    cli = MozProfileCLI(args, add_options)
112
113    if cli.args:
114        cli.parser.error("Program doesn't support positional arguments.")
115
116    if cli.options.firefox_profile:
117        cli.profile_class = FirefoxProfile
118
119    # create the profile
120    profile = cli.profile()
121
122    if cli.options.view:
123        # view the profile, if specified
124        print(profile.summary())
125        return
126
127    # if no profile was passed in print the newly created profile
128    if not cli.options.profile:
129        print(profile.profile)
130
131
132if __name__ == '__main__':
133    cli()
134