blob: 9364d72d5b9bb117a211e716887d087b69610819 [file] [log] [blame]
# Copyright (c) 2012 The Chromium Authors. All rights reserved.
# Use of this source code is governed by a BSD-style license that can be
# found in the LICENSE file.
import copy
import logging
from compiled_file_system import SingleFile
from data_source import DataSource
from future import Gettable, Future
from third_party.json_schema_compiler.json_parse import Parse
from svn_constants import JSON_PATH
def _AddLevels(items, level):
'''Add a 'level' key to each item in |items|. 'level' corresponds to how deep
in |items| an item is. |level| sets the starting depth.
'''
for item in items:
item['level'] = level
if 'items' in item:
_AddLevels(item['items'], level + 1)
def _AddSelected(items, path):
'''Add 'selected' and 'child_selected' properties to |items| so that the
sidenav can be expanded to show which menu item has been selected. Returns
True if an item was marked 'selected'.
'''
for item in items:
if item.get('href', '') == path:
item['selected'] = True
return True
if 'items' in item:
if _AddSelected(item['items'], path):
item['child_selected'] = True
return True
return False
class SidenavDataSource(DataSource):
'''Provides templates with access to JSON files used to create the side
navigation bar.
'''
def __init__(self, server_instance, request):
self._cache = server_instance.compiled_fs_factory.Create(
server_instance.host_file_system_provider.GetTrunk(),
self._CreateSidenavDict,
SidenavDataSource)
self._server_instance = server_instance
self._request = request
@SingleFile
def _CreateSidenavDict(self, _, content):
items = Parse(content)
# Start at level 2, the top <ul> element is level 1.
_AddLevels(items, level=2)
self._QualifyHrefs(items)
return items
def _QualifyHrefs(self, items):
'''Force hrefs in |items| to either be absolute (http://...) or qualified
(beginning with /, in which case it will be moved relative to |base_path|).
Relative hrefs emit a warning and should be updated.
'''
for item in items:
if 'items' in item:
self._QualifyHrefs(item['items'])
href = item.get('href')
if href is not None and not href.startswith(('http://', 'https://')):
if not href.startswith('/'):
logging.warn('Paths in sidenav must be qualified. %s is not.' % href)
else:
href = href.lstrip('/')
item['href'] = self._server_instance.base_path + href
def Cron(self):
futures = [
self._cache.GetFromFile('%s/%s_sidenav.json' % (JSON_PATH, platform))
for platform in ('apps', 'extensions')]
for future in futures:
future.Get()
def get(self, key):
sidenav = copy.deepcopy(self._cache.GetFromFile(
'%s/%s_sidenav.json' % (JSON_PATH, key)).Get())
_AddSelected(sidenav, self._server_instance.base_path + self._request.path)
return sidenav