Skip to content

Commit

Permalink
Merge pull request #8 from geopozo/neyberson/browser_protocol
Browse files Browse the repository at this point in the history
Neyberson/browser protocol
  • Loading branch information
ayjayt authored Aug 19, 2024
2 parents 19c004a + 20d08d7 commit 17c7721
Show file tree
Hide file tree
Showing 10 changed files with 119 additions and 95 deletions.
59 changes: 9 additions & 50 deletions app/app.py
Original file line number Diff line number Diff line change
Expand Up @@ -4,60 +4,19 @@

def main():
# Interface Test

## Create Connection
connection = devtools.Connection()

connection.list_tabs()

## Simulate Commands
print(
connection.browser_session.send_command(
"command1", dict(param1="1", param2="a")
)
)
print(
connection.browser_session.send_command(
"command2", dict(param1="2", param2="b")
)
)

## Create Tab
myTab = connection.create_tab()
connection.list_tabs()

## Simulate Commands
print(myTab.send_command("tabCommand1", dict(param1="tab1", param2="taba")))
print(myTab.send_command("tabCommand2", dict(param1="tab2", param2="tabb")))
print(
connection.browser_session.send_command(
"command3", dict(param1="3", param2="c")
)
)

## Close Tab
connection.close_tab(myTab)
connection.list_tabs()

## Simulate Commands
print(
connection.browser_session.send_command(
"command4", dict(param1="4", param2="d")
)
)

# Process/Pipes Test
with devtools.Browser() as browser:
pipe = browser.pipe
with devtools.Browser(headless=False) as browser:
## Create Protocol
connection = browser.protocol

pipe.write("{}")
print(pipe.read_jsons(debug=True))
print(pipe.read_jsons(blocking=False, debug=True))
print(pipe.read_jsons(blocking=False, debug=True))
print(pipe.read_jsons(blocking=False, debug=True))
connection.send_command(command="Target.createTarget", params={"url": "https://www.youtube.com/"})

time.sleep(10)
connection.pipe.read_jsons(debug=True)
connection.pipe.read_jsons(blocking=False, debug=True)
connection.pipe.read_jsons(blocking=False, debug=True)
connection.pipe.read_jsons(blocking=False, debug=True)

time.sleep(10)

if __name__ == "__main__":
main()
9 changes: 5 additions & 4 deletions app/app_devtools.py
Original file line number Diff line number Diff line change
Expand Up @@ -54,14 +54,15 @@

list_r = [r1, r3, r4, r5, r6, r7, r8, r9, r10, r11, r12]

## Create Connection
browser = devtools.Connection()
browser.list_tabs()
## Create Protocol
browser = devtools.Browser()
connection = browser.protocol
connection.list_tabs()

## Print Commands
for r in list_r:
print(
browser.browser_session.send_command(
connection.browser_session.send_command(
command=r["method"], params=r["params"] if "params" in r else None
)
)
3 changes: 1 addition & 2 deletions devtools/__init__.py
Original file line number Diff line number Diff line change
@@ -1,4 +1,3 @@
from .browser import Browser
from .connection import Connection

__all__ = [Browser, Connection]
__all__ = [Browser]
10 changes: 9 additions & 1 deletion devtools/browser.py
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
from .pipe import Pipe
from .protocol import Protocol
import platform
import os
import sys
Expand All @@ -7,7 +8,7 @@


class Browser:
def __init__(self, debug=None, path=None):
def __init__(self, debug=None, path=None, headless=True):
self.pipe = Pipe()

if not debug: # false o None
Expand All @@ -27,6 +28,9 @@ def __init__(self, debug=None, path=None):

new_env = os.environ.copy()
new_env["CHROMIUM_PATH"] = path
if headless:
new_env["HEADLESS"] = "--headless"

win_only = {}
if platform.system() == "Windows":
win_only = {"creationflags": subprocess.CREATE_NEW_PROCESS_GROUP}
Expand All @@ -46,6 +50,7 @@ def __init__(self, debug=None, path=None):
**win_only,
)
self.subprocess = proc
self.protocol = Protocol(self.pipe)

def __enter__(self):
return self
Expand All @@ -60,3 +65,6 @@ def close_browser(self):
self.subprocess.terminate()
self.subprocess.wait(5)
self.subprocess.kill()

def send_command(self, command, params=None, cb=None):
return self.protocol.send_command(self, command, params, cb)
4 changes: 3 additions & 1 deletion devtools/chrome_wrapper.py
Original file line number Diff line number Diff line change
Expand Up @@ -28,12 +28,14 @@

cli = [
path,
"--headless",
"--remote-debugging-pipe",
"--disable-breakpad",
"--allow-file-access-from-files",
]

if "HEADLESS" in os.environ:
cli.append("--headless")

if system == "Windows":
to_chromium_handle = msvcrt.get_osfhandle(3)
os.set_handle_inheritable(to_chromium_handle, True)
Expand Down
29 changes: 0 additions & 29 deletions devtools/connection.py

This file was deleted.

16 changes: 14 additions & 2 deletions devtools/pipe.py
Original file line number Diff line number Diff line change
Expand Up @@ -12,8 +12,20 @@ def __init__(self):
self.read_from_chromium, self.write_from_chromium = list(os.pipe())
self.read_to_chromium, self.write_to_chromium = list(os.pipe())

def write(self, msg): # this should accept an objects not a string
os.write(self.write_to_chromium, str.encode(msg + "\0"))
def write_json(
self, message_id, method, params=None, session_id=""
): # this should accept an objects not a string
if params:
message = {"id": message_id, "method": method, "params": params}
else:
message = {"id": message_id, "method": method}

if session_id != "":
message["session_id"] = session_id

encoded_message = json.dumps(message).encode() + b"\0"

os.write(self.write_to_chromium, encoded_message)

def read_jsons(self, blocking=True, debug=False):
if debug:
Expand Down
33 changes: 33 additions & 0 deletions devtools/protocol.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,33 @@
from .tab import Tab
from .session import Session
from collections import OrderedDict


class Protocol:
def __init__(self, browser_pipe):
self.browser_session = Session(self, session_id="")
self.target_id = 0
self.tabs = OrderedDict()
self.pipe = browser_pipe

def create_tab(self):
tab_obj = Tab()
self.tabs[tab_obj.target_id] = tab_obj
print(f"New Tab Created: {tab_obj.target_id}")
return tab_obj

def list_tabs(self):
print("Tabs".center(50, "-"))
for target_id in self.tabs.keys():
print(target_id.center(50, " "))
print("End".center(50, "-"))

def close_tab(self, tab_id):
if isinstance(tab_id, str):
del self.tabs[tab_id]
else:
del self.tabs[tab_id.target_id]
print(f"The following tab was deleted: {tab_id}")

def send_command(self, command, params=None, cb=None):
return self.browser_session.send_command(command, params, cb)
23 changes: 17 additions & 6 deletions devtools/session.py
Original file line number Diff line number Diff line change
@@ -1,8 +1,9 @@
import json
import uuid


class Session:
def __init__(self, parent, session_id=""):
def __init__(self, parent, session_id=str(uuid.uuid4())):
if isinstance(session_id, str):
self.session_id = session_id
else:
Expand All @@ -27,15 +28,25 @@ def send_command(self, command, params=None, cb=None):
"method": command,
}

if self.session_id != "":
json_command["session_id"] = self.session_id

if params:
json_command["params"] = params

if self.session_id != "":
json_command["session_id"] = self.session_id
self.parent_connection.pipe.write_json(
message_id=json_command["id"],
method=json_command["method"],
params=json_command["params"],
session_id=self.session_id,
)
else:
self.parent_connection.pipe.write_json(
message_id=json_command["id"],
method=json_command["method"],
session_id=self.session_id,
)

self.message_id += 1

return json.dumps(json_command)

def close_tab(self):
self.parent.close_tab(self)
28 changes: 28 additions & 0 deletions devtools/tab.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,28 @@
from .session import Session
from collections import OrderedDict
import uuid


class Tab:
def __init__(self):
self.tab_sessions = OrderedDict()
self.target_id = str(uuid.uuid4())

def add_session(self):
session_obj = Session(self)
self.tab_sessions[session_obj.session_id] = session_obj
print(f"New Session Added: {session_obj.session_id}")
return session_obj

def list_sessions(self):
print("Sessions".center(50, "-"))
for session_instance in self.tab_sessions.values():
print(str(session_instance.session_id).center(50, " "))
print("End".center(50, "-"))

def close_session(self, session_obj):
if isinstance(session_obj, str):
del self.tab_sessions[session_obj]
else:
del self.tab_sessions[session_obj.session_id]
print(f"The following session was deleted: {session_obj.session_id}")

0 comments on commit 17c7721

Please sign in to comment.