- add sources.
[platform/framework/web/crosswalk.git] / src / chrome / common / extensions / docs / server2 / sidenav_data_source.py
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
3 # found in the LICENSE file.
4
5 import copy
6 import logging
7
8 from compiled_file_system import SingleFile
9 from data_source import DataSource
10 from future import Gettable, Future
11 from third_party.json_schema_compiler.json_parse import Parse
12 from svn_constants import JSON_PATH
13
14
15 def _AddLevels(items, level):
16   '''Add a 'level' key to each item in |items|. 'level' corresponds to how deep
17   in |items| an item is. |level| sets the starting depth.
18   '''
19   for item in items:
20     item['level'] = level
21     if 'items' in item:
22       _AddLevels(item['items'], level + 1)
23
24
25 def _AddSelected(items, path):
26   '''Add 'selected' and 'child_selected' properties to |items| so that the
27   sidenav can be expanded to show which menu item has been selected. Returns
28   True if an item was marked 'selected'.
29   '''
30   for item in items:
31     if item.get('href', '') == path:
32       item['selected'] = True
33       return True
34     if 'items' in item:
35       if _AddSelected(item['items'], path):
36         item['child_selected'] = True
37         return True
38
39   return False
40
41
42 class SidenavDataSource(DataSource):
43   '''Provides templates with access to JSON files used to create the side
44   navigation bar.
45   '''
46   def __init__(self, server_instance, request):
47     self._cache = server_instance.compiled_fs_factory.Create(
48         server_instance.host_file_system_provider.GetTrunk(),
49         self._CreateSidenavDict,
50         SidenavDataSource)
51     self._server_instance = server_instance
52     self._request = request
53
54   @SingleFile
55   def _CreateSidenavDict(self, _, content):
56     items = Parse(content)
57     # Start at level 2, the top <ul> element is level 1.
58     _AddLevels(items, level=2)
59     self._QualifyHrefs(items)
60     return items
61
62   def _QualifyHrefs(self, items):
63     '''Force hrefs in |items| to either be absolute (http://...) or qualified
64     (beginning with /, in which case it will be moved relative to |base_path|).
65     Relative hrefs emit a warning and should be updated.
66     '''
67     for item in items:
68       if 'items' in item:
69         self._QualifyHrefs(item['items'])
70
71       href = item.get('href')
72       if href is not None and not href.startswith(('http://', 'https://')):
73         if not href.startswith('/'):
74           logging.warn('Paths in sidenav must be qualified. %s is not.' % href)
75         else:
76           href = href.lstrip('/')
77         item['href'] = self._server_instance.base_path + href
78
79   def Cron(self):
80     futures = [
81         self._cache.GetFromFile('%s/%s_sidenav.json' % (JSON_PATH, platform))
82         for platform in ('apps', 'extensions')]
83     for future in futures:
84       future.Get()
85
86   def get(self, key):
87     sidenav = copy.deepcopy(self._cache.GetFromFile(
88         '%s/%s_sidenav.json' % (JSON_PATH, key)).Get())
89     _AddSelected(sidenav, self._server_instance.base_path + self._request.path)
90     return sidenav