Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(669)

Side by Side Diff: tools/perf/profile_creators/update_remote_extensions.py

Issue 1240703003: Extension profile generator + benchmark for startup with profile. (Closed) Base URL: https://chromium.googlesource.com/chromium/src.git@master
Patch Set: Comments added to extension_set.csv and small style fixes. Created 5 years, 5 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch
OLDNEW
(Empty)
1 # Copyright 2015 The Chromium Authors. All rights reserved.
2 # Use of this source code is governed by a BSD-style license that can be
3 # found in the LICENSE file.
4
5 import base64
6 import csv
7 import json
8 import optparse
9 import os
10 import shutil
11 import sys
12 import tempfile
13 import urllib2
14 import zipfile
15
16 sys.path.append(os.path.join(os.path.dirname(__file__), os.pardir, os.pardir,
17 'telemetry'))
18
19 from catapult_base import cloud_storage
20 from telemetry.core import exceptions
21
22 # Remote target upload directory in cloud storage for extensions.
23 REMOTE_DIR = 'extension_set'
24
25 # Target zip file.
26 ZIP_NAME = 'extensions.zip'
27
28 def _DownloadCrxFromCws(ext_id, dst):
robliao 2015/07/21 19:49:52 Two linebreaks above functions from here and forwa
sydli 2015/07/21 20:33:04 Done.
29 """Downloads CRX specified from Chrome Web Store.
30
31 Retrieves CRX (Chrome extension file) specified by ext_id from Chrome Web
32 Store, into directory specified by dst.
33
34 Args:
35 ext_id: id of extension to retrieve.
36 dst: directory to download CRX into
37
38 Returns:
39 Returns local path to downloaded CRX.
40 If download fails, return None.
41 """
42 dst_path = os.path.join(dst, '%s.crx' % ext_id)
43 cws_url = ('https://clients2.google.com/service/update2/crx?response='
44 'redirect&prodversion=38.0&x=id%%3D%s%%26installsource%%3D'
45 'ondemand%%26uc' % ext_id)
46 response = urllib2.urlopen(cws_url)
47 if response.getcode() is not 200:
48 return None
49 with open(dst_path, 'w') as f:
50 f.write(response.read())
51 return dst_path
52
53 def _UpdateExtensionsInCloud(local_extensions_dir, extensions_csv, remote_dir):
54 """Updates set of extensions in Cloud Storage from a CSV of extension ids.
55
56 From well-formatted CSV file containing some set of extensions
57 (extensions_csv), download them, compress into archive, and update
58 the remote extension archive under REMOTE_DIR in CHROME-PARTNER-TELEMETRY
59 bucket. This script expects 2nd column of CSV file to contain extension ids.
60
61 Args:
62 local_extensions_dir: directory to download CRX files into.
63 extension_csv: CSV to pull extension_ids from.
64 remote_dir: remote directory to put extension archive in cloud storage.
65
66 Raises:
67 Exception if a CRX download fails.
68 """
69
70 # Download CRX to temp files and compress into archive
71 zip_path = os.path.join(local_extensions_dir, ZIP_NAME)
72 extension_zip = zipfile.ZipFile(zip_path, 'w')
73 update_csv = False
74 extensions_info = []
75 with open(extensions_csv, 'rb') as csv_file:
76 reader = csv.reader(csv_file)
77 # skip comments and header line
robliao 2015/07/21 19:49:52 We're no longer skipping the comments and header l
sydli 2015/07/21 20:33:04 Updated the comment. The headers line gets skipped
robliao 2015/07/21 20:39:50 Ah, I see it now.
78 comments = []
79 line = ','.join(reader.next())
80 while line.startswith('#'):
81 comments.append(line)
82 line = ','.join(reader.next())
83 for row in reader:
84 extension_info = {
85 'extension_name': row[0],
86 'id': row[1],
87 'hash': row[2],
88 'version': row[3]
89 }
90
91 print 'Fetching extension %s...' % extension_info['id']
92 crx_path = _DownloadCrxFromCws(extension_info['id'], local_extensions_dir)
93 if crx_path is None:
94 raise exceptions.Error('\tCould not fetch %s.\n\n'
95 'If this extension dl consistently fails, '
96 'remove this entry from %s.'
97 % (extension_info['id'], extensions_csv))
98 (new_hash, new_version) = _CrxHashIfChanged(crx_path, extension_info)
99 if new_hash is not None:
100 update_csv = True
101 extension_info['hash'] = new_hash
102 extension_info['version'] = new_version
103 extensions_info.append(extension_info)
104 extension_zip.write(crx_path, arcname='%s.crx' % extension_info['id'])
105 extension_zip.close()
106
107 if update_csv:
108 print 'Updating CSV...'
109 _UpdateCsv(comments, extensions_csv, extensions_info)
110
111 print 'Uploading extensions to cloud...'
112 remote_zip_path = os.path.join(remote_dir, ZIP_NAME)
113 cloud_storage.Insert(cloud_storage.PARTNER_BUCKET, remote_zip_path, zip_path)
114
115 def _CrxHashIfChanged(crx_path, extension_info):
116 """Checks whether downloaded Crx has been altered.
117
118 Compares stored hash with hash of downloaded Crx. If different, alerts user
119 that CRX version has changed and will be updated in CSV file.
120
121 Args:
122 crx_path: Path to downloaded CRX.
123 extension_info: Info from CSV (including id and previous hash) about CRX.
124
125 Returns:
126 New hash and version if extension differed. Otherwise, returns (None, None)
127 """
128 downloaded_hash = _Base64Hash(crx_path)
129 new_version = _GetVersionFromCrx(crx_path)
130 if downloaded_hash != extension_info['hash']:
131 if new_version != extension_info['version']:
132 ans = raw_input('\tWarning: Extension %s version from Web Store differs '
133 'from CSV version.\n\tIf continued, script will write '
134 'new hash and version to CSV.\n\tContinue? (y/n) '
135 % extension_info['id']).lower()
136 else:
137 raise exceptions.Error('Extension %s hash from Web Store differs from '
138 '\nhash stored in CSV, but versions are the same.')
139 if not ans.startswith('y'):
140 sys.exit('Web Store extension %s hash differs from hash in CSV.'
141 % extension_info['id'])
142 return (downloaded_hash, new_version)
143 return (None, None)
144
145 def _UpdateCsv(comments, extensions_csv, extensions_info):
146 """Updates CSV with information in extensions_info.
robliao 2015/07/21 19:49:52 This docstring needs argument docs.
147
148 CSV is written with updated information about each extension:
149 name, id, hash, version.
150 """
151 # Maintain pre-existing comments.
152 with open(extensions_csv, 'w') as csv_file:
153 csv_file.write('\n'.join(comments))
154 csv_file.write('\n')
155 with open(extensions_csv, 'a') as csv_file:
156 writer = csv.DictWriter(
157 csv_file, fieldnames=['extension_name', 'id', 'hash', 'version'])
158 writer.writeheader()
159 writer.writerows(extensions_info)
160
161 def _GetCsvFromArgs():
162 """Parse options to retrieve name of CSV file."""
163 parser = optparse.OptionParser()
164 parser.add_option('-e', '--extension-csv', dest='extension_csv',
165 help='CSV of extensions to load.')
166 (options, _) = parser.parse_args()
167 if not options.extension_csv:
168 parser.error('Must specify --extension-csv option.')
169 return options.extension_csv
170
171 def _GetVersionFromCrx(crx_path):
172 """Retrieves extension version from CRX archive."""
robliao 2015/07/21 19:49:52 This docstring needs argument docs.
173 with zipfile.ZipFile(crx_path, 'r') as crx_zip:
174 manifest_contents = crx_zip.read('manifest.json')
175 version = json.loads(manifest_contents)['version']
176 return version
177
178 def _Base64Hash(file_path):
179 """Calculates base64 hash of item at file_path"""
robliao 2015/07/21 19:49:52 Arguably this satisfies... * not externally visibl
180 return base64.b64encode(cloud_storage.CalculateHash(file_path))
181
182 def main():
183 extension_csv = _GetCsvFromArgs()
184 local_extensions_dir = tempfile.mkdtemp()
185 try:
186 _UpdateExtensionsInCloud(local_extensions_dir,
187 extension_csv, REMOTE_DIR)
188 finally:
189 shutil.rmtree(local_extensions_dir)
190
191 if __name__ == '__main__':
192 main()
193
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698