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

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

Issue 1240703003: Extension profile generator + benchmark for startup with profile. (Closed) Base URL: https://chromium.googlesource.com/chromium/src.git@master
Patch Set: Fixing docstrings and some style. 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 json
6 import os
7 import time
8 import zipfile
9
10 from catapult_base import cloud_storage
11 from profile_creators import profile_extender
12 from telemetry.core import exceptions
13
14
15 # Remote target upload directory in cloud storage for extensions.
16 REMOTE_DIR = 'extension_set'
17
18 # Target zip file.
19 ZIP_NAME = 'extensions.zip'
20
21
22 class InvalidExtensionArchiveError(exceptions.Error):
23 """Exception thrown when remote archive is invalid or malformed.
24
25 Remote archive should be located at REMOTE_DIR/ZIP_NAME. Upon failure,
26 prompts user to update remote archive using update_remote_extensions
27 script.
28 """
29
30 def __init__(self, msg=''):
31 msg += ('\nTry running\n'
32 '\tpython update_remote_extensions.py -e extension_set.csv\n'
33 'in src/tools/perf/profile_creator subdirectory.')
34 super(InvalidExtensionArchiveError, self).__init__(msg)
35
36
37 class ExtensionProfileExtender(profile_extender.ProfileExtender):
38 """Creates a profile with many extensions."""
39
40 def __init__(self, finder_options):
41 super(ExtensionProfileExtender, self).__init__(finder_options)
42 self._extensions = []
43 finder_options.browser_options.disable_default_apps = False
44
45 def Run(self):
46 """Superclass override."""
47 # Download extensions from cloud and force-install extensions into profile.
48 local_extensions_dir = os.path.join(self.profile_path,
49 'external_extensions_crx')
50 self._DownloadRemoteExtensions(cloud_storage.PARTNER_BUCKET,
51 local_extensions_dir)
52 self._LoadExtensions(local_extensions_dir, self.profile_path)
53
54 try:
55 self.SetUpBrowser()
56 self._WaitForExtensionsToLoad()
57 finally:
58 self.TearDownBrowser()
59
60 def RestrictedOSList(self):
61 """Superclass override."""
62 return ['mac']
63
64 def _DownloadRemoteExtensions(self, remote_bucket, local_extensions_dir):
65 """Downloads and unzips archive of common extensions to disk.
66
67 Args:
68 remote_bucket: bucket to download remote archive from.
69 local_extensions_dir: destination extensions directory.
70
71 Raises:
72 InvalidExtensionArchiveError if remote archive is not found.
73 """
74 remote_zip_path = os.path.join(REMOTE_DIR, ZIP_NAME)
75 local_zip_path = os.path.join(local_extensions_dir, ZIP_NAME)
76 try:
77 cloud_storage.Get(remote_bucket, remote_zip_path, local_zip_path)
78 except:
79 raise InvalidExtensionArchiveError('Can\'t find archive at gs://%s/%s..'
80 % (remote_bucket, remote_zip_path))
81 try:
82 with zipfile.ZipFile(local_zip_path, 'r') as extensions_zip:
83 extensions_zip.extractall(local_extensions_dir)
84 finally:
85 os.remove(local_zip_path)
86
87 def _GetExtensionInfoFromCrx(self, crx_file):
88 """Retrieves version + name of extension from CRX archive."""
89 with zipfile.ZipFile(crx_file, 'r') as crx_zip:
90 manifest_contents = crx_zip.read('manifest.json')
91 decoded_manifest = json.loads(manifest_contents)
92 crx_version = decoded_manifest['version']
93 extension_name = decoded_manifest['name']
94 return (crx_version, extension_name)
95
96 def _LoadExtensions(self, local_extensions_dir, profile_dir):
97 """Loads extensions in _local_extensions_dir into user profile.
98
99 Extensions are loaded according to platform specifications at
100 https://developer.chrome.com/extensions/external_extensions.html
101
102 Args:
103 local_extensions_dir: directory containing CRX files.
104 profile_dir: target profile directory for the extensions.
105
106 Raises:
107 InvalidExtensionArchiveError if archive contains a non-CRX file.
108 """
109 ext_files = os.listdir(local_extensions_dir)
110 external_ext_dir = os.path.join(profile_dir, 'External Extensions')
111 os.makedirs(external_ext_dir)
112 for ext_file in ext_files:
113 ext_path = os.path.join(local_extensions_dir, ext_file)
114 if not ext_file.endswith('.crx'):
115 raise InvalidExtensionArchiveError('Archive contains non-crx file %s.'
116 % ext_file)
117 (version, name) = self._GetExtensionInfoFromCrx(ext_path)
118 extension_info = {
119 'external_crx': ext_path,
120 'external_version': version,
121 '_comment': name
122 }
123 ext_id = os.path.splitext(os.path.basename(ext_path))[0]
124 extension_json_path = os.path.join(external_ext_dir, '%s.json' % ext_id)
125 with open(extension_json_path, 'w') as f:
126 f.write(json.dumps(extension_info))
127 self._extensions.append(ext_id)
128
129 def _WaitForExtensionsToLoad(self):
130 """Stall until browser has finished installing/loading all extensions."""
131 for extension_id in self._extensions:
132 while True:
133 try:
134 self.browser.extensions.GetByExtensionId(extension_id)
135 except KeyError:
136 # There's no event signalling when browser finishes installing
137 # or loading an extension so re-check every 5 seconds.
138 time.sleep(5)
139 continue
140 break
robliao 2015/07/21 20:39:51 This break can go into the try, no? That allows yo
sydli 2015/07/21 20:44:51 Yep! Done.
robliao 2015/07/21 20:46:45 Sweet. Much nicer than what I originally proposed.
OLDNEW
« no previous file with comments | « tools/perf/page_sets/extension_profile_shared_state.py ('k') | tools/perf/profile_creators/extension_set.csv » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698