[module.json extensions] timeline views

Bug: 1134103
Change-Id: I168d621048b93f00b16b6f7d4fd11d2e4bb4f031
Reviewed-on: https://chromium-review.googlesource.com/c/devtools/devtools-frontend/+/2631963
Commit-Queue: Andres Olivares <[email protected]>
Reviewed-by: Tim van der Lippe <[email protected]>
diff --git a/devtools_grd_files.gni b/devtools_grd_files.gni
index 7df06c2..179da0d 100644
--- a/devtools_grd_files.gni
+++ b/devtools_grd_files.gni
@@ -391,6 +391,7 @@
   "front_end/third_party/marked/marked.js",
   "front_end/third_party/puppeteer/puppeteer.js",
   "front_end/timeline/timeline-legacy.js",
+  "front_end/timeline/timeline-meta.js",
   "front_end/timeline/timeline.js",
   "front_end/timeline/timeline_module.js",
   "front_end/timeline_model/timeline_model-legacy.js",
diff --git a/devtools_module_entrypoints.gni b/devtools_module_entrypoints.gni
index 975fdc1..f77da72 100644
--- a/devtools_module_entrypoints.gni
+++ b/devtools_module_entrypoints.gni
@@ -187,6 +187,7 @@
   "third_party/marked/marked.js",
   "third_party/puppeteer/puppeteer.js",
   "timeline/timeline-legacy.js",
+  "timeline/timeline-meta.js",
   "timeline/timeline.js",
   "timeline_model/timeline_model-legacy.js",
   "timeline_model/timeline_model.js",
diff --git a/front_end/BUILD.gn b/front_end/BUILD.gn
index 07f8b51..1f54dc6 100644
--- a/front_end/BUILD.gn
+++ b/front_end/BUILD.gn
@@ -121,6 +121,7 @@
     "third_party/lighthouse",
     "third_party/puppeteer:bundle",
     "timeline:bundle",
+    "timeline:meta",
     "timeline_model:bundle",
     "toolbox_bootstrap:bundle",
     "ui:bundle",
diff --git a/front_end/devtools_app.js b/front_end/devtools_app.js
index 74660a1..590f741 100644
--- a/front_end/devtools_app.js
+++ b/front_end/devtools_app.js
@@ -20,6 +20,7 @@
 import './media/media-meta.js';
 import './mobile_throttling/mobile_throttling-meta.js';
 import './performance_monitor/performance_monitor-meta.js';
+import './timeline/timeline-meta.js';
 import * as Startup from './startup/startup.js';
 
 Startup.RuntimeInstantiator.startApplication('devtools_app');
diff --git a/front_end/timeline/BUILD.gn b/front_end/timeline/BUILD.gn
index 7605879..d099822 100644
--- a/front_end/timeline/BUILD.gn
+++ b/front_end/timeline/BUILD.gn
@@ -60,3 +60,9 @@
 
   deps = [ ":bundle" ]
 }
+
+devtools_entrypoint("meta") {
+  entrypoint = "timeline-meta.ts"
+
+  deps = [ ":bundle" ]
+}
diff --git a/front_end/timeline/module.json b/front_end/timeline/module.json
index c37a4fd..68c5b26 100644
--- a/front_end/timeline/module.json
+++ b/front_end/timeline/module.json
@@ -1,14 +1,6 @@
 {
   "extensions": [
     {
-      "type": "view",
-      "location": "panel",
-      "id": "timeline",
-      "title": "Performance",
-      "order": 50,
-      "className": "Timeline.TimelinePanel"
-    },
-    {
       "type": "setting",
       "category": "Performance",
       "title": "Hide chrome frame in Layers view",
@@ -185,15 +177,6 @@
       ]
     },
     {
-      "type": "view",
-      "location": "panel",
-      "id": "js_profiler",
-      "title": "JavaScript Profiler",
-      "persistence": "closeable",
-      "order": 65,
-      "className": "Profiler.JSProfilerPanel"
-    },
-    {
       "type": "action",
       "actionId": "timeline.previous-recording",
       "category": "Performance",
diff --git a/front_end/timeline/timeline-meta.ts b/front_end/timeline/timeline-meta.ts
new file mode 100644
index 0000000..0d20a80
--- /dev/null
+++ b/front_end/timeline/timeline-meta.ts
@@ -0,0 +1,67 @@
+// Copyright 2020 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 type * as Platform from '../platform/platform.js';
+import {ls} from '../platform/platform.js';
+import * as Root from '../root/root.js';
+import * as UI from '../ui/ui.js';
+
+// eslint-disable-next-line rulesdir/es_modules_import
+import type * as Timeline from './timeline.js';
+
+import type * as Profiler from '../profiler/profiler.js';
+
+let loadedTimelineModule: (typeof Timeline|undefined);
+
+let loadedProfilerModule: (typeof Profiler|undefined);
+
+
+async function loadTimelineModule(): Promise<typeof Timeline> {
+  if (!loadedTimelineModule) {
+    // Side-effect import resources in module.json
+    await Root.Runtime.Runtime.instance().loadModulePromise('timeline');
+    loadedTimelineModule = await import('./timeline.js');
+  }
+  return loadedTimelineModule;
+}
+
+
+// The profiler module is imported here because the view with id `js_profiler`
+// is implemented by `JSProfilerPanel` in profiler. It cannot be registered
+// in the profiler module as it belongs to the shell app and thus all apps
+// that extend from shell will have such view registered. This would cause a
+// collision with js_app as a separate view with the same id is registered in it.
+async function loadProfilerModule(): Promise<typeof Profiler> {
+  if (!loadedProfilerModule) {
+    // Side-effect import resources in module.json
+    await Root.Runtime.Runtime.instance().loadModulePromise('profiler');
+    loadedProfilerModule = await import('../profiler/profiler.js');
+  }
+  return loadedProfilerModule;
+}
+
+UI.ViewManager.registerViewExtension({
+  location: UI.ViewManager.ViewLocationValues.PANEL,
+  id: 'timeline',
+  title: (): Platform.UIString.LocalizedString => ls`Performance`,
+  commandPrompt: 'Show Performance',
+  order: 50,
+  async loadView() {
+    const Timeline = await loadTimelineModule();
+    return Timeline.TimelinePanel.TimelinePanel.instance();
+  },
+});
+
+UI.ViewManager.registerViewExtension({
+  location: UI.ViewManager.ViewLocationValues.PANEL,
+  id: 'js_profiler',
+  title: (): Platform.UIString.LocalizedString => ls`JavaScript Profiler`,
+  commandPrompt: 'Show JavaScript Profiler',
+  persistence: UI.ViewManager.ViewPersistence.CLOSEABLE,
+  order: 65,
+  async loadView() {
+    const Profiler = await loadProfilerModule();
+    return Profiler.ProfilesPanel.JSProfilerPanel.instance();
+  },
+});