y.CookieBannerL10n.formatMessages([
      { id: "cookie-banner-handled-webconsole" },
    ]);

    if (!this.manager?.innerWindowId) {
      return;
    }
    consoleMsg.initWithWindowID(
      message.value,
      this.manager.documentURI?.spec,
      0,
      0,
      Ci.nsIScriptError.warningFlag,
      "cookiebannerhandling",
      this.manager?.innerWindowId
    );
    Services.console.logMessage(consoleMsg);
  }

  async receiveMessage(message) {
    if (message.name == "CookieBanner::Test-FinishClicking") {
      Services.obs.notifyObservers(
        null,
        "cookie-banner-test-clicking-finish",
        this.manager.documentPrincipal?.baseDomain
      );
      return undefined;
    }

    // Forwards cookie banner detected signals to frontend consumers.
    if (message.name == "CookieBanner::DetectedBanner") {
      this.#notifyCookieBannerState("cookiebannerdetected");
      return undefined;
    }

    // Forwards cookie banner handled signals to frontend consumers.
    if (message.name == "CookieBanner::HandledBanner") {
      this.#notifyCookieBannerState("cookiebannerhandled");
      this.#logCookieBannerHandledToWebConsole();
      return undefined;
    }

    let domain = this.manager.documentPrincipal?.baseDomain;

    if (message.name == "CookieBanner::MarkSiteExecuted") {
      if (!domain) {
        return undefined;
      }

      Services.cookieBanners.markSiteExecuted(
        domain,
        this.#isTopLevel,
        this.#isPrivateBrowsing
      );
      return undefined;
    }

    if (message.name != "CookieBanner::GetClickRules") {
      return undefined;
    }

    // TODO: Bug 1790688: consider moving this logic to the cookie banner service.
    let mode;
    if (this.#isPrivateBrowsing) {
      mode = lazy.serviceModePBM;
    } else {
      mode = lazy.serviceMode;
    }

    // Check if we have a site preference of the top-level URI. If so, it
    // takes precedence over the pref setting.
    let topBrowsingContext = this.manager.browsingContext.top;
    let topURI = topBrowsingContext.currentWindowGlobal?.documentURI;

    // We don't need to check the domain preference if the cookie banner
    // handling was disabled by pref.
    if (mode != Ci.nsICookieBannerService.MODE_DISABLED && topURI) {
      try {
        let perDomainMode = Services.cookieBanners.getDomainPref(
          topURI,
          this.#isPrivateBrowsing
        );

        if (perDomainMode != Ci.nsICookieBannerService.MODE_UNSET) {
          mode = perDomainMode;
        }
      } catch (e) {
        // getPerSitePref could throw with NS_ERROR_NOT_AVAILABLE if the service
        // is disabled. We will fallback to global pref setting if any errors
        // occur.
        if (e.result == Cr.NS_ERROR_NOT_AVAILABLE) {
          console.error("The cookie banner handling service is not available");
        } else {
          console.error("Fail on getting domain pref:", e);
        }
      }
    }

    // Check if we previously executed banner clicking for the site. If the pref
    // instructs to always execute banner clicking, we will set it to
    // false.
    let hasExecuted = false;
    if (lazy.maxTriesPerSiteAndSession > 0) {
      hasExecuted = Services.cookieBanners.shouldStopBannerClickingForSite(
        domain,
        this.#isTopLevel,
        this.#isPrivateBrowsing
      );
    }

    // If we have previously executed banner clicking or the service is disabled
    // for current context (normal or private browsing), return empty array.
    if (hasExecuted || mode == Ci.nsICookieBannerService.MODE_DISABLED) {
      return { rules: [], hasExecuted };
    }

    if (!domain) {
      return { rules: [], hasExecuted };
    }

    let rules = Services.cookieBanners.getClickRulesForDomain(
      domain,
      this.#isTopLevel
    );

    if (!rules.length) {
      return { rules: [], hasExecuted };
    }

    // Determine whether we can fall back to opt-in rules. This includes the
    // detect-only mode where don't interact with the banner.
    let modeAllowsOptIn =
      mode == Ci.nsICookieBannerService.MODE_REJECT_OR_ACCEPT;

    rules = rules.map(rule => {
      let target = rule.optOut;

      if (modeAllowsOptIn && !target) {
        target = rule.optIn;
      }
      return {
        hide: rule.hide ?? rule.presence,
        presence: rule.presence,
        skipPresenceVisibilityCheck: rule.skipPresenceVisibilityCheck,
        target,
      };
    });

    return { rules, hasExecuted };
  }
}
PK