OLD | NEW |
1 # Copyright 2013 The Chromium Authors. All rights reserved. | 1 # Copyright 2013 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 logging | 5 import logging |
6 import traceback | 6 import traceback |
7 | 7 |
8 from chroot_file_system import ChrootFileSystem | 8 from chroot_file_system import ChrootFileSystem |
9 from content_provider import ContentProvider | 9 from content_provider import ContentProvider |
10 from extensions_paths import CONTENT_PROVIDERS | 10 from extensions_paths import CONTENT_PROVIDERS |
(...skipping 19 matching lines...) Expand all Loading... |
30 | 30 |
31 class ContentProviders(object): | 31 class ContentProviders(object): |
32 '''Implements the content_providers.json configuration; see | 32 '''Implements the content_providers.json configuration; see |
33 chrome/common/extensions/docs/templates/json/content_providers.json for its | 33 chrome/common/extensions/docs/templates/json/content_providers.json for its |
34 current state and a description of the format. | 34 current state and a description of the format. |
35 | 35 |
36 Returns ContentProvider instances based on how they're configured there. | 36 Returns ContentProvider instances based on how they're configured there. |
37 ''' | 37 ''' |
38 | 38 |
39 def __init__(self, | 39 def __init__(self, |
| 40 object_store_creator, |
40 compiled_fs_factory, | 41 compiled_fs_factory, |
41 host_file_system, | 42 host_file_system, |
42 github_file_system_provider): | 43 github_file_system_provider): |
| 44 self._object_store_creator = object_store_creator |
43 self._compiled_fs_factory = compiled_fs_factory | 45 self._compiled_fs_factory = compiled_fs_factory |
44 self._host_file_system = host_file_system | 46 self._host_file_system = host_file_system |
45 self._github_file_system_provider = github_file_system_provider | 47 self._github_file_system_provider = github_file_system_provider |
46 self._cache = compiled_fs_factory.ForJson(host_file_system) | 48 self._cache = compiled_fs_factory.ForJson(host_file_system) |
47 | 49 |
48 @memoize | 50 @memoize |
49 def GetByName(self, name): | 51 def GetByName(self, name): |
50 '''Gets the ContentProvider keyed by |name| in content_providers.json, or | 52 '''Gets the ContentProvider keyed by |name| in content_providers.json, or |
51 None of there is no such content provider. | 53 None of there is no such content provider. |
52 ''' | 54 ''' |
53 config = self._GetConfig().get(name) | 55 config = self._GetConfig().get(name) |
54 if config is None: | 56 if config is None: |
55 logging.error('No content provider found with name "%s"' % name) | 57 logging.error('No content provider found with name "%s"' % name) |
56 return None | 58 return None |
57 return self._CreateContentProvider(name, config) | 59 return self._CreateContentProvider(name, config) |
58 | 60 |
59 @memoize | 61 @memoize |
60 def GetByServeFrom(self, path): | 62 def GetByServeFrom(self, path): |
61 '''Gets a (content_provider, path_in_content_provider) tuple, where | 63 '''Gets a (content_provider, serve_from, path_in_content_provider) tuple, |
62 content_provider is the ContentProvider with the longest "serveFrom" | 64 where content_provider is the ContentProvider with the longest "serveFrom" |
63 property that is a subpath of |path|, and path_in_content_provider is the | 65 property that is a subpath of |path|, serve_from is that property, and |
64 remainder of |path|. | 66 path_in_content_provider is the remainder of |path|. |
65 | 67 |
66 For example, if content provider A serves from "foo" and content provider B | 68 For example, if content provider A serves from "foo" and content provider B |
67 serves from "foo/bar", GetByServeFrom("foo/bar/baz") will return (B, "baz"). | 69 serves from "foo/bar", GetByServeFrom("foo/bar/baz") will return (B, |
| 70 "foo/bar", "baz"). |
68 | 71 |
69 Returns (None, |path|) if no ContentProvider serves from |path|. | 72 Returns (None, '', |path|) if no ContentProvider serves from |path|. |
70 ''' | 73 ''' |
71 serve_from_to_config = dict( | 74 serve_from_to_config = dict( |
72 (config['serveFrom'], (name, config)) | 75 (config['serveFrom'], (name, config)) |
73 for name, config in self._GetConfig().iteritems()) | 76 for name, config in self._GetConfig().iteritems()) |
74 path_parts = path.split('/') | 77 path_parts = path.split('/') |
75 for i in xrange(len(path_parts), -1, -1): | 78 for i in xrange(len(path_parts), -1, -1): |
76 name_and_config = serve_from_to_config.get('/'.join(path_parts[:i])) | 79 name_and_config = serve_from_to_config.get('/'.join(path_parts[:i])) |
77 if name_and_config is not None: | 80 if name_and_config is not None: |
78 return (self._CreateContentProvider(name_and_config[0], | 81 return (self._CreateContentProvider(name_and_config[0], |
79 name_and_config[1]), | 82 name_and_config[1]), |
| 83 '/'.join(path_parts[:i]), |
80 '/'.join(path_parts[i:])) | 84 '/'.join(path_parts[i:])) |
81 return None, path | 85 return None, '', path |
82 | 86 |
83 def _GetConfig(self): | 87 def _GetConfig(self): |
84 return self._cache.GetFromFile(CONTENT_PROVIDERS).Get() | 88 return self._cache.GetFromFile(CONTENT_PROVIDERS).Get() |
85 | 89 |
86 def _CreateContentProvider(self, name, config): | 90 def _CreateContentProvider(self, name, config): |
| 91 default_extensions = config.get('defaultExtensions', ()) |
87 supports_templates = config.get('supportsTemplates', False) | 92 supports_templates = config.get('supportsTemplates', False) |
88 supports_zip = config.get('supportsZip', False) | 93 supports_zip = config.get('supportsZip', False) |
89 | 94 |
90 if 'chromium' in config: | 95 if 'chromium' in config: |
91 chromium_config = config['chromium'] | 96 chromium_config = config['chromium'] |
92 if 'dir' not in chromium_config: | 97 if 'dir' not in chromium_config: |
93 logging.error('%s: "chromium" must have a "dir" property' % name) | 98 logging.error('%s: "chromium" must have a "dir" property' % name) |
94 return None | 99 return None |
95 file_system = ChrootFileSystem(self._host_file_system, | 100 file_system = ChrootFileSystem(self._host_file_system, |
96 chromium_config['dir']) | 101 chromium_config['dir']) |
97 elif 'github' in config: | 102 elif 'github' in config: |
98 github_config = config['github'] | 103 github_config = config['github'] |
99 if 'owner' not in github_config or 'repo' not in github_config: | 104 if 'owner' not in github_config or 'repo' not in github_config: |
100 logging.error('%s: "github" must provide an "owner" and "repo"' % name) | 105 logging.error('%s: "github" must provide an "owner" and "repo"' % name) |
101 return None | 106 return None |
102 file_system = self._github_file_system_provider.Create( | 107 file_system = self._github_file_system_provider.Create( |
103 github_config['owner'], github_config['repo']) | 108 github_config['owner'], github_config['repo']) |
104 if 'dir' in github_config: | 109 if 'dir' in github_config: |
105 file_system = ChrootFileSystem(file_system, github_config['dir']) | 110 file_system = ChrootFileSystem(file_system, github_config['dir']) |
106 else: | 111 else: |
107 logging.error( | 112 logging.error( |
108 '%s: content provider type "%s" not supported' % (name, type_)) | 113 '%s: content provider type "%s" not supported' % (name, type_)) |
109 return None | 114 return None |
110 | 115 |
111 return ContentProvider(name, | 116 return ContentProvider(name, |
112 self._compiled_fs_factory, | 117 self._compiled_fs_factory, |
113 file_system, | 118 file_system, |
| 119 self._object_store_creator, |
| 120 default_extensions=default_extensions, |
114 supports_templates=supports_templates, | 121 supports_templates=supports_templates, |
115 supports_zip=supports_zip) | 122 supports_zip=supports_zip) |
116 | 123 |
117 def Cron(self): | 124 def Cron(self): |
118 def safe(name, action, callback): | 125 def safe(name, action, callback): |
119 '''Safely runs |callback| for a ContentProvider called |name| by | 126 '''Safely runs |callback| for a ContentProvider called |name| by |
120 swallowing exceptions and turning them into a None return value. It's | 127 swallowing exceptions and turning them into a None return value. It's |
121 important to run all ContentProvider Crons even if some of them fail. | 128 important to run all ContentProvider Crons even if some of them fail. |
122 ''' | 129 ''' |
123 try: | 130 try: |
124 return callback() | 131 return callback() |
125 except: | 132 except: |
126 if not _IGNORE_MISSING_CONTENT_PROVIDERS[0]: | 133 if not _IGNORE_MISSING_CONTENT_PROVIDERS[0]: |
127 logging.error('Error %s Cron for ContentProvider "%s":\n%s' % | 134 logging.error('Error %s Cron for ContentProvider "%s":\n%s' % |
128 (action, name, traceback.format_exc())) | 135 (action, name, traceback.format_exc())) |
129 return None | 136 return None |
130 | 137 |
131 futures = [(name, safe(name, | 138 futures = [(name, safe(name, |
132 'initializing', | 139 'initializing', |
133 self._CreateContentProvider(name, config).Cron)) | 140 self._CreateContentProvider(name, config).Cron)) |
134 for name, config in self._GetConfig().iteritems()] | 141 for name, config in self._GetConfig().iteritems()] |
135 return Future(delegate=Gettable( | 142 return Future(delegate=Gettable( |
136 lambda: [safe(name, 'resolving', f.Get) for name, f in futures if f])) | 143 lambda: [safe(name, 'resolving', f.Get) for name, f in futures if f])) |
OLD | NEW |