Eine aufbereitete Darstellung der Quelle

 
     
 
 
Anforderungen  |   Konzepte  |   Entwurf  |   Entwicklung  |   Qualitätssicherung  |   Lebenszyklus  |   Steuerung
 
 
 
 

Benutzer

Quelle  test_Navigate.js

  Sprache: JAVA
 

/* This Source Code Form is subject to the terms of the Mozilla Public
 * License, v. 2.0. If a copy of the MPL was not distributed with this file,
 * You can obtain one at http://mozilla.org/MPL/2.0/. */


let { EventEmitter } = ChromeUtils.importESModule(
  "resource://gre/modules/EventEmitter.sys.mjs"
);
const { setTimeout } = ChromeUtils.importESModule(
  "resource://gre/modules/Timer.sys.mjs"
);

const {
  DEFAULT_UNLOAD_TIMEOUT,
  getUnloadTimeoutMultiplier,
  ProgressListener,
  waitForInitialNavigationCompleted,
} = ChromeUtils.importESModule(
  "chrome://remote/content/shared/Navigate.sys.mjs"
);

const { isInitialDocument, isUncommittedInitialDocument } =
  ChromeUtils.importESModule(
    "chrome://remote/content/shared/BrowsingContextUtils.sys.mjs"
  );

const LOAD_FLAG_ERROR_PAGE = 0x10000;

const CURRENT_URI = Services.io.newURI("http://foo.bar/");
const INITIAL_URI = Services.io.newURI("about:blank");
const TARGET_URI = Services.io.newURI("http://foo.cheese/");
const TARGET_URI_ERROR_PAGE = Services.io.newURI("doesnotexist://");
const TARGET_URI_WITH_HASH = Services.io.newURI("http://foo.cheese/#foo");
const TARGET_URI_FROM_NAVIGATION_COMMITTED = Services.io.newURI(
  "http://foo.cheese/#bar"
);

function wait(time) {
  // eslint-disable-next-line mozilla/no-arbitrary-setTimeout
  return new Promise(resolve => setTimeout(resolve, time));
}

class MockRequest {
  constructor(uri) {
    this.originalURI = uri;
  }

  QueryInterface = ChromeUtils.generateQI(["nsIRequest""nsIChannel"]);
}

class MockWebProgress {
  constructor(browsingContext) {
    this.browsingContext = browsingContext;

    this.documentRequest = null;
    this.isLoadingDocument = false;
    this.listener = null;
    this.loadType = 0;
    this.progressListenerRemoved = false;
  }

  addProgressListener(listener) {
    if (this.listener) {
      throw new Error("Cannot register listener twice");
    }

    this.listener = listener;
  }

  removeProgressListener(listener) {
    if (listener === this.listener) {
      this.listener = null;
      this.progressListenerRemoved = true;
    } else {
      throw new Error("Unknown listener");
    }
  }

  sendLocationChange(options = {}) {
    const { flag = 0 } = options;

    this.documentRequest = null;

    if (flag & Ci.nsIWebProgressListener.LOCATION_CHANGE_SAME_DOCUMENT) {
      this.browsingContext.updateURI(TARGET_URI_WITH_HASH);
    } else if (flag & Ci.nsIWebProgressListener.LOCATION_CHANGE_ERROR_PAGE) {
      this.browsingContext.updateURI(TARGET_URI_ERROR_PAGE, true);
    }

    this.listener?.onLocationChange(
      this,
      this.documentRequest,
      this.browsingContext.currentURI,
      flag
    );

    return new Promise(executeSoon);
  }

  sendStartState(options = {}) {
    const { coop = false, isInitial = false } = options;

    if (coop) {
      this.browsingContext = new MockTopContext(this);
    }

    if (!this.browsingContext.currentWindowGlobal) {
      this.browsingContext.currentWindowGlobal = {};
    }

    this.browsingContext.currentWindowGlobal.isInitialDocument = isInitial;
    // Start is sent for the initial about:blank if and only if we commit to it
    this.browsingContext.currentWindowGlobal.isUncommittedInitialDocument = false;

    this.isLoadingDocument = true;
    this.loadType = 0;
    const uri = isInitial ? INITIAL_URI : TARGET_URI;
    this.documentRequest = new MockRequest(uri);

    this.listener?.onStateChange(
      this,
      this.documentRequest,
      Ci.nsIWebProgressListener.STATE_START,
      0
    );

    return new Promise(executeSoon);
  }

  sendStopState(options = {}) {
    const { flag = 0, loadType = 0 } = options;

    this.browsingContext.currentURI = this.documentRequest.originalURI;

    this.isLoadingDocument = false;
    this.documentRequest = null;

    if (loadType & LOAD_FLAG_ERROR_PAGE) {
      // loadType must be set before sending the stop state.
      this.loadType = 0x10000;
    }

    this.listener?.onStateChange(
      this,
      this.documentRequest,
      Ci.nsIWebProgressListener.STATE_STOP,
      flag
    );

    if (loadType & LOAD_FLAG_ERROR_PAGE) {
      return this.sendLocationChange({
        flag: Ci.nsIWebProgressListener.LOCATION_CHANGE_ERROR_PAGE,
      });
    }

    return new Promise(executeSoon);
  }
}

class MockTopContext {
  constructor(webProgress = null) {
    this.currentURI = CURRENT_URI;
    this.currentWindowGlobal = {
      isInitialDocument: true,
      isUncommittedInitialDocument: true,
      documentURI: CURRENT_URI,
    };
    this.id = 7;
    this.top = this;
    this.webProgress = webProgress || new MockWebProgress(this);
  }

  updateURI(uri, isError = false) {
    this.currentURI = uri;
    if (isError) {
      this.currentWindowGlobal.documentURI = "about:neterror?e=errorMessage";
    } else {
      this.currentWindowGlobal.documentURI = uri;
    }
  }
}

add_task(
  async function test_waitForInitialNavigation_initialDocumentNoWindowGlobal() {
    const browsingContext = new MockTopContext();
    const webProgress = browsingContext.webProgress;

    // In some cases there might be no window global yet.
    delete browsingContext.currentWindowGlobal;

    ok(!webProgress.isLoadingDocument, "Document is not loading");

    // without window global, we'll wait for start and stop
    const navigated = waitForInitialNavigationCompleted(webProgress);
    await webProgress.sendStartState({ isInitial: true });

    ok(
      !(await hasPromiseResolved(navigated)),
      "waitForInitialNavigationCompleted has not resolved yet"
    );

    await webProgress.sendStopState();
    const { currentURI, targetURI } = await navigated;

    ok(!webProgress.isLoadingDocument, "Document is not loading");
    ok(
      webProgress.browsingContext.currentWindowGlobal.isInitialDocument,
      "Is initial document"
    );
    equal(
      currentURI.spec,
      INITIAL_URI.spec,
      "Expected current URI has been set"
    );
    equal(targetURI.spec, INITIAL_URI.spec, "Expected target URI has been set");
  }
);

add_task(
  async function test_waitForInitialNavigation_initialDocumentNotLoaded() {
    const browsingContext = new MockTopContext();
    const webProgress = browsingContext.webProgress;

    ok(!webProgress.isLoadingDocument, "Document is not loading");
    ok(
      isUncommittedInitialDocument(webProgress.browsingContext),
      "Document is uncommitted initial"
    );

    // for uncommitted initial, we'll wait for start and stop
    const navigated = waitForInitialNavigationCompleted(webProgress);

    await webProgress.sendStartState({ isInitial: true });

    ok(
      !(await hasPromiseResolved(navigated)),
      "waitForInitialNavigationCompleted has not resolved yet"
    );

    await webProgress.sendStopState();
    const { currentURI, targetURI } = await navigated;

    ok(!webProgress.isLoadingDocument, "Document is not loading");
    ok(
      webProgress.browsingContext.currentWindowGlobal.isInitialDocument,
      "Is initial document"
    );
    equal(
      currentURI.spec,
      INITIAL_URI.spec,
      "Expected current URI has been set"
    );
    equal(targetURI.spec, INITIAL_URI.spec, "Expected target URI has been set");
  }
);

add_task(
  async function test_waitForInitialNavigation_initialDocumentLoadingAndNoAdditionalLoad() {
    const browsingContext = new MockTopContext();
    const webProgress = browsingContext.webProgress;

    await webProgress.sendStartState({ isInitial: true });
    ok(webProgress.isLoadingDocument, "Document is loading");

    const navigated = waitForInitialNavigationCompleted(webProgress);

    ok(
      !(await hasPromiseResolved(navigated)),
      "waitForInitialNavigationCompleted has not resolved yet"
    );

    await webProgress.sendStopState();
    const { currentURI, targetURI } = await navigated;

    ok(!webProgress.isLoadingDocument, "Document is not loading");
    ok(
      webProgress.browsingContext.currentWindowGlobal.isInitialDocument,
      "Is initial document"
    );
    equal(
      currentURI.spec,
      INITIAL_URI.spec,
      "Expected current URI has been set"
    );
    equal(targetURI.spec, INITIAL_URI.spec, "Expected target URI has been set");
  }
);

add_task(
  async function test_waitForInitialNavigation_initialDocumentFinishedLoadingNoAdditionalLoad() {
    const browsingContext = new MockTopContext();
    const webProgress = browsingContext.webProgress;

    await webProgress.sendStartState({ isInitial: true });
    await webProgress.sendStopState();

    ok(!webProgress.isLoadingDocument, "Document is not loading");
    ok(isInitialDocument(webProgress.browsingContext), "Document is initial");
    ok(
      !isUncommittedInitialDocument(webProgress.browsingContext),
      "Document is uncommitted"
    );

    const navigated = waitForInitialNavigationCompleted(webProgress);

    ok(
      await hasPromiseResolved(navigated),
      "waitForInitialNavigationCompleted resolves immediately"
    );

    const { currentURI, targetURI } = await navigated;

    ok(!webProgress.isLoadingDocument, "Document is not loading");
    ok(
      webProgress.browsingContext.currentWindowGlobal.isInitialDocument,
      "Is initial document"
    );
    equal(
      currentURI.spec,
      INITIAL_URI.spec,
      "Expected current URI has been set"
    );
    equal(targetURI.spec, INITIAL_URI.spec, "Expected target URI has been set");
  }
);

add_task(
  async function test_waitForInitialNavigation_notInitialDocumentNotLoading() {
    const browsingContext = new MockTopContext();
    const webProgress = browsingContext.webProgress;

    ok(!webProgress.isLoadingDocument, "Document is not loading");

    const navigated = waitForInitialNavigationCompleted(webProgress);
    await webProgress.sendStartState({ isInitial: false });

    ok(
      !(await hasPromiseResolved(navigated)),
      "waitForInitialNavigationCompleted has not resolved yet"
    );

    await webProgress.sendStopState();
    const { currentURI, targetURI } = await navigated;

    ok(!webProgress.isLoadingDocument, "Document is not loading");
    ok(
      !browsingContext.currentWindowGlobal.isInitialDocument,
      "Is not initial document"
    );
    equal(
      currentURI.spec,
      TARGET_URI.spec,
      "Expected current URI has been set"
    );
    equal(targetURI.spec, TARGET_URI.spec, "Expected target URI has been set");
  }
);

add_task(
  async function test_waitForInitialNavigation_notInitialDocumentAlreadyLoading() {
    const browsingContext = new MockTopContext();
    const webProgress = browsingContext.webProgress;

    await webProgress.sendStartState({ isInitial: false });
    ok(webProgress.isLoadingDocument, "Document is loading");

    const navigated = waitForInitialNavigationCompleted(webProgress);

    ok(
      !(await hasPromiseResolved(navigated)),
      "waitForInitialNavigationCompleted has not resolved yet"
    );

    await webProgress.sendStopState();
    const { currentURI, targetURI } = await navigated;

    ok(!webProgress.isLoadingDocument, "Document is not loading");
    ok(
      !browsingContext.currentWindowGlobal.isInitialDocument,
      "Is not initial document"
    );
    equal(
      currentURI.spec,
      TARGET_URI.spec,
      "Expected current URI has been set"
    );
    equal(targetURI.spec, TARGET_URI.spec, "Expected target URI has been set");
  }
);

add_task(
  async function test_waitForInitialNavigation_notInitialDocumentFinishedLoading() {
    const browsingContext = new MockTopContext();
    const webProgress = browsingContext.webProgress;

    await webProgress.sendStartState({ isInitial: false });
    await webProgress.sendStopState();

    ok(!webProgress.isLoadingDocument, "Document is not loading");

    const { currentURI, targetURI } =
      await waitForInitialNavigationCompleted(webProgress);

    ok(!webProgress.isLoadingDocument, "Document is not loading");
    ok(
      !webProgress.browsingContext.currentWindowGlobal.isInitialDocument,
      "Is not initial document"
    );
    equal(
      currentURI.spec,
      TARGET_URI.spec,
      "Expected current URI has been set"
    );
    equal(targetURI.spec, TARGET_URI.spec, "Expected target URI has been set");
  }
);

add_task(async function test_waitForInitialNavigation_resolveWhenStarted() {
  const browsingContext = new MockTopContext();
  const webProgress = browsingContext.webProgress;

  await webProgress.sendStartState({ isInitial: true });
  ok(webProgress.isLoadingDocument, "Document is already loading");

  const { currentURI, targetURI } = await waitForInitialNavigationCompleted(
    webProgress,
    {
      resolveWhenStarted: true,
    }
  );

  ok(webProgress.isLoadingDocument, "Document is still loading");
  ok(
    webProgress.browsingContext.currentWindowGlobal.isInitialDocument,
    "Is initial document"
  );
  equal(currentURI.spec, CURRENT_URI.spec, "Expected current URI has been set");
  equal(targetURI.spec, INITIAL_URI.spec, "Expected target URI has been set");
});

add_task(async function test_waitForInitialNavigation_crossOrigin() {
  const browsingContext = new MockTopContext();
  const webProgress = browsingContext.webProgress;

  ok(!webProgress.isLoadingDocument, "Document is not loading");

  const navigated = waitForInitialNavigationCompleted(webProgress);
  await webProgress.sendStartState({ coop: true });

  ok(
    !(await hasPromiseResolved(navigated)),
    "waitForInitialNavigationCompleted has not resolved yet"
  );

  await webProgress.sendStopState();
  const { currentURI, targetURI } = await navigated;

  notEqual(
    browsingContext,
    webProgress.browsingContext,
    "Got new browsing context"
  );
  ok(!webProgress.isLoadingDocument, "Document is not loading");
  ok(
    !webProgress.browsingContext.currentWindowGlobal.isInitialDocument,
    "Is not initial document"
  );
  equal(currentURI.spec, TARGET_URI.spec, "Expected current URI has been set");
  equal(targetURI.spec, TARGET_URI.spec, "Expected target URI has been set");
});

add_task(async function test_waitForInitialNavigation_unloadTimeout_default() {
  const browsingContext = new MockTopContext();
  const webProgress = browsingContext.webProgress;

  // Document starts out as uncommitted initial and not loading
  ok(!webProgress.isLoadingDocument, "Document is not loading");

  const navigated = waitForInitialNavigationCompleted(webProgress);

  // Start a timer longer than the timeout which will be used by
  // waitForInitialNavigationCompleted, and check that navigated resolves first.
  const waitForMoreThanDefaultTimeout = wait(
    DEFAULT_UNLOAD_TIMEOUT * 1.5 * getUnloadTimeoutMultiplier()
  );
  await Promise.race([navigated, waitForMoreThanDefaultTimeout]);

  ok(
    await hasPromiseResolved(navigated),
    "waitForInitialNavigationCompleted has resolved"
  );

  ok(!webProgress.isLoadingDocument, "Document is not loading");
  ok(
    webProgress.browsingContext.currentWindowGlobal.isInitialDocument,
    "Document is still on the initial document"
  );
});

add_task(async function test_waitForInitialNavigation_unloadTimeout_longer() {
  const browsingContext = new MockTopContext();
  const webProgress = browsingContext.webProgress;

  // Document starts out as uncommitted initial and not loading
  ok(!webProgress.isLoadingDocument, "Document is not loading");

  const navigated = waitForInitialNavigationCompleted(webProgress, {
    unloadTimeout: DEFAULT_UNLOAD_TIMEOUT * 3,
  });

  // Start a timer longer than the default timeout of the Navigate module.
  // However here we used a custom timeout, so we expect that the navigation
  // will not be done yet by the time this timer is done.
  const waitForMoreThanDefaultTimeout = wait(
    DEFAULT_UNLOAD_TIMEOUT * 1.5 * getUnloadTimeoutMultiplier()
  );
  await Promise.race([navigated, waitForMoreThanDefaultTimeout]);

  // The promise should not have resolved because we didn't reached the custom
  // timeout which is 3 times the default one.
  ok(
    !(await hasPromiseResolved(navigated)),
    "waitForInitialNavigationCompleted has not resolved yet"
  );

  // The navigation should eventually resolve once we reach the custom timeout.
  await navigated;

  ok(!webProgress.isLoadingDocument, "Document is not loading");
  ok(
    webProgress.browsingContext.currentWindowGlobal.isInitialDocument,
    "Document is still on the initial document"
  );
});

add_task(async function test_ProgressListener_expectNavigation() {
  const browsingContext = new MockTopContext();
  const webProgress = browsingContext.webProgress;

  const progressListener = new ProgressListener(webProgress, {
    expectNavigation: true,
    unloadTimeout: 10,
  });
  const navigated = progressListener.start();

  // Wait for unloadTimeout to finish in case it started
  await wait(30);

  ok(!(await hasPromiseResolved(navigated)), "Listener has not resolved yet");

  await webProgress.sendStartState();
  await webProgress.sendStopState();

  ok(await hasPromiseResolved(navigated), "Listener has resolved");
});

add_task(
  async function test_ProgressListener_expectNavigation_initialDocument() {
    const browsingContext = new MockTopContext();
    const webProgress = browsingContext.webProgress;

    const progressListener = new ProgressListener(webProgress, {
      expectNavigation: true,
      unloadTimeout: 10,
    });
    const navigated = progressListener.start();

    ok(!(await hasPromiseResolved(navigated)), "Listener has not resolved yet");

    await webProgress.sendStartState({ isInitial: true });
    await webProgress.sendStopState();

    ok(await hasPromiseResolved(navigated), "Listener has resolved");
  }
);

add_task(async function test_ProgressListener_isStarted() {
  const browsingContext = new MockTopContext();
  const webProgress = browsingContext.webProgress;

  const progressListener = new ProgressListener(webProgress);
  ok(!progressListener.isStarted);

  progressListener.start();
  ok(progressListener.isStarted);

  progressListener.stop();
  ok(!progressListener.isStarted);
});

add_task(async function test_ProgressListener_notWaitForExplicitStart() {
  // Create a webprogress and start it before creating the progress listener.
  const browsingContext = new MockTopContext();
  const webProgress = browsingContext.webProgress;
  await webProgress.sendStartState();

  // Create the progress listener for a webprogress already in a navigation.
  const progressListener = new ProgressListener(webProgress, {
    waitForExplicitStart: false,
  });
  const navigated = progressListener.start();

  // Send stop state to complete the initial navigation
  await webProgress.sendStopState();
  ok(
    await hasPromiseResolved(navigated),
    "Listener has resolved after initial navigation"
  );
});

add_task(async function test_ProgressListener_waitForExplicitStart() {
  // Create a webprogress and start it before creating the progress listener.
  const browsingContext = new MockTopContext();
  const webProgress = browsingContext.webProgress;
  await webProgress.sendStartState();

  // Create the progress listener for a webprogress already in a navigation.
  const progressListener = new ProgressListener(webProgress, {
    waitForExplicitStart: true,
  });
  const navigated = progressListener.start();

  // Send stop state to complete the initial navigation
  await webProgress.sendStopState();
  ok(
    !(await hasPromiseResolved(navigated)),
    "Listener has not resolved after initial navigation"
  );

  // Start a new navigation
  await webProgress.sendStartState();
  ok(
    !(await hasPromiseResolved(navigated)),
    "Listener has not resolved after starting new navigation"
  );

  // Finish the new navigation
  await webProgress.sendStopState();
  ok(
    await hasPromiseResolved(navigated),
    "Listener resolved after finishing the new navigation"
  );
});

add_task(async function test_invalid_resolveWhenCommitted() {
  // Create a webprogress and start it before creating the progress listener.
  const browsingContext = new MockTopContext();
  const webProgress = browsingContext.webProgress;
  await webProgress.sendStartState();

  Assert.throws(
    () =>
      new ProgressListener(webProgress, {
        resolveWhenCommitted: true,
        resolveWhenStarted: true,
        navigationManager: {},
      }),
    /Cannot use both resolveWhenStarted and resolveWhenCommitted/,
    "Expected error was returned"
  );

  Assert.throws(
    () =>
      new ProgressListener(webProgress, {
        resolveWhenCommitted: true,
        navigationManager: null,
      }),
    /Cannot use resolveWhenCommitted without a navigationManager/,
    "Expected error was returned"
  );
});

class MockNavigationManager extends EventEmitter {}

add_task(async function test_ProgressListener_resolveWhenCommitted() {
  // Create a webprogress and start it before creating the progress listener.
  const browsingContext = new MockTopContext();
  const webProgress = browsingContext.webProgress;
  await webProgress.sendStartState();
  const mockNavigationManager = new MockNavigationManager();

  // Create the progress listener for a webprogress already in a navigation.
  const progressListener = new ProgressListener(webProgress, {
    resolveWhenCommitted: true,
    navigationManager: mockNavigationManager,
  });

  // Setup two navigation ids, and start the progress listener with the first
  // one.
  const navigationId1 = "navigationId1";
  const navigationId2 = "navigationId2";

  const navigated = progressListener.start(navigationId1);

  // Start a new navigation
  await webProgress.sendStartState();
  ok(
    !(await hasPromiseResolved(navigated)),
    "Listener has not resolved after navigation has only started"
  );

  // Emit an unexpected navigation-committed for the other navigation id.
  mockNavigationManager.emit("navigation-committed", {
    navigationId: navigationId2,
    url: TARGET_URI_FROM_NAVIGATION_COMMITTED.spec,
  });
  ok(
    !(await hasPromiseResolved(navigated)),
    "Listener has not resolved after an unexpected navigation-committed"
  );
  notEqual(
    progressListener.targetURI.spec,
    TARGET_URI_FROM_NAVIGATION_COMMITTED.spec,
    "Expected target URI has not been set from unexpected navigation-committed"
  );

  // Emit the expected navigation-committed event.
  mockNavigationManager.emit("navigation-committed", {
    navigationId: navigationId1,
    url: TARGET_URI_FROM_NAVIGATION_COMMITTED.spec,
  });
  ok(
    await hasPromiseResolved(navigated),
    "Listener has resolved after receiving the correct navigation-committed"
  );
  equal(
    progressListener.targetURI.spec,
    TARGET_URI_FROM_NAVIGATION_COMMITTED.spec,
    "Expected target URI has been set from navigation-committed"
  );
});

add_task(
  async function test_ProgressListener_waitForExplicitStartAndResolveWhenStarted() {
    // Create a webprogress and start it before creating the progress listener.
    const browsingContext = new MockTopContext();
    const webProgress = browsingContext.webProgress;
    await webProgress.sendStartState();

    // Create the progress listener for a webprogress already in a navigation.
    const progressListener = new ProgressListener(webProgress, {
      resolveWhenStarted: true,
      waitForExplicitStart: true,
    });
    const navigated = progressListener.start();

    // Send stop state to complete the initial navigation
    await webProgress.sendStopState();
    ok(
      !(await hasPromiseResolved(navigated)),
      "Listener has not resolved after initial navigation"
    );

    // Start a new navigation
    await webProgress.sendStartState();
    ok(
      await hasPromiseResolved(navigated),
      "Listener resolved after starting the new navigation"
    );
  }
);

add_task(
  async function test_ProgressListener_resolveWhenNavigatingInsideDocument() {
    const browsingContext = new MockTopContext();
    const webProgress = browsingContext.webProgress;

    const progressListener = new ProgressListener(webProgress);
    const navigated = progressListener.start();

    ok(!(await hasPromiseResolved(navigated)), "Listener has not resolved");

    // Send hash change location change notification to complete the navigation
    await webProgress.sendLocationChange({
      flag: Ci.nsIWebProgressListener.LOCATION_CHANGE_SAME_DOCUMENT,
    });

    ok(await hasPromiseResolved(navigated), "Listener has resolved");

    const { currentURI, targetURI } = progressListener;
    equal(
      currentURI.spec,
      TARGET_URI_WITH_HASH.spec,
      "Expected current URI has been set"
    );
    equal(
      targetURI.spec,
      TARGET_URI_WITH_HASH.spec,
      "Expected target URI has been set"
    );
  }
);

add_task(async function test_ProgressListener_ignoreCacheError() {
  const browsingContext = new MockTopContext();
  const webProgress = browsingContext.webProgress;

  const progressListener = new ProgressListener(webProgress);
  const navigated = progressListener.start();

  ok(!(await hasPromiseResolved(navigated)), "Listener has not resolved");

  await webProgress.sendStartState();
  await webProgress.sendStopState({
    flag: Cr.NS_ERROR_PARSED_DATA_CACHED,
  });

  ok(await hasPromiseResolved(navigated), "Listener has resolved");
});

add_task(async function test_ProgressListener_navigationRejectedOnErrorPage() {
  const browsingContext = new MockTopContext();
  const webProgress = browsingContext.webProgress;

  const progressListener = new ProgressListener(webProgress, {
    waitForExplicitStart: false,
  });
  const navigated = progressListener.start();

  await webProgress.sendStartState();
  await webProgress.sendLocationChange({
    flag:
      Ci.nsIWebProgressListener.LOCATION_CHANGE_SAME_DOCUMENT |
      Ci.nsIWebProgressListener.LOCATION_CHANGE_ERROR_PAGE,
  });

  ok(
    await hasPromiseRejected(navigated),
    "Listener has rejected in location change for error page"
  );
});

add_task(
  async function test_ProgressListener_navigationRejectedOnStopStateErrorPage() {
    const browsingContext = new MockTopContext();
    const webProgress = browsingContext.webProgress;

    const progressListener = new ProgressListener(webProgress, {
      waitForExplicitStart: false,
    });
    const navigated = progressListener.start();

    await webProgress.sendStartState();
    await webProgress.sendStopState({
      flag: Cr.NS_ERROR_MALWARE_URI,
      loadType: LOAD_FLAG_ERROR_PAGE,
    });

    ok(
      await hasPromiseRejected(navigated),
      "Listener has rejected in stop state for erroneous navigation"
    );
  }
);

add_task(
  async function test_ProgressListener_navigationRejectedOnStopStateAndAborted() {
    const browsingContext = new MockTopContext();
    const webProgress = browsingContext.webProgress;

    for (const flag of [Cr.NS_BINDING_ABORTED, Cr.NS_ERROR_ABORT]) {
      const progressListener = new ProgressListener(webProgress, {
        waitForExplicitStart: false,
      });
      const navigated = progressListener.start();

      await webProgress.sendStartState();
      await webProgress.sendStopState({ flag });

      ok(
        await hasPromiseRejected(navigated),
        "Listener has rejected in stop state for erroneous navigation"
      );
    }
  }
);

add_task(
  async function test_ProgressListener_navigationRejectedWaitsForNavigationCommitted() {
    const browsingContext = new MockTopContext();
    const webProgress = browsingContext.webProgress;
    const mockNavigationManager = new MockNavigationManager();

    const progressListener = new ProgressListener(webProgress, {
      navigationManager: mockNavigationManager,
    });

    const navigationId = "navigationId1";
    const navigated = progressListener.start(navigationId);

    await webProgress.sendStartState();

    // Emit a first navigation-committed before the location change
    mockNavigationManager.emit("navigation-committed", {
      navigationId,
      url: TARGET_URI.spec,
    });

    await webProgress.sendStopState({
      flag: Cr.NS_ERROR_MALWARE_URI,
      loadType: LOAD_FLAG_ERROR_PAGE,
    });

    ok(
      !(await hasPromiseRejected(navigated)),
      "Listener waiting for navigation-committed event before rejecting"
    );

    mockNavigationManager.emit("navigation-committed", {
      navigationId,
      url: TARGET_URI_ERROR_PAGE.spec,
    });

    ok(
      await hasPromiseRejected(navigated),
      "Listener rejected after receiving navigation-committed for error page"
    );
  }
);

add_task(async function test_ProgressListener_stopIfStarted() {
  const browsingContext = new MockTopContext();
  const webProgress = browsingContext.webProgress;

  const progressListener = new ProgressListener(webProgress);
  const navigated = progressListener.start();

  progressListener.stopIfStarted();
  ok(!(await hasPromiseResolved(navigated)), "Listener has not resolved");

  await webProgress.sendStartState();
  progressListener.stopIfStarted();
  ok(await hasPromiseResolved(navigated), "Listener has resolved");
});

add_task(async function test_ProgressListener_stopIfStarted_alreadyStarted() {
  // Create an already navigating browsing context.
  const browsingContext = new MockTopContext();
  const webProgress = browsingContext.webProgress;
  await webProgress.sendStartState();

  // Create a progress listener which accepts already ongoing navigations.
  const progressListener = new ProgressListener(webProgress, {
    waitForExplicitStart: false,
  });
  const navigated = progressListener.start();

  // stopIfStarted should stop the listener because of the ongoing navigation.
  progressListener.stopIfStarted();
  ok(await hasPromiseResolved(navigated), "Listener has resolved");
});

add_task(
  async function test_ProgressListener_stopIfStarted_alreadyStarted_waitForExplicitStart() {
    // Create an already navigating browsing context.
    const browsingContext = new MockTopContext();
    const webProgress = browsingContext.webProgress;
    await webProgress.sendStartState();

    // Create a progress listener which rejects already ongoing navigations.
    const progressListener = new ProgressListener(webProgress, {
      waitForExplicitStart: true,
    });
    const navigated = progressListener.start();

    // stopIfStarted will not stop the listener for the existing navigation.
    progressListener.stopIfStarted();
    ok(!(await hasPromiseResolved(navigated)), "Listener has not resolved");

    // stopIfStarted will stop the listener when called after starting a new
    // navigation.
    await webProgress.sendStartState();
    progressListener.stopIfStarted();
    ok(await hasPromiseResolved(navigated), "Listener has resolved");
  }
);

Messung V0.5 in Prozent
C=82 H=95 G=88

¤ Dauer der Verarbeitung: 0.18 Sekunden  (vorverarbeitet am  2026-08-26) ¤

*© Formatika GbR, Deutschland






Wurzel

Suchen

PVS Prover

Isabelle Prover

NIST Cobol Testsuite

Cephes Mathematical Library

Vienna Development Method

Haftungshinweis

Die Informationen auf dieser Webseite wurden nach bestem Wissen sorgfältig zusammengestellt. Es wird jedoch weder Vollständigkeit, noch Richtigkeit, noch Qualität der bereit gestellten Informationen zugesichert.

Bemerkung:

Die farbliche Syntaxdarstellung und die Messung sind noch experimentell.






                                                                                                                                                                                                                                                                                                                                                                                                     


Neuigkeiten

     Aktuelles
     Motto des Tages

Open Source Software

     Quellcodebibliothek
     Eigene Quellcodes
     Fremde Quellcodes
     Suchen

Jenseits des Üblichen ....

Besucherstatistik

Besucherstatistik

Statistik
#Sources=277311
#Domains=752002