1#!/usr/bin/env python
2# Copyright 2014 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
7"""Takes the JSON files in components/domain_reliability/baked_in_configs and
8encodes their contents as an array of C strings that gets compiled in to Chrome
9and loaded at runtime."""
10
11
12import json
13import os
14import sys
15
16
17# A whitelist of domains that the script will accept when baking configs in to
18# Chrome, to ensure incorrect ones are not added accidentally. Subdomains of
19# whitelist entries are also allowed (e.g. maps.google.com, ssl.gstatic.com).
20DOMAIN_WHITELIST = ('2mdn.net', 'admob.com', 'doubleclick.net', 'ggpht.com',
21                    'google.cn', 'google.co.uk', 'google.com', 'google.com.au',
22                    'google.de', 'google.fr', 'google.it', 'google.jp',
23                    'google.org', 'google.ru', 'googleadservices.com',
24                    'googleapis.com', 'googlesyndication.com',
25                    'googleusercontent.com', 'googlevideo.com', 'gstatic.com',
26                    'gvt1.com', 'youtube.com', 'ytimg.com')
27
28
29CC_HEADER = """// Copyright (C) 2014 The Chromium Authors. All rights reserved.
30// Use of this source code is governed by a BSD-style license that can be
31// found in the LICENSE file.
32
33// AUTOGENERATED FILE. DO NOT EDIT.
34//
35// (Update configs in components/domain_reliability/baked_in_configs and list
36// configs in components/domain_reliability.gypi instead.)
37
38#include "components/domain_reliability/baked_in_configs.h"
39
40#include <stdlib.h>
41
42namespace domain_reliability {
43
44const char* const kBakedInJsonConfigs[] = {
45"""
46
47
48CC_FOOTER = """  NULL
49};
50
51}  // namespace domain_reliability
52"""
53
54
55def domain_is_whitelisted(domain):
56  return any(domain == e or domain.endswith('.' + e)  for e in DOMAIN_WHITELIST)
57
58
59def quote_and_wrap_text(text, width=79, prefix='  "', suffix='"'):
60  max_length = width - len(prefix) - len(suffix)
61  output = prefix
62  line_length = 0
63  for c in text:
64    if c == "\"":
65      c = "\\\""
66    elif c == "\n":
67      c = "\\n"
68    elif c == "\\":
69      c = "\\\\"
70    if line_length + len(c) > max_length:
71      output += suffix + "\n" + prefix
72      line_length = 0
73    output += c
74    line_length += len(c)
75  output += suffix
76  return output
77
78
79def main():
80  if len(sys.argv) < 3:
81    print >> sys.stderr, ('Usage: %s <JSON files...> <output C++ file>' %
82                          sys.argv[0])
83    print >> sys.stderr, sys.modules[__name__].__doc__
84    return 1
85
86  cpp_code = CC_HEADER
87  found_invalid_config = False
88  for json_file in sys.argv[1:-1]:
89    with open(json_file, 'r') as f:
90      json_text = f.read()
91    config = json.loads(json_text)
92    if 'monitored_domain' not in config:
93      print >> sys.stderr, ('%s: no monitored_domain found' % json_file)
94      found_invalid_config = True
95      continue
96    domain = config['monitored_domain']
97    if not domain_is_whitelisted(domain):
98      print >> sys.stderr, ('%s: monitored_domain "%s" not in whitelist' %
99                            (json_file, domain))
100      found_invalid_config = True
101      continue
102    cpp_code += "  // " + json_file + ":\n"
103    cpp_code += quote_and_wrap_text(json_text) + ",\n"
104    cpp_code += "\n"
105  cpp_code += CC_FOOTER
106
107  if found_invalid_config:
108    return 1
109
110  with open(sys.argv[-1], 'wb') as f:
111    f.write(cpp_code)
112
113  return 0
114
115
116if __name__ == '__main__':
117  sys.exit(main())
118