#!/usr/bin/env python
# Copyright 2014 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.


"""Takes the JSON files in components/domain_reliability/baked_in_configs and
encodes their contents as an array of C strings that gets compiled in to Chrome
and loaded at runtime."""


import json
import os
import sys


# A whitelist of domains that the script will accept when baking configs in to
# Chrome, to ensure incorrect ones are not added accidentally. Subdomains of
# whitelist entries are also allowed (e.g. maps.google.com, ssl.gstatic.com).
DOMAIN_WHITELIST = ('2mdn.net', 'admob.com', 'doubleclick.net', 'ggpht.com',
                    'google.cn', 'google.co.uk', 'google.com', 'google.com.au',
                    'google.de', 'google.fr', 'google.it', 'google.jp',
                    'google.org', 'google.ru', 'googleadservices.com',
                    'googleapis.com', 'googlesyndication.com',
                    'googleusercontent.com', 'googlevideo.com', 'gstatic.com',
                    'gvt1.com', 'youtube.com', 'ytimg.com')


CC_HEADER = """// Copyright (C) 2014 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.

// AUTOGENERATED FILE. DO NOT EDIT.
//
// (Update configs in components/domain_reliability/baked_in_configs and list
// configs in components/domain_reliability.gypi instead.)

#include "components/domain_reliability/baked_in_configs.h"

#include <stdlib.h>

namespace domain_reliability {

const char* const kBakedInJsonConfigs[] = {
"""


CC_FOOTER = """  NULL
};

}  // namespace domain_reliability
"""


def domain_is_whitelisted(domain):
  return any(domain == e or domain.endswith('.' + e)  for e in DOMAIN_WHITELIST)


def quote_and_wrap_text(text, width=79, prefix='  "', suffix='"'):
  max_length = width - len(prefix) - len(suffix)
  output = prefix
  line_length = 0
  for c in text:
    if c == "\"":
      c = "\\\""
    elif c == "\n":
      c = "\\n"
    elif c == "\\":
      c = "\\\\"
    if line_length + len(c) > max_length:
      output += suffix + "\n" + prefix
      line_length = 0
    output += c
    line_length += len(c)
  output += suffix
  return output


def main():
  if len(sys.argv) < 3:
    print >> sys.stderr, ('Usage: %s <JSON files...> <output C++ file>' %
                          sys.argv[0])
    print >> sys.stderr, sys.modules[__name__].__doc__
    return 1

  cpp_code = CC_HEADER
  found_invalid_config = False
  for json_file in sys.argv[1:-1]:
    with open(json_file, 'r') as f:
      json_text = f.read()
    config = json.loads(json_text)
    if 'monitored_domain' not in config:
      print >> sys.stderr, ('%s: no monitored_domain found' % json_file)
      found_invalid_config = True
      continue
    domain = config['monitored_domain']
    if not domain_is_whitelisted(domain):
      print >> sys.stderr, ('%s: monitored_domain "%s" not in whitelist' %
                            (json_file, domain))
      found_invalid_config = True
      continue
    cpp_code += "  // " + json_file + ":\n"
    cpp_code += quote_and_wrap_text(json_text) + ",\n"
    cpp_code += "\n"
  cpp_code += CC_FOOTER

  if found_invalid_config:
    return 1

  with open(sys.argv[-1], 'wb') as f:
    f.write(cpp_code)

  return 0


if __name__ == '__main__':
  sys.exit(main())
