UNPKG

5.49 kBJavaScriptView Raw
1/**
2 * Copyright 2017 Google Inc. All rights reserved.
3 *
4 * Licensed under the Apache License, Version 2.0 (the "License");
5 * you may not use this file except in compliance with the License.
6 * You may obtain a copy of the License at
7 *
8 * http://www.apache.org/licenses/LICENSE-2.0
9 *
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the License for the specific language governing permissions and
14 * limitations under the License.
15 */
16
17const { helper } = require('./helper');
18const Target = require('./Target');
19const EventEmitter = require('events');
20const TaskQueue = require('./TaskQueue');
21
22class Browser extends EventEmitter {
23 /**
24 * @param {!Puppeteer.Connection} connection
25 * @param {!BrowserOptions=} options
26 * @param {?Puppeteer.ChildProcess} process
27 * @param {(function():Promise)=} closeCallback
28 */
29 constructor(connection, options = {}, process, closeCallback) {
30 super();
31 this._ignoreHTTPSErrors = !!options.ignoreHTTPSErrors;
32 this._appMode = !!options.appMode;
33 this._process = process;
34 this._screenshotTaskQueue = new TaskQueue();
35 this._connection = connection;
36 this._closeCallback = closeCallback || new Function();
37 /** @type {Map<string, Target>} */
38 this._targets = new Map();
39 this._connection.setClosedCallback(() => {
40 this.emit(Browser.Events.Disconnected);
41 });
42 this._connection.on('Target.targetCreated', this._targetCreated.bind(this));
43 this._connection.on('Target.targetDestroyed', this._targetDestroyed.bind(this));
44 this._connection.on('Target.targetInfoChanged', this._targetInfoChanged.bind(this));
45 }
46
47 /**
48 * @return {?Puppeteer.ChildProcess}
49 */
50 process() {
51 return this._process;
52 }
53
54 /**
55 * @param {!Puppeteer.Connection} connection
56 * @param {!BrowserOptions=} options
57 * @param {?Puppeteer.ChildProcess} process
58 * @param {function()=} closeCallback
59 */
60 static async create(connection, options, process, closeCallback) {
61 const browser = new Browser(connection, options, process, closeCallback);
62 await connection.send('Target.setDiscoverTargets', {discover: true});
63 return browser;
64 }
65
66 /**
67 * @param {{targetInfo: !Puppeteer.TargetInfo}} event
68 */
69 async _targetCreated(event) {
70 const targetInfo = event.targetInfo;
71 const target = new Target(targetInfo, () => this._connection.createSession(targetInfo.targetId), this._ignoreHTTPSErrors, !this._appMode, this._screenshotTaskQueue);
72 console.assert(!this._targets.has(event.targetInfo.targetId), 'Target should not exist before targetCreated');
73 this._targets.set(event.targetInfo.targetId, target);
74
75 if (await target._initializedPromise)
76 this.emit(Browser.Events.TargetCreated, target);
77 }
78
79 /**
80 * @param {{targetId: string}} event
81 */
82 async _targetDestroyed(event) {
83 const target = this._targets.get(event.targetId);
84 target._initializedCallback(false);
85 this._targets.delete(event.targetId);
86 target._closedCallback();
87 if (await target._initializedPromise)
88 this.emit(Browser.Events.TargetDestroyed, target);
89 }
90
91 /**
92 * @param {{targetInfo: !Puppeteer.TargetInfo}} event
93 */
94 _targetInfoChanged(event) {
95 const target = this._targets.get(event.targetInfo.targetId);
96 console.assert(target, 'target should exist before targetInfoChanged');
97 const previousURL = target.url();
98 const wasInitialized = target._isInitialized;
99 target._targetInfoChanged(event.targetInfo);
100 if (wasInitialized && previousURL !== target.url())
101 this.emit(Browser.Events.TargetChanged, target);
102 }
103
104 /**
105 * @return {string}
106 */
107 wsEndpoint() {
108 return this._connection.url();
109 }
110
111 /**
112 * @return {!Promise<!Puppeteer.Page>}
113 */
114 async newPage() {
115 const {targetId} = await this._connection.send('Target.createTarget', {url: 'about:blank'});
116 const target = await this._targets.get(targetId);
117 console.assert(await target._initializedPromise, 'Failed to create target for page');
118 const page = await target.page();
119 return page;
120 }
121
122 /**
123 * @return {!Array<!Target>}
124 */
125 targets() {
126 return Array.from(this._targets.values()).filter(target => target._isInitialized);
127 }
128
129 /**
130 * @return {!Promise<!Array<!Puppeteer.Page>>}
131 */
132 async pages() {
133 const pages = await Promise.all(this.targets().map(target => target.page()));
134 return pages.filter(page => !!page);
135 }
136
137 /**
138 * @return {!Promise<string>}
139 */
140 async version() {
141 const version = await this._getVersion();
142 return version.product;
143 }
144
145 /**
146 * @return {!Promise<string>}
147 */
148 async userAgent() {
149 const version = await this._getVersion();
150 return version.userAgent;
151 }
152
153 async close() {
154 await this._closeCallback.call(null);
155 this.disconnect();
156 }
157
158 disconnect() {
159 this._connection.dispose();
160 }
161
162 /**
163 * @return {!Promise<!Object>}
164 */
165 _getVersion() {
166 return this._connection.send('Browser.getVersion');
167 }
168}
169
170/** @enum {string} */
171Browser.Events = {
172 TargetCreated: 'targetcreated',
173 TargetDestroyed: 'targetdestroyed',
174 TargetChanged: 'targetchanged',
175 Disconnected: 'disconnected'
176};
177
178helper.tracePublicAPI(Browser);
179
180module.exports = Browser;
181
182/**
183 * @typedef {Object} BrowserOptions
184 * @property {boolean=} appMode
185 * @property {boolean=} ignoreHTTPSErrors
186 */
\No newline at end of file