Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(392)

Side by Side Diff: chrome/common/extensions/docs/server2/path_canonicalizer.py

Issue 15087006: Docserver: there is only one. (Closed) Base URL: svn://svn.chromium.org/chrome/trunk/src
Patch Set: better redirects Created 7 years, 7 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch | Annotate | Revision Log
OLDNEW
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 os 6 import os
7 import posixpath
8 import traceback
9
10 from branch_utility import BranchUtility
11 from file_system import FileNotFoundError
7 from third_party.json_schema_compiler.model import UnixName 12 from third_party.json_schema_compiler.model import UnixName
8 import svn_constants 13 import svn_constants
9 14
15 def _SimplifyFileName(file_name):
16 return (posixpath.splitext(file_name)[0]
17 .lower()
18 .replace('.', '')
19 .replace('-', '')
20 .replace('_', ''))
21
10 class PathCanonicalizer(object): 22 class PathCanonicalizer(object):
11 '''Transforms paths into their canonical forms. Since the dev server has had 23 '''Transforms paths into their canonical forms. Since the dev server has had
12 many incarnations - e.g. there didn't use to be apps/ - there may be old 24 many incarnations - e.g. there didn't use to be apps/ - there may be old
13 paths lying around the webs. We try to redirect those to where they are now. 25 paths lying around the webs. We try to redirect those to where they are now.
14 ''' 26 '''
15 def __init__(self, channel, compiled_fs_factory): 27 def __init__(self, compiled_fs_factory):
16 self._channel = channel 28 # Map of simplified API names (for typo detection) to their real paths.
17 self._identity_fs = compiled_fs_factory.CreateIdentity(PathCanonicalizer) 29 def make_public_apis(_, file_names):
30 return {_SimplifyFileName(name): name for name in file_names}
cduvall 2013/05/15 00:50:50 use dict((...
not at google - send to devlin 2013/05/15 01:26:50 Done.
31 self._public_apis = compiled_fs_factory.Create(make_public_apis,
32 PathCanonicalizer)
18 33
19 def Canonicalize(self, path): 34 def Canonicalize(self, path):
20 starts_with_channel, path_without_channel = (False, path) 35 '''Returns the canonical path for |path|, and whether that path is a
21 if path.startswith('%s/' % self._channel): 36 permanent canonicalisation (e.g. when we redirect from a channel to a
22 starts_with_channel, path_without_channel = ( 37 channel-less URL) or temporary (e.g. when we redirect from an apps-only API
23 True, path[len(self._channel) + 1:]) 38 to an extensions one - we may at some point enable it for extensions).
39 '''
40 class ReturnType(object):
41 def __init__(self, path, permanent):
42 self.path = path
43 self.permanent = permanent
44 # Catch incorrect comparisons by disabling ==/!=.
45 def __eq__(self): raise NotImplementedError()
cduvall 2013/05/15 00:50:50 these need to take another argument or you get a T
not at google - send to devlin 2013/05/15 01:26:50 ah. thanks.
46 def __ne__(self): raise NotImplementedError()
24 47
25 if any(path.startswith(prefix) 48 # Strip any channel info off it. There are no channels anymore.
26 for prefix in ('extensions/', 'apps/', 'static/')): 49 for channel_name in BranchUtility.GetAllChannelNames():
27 return path 50 channel_prefix = channel_name + '/'
51 if path.startswith(channel_prefix):
52 # Redirect now so that we can set the permanent-redirect bit. Channel
53 # redirects are the only things that should be permanent redirects;
54 # anything else *could* change, so is temporary.
55 return ReturnType(path[len(channel_prefix):], True)
28 56
29 if '/' in path_without_channel or path_without_channel == '404.html': 57 # No further work needed for static.
30 return path 58 if path.startswith('static/'):
59 return ReturnType(path, False)
31 60
32 apps_templates = self._identity_fs.GetFromFileListing( 61 # People go to just "extensions" or "apps". Redirect to the directory.
33 '/'.join((svn_constants.PUBLIC_TEMPLATE_PATH, 'apps'))) 62 if path in ('extensions', 'apps'):
34 extensions_templates = self._identity_fs.GetFromFileListing( 63 return ReturnType(path + '/', False)
35 '/'.join((svn_constants.PUBLIC_TEMPLATE_PATH, 'extensions')))
36 64
37 if self._channel is None or not starts_with_channel: 65 # The rest of this function deals with trying to figure out what API page
38 apps_path = 'apps/%s' % path_without_channel 66 # for extensions/apps to redirect to, if any. We see a few different cases
39 extensions_path = 'extensions/%s' % path_without_channel 67 # here:
68 # - Unqualified names ("browserAction.html"). These are easy to resolve;
69 # figure out whether it's an extension or app API and redirect.
70 # - but what if it's both? Well, assume extensions. Maybe later we can
71 # check analytics and see which is more popular.
72 # - Wrong names ("apps/browserAction.html"). This really does happen,
73 # damn it, so do the above logic but record which is the default.
74 if any(path.startswith(prefix) for prefix in ('extensions/', 'apps/')):
cduvall 2013/05/15 00:50:50 i believe you can do: path.startswith(('extensions
not at google - send to devlin 2013/05/15 01:26:50 Done.
75 default_platform, reference_path = path.split('/', 1)
40 else: 76 else:
41 apps_path = '%s/apps/%s' % (self._channel, path_without_channel) 77 default_platform, reference_path = ('extensions', path)
42 extensions_path = '%s/extensions/%s' % (self._channel,
43 path_without_channel)
44 78
45 unix_path = UnixName(os.path.splitext(path_without_channel)[0]) 79 try:
46 if unix_path in extensions_templates: 80 apps_public = self._public_apis.GetFromFileListing(
47 return extensions_path 81 '/'.join((svn_constants.PUBLIC_TEMPLATE_PATH, 'apps')))
48 if unix_path in apps_templates: 82 extensions_public = self._public_apis.GetFromFileListing(
49 return apps_path 83 '/'.join((svn_constants.PUBLIC_TEMPLATE_PATH, 'extensions')))
50 return extensions_path 84 except FileNotFoundError:
85 # Probably offline.
86 logging.warning(traceback.format_exc())
87 return ReturnType(path, False)
88
89 simple_reference_path = _SimplifyFileName(reference_path)
90 apps_path = apps_public.get(simple_reference_path)
91 extensions_path = extensions_public.get(simple_reference_path)
92
93 if apps_path is None:
94 if extensions_path is None:
95 # No idea. Just return the original path. It'll probably 404.
96 pass
97 else:
98 path = 'extensions/%s' % extensions_path
99 else:
100 if extensions_path is None:
101 path = 'apps/%s' % apps_path
102 else:
103 assert apps_path == extensions_path
104 path = '%s/%s' % (default_platform, apps_path)
105
106 return ReturnType(path, False)
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698