Switch to new repository
diff --git a/scripts/assert_empty_deps.py b/scripts/assert_empty_deps.py
new file mode 100644
index 0000000..6051f8f
--- /dev/null
+++ b/scripts/assert_empty_deps.py
@@ -0,0 +1,38 @@
+#!/usr/bin/env python
+#
+# Copyright 2019 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.
+
+import os
+import sys
+import json
+import devtools_paths
+
+
+def run_assert():
+    assert_errors_found = False
+    try:
+        with open(devtools_paths.package_json_path(), 'r') as pkg_file:
+            pkg = json.load(pkg_file)
+            if 'dependencies' in pkg:
+                print('dependencies property found in package.json')
+                assert_errors_found = True
+            if 'devDependencies' in pkg:
+                print('devDependencies property found in package.json')
+                assert_errors_found = True
+    except ValueError:
+        print('Unable to parse package.json')
+        assert_errors_found = True
+    except FileNotFoundError:
+        print('Unable to find package.json')
+        assert_errors_found = True
+
+    return assert_errors_found
+
+
+errors_found = run_assert()
+
+if errors_found:
+    print("ERRORS DETECTED")
+    sys.exit(1)
diff --git a/scripts/build/build_release_applications.py b/scripts/build/build_release_applications.py
index c9f78af..7dff77e 100755
--- a/scripts/build/build_release_applications.py
+++ b/scripts/build/build_release_applications.py
@@ -127,7 +127,6 @@
             self._write_include_tags(descriptors.extends, output)
         output.write(self._generate_include_tag(descriptors.application_name + '.js'))
 
-
     def _build_html(self):
         html_name = self.app_file('html')
         output = StringIO()
@@ -203,8 +202,8 @@
                 deps = set(desc.get('dependencies', []))
                 non_autostart_deps = deps & non_autostart
                 if len(non_autostart_deps):
-                    bail_error('Non-autostart dependencies specified for the autostarted module "%s": %s' %
-                               (name, non_autostart_deps))
+                    bail_error(
+                        'Non-autostart dependencies specified for the autostarted module "%s": %s' % (name, non_autostart_deps))
                 namespace = self._map_module_to_namespace(name)
                 output.write('\n/* Module %s */\n' % name)
                 output.write('\nself[\'%s\'] = self[\'%s\'] || {};\n' % (namespace, namespace))
diff --git a/scripts/build/code_generator_frontend.py b/scripts/build/code_generator_frontend.py
index 8b00f70..0f78ff8 100755
--- a/scripts/build/code_generator_frontend.py
+++ b/scripts/build/code_generator_frontend.py
@@ -229,8 +229,8 @@
         for member in json_enum["enum"]:
             enum_members.append("%s: \"%s\"" % (fix_camel_case(member), member))
 
-        Generator.backend_js_domain_initializer_list.append("Protocol.inspectorBackend.registerEnum(\"%s\", {%s});\n" %
-                                                            (enum_name, ", ".join(enum_members)))
+        Generator.backend_js_domain_initializer_list.append(
+            "Protocol.inspectorBackend.registerEnum(\"%s\", {%s});\n" % (enum_name, ", ".join(enum_members)))
 
     @staticmethod
     def process_event(json_event, domain_name):
@@ -291,7 +291,6 @@
 backend_js_file = open(output_js_dirname + "/InspectorBackendCommands.js", "w")
 
 backend_js_file.write(
-    Templates.backend_js.substitute(
-        None, domainInitializers="".join(Generator.backend_js_domain_initializer_list)))
+    Templates.backend_js.substitute(None, domainInitializers="".join(Generator.backend_js_domain_initializer_list)))
 
 backend_js_file.close()
diff --git a/scripts/build/generate_aria.py b/scripts/build/generate_aria.py
index 52cd165..c8f3f9c 100644
--- a/scripts/build/generate_aria.py
+++ b/scripts/build/generate_aria.py
@@ -4,11 +4,9 @@
 
 import json
 import os
-import os.path
 import sys
 
-PYJSON5_DIR = os.path.join(os.path.dirname(__file__),
-                           '..', '..', '..', '..', '..', 'pyjson5', 'src')
+PYJSON5_DIR = os.path.join(os.path.dirname(__file__), '..', '..', 'third_party', 'pyjson5', 'src')
 sys.path.append(PYJSON5_DIR)
 
 import json5  # pylint: disable=import-error
diff --git a/scripts/build/generate_protocol_externs.py b/scripts/build/generate_protocol_externs.py
index 492ee41..3c29239 100755
--- a/scripts/build/generate_protocol_externs.py
+++ b/scripts/build/generate_protocol_externs.py
@@ -36,11 +36,11 @@
 except ImportError:
     import simplejson as json
 
-sys.path.append(
-    path.normpath(
-        path.join(
-            path.dirname(path.abspath(__file__)),
-            os.pardir, os.pardir, os.pardir, os.pardir, os.pardir, 'inspector_protocol')))
+sys.path.append(path.dirname(path.abspath(__file__)))
+
+from devtools_paths import third_party_path
+
+sys.path.append(path.join(third_party_path(), 'inspector_protocol'))
 import pdl  # pylint: disable=F0401
 
 type_traits = {
@@ -173,8 +173,8 @@
                 output_file.write(" * @return {!Promise<%s>}\n" % out_param_type)
 
                 output_file.write(" */\n")
-                output_file.write("Protocol.%sAgent.prototype.%s = function(%s) {};\n" %
-                                  (domain_name, command["name"], ", ".join(params)))
+                output_file.write(
+                    "Protocol.%sAgent.prototype.%s = function(%s) {};\n" % (domain_name, command["name"], ", ".join(params)))
 
                 request_object_properties = []
                 request_type = "Protocol.%sAgent.%sRequest" % (domain_name, to_title_case(command["name"]))
@@ -200,8 +200,7 @@
                 output_file.write(" * @param {!%s} obj\n" % request_type)
                 output_file.write(" * @return {!Promise<!%s>}" % response_type)
                 output_file.write(" */\n")
-                output_file.write("Protocol.%sAgent.prototype.invoke_%s = function(obj) {};\n" %
-                                  (domain_name, command["name"]))
+                output_file.write("Protocol.%sAgent.prototype.invoke_%s = function(obj) {};\n" % (domain_name, command["name"]))
 
         if "types" in domain:
             for type in domain["types"]:
@@ -219,18 +218,18 @@
                             else:
                                 typedef_args.append("%s:(%s%s)" % (property["name"], param_type(domain_name, property), suffix))
                     if (typedef_args):
-                        output_file.write("\n/** @typedef {!{%s}} */\nProtocol.%s.%s;\n" %
-                                          (", ".join(typedef_args), domain_name, type["id"]))
+                        output_file.write(
+                            "\n/** @typedef {!{%s}} */\nProtocol.%s.%s;\n" % (", ".join(typedef_args), domain_name, type["id"]))
                     else:
                         output_file.write("\n/** @typedef {!Object} */\nProtocol.%s.%s;\n" % (domain_name, type["id"]))
                 elif type["type"] == "string" and "enum" in type:
                     output_file.write(generate_enum("Protocol.%s.%s" % (domain_name, type["id"]), type))
                 elif type["type"] == "array":
-                    output_file.write("\n/** @typedef {!Array<!%s>} */\nProtocol.%s.%s;\n" %
-                                      (param_type(domain_name, type["items"]), domain_name, type["id"]))
+                    output_file.write("\n/** @typedef {!Array<!%s>} */\nProtocol.%s.%s;\n" % (param_type(
+                        domain_name, type["items"]), domain_name, type["id"]))
                 else:
-                    output_file.write("\n/** @typedef {%s} */\nProtocol.%s.%s;\n" %
-                                      (type_traits[type["type"]], domain_name, type["id"]))
+                    output_file.write(
+                        "\n/** @typedef {%s} */\nProtocol.%s.%s;\n" % (type_traits[type["type"]], domain_name, type["id"]))
 
         if domain_name in ["Runtime", "Debugger", "HeapProfiler"]:
             output_file.write("/** @constructor */\n")
@@ -250,8 +249,8 @@
                             params.append(param["name"])
                             output_file.write(" * @param {%s} %s\n" % (param_type(domain_name, param), param["name"]))
                     output_file.write(" */\n")
-                output_file.write("Protocol.%sDispatcher.prototype.%s = function(%s) {};\n" %
-                                  (domain_name, event["name"], ", ".join(params)))
+                output_file.write(
+                    "Protocol.%sDispatcher.prototype.%s = function(%s) {};\n" % (domain_name, event["name"], ", ".join(params)))
 
     for domain in domains:
         domain_name = domain["domain"]
diff --git a/scripts/build/generate_supported_css.py b/scripts/build/generate_supported_css.py
index 45f9629..96aa40b 100755
--- a/scripts/build/generate_supported_css.py
+++ b/scripts/build/generate_supported_css.py
@@ -27,28 +27,14 @@
 # (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
 # OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
 
-try:
-    import simplejson as json
-except ImportError:
-    import json
-
-import ast
-import re
+import json
+import os
 import sys
 
+PYJSON5_DIR = os.path.join(os.path.dirname(__file__), '..', '..', 'third_party', 'pyjson5', 'src')
+sys.path.append(PYJSON5_DIR)
 
-def _json5_load(lines):
-    # Use json5.loads when json5 is available. Currently we use simple
-    # regexs to convert well-formed JSON5 to PYL format.
-    # Strip away comments and quote unquoted keys.
-    re_comment = re.compile(r"^\s*//.*$|//+ .*$", re.MULTILINE)
-    re_map_keys = re.compile(r"^\s*([$A-Za-z_][\w]*)\s*:", re.MULTILINE)
-    pyl = re.sub(re_map_keys, r"'\1':", re.sub(re_comment, "", lines))
-    # Convert map values of true/false to Python version True/False.
-    re_true = re.compile(r":\s*true\b")
-    re_false = re.compile(r":\s*false\b")
-    pyl = re.sub(re_true, ":True", re.sub(re_false, ":False", pyl))
-    return ast.literal_eval(pyl)
+import json5  # pylint: disable=import-error
 
 
 def _keep_only_required_keys(entry):
@@ -60,7 +46,7 @@
 
 def properties_from_file(file_name):
     with open(file_name) as json5_file:
-        doc = _json5_load(json5_file.read())
+        doc = json5.loads(json5_file.read())
 
     properties = []
     property_names = {}
diff --git a/scripts/build/modular_build.py b/scripts/build/modular_build.py
index c818ad9..c12f669 100755
--- a/scripts/build/modular_build.py
+++ b/scripts/build/modular_build.py
@@ -192,8 +192,8 @@
                     bail_error('Module "%s" (dependency of "%s") not listed in application descriptor %s' %
                                (dep, module['name'], application_descriptor_filename))
 
-        return Descriptors(
-            application_descriptor_name, self.application_dir, application_descriptor, module_descriptors, extends, has_html)
+        return Descriptors(application_descriptor_name, self.application_dir, application_descriptor, module_descriptors, extends,
+                           has_html)
 
     def _read_module_descriptor(self, module_name, application_descriptor_filename):
         json_filename = path.join(self.application_dir, module_name, 'module.json')
diff --git a/scripts/chromium.patch b/scripts/chromium.patch
new file mode 100644
index 0000000..24a7b56
--- /dev/null
+++ b/scripts/chromium.patch
@@ -0,0 +1,184 @@
+diff --git a/DEPS b/DEPS
+index 546c79bf0c61..3f25656ea33a 100644
+--- a/DEPS
++++ b/DEPS
+@@ -240,6 +240,10 @@ vars = {
+   # and whatever else without interference from each other.
+   'devtools_node_modules_revision': '499e57bfea8a4f8e8373321f2c99632372553e56',
+   # Three lines of non-changing comments so that
++  # the commit queue can handle CLs rolling devtools-frontend
++  # and whatever else without interference from each other.
++  'devtools_frontend_revision': '4175f4339ebc2c6ff392ccccfaeea7b62741f4eb',
++  # Three lines of non-changing comments so that
+   # the commit queue can handle CLs rolling libprotobuf-mutator
+   # and whatever else without interference from each other.
+   'libprotobuf-mutator': '439e81f8f4847ec6e2bf11b3aa634a5d8485633d',
+@@ -892,6 +896,9 @@ deps = {
+   'src/third_party/devtools-node-modules':
+     Var('chromium_git') + '/external/github.com/ChromeDevTools/devtools-node-modules' + '@' + Var('devtools_node_modules_revision'),
+
++  'src/third_party/devtools-frontend':
++    Var('chromium_git') + '/devtools/devtools-frontend' + '@' + Var('devtools_frontend_revision'),
++
+   'src/third_party/dom_distiller_js/dist':
+     Var('chromium_git') + '/chromium/dom-distiller/dist.git' + '@' + '3093c3e238768ab27ff756bd7563ccbb12129d9f',
+
+diff --git a/PRESUBMIT.py b/PRESUBMIT.py
+index 6f5b5b8b5334..6a0b2cbcaaf0 100644
+--- a/PRESUBMIT.py
++++ b/PRESUBMIT.py
+@@ -17,6 +17,7 @@ _EXCLUDED_PATHS = (
+     r"^skia[\\/].*",
+     r"^third_party[\\/]blink[\\/].*",
+     r"^third_party[\\/]breakpad[\\/].*",
++    r"^third_party[\\/]devtools-frontend[\\/].*",
+     # sqlite is an imported third party dependency.
+     r"^third_party[\\/]sqlite[\\/].*",
+     r"^v8[\\/].*",
+diff --git a/chrome/browser/flag-metadata.json b/chrome/browser/flag-metadata.json
+index 17195be4677a..b914c63b654d 100644
+--- a/chrome/browser/flag-metadata.json
++++ b/chrome/browser/flag-metadata.json
+@@ -1186,7 +1186,7 @@
+   },
+   {
+     "name": "enable-devtools-experiments",
+-    "owners": [ "//third_party/blink/renderer/devtools/OWNERS" ],
++    "owners": [ "//third_party/devtools-frontend/OWNERS" ],
+     // This is a catch-all for ongoing devtools experiments.
+     "expiry_milestone": -1
+   },
+diff --git a/chrome/browser/resources/chromeos/chromevox/run_jsbundler.gni b/chrome/browser/resources/chromeos/chromevox/run_jsbundler.gni
+index 0ae15629e8bc..6fa243b100bb 100644
+--- a/chrome/browser/resources/chromeos/chromevox/run_jsbundler.gni
++++ b/chrome/browser/resources/chromeos/chromevox/run_jsbundler.gni
+@@ -16,7 +16,7 @@ jsbundler_modules = rebase_path([
+                                 ".",
+                                 "$closure_library_dir/../bin/build")
+ jsbundler_modules +=
+-    [ "//third_party/blink/renderer/devtools/scripts/build/rjsmin.py" ]
++    [ "//third_party/devtools-frontend/scripts/build/rjsmin.py" ]
+
+ template("run_jsbundler") {
+   assert(defined(invoker.mode))
+diff --git a/chrome/browser/resources/chromeos/chromevox/tools/jsbundler.py b/chrome/browser/resources/chromeos/chromevox/tools/jsbundler.py
+index 38c1a8481be4..72f173bba736 100755
+--- a/chrome/browser/resources/chromeos/chromevox/tools/jsbundler.py
++++ b/chrome/browser/resources/chromeos/chromevox/tools/jsbundler.py
+@@ -41,7 +41,7 @@ _SCRIPT_DIR = os.path.realpath(os.path.dirname(__file__))
+ _CHROME_SOURCE = os.path.realpath(
+     os.path.join(_SCRIPT_DIR, *[os.path.pardir] * 6))
+ sys.path.insert(0, os.path.join(
+-    _CHROME_SOURCE, 'third_party/blink/renderer/devtools/scripts/build'))
++    _CHROME_SOURCE, 'third_party/devtools-frontend/scripts/build'))
+ sys.path.insert(0, os.path.join(
+     _CHROME_SOURCE, ('third_party/chromevox/third_party/' +
+                      'closure-library/closure/bin/build')))
+diff --git a/docs/chromoting_android_hacking.md b/docs/chromoting_android_hacking.md
+index 4ff112f55df7..dfd77cbc7e9e 100644
+--- a/docs/chromoting_android_hacking.md
++++ b/docs/chromoting_android_hacking.md
+@@ -80,8 +80,8 @@ display log messages to the `LogCat` pane.
+ <classpathentry kind="src" path="remoting/android/java/src"/>
+ <classpathentry kind="src" path="remoting/android/apk/src"/>
+ <classpathentry kind="src" path="remoting/android/javatests/src"/>
+-<classpathentry kind="src" path="third_party/blink/renderer/devtools/scripts/jsdoc-validator/src"/>
+-<classpathentry kind="src" path="third_party/blink/renderer/devtools/scripts/compiler-runner/src"/>
++<classpathentry kind="src" path="third_party/devtools-frontend/scripts/jsdoc-validator/src"/>
++<classpathentry kind="src" path="third_party/devtools-frontend/scripts/compiler-runner/src"/>
+ <classpathentry kind="src" path="third_party/webrtc/voice_engine/test/android/android_test/src"/>
+ <classpathentry kind="src" path="third_party/webrtc/modules/video_capture/android/java/src"/>
+ <classpathentry kind="src" path="third_party/webrtc/modules/video_render/android/java/src"/>
+diff --git a/docs/ui/ui_devtools/index.md b/docs/ui/ui_devtools/index.md
+index 29dc0a47b9f3..79bf4d546171 100644
+--- a/docs/ui/ui_devtools/index.md
++++ b/docs/ui/ui_devtools/index.md
+@@ -5,7 +5,7 @@ currently supported on Linux, Windows, Mac, and ChromeOS.
+
+ * [Old Ash Doc](https://www.chromium.org/developers/how-tos/inspecting-ash)
+ * [Backend Source Code](https://cs.chromium.org/chromium/src/components/ui_devtools/)
+-* [Inspector Frontend Source Code](https://cs.chromium.org/chromium/src/third_party/blink/renderer/devtools/front_end/)
++* [Inspector Frontend Source Code](https://chromium.googlesource.com/devtools/devtools-frontend)
+
+ ## How to run
+
+diff --git a/testing/buildbot/gn_isolate_map.pyl b/testing/buildbot/gn_isolate_map.pyl
+index 8bf82e7b2dfd..8f0c6224dae4 100644
+--- a/testing/buildbot/gn_isolate_map.pyl
++++ b/testing/buildbot/gn_isolate_map.pyl
+@@ -1012,17 +1012,17 @@
+   },
+   "devtools_closure_compile": {
+     "args": [
+-      "../../third_party/blink/renderer/devtools/scripts/compile_frontend.py",
++      "../../third_party/devtools-frontend/scripts/compile_frontend.py",
+     ],
+-    "label": "//third_party/blink/renderer/devtools:devtools_closure_compile",
++    "label": "//third_party/devtools-frontend:devtools_closure_compile",
+     "script": "//testing/scripts/run_devtools_check.py",
+     "type": "script",
+   },
+   "devtools_eslint": {
+     "args": [
+-      "../../third_party/blink/renderer/devtools/scripts/lint_javascript.py",
++      "../../third_party/devtools-frontend/scripts/lint_javascript.py",
+     ],
+-    "label": "//third_party/blink/renderer/devtools:devtools_eslint",
++    "label": "//third_party/devtools-frontend:devtools_eslint",
+     "script": "//testing/scripts/run_devtools_check.py",
+     "type": "script",
+   },
+diff --git a/third_party/blink/public/public_features.gni b/third_party/blink/public/public_features.gni
+index c4834efc30d1..f596ba74ca6e 100644
+--- a/third_party/blink/public/public_features.gni
++++ b/third_party/blink/public/public_features.gni
+@@ -13,7 +13,7 @@ declare_args() {
+
+   # If external_devtools_frontend is set to true, use DevTools frontend that is
+   # pulled as external dependency.
+-  external_devtools_frontend = false
++  external_devtools_frontend = true
+ }
+
+ # Unhandled Tap enable means Contextual Search aka Tap to Search.
+diff --git a/third_party/blink/web_tests/inspector-protocol/heap-profiler/resources/heap-snapshot-common.js b/third_party/blink/web_tests/inspector-protocol/heap-profiler/resources/heap-snapshot-common.js
+index ff6c2ff5328b..9bbffcbdb3d9 100644
+--- a/third_party/blink/web_tests/inspector-protocol/heap-profiler/resources/heap-snapshot-common.js
++++ b/third_party/blink/web_tests/inspector-protocol/heap-profiler/resources/heap-snapshot-common.js
+@@ -7,17 +7,17 @@
+   // This script is supposed to be evaluated in inspector-protocol/heap-profiler tests
+   // and the relative paths below are relative to that location.
+   await testRunner.loadScriptModule(
+-      '../../../../blink/renderer/devtools/front_end/platform/utilities.js');
++      '../../../../devtools-frontend/front_end/platform/utilities.js');
+   await testRunner.loadScriptModule(
+-      '../../../../blink/renderer/devtools/front_end/common/UIString.js');
++      '../../../../devtools-frontend/front_end/common/UIString.js');
+   await testRunner.loadScriptModule(
+-      '../../../../blink/renderer/devtools/front_end/heap_snapshot_model/HeapSnapshotModel.js');
++      '../../../../devtools-frontend/front_end/heap_snapshot_model/HeapSnapshotModel.js');
+   await testRunner.loadScriptModule(
+-      '../../../../blink/renderer/devtools/front_end/heap_snapshot_worker/HeapSnapshot.js');
++      '../../../../devtools-frontend/front_end/heap_snapshot_worker/HeapSnapshot.js');
+   await testRunner.loadScriptModule(
+-      '../../../../blink/renderer/devtools/front_end/text_utils/TextUtils.js');
++      '../../../../devtools-frontend/front_end/text_utils/TextUtils.js');
+   await testRunner.loadScriptModule(
+-      '../../../../blink/renderer/devtools/front_end/heap_snapshot_worker/HeapSnapshotLoader.js');
++      '../../../../devtools-frontend/front_end/heap_snapshot_worker/HeapSnapshotLoader.js');
+
+   // Expose the (de)serialize code from Common because the worker expects it on self.
+   // TODO(https://crbug.com/680046) Remove the dupe code below.
+diff --git a/tools/gritsettings/translation_expectations.pyl b/tools/gritsettings/translation_expectations.pyl
+index 7dc85b2ddb3a..2ca4cf1d885b 100644
+--- a/tools/gritsettings/translation_expectations.pyl
++++ b/tools/gritsettings/translation_expectations.pyl
+@@ -95,7 +95,7 @@
+     "cloud_print/virtual_driver/win/install/virtual_driver_setup_resources.grd": "Separate release process",
+     "components/components_locale_settings.grd": "Not UI strings; localized separately",
+     "components/omnibox/resources/omnibox_resources.grd": "Not UI strings; localized separately",
+-    "third_party/blink/renderer/devtools/front_end/langpacks/devtools_ui_strings.grd" : "Devtools UI strings that are optionally enabled by browser.",
++    "third_party/devtools-frontend/front_end/langpacks/devtools_ui_strings.grd" : "Devtools UI strings that are optionally enabled by browser.",
+     "tools/grit/grit/testdata/buildinfo.grd": "Test data",
+     "tools/grit/grit/testdata/chrome/app/generated_resources.grd": "Test data",
+     "tools/grit/grit/testdata/substitute.grd": "Test data",
diff --git a/scripts/compile_frontend.py b/scripts/compile_frontend.py
index 944ff15..58f1bd6 100755
--- a/scripts/compile_frontend.py
+++ b/scripts/compile_frontend.py
@@ -40,6 +40,7 @@
 from build import generate_protocol_externs
 
 import dependency_preprocessor
+import devtools_paths
 import utils
 
 try:
@@ -70,9 +71,10 @@
 
 SCRIPTS_PATH = path.dirname(path.abspath(__file__))
 DEVTOOLS_PATH = path.dirname(SCRIPTS_PATH)
-INSPECTOR_PATH = path.join(path.dirname(DEVTOOLS_PATH), 'core', 'inspector')
+ROOT_PATH = devtools_paths.root_path()
+BROWSER_PROTOCOL_PATH = path.join(ROOT_PATH, 'third_party', 'blink', 'renderer', 'core', 'inspector', 'browser_protocol.pdl')
 # TODO(dgozman): move these checks to v8.
-V8_INCLUDE_PATH = path.normpath(path.join(path.dirname(DEVTOOLS_PATH), os.pardir, os.pardir, os.pardir, 'v8', 'include'))
+JS_PROTOCOL_PATH = path.join(ROOT_PATH, 'v8', 'include', 'js_protocol.pdl')
 DEVTOOLS_FRONTEND_PATH = path.join(DEVTOOLS_PATH, 'front_end')
 GLOBAL_EXTERNS_FILE = to_platform_path(path.join(DEVTOOLS_FRONTEND_PATH, 'externs.js'))
 DEFAULT_PROTOCOL_EXTERNS_FILE = path.join(DEVTOOLS_FRONTEND_PATH, 'protocol_externs.js')
@@ -348,8 +350,7 @@
     if args.protocol_externs_file:
         protocol_externs_file = args.protocol_externs_file
     else:
-        generate_protocol_externs.generate_protocol_externs(protocol_externs_file, path.join(
-            INSPECTOR_PATH, 'browser_protocol.pdl'), path.join(V8_INCLUDE_PATH, 'js_protocol.pdl'))
+        generate_protocol_externs.generate_protocol_externs(protocol_externs_file, BROWSER_PROTOCOL_PATH, JS_PROTOCOL_PATH)
     loader = modular_build.DescriptorLoader(DEVTOOLS_FRONTEND_PATH)
     descriptors = loader.load_applications(APPLICATION_DESCRIPTORS)
     modules_by_name = descriptors.modules
diff --git a/scripts/dependency_preprocessor.py b/scripts/dependency_preprocessor.py
index 6b0e558..344a8cc 100644
--- a/scripts/dependency_preprocessor.py
+++ b/scripts/dependency_preprocessor.py
@@ -1,7 +1,6 @@
 # Copyright 2016 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.
-
 """
 This ensures that each front-end module does not accidentally rely on a module
 that isn't listed as a transitive dependency in the module.json.
diff --git a/scripts/devtools_paths.py b/scripts/devtools_paths.py
index 14d721c..6a50a6d 100644
--- a/scripts/devtools_paths.py
+++ b/scripts/devtools_paths.py
@@ -21,9 +21,9 @@
     if path.basename(PARENT_PATH) == 'renderer':
         # Chromium repository
         return path.dirname(path.dirname(path.dirname(PARENT_PATH)))
-    elif path.basename(PARENT_PATH) == 'third_party':
+    elif path.basename(PARENT_PATH) == 'devtools-frontend':
         # External repository, integrated build
-        return path.dirname(PARENT_PATH)
+        return path.dirname(path.dirname(PARENT_PATH))
     else:
         # External repository, standalone build
         return ABS_DEVTOOLS_PATH
@@ -49,16 +49,7 @@
 
 
 def node_modules_path():
-    SCRIPTS_PATH = path.dirname(path.abspath(__file__))
-    ABS_DEVTOOLS_PATH = path.dirname(SCRIPTS_PATH)
-    PARENT_PATH = path.dirname(ABS_DEVTOOLS_PATH)
-    # TODO(1011259): remove Chromium repository handling
-    if path.basename(PARENT_PATH) == 'renderer':
-        # While in Chromium repo, node modules are hosted in //third_party/devtools-node-modules.
-        return path.join(root_path(), 'third_party', 'devtools-node-modules', 'third_party', 'node_modules')
-    else:
-        # In the external repo, node modules are hosted in root.
-        return path.join(root_path(), 'node_modules')
+    return path.join(DEVTOOLS_ROOT_PATH, 'node_modules')
 
 
 def eslint_path():
diff --git a/scripts/download_chromium.py b/scripts/download_chromium.py
new file mode 100644
index 0000000..5c8b7e5
--- /dev/null
+++ b/scripts/download_chromium.py
@@ -0,0 +1,53 @@
+#!/usr/bin/env python
+#
+# Copyright 2019 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.
+"""
+Used to download a pre-built version of Chrome for running unit tests
+"""
+
+import argparse
+import os
+import shutil
+import sys
+import urllib
+import zipfile
+
+
+def parse_options(cli_args):
+    parser = argparse.ArgumentParser(description='Download Chromium')
+    parser.add_argument('url', help='download URL')
+    parser.add_argument('target', help='target directory')
+    parser.add_argument('path_to_binary', help='path to binary inside of the zip archive')
+    parser.add_argument('build_number', help='build number to find out whether we need to re-download')
+    return parser.parse_args(cli_args)
+
+
+def download_and_extract(options):
+    BUILD_NUMBER_FILE = os.path.join(options.target, 'build_number')
+    EXPECTED_BINARY = os.path.join(options.target, options.path_to_binary)
+    # Check whether we already downloaded pre-built Chromium of right build number
+    if os.path.exists(BUILD_NUMBER_FILE):
+        with open(BUILD_NUMBER_FILE) as file:
+            build_number = file.read().strip()
+            if build_number == options.build_number:
+                assert os.path.exists(EXPECTED_BINARY)
+                return
+
+    # Remove previous download
+    if os.path.exists(options.target):
+        shutil.rmtree(options.target)
+
+    # Download again and save build number
+    filehandle, headers = urllib.urlretrieve(options.url)
+    zip_file = zipfile.ZipFile(filehandle, 'r')
+    zip_file.extractall(path=options.target)
+    os.chmod(EXPECTED_BINARY, 0o555)
+    with open(BUILD_NUMBER_FILE, 'w') as file:
+        file.write(options.build_number)
+
+
+if __name__ == '__main__':
+    OPTIONS = parse_options(sys.argv[1:])
+    download_and_extract(OPTIONS)
diff --git a/scripts/jsdoc_validator/run_tests.py b/scripts/jsdoc_validator/run_tests.py
index 1fc290e..1739fdd 100755
--- a/scripts/jsdoc_validator/run_tests.py
+++ b/scripts/jsdoc_validator/run_tests.py
@@ -23,7 +23,8 @@
 golden_file = os.path.join(tests_path, 'golden.dat')
 
 test_files = [
-    os.path.join(tests_path, f) for f in os.listdir(tests_path)
+    os.path.join(tests_path, f)
+    for f in os.listdir(tests_path)
     if f.endswith('.js') and os.path.isfile(os.path.join(tests_path, f))
 ]
 
diff --git a/scripts/localization_utils/check_localized_strings.js b/scripts/localization_utils/check_localized_strings.js
index 90dd6b6..e82f435 100644
--- a/scripts/localization_utils/check_localized_strings.js
+++ b/scripts/localization_utils/check_localized_strings.js
@@ -500,8 +500,8 @@
   errorStr += 'Please refer to auto-generated message(s) below and modify as needed.\n\n';
 
   // Example error message:
-  // third_party/blink/renderer/devtools/front_end/network/NetworkDataGridNode.js Line 973: ls`(disk cache)`
-  // Add a new message tag for this string to third_party\blink\renderer\devtools\front_end\network\network_strings.grdp
+  // third_party/devtools-frontend/front_end/network/NetworkDataGridNode.js Line 973: ls`(disk cache)`
+  // Add a new message tag for this string to third_party\devtools-frontend\front_end\network\network_strings.grdp
   // <message name="IDS_DEVTOOLS_ad86890fb40822a3b12627efaca4ecd7" desc="Fill in the description.">
   //   (disk cache)
   // </message>
@@ -523,7 +523,7 @@
   let errorStr =
       '\nThe message(s) associated with the following IDS key(s) should be removed from its GRD/GRDP file(s):\n';
   // Example error message:
-  // third_party/blink/renderer/devtools/front_end/accessibility/accessibility_strings.grdp Line 300: IDS_DEVTOOLS_c9bbad3047af039c14d0e7ec957bb867
+  // third_party/devtools-frontend/front_end/accessibility/accessibility_strings.grdp Line 300: IDS_DEVTOOLS_c9bbad3047af039c14d0e7ec957bb867
   for (const [ids, messages] of keysToRemoveFromGRD) {
     messages.forEach(
         message => errorStr += `${localizationUtils.getRelativeFilePathFromSrc(message.grdpPath)}${
diff --git a/scripts/localization_utils/localization_utils.js b/scripts/localization_utils/localization_utils.js
index faf1d24..b10890a 100644
--- a/scripts/localization_utils/localization_utils.js
+++ b/scripts/localization_utils/localization_utils.js
@@ -32,13 +32,12 @@
 };
 const IDSPrefix = 'IDS_DEVTOOLS_';
 
-const THIRD_PARTY_PATH = path.resolve(__dirname, '..', '..', '..', '..', '..');
-const SRC_PATH = path.resolve(THIRD_PARTY_PATH, '..');
-const GRD_PATH = path.resolve(__dirname, '..', '..', 'front_end', 'langpacks', 'devtools_ui_strings.grd');
+const SRC_PATH = path.resolve(__dirname, '..', '..');
+const GRD_PATH = path.resolve(SRC_PATH, 'front_end', 'langpacks', 'devtools_ui_strings.grd');
 const SHARED_STRINGS_PATH = path.resolve(__dirname, '..', '..', 'front_end', 'langpacks', 'shared_strings.grdp');
-const REPO_NODE_MODULES_PATH = path.resolve(THIRD_PARTY_PATH, 'devtools-node-modules', 'third_party', 'node_modules');
-const escodegen = require(path.resolve(REPO_NODE_MODULES_PATH, 'escodegen'));
-const esprima = require(path.resolve(REPO_NODE_MODULES_PATH, 'esprima'));
+const NODE_MODULES_PATH = path.resolve(SRC_PATH, 'node_modules');
+const escodegen = require(path.resolve(NODE_MODULES_PATH, 'escodegen'));
+const esprima = require(path.resolve(NODE_MODULES_PATH, 'esprima'));
 
 function getRelativeFilePathFromSrc(filePath) {
   return path.relative(SRC_PATH, filePath);
@@ -335,4 +334,4 @@
   sanitizeStringIntoFrontendFormat,
   shouldParseDirectory,
   verifyFunctionCallee
-};
\ No newline at end of file
+};
diff --git a/scripts/manage_node_deps.py b/scripts/manage_node_deps.py
new file mode 100644
index 0000000..b4762f5
--- /dev/null
+++ b/scripts/manage_node_deps.py
@@ -0,0 +1,103 @@
+# Copyright 2019 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.
+"""
+Helper to manage DEPS.
+"""
+
+import os
+import os.path as path
+import subprocess
+import devtools_paths
+import shutil
+import json
+
+# List all DEPS here.
+DEPS = {
+    "@types/chai": "4.2.0",
+    "@types/mocha": "5.2.7",
+    "chai": "4.2.0",
+    "eslint": "6.0.1",
+    "karma": "4.2.0",
+    "karma-chai": "0.1.0",
+    "karma-chrome-launcher": "3.1.0",
+    "karma-mocha": "1.3.0",
+    "karma-typescript": "4.1.1",
+    "mocha": "6.2.0",
+    "escodegen": "1.12.0",
+    "esprima": "git+https://git@github.com/jquery/esprima.git#fe13460e646a0adc3c434ca8c478264ca2e78cec",
+    "typescript": "3.5.3"
+}
+
+
+def popen(arguments, cwd=None):
+    return subprocess.Popen(arguments, cwd=cwd, stdout=subprocess.PIPE, stderr=subprocess.STDOUT)
+
+
+def clean_node_modules():
+    # Clean the node_modules folder first. That way only the packages listed above
+    # (and their deps) are installed.
+    try:
+        shutil.rmtree(path.realpath(devtools_paths.node_modules_path()))
+    except OSError as err:
+        print('Error removing node_modules: %s, %s' % (err.filename, err.strerror))
+
+
+def strip_private_fields():
+    # npm adds private fields which need to be stripped.
+    pattern = path.join(devtools_paths.node_modules_path(), 'package.json')
+    packages = []
+    for root, dirnames, filenames in os.walk(devtools_paths.node_modules_path()):
+        for filename in filter(lambda f: f == 'package.json', filenames):
+            packages.append(path.join(root, filename))
+
+    for pkg in packages:
+        with open(pkg, 'r+') as pkg_file:
+            prop_removal_count = 0
+            try:
+                pkg_data = json.load(pkg_file)
+
+                # Remove anything that begins with an underscore, as these are
+                # the private fields in a package.json
+                for key in pkg_data.keys():
+                    if key.find(u'_') == 0:
+                        pkg_data.pop(key)
+                        prop_removal_count = prop_removal_count + 1
+
+                pkg_file.truncate(0)
+                pkg_file.seek(0)
+                json.dump(pkg_data, pkg_file, indent=2, sort_keys=True)
+                print("(%s): %s" % (prop_removal_count, pkg))
+            except:
+                print('Unable to fix: %s' % pkg)
+                return True
+
+    return False
+
+
+def install_deps():
+    clean_node_modules()
+
+    exec_command = ['npm', 'install', '--no-save']
+    for pkg, version in DEPS.items():
+        exec_command.append('%s@%s' % (pkg, version))
+
+    errors_found = False
+    npm_proc_result = subprocess.check_call(exec_command, cwd=devtools_paths.root_path())
+    if npm_proc_result != 0:
+        errors_found = True
+
+    # If npm fails, bail here, otherwise attempt to strip private fields.
+    if errors_found:
+        return True
+
+    errors_found = strip_private_fields()
+    return errors_found
+
+
+npm_errors_found = install_deps()
+
+if npm_errors_found:
+    print('npm installation failed')
+else:
+    print('npm installation successful')
diff --git a/scripts/roll_codemirror.py b/scripts/roll_codemirror.py
index 1019259..531b76c 100644
--- a/scripts/roll_codemirror.py
+++ b/scripts/roll_codemirror.py
@@ -2,6 +2,10 @@
 # Use of this source code is governed by a BSD-style license that can be
 # found in the LICENSE file.
 
+"""
+Helper script to update CodeMirror from upstream.
+"""
+
 import argparse
 import glob
 import os
@@ -9,20 +13,17 @@
 import subprocess
 import sys
 
-
 def parse_options(cli_args):
     parser = argparse.ArgumentParser(description='Roll CodeMirror')
     parser.add_argument('cm_dir', help='CodeMirror directory')
     parser.add_argument('devtools_dir', help='DevTools directory')
     return parser.parse_args(cli_args)
 
-
 def run_npm(options):
     print 'Building CodeMirror in %s' % os.path.abspath(options.cm_dir)
     subprocess.check_output(['npm', 'install'], cwd=options.cm_dir, stderr=subprocess.PIPE)
     subprocess.check_output(['npm', 'run', 'build'], cwd=options.cm_dir, stderr=subprocess.PIPE)
 
-
 def copy_lib_files(options):
     print 'Copying codemirror.js and codemirror.css'
     result = ''
@@ -78,7 +79,6 @@
         print 'Copying %s from %s' % (target_file, source_file)
         shutil.copyfile(source_file, target_file)
 
-
 def copy_cm_files(options):
     source_dir = os.path.join(options.cm_dir, 'addon')
     target_dir = os.path.join(options.devtools_dir, 'front_end', 'cm')
@@ -88,7 +88,6 @@
 
     find_and_copy_js_files(source_dir, target_dir, cm_filter)
 
-
 def copy_cm_modes_files(options):
     source_dir = os.path.join(options.cm_dir, 'mode')
     target_dir = os.path.join(options.devtools_dir, 'front_end', 'cm_modes')
@@ -98,7 +97,6 @@
 
     find_and_copy_js_files(source_dir, target_dir, cm_modes_filter)
 
-
 def copy_cm_web_modes_files(options):
     source_dir = os.path.join(options.cm_dir, 'mode')
     target_dir = os.path.join(options.devtools_dir, 'front_end', 'cm_web_modes')
@@ -108,7 +106,6 @@
 
     find_and_copy_js_files(source_dir, target_dir, cm_web_modes_filter)
 
-
 if __name__ == '__main__':
     OPTIONS = parse_options(sys.argv[1:])
     run_npm(OPTIONS)
diff --git a/scripts/roll_deps.py b/scripts/roll_deps.py
new file mode 100644
index 0000000..8690025
--- /dev/null
+++ b/scripts/roll_deps.py
@@ -0,0 +1,39 @@
+# Copyright 2019 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.
+"""
+Update manually maintained dependencies from Chromium.
+"""
+
+import argparse
+import os
+import shutil
+import sys
+
+FILES = [
+    ['v8', 'include', 'js_protocol.pdl'],
+    ['third_party', 'blink', 'renderer', 'core', 'css', 'css_properties.json5'],
+    ['third_party', 'blink', 'renderer', 'core', 'html', 'aria_properties.json5'],
+    ['third_party', 'blink', 'renderer', 'core', 'inspector', 'browser_protocol.pdl'],
+    ['third_party', 'axe-core', 'axe.d.ts'],
+    ['third_party', 'axe-core', 'axe.js'],
+    ['third_party', 'axe-core', 'axe.min.js'],
+    ['third_party', 'axe-core', 'LICENSE'],
+]
+
+
+def parse_options(cli_args):
+    parser = argparse.ArgumentParser(description='Roll dependencies from Chromium.')
+    parser.add_argument('chromium_dir', help='Chromium directory')
+    parser.add_argument('devtools_dir', help='DevTools directory')
+    return parser.parse_args(cli_args)
+
+
+def copy_files(options):
+    for file in FILES:
+        shutil.copy(os.path.join(options.chromium_dir, *file), os.path.join(options.devtools_dir, *file))
+
+
+if __name__ == '__main__':
+    OPTIONS = parse_options(sys.argv[1:])
+    copy_files(OPTIONS)
diff --git a/scripts/run_tests.py b/scripts/run_tests.py
index da9fcd8..6fe2c64 100755
--- a/scripts/run_tests.py
+++ b/scripts/run_tests.py
@@ -1,9 +1,13 @@
 #!/usr/bin/env python
 #
-# Copyright 2016 The Chromium Authors. All rights reserved.
+# Copyright 2019 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.
 
+"""
+Run Karma unit tests on a pre-built chrome or one specified via --chrome-binary.
+"""
+
 import os
 import re
 import subprocess
@@ -11,21 +15,14 @@
 
 import devtools_paths
 
-is_cygwin = sys.platform == 'cygwin'
-chrome_binary = None
 
-if len(sys.argv) >= 2:
-    chrome_binary = re.sub(r'^\-\-chrome-binary=(.*)', '\\1', sys.argv[1])
-    is_executable = os.path.exists(chrome_binary) and os.path.isfile(chrome_binary) and os.access(chrome_binary, os.X_OK)
-    if not is_executable:
-        print('Unable to find a Chrome binary at \'%s\'' % chrome_binary)
-        sys.exit(1)
+def check_chrome_binary(chrome_binary):
+    return os.path.exists(chrome_binary) and os.path.isfile(chrome_binary) and os.access(chrome_binary, os.X_OK)
 
 
 def popen(arguments, cwd=None, env=None):
     return subprocess.Popen(arguments, cwd=cwd, stdout=subprocess.PIPE, stderr=subprocess.STDOUT, env=env)
 
-
 def to_platform_path_exact(filepath):
     if not is_cygwin:
         return filepath
@@ -34,16 +31,6 @@
     return output.strip().replace('\\', '\\\\')
 
 
-scripts_path = os.path.dirname(os.path.abspath(__file__))
-devtools_path = os.path.dirname(scripts_path)
-
-print('Running tests with Karma...')
-if (chrome_binary is not None):
-    print('Using custom Chrome Binary (%s)\n' % chrome_binary)
-else:
-    print('Using system Chrome')
-
-
 def run_tests():
     karma_errors_found = False
 
@@ -66,6 +53,29 @@
     return karma_errors_found
 
 
+is_cygwin = sys.platform == "cygwin"
+chrome_binary = None
+DOWNLOADED_CHROME_BINARY = os.path.abspath(
+    os.path.join(os.path.dirname(__file__), '..', 'third_party', 'chrome', 'chrome-linux', 'chrome'))
+
+if check_chrome_binary(DOWNLOADED_CHROME_BINARY):
+    chrome_binary = DOWNLOADED_CHROME_BINARY
+
+if len(sys.argv) >= 2:
+    chrome_binary = re.sub(r"^\-\-chrome-binary=(.*)", "\\1", sys.argv[1])
+    if not check_chrome_binary(chrome_binary):
+        print("Unable to find a Chrome binary at \"%s\"" % chrome_binary)
+        sys.exit(1)
+
+scripts_path = os.path.dirname(os.path.abspath(__file__))
+devtools_path = os.path.dirname(scripts_path)
+
+print("Running tests with Karma...")
+if (chrome_binary is not None):
+    print("Using custom Chrome Binary (%s)\n" % chrome_binary)
+else:
+    print("Using system Chrome")
+
 errors_found = run_tests()
 
 if errors_found:
diff --git a/scripts/run_web_tests.py b/scripts/run_web_tests.py
new file mode 100755
index 0000000..3a9f091
--- /dev/null
+++ b/scripts/run_web_tests.py
@@ -0,0 +1,52 @@
+#!/usr/bin/python
+
+# Copyright 2019 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.
+"""
+Integrate into Chromium and run webtests.
+"""
+
+import argparse
+import os
+import shutil
+import subprocess
+import sys
+
+
+def parse_options(cli_args):
+    parser = argparse.ArgumentParser(description='Integrate into Chromium and run webtests.')
+    parser.add_argument('chromium_dir', help='Chromium directory')
+    parser.add_argument('devtools_dir', help='DevTools directory')
+    parser.add_argument('--nopatch', help='skip patching', action='store_true')
+    parser.add_argument('--nobuild', help='skip building', action='store_true')
+    return parser.parse_args(cli_args)
+
+
+def patch(options):
+    subprocess.check_call(['git', 'fetch', 'origin'], cwd=options.chromium_dir)
+    subprocess.check_call(['git', 'checkout', 'origin/lkgr'], cwd=options.chromium_dir)
+    DEVTOOLS_PATH = os.path.abspath(options.devtools_dir)
+    PATCH_FILE = os.path.join(DEVTOOLS_PATH, 'scripts', 'chromium.patch')
+    subprocess.check_call(['git', 'apply', PATCH_FILE], cwd=options.chromium_dir)
+    subprocess.check_call(['gclient', 'setdep', '--var=devtools_frontend_url=file://%s' % DEVTOOLS_PATH], cwd=options.chromium_dir)
+    subprocess.check_call(['gclient', 'setdep', '--var=devtools_frontend_revision=FETCH_HEAD'], cwd=options.chromium_dir)
+    subprocess.check_call(['gclient', 'sync'], cwd=options.chromium_dir)
+
+
+def build(options):
+    subprocess.check_call(['autoninja', '-C', 'out/Release', 'blink_tests'], cwd=options.chromium_dir)
+
+
+def run(options):
+    subprocess.check_call(
+        [os.path.join(options.chromium_dir, 'third_party', 'blink', 'tools', 'run_web_tests.py'), 'http/tests/devtools/'])
+
+
+if __name__ == '__main__':
+    OPTIONS = parse_options(sys.argv[1:])
+    if not OPTIONS.nopatch:
+        patch(OPTIONS)
+    if not OPTIONS.nobuild:
+        build(OPTIONS)
+    run(OPTIONS)