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

Side by Side Diff: chrome/common/extensions/docs/server2/samples_data_source.py

Issue 68873003: Docserver: Serve docs out of src/ not src/chrome/common/extensions. This allows (Closed) Base URL: svn://svn.chromium.org/chrome/trunk/src
Patch Set: fix samples Created 7 years, 1 month 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 | Annotate | Revision Log
OLDNEW
1 # Copyright (c) 2012 The Chromium Authors. All rights reserved. 1 # Copyright (c) 2012 The Chromium Authors. All rights reserved.
2 # Use of this source code is governed by a BSD-style license that can be 2 # Use of this source code is governed by a BSD-style license that can be
3 # found in the LICENSE file. 3 # found in the LICENSE file.
4 4
5 import hashlib 5 import hashlib
6 import json 6 import json
7 import logging 7 import logging
8 import posixpath 8 import posixpath
9 import re 9 import re
10 import traceback 10 import traceback
11 11
12 from compiled_file_system import CompiledFileSystem 12 from compiled_file_system import CompiledFileSystem
13 from extensions_paths import EXAMPLES
13 import third_party.json_schema_compiler.json_comment_eater as json_comment_eater 14 import third_party.json_schema_compiler.json_comment_eater as json_comment_eater
14 import third_party.json_schema_compiler.model as model 15 import third_party.json_schema_compiler.model as model
15 import url_constants 16 import url_constants
16 17
17 DEFAULT_ICON_PATH = 'images/sample-default-icon.png' 18
19 _DEFAULT_ICON_PATH = 'images/sample-default-icon.png'
20
18 21
19 class SamplesDataSource(object): 22 class SamplesDataSource(object):
20 '''Constructs a list of samples and their respective files and api calls. 23 '''Constructs a list of samples and their respective files and api calls.
21 ''' 24 '''
22 class Factory(object): 25 class Factory(object):
23 '''A factory to create SamplesDataSource instances bound to individual 26 '''A factory to create SamplesDataSource instances bound to individual
24 Requests. 27 Requests.
25 ''' 28 '''
26 def __init__(self, 29 def __init__(self,
27 host_file_system, 30 host_file_system,
28 app_samples_file_system, 31 app_samples_file_system,
29 compiled_fs_factory, 32 compiled_fs_factory,
30 ref_resolver_factory, 33 ref_resolver_factory,
31 extension_samples_path,
32 base_path): 34 base_path):
33 self._host_file_system = host_file_system 35 self._host_file_system = host_file_system
34 self._app_samples_file_system = app_samples_file_system 36 self._app_samples_file_system = app_samples_file_system
35 self._ref_resolver = ref_resolver_factory.Create() 37 self._ref_resolver = ref_resolver_factory.Create()
36 self._extension_samples_path = extension_samples_path
37 self._base_path = base_path 38 self._base_path = base_path
38 self._extensions_cache = compiled_fs_factory.Create( 39 self._extensions_cache = compiled_fs_factory.Create(
39 host_file_system, 40 host_file_system,
40 self._MakeSamplesList, 41 self._MakeSamplesList,
41 SamplesDataSource, 42 SamplesDataSource,
42 category='extensions') 43 category='extensions')
43 self._apps_cache = compiled_fs_factory.Create( 44 self._apps_cache = compiled_fs_factory.Create(
44 app_samples_file_system, 45 app_samples_file_system,
45 lambda *args: self._MakeSamplesList(*args, is_apps=True), 46 lambda *args: self._MakeSamplesList(*args, is_apps=True),
46 SamplesDataSource, 47 SamplesDataSource,
47 category='apps') 48 category='apps')
48 49
49 def Create(self, request): 50 def Create(self, request):
50 '''Returns a new SamplesDataSource bound to |request|. 51 '''Returns a new SamplesDataSource bound to |request|.
51 ''' 52 '''
52 return SamplesDataSource(self._extensions_cache, 53 return SamplesDataSource(self._extensions_cache,
53 self._apps_cache, 54 self._apps_cache,
54 self._extension_samples_path,
55 self._base_path, 55 self._base_path,
56 request) 56 request)
57 57
58 def _GetAPIItems(self, js_file): 58 def _GetAPIItems(self, js_file):
59 chrome_pattern = r'chrome[\w.]+' 59 chrome_pattern = r'chrome[\w.]+'
60 # Add API calls that appear normally, like "chrome.runtime.connect". 60 # Add API calls that appear normally, like "chrome.runtime.connect".
61 calls = set(re.findall(chrome_pattern, js_file)) 61 calls = set(re.findall(chrome_pattern, js_file))
62 # Add API calls that have been assigned into variables, like 62 # Add API calls that have been assigned into variables, like
63 # "var storageArea = chrome.storage.sync; storageArea.get", which should 63 # "var storageArea = chrome.storage.sync; storageArea.get", which should
64 # be expanded like "chrome.storage.sync.get". 64 # be expanded like "chrome.storage.sync.get".
(...skipping 31 matching lines...) Expand 10 before | Expand all | Expand 10 after
96 locales_json = [(locale_path, json.loads(contents)) 96 locales_json = [(locale_path, json.loads(contents))
97 for locale_path, contents in 97 for locale_path, contents in
98 locales_files.iteritems()] 98 locales_files.iteritems()]
99 except ValueError as e: 99 except ValueError as e:
100 logging.error('Error parsing locales files for %s: %s' % (path, e)) 100 logging.error('Error parsing locales files for %s: %s' % (path, e))
101 else: 101 else:
102 for path, json_ in locales_json: 102 for path, json_ in locales_json:
103 l10n_data['locales'][path[len(locales_path):].split('/')[0]] = json_ 103 l10n_data['locales'][path[len(locales_path):].split('/')[0]] = json_
104 return l10n_data 104 return l10n_data
105 105
106 def _MakeSamplesList(self, base_dir, files, is_apps=False): 106 def _MakeSamplesList(self, base_path, files, is_apps=False):
107 # HACK(kalman): The code here (for legacy reasons) assumes that |files| is
108 # prefixed by |base_dir|, so make it true.
109 files = ['%s%s' % (base_dir, f) for f in files]
110 file_system = (self._app_samples_file_system if is_apps else 107 file_system = (self._app_samples_file_system if is_apps else
111 self._host_file_system) 108 self._host_file_system)
112 samples_list = [] 109 samples_list = []
113 for filename in sorted(files): 110 for filename in sorted(files):
114 if filename.rsplit('/')[-1] != 'manifest.json': 111 if filename.rsplit('/')[-1] != 'manifest.json':
115 continue 112 continue
116 113
117 # This is a little hacky, but it makes a sample page. 114 # This is a little hacky, but it makes a sample page.
118 sample_path = filename.rsplit('/', 1)[-2] 115 sample_path = filename.rsplit('/', 1)[-2]
119 sample_files = [path for path in files 116 sample_files = [path for path in files
120 if path.startswith(sample_path + '/')] 117 if path.startswith(sample_path + '/')]
121 js_files = [path for path in sample_files if path.endswith('.js')] 118 js_files = [path for path in sample_files if path.endswith('.js')]
122 js_contents = file_system.Read(js_files).Get() 119 js_contents = file_system.Read(
120 [posixpath.join(base_path, js_file) for js_file in js_files]).Get()
123 api_items = set() 121 api_items = set()
124 for js in js_contents.values(): 122 for js in js_contents.itervalues():
125 api_items.update(self._GetAPIItems(js)) 123 api_items.update(self._GetAPIItems(js))
126 124
127 api_calls = [] 125 api_calls = []
128 for item in sorted(api_items): 126 for item in sorted(api_items):
129 if len(item.split('.')) < 3: 127 if len(item.split('.')) < 3:
130 continue 128 continue
131 if item.endswith('.removeListener') or item.endswith('.hasListener'): 129 if item.endswith('.removeListener') or item.endswith('.hasListener'):
132 continue 130 continue
133 if item.endswith('.addListener'): 131 if item.endswith('.addListener'):
134 item = item[:-len('.addListener')] 132 item = item[:-len('.addListener')]
135 if item.startswith('chrome.'): 133 if item.startswith('chrome.'):
136 item = item[len('chrome.'):] 134 item = item[len('chrome.'):]
137 ref_data = self._ref_resolver.GetLink(item) 135 ref_data = self._ref_resolver.GetLink(item)
138 # TODO(kalman): What about references like chrome.storage.sync.get? 136 # TODO(kalman): What about references like chrome.storage.sync.get?
139 # That should link to either chrome.storage.sync or 137 # That should link to either chrome.storage.sync or
140 # chrome.storage.StorageArea.get (or probably both). 138 # chrome.storage.StorageArea.get (or probably both).
141 # TODO(kalman): Filter out API-only references? This can happen when 139 # TODO(kalman): Filter out API-only references? This can happen when
142 # the API namespace is assigned to a variable, but it's very hard to 140 # the API namespace is assigned to a variable, but it's very hard to
143 # to disambiguate. 141 # to disambiguate.
144 if ref_data is None: 142 if ref_data is None:
145 continue 143 continue
146 api_calls.append({ 144 api_calls.append({
147 'name': ref_data['text'], 145 'name': ref_data['text'],
148 'link': ref_data['href'] 146 'link': ref_data['href']
149 }) 147 })
150 148
151 sample_base_path = sample_path.split('/', 1)[1] 149 sample_base_path = posixpath.join('examples', sample_path)
152 if is_apps: 150 if is_apps:
153 url = url_constants.GITHUB_BASE + '/' + sample_base_path 151 url = url_constants.GITHUB_BASE + '/' + sample_base_path
154 icon_base = url_constants.RAW_GITHUB_BASE + '/' + sample_base_path 152 icon_base = url_constants.RAW_GITHUB_BASE + '/' + sample_base_path
155 download_url = url 153 download_url = url
156 else: 154 else:
157 url = sample_base_path 155 url = sample_base_path
158 icon_base = sample_base_path 156 icon_base = sample_base_path
159 download_url = sample_base_path + '.zip' 157 download_url = sample_base_path + '.zip'
160 158
161 manifest_data = self._GetDataFromManifest(sample_path, file_system) 159 manifest_data = self._GetDataFromManifest(
160 posixpath.join(base_path, sample_path), file_system)
162 if manifest_data['icon'] is None: 161 if manifest_data['icon'] is None:
163 icon_path = posixpath.join( 162 icon_path = posixpath.join(
164 self._base_path, 'static', DEFAULT_ICON_PATH) 163 self._base_path, 'static', _DEFAULT_ICON_PATH)
165 else: 164 else:
166 icon_path = '%s/%s' % (icon_base, manifest_data['icon']) 165 icon_path = '%s/%s' % (icon_base, manifest_data['icon'])
167 manifest_data.update({ 166 manifest_data.update({
168 'icon': icon_path, 167 'icon': icon_path,
169 'download_url': download_url, 168 'download_url': download_url,
170 'url': url, 169 'url': url,
171 'files': [f.replace(sample_path + '/', '') for f in sample_files], 170 'files': [f.replace(sample_path + '/', '') for f in sample_files],
172 'api_calls': api_calls 171 'api_calls': api_calls
173 }) 172 })
174 samples_list.append(manifest_data) 173 samples_list.append(manifest_data)
175 174
176 return samples_list 175 return samples_list
177 176
178 def __init__(self, 177 def __init__(self,
179 extensions_cache, 178 extensions_cache,
180 apps_cache, 179 apps_cache,
181 extension_samples_path,
182 base_path, 180 base_path,
183 request): 181 request):
184 self._extensions_cache = extensions_cache 182 self._extensions_cache = extensions_cache
185 self._apps_cache = apps_cache 183 self._apps_cache = apps_cache
186 self._extension_samples_path = extension_samples_path
187 self._base_path = base_path 184 self._base_path = base_path
188 self._request = request 185 self._request = request
189 186
190 def _GetSampleId(self, sample_name): 187 def _GetSampleId(self, sample_name):
191 return sample_name.lower().replace(' ', '-') 188 return sample_name.lower().replace(' ', '-')
192 189
193 def _GetAcceptedLanguages(self): 190 def _GetAcceptedLanguages(self):
194 accept_language = self._request.headers.get('Accept-Language', None) 191 accept_language = self._request.headers.get('Accept-Language', None)
195 if accept_language is None: 192 if accept_language is None:
196 return [] 193 return []
197 return [lang_with_q.split(';')[0].strip() 194 return [lang_with_q.split(';')[0].strip()
198 for lang_with_q in accept_language.split(',')] 195 for lang_with_q in accept_language.split(',')]
199 196
200 def FilterSamples(self, key, api_name): 197 def FilterSamples(self, key, api_name):
201 '''Fetches and filters the list of samples specified by |key|, returning 198 '''Fetches and filters the list of samples specified by |key|, returning
202 only the samples that use the API |api_name|. |key| is either 'apps' or 199 only the samples that use the API |api_name|. |key| is either 'apps' or
203 'extensions'. 200 'extensions'.
204 ''' 201 '''
205 return [sample for sample in self.get(key) if any( 202 return [sample for sample in self.get(key) if any(
206 call['name'].startswith(api_name + '.') 203 call['name'].startswith(api_name + '.')
207 for call in sample['api_calls'])] 204 for call in sample['api_calls'])]
208 205
209 def _CreateSamplesDict(self, key): 206 def _CreateSamplesDict(self, key):
210 if key == 'apps': 207 if key == 'apps':
211 samples_list = self._apps_cache.GetFromFileListing('/').Get() 208 samples_list = self._apps_cache.GetFromFileListing('/').Get()
212 else: 209 else:
213 samples_list = self._extensions_cache.GetFromFileListing( 210 samples_list = self._extensions_cache.GetFromFileListing(EXAMPLES).Get()
214 self._extension_samples_path + '/').Get()
215 return_list = [] 211 return_list = []
216 for dict_ in samples_list: 212 for dict_ in samples_list:
217 name = dict_['name'] 213 name = dict_['name']
218 description = dict_['description'] 214 description = dict_['description']
219 if description is None: 215 if description is None:
220 description = '' 216 description = ''
221 if name.startswith('__MSG_') or description.startswith('__MSG_'): 217 if name.startswith('__MSG_') or description.startswith('__MSG_'):
222 try: 218 try:
223 # Copy the sample dict so we don't change the dict in the cache. 219 # Copy the sample dict so we don't change the dict in the cache.
224 sample_data = dict_.copy() 220 sample_data = dict_.copy()
(...skipping 16 matching lines...) Expand all
241 else: 237 else:
242 dict_['id'] = self._GetSampleId(name) 238 dict_['id'] = self._GetSampleId(name)
243 return_list.append(dict_) 239 return_list.append(dict_)
244 return return_list 240 return return_list
245 241
246 def get(self, key): 242 def get(self, key):
247 return { 243 return {
248 'apps': lambda: self._CreateSamplesDict('apps'), 244 'apps': lambda: self._CreateSamplesDict('apps'),
249 'extensions': lambda: self._CreateSamplesDict('extensions') 245 'extensions': lambda: self._CreateSamplesDict('extensions')
250 }.get(key, lambda: {})() 246 }.get(key, lambda: {})()
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698