blob: 0bc046be8c7df59d6a1506dba628c13aa517ff8e [file] [log] [blame]
#!/usr/bin/env python
# Copyright 2018 The Chromium Authors. All rights reserved.
# Use of this source code is governed by a BSD-style license that can be
# found in the LICENSE file.
"""Copies file_manager/main.html to file_manager/test.html.
Modifies it to be able to run the CrOS FileManager app
as a regular web page in a single renderer.
"""
import argparse
import json
import os
import re
import sys
import time
import xml.etree.ElementTree as ET
assert __name__ == '__main__'
parser = argparse.ArgumentParser()
parser.add_argument('--output')
args = parser.parse_args()
# If --output is not provided, write to local test.html.
output = args.output or os.path.abspath(
os.path.join(sys.path[0], '../../test.html'))
# ROOT_SRC: Absolute path to src //ui/file_manager/file_manager.
# ROOT_GEN: Absolute path to $target_gen_dir of ROOT_SRC.
# ROOT : Relative path from ROOT_GEN to ROOT_SRC.
ROOT_SRC = os.path.abspath(os.path.join(sys.path[0], '../..'))
ROOT_GEN = os.path.dirname(os.path.abspath(output))
ROOT = os.path.relpath(ROOT_SRC, ROOT_GEN) + '/'
scripts = []
GENERATED = 'Generated at %s by: %s' % (time.ctime(), sys.path[0])
GENERATED_HTML = '<!-- %s -->\n\n' % GENERATED
def read(path):
with open(os.path.join(ROOT_SRC, path)) as f:
return f.read()
def write(path, content):
fullpath = os.path.join(ROOT_GEN, path)
if not os.path.exists(os.path.dirname(fullpath)):
os.makedirs(os.path.dirname(fullpath))
with open(fullpath, 'w') as f:
f.write(content)
def replaceline(f, match, lines):
"""Replace matching line in file with lines."""
for i in range(len(f)):
if match in f[i]:
return f[:i] + lines + f[i+1:]
return f
def includes2scripts(include_filename):
"""Convert <include src='foo'> to <script src='<prefix>foo'></script>."""
scripts.append('<!-- %s -->' % include_filename)
prefix = ROOT + include_filename[:include_filename.rindex('/')+1]
f = read(include_filename).split('\n')
for i in range(len(f)):
l = f[i]
# Join back any include with a line-break.
if l == '// <include' and f[i+1].startswith('// src='):
f[i+1] = l + f[i+1][2:]
continue
if l.startswith('// <include '):
l = l.replace('// <include ', '<script ')
# Special fix for analytics.
if 'webui/resources/js/analytics.js' in l:
l = l.replace('webui/resources/js/analytics.js',
'../third_party/analytics/google-analytics-bundle.js')
# main.js should be defer.
if 'src="main.js"' in l:
l = l.replace('src="main.js"', 'src="main.js" defer')
# Fix the path for scripts to be relative to ROOT.
if 'src="../../' in l:
l = l.replace('src="../../', 'src="' + ROOT)
else:
l = l.replace('src="', 'src="' + prefix)
tag = l + '</script>'
if tag not in scripts:
scripts.append(tag)
# Update relative paths.
# Fix link to action_link.css and text_defaults.css.
# Fix stylesheet from extension.
main_html = (read('main.html')
.replace('chrome://resources/css/action_link.css',
'../../webui/resources/css/action_link.css')
.replace('<link rel="import" '
'href="chrome://resources/html/polymer.html">',
'<script src="../../webui/resources/js/'
'polymer_config.js"></script>')
.replace('href="', 'href="' + ROOT)
.replace('src="', 'src="' + ROOT)
.replace(ROOT + 'chrome://resources/css/text_defaults.css',
'test/gen/css/text_defaults.css')
.split('\n'))
# Fix text_defaults.css. Copy and replace placeholders.
text_defaults = (read('../../webui/resources/css/text_defaults.css')
.replace('$i18n{textDirection}', 'ltr')
.replace('$i18nRaw{fontFamily}', 'Roboto, sans-serif')
.replace('$i18nRaw{fontSize}', '75%'))
write('test/gen/css/text_defaults.css', text_defaults)
# Add scripts required for testing, and the test files (test/*.js).
scripts.append('<!-- required for testing -->')
scripts += ['<script src="%s%s"></script>' % (ROOT, s) for s in [
'test/js/chrome_api_test_impl.js',
'../../webui/resources/js/assert.js',
'../../webui/resources/js/cr.js',
'../../webui/resources/js/cr/event_target.js',
'../../webui/resources/js/cr/ui/array_data_model.js',
'../../webui/resources/js/load_time_data.js',
'../../webui/resources/js/webui_resource_test.js',
'test/js/strings.js',
'common/js/files_app_entry_types.js',
'common/js/util.js',
'common/js/mock_entry.js',
'../base/js/volume_manager_types.js',
'background/js/volume_info_impl.js',
'background/js/volume_info_list_impl.js',
'background/js/volume_manager_impl.js',
'background/js/mock_volume_manager.js',
'foreground/js/constants.js',
'test/js/chrome_file_manager_private_test_impl.js',
'test/js/test_util.js',
] + ['test/' + s for s in os.listdir(os.path.join(ROOT_SRC, 'test'))
if s.endswith('.js')]]
# Convert all includes from:
# * foreground/js/main_scripts.js
# * background/js/background_common_scripts.js
# * background/js/background_scripts.js
# into <script> tags in main.html.
# Add polymer libs at start.
# Define FILE_MANAGER_ROOT which is required to locate test data files.
includes2scripts('foreground/js/main_scripts.js')
includes2scripts('background/js/background_common_scripts.js')
includes2scripts('background/js/background_scripts.js')
# test_util_base.js in background_common_scripts.js loads this at runtime.
# However, test/js/test_util.js copies some functions from it into its own
# test context, so provide it here.
scripts += ['<script src="%s%s"></script>' %
(ROOT, 'background/js/runtime_loaded_test_util.js')]
main_html = replaceline(main_html, 'foreground/js/main_scripts.js', [
('<link rel="import" href="%s../../../third_party/polymer/v1_0/'
'components-chromium/polymer/polymer.html">' % ROOT),
('<link rel="import" href="%s../../../third_party/polymer/v1_0/'
'components-chromium/paper-progress/paper-progress.html">' % ROOT),
"<script>var FILE_MANAGER_ROOT = '%s';</script>" % ROOT,
] + scripts)
# Get strings from grdp files. Remove any ph/ex elements before getting text.
# Parse private_api_strings.cc to match the string name to the grdp message.
strings = {}
grdp_files = [
'../../../chrome/app/chromeos_strings.grdp',
'../../../chrome/app/file_manager_strings.grdp',
]
resource_bundle = {}
for grdp in grdp_files:
for msg in ET.fromstring(read(grdp)):
for ph in msg.findall('ph'):
for ex in ph.findall('ex'):
ph.remove(ex)
resource_bundle[msg.attrib['name']] = ''.join(msg.itertext()).strip()
private_api_strings = read('../../../chrome/browser/chromeos/extensions/'
'file_manager/private_api_strings.cc')
for m in re.finditer(r'SET_STRING\(\"(.*?)\",\s+(\w+)\);', private_api_strings):
strings[m.group(1)] = resource_bundle.get(m.group(2), m.group(2))
def elements_path(elements_filename):
return '="../../../../%sforeground/elements/%s' % (ROOT, elements_filename)
# Fix relative file paths in elements_bundle.html
# Load QuickView in iframe rather than webview.
# Change references in files_quick_view.html to use updated
# files_safe_media.html which will use webview rather than iframe,
# and sets src directly on iframe.
for filename, substitutions in (
('test/js/strings.js', (
('$GRDP', json.dumps(strings, sort_keys=True, indent=2)),
)),
('foreground/elements/elements_bundle.html', (
('="files_ripple', elements_path('files_ripple')),
('="files_toast', elements_path('files_toast')),
('="files_toggle_ripple', elements_path('files_toggle_ripple')),
('="files_tooltip', elements_path('files_tooltip')),
('="icons', elements_path('icons')),
)),
('foreground/js/elements_importer.js', (
("= 'foreground", "= 'test/gen/foreground"),
)),
('foreground/elements/files_quick_view.html', (
('="files_icon', elements_path('files_icon')),
('="files_metadata', elements_path('files_metadata')),
('="files_tooltip', elements_path('files_tooltip')),
('="files_quick', elements_path('files_quick')),
('="icons', elements_path('icons')),
('webview', 'iframe'),
)),
('foreground/elements/files_safe_media.html', (('webview', 'iframe'),)),
('foreground/elements/files_safe_media.js', (
("'foreground/elements", "'%sforeground/elements" % ROOT),
("'webview'", "'iframe'"),
("'contentload'", "'load'"),
('this.webview_.contentWindow.postMessage(data, FILES_APP_ORIGIN);',
('this.webview_.contentWindow.content.type = this.type;'
'this.webview_.contentWindow.content.src = this.src;')),
)),
):
buf = read(filename)
for old, new in substitutions:
buf = buf.replace(old, new)
write('test/gen/' + filename, buf)
main_html = replaceline(main_html, filename,
['<script src="test/gen/%s"></script>' % filename])
test_html = GENERATED_HTML + '\n'.join(main_html)
write('test.html', test_html)