-
Notifications
You must be signed in to change notification settings - Fork 0
/
manage.py
executable file
·246 lines (202 loc) · 8.27 KB
/
manage.py
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
#! /usr/bin/env python
import os
import sys
if __name__ == '__main__':
# This code is run if we're executed directly from the command-line.
myfile = os.path.abspath(__file__)
mydir = os.path.dirname(myfile)
sys.path.insert(0, os.path.join(mydir, 'python-modules'))
args = sys.argv[1:]
if not args:
args = ['help']
# Have paver run this very file as its pavement script.
args = ['-f', myfile] + args
import paver.tasks
paver.tasks.main(args)
sys.exit(0)
# This code is run if we're executed as a pavement script by paver.
import os
import sys
import xml.dom.minidom
import zipfile
import shutil
import distutils.dir_util
import time
import threading
import subprocess
import simplejson
from ConfigParser import ConfigParser
from paver.easy import *
# Path to the root of the extension, relative to where this script is
# located.
EXT_SUBDIR = "extension"
def clear_dir(dirname):
if os.path.exists(dirname) and os.path.isdir(dirname):
shutil.rmtree(dirname)
def find_profile_dir(name):
"""
Given the name of a Firefox profile, attempts to find the absolute
path to its directory. If it can't be found, None is returned.
"""
base_path = None
if sys.platform == "darwin":
base_path = os.path.expanduser(
"~/Library/Application Support/Firefox/"
)
elif sys.platform.startswith("win"):
# TODO: This only works on 2000/XP/Vista, not 98/Me.
appdata = os.environ["APPDATA"]
base_path = os.path.join(appdata, "Mozilla\\Firefox")
elif sys.platform == "cygwin":
appdata = os.environ["APPDATA"]
base_path = os.path.join(appdata, "Mozilla\\Firefox")
else:
base_path = os.path.expanduser("~/.mozilla/firefox/")
inifile = os.path.join(base_path, "profiles.ini")
config = ConfigParser()
config.read(inifile)
profiles = [section for section in config.sections()
if section.startswith("Profile")]
for profile in profiles:
if config.get(profile, "Name") == name:
# TODO: Look at IsRelative?
path = config.get(profile, "Path")
if not os.path.isabs(path):
path = os.path.join(base_path, path)
return path
return None
def get_install_rdf_dom(path_to_ext_root):
rdf_path = os.path.join(path_to_ext_root, "install.rdf")
rdf = xml.dom.minidom.parse(rdf_path)
return rdf
def get_install_rdf_property(path_to_ext_root, property):
rdf = get_install_rdf_dom(path_to_ext_root)
element = rdf.documentElement.getElementsByTagName(property)[0]
return element.firstChild.nodeValue
def resolve_options(options, ext_subdir = EXT_SUBDIR):
if not options.get('profile'):
options.profile = 'default'
options.my_dir = os.path.dirname(os.path.abspath(options.pavement_file))
options.profile_dir = find_profile_dir(options.profile)
options.path_to_ext_root = os.path.join(options.my_dir, ext_subdir)
options.ext_id = get_install_rdf_property(options.path_to_ext_root,
"em:id")
options.ext_version = get_install_rdf_property(options.path_to_ext_root,
"em:version")
options.ext_name = get_install_rdf_property(options.path_to_ext_root,
"em:name")
if options.profile_dir:
options.extension_file = os.path.join(options.profile_dir,
"extensions",
options.ext_id)
# If cygwin, change the path to windows format so firefox can
# understand it.
if sys.platform == "cygwin":
# TODO: Will this work if path_to_ext_root has spaces in it?
file = 'cygpath.exe -w ' + options.path_to_ext_root
path = "".join(os.popen(file).readlines())
path = path.replace("\n", " ").rstrip()
options.firefox_path_to_ext_root = path
else:
options.firefox_path_to_ext_root = options.path_to_ext_root
def remove_extension(options):
if not (options.profile_dir and
os.path.exists(options.profile_dir) and
os.path.isdir(options.profile_dir)):
raise BuildFailure("Can't resolve profile directory; aborting.")
files_to_remove = ["compreg.dat", "xpti.dat"]
for filename in files_to_remove:
abspath = os.path.join(options.profile_dir, filename)
if os.path.exists(abspath):
os.remove(abspath)
if os.path.exists(options.extension_file):
if os.path.isdir(options.extension_file):
shutil.rmtree(options.extension_file)
else:
os.remove(options.extension_file)
INSTALL_OPTIONS = [("profile=", "p", "Profile name.")]
JSBRIDGE_OPTIONS = [("port=", "p", "Port to use for jsbridge communication."),
("binary=", "b", "Path to Firefox binary.")]
@task
@cmdopts(INSTALL_OPTIONS)
def install(options):
"""Install the extension to a Firefox profile."""
resolve_options(options)
remove_extension(options)
extdir = os.path.dirname(options.extension_file)
if not os.path.exists(extdir):
distutils.dir_util.mkpath(extdir)
fileobj = open(options.extension_file, "w")
fileobj.write(options.firefox_path_to_ext_root)
fileobj.close()
print "Extension '%s' installed to profile '%s'." % (options.ext_id,
options.profile)
@task
@cmdopts(INSTALL_OPTIONS)
def uninstall(options):
"""Uninstall the extension from a Firefox profile."""
resolve_options(options)
remove_extension(options)
print "Extension '%s' uninstalled from profile '%s'." % (options.ext_id,
options.profile)
@task
def xpi(options):
"""Build a distributable xpi installer for the extension."""
resolve_options(options)
name = options.ext_name.lower().replace(" ", "")
zfname = "%s-%s.xpi" % (name, options.ext_version)
zf = zipfile.ZipFile(zfname, "w", zipfile.ZIP_DEFLATED)
for dirpath, dirnames, filenames in os.walk(options.path_to_ext_root):
for filename in filenames:
abspath = os.path.join(dirpath, filename)
arcpath = abspath[len(options.path_to_ext_root)+1:]
zf.write(abspath, arcpath)
print "Created %s." % zfname
def start_jsbridge(options):
import mozrunner
import jsbridge
resolve_options(options)
if not options.get('port'):
options.port = '24242'
options.port = int(options.port)
options.binary = options.get('binary')
plugins = [jsbridge.extension_path, options.path_to_ext_root]
profile = mozrunner.FirefoxProfile(
plugins=plugins,
preferences={'browser.startup.homepage' : 'about:blank',
'javascript.options.showInConsole' : True,
'browser.dom.window.dump.enabled' : True,
'startup.homepage_welcome_url' : 'about:blank'}
)
runner = mozrunner.FirefoxRunner(profile=profile,
binary=options.binary,
cmdargs=["-jsbridge", str(options.port)])
runner.start()
back_channel, bridge = jsbridge.wait_and_create_network("127.0.0.1",
options.port)
return Bunch(back_channel = back_channel,
bridge = bridge,
runner = runner)
@task
@cmdopts(JSBRIDGE_OPTIONS)
def run(options):
"""Run Firefox in a temporary new profile with the extension installed."""
remote = start_jsbridge(options)
try:
print "Now running, press Ctrl-C to stop."
remote.runner.wait()
except KeyboardInterrupt:
print "Received interrupt, stopping."
remote.runner.stop()
@task
def clean(options):
"""Removes all intermediate and non-essential files."""
EXTENSIONS_TO_REMOVE = [".pyc", ".orig"]
for dirpath, dirnames, filenames in os.walk(os.getcwd()):
if ".hg" in dirnames:
dirnames.remove(".hg")
for filename in filenames:
fullpath = os.path.join(dirpath, filename)
ext = os.path.splitext(filename)[1]
if ext in EXTENSIONS_TO_REMOVE:
os.remove(fullpath)