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

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: Extension profile extender properly waits for extensions to install. 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):
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 reader.next() # skip header line
78 for row in reader:
79 extension_info = {
80 'extension_name': row[0],
81 'id': row[1],
82 'hash': row[2],
83 'version': row[3]
84 }
85
86 print 'Fetching extension %s...' % extension_info['id']
87 crx_path = _DownloadCrxFromCws(extension_info['id'], local_extensions_dir)
88 if crx_path is None:
89 raise exceptions.Error('\tCould not fetch %s.\n\n'
90 'If this extension dl consistently fails, '
91 'remove this entry from %s.'
92 % (extension_info['id'], extensions_csv))
93 (new_hash, new_version) = _CrxHashIfChanged(crx_path, extension_info)
94 if new_hash is not None:
95 update_csv = True
96 extension_info['hash'] = new_hash
97 extension_info['version'] = new_version
98 extensions_info.append(extension_info)
99 extension_zip.write(crx_path, arcname='%s.crx' % extension_info['id'])
100 extension_zip.close()
101
102 if update_csv:
103 print 'Updating CSV...'
104 _UpdateCsv(extensions_csv, extensions_info)
105
106 print 'Uploading extensions to cloud...'
107 remote_zip_path = os.path.join(remote_dir, ZIP_NAME)
108 cloud_storage.Insert(cloud_storage.PARTNER_BUCKET, remote_zip_path, zip_path)
109
110 def _CrxHashIfChanged(crx_path, extension_info):
111 """Checks whether downloaded Crx has been altered.
112
113 Compares stored hash with hash of downloaded Crx. If different, alerts user
114 that CRX version has changed and will be updated in CSV file.
115
116 Args:
117 crx_path: Path to downloaded CRX.
118 extension_info: Info from CSV (including id and previous hash) about CRX.
119
120 Returns:
121 New hash and version if extension differed. Otherwise, returns (None, None)
122 """
123 downloaded_hash = _Base64Hash(crx_path)
124 new_version = _GetVersionFromCrx(crx_path)
125 if downloaded_hash != extension_info['hash']:
126 if new_version != extension_info['version']:
127 ans = raw_input('\tWarning: Extension %s version from Web Store differs '
128 'from CSV version.\n\tIf continued, script will write '
129 'new hash and version to CSV.\n\tContinue? (y/n) '
130 % extension_info['id']).lower()
131 else:
132 raise exceptions.Error('Extension %s hash from Web Store differs from '
133 '\nhash stored in CSV, but versions are the same.')
134 if not ans.startswith('y'):
135 sys.exit('Web Store extension %s hash differs from hash in CSV.'
136 % extension_info['id'])
137 return (downloaded_hash, new_version)
138 return (None, None)
139
140 def _UpdateCsv(extensions_csv, extensions_info):
141 '''Updates CSV with information in extensions_info.
142
143 CSV is written with updated information about each extension:
144 name, id, hash, version.
145 '''
146 with open(extensions_csv, 'w') as csv_file:
147 writer = csv.DictWriter(
148 csv_file, fieldnames=['extension_name', 'id', 'hash', 'version'])
149 writer.writeheader()
150 for entry in extensions_info:
151 writer.writerow(entry)
152
153 def _GetCsvFromArgs():
154 """Parse options to retrieve name of CSV file."""
155 parser = optparse.OptionParser()
156 parser.add_option('-e', '--extension-csv', dest='extension_csv',
157 help='CSV of extensions to load.')
158 (options, _) = parser.parse_args()
159 if not options.extension_csv:
160 parser.error('Must specify --extension-csv option.')
161 return options.extension_csv
162
163 def _GetVersionFromCrx(crx_path):
164 with zipfile.ZipFile(crx_path, 'r') as crx_zip:
165 manifest_contents = crx_zip.read('manifest.json')
166 version = json.loads(manifest_contents)['version']
167 return version
168
169 def _Base64Hash(file_path):
170 return base64.b64encode(cloud_storage.CalculateHash(file_path))
171
172 def main():
173 extension_csv = _GetCsvFromArgs()
174 local_extensions_dir = tempfile.mkdtemp()
175 try:
176 _UpdateExtensionsInCloud(local_extensions_dir,
177 extension_csv, REMOTE_DIR)
178 finally:
179 shutil.rmtree(local_extensions_dir)
180
181 if __name__ == '__main__':
182 main()
183
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698