func waitForEventNetworkIdle(ctx context.Context, logger *zap.Logger) func() error {
	return func() error {
		ch := make(chan struct{})
		cctx, cancel := context.WithCancel(ctx)
		chromedp.ListenTarget(cctx, func(ev interface{}) {
			switch e := ev.(type) {
			case *page.EventLifecycleEvent:
				if e.Name == "networkIdle" {
					cancel()
					close(ch)
				}
			}
		})
		select {
		case <-ch:
			logger.Debug("event networkIdle fired")
			return nil
		case <-ctx.Done():
			return fmt.Errorf("wait for event networkIdle: %w", ctx.Err())
		}
	}
}
waitForEventNetworkIdle waits until the event networkIdle is fired or the
context timeout.
package chromium
import (
	"context"
	"fmt"
	"regexp"
	"github.com/chromedp/cdproto/cdp"
	"github.com/chromedp/cdproto/fetch"
	"github.com/chromedp/cdproto/network"
	"github.com/chromedp/cdproto/page"
	"github.com/chromedp/chromedp"
	"go.uber.org/zap"
	"golang.org/x/sync/errgroup"
)
func listenForEventRequestPaused(ctx context.Context, logger *zap.Logger, allowList *regexp.Regexp, denyList *regexp.Regexp) {
	chromedp.ListenTarget(ctx, func(ev interface{}) {
		switch e := ev.(type) {
		case *fetch.EventRequestPaused:
			go func() {
				logger.Debug(fmt.Sprintf("event EventRequestPaused fired for '%s'", e.Request.URL))
				allow := true
				if !allowList.MatchString(e.Request.URL) {
					logger.Warn(fmt.Sprintf("'%s' does not match the expression from the allowed list", e.Request.URL))
					allow = false
				}
				if denyList.String() != "" && denyList.MatchString(e.Request.URL) {
					logger.Warn(fmt.Sprintf("'%s' matches the expression from the denied list", e.Request.URL))
					allow = false
				}
				cctx := chromedp.FromContext(ctx)
				executorCtx := cdp.WithExecutor(ctx, cctx.Target)
				if allow {
					req := fetch.ContinueRequest(e.RequestID)
					err := req.Do(executorCtx)
					if err != nil {
						logger.Error(fmt.Sprintf("continue request: %s", err))
					}
					return
				}
				req := fetch.FailRequest(e.RequestID, network.ErrorReasonAccessDenied)
				err := req.Do(executorCtx)
				if err != nil {
					logger.Error(fmt.Sprintf("fail request: %s", err))
				}
			}()
		}
	})
}
func waitForEventDomContentEventFired(ctx context.Context, logger *zap.Logger) func() error {
	return func() error {
		ch := make(chan struct{})
		cctx, cancel := context.WithCancel(ctx)
		chromedp.ListenTarget(cctx, func(ev interface{}) {
			switch ev.(type) {
			case *page.EventDomContentEventFired:
				cancel()
				close(ch)
			}
		})
		select {
		case <-ch:
			logger.Debug("event DomContentEventFired fired")
			return nil
		case <-ctx.Done():
			return fmt.Errorf("wait for event DomContentEventFired: %w", ctx.Err())
		}
	}
}
func waitForEventLoadEventFired(ctx context.Context, logger *zap.Logger) func() error {
	return func() error {
		ch := make(chan struct{})
		cctx, cancel := context.WithCancel(ctx)
		chromedp.ListenTarget(cctx, func(ev interface{}) {
			switch ev.(type) {
			case *page.EventLoadEventFired:
				cancel()
				close(ch)
			}
		})
		select {
		case <-ch:
			logger.Debug("event LoadEventFired fired")
			return nil
		case <-ctx.Done():
			return fmt.Errorf("wait for event LoadEventFired: %w", ctx.Err())
		}
	}
}