[module.json extensions] migrate remaining views in browser_debuger

3 views where remaining from the browser_debugger migration because they
depend on sources. Because duplication of view ids would occur if such
views were migrated into sources-meta.ts they are kept in
browser_debugger-meta.ts.

Bug: 1134103
Change-Id: I2b1a353043a3cb9a880882dd429f55ad5bf567ab
Reviewed-on: https://chromium-review.googlesource.com/c/devtools/devtools-frontend/+/2631964
Commit-Queue: Andres Olivares <[email protected]>
Reviewed-by: Tim van der Lippe <[email protected]>
diff --git a/front_end/browser_debugger/browser_debugger-meta.ts b/front_end/browser_debugger/browser_debugger-meta.ts
index 03eb2ce..dc01fae 100644
--- a/front_end/browser_debugger/browser_debugger-meta.ts
+++ b/front_end/browser_debugger/browser_debugger-meta.ts
@@ -9,6 +9,7 @@
 
 // eslint-disable-next-line rulesdir/es_modules_import
 import type * as BrowserDebugger from './browser_debugger.js';
+import type * as Sources from '../sources/sources.js';
 
 let loadedBrowserDebuggerModule: (typeof BrowserDebugger|undefined);
 
@@ -21,6 +22,22 @@
   return loadedBrowserDebuggerModule;
 }
 
+let loadedSourcesModule: (typeof Sources|undefined);
+
+//  The sources module is imported here because the view with id `navigator-network`
+//  is implemented by `NetworkNavigatorView` in sources. It cannot be registered
+//  in the sources 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 node_app as a separate view with the same id is registered in it.
+async function loadSourcesModule(): Promise<typeof Sources> {
+  if (!loadedSourcesModule) {
+    // Side-effect import resources in module.json
+    await Root.Runtime.Runtime.instance().loadModulePromise('sources');
+    loadedSourcesModule = await import('../sources/sources.js');
+  }
+  return loadedSourcesModule;
+}
+
 UI.ViewManager.registerViewExtension({
   async loadView() {
     const BrowserDebugger = await loadBrowserDebuggerModule();
@@ -100,3 +117,43 @@
   order: 6,
   persistence: UI.ViewManager.ViewPersistence.PERMANENT,
 });
+
+
+UI.ViewManager.registerViewExtension({
+  location: UI.ViewManager.ViewLocationValues.NAVIGATOR_VIEW,
+  id: 'navigator-network',
+  title: (): Platform.UIString.LocalizedString => ls`Page`,
+  commandPrompt: 'Show Page',
+  order: 2,
+  persistence: UI.ViewManager.ViewPersistence.PERMANENT,
+  async loadView() {
+    const Sources = await loadSourcesModule();
+    return Sources.SourcesNavigator.NetworkNavigatorView.instance();
+  },
+});
+
+UI.ViewManager.registerViewExtension({
+  location: UI.ViewManager.ViewLocationValues.NAVIGATOR_VIEW,
+  id: 'navigator-overrides',
+  title: (): Platform.UIString.LocalizedString => ls`Overrides`,
+  commandPrompt: 'Show Overrides',
+  order: 4,
+  persistence: UI.ViewManager.ViewPersistence.PERMANENT,
+  async loadView() {
+    const Sources = await loadSourcesModule();
+    return Sources.SourcesNavigator.OverridesNavigatorView.instance();
+  },
+});
+
+UI.ViewManager.registerViewExtension({
+  location: UI.ViewManager.ViewLocationValues.NAVIGATOR_VIEW,
+  id: 'navigator-contentScripts',
+  title: (): Platform.UIString.LocalizedString => ls`Content scripts`,
+  commandPrompt: 'Show Content scripts',
+  order: 5,
+  persistence: UI.ViewManager.ViewPersistence.PERMANENT,
+  async loadView() {
+    const Sources = await loadSourcesModule();
+    return Sources.SourcesNavigator.ContentScriptsNavigatorView.instance();
+  },
+});
diff --git a/front_end/browser_debugger/module.json b/front_end/browser_debugger/module.json
index 2cdd980..ed9a142 100644
--- a/front_end/browser_debugger/module.json
+++ b/front_end/browser_debugger/module.json
@@ -29,33 +29,6 @@
       "className": "BrowserDebugger.DOMBreakpointsSidebarPane"
     },
     {
-      "type": "view",
-      "location": "navigator-view",
-      "id": "navigator-network",
-      "title": "Page",
-      "order": 2,
-      "persistence": "permanent",
-      "className": "Sources.NetworkNavigatorView"
-    },
-    {
-      "type": "view",
-      "location": "navigator-view",
-      "id": "navigator-overrides",
-      "title": "Overrides",
-      "order": 4,
-      "persistence": "permanent",
-      "className": "Sources.OverridesNavigatorView"
-    },
-    {
-      "type": "view",
-      "location": "navigator-view",
-      "id": "navigator-contentScripts",
-      "title": "Content scripts",
-      "order": 5,
-      "persistence": "permanent",
-      "className": "Sources.ContentScriptsNavigatorView"
-    },
-    {
       "type": "@Sources.NavigatorView",
       "viewId": "navigator-overrides",
       "className": "Sources.OverridesNavigatorView"
diff --git a/front_end/sources/SourcesNavigator.js b/front_end/sources/SourcesNavigator.js
index 3a4f044..be6b090 100644
--- a/front_end/sources/SourcesNavigator.js
+++ b/front_end/sources/SourcesNavigator.js
@@ -53,7 +53,6 @@
     // Record the sources tool load time after the file navigator has loaded.
     Host.userMetrics.panelLoaded('sources', 'DevTools.Launch.Sources');
   }
-
   /**
    * @param {{forceNew: ?boolean}} opts
    */
@@ -166,7 +165,11 @@
   }
 }
 
+/** @type {!OverridesNavigatorView} */
+let overridesNavigatorViewInstance;
+
 export class OverridesNavigatorView extends NavigatorView {
+  /** @private */
   constructor() {
     super();
     const placeholder = new UI.EmptyWidget.EmptyWidget('');
@@ -188,6 +191,19 @@
   }
 
   /**
+   * @param {{forceNew: ?boolean}} opts
+   */
+  static instance(opts = {forceNew: null}) {
+    const {forceNew} = opts;
+    if (!overridesNavigatorViewInstance || forceNew) {
+      overridesNavigatorViewInstance = new OverridesNavigatorView();
+    }
+
+    return overridesNavigatorViewInstance;
+  }
+
+
+  /**
    * @param {!Common.EventTarget.EventTargetEvent} event
    */
   _onProjectAddOrRemoved(event) {
@@ -252,7 +268,11 @@
   }
 }
 
+/** @type {!ContentScriptsNavigatorView} */
+let contentScriptsNavigatorViewInstance;
+
 export class ContentScriptsNavigatorView extends NavigatorView {
+  /** @private */
   constructor() {
     super();
     const placeholder = new UI.EmptyWidget.EmptyWidget('');
@@ -264,6 +284,19 @@
   }
 
   /**
+   * @param {{forceNew: ?boolean}} opts
+   */
+  static instance(opts = {forceNew: null}) {
+    const {forceNew} = opts;
+    if (!contentScriptsNavigatorViewInstance || forceNew) {
+      contentScriptsNavigatorViewInstance = new ContentScriptsNavigatorView();
+    }
+
+    return contentScriptsNavigatorViewInstance;
+  }
+
+
+  /**
    * @override
    * @param {!Workspace.Workspace.Project} project
    * @return {boolean}