mirror of
				https://github.com/microsoft/playwright.git
				synced 2025-06-26 21:40:17 +00:00 
			
		
		
		
	
		
			
				
	
	
		
			136 lines
		
	
	
		
			4.3 KiB
		
	
	
	
		
			JavaScript
		
	
	
	
	
	
			
		
		
	
	
			136 lines
		
	
	
		
			4.3 KiB
		
	
	
	
		
			JavaScript
		
	
	
	
	
	
| /* 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/. */
 | |
| 
 | |
| const {protocol, checkScheme} = ChromeUtils.import("chrome://juggler/content/protocol/Protocol.js");
 | |
| const {Helper} = ChromeUtils.import('chrome://juggler/content/Helper.js');
 | |
| 
 | |
| const helper = new Helper();
 | |
| 
 | |
| class Dispatcher {
 | |
|   /**
 | |
|    * @param {Connection} connection
 | |
|    */
 | |
|   constructor(connection) {
 | |
|     this._connection = connection;
 | |
|     this._connection.onmessage = this._dispatch.bind(this);
 | |
|     this._connection.onclose = this._dispose.bind(this);
 | |
|     this._sessions = new Map();
 | |
|     this._rootSession = new ProtocolSession(this, undefined);
 | |
|   }
 | |
| 
 | |
|   rootSession() {
 | |
|     return this._rootSession;
 | |
|   }
 | |
| 
 | |
|   createSession() {
 | |
|     const session = new ProtocolSession(this, helper.generateId());
 | |
|     this._sessions.set(session.sessionId(), session);
 | |
|     return session;
 | |
|   }
 | |
| 
 | |
|   destroySession(session) {
 | |
|     this._sessions.delete(session.sessionId());
 | |
|     session._dispose();
 | |
|   }
 | |
| 
 | |
|   _dispose() {
 | |
|     this._connection.onmessage = null;
 | |
|     this._connection.onclose = null;
 | |
|     this._rootSession._dispose();
 | |
|     this._rootSession = null;
 | |
|     this._sessions.clear();
 | |
|   }
 | |
| 
 | |
|   async _dispatch(event) {
 | |
|     const data = JSON.parse(event.data);
 | |
|     const id = data.id;
 | |
|     const sessionId = data.sessionId;
 | |
|     delete data.sessionId;
 | |
|     try {
 | |
|       const session = sessionId ? this._sessions.get(sessionId) : this._rootSession;
 | |
|       if (!session)
 | |
|         throw new Error(`ERROR: cannot find session with id "${sessionId}"`);
 | |
|       const method = data.method;
 | |
|       const params = data.params || {};
 | |
|       if (!id)
 | |
|         throw new Error(`ERROR: every message must have an 'id' parameter`);
 | |
|       if (!method)
 | |
|         throw new Error(`ERROR: every message must have a 'method' parameter`);
 | |
| 
 | |
|       const [domain, methodName] = method.split('.');
 | |
|       const descriptor = protocol.domains[domain] ? protocol.domains[domain].methods[methodName] : null;
 | |
|       if (!descriptor)
 | |
|         throw new Error(`ERROR: method '${method}' is not supported`);
 | |
|       let details = {};
 | |
|       if (!checkScheme(descriptor.params || {}, params, details))
 | |
|         throw new Error(`ERROR: failed to call method '${method}' with parameters ${JSON.stringify(params, null, 2)}\n${details.error}`);
 | |
| 
 | |
|       const result = await session.dispatch(method, params);
 | |
| 
 | |
|       details = {};
 | |
|       if ((descriptor.returns || result) && !checkScheme(descriptor.returns, result, details))
 | |
|         throw new Error(`ERROR: failed to dispatch method '${method}' result ${JSON.stringify(result, null, 2)}\n${details.error}`);
 | |
| 
 | |
|       this._connection.send(JSON.stringify({id, sessionId, result}));
 | |
|     } catch (e) {
 | |
|       this._connection.send(JSON.stringify({id, sessionId, error: {
 | |
|         message: e.message,
 | |
|         data: e.stack
 | |
|       }}));
 | |
|     }
 | |
|   }
 | |
| 
 | |
|   _emitEvent(sessionId, eventName, params) {
 | |
|     const [domain, eName] = eventName.split('.');
 | |
|     const scheme = protocol.domains[domain] ? protocol.domains[domain].events[eName] : null;
 | |
|     if (!scheme)
 | |
|       throw new Error(`ERROR: event '${eventName}' is not supported`);
 | |
|     const details = {};
 | |
|     if (!checkScheme(scheme, params || {}, details))
 | |
|       throw new Error(`ERROR: failed to emit event '${eventName}' ${JSON.stringify(params, null, 2)}\n${details.error}`);
 | |
|     this._connection.send(JSON.stringify({method: eventName, params, sessionId}));
 | |
|   }
 | |
| }
 | |
| 
 | |
| class ProtocolSession {
 | |
|   constructor(dispatcher, sessionId) {
 | |
|     this._sessionId = sessionId;
 | |
|     this._dispatcher = dispatcher;
 | |
|     this._handler = null;
 | |
|   }
 | |
| 
 | |
|   sessionId() {
 | |
|     return this._sessionId;
 | |
|   }
 | |
| 
 | |
|   setHandler(handler) {
 | |
|     this._handler = handler;
 | |
|   }
 | |
| 
 | |
|   _dispose() {
 | |
|     if (this._handler)
 | |
|       this._handler.dispose();
 | |
|     this._handler = null;
 | |
|     this._dispatcher = null;
 | |
|   }
 | |
| 
 | |
|   emitEvent(eventName, params) {
 | |
|     if (!this._dispatcher)
 | |
|       throw new Error(`Session has been disposed.`);
 | |
|     this._dispatcher._emitEvent(this._sessionId, eventName, params);
 | |
|   }
 | |
| 
 | |
|   async dispatch(method, params) {
 | |
|     if (!this._handler)
 | |
|       throw new Error(`Session does not have a handler!`);
 | |
|     if (!this._handler[method])
 | |
|       throw new Error(`Handler for does not implement method "${method}"`);
 | |
|     return await this._handler[method](params);
 | |
|   }
 | |
| }
 | |
| 
 | |
| this.EXPORTED_SYMBOLS = ['Dispatcher'];
 | |
| this.Dispatcher = Dispatcher;
 | |
| 
 | 
