| OLD | NEW | 
|    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 re |    8 import re | 
|    9  |    9  | 
|   10 import compiled_file_system as compiled_fs |   10 import compiled_file_system as compiled_fs | 
|   11 from file_system import FileNotFoundError |   11 from file_system import FileNotFoundError | 
|   12 import third_party.json_schema_compiler.json_comment_eater as json_comment_eater |   12 import third_party.json_schema_compiler.json_comment_eater as json_comment_eater | 
|   13 import third_party.json_schema_compiler.model as model |   13 import third_party.json_schema_compiler.model as model | 
|   14 import url_constants |   14 import url_constants | 
|   15  |   15  | 
|   16 DEFAULT_ICON_PATH = '/images/sample-default-icon.png' |   16 DEFAULT_ICON_PATH = '/images/sample-default-icon.png' | 
|   17  |   17  | 
|   18 def _MakeAPILink(prefix, item, api_list): |  | 
|   19   item = item.replace('chrome.', '') |  | 
|   20   parts = item.split('.') |  | 
|   21   api_name = [] |  | 
|   22   for i in range(1, len(parts) + 1): |  | 
|   23     if '.'.join(parts[:i]) in api_list: |  | 
|   24       return '%s.html#%s-%s' % ('.'.join(parts[:i]), |  | 
|   25                                 prefix, |  | 
|   26                                 '.'.join(parts[i:])) |  | 
|   27   return None |  | 
|   28  |  | 
|   29 class SamplesDataSource(object): |   18 class SamplesDataSource(object): | 
|   30   """Constructs a list of samples and their respective files and api calls. |   19   """Constructs a list of samples and their respective files and api calls. | 
|   31   """ |   20   """ | 
|   32  |   21  | 
|   33   class Factory(object): |   22   class Factory(object): | 
|   34     """A factory to create SamplesDataSource instances bound to individual |   23     """A factory to create SamplesDataSource instances bound to individual | 
|   35     Requests. |   24     Requests. | 
|   36     """ |   25     """ | 
|   37     def __init__(self, |   26     def __init__(self, | 
|   38                  channel, |   27                  channel, | 
|   39                  file_system, |   28                  file_system, | 
|   40                  github_file_system, |   29                  github_file_system, | 
|   41                  cache_factory, |   30                  cache_factory, | 
|   42                  github_cache_factory, |   31                  github_cache_factory, | 
|   43                  api_list_data_source_factory, |   32                  ref_resolver_factory, | 
|   44                  samples_path): |   33                  samples_path): | 
|   45       self._file_system = file_system |   34       self._file_system = file_system | 
|   46       self._github_file_system = github_file_system |   35       self._github_file_system = github_file_system | 
|   47       self._static_path = ((('/' + channel) if channel != 'local' else '') + |   36       self._static_path = ((('/' + channel) if channel != 'local' else '') + | 
|   48                            '/static') |   37                            '/static') | 
|   49       self._extensions_cache = cache_factory.Create(self._MakeSamplesList, |   38       self._extensions_cache = cache_factory.Create(self._MakeSamplesList, | 
|   50                                                     compiled_fs.EXTENSIONS) |   39                                                     compiled_fs.EXTENSIONS) | 
|   51       self._apps_cache = github_cache_factory.Create( |   40       self._apps_cache = github_cache_factory.Create( | 
|   52           lambda x: self._MakeSamplesList(x, is_apps=True), |   41           lambda x: self._MakeSamplesList(x, is_apps=True), | 
|   53           compiled_fs.APPS) |   42           compiled_fs.APPS) | 
|   54       self._api_list_data_source = api_list_data_source_factory.Create() |   43       self._ref_resolver = ref_resolver_factory.Create() | 
|   55       self._samples_path = samples_path |   44       self._samples_path = samples_path | 
|   56  |   45  | 
|   57     def Create(self, request): |   46     def Create(self, request): | 
|   58       """Returns a new SamplesDataSource bound to |request|. |   47       """Returns a new SamplesDataSource bound to |request|. | 
|   59       """ |   48       """ | 
|   60       return SamplesDataSource(self._extensions_cache, |   49       return SamplesDataSource(self._extensions_cache, | 
|   61                                self._apps_cache, |   50                                self._apps_cache, | 
|   62                                self._samples_path, |   51                                self._samples_path, | 
|   63                                request) |   52                                request) | 
|   64  |   53  | 
|   65     def _GetAllAPINames(self): |  | 
|   66       apis = [] |  | 
|   67       for k1 in ['apps', 'extensions']: |  | 
|   68         for k2 in ['chrome', 'experimental']: |  | 
|   69           apis.extend( |  | 
|   70               [api['name'] for api in self._api_list_data_source[k1][k2]]) |  | 
|   71       return apis |  | 
|   72  |  | 
|   73     def _GetAPIItems(self, js_file): |   54     def _GetAPIItems(self, js_file): | 
|   74       return set(re.findall('(chrome\.[a-zA-Z0-9\.]+)', js_file)) |   55       return set(re.findall('(chrome\.[a-zA-Z0-9\.]+)', js_file)) | 
|   75  |   56  | 
|   76     def _GetDataFromManifest(self, path, file_system): |   57     def _GetDataFromManifest(self, path, file_system): | 
|   77       manifest = file_system.ReadSingle(path + '/manifest.json') |   58       manifest = file_system.ReadSingle(path + '/manifest.json') | 
|   78       try: |   59       try: | 
|   79         manifest_json = json.loads(json_comment_eater.Nom(manifest)) |   60         manifest_json = json.loads(json_comment_eater.Nom(manifest)) | 
|   80       except ValueError as e: |   61       except ValueError as e: | 
|   81         logging.error('Error parsing manifest.json for %s: %s' % (path, e)) |   62         logging.error('Error parsing manifest.json for %s: %s' % (path, e)) | 
|   82         return None |   63         return None | 
| (...skipping 18 matching lines...) Expand all  Loading... | 
|  101         except ValueError as e: |   82         except ValueError as e: | 
|  102           logging.error('Error parsing locales files for %s: %s' % (path, e)) |   83           logging.error('Error parsing locales files for %s: %s' % (path, e)) | 
|  103         else: |   84         else: | 
|  104           for path, json_ in locales_json: |   85           for path, json_ in locales_json: | 
|  105             l10n_data['locales'][path[len(locales_path):].split('/')[0]] = json_ |   86             l10n_data['locales'][path[len(locales_path):].split('/')[0]] = json_ | 
|  106       return l10n_data |   87       return l10n_data | 
|  107  |   88  | 
|  108     def _MakeSamplesList(self, files, is_apps=False): |   89     def _MakeSamplesList(self, files, is_apps=False): | 
|  109       file_system = self._github_file_system if is_apps else self._file_system |   90       file_system = self._github_file_system if is_apps else self._file_system | 
|  110       samples_list = [] |   91       samples_list = [] | 
|  111       api_list = self._GetAllAPINames() |  | 
|  112       for filename in sorted(files): |   92       for filename in sorted(files): | 
|  113         if filename.rsplit('/')[-1] != 'manifest.json': |   93         if filename.rsplit('/')[-1] != 'manifest.json': | 
|  114           continue |   94           continue | 
|  115         # This is a little hacky, but it makes a sample page. |   95         # This is a little hacky, but it makes a sample page. | 
|  116         sample_path = filename.rsplit('/', 1)[-2] |   96         sample_path = filename.rsplit('/', 1)[-2] | 
|  117         sample_files = [path for path in files |   97         sample_files = [path for path in files | 
|  118                         if path.startswith(sample_path + '/')] |   98                         if path.startswith(sample_path + '/')] | 
|  119         js_files = [path for path in sample_files if path.endswith('.js')] |   99         js_files = [path for path in sample_files if path.endswith('.js')] | 
|  120         try: |  100         try: | 
|  121           js_contents = file_system.Read(js_files).Get() |  101           js_contents = file_system.Read(js_files).Get() | 
|  122         except FileNotFoundError as e: |  102         except FileNotFoundError as e: | 
|  123           logging.warning('Error fetching samples files: %s. Was a file ' |  103           logging.warning('Error fetching samples files: %s. Was a file ' | 
|  124                           'deleted from a sample? This warning should go away ' |  104                           'deleted from a sample? This warning should go away ' | 
|  125                           'in 5 minutes.' % e) |  105                           'in 5 minutes.' % e) | 
|  126           continue |  106           continue | 
|  127         api_items = set() |  107         api_items = set() | 
|  128         for js in js_contents.values(): |  108         for js in js_contents.values(): | 
|  129           api_items.update(self._GetAPIItems(js)) |  109           api_items.update(self._GetAPIItems(js)) | 
|  130  |  110  | 
|  131         api_calls = [] |  111         api_calls = [] | 
|  132         for item in api_items: |  112         for item in api_items: | 
|  133           if len(item.split('.')) < 3: |  113           if len(item.split('.')) < 3: | 
|  134             continue |  114             continue | 
|  135           if item.endswith('.removeListener') or item.endswith('.hasListener'): |  115           if item.endswith('.removeListener') or item.endswith('.hasListener'): | 
|  136             continue |  116             continue | 
|  137           if item.endswith('.addListener'): |  117           if item.endswith('.addListener'): | 
|  138             item = item[:-len('.addListener')] |  118             item = item[:-len('.addListener')] | 
|  139             link = _MakeAPILink('event', item, api_list) |  119           if item.startswith('chrome.'): | 
|  140             if link is None: |  120             item = item[len('chrome.'):] | 
|  141               continue |  121           ref_data = self._ref_resolver.GetLink('samples', item) | 
|  142             api_calls.append({ |  122           if ref_data is None: | 
|  143               'name': item, |  123             continue | 
|  144               'link': link |  124           api_calls.append({ | 
|  145             }) |  125             'name': ref_data['text'], | 
|  146           else: |  126             'link': ref_data['href'] | 
|  147             # TODO(cduvall): this might be a property or a type. |  127           }) | 
|  148             link = _MakeAPILink('method', item, api_list) |  | 
|  149             if link is None: |  | 
|  150               continue |  | 
|  151             api_calls.append({ |  | 
|  152               'name': item, |  | 
|  153               'link': link |  | 
|  154             }) |  | 
|  155         try: |  128         try: | 
|  156           manifest_data = self._GetDataFromManifest(sample_path, file_system) |  129           manifest_data = self._GetDataFromManifest(sample_path, file_system) | 
|  157         except FileNotFoundError as e: |  130         except FileNotFoundError as e: | 
|  158           logging.warning('Error getting data from samples manifest: %s. If ' |  131           logging.warning('Error getting data from samples manifest: %s. If ' | 
|  159                           'this file was deleted from a sample this message ' |  132                           'this file was deleted from a sample this message ' | 
|  160                           'should go away in 5 minutes.' % e) |  133                           'should go away in 5 minutes.' % e) | 
|  161           continue |  134           continue | 
|  162         if manifest_data is None: |  135         if manifest_data is None: | 
|  163           continue |  136           continue | 
|  164  |  137  | 
| (...skipping 34 matching lines...) Expand 10 before | Expand all | Expand 10 after  Loading... | 
|  199     if accept_language is None: |  172     if accept_language is None: | 
|  200       return [] |  173       return [] | 
|  201     return [lang_with_q.split(';')[0].strip() |  174     return [lang_with_q.split(';')[0].strip() | 
|  202             for lang_with_q in accept_language.split(',')] |  175             for lang_with_q in accept_language.split(',')] | 
|  203  |  176  | 
|  204   def FilterSamples(self, key, api_name): |  177   def FilterSamples(self, key, api_name): | 
|  205     """Fetches and filters the list of samples specified by |key|, returning |  178     """Fetches and filters the list of samples specified by |key|, returning | 
|  206     only the samples that use the API |api_name|. |key| is either 'apps' or |  179     only the samples that use the API |api_name|. |key| is either 'apps' or | 
|  207     'extensions'. |  180     'extensions'. | 
|  208     """ |  181     """ | 
|  209     api_search = '_' + api_name + '_' |  182     api_search = api_name + '_' | 
|  210     samples_list = [] |  183     samples_list = [] | 
|  211     try: |  184     try: | 
|  212       for sample in self.get(key): |  185       for sample in self.get(key): | 
|  213         api_calls_unix = [model.UnixName(call['name']) |  186         api_calls_unix = [model.UnixName(call['name']) | 
|  214                           for call in sample['api_calls']] |  187                           for call in sample['api_calls']] | 
|  215         for call in api_calls_unix: |  188         for call in api_calls_unix: | 
|  216           if api_search in call: |  189           if api_search in call: | 
|  217             samples_list.append(sample) |  190             samples_list.append(sample) | 
|  218             break |  191             break | 
|  219     except NotImplementedError: |  192     except NotImplementedError: | 
| (...skipping 28 matching lines...) Expand all  Loading... | 
|  248           sample_data['description'] = locale_data[description_key]['message'] |  221           sample_data['description'] = locale_data[description_key]['message'] | 
|  249         except Exception as e: |  222         except Exception as e: | 
|  250           logging.error(e) |  223           logging.error(e) | 
|  251           # Revert the sample to the original dict. |  224           # Revert the sample to the original dict. | 
|  252           sample_data = dict_ |  225           sample_data = dict_ | 
|  253         return_list.append(sample_data) |  226         return_list.append(sample_data) | 
|  254       else: |  227       else: | 
|  255         return_list.append(dict_) |  228         return_list.append(dict_) | 
|  256     return return_list |  229     return return_list | 
|  257  |  230  | 
|  258   def __getitem__(self, key): |  | 
|  259     return self.get(key) |  | 
|  260  |  | 
|  261   def get(self, key): |  231   def get(self, key): | 
|  262     return { |  232     return { | 
|  263       'apps': lambda: self._CreateSamplesDict('apps'), |  233       'apps': lambda: self._CreateSamplesDict('apps'), | 
|  264       'extensions': lambda: self._CreateSamplesDict('extensions') |  234       'extensions': lambda: self._CreateSamplesDict('extensions') | 
|  265     }.get(key, lambda: {})() |  235     }.get(key, lambda: {})() | 
| OLD | NEW |