# found in the LICENSE file.
import logging
+import os
import traceback
from chroot_file_system import ChrootFileSystem
from content_provider import ContentProvider
-from extensions_paths import CONTENT_PROVIDERS
+import environment
+from extensions_paths import CONTENT_PROVIDERS, LOCAL_DEBUG_DIR
from future import Gettable, Future
+from local_file_system import LocalFileSystem
from third_party.json_schema_compiler.memoize import memoize
+_IGNORE_MISSING_CONTENT_PROVIDERS = [False]
+
+
+def IgnoreMissingContentProviders(fn):
+ '''Decorates |fn| to ignore missing content providers during its run.
+ '''
+ def run(*args, **optargs):
+ saved = _IGNORE_MISSING_CONTENT_PROVIDERS[0]
+ _IGNORE_MISSING_CONTENT_PROVIDERS[0] = True
+ try:
+ return fn(*args, **optargs)
+ finally:
+ _IGNORE_MISSING_CONTENT_PROVIDERS[0] = saved
+ return run
+
+
class ContentProviders(object):
'''Implements the content_providers.json configuration; see
chrome/common/extensions/docs/templates/json/content_providers.json for its
'''
def __init__(self,
+ object_store_creator,
compiled_fs_factory,
host_file_system,
- github_file_system_provider):
+ github_file_system_provider,
+ gcs_file_system_provider):
+ self._object_store_creator = object_store_creator
self._compiled_fs_factory = compiled_fs_factory
self._host_file_system = host_file_system
self._github_file_system_provider = github_file_system_provider
- self._cache = compiled_fs_factory.ForJson(host_file_system)
+ self._gcs_file_system_provider = gcs_file_system_provider
+ self._cache = None
+
+ # If running the devserver and there is a LOCAL_DEBUG_DIR, we
+ # will read the content_provider configuration from there instead
+ # of fetching it from SVN trunk or patch.
+ if environment.IsDevServer() and os.path.exists(LOCAL_DEBUG_DIR):
+ local_fs = LocalFileSystem(LOCAL_DEBUG_DIR)
+ conf_stat = None
+ try:
+ conf_stat = local_fs.Stat(CONTENT_PROVIDERS)
+ except:
+ pass
+
+ if conf_stat:
+ logging.warn(("Using local debug folder (%s) for "
+ "content_provider.json configuration") % LOCAL_DEBUG_DIR)
+ self._cache = compiled_fs_factory.ForJson(local_fs)
+
+ if not self._cache:
+ self._cache = compiled_fs_factory.ForJson(host_file_system)
@memoize
def GetByName(self, name):
@memoize
def GetByServeFrom(self, path):
- '''Gets a (content_provider, path_in_content_provider) tuple, where
- content_provider is the ContentProvider with the longest "serveFrom"
- property that is a subpath of |path|, and path_in_content_provider is the
- remainder of |path|.
+ '''Gets a (content_provider, serve_from, path_in_content_provider) tuple,
+ where content_provider is the ContentProvider with the longest "serveFrom"
+ property that is a subpath of |path|, serve_from is that property, and
+ path_in_content_provider is the remainder of |path|.
For example, if content provider A serves from "foo" and content provider B
- serves from "foo/bar", GetByServeFrom("foo/bar/baz") will return (B, "baz").
+ serves from "foo/bar", GetByServeFrom("foo/bar/baz") will return (B,
+ "foo/bar", "baz").
- Returns (None, |path|) if no ContentProvider serves from |path|.
+ Returns (None, '', |path|) if no ContentProvider serves from |path|.
'''
serve_from_to_config = dict(
(config['serveFrom'], (name, config))
if name_and_config is not None:
return (self._CreateContentProvider(name_and_config[0],
name_and_config[1]),
+ '/'.join(path_parts[:i]),
'/'.join(path_parts[i:]))
- return None, path
+ return None, '', path
def _GetConfig(self):
return self._cache.GetFromFile(CONTENT_PROVIDERS).Get()
def _CreateContentProvider(self, name, config):
+ default_extensions = config.get('defaultExtensions', ())
supports_templates = config.get('supportsTemplates', False)
supports_zip = config.get('supportsZip', False)
return None
file_system = ChrootFileSystem(self._host_file_system,
chromium_config['dir'])
+ elif 'gcs' in config:
+ gcs_config = config['gcs']
+ if 'bucket' not in gcs_config:
+ logging.error('%s: "gcs" must have a "bucket" property' % name)
+ return None
+ bucket = gcs_config['bucket']
+ if not bucket.startswith('gs://'):
+ logging.error('%s: bucket %s should start with gs://' % (name, bucket))
+ return None
+ bucket = bucket[len('gs://'):]
+ file_system = self._gcs_file_system_provider.Create(bucket)
+ if 'dir' in gcs_config:
+ file_system = ChrootFileSystem(file_system, gcs_config['dir'])
+
elif 'github' in config:
github_config = config['github']
if 'owner' not in github_config or 'repo' not in github_config:
github_config['owner'], github_config['repo'])
if 'dir' in github_config:
file_system = ChrootFileSystem(file_system, github_config['dir'])
+
else:
- logging.error(
- '%s: content provider type "%s" not supported' % (name, type_))
+ logging.error('%s: content provider type not supported' % name)
return None
return ContentProvider(name,
self._compiled_fs_factory,
file_system,
+ self._object_store_creator,
+ default_extensions=default_extensions,
supports_templates=supports_templates,
supports_zip=supports_zip)
try:
return callback()
except:
- logging.error('Error %s Cron for ContentProvider "%s":\n%s' %
- (action, name, traceback.format_exc()))
+ if not _IGNORE_MISSING_CONTENT_PROVIDERS[0]:
+ logging.error('Error %s Cron for ContentProvider "%s":\n%s' %
+ (action, name, traceback.format_exc()))
return None
futures = [(name, safe(name,