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

Side by Side Diff: chrome/common/extensions/docs/server/main.py

Issue 10885049: Extensions Docs Server: KILL BUILD.PY (Closed) Base URL: svn://svn.chromium.org/chrome/trunk/src
Patch Set: Created 8 years, 3 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
(Empty)
1 #!/usr/bin/env python
2 # Copyright (c) 2012 The Chromium Authors. All rights reserved.
3 # Use of this source code is governed by a BSD-style license that can be
4 # found in the LICENSE file.
5
6 import cgi
7 import logging
8 import os
9 import re
10
11 from google.appengine.ext import webapp
12 from google.appengine.ext.webapp.util import run_wsgi_app
13 from google.appengine.api import memcache
14 from google.appengine.api import urlfetch
15
16 import app_known_issues
17
18 DEFAULT_CACHE_TIME = 300
19 VIEW_VC_ROOT = 'http://src.chromium.org'
20 CHROME_DOMAIN_URL = 'http://developer.chrome.com'
21
22 class Channel():
23 def __init__(self, name, tag):
24 self.name = name
25 self.tag = tag
26
27 Channel.DEV = Channel("dev", "2.0-dev")
28 Channel.BETA = Channel("beta", "1.1-beta")
29 Channel.STABLE = Channel("stable", "")
30 Channel.TRUNK = Channel("trunk", "")
31 Channel.CHANNELS = [Channel.TRUNK, Channel.DEV, Channel.BETA, Channel.STABLE]
32 Channel.DEFAULT = Channel.STABLE
33
34
35 def GetChannelByName(channelName):
36 for channel in Channel.CHANNELS:
37 if channel.name == channelName:
38 return channel
39
40 return None
41
42
43 def GetBranchRoot(branch):
44 if branch is None:
45 return '%s/viewvc/chrome/trunk/src/' % VIEW_VC_ROOT
46 else:
47 return '%s/viewvc/chrome/branches/%s/src/' % (VIEW_VC_ROOT, branch)
48
49
50 def GetExtensionsRoot(branch):
51 return GetBranchRoot(branch) + 'chrome/common/extensions/'
52
53
54 def GetDocsRoot(branch, docFamily):
55 if docFamily is None:
56 return GetExtensionsRoot(branch) + 'docs/'
57 else:
58 return GetExtensionsRoot(branch) + ('docs/%s/' % docFamily)
59
60
61 def GetSrcUrl(branch, docFamily, path):
62 # TODO(aa): Need cooler favicon.
63 if path[0] == 'favicon.ico':
64 return '%s/%s' % (VIEW_VC_ROOT, path[0])
65
66 pathstr = '/'.join(path)
67
68 if path[0] == 'api' and path[-1].endswith('.json'):
69 return GetExtensionsRoot(branch) + pathstr
70
71 if path[0] == 'third_party':
72 if path[-1] == 'jstemplate_compiled.js':
73 return GetBranchRoot(branch) + ('chrome/%s' % pathstr)
74 else:
75 return GetBranchRoot(branch) + pathstr
76
77 return GetDocsRoot(branch, docFamily) + pathstr
78
79
80 def GetBranch(channel):
81 """ Gets the name of the branch in source control that contains the code for
82 the Chrome version currently being served on |channel|."""
83 branch = memcache.get(channel.name)
84 if branch is not None:
85 return branch
86
87 # query Omaha to figure out which version corresponds to this channel
88 postdata = """<?xml version="1.0" encoding="UTF-8"?>
89 <o:gupdate xmlns:o="http://www.google.com/update2/request"
90 protocol="2.0" testsource="crxdocs">
91 <o:app appid="{8A69D345-D564-463C-AFF1-A69D9E530F96}"
92 version="0.0.0.0" lang="">
93 <o:updatecheck tag="%s"
94 installsource="ondemandcheckforupdates" />
95 </o:app>
96 </o:gupdate>
97 """ % channel.tag
98
99 result = urlfetch.fetch(
100 url="https://tools.google.com/service/update2",
101 payload=postdata,
102 method=urlfetch.POST,
103 headers={'Content-Type':'application/x-www-form-urlencoded',
104 'X-USER-IP': '72.1.1.1'})
105
106 if result.status_code != 200:
107 return None
108
109 match = re.search(r'<updatecheck Version="\d+\.\d+\.(\d+)\.\d+"',
110 result.content)
111 if match is None:
112 logging.error("Cannot find branch for requested channel: " + result.content)
113 return None
114
115 branch = match.group(1)
116 memcache.add(channel.name, branch, DEFAULT_CACHE_TIME)
117 return branch
118
119 class MainPage(webapp.RequestHandler):
120 def redirectToIndexIfNecessary(self):
121 if len(self.path) > 0:
122 return True
123 newPath = self.request.path
124 if not newPath.endswith('/'):
125 newPath += '/'
126 newPath += 'index.html'
127 self.redirect(newPath)
128 return False
129
130
131 def initPath(self):
132 self.path = self.request.path.split('/')
133
134 # The first component is always empty.
135 self.path.pop(0)
136
137 # The last component might be empty if there was a trailing slash.
138 if len(self.path) > 0 and self.path[-1] == '':
139 self.path.pop()
140
141 # Temporary hacks for apps.
142 # TODO(aa): Remove once the apps content percolates through Chrome's release
143 # process more.
144 if self.path == ['apps'] or self.path == ['trunk', 'apps']:
145 self.redirect('/trunk/apps/about_apps.html')
146 return False
147
148 # TODO(aa): Remove once we have a homepage for developer.chrome.com.
149 if (self.path == [] and
150 self.request.url.startswith('http://developer.chrome.com')):
151 self.redirect('http://developers.google.com/chrome')
152 return False
153
154 return self.redirectToIndexIfNecessary()
155
156
157 def initChannel(self):
158 self.channel = GetChannelByName(self.path[0])
159 if self.channel is not None:
160 self.path.pop(0)
161 else:
162 self.channel = Channel.DEFAULT
163 return self.redirectToIndexIfNecessary()
164
165
166 def initDocFamily(self):
167 if self.path[0] in ('extensions', 'apps'):
168 self.docFamily = self.path.pop(0)
169 else:
170 self.docFamily = 'extensions'
171 return self.redirectToIndexIfNecessary()
172
173
174 def redirectDomain(self):
175 if (self.request.url.startswith(('http://code.google.com',
176 'https://code.google.com'))):
177 newUrl = CHROME_DOMAIN_URL
178 # switch to https if necessary
179 if (self.request.url.startswith('https')):
180 newUrl = newUrl.replace('http', 'https', 1)
181 self.path.pop(0) # 'chrome'
182 for channel in ['dev', 'beta', 'stable', 'trunk']:
183 if channel in self.path:
184 position = self.path.index(channel)
185 self.path.pop(position)
186 self.path.insert(0, channel)
187 self.redirect(newUrl + '/' + '/'.join(self.path), True)
188 return False
189 else:
190 return True
191
192
193 def fetchContent(self):
194 logging.info("fetching: %s" % str((self.branch, self.docFamily, self.path)))
195
196 # For extensions, try the old directory layout first.
197 result = None
198 oldUrl = ''
199
200 if self.docFamily == 'extensions':
201 oldUrl = GetSrcUrl(self.branch, None, self.path)
202 result = urlfetch.fetch(oldUrl)
203
204 if result is None or result.status_code != 200:
205 newUrl = GetSrcUrl(self.branch, self.docFamily, self.path)
206 if oldUrl != newUrl:
207 logging.info('Trying new directory layout...')
208 result = urlfetch.fetch(newUrl)
209
210 # Files inside of samples should be rendered with content-type
211 # text/plain so that their source is visible when linked to. The only
212 # types we should serve as-is are images.
213 if (self.path[0] == 'examples' and
214 not (result.headers['content-type'].startswith('image/') or
215 result.headers['Content-Type'].startswith('image/'))):
216 result.headers['content-type'] = 'text/plain'
217
218 return result
219
220
221 def get(self):
222 if (not self.initPath() or
223 not self.redirectDomain() or
224 not self.initChannel() or
225 not self.initDocFamily()):
226 return
227
228 cacheKey = str((self.channel.name, self.docFamily, self.path))
229 result = memcache.get(cacheKey)
230 if result is None:
231 logging.info("cache miss: " + cacheKey)
232
233 self.branch = None
234 if self.channel is not Channel.TRUNK:
235 self.branch = GetBranch(self.channel)
236
237 result = self.fetchContent()
238 memcache.add(cacheKey, result, DEFAULT_CACHE_TIME)
239
240 if result is not None:
241 for key in result.headers:
242 self.response.headers[key] = result.headers[key]
243 self.response.out.write(result.content)
244
245
246 application = webapp.WSGIApplication([
247 ('/app_known_issues_snippet.html', app_known_issues.Handler),
248 ('/.*', MainPage),
249 ], debug=False)
250
251
252 def main():
253 run_wsgi_app(application)
254
255
256 if __name__ == '__main__':
257 main()
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698