content_providers.py revision 0f1bc08d4cfcc34181b0b5cbf065c40f687bf740
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 3# found in the LICENSE file. 4 5import logging 6from operator import itemgetter 7import posixpath 8 9from chroot_file_system import ChrootFileSystem 10from content_provider import ContentProvider 11from svn_constants import JSON_PATH 12from third_party.json_schema_compiler.memoize import memoize 13 14 15_CONFIG_PATH = '%s/content_providers.json' % JSON_PATH 16 17 18class ContentProviders(object): 19 '''Implements the content_providers.json configuration; see 20 chrome/common/extensions/docs/templates/json/content_providers.json for its 21 current state and a description of the format. 22 23 Returns ContentProvider instances based on how they're configured there. 24 ''' 25 26 def __init__(self, compiled_fs_factory, host_file_system): 27 self._compiled_fs_factory = compiled_fs_factory 28 self._host_file_system = host_file_system 29 self._cache = compiled_fs_factory.ForJson(host_file_system) 30 31 @memoize 32 def GetByName(self, name): 33 '''Gets the ContentProvider keyed by |name| in content_providers.json, or 34 None of there is no such content provider. 35 ''' 36 config = self._GetConfig().get(name) 37 if config is None: 38 logging.error('No content provider found with name "%s"' % name) 39 return None 40 return self._CreateContentProvider(name, config) 41 42 @memoize 43 def GetByServeFrom(self, path): 44 '''Gets a (content_provider, path_in_content_provider) tuple, where 45 content_provider is the ContentProvider with the longest "serveFrom" 46 property that is a subpath of |path|, and path_in_content_provider is the 47 remainder of |path|. 48 49 For example, if content provider A serves from "foo" and content provider B 50 serves from "foo/bar", GetByServeFrom("foo/bar/baz") will return (B, "baz"). 51 52 Returns (None, |path|) if no ContentProvider serves from |path|. 53 ''' 54 serve_from_to_config = dict( 55 (config['serveFrom'], (name, config)) 56 for name, config in self._GetConfig().iteritems()) 57 path_parts = path.split('/') 58 for i in xrange(len(path_parts), -1, -1): 59 name_and_config = serve_from_to_config.get('/'.join(path_parts[:i])) 60 if name_and_config is not None: 61 return (self._CreateContentProvider(name_and_config[0], 62 name_and_config[1]), 63 '/'.join(path_parts[i:])) 64 return None, path 65 66 def _GetConfig(self): 67 return self._cache.GetFromFile(_CONFIG_PATH).Get() 68 69 def _CreateContentProvider(self, name, config): 70 supports_templates = config.get('supportsTemplates', False) 71 supports_zip = config.get('supportsZip', False) 72 73 if 'chromium' in config: 74 chromium_config = config['chromium'] 75 if 'dir' not in chromium_config: 76 logging.error('"chromium" must have a "dir" property') 77 return None 78 file_system = ChrootFileSystem(self._host_file_system, 79 chromium_config['dir']) 80 else: 81 logging.error('Content provider type "%s" not supported', type_) 82 return None 83 84 return ContentProvider(name, 85 self._compiled_fs_factory, 86 file_system, 87 supports_templates=supports_templates, 88 supports_zip=supports_zip) 89 90 def Cron(self): 91 for name, config in self._GetConfig().iteritems(): 92 self._CreateContentProvider(name, config).Cron() 93