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

Side by Side Diff: sitescripts/extensions/bin/legacy/packagerSafari.py

Issue 29589691: Issue 5757 - Update buildtools dependency, (re)move legacy extensions (Closed)
Patch Set: Created Oct. 26, 2017, 10:50 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
OLDNEW
(Empty)
1 # This Source Code Form is subject to the terms of the Mozilla Public
tlucas 2017/11/02 10:03:29 This code was (apart from the below exception) com
Vasily Kuznetsov 2017/11/30 17:34:00 Acknowledged.
2 # License, v. 2.0. If a copy of the MPL was not distributed with this
3 # file, You can obtain one at http://mozilla.org/MPL/2.0/.
4
5 import base64
6 import collections
7 import ConfigParser
8 import json
9 import os
10 import re
11 from urlparse import urlparse
12
13 from buildtools.packager import readMetadata, getDefaultFileName, getBuildVersio n, getTemplate, Files
14 from buildtools.packagerChrome import import_locales, getIgnoredFiles, getPackag eFiles, defaultLocale, createScriptPage
15
16
17 def processFile(path, data, params):
18 return data
19
20
21 def createManifest(params, files):
22 template = getTemplate('Info.plist.tmpl', autoEscape=True)
23 metadata = params['metadata']
24 catalog = json.loads(files['_locales/%s/messages.json' % defaultLocale])
25
26 def parse_section(section, depth=1):
27 result = {}
28
29 if not metadata.has_section(section):
30 return result
31
32 for opt in metadata.options(section):
33 bits = opt.split('_', depth)
34 key = bits.pop().replace('_', ' ').title()
35 val = metadata.get(section, opt)
36
37 try:
38 val = int(val)
39 except ValueError:
40 try:
41 val = float(val)
42 except ValueError:
43 pass
44
45 reduce(lambda d, x: d.setdefault(x, {}), bits, result)[key] = val
46
47 return result
48
49 def get_optional(*args):
50 try:
51 return metadata.get(*args)
52 except ConfigParser.Error:
53 return None
54
55 allowedDomains = set()
56 allowAllDomains = False
57 allowSecurePages = False
58
59 for perm in metadata.get('general', 'permissions').split():
60 if perm == '<all_urls>':
61 allowAllDomains = True
62 allowSecurePages = True
63 continue
64
65 url = urlparse(perm)
66
67 if url.scheme == 'https':
68 allowSecurePages = True
69 elif url.scheme != 'http':
70 continue
71
72 if '*' in url.hostname:
73 allowAllDomains = True
74 continue
75
76 allowedDomains.add(url.hostname)
77
78 return template.render(
79 basename=metadata.get('general', 'basename'),
80 version=params['version'],
81 releaseBuild=params['releaseBuild'],
82 name=catalog['name']['message'],
83 description=catalog['description']['message'],
84 author=get_optional('general', 'author'),
85 homepage=get_optional('general', 'homepage'),
86 updateURL=get_optional('general', 'updateURL'),
87 allowedDomains=allowedDomains,
88 allowAllDomains=allowAllDomains,
89 allowSecurePages=allowSecurePages,
90 startScripts=(get_optional('contentScripts', 'document_start') or '').sp lit(),
91 endScripts=(get_optional('contentScripts', 'document_end') or '').split( ),
92 menus=parse_section('menus', 2),
93 toolbarItems=parse_section('toolbar_items'),
94 popovers=parse_section('popovers'),
95 developerIdentifier=params.get('developerIdentifier')
96 ).encode('utf-8')
97
98
99 def createInfoModule(params):
100 template = getTemplate('safariInfo.js.tmpl')
101 return template.render(params).encode('utf-8')
102
103
104 def _get_sequence(data):
105 from Crypto.Util import asn1
106 sequence = asn1.DerSequence()
107 sequence.decode(data)
108 return sequence
109
110
111 def get_developer_identifier(certs):
112 for cert in certs:
113 # See https://tools.ietf.org/html/rfc5280#section-4
114 tbscertificate = _get_sequence(base64.b64decode(cert))[0]
115 subject = _get_sequence(tbscertificate)[5]
116
117 # We could decode the subject but since we have to apply a regular
118 # expression on CN entry anyway we can just skip that.
119 m = re.search(r'Safari Developer: \((\S*?)\)', subject)
120 if m:
121 return m.group(1)
122
123 raise Exception('No Safari developer certificate found in chain')
124
125
126 def convertJS(params, files):
tlucas 2017/11/02 10:03:29 Thins function was copied from packagerChrome.py i
127 output_files = collections.OrderedDict()
128 args = {}
129
130 for item in params['metadata'].items('convert_js'):
131 name, value = item
132 filename, arg = re.search(r'^(.*?)(?:\[(.*)\])?$', name).groups()
133 if arg is None:
134 output_files[filename] = (value.split(), item.source)
135 else:
136 args.setdefault(filename, {})[arg] = value
137
138 template = getTemplate('modules.js.tmpl')
139
140 for filename, (input_files, origin) in output_files.iteritems():
141 if '/' in filename and not files.isIncluded(filename):
142 continue
143
144 current_args = args.get(filename, {})
145 current_args['autoload'] = [module for module in
146 current_args.get('autoload', '').split(',')
147 if module != '']
148
149 base_dir = os.path.dirname(origin)
150 modules = []
151
152 for input_filename in input_files:
153 module_name = os.path.splitext(os.path.basename(input_filename))[0]
154 prefix = os.path.basename(os.path.dirname(input_filename))
155 if prefix != 'lib':
156 module_name = '{}_{}'.format(prefix, module_name)
157 with open(os.path.join(base_dir, input_filename), 'r') as file:
158 modules.append((module_name, file.read().decode('utf-8')))
159 files.pop(input_filename, None)
160
161 files[filename] = template.render(
162 args=current_args,
163 modules=modules
164 ).encode('utf-8')
165
166
167 def createBuild(baseDir, type, outFile=None, buildNum=None, releaseBuild=False, keyFile=None, devenv=False):
168 metadata = readMetadata(baseDir, type)
169 version = getBuildVersion(baseDir, metadata, releaseBuild, buildNum)
170
171 if not outFile:
172 outFile = getDefaultFileName(metadata, version, 'safariextz' if keyFile else 'zip')
173
174 params = {
175 'type': type,
176 'baseDir': baseDir,
177 'releaseBuild': releaseBuild,
178 'version': version,
179 'devenv': devenv,
180 'metadata': metadata,
181 }
182
183 mapped = metadata.items('mapping') if metadata.has_section('mapping') else [ ]
184 files = Files(getPackageFiles(params), getIgnoredFiles(params),
185 process=lambda path, data: processFile(path, data, params))
186 files.readMappedFiles(mapped)
187 files.read(baseDir, skip=[opt for opt, _ in mapped])
188
189 if metadata.has_section('convert_js'):
190 convertJS(params, files)
191
192 if metadata.has_section('preprocess'):
193 files.preprocess(
194 [f for f, _ in metadata.items('preprocess')],
195 {'needsExt': True}
196 )
197
198 if metadata.has_section('import_locales'):
199 import_locales(params, files)
200
201 if metadata.has_option('general', 'testScripts'):
202 files['qunit/index.html'] = createScriptPage(params, 'testIndex.html.tmp l',
203 ('general', 'testScripts'))
204
205 if keyFile:
206 from buildtools import xarfile
207 certs, key = xarfile.read_certificates_and_key(keyFile)
208 params['developerIdentifier'] = get_developer_identifier(certs)
209
210 files['lib/info.js'] = createInfoModule(params)
211 files['background.html'] = createScriptPage(params, 'background.html.tmpl',
212 ('general', 'backgroundScripts') )
213 files['Info.plist'] = createManifest(params, files)
214
215 dirname = metadata.get('general', 'basename') + '.safariextension'
216 for filename in files.keys():
217 files[os.path.join(dirname, filename)] = files.pop(filename)
218
219 if not devenv and keyFile:
220 from buildtools import xarfile
221 xarfile.create(outFile, files, keyFile)
222 else:
223 files.zip(outFile)
OLDNEW

Powered by Google App Engine
This is Rietveld