"use strict";

Object.defineProperty(exports, "__esModule", {
  value: true
});
exports.BrowserContextDispatcher = void 0;

var _browserContext = require("../server/browserContext");

var _dispatcher = require("./dispatcher");

var _pageDispatcher = require("./pageDispatcher");

var _fetch = require("../server/fetch");

var _networkDispatchers = require("./networkDispatchers");

var _crBrowser = require("../server/chromium/crBrowser");

var _cdpSessionDispatcher = require("./cdpSessionDispatcher");

var _recorderSupplement = require("../server/supplements/recorderSupplement");

var _artifactDispatcher = require("./artifactDispatcher");

var _utils = require("../utils/utils");

/**
 * Copyright (c) Microsoft Corporation.
 *
 * Licensed under the Apache License, Version 2.0 (the 'License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 * http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */
class BrowserContextDispatcher extends _dispatcher.Dispatcher {
  constructor(scope, context) {
    super(scope, context, 'BrowserContext', {
      isChromium: context._browser.options.isChromium
    }, true);
    this._context = void 0;
    this._context = context; // Note: when launching persistent context, dispatcher is created very late,
    // so we can already have pages, videos and everything else.

    const onVideo = artifact => {
      // Note: Video must outlive Page and BrowserContext, so that client can saveAs it
      // after closing the context. We use |scope| for it.
      const artifactDispatcher = new _artifactDispatcher.ArtifactDispatcher(scope, artifact);

      this._dispatchEvent('video', {
        artifact: artifactDispatcher
      });
    };

    context.on(_browserContext.BrowserContext.Events.VideoStarted, onVideo);

    for (const video of context._browser._idToVideo.values()) {
      if (video.context === context) onVideo(video.artifact);
    }

    for (const page of context.pages()) this._dispatchEvent('page', {
      page: new _pageDispatcher.PageDispatcher(this._scope, page)
    });

    context.on(_browserContext.BrowserContext.Events.Page, page => this._dispatchEvent('page', {
      page: new _pageDispatcher.PageDispatcher(this._scope, page)
    }));
    context.on(_browserContext.BrowserContext.Events.Close, () => {
      this._dispatchEvent('close');

      this._dispose();
    });

    if (context._browser.options.name === 'chromium') {
      for (const page of context.backgroundPages()) this._dispatchEvent('backgroundPage', {
        page: new _pageDispatcher.PageDispatcher(this._scope, page)
      });

      context.on(_crBrowser.CRBrowserContext.CREvents.BackgroundPage, page => this._dispatchEvent('backgroundPage', {
        page: new _pageDispatcher.PageDispatcher(this._scope, page)
      }));

      for (const serviceWorker of context.serviceWorkers()) this._dispatchEvent('serviceWorker', {
        worker: new _pageDispatcher.WorkerDispatcher(this._scope, serviceWorker)
      });

      context.on(_crBrowser.CRBrowserContext.CREvents.ServiceWorker, serviceWorker => this._dispatchEvent('serviceWorker', {
        worker: new _pageDispatcher.WorkerDispatcher(this._scope, serviceWorker)
      }));
    }

    context.on(_browserContext.BrowserContext.Events.Request, request => {
      return this._dispatchEvent('request', {
        request: _networkDispatchers.RequestDispatcher.from(this._scope, request),
        page: _pageDispatcher.PageDispatcher.fromNullable(this._scope, request.frame()._page.initializedOrUndefined())
      });
    });
    context.on(_browserContext.BrowserContext.Events.Response, response => this._dispatchEvent('response', {
      response: _networkDispatchers.ResponseDispatcher.from(this._scope, response),
      page: _pageDispatcher.PageDispatcher.fromNullable(this._scope, response.frame()._page.initializedOrUndefined())
    }));
    context.on(_browserContext.BrowserContext.Events.RequestFailed, request => this._dispatchEvent('requestFailed', {
      request: _networkDispatchers.RequestDispatcher.from(this._scope, request),
      failureText: request._failureText || undefined,
      responseEndTiming: request._responseEndTiming,
      page: _pageDispatcher.PageDispatcher.fromNullable(this._scope, request.frame()._page.initializedOrUndefined())
    }));
    context.on(_browserContext.BrowserContext.Events.RequestFinished, ({
      request,
      response
    }) => this._dispatchEvent('requestFinished', {
      request: _networkDispatchers.RequestDispatcher.from(scope, request),
      response: _networkDispatchers.ResponseDispatcher.fromNullable(scope, response),
      responseEndTiming: request._responseEndTiming,
      page: _pageDispatcher.PageDispatcher.fromNullable(this._scope, request.frame()._page.initializedOrUndefined())
    }));
  }

  async setDefaultNavigationTimeoutNoReply(params) {
    this._context.setDefaultNavigationTimeout(params.timeout);
  }

  async setDefaultTimeoutNoReply(params) {
    this._context.setDefaultTimeout(params.timeout);
  }

  async exposeBinding(params) {
    await this._context.exposeBinding(params.name, !!params.needsHandle, (source, ...args) => {
      const binding = new _pageDispatcher.BindingCallDispatcher(this._scope, params.name, !!params.needsHandle, source, args);

      this._dispatchEvent('bindingCall', {
        binding
      });

      return binding.promise();
    });
  }

  async fetch(params) {
    const {
      fetchResponse,
      error
    } = await (0, _fetch.playwrightFetch)(this._context, {
      url: params.url,
      params: (0, _utils.arrayToObject)(params.params),
      method: params.method,
      headers: params.headers ? (0, _utils.headersArrayToObject)(params.headers, false) : undefined,
      postData: params.postData ? Buffer.from(params.postData, 'base64') : undefined,
      timeout: params.timeout,
      failOnStatusCode: params.failOnStatusCode
    });
    let response;

    if (fetchResponse) {
      response = {
        url: fetchResponse.url,
        status: fetchResponse.status,
        statusText: fetchResponse.statusText,
        headers: fetchResponse.headers,
        fetchUid: fetchResponse.fetchUid
      };
    }

    return {
      response,
      error
    };
  }

  async fetchResponseBody(params) {
    const buffer = this._context.fetchResponses.get(params.fetchUid);

    return {
      binary: buffer ? buffer.toString('base64') : undefined
    };
  }

  async disposeFetchResponse(params) {
    this._context.fetchResponses.delete(params.fetchUid);
  }

  async newPage(params, metadata) {
    return {
      page: (0, _dispatcher.lookupDispatcher)(await this._context.newPage(metadata))
    };
  }

  async cookies(params) {
    return {
      cookies: await this._context.cookies(params.urls)
    };
  }

  async addCookies(params) {
    await this._context.addCookies(params.cookies);
  }

  async clearCookies() {
    await this._context.clearCookies();
  }

  async grantPermissions(params) {
    await this._context.grantPermissions(params.permissions, params.origin);
  }

  async clearPermissions() {
    await this._context.clearPermissions();
  }

  async setGeolocation(params) {
    await this._context.setGeolocation(params.geolocation);
  }

  async setExtraHTTPHeaders(params) {
    await this._context.setExtraHTTPHeaders(params.headers);
  }

  async setOffline(params) {
    await this._context.setOffline(params.offline);
  }

  async setHTTPCredentials(params) {
    await this._context.setHTTPCredentials(params.httpCredentials);
  }

  async addInitScript(params) {
    await this._context._doAddInitScript(params.source);
  }

  async setNetworkInterceptionEnabled(params) {
    if (!params.enabled) {
      await this._context._setRequestInterceptor(undefined);
      return;
    }

    await this._context._setRequestInterceptor((route, request) => {
      this._dispatchEvent('route', {
        route: _networkDispatchers.RouteDispatcher.from(this._scope, route),
        request: _networkDispatchers.RequestDispatcher.from(this._scope, request)
      });
    });
  }

  async storageState(params, metadata) {
    return await this._context.storageState(metadata);
  }

  async close(params, metadata) {
    await this._context.close(metadata);
  }

  async recorderSupplementEnable(params) {
    await _recorderSupplement.RecorderSupplement.show(this._context, params);
  }

  async pause(params, metadata) {// Inspector controller will take care of this.
  }

  async newCDPSession(params) {
    if (!this._object._browser.options.isChromium) throw new Error(`CDP session is only available in Chromium`);
    if (!params.page && !params.frame || params.page && params.frame) throw new Error(`CDP session must be initiated with either Page or Frame, not none or both`);
    const crBrowserContext = this._object;
    return {
      session: new _cdpSessionDispatcher.CDPSessionDispatcher(this._scope, await crBrowserContext.newCDPSession((params.page ? params.page : params.frame)._object))
    };
  }

  async tracingStart(params) {
    await this._context.tracing.start(params);
  }

  async tracingStartChunk(params) {
    await this._context.tracing.startChunk();
  }

  async tracingStopChunk(params) {
    const artifact = await this._context.tracing.stopChunk(params.save);
    return {
      artifact: artifact ? new _artifactDispatcher.ArtifactDispatcher(this._scope, artifact) : undefined
    };
  }

  async tracingStop(params) {
    await this._context.tracing.stop();
  }

  async harExport(params) {
    var _this$_context$_harRe;

    const artifact = await ((_this$_context$_harRe = this._context._harRecorder) === null || _this$_context$_harRe === void 0 ? void 0 : _this$_context$_harRe.export());
    if (!artifact) throw new Error('No HAR artifact. Ensure record.harPath is set.');
    return {
      artifact: new _artifactDispatcher.ArtifactDispatcher(this._scope, artifact)
    };
  }

}

exports.BrowserContextDispatcher = BrowserContextDispatcher;