Rietveld Code Review Tool
Help | Bug tracker | Discussion group | Source code

Side by Side Diff: packagerSafari.py

Issue 11544056: Prepared buildtools for Safari (Closed)
Patch Set: Prepared buildtools for Safari Created Sept. 6, 2013, 2:45 p.m.
Left:
Right:
Use n/p to move between diff chunks; N/P to move between comments.
Jump to:
View unified diff | Download patch
« no previous file with comments | « packagerChrome.py ('k') | safariInfo.js.tmpl » ('j') | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
(Empty)
1 # coding: utf-8
2
3 # This file is part of the Adblock Plus build tools,
4 # Copyright (C) 2006-2013 Eyeo GmbH
5 #
6 # Adblock Plus is free software: you can redistribute it and/or modify
7 # it under the terms of the GNU General Public License version 3 as
8 # published by the Free Software Foundation.
9 #
10 # Adblock Plus is distributed in the hope that it will be useful,
11 # but WITHOUT ANY WARRANTY; without even the implied warranty of
12 # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13 # GNU General Public License for more details.
14 #
15 # You should have received a copy of the GNU General Public License
16 # along with Adblock Plus. If not, see <http://www.gnu.org/licenses/>.
17
18 import os
19 import re
20 import json
21 from urlparse import urlparse
22 from collections import OrderedDict
23
24 from packager import readMetadata, getDefaultFileName, getBuildVersion, getTempl ate, Files
25 from buildtools.packagerChrome import convertJS, importGeckoLocales, getIgnoredF iles, getPackageFiles, ImageConverter
26
27 def createPlist(params, files):
28 template = getTemplate('Info.plist.tmpl')
29 metadata = params['metadata']
30 catalog = json.loads(files['_locales/en_US/messages.json'])
31
32 def parse_section(section, depth=1):
33 rv = {}
34
35 if not metadata.has_section(section):
36 return rv
37
38 for opt in metadata.options(section):
39 bits = opt.split('_', depth)
40 key = bits.pop(-1).replace('_', ' ').title()
41 d = rv
42
43 for x in bits:
44 d = d.setdefault(x, {})
45
46 val = metadata.get(section, opt)
47
48 if val is True:
49 d[key] = '<true/>'
50 elif val is False:
51 d[key] = '<false/>'
52 elif isinstance(val, (int, long)):
53 d[key] = '<real>%d</real>' % val
54 else:
55 d[key] = '<string>%s</string>' % val
56
57 return rv
58
59 allowedDomains = set()
60 allowAllDomains = False
61 allowSecurePages = False
62
63 for perm in re.split(r'\s+', metadata.get('general', 'permissions')):
64 if perm == '<all_urls>':
65 allowAllDomains = True
66 allowSecurePages = True
67 continue
68
69 url = urlparse(perm)
70
71 if url.scheme == 'https':
72 allowSecurePages = True
73 elif url.scheme != 'http':
74 continue
75
76 if '*' in url.hostname:
77 allowAllDomains = True
78 continue
79
80 allowedDomains.add(url.hostname)
81
82 return template.render(
83 author=metadata.get('general', 'author'),
84 version=params['version'],
85 name=catalog['name']['message'],
86 description=catalog['description']['message'],
87 website=metadata.get('general', 'website'),
88 identifier=metadata.get('general', 'identifier'),
89 allowedDomains=allowedDomains,
90 allowAllDomains=allowAllDomains,
91 allowSecurePages=allowSecurePages,
92 contentScripts={
93 'start': metadata.get('contentScripts', 'document_start').split(),
94 'end': metadata.get('contentScripts', 'document_end' ).split(),
95 },
96 menus=parse_section('menus', 2),
97 toolbarItems=parse_section('toolbar_items'),
98 popovers=parse_section('popovers')
99 ).encode('utf-8')
100
101 def createBackgroundPage(params):
102 template = getTemplate('background.html.tmpl')
103 return template.render(
104 backgroundScripts=re.split(r'\s+', params['metadata'].get(
105 'general', 'backgroundScripts'
106 ))
107 ).encode('utf-8')
108
109 def createInfoModule(params):
110 template = getTemplate('safariInfo.js.tmpl')
111 return template.render(params).encode('utf-8');
112
113 def createSignedXarArchive(outFile, files, keyFile, certs):
114 import subprocess
115 import tempfile
116 import shutil
117 import errno
118 import M2Crypto
119
120 # write files to temporary directory and create a xar archive
121 dirname = tempfile.mkdtemp()
122 try:
123 for filename, contents in files.iteritems():
124 path = os.path.join(dirname, filename)
125
126 while True:
127 try:
128 file = open(path, 'wb')
129 break
130 except IOError, e:
131 if e.errno != errno.ENOENT:
132 raise
133 os.makedirs(os.path.dirname(path))
134
135 with file:
136 file.write(contents)
137
138 subprocess.check_output(
139 ['xar', '-czf', os.path.abspath(outFile), '--distribution'] + os.listdir(d irname),
140 cwd=dirname
141 )
142 finally:
143 shutil.rmtree(dirname)
144
145 # add placeholder signature and certificates to the xar archive, and get data to sign
146 key = M2Crypto.RSA.load_key(keyFile)
147 digestinfo_filename = tempfile.mktemp()
148 try:
149 subprocess.check_call(
150 [
151 'xar', '--sign', '-f', outFile,
152 '--digestinfo-to-sign', digestinfo_filename,
153 '--sig-size', str(len(key.sign('')))
154 ] + [
155 arg for cert in certs for arg in ('--cert-loc', cert)
156 ]
157 )
158
159 with open(digestinfo_filename, 'rb') as file:
160 digestinfo = file.read()
161 finally:
162 try:
163 os.unlink(digestinfo_filename)
164 except OSError, e:
165 if e.errno != errno.ENOENT:
166 raise
167
168 # sign data and inject signature into xar archive
169 fd, signature_filename = tempfile.mkstemp()
170 try:
171 try:
172 os.write(fd, key.private_encrypt(
173 digestinfo,
174 M2Crypto.RSA.pkcs1_padding
175 ))
176 finally:
177 os.close(fd)
178
179 subprocess.check_call(['xar', '--inject-sig', signature_filename, '-f', outF ile])
180 finally:
181 os.unlink(signature_filename)
182
183 def createBuild(baseDir, type, outFile=None, buildNum=None, releaseBuild=False, keyFile=None, certs=()):
184 metadata = readMetadata(baseDir, type)
185 version = getBuildVersion(baseDir, metadata, releaseBuild, buildNum)
186
187 if not outFile:
188 outFile = getDefaultFileName(baseDir, metadata, version, 'safariextz' if key File else 'zip')
189
190 params = {
191 'type': type,
192 'baseDir': baseDir,
193 'releaseBuild': releaseBuild,
194 'version': version,
195 'devenv': False,
196 'metadata': metadata,
197 }
198
199 files = Files(getPackageFiles(params), getIgnoredFiles(params),
200 process=lambda path, data: data)
201 if metadata.has_section('mapping'):
202 files.readMappedFiles(metadata.items('mapping'))
203 files.read(baseDir)
204
205 if metadata.has_section('convert_js'):
206 convertJS(params, files)
207
208 if metadata.has_section('convert_img'):
209 ImageConverter().convert(params, files)
210
211 if metadata.has_section('import_locales'):
212 importGeckoLocales(params, files)
213
214 files['lib/info.js'] = createInfoModule(params)
215 files['background.html'] = createBackgroundPage(params)
216 files['Info.plist'] = createPlist(params, files)
217
218 dirname = getDefaultFileName('', metadata, version, 'safariextension')
219 for filename in files.keys():
220 files[os.path.join(dirname, filename)] = files.pop(filename)
221
222 if keyFile:
223 createSignedXarArchive(outFile, files, keyFile, certs)
224 else:
225 files.zip(outFile)
OLDNEW
« no previous file with comments | « packagerChrome.py ('k') | safariInfo.js.tmpl » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld