Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Neyberson/connection #15

Closed
wants to merge 188 commits into from
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
188 commits
Select commit Hold shift + click to select a range
806a7d8
Reorganize protocol.py
neyberson Aug 16, 2024
f0e41b0
Use send_command() into create_tab() from Protocol
neyberson Aug 16, 2024
ba08d1b
Use send_command() into close_tab() from Protocol
neyberson Aug 16, 2024
4590668
Format code at protocol.py
neyberson Aug 16, 2024
f4ca686
Use send_command() into add_session() from Tab
neyberson Aug 16, 2024
7b35a1f
Improve the session_id use at add_session() from Tab
neyberson Aug 16, 2024
93b34a4
Use send_command() into close_session() from Tab
neyberson Aug 16, 2024
5c32506
Format code at tab.py
neyberson Aug 16, 2024
4ef9b44
Delete return at send_command() from Session
neyberson Aug 16, 2024
a19ff1a
Update app.py with for devtools update
neyberson Aug 16, 2024
b04df4f
Create create_tab(), list_tabs() and close_tabs() at Browser
neyberson Aug 16, 2024
5963115
Delete variable at add_session() from Tab
neyberson Aug 16, 2024
b6e4c81
Improve create_tab() extracting target_id at Protocol
neyberson Aug 16, 2024
8c45eca
Improve close_tab() using target_id at Protocol
neyberson Aug 16, 2024
e5118b4
Delete print and add time.sleep() at app.py
neyberson Aug 16, 2024
b7d6496
Simplify code at app.py
neyberson Aug 16, 2024
42bc7da
Format code at app.py
neyberson Aug 16, 2024
10139e3
Delete json import at protocol.py and session.py
neyberson Aug 16, 2024
9c1d405
Use target_id at add_session() from Tab
neyberson Aug 17, 2024
c371ac9
Change session_obj to session at close_session() from Tab
neyberson Aug 17, 2024
515aa0d
Change tab_id to tab at close_tab() from Protocol
neyberson Aug 17, 2024
93d936d
Delete useless code about read_jsons() at app.py
neyberson Aug 17, 2024
c317512
Add time.sleep and use close_tab() at app.py
neyberson Aug 17, 2024
f5464dc
Add time.sleep at app.py
neyberson Aug 17, 2024
e7423e4
Add jupyter stuff to .gitignore
ayjayt Aug 19, 2024
63e38c4
Add --user-data-dir to chrome flags:
ayjayt Aug 19, 2024
591537b
Merge pull request #16 from geopozo/andrew/user-data-dir
neyberson Aug 20, 2024
030602c
Delete return at __exit__() from Browser
neyberson Aug 20, 2024
ad00073
Add function which() to find variations of chrome
ayjayt Aug 20, 2024
1dcfdc9
Make changes to app.py to make consistent
ayjayt Aug 20, 2024
4b503f4
Improve which for windows
ayjayt Aug 20, 2024
82535f5
Fix windows signaling
ayjayt Aug 20, 2024
bcb0fa6
Merge branch 'andrew/app_consistent' into andrew/windows-which-2
ayjayt Aug 20, 2024
a6fd79e
Add sleep after context exit in app.py
ayjayt Aug 20, 2024
a8c78d9
Lint
ayjayt Aug 20, 2024
e252d1e
Lint2
ayjayt Aug 20, 2024
b202e95
Merge pull request #18 from geopozo/andrew/windows-which-2
neyberson Aug 20, 2024
8ce6589
Merge branch 'neyberson/connection' of github.com:geopozo/devtools_pr…
neyberson Aug 20, 2024
9d35f79
Change onerror to onexc at shutil.rmtree from Browser
neyberson Aug 20, 2024
365dfc6
Improve conditional to detect system at chrome_wrapper.py
neyberson Aug 20, 2024
0cfcaba
Format code at chrome_wrapper.py
neyberson Aug 20, 2024
3da8902
Delete some conditionals and improve .get() use at chrome_wrapper.py
neyberson Aug 20, 2024
918419d
Delete path='' at chrome_wrapper.py
neyberson Aug 20, 2024
45c1801
Simplify the write_jsons() use into send_command() from Session
neyberson Aug 20, 2024
724c5c9
Format code at browser.py
neyberson Aug 20, 2024
c9135fe
Format code at system.py
neyberson Aug 20, 2024
26e6d19
Simplify the write_jsons() use and change id to message_id at Session
neyberson Aug 20, 2024
ec49b24
Simplify close_session() from Tab
neyberson Aug 21, 2024
6a5c770
Simplify close_tab() from Protocol
neyberson Aug 21, 2024
297c956
Reorganize close_session() from Tab
neyberson Aug 21, 2024
48beb09
Format code at protocol.py
neyberson Aug 21, 2024
40f9ef2
Improve chrome_wrapper.py to verify path
neyberson Aug 21, 2024
8cb8d33
Verify path at Browser
neyberson Aug 21, 2024
10b62f0
Create verify_json() at Pipe
neyberson Aug 21, 2024
ea9ee39
Use verify_jsons() into read_jsons() from Pipe
neyberson Aug 21, 2024
39f3b67
Change verify_json() to verify_json_id() at Pipe
neyberson Aug 21, 2024
20a53ec
Move verify_json_id() from pipe.py to protocol.py
neyberson Aug 21, 2024
863d5fd
Use verify_json_id() into create_tab() from Protocol
neyberson Aug 21, 2024
656654a
Add comment at protocol.py
neyberson Aug 21, 2024
22f996a
Add loop into verify_json_id() from Protocol
neyberson Aug 21, 2024
348ae64
Lint at protocol.py
neyberson Aug 21, 2024
61b976d
Create verify_json() at Protocol
neyberson Aug 21, 2024
aced63c
Use verify_json() into create_tab() from Protocol
neyberson Aug 21, 2024
b3bb08a
Delete verify_json() and improve verify_json_id() at Protocol
neyberson Aug 21, 2024
ba54d21
Simplify loop and conditionals at verify_json_id() from Protocol
neyberson Aug 21, 2024
f5ca5bb
Rename some variables at verify_json_id() from Protocol
neyberson Aug 21, 2024
7f13cd8
Create utils.py
neyberson Aug 21, 2024
e8b7c24
Move verify_json_id() to utils.py
neyberson Aug 21, 2024
fb8705e
Format code at utils.py
neyberson Aug 21, 2024
2577a30
Delete th use of verify_json() and verify_json_id() at protocol.py
neyberson Aug 21, 2024
abaea05
Fixbug at add_session() from Tab
neyberson Aug 21, 2024
f1236ab
Add session_id parameter at send_command() from Session
neyberson Aug 21, 2024
f5ef357
Add session_id parameter in send_command() at protocol.py and browser.py
neyberson Aug 22, 2024
99c12ed
Add pipe attribute to Tab
neyberson Aug 22, 2024
4fedade
Update app.py
neyberson Aug 22, 2024
bb75426
Delete print at app.py
neyberson Aug 22, 2024
2ff400c
Use read_jsons() at add_session() from Tab
neyberson Aug 22, 2024
ecd2849
Add debug parameter at write_jsons() from Pipe
neyberson Aug 22, 2024
29e7ae4
Change session_id to sessionId at write_json() from Pipe
neyberson Aug 22, 2024
d945b84
Add debug parameter at create_tab() from Protocol
neyberson Aug 22, 2024
ed33cd7
Use debug into create_tab() from Protocol
neyberson Aug 22, 2024
bd19e6a
Add print at Pipe
neyberson Aug 22, 2024
824cc54
Add debug parameter at send_command()
neyberson Aug 22, 2024
f3760c4
Add debug parameter at add_session() from Tab
neyberson Aug 22, 2024
1301d76
Fixbug at add_session() from Tab
neyberson Aug 22, 2024
16fb595
Add debug parameter to some methods from Browser
neyberson Aug 22, 2024
fe1123b
Change tab_id to tab at close_tab from Browser
neyberson Aug 22, 2024
f1a3a9f
Fixbug at send_command() from Browser
neyberson Aug 22, 2024
4b2a158
Update app.py
neyberson Aug 22, 2024
cfb7245
Add url parameter at create_tab()
neyberson Aug 22, 2024
537ae35
Create varify_json_error() at utils.py
neyberson Aug 22, 2024
e447f99
Use verify_json_error() at tab.py and protocol.py
neyberson Aug 22, 2024
697cc92
Fixbug about session_id at add_session() from Tab
neyberson Aug 22, 2024
864d828
Improve create_tab() to set target_id in tab objects from Protocol
neyberson Aug 22, 2024
c1ba5e5
Improve prints for debugging at create_tab()
neyberson Aug 22, 2024
874c4e8
Improve prints for debugging at add_session()
neyberson Aug 22, 2024
a2adfa2
Delete pipe parameter and add message_id at verify_json_id() from utils
neyberson Aug 23, 2024
29a5838
Delete error at verify_json_id() from utils.py
neyberson Aug 23, 2024
5b67a9a
Add session_id parameter at verify_json_id() from utils.py
neyberson Aug 23, 2024
5656ece
Add target_id parameter at verify_json_id() from utils.py
neyberson Aug 23, 2024
f9e4435
Delete os import at utils.py
neyberson Aug 23, 2024
240fbab
Format code at utils.py
neyberson Aug 23, 2024
d6009d7
Add debug at json_command dictionary from send_command()
neyberson Aug 23, 2024
2d13b7e
Improve print at write_json() from Pipe
neyberson Aug 23, 2024
72efd21
Add conditionals to set target_id into create_tab()
neyberson Aug 23, 2024
ca68ba5
Add conditionals to set session_id into add_session()
neyberson Aug 23, 2024
54ccaee
Add loop to verify the list from read_jsons() at create_tab()
neyberson Aug 23, 2024
5f1b139
Improve message creation at write_json() from Pipe
neyberson Aug 23, 2024
e937d07
Add try except to delete temp file at close_browser()
neyberson Aug 23, 2024
7db628e
Add conditional to get 'targetId' at create_tab() from Protocol
neyberson Aug 23, 2024
78f3129
Add 'flatten' to send_command() at add_session()
neyberson Aug 23, 2024
d3bed69
Create verify_target_id() in utils.py
neyberson Aug 26, 2024
e2ba075
Use verify_target_id() into create_tab() from Protocol
neyberson Aug 26, 2024
21db34f
Improve loop with verify_target_id() into create_tab()
neyberson Aug 26, 2024
edc8a60
Add print to debug at create_tab() from Protocol
neyberson Aug 26, 2024
a56dc94
Create verify_session_id() in utils.py
neyberson Aug 26, 2024
5630252
Create verify_json_list() in utils.py
neyberson Aug 26, 2024
f353d05
Use verify_json_list() into create_tab() from Protocol
neyberson Aug 26, 2024
fd526fc
Use verify_json_list() and verify_session_id() into add_session()
neyberson Aug 26, 2024
d9e7703
Delete some imports at protocol.py
neyberson Aug 26, 2024
451e60b
Delete some imports at tab.py
neyberson Aug 26, 2024
9166635
Add a pipe-general debug
ayjayt Aug 26, 2024
567898c
Merge pull request #20 from geopozo/andrew/improve_debug
neyberson Aug 26, 2024
6e2d8d1
Move print at pipe.py:read_jsons()
neyberson Aug 27, 2024
a64f269
Divide protocol.py:create_tab() in create_tab_1() and create_tab_2()
neyberson Aug 27, 2024
16440da
Divide tab.py:add_session() in add_session_1() and add_session_2()
neyberson Aug 27, 2024
16eac99
Create create_tab_3() in Protocol
neyberson Aug 27, 2024
19f8e4e
Create add_session_3() in Tab
neyberson Aug 27, 2024
0ed0055
Add session_obj parameter in protocol.py:create_tab_3()
neyberson Aug 27, 2024
2d09ca1
Lint
neyberson Aug 27, 2024
2ef9f62
Delete print in pipe.py:read_jsons()
neyberson Aug 28, 2024
efe2d23
Add some prints at Tab
neyberson Aug 28, 2024
e9a16a6
Add some prints at Protocol
neyberson Aug 28, 2024
329a52e
Add print and improve print at Session
neyberson Aug 28, 2024
d1448b5
Add print and improve print in pipe.py:write_json()
neyberson Aug 28, 2024
1f0ce89
Format code in pipe.py
neyberson Aug 28, 2024
21c406d
Format code in session.py
neyberson Aug 28, 2024
88d50aa
Improve prints in pipe.py:read_jsons()
neyberson Aug 28, 2024
5c50f51
Improve while loop with foor loop in protocol.py:create_tab_3()
neyberson Aug 28, 2024
bf71bfd
Add create_tab_1(), create_tab_2() and create_tab_3() in Browser
neyberson Aug 28, 2024
7f3a484
Delete create_tab_3()
neyberson Aug 28, 2024
a770da9
Delete add_session_3() in Tab
neyberson Aug 28, 2024
eaf092a
Create run_output_thread() in utils.py
neyberson Aug 28, 2024
30723d3
Add run_output_thread() in __init__.py
neyberson Aug 28, 2024
ab31774
Browser(debug=x) now sets Pipe(debug=X)
ayjayt Aug 28, 2024
fb1759a
Add blocking and debug parameters in utils.py:run_output_thread()
neyberson Aug 28, 2024
c41b0e7
Split debug and debug_browser into two options
ayjayt Aug 28, 2024
e589ec7
Remove mid-level debug statements
ayjayt Aug 28, 2024
10a9f94
Wrap tempdir cleanup in try
ayjayt Aug 28, 2024
154a59e
Format
ayjayt Aug 28, 2024
0e0871a
Remove another midlevel debug
ayjayt Aug 28, 2024
ba75dfe
Delete () to fixbug in utils.py imports
neyberson Aug 28, 2024
f2b39cf
Change session_id default from None to ""
ayjayt Aug 28, 2024
9944644
Cleanup write_json defaults + object construction
ayjayt Aug 28, 2024
8bff04c
Straighten out decoding in write_jsons
ayjayt Aug 28, 2024
574c81d
Add run_output_thread() in Browser
neyberson Aug 28, 2024
d0bd917
Improve debug statements a bit
ayjayt Aug 28, 2024
274cd4c
Simplify session.py:Session class
ayjayt Aug 29, 2024
d323ad5
Write and integrate a Target class
ayjayt Aug 29, 2024
d39f7f8
Simplify protocol and write
ayjayt Aug 29, 2024
5fba2e0
Add returns for send command
ayjayt Aug 29, 2024
aed8df3
Add thread in utils.py:run_output_thread()
neyberson Aug 29, 2024
29abb68
Move run_output_thread of utils.py to browser.py
neyberson Aug 29, 2024
8eb43c1
Delete blocking parameter in browser.py:run_output_thread()
neyberson Aug 29, 2024
fc4b33a
Add print in browser.py:run_output_thread()
neyberson Aug 29, 2024
4e6193a
Delete run_output_thread() import in __init__.py
neyberson Aug 29, 2024
93ad1f2
Add verify_response() function to protocol
ayjayt Aug 29, 2024
5c7d389
Change some parameters and prints in browser.py:run_output_thread()
neyberson Aug 29, 2024
88d2dab
Add loop to print any json in browser.py:run_output_thread()
neyberson Aug 29, 2024
ec9300f
Make Browser inherit target
ayjayt Aug 29, 2024
0ad74a4
Make Tab() a shim for Target()
ayjayt Aug 29, 2024
a3c5e71
Make tab's constructor accept browser not protocol
ayjayt Aug 29, 2024
650c68f
Change browser.close_browser to browser.close
ayjayt Aug 29, 2024
4175b9b
Use hasattr, not isinstance, avoid import circle
ayjayt Aug 29, 2024
ff85ce0
Make dict of Tabs in Browser
ayjayt Aug 29, 2024
a9eca0a
Add default session to browser
ayjayt Aug 29, 2024
955d34e
Initialize default session w/ browser
ayjayt Aug 29, 2024
f2c924f
Fix simple typo, variable name
ayjayt Aug 29, 2024
f7c0e5d
Change app/ for new API
ayjayt Aug 29, 2024
4570a0b
Lint
ayjayt Aug 29, 2024
edb831f
Merge pull request #21 from geopozo/andrew/revision_connection
neyberson Aug 30, 2024
aa154af
Merge branch 'neyberson/connection' into neyberson/print_read_jsons
neyberson Aug 30, 2024
f91bdbe
Change vale to center string in run_output_thread()
neyberson Aug 30, 2024
fde1a50
Merge branch 'andrew/connection_restructure' into neyberson/print_rea…
neyberson Aug 30, 2024
c1256eb
Reorganize imports and format code in browser.py
neyberson Aug 30, 2024
8d5a4ea
Move run_output_thread() of browser.py to protocol.py
neyberson Aug 30, 2024
a4d5e11
Merge pull request #23 from geopozo/andrew/connection_restructure
neyberson Aug 30, 2024
c7937dc
Merge branch 'neyberson/connection' of github.com:geopozo/devtools_pr…
neyberson Aug 30, 2024
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
3 changes: 3 additions & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -7,3 +7,6 @@ __pycache__

# editor files
*.sw*

# ipynb
.ipynb_checkpoints/
39 changes: 29 additions & 10 deletions app/app.py
Original file line number Diff line number Diff line change
Expand Up @@ -6,17 +6,36 @@ def main():
# Interface Test
# Process/Pipes Test
with devtools.Browser(headless=False) as browser:
## Create Protocol
connection = browser.protocol
browser.send_command(command="Target.getTargets")
browser.protocol.pipe.read_jsons(debug=True)
browser.protocol.pipe.read_jsons(blocking=False, debug=True)
browser.protocol.pipe.read_jsons(blocking=False, debug=True)
browser.protocol.pipe.read_jsons(blocking=False, debug=True)
time.sleep(4)
browser.protocol.send_command(
command="Target.createTarget", params={"url": "https://www.youtube.com"}
)
time.sleep(5)
browser.protocol.send_command(command="Target.getTargets")
browser.protocol.pipe.read_jsons(debug=True)
browser.protocol.pipe.read_jsons(blocking=False, debug=True)
browser.protocol.pipe.read_jsons(blocking=False, debug=True)
browser.protocol.pipe.read_jsons(blocking=False, debug=True)
time.sleep(3)
browser.protocol.send_command(command="Target.getTargets")
browser.protocol.pipe.read_jsons(debug=True)
browser.protocol.pipe.read_jsons(blocking=False, debug=True)
browser.protocol.pipe.read_jsons(blocking=False, debug=True)
browser.protocol.pipe.read_jsons(blocking=False, debug=True)
time.sleep(3)
time.sleep(3)

connection.send_command(command="Target.createTarget", params={"url": "https://www.youtube.com/"})

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()


# blocking, regular blocking, you read and write, good luck (we need to be able to piece-meal the thing together)

# blocking with dumping out output off separate thread that you can see
# that one should probably be working with a queue
File renamed without changes.
110 changes: 83 additions & 27 deletions devtools/browser.py
Original file line number Diff line number Diff line change
@@ -1,35 +1,53 @@
from .pipe import Pipe
from .protocol import Protocol
import platform
import os
import sys
import subprocess
import signal
import tempfile
import warnings

from collections import OrderedDict

from .pipe import Pipe
from .protocol import Protocol
from .target import Target
from .session import Session
from .tab import Tab
from .system import which_browser

default_path = which_browser()


class Browser:
def __init__(self, debug=None, path=None, headless=True):
self.pipe = Pipe()
class Browser(Target):
def __init__(
self, path=default_path, headless=True, debug=False, debug_browser=None
):
if path is None:
raise ValueError("You must specify a path")

if not debug: # false o None
self.pipe = Pipe(debug=debug)
self.protocol = Protocol(self.pipe)
super().__init__("0", self.protocol) # TODO not sure about target id "0"
self.add_session(Session(self, ""))

if platform.system() != "Windows":
self.temp_dir = tempfile.TemporaryDirectory()
else:
self.temp_dir = tempfile.TemporaryDirectory(
delete=False, ignore_cleanup_errors=True
)

if not debug_browser: # false o None
stderr = subprocess.DEVNULL
elif debug is True:
elif debug_browser is True:
stderr = None
else:
stderr = debug

if not path:
if platform.system() == "Windows":
path = r"C:\Program Files\Google\Chrome\Application\chrome.exe"
elif platform.system() == "Linux":
path = "/usr/bin/google-chrome-stable"
else:
raise ValueError("You must set path to a chrome-like browser")

new_env = os.environ.copy()
new_env["CHROMIUM_PATH"] = path
new_env["CHROMIUM_PATH"] = str(path)
new_env["USER_DATA_DIR"] = str(self.temp_dir.name)
if headless:
new_env["HEADLESS"] = "--headless"
new_env["HEADLESS"] = "--headless" # unset if false

win_only = {}
if platform.system() == "Windows":
Expand All @@ -50,21 +68,59 @@ def __init__(self, debug=None, path=None, headless=True):
**win_only,
)
self.subprocess = proc
self.protocol = Protocol(self.pipe)
self.tabs = OrderedDict()

def __enter__(self):
return self

def __exit__(self, type, value, traceback):
return self.close_browser()
self.close()

def close_browser(self):
def close(self):
if platform.system() == "Windows":
self.subprocess.send_signal(signal.CTRL_BREAK_EVENT)
else:
self.subprocess.terminate()
self.subprocess.wait(5)
# maybe we don't need chrome_wrapper for windows because of how handles are needed
# if we're not chaining process, this might not be necessary
# otherwise, win behaves strangely in the face of signals, so call a command to kill the process instead
# NB: chrome accepts being killed like this because it knows windows is a nightmare
subprocess.call(
["taskkill", "/F", "/T", "/PID", str(self.subprocess.pid)]
) # this output should be handled better by where there is debug
self.subprocess.wait(2)
self.subprocess.terminate()
self.subprocess.wait(2)
self.subprocess.kill()
try:
self.temp_dir.cleanup()
except Exception as e: # TODO- handle specific errors
print(str(e))

# windows doesn't like python's default cleanup
if platform.system() == "Windows":
import stat
import shutil

def remove_readonly(func, path, excinfo):
os.chmod(path, stat.S_IWUSR)
func(path)

try:
shutil.rmtree(self.temp_dir.name, onexc=remove_readonly)
del self.temp_dir
except PermissionError:
warnings.warn(
"The temporary directory could not be deleted, but execution will continue."
)
except Exception:
warnings.warn(
"The temporary directory could not be deleted, but execution will continue."
)

def add_tab(self, tab):
if not isinstance(tab, Tab):
raise TypeError("tab must be an object of class Tab")
self.sessions[tab.target_id] = tab
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

el error mio pero debes cuidarlos tambien, no debe estar en self.sessions[] debe esta en self.tabs[]


def send_command(self, command, params=None, cb=None):
return self.protocol.send_command(self, command, params, cb)
def remove_session(self, target_id):
if isinstance(target_id, Tab):
target_id = target_id.target_id
del self.sessions[target_id]
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

mismo

24 changes: 15 additions & 9 deletions devtools/chrome_wrapper.py
Original file line number Diff line number Diff line change
Expand Up @@ -16,21 +16,27 @@
if system == "Windows":
import msvcrt # noqa

path = ""
if system == "Linux":
path = os.environ.get("BROWSER_PATH", "/usr/bin/google-chrome-stable")
elif system == "Windows":
path = os.environ.get(
"BROWSER_PATH", r"c:\Program Files\Google\Chrome\Application\chrome.exe"
)
else:
path = os.environ["CHROMIUM_PATH"]
default_paths = {
"Linux": "/usr/bin/google-chrome-stable",
"Windows": r"c:\Program Files\Google\Chrome\Application\chrome.exe",
}

path = os.environ.get(
"BROWSER_PATH", default_paths.get(system, os.environ.get("CHROMIUM_PATH"))
)

if path is None:
raise ValueError("You must specify a path")

user_data_dir = os.environ["USER_DATA_DIR"]

cli = [
path,
"--remote-debugging-pipe",
"--disable-breakpad",
"--allow-file-access-from-files",
f"--user-data-dir={user_data_dir}",
"--no-first-run",
]

if "HEADLESS" in os.environ:
Expand Down
41 changes: 23 additions & 18 deletions devtools/pipe.py
Original file line number Diff line number Diff line change
Expand Up @@ -2,50 +2,55 @@
import sys
import json


class PipeClosedError(IOError):
pass


class Pipe:
def __init__(self):
def __init__(self, debug=False):
self.read_from_chromium, self.write_from_chromium = list(os.pipe())
self.read_to_chromium, self.write_to_chromium = list(os.pipe())
self.debug = debug

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
# TODO: accept already formed object
def write_json(self, obj, debug=None):
if not debug: debug = self.debug
if debug:
print("write_json:", file=sys.stderr)

encoded_message = json.dumps(message).encode() + b"\0"
encoded_message = json.dumps(obj).encode("utf-8") + b"\0"

if debug:
print(f"write_json: {encoded_message}", file=sys.stderr)
# windows may print weird characters if we set utf-8 instead of utf-16
# check this TODO
os.write(self.write_to_chromium, encoded_message)

def read_jsons(self, blocking=True, debug=False):
def read_jsons(self, blocking=True, debug=None):
if not debug:
debug = self.debug
if debug:
print("Debug enabled", file=sys.stderr)
print(f"read_jsons ({'blocking' if blocking else 'not blocking'}):", file=sys.stderr)
jsons = []
os.set_blocking(self.read_from_chromium, blocking)
try:
raw_buffer = os.read(
self.read_from_chromium, 10000
) # 10MB buffer, nbd, doesn't matter w/ this
if not raw_buffer:
if debug: print("read_jsons pipe was closed")
raise PipeClosedError()
while raw_buffer[-1] != 0:
# still not great, return what you have
os.set_blocking(self.read_from_chromium, True)
raw_buffer += os.read(self.read_from_chromium, 10000)
except BlockingIOError:
if debug:
print("read_jsons: BlockingIOError caught.", file=sys.stderr)
return jsons
decoded_buffer = raw_buffer.decode("utf-8")
if debug:
print(raw_buffer, file=sys.stderr) # noqa
for raw_message in raw_buffer.decode("utf-8").split("\0"):
print(f"read_jsons: {decoded_buffer}", file=sys.stderr)
for raw_message in decoded_buffer.split("\0"):
if raw_message:
jsons.append(json.loads(raw_message))
return jsons
79 changes: 54 additions & 25 deletions devtools/protocol.py
Original file line number Diff line number Diff line change
@@ -1,33 +1,62 @@
from .tab import Tab
from .session import Session
from collections import OrderedDict
import json

from .pipe import PipeClosedError
from threading import Thread


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]
def write_json(self, obj):
n_keys = 0
if "id" in obj and "method" in obj:
n_keys += 2
else:
raise RuntimeError("Each message object must contain an id and method key")

if "params" in obj:
n_keys += 1
if "sessionId" in obj:
n_keys += 1

if len(obj.keys()) != n_keys:
raise RuntimeError(
"Message objects must have id and method keys, and may have params and sessionId keys"
)

self.pipe.write_json(obj)

def verify_response(self, response, session_id, message_id):
if "session_id" not in response and session_id == "":
pass
elif "session_id" in response and response["session_id"] == session_id:
pass
else:
del self.tabs[tab_id.target_id]
print(f"The following tab was deleted: {tab_id}")
return False

if "id" in response and str(response["id"]) == str(message_id):
pass
else:
return False

return True

def run_output_thread(self, debug=False):
print("Start run_output_thread() to improve debugging".center(6, "-"))
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

si vas a imprimir debug, debe estar a file=sys.stderr o lo que sea, y solo con debug=True


def run_print(debug):
while True:
try:
json_list = self.pipe.read_jsons(debug=debug)
if json_list:
for json_ in json_list:
print(json.dumps(json_, indent=4))
except PipeClosedError:
print("Pipe closed".center(10, "-"))
break

thread_print = Thread(target=run_print, args=(debug,))
thread_print.start()

def send_command(self, command, params=None, cb=None):
return self.browser_session.send_command(command, params, cb)
# we need to do something for errors
Loading