UNPKG

chrome-devtools-frontend

Version:
260 lines (238 loc) • 11.7 kB
// Copyright 2022 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 Protocol from '../../generated/protocol.js'; import { createTarget, } from '../../testing/EnvironmentHelpers.js'; import { describeWithMockConnection, } from '../../testing/MockConnection.js'; import * as SDK from './sdk.js'; const TARGET_ID = 'TARGET_ID' as Protocol.Target.TargetID; const TITLE = 'TITLE'; let nextTargetId = 0; function createTargetInfo(targetId?: string, type?: string, url?: string, title?: string) { return { targetId: (targetId ?? String(++nextTargetId)) as Protocol.Target.TargetID, type: type ?? 'page', title: title ?? '', url: url ?? 'http://example.com', attached: true, canAccessOpener: true, }; } let nextSessionId = 0; function createSessionId() { return ('SESSION_ID' + ++nextSessionId) as Protocol.Target.SessionID; } describeWithMockConnection('ChildTargetManager', () => { it('adds subtargets', async () => { const target = createTarget(); const childTargetManager = new SDK.ChildTargetManager.ChildTargetManager(target); assert.lengthOf(childTargetManager.childTargets(), 0); await childTargetManager.attachedToTarget( {sessionId: createSessionId(), targetInfo: createTargetInfo(TARGET_ID), waitingForDebugger: false}); assert.lengthOf(childTargetManager.childTargets(), 1); assert.strictEqual(childTargetManager.childTargets()[0].id(), TARGET_ID); }); it('sets subtarget type', async () => { const target = createTarget(); const childTargetManager = new SDK.ChildTargetManager.ChildTargetManager(target); assert.lengthOf(childTargetManager.childTargets(), 0); for (const [protocolType, sdkType] of [ ['iframe', SDK.Target.Type.FRAME], ['webview', SDK.Target.Type.FRAME], ['page', SDK.Target.Type.FRAME], ['background_page', SDK.Target.Type.FRAME], ['app', SDK.Target.Type.FRAME], ['popup_page', SDK.Target.Type.FRAME], ['worker', SDK.Target.Type.Worker], ['shared_worker', SDK.Target.Type.SHARED_WORKER], ['service_worker', SDK.Target.Type.ServiceWorker], ['auction_worklet', SDK.Target.Type.AUCTION_WORKLET], ['browser', SDK.Target.Type.BROWSER], ]) { await childTargetManager.attachedToTarget({ sessionId: createSessionId(), targetInfo: createTargetInfo(undefined, protocolType), waitingForDebugger: false, }); const [subtarget] = childTargetManager.childTargets().slice(-1); assert.strictEqual(subtarget.type(), sdkType); } }); it('sets subtarget to frame for devtools scheme if type is other', async () => { const target = createTarget(); const childTargetManager = new SDK.ChildTargetManager.ChildTargetManager(target); assert.lengthOf(childTargetManager.childTargets(), 0); await childTargetManager.attachedToTarget({ sessionId: createSessionId(), targetInfo: createTargetInfo(undefined, 'other', 'devtools://foo/bar'), waitingForDebugger: false, }); let [subtarget] = childTargetManager.childTargets().slice(-1); assert.strictEqual(subtarget.type(), SDK.Target.Type.FRAME); await childTargetManager.attachedToTarget({ sessionId: createSessionId(), targetInfo: createTargetInfo(undefined, 'worker', 'devtools://foo/bar'), waitingForDebugger: false, }); [subtarget] = childTargetManager.childTargets().slice(-1); assert.strictEqual(subtarget.type(), SDK.Target.Type.Worker); }); it('sets subtarget to frame for chrome://print/ if type is other', async () => { const target = createTarget(); const childTargetManager = new SDK.ChildTargetManager.ChildTargetManager(target); assert.lengthOf(childTargetManager.childTargets(), 0); await childTargetManager.attachedToTarget({ sessionId: createSessionId(), targetInfo: createTargetInfo(undefined, 'other', 'chrome://print/'), waitingForDebugger: false, }); const [subtarget] = childTargetManager.childTargets().slice(-1); assert.strictEqual(subtarget.type(), SDK.Target.Type.FRAME); }); it('sets subtarget to frame for chrome://file-manager/ if type is other', async () => { const target = createTarget(); const childTargetManager = new SDK.ChildTargetManager.ChildTargetManager(target); assert.lengthOf(childTargetManager.childTargets(), 0); await childTargetManager.attachedToTarget({ sessionId: createSessionId(), targetInfo: createTargetInfo(undefined, 'other', 'chrome://file-manager/?%7B%22allowedPaths%22:%22anyPathOrUrl'), waitingForDebugger: false, }); const [subtarget] = childTargetManager.childTargets().slice(-1); assert.strictEqual(subtarget.type(), SDK.Target.Type.FRAME); }); it('sets subtarget to frame for sidebar URLs if type is other', async () => { const target = createTarget(); const childTargetManager = new SDK.ChildTargetManager.ChildTargetManager(target); assert.lengthOf(childTargetManager.childTargets(), 0); await childTargetManager.attachedToTarget({ sessionId: createSessionId(), targetInfo: createTargetInfo(undefined, 'other', 'chrome://read-later.top-chrome/'), waitingForDebugger: false, }); let [subtarget] = childTargetManager.childTargets().slice(-1); assert.strictEqual(subtarget.type(), SDK.Target.Type.FRAME); await childTargetManager.attachedToTarget({ sessionId: createSessionId(), targetInfo: createTargetInfo(undefined, 'other', 'chrome://booksmarks-side-panel.top-chrome/'), waitingForDebugger: false, }); [subtarget] = childTargetManager.childTargets().slice(-1); assert.strictEqual(subtarget.type(), SDK.Target.Type.FRAME); }); it('sets worker target name to the target title', async () => { const target = createTarget(); const childTargetManager = new SDK.ChildTargetManager.ChildTargetManager(target); assert.lengthOf(childTargetManager.childTargets(), 0); await childTargetManager.attachedToTarget({ sessionId: createSessionId(), targetInfo: createTargetInfo(undefined, 'worker', 'http://example.com/worker.js', TITLE), waitingForDebugger: false, }); assert.strictEqual(childTargetManager.childTargets()[0].name(), TITLE); }); it('sets non-frame target name to the last path component if present', async () => { const target = createTarget(); const childTargetManager = new SDK.ChildTargetManager.ChildTargetManager(target); assert.lengthOf(childTargetManager.childTargets(), 0); await childTargetManager.attachedToTarget({ sessionId: createSessionId(), targetInfo: createTargetInfo(undefined, 'service_worker', 'http://example.org/service_worker.html', TITLE), waitingForDebugger: false, }); await childTargetManager.attachedToTarget({ sessionId: createSessionId(), targetInfo: createTargetInfo(undefined, 'worker', 'http://example.com/worker.js'), waitingForDebugger: false, }); assert.strictEqual(childTargetManager.childTargets()[0].name(), 'service_worker.html'); assert.strictEqual(childTargetManager.childTargets()[1].name(), 'worker.js'); }); it('sets non-frame target a numbered name if it cannot use URL path', async () => { const target = createTarget(); const childTargetManager = new SDK.ChildTargetManager.ChildTargetManager(target); assert.lengthOf(childTargetManager.childTargets(), 0); await childTargetManager.attachedToTarget({ sessionId: createSessionId(), targetInfo: createTargetInfo(undefined, 'page', 'data:text/html,<!doctype html>'), waitingForDebugger: false, }); await childTargetManager.attachedToTarget({ sessionId: createSessionId(), targetInfo: createTargetInfo(undefined, 'iframe', 'data:text/html,<!doctype html>'), waitingForDebugger: false, }); await childTargetManager.attachedToTarget({ sessionId: createSessionId(), targetInfo: createTargetInfo(undefined, 'webview', 'data:text/html,<!doctype html>'), waitingForDebugger: false, }); // The targets above are frames and should not be given a numbered named await childTargetManager.attachedToTarget({ sessionId: createSessionId(), targetInfo: createTargetInfo(undefined, 'service_worker', 'data:application/javascript;console.log("Service Worker")'), waitingForDebugger: false, }); await childTargetManager.attachedToTarget({ sessionId: createSessionId(), targetInfo: createTargetInfo(undefined, 'worker', 'data:application/javascript;console.log("Worker")'), waitingForDebugger: false, }); assert.strictEqual(childTargetManager.childTargets()[3].name(), '#1'); assert.strictEqual(childTargetManager.childTargets()[4].name(), '#2'); }); it('calls attach callback', async () => { const target = createTarget(); const childTargetManager = new SDK.ChildTargetManager.ChildTargetManager(target); const attachCallback = sinon.spy(); SDK.ChildTargetManager.ChildTargetManager.install(attachCallback); await childTargetManager.attachedToTarget( {sessionId: createSessionId(), targetInfo: createTargetInfo(TARGET_ID), waitingForDebugger: false}); assert.isTrue(attachCallback.calledOnce); assert.strictEqual(attachCallback.firstCall.firstArg.target.id(), TARGET_ID); assert.isFalse(attachCallback.firstCall.firstArg.waitingForDebugger); const OTHER_TARGET_ID = 'OTHER_TARGET_ID' as Protocol.Target.TargetID; await childTargetManager.attachedToTarget( {sessionId: createSessionId(), targetInfo: createTargetInfo(OTHER_TARGET_ID), waitingForDebugger: true}); assert.isTrue(attachCallback.calledTwice); assert.strictEqual(attachCallback.secondCall.firstArg.target.id(), OTHER_TARGET_ID); assert.isTrue(attachCallback.secondCall.firstArg.waitingForDebugger); }); it('marks the target as crashed when it crashes', async () => { const parentTarget = createTarget(); const childTargetManager = new SDK.ChildTargetManager.ChildTargetManager(parentTarget); await childTargetManager.attachedToTarget({ sessionId: createSessionId(), targetInfo: createTargetInfo('child-target-id'), waitingForDebugger: false, }); const target = childTargetManager.childTargets().at(0); assert.isDefined(target); assert.strictEqual(target.id(), 'child-target-id'); childTargetManager.targetCrashed( {targetId: target.id() as Protocol.Target.TargetID, status: 'crashed', errorCode: 1}); assert.isTrue(target.hasCrashed()); }); it('"un-crashes" a target when the target info message is received', async () => { const parentTarget = createTarget(); const childTargetManager = new SDK.ChildTargetManager.ChildTargetManager(parentTarget); await childTargetManager.attachedToTarget({ sessionId: createSessionId(), targetInfo: createTargetInfo('child-target-id'), waitingForDebugger: false, }); const target = childTargetManager.childTargets().at(0); assert.isDefined(target); assert.strictEqual(target.id(), 'child-target-id'); childTargetManager.targetCrashed( {targetId: target.id() as Protocol.Target.TargetID, status: 'crashed', errorCode: 1}); assert.isTrue(target.hasCrashed()); childTargetManager.targetInfoChanged({targetInfo: createTargetInfo(target.id())}); assert.isFalse(target.hasCrashed()); }); });