168043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)# Copyright 2013 The Chromium Authors. All rights reserved. 268043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)# Use of this source code is governed by a BSD-style license that can be 368043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)# found in the LICENSE file. 468043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles) 51e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)# This file is expected to be used under another directory to use, 61e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)# so we disable checking import path of GAE tools from this directory. 71e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)# pylint: disable=F0401,E0611,W0232 81e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles) 968043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)import jinja2 1068043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)import json 1168043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)import os 1268043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)import re 1368043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)import urllib 1468043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)import webapp2 1568043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles) 1668043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)from google.appengine.ext import blobstore 1768043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)from google.appengine.ext.webapp import blobstore_handlers 1868043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles) 1968043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)import services 2068043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles) 2168043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles) 2268043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)JINJA_ENVIRONMENT = jinja2.Environment( 2368043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles) loader=jinja2.FileSystemLoader(os.path.dirname(__file__)), 2468043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles) extensions=['jinja2.ext.autoescape']) 2568043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles) 2668043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles) 2768043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)class MainPage(webapp2.RequestHandler): 2868043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles) """Show breakdown with received profiler-id and template-id. If nothing was 2968043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles) received, show blank page waiting user to upload file.""" 3068043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles) def get(self): 3168043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles) page_template = JINJA_ENVIRONMENT.get_template('index.html') 3268043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles) upload_url = blobstore.create_upload_url('/upload') 3368043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles) 3468043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles) # Get profiler id and template id from url query. 3568043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles) run_id = self.request.get('run_id') 3668043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles) tmpl_id = self.request.get('tmpl_id') 3768043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles) upload_msg = self.request.get('upload_msg') 3868043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles) 3968043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles) template_values = { 4068043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles) 'upload_url': upload_url, 4168043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles) 'upload_msg': upload_msg 4268043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles) } 4368043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles) 4468043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles) if run_id and tmpl_id: 4568043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles) template_values['json'] = services.GetProfiler(run_id) 4668043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles) template_values['template'] = services.GetTemplate(tmpl_id) 4768043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles) 4868043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles) self.response.write(page_template.render(template_values)) 4968043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles) 5068043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles) 5168043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)class UploadHandler(blobstore_handlers.BlobstoreUploadHandler): 5268043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles) """Handle file uploading with BlobstoreUploadHandler. BlobstoreUploadHandler 5368043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles) can deal with files overweighing size limitation within one HTTP connection so 5468043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles) that user can upload large json file.""" 5568043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles) def post(self): 5668043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles) blob_info = self.get_uploads('file')[0] 5768043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles) 5868043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles) run_id = services.CreateProfiler(blob_info) 5968043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles) default_key = services.CreateTemplates(blob_info) 6068043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles) 6168043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles) # TODO(junjianx): Validation of uploaded file should be done separately. 6268043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles) if not default_key: 6368043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles) # Jump to home page with error message. 6468043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles) req_params = { 6568043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles) 'upload_msg': 'No default_template key was found.' 6668043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles) } 6768043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles) else: 6868043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles) # Jump to new graph page using default template. 6968043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles) req_params = { 7068043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles) 'run_id': run_id, 7168043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles) 'tmpl_id': default_key.urlsafe() 7268043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles) } 7368043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles) 7468043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles) self.redirect('/?' + urllib.urlencode(req_params)) 7568043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles) 7668043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles) 7768043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)class ShareHandler(webapp2.RequestHandler): 7868043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles) """Handle breakdown template sharing. Generate public url for transferred 7968043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles) template and return it back.""" 8068043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles) def post(self): 8168043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles) run_id = self.request.POST['run_id'] 8268043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles) content = json.loads(self.request.POST['content']) 8368043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles) tmpl_key = services.CreateTemplate(content) 8468043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles) 8568043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles) req_params = { 8668043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles) 'run_id': run_id, 8768043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles) 'tmpl_id': tmpl_key.urlsafe() 8868043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles) } 8968043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles) 9068043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles) # Take out host url from request by removing share suffix. 9168043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles) url = re.sub('share', '', self.request.url) 9268043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles) self.response.write(url + '?' + urllib.urlencode(req_params)) 9368043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles) 9468043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles) 9568043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)application = webapp2.WSGIApplication([ 9668043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles) ('/', MainPage), 9768043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles) ('/upload', UploadHandler), 9868043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles) ('/share', ShareHandler) 991e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)], debug=True) 100