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