diff --git a/README.md b/README.md index 866020d..26eaa45 100644 --- a/README.md +++ b/README.md @@ -19,7 +19,7 @@ MagicMouse runs on all platforms that run Squeak and Chrome, but works best and - Right-click on images and code to transform them into `Morph`s. I call those "Portals". Because portals are cool. - Supercharged search bar: - If you type something with at least one space, your search terms are googled. - - If you start your search with `!s `, your search terms are used to search https://squeak.org. + - If you start your search with `!s`, your search terms are used to search . - `CTRL+L` toggles fullscreen. - Dropped texts are typed into form fields. - _browseIt_ any URL to open it in a browser. diff --git a/packages/MagicMouse-Core.package/MMBrowserMorph.class/class/parseImage.into..st b/packages/MagicMouse-Core.package/MMBrowserMorph.class/class/parseImage.into..st new file mode 100644 index 0000000..d13e59d --- /dev/null +++ b/packages/MagicMouse-Core.package/MMBrowserMorph.class/class/parseImage.into..st @@ -0,0 +1,26 @@ +accessing +parseImage: payload into: aMaybeUsedForm + + | format png form | + format := payload unsignedCharAt: 2. + format = $r + ifTrue: [ | width height | + width := payload unsignedLongAt: 3. + height := payload unsignedLongAt: 7. + png := payload copyFrom: 11 to: payload size. + form := Form extent: width @ height depth: 32. + 1 to: width * height - 1 do: [:index | + form bits + at: index + put: (png at: index * 4 + 3) asInteger << 0 + ((png at: index * 4 + 2) asInteger << 8) + ((png at: index * 4 + 1) asInteger << 16) + ((png at: index * 4 + 0) asInteger << 24)]] + ifFalse: [ | reader | + format caseOf: { + [$p] -> [ + reader := PNGReadWriter on: (payload copyFrom: 3 to: payload size) readStream. + form := reader nextImage]. + [$j] -> [ + reader := MMFastJPEGReader on: (payload readStream + skip: 2; + yourself). + form := reader nextImage: aMaybeUsedForm]}]. + ^ form \ No newline at end of file diff --git a/packages/MagicMouse-Core.package/MMBrowserMorph.class/instance/abandon.st b/packages/MagicMouse-Core.package/MMBrowserMorph.class/instance/abandon.st new file mode 100644 index 0000000..71a140a --- /dev/null +++ b/packages/MagicMouse-Core.package/MMBrowserMorph.class/instance/abandon.st @@ -0,0 +1,5 @@ +accessing +abandon + + self closeTab. + super abandon \ No newline at end of file diff --git a/packages/MagicMouse-Core.package/MMBrowserMorph.class/instance/changeLocation..st b/packages/MagicMouse-Core.package/MMBrowserMorph.class/instance/changeLocation..st index 3fd7ed0..0296c9e 100644 --- a/packages/MagicMouse-Core.package/MMBrowserMorph.class/instance/changeLocation..st +++ b/packages/MagicMouse-Core.package/MMBrowserMorph.class/instance/changeLocation..st @@ -2,4 +2,7 @@ public changeLocation: aUrl location := aUrl. - self sendCommand: $l withBuffer: aUrl asByteArray \ No newline at end of file + MMProcessWrapper getOSDependentSingleton + sendCommand: $l + withBuffer: aUrl asByteArray + for: self \ No newline at end of file diff --git a/packages/MagicMouse-Core.package/MMBrowserMorph.class/instance/closeTab.st b/packages/MagicMouse-Core.package/MMBrowserMorph.class/instance/closeTab.st new file mode 100644 index 0000000..317b1c3 --- /dev/null +++ b/packages/MagicMouse-Core.package/MMBrowserMorph.class/instance/closeTab.st @@ -0,0 +1,4 @@ +-> to chrome +closeTab + + self tabId ifNotNil: [MMProcessWrapper getOSDependentSingleton closeTab: self tabId] \ No newline at end of file diff --git a/packages/MagicMouse-Core.package/MMBrowserMorph.class/instance/connect..st b/packages/MagicMouse-Core.package/MMBrowserMorph.class/instance/connect..st index 0b3a6c0..e93ba85 100644 --- a/packages/MagicMouse-Core.package/MMBrowserMorph.class/instance/connect..st +++ b/packages/MagicMouse-Core.package/MMBrowserMorph.class/instance/connect..st @@ -1,38 +1,8 @@ connecting connect: aUrl - | path arguments | - process := MMProcessWrapper newForOS. - self class debugEnabled ifTrue: [process enableDebug]. - arguments := { - aUrl. - viewportSize x. - viewportSize y. - self class runChromeHeadless ifTrue: ['headless'] ifFalse: ['windowed']. - self class chromeProfilePath}. - self class doNotUsePrebuiltBinary - ifTrue: [ - self assertNodeScriptExists. - path := self class gitRepositoryPath, FileDirectory slash, 'run.js'. - process - startNodeScript: path - arguments: arguments - nodeArguments: (self class debugNodejs ifTrue: [{'--inspect'}] ifFalse: [{}])] - ifFalse: [ - path := (FileDirectory default / MMPluginDownloader filenameForCurrentPlatform) fullName. - process startCommand: path withArguments: arguments]. - - location := aUrl. - - imageUpdaterProcess := [ - [ | length command payload | - length := process stdoutNextUint32. - payload := process stdoutNextBuffer: length. - command := payload unsignedCharAt: 1. - command caseOf: { - [$i] -> [self updateImage: payload]. - [$h] -> [self handlePortal: payload]. - [$l] -> [self locationUpdated: payload]. - [$s] -> [self handleStructuredData: payload]. - [$g] -> [self handleGitClone: payload]. - [$f] -> [self handleFormFields: payload]}] repeat] fork \ No newline at end of file + self tabId: (MMProcessWrapper getOSDependentSingleton + lauchNewPageAt: aUrl + withExtend: self viewportSize x @ self viewportSize y + for: self). + location := aUrl \ No newline at end of file diff --git a/packages/MagicMouse-Core.package/MMBrowserMorph.class/instance/contentOfField.changedTo..st b/packages/MagicMouse-Core.package/MMBrowserMorph.class/instance/contentOfField.changedTo..st index 80f7b1c..642b53f 100644 --- a/packages/MagicMouse-Core.package/MMBrowserMorph.class/instance/contentOfField.changedTo..st +++ b/packages/MagicMouse-Core.package/MMBrowserMorph.class/instance/contentOfField.changedTo..st @@ -13,4 +13,7 @@ contentOfField: anId changedTo: text replaceFrom: 5 + id byteSize + 4 to: 5 + id byteSize + 4 + content byteSize - 1 with: content asByteArray. - self sendCommand: $t withBuffer: bytes \ No newline at end of file + MMProcessWrapper getOSDependentSingleton + sendCommand: $t + withBuffer: bytes + for: self \ No newline at end of file diff --git a/packages/MagicMouse-Core.package/MMBrowserMorph.class/instance/dispose.st b/packages/MagicMouse-Core.package/MMBrowserMorph.class/instance/dispose.st index a772069..bcc09e7 100644 --- a/packages/MagicMouse-Core.package/MMBrowserMorph.class/instance/dispose.st +++ b/packages/MagicMouse-Core.package/MMBrowserMorph.class/instance/dispose.st @@ -1,9 +1,7 @@ disconnecting dispose - process ifNotNil: [:p | - p terminate. - process := nil]. + self closeTab. imageUpdaterProcess ifNotNil: [:p | p terminate. imageUpdaterProcess := nil] \ No newline at end of file diff --git a/packages/MagicMouse-Core.package/MMBrowserMorph.class/instance/droppedDomainObject.at..st b/packages/MagicMouse-Core.package/MMBrowserMorph.class/instance/droppedDomainObject.at..st index 6ba9b2b..2f52f3a 100644 --- a/packages/MagicMouse-Core.package/MMBrowserMorph.class/instance/droppedDomainObject.at..st +++ b/packages/MagicMouse-Core.package/MMBrowserMorph.class/instance/droppedDomainObject.at..st @@ -7,4 +7,7 @@ droppedDomainObject: aDomainObject at: aPoint bytes signedLongAt: 1 put: aPoint x; signedLongAt: 5 put: aPoint y. - self sendCommand: $f withBuffer: bytes \ No newline at end of file + MMProcessWrapper getOSDependentSingleton + sendCommand: $f + withBuffer: bytes + for: self \ No newline at end of file diff --git a/packages/MagicMouse-Core.package/MMBrowserMorph.class/instance/droppedString.at..st b/packages/MagicMouse-Core.package/MMBrowserMorph.class/instance/droppedString.at..st index 3a42ab0..858e6a4 100644 --- a/packages/MagicMouse-Core.package/MMBrowserMorph.class/instance/droppedString.at..st +++ b/packages/MagicMouse-Core.package/MMBrowserMorph.class/instance/droppedString.at..st @@ -7,4 +7,7 @@ droppedString: aString at: aPoint bytes signedLongAt: 1 put: aPoint x; signedLongAt: 5 put: aPoint y. - self sendCommand: $s withBuffer: bytes, strBuffer \ No newline at end of file + MMProcessWrapper getOSDependentSingleton + sendCommand: $s + withBuffer: bytes, strBuffer + for: self \ No newline at end of file diff --git a/packages/MagicMouse-Core.package/MMBrowserMorph.class/instance/imageUpdaterProcess..st b/packages/MagicMouse-Core.package/MMBrowserMorph.class/instance/imageUpdaterProcess..st deleted file mode 100644 index 9e2decb..0000000 --- a/packages/MagicMouse-Core.package/MMBrowserMorph.class/instance/imageUpdaterProcess..st +++ /dev/null @@ -1,4 +0,0 @@ -accessing -imageUpdaterProcess: anObject - - imageUpdaterProcess := anObject \ No newline at end of file diff --git a/packages/MagicMouse-Core.package/MMBrowserMorph.class/instance/imageUpdaterProcess.st b/packages/MagicMouse-Core.package/MMBrowserMorph.class/instance/imageUpdaterProcess.st deleted file mode 100644 index 612eb6a..0000000 --- a/packages/MagicMouse-Core.package/MMBrowserMorph.class/instance/imageUpdaterProcess.st +++ /dev/null @@ -1,4 +0,0 @@ -accessing -imageUpdaterProcess - - ^ imageUpdaterProcess \ No newline at end of file diff --git a/packages/MagicMouse-Core.package/MMBrowserMorph.class/instance/initialize.st b/packages/MagicMouse-Core.package/MMBrowserMorph.class/instance/initialize.st index 15fe2df..5dc8473 100644 --- a/packages/MagicMouse-Core.package/MMBrowserMorph.class/instance/initialize.st +++ b/packages/MagicMouse-Core.package/MMBrowserMorph.class/instance/initialize.st @@ -8,4 +8,5 @@ initialize "Mark the image as opaque. Although we render PNGs, the browser should never send us an image of the webpage that includes transparency." self isOpaque: true. self image: self class logo. - self portalMorphs: Dictionary new \ No newline at end of file + self portalMorphs: Dictionary new. + self performedAutoResizing: true \ No newline at end of file diff --git a/packages/MagicMouse-Core.package/MMBrowserMorph.class/instance/isConnected.st b/packages/MagicMouse-Core.package/MMBrowserMorph.class/instance/isConnected.st index b866653..54cd61b 100644 --- a/packages/MagicMouse-Core.package/MMBrowserMorph.class/instance/isConnected.st +++ b/packages/MagicMouse-Core.package/MMBrowserMorph.class/instance/isConnected.st @@ -1,4 +1,4 @@ accessing isConnected - ^ process notNil \ No newline at end of file + ^ self tabId notNil \ No newline at end of file diff --git a/packages/MagicMouse-Core.package/MMBrowserMorph.class/instance/mouseWheel..st b/packages/MagicMouse-Core.package/MMBrowserMorph.class/instance/mouseWheel..st index 09f90e7..904e78f 100644 --- a/packages/MagicMouse-Core.package/MMBrowserMorph.class/instance/mouseWheel..st +++ b/packages/MagicMouse-Core.package/MMBrowserMorph.class/instance/mouseWheel..st @@ -1,4 +1,6 @@ events mouseWheel: anEvent - self sendEvent: #mouseWheel withNumber: (anEvent isWheelUp ifTrue: [0] ifFalse: [1]) \ No newline at end of file + | naturalScrollingDelta | + naturalScrollingDelta := anEvent wheelDelta x @ anEvent wheelDelta y negated. + self sendEvent: #mouseWheel withSignedPoint: naturalScrollingDelta \ No newline at end of file diff --git a/packages/MagicMouse-Core.package/MMBrowserMorph.class/instance/performedAutoResizing..st b/packages/MagicMouse-Core.package/MMBrowserMorph.class/instance/performedAutoResizing..st new file mode 100644 index 0000000..22baa2b --- /dev/null +++ b/packages/MagicMouse-Core.package/MMBrowserMorph.class/instance/performedAutoResizing..st @@ -0,0 +1,4 @@ +accessing +performedAutoResizing: aBoolean + + performedAutoResizing := aBoolean \ No newline at end of file diff --git a/packages/MagicMouse-Core.package/MMBrowserMorph.class/instance/performedAutoResizing.st b/packages/MagicMouse-Core.package/MMBrowserMorph.class/instance/performedAutoResizing.st new file mode 100644 index 0000000..91177a0 --- /dev/null +++ b/packages/MagicMouse-Core.package/MMBrowserMorph.class/instance/performedAutoResizing.st @@ -0,0 +1,4 @@ +accessing +performedAutoResizing + + ^ performedAutoResizing \ No newline at end of file diff --git a/packages/MagicMouse-Core.package/MMBrowserMorph.class/instance/sendCommand.withBuffer..st b/packages/MagicMouse-Core.package/MMBrowserMorph.class/instance/sendCommand.withBuffer..st deleted file mode 100644 index 1dcddf5..0000000 --- a/packages/MagicMouse-Core.package/MMBrowserMorph.class/instance/sendCommand.withBuffer..st +++ /dev/null @@ -1,7 +0,0 @@ --> to chrome -sendCommand: aCharacter withBuffer: aBuffer - - self process - stdinPutUint32: aBuffer size + 1; - stdinPutChar: aCharacter; - stdinPutBuffer: aBuffer asByteArray \ No newline at end of file diff --git a/packages/MagicMouse-Core.package/MMBrowserMorph.class/instance/sendEvent.withBuffer..st b/packages/MagicMouse-Core.package/MMBrowserMorph.class/instance/sendEvent.withBuffer..st index c289695..dbea7ab 100644 --- a/packages/MagicMouse-Core.package/MMBrowserMorph.class/instance/sendEvent.withBuffer..st +++ b/packages/MagicMouse-Core.package/MMBrowserMorph.class/instance/sendEvent.withBuffer..st @@ -1,8 +1,7 @@ -> to chrome sendEvent: anEventType withBuffer: aBuffer - self process - stdinPutUint32: aBuffer size + 2; - stdinPutChar: $e; - stdinPutUint8: (self eventTypeCode: anEventType); - stdinPutBuffer: aBuffer asByteArray \ No newline at end of file + MMProcessWrapper getOSDependentSingleton + sendEvent: (self eventTypeCode: anEventType) + withBuffer: aBuffer + for: self \ No newline at end of file diff --git a/packages/MagicMouse-Core.package/MMBrowserMorph.class/instance/sendEvent.withSignedPoint..st b/packages/MagicMouse-Core.package/MMBrowserMorph.class/instance/sendEvent.withSignedPoint..st new file mode 100644 index 0000000..1bb41c7 --- /dev/null +++ b/packages/MagicMouse-Core.package/MMBrowserMorph.class/instance/sendEvent.withSignedPoint..st @@ -0,0 +1,7 @@ +-> to chrome +sendEvent: anEventType withSignedPoint: aPoint + + self sendEvent: anEventType withBuffer: ((ByteArray new: 8) + signedLongAt: 1 put: aPoint x asInteger; + signedLongAt: 5 put: aPoint y asInteger; + yourself) \ No newline at end of file diff --git a/packages/MagicMouse-Core.package/MMBrowserMorph.class/instance/tabId..st b/packages/MagicMouse-Core.package/MMBrowserMorph.class/instance/tabId..st new file mode 100644 index 0000000..9943f21 --- /dev/null +++ b/packages/MagicMouse-Core.package/MMBrowserMorph.class/instance/tabId..st @@ -0,0 +1,4 @@ +accessing +tabId: anObject + + tabId := anObject \ No newline at end of file diff --git a/packages/MagicMouse-Core.package/MMBrowserMorph.class/instance/tabId.st b/packages/MagicMouse-Core.package/MMBrowserMorph.class/instance/tabId.st new file mode 100644 index 0000000..6400bf6 --- /dev/null +++ b/packages/MagicMouse-Core.package/MMBrowserMorph.class/instance/tabId.st @@ -0,0 +1,4 @@ +accessing +tabId + + ^ tabId \ No newline at end of file diff --git a/packages/MagicMouse-Core.package/MMBrowserMorph.class/instance/updateImage..st b/packages/MagicMouse-Core.package/MMBrowserMorph.class/instance/updateImage..st index dd406d1..eb124e6 100644 --- a/packages/MagicMouse-Core.package/MMBrowserMorph.class/instance/updateImage..st +++ b/packages/MagicMouse-Core.package/MMBrowserMorph.class/instance/updateImage..st @@ -1,28 +1,8 @@ <- from chrome updateImage: payload - | format png form | - format := payload unsignedCharAt: 2. - format = $r - ifTrue: [ | width height | - width := payload unsignedLongAt: 3. - height := payload unsignedLongAt: 7. - png := payload copyFrom: 11 to: payload size. - form := Form extent: width @ height depth: 32. - 1 to: width * height - 1 do: [:index | - form bits - at: index - put: (png at: index * 4 + 3) asInteger << 0 + ((png at: index * 4 + 2) asInteger << 8) + ((png at: index * 4 + 1) asInteger << 16) + ((png at: index * 4 + 0) asInteger << 24)]] - ifFalse: [ | reader | - format caseOf: { - [$p] -> [ - reader := PNGReadWriter on: (payload copyFrom: 3 to: payload size) readStream. - form := reader nextImage]. - [$j] -> [ - reader := MMFastJPEGReader on: (payload readStream - skip: 2; - yourself). - form := reader nextImage: self image]}]. + | form | + form := self class parseImage: payload into: self image. form extent > viewportSize ifTrue: ["We need to crop the incoming image if we don't run Chrome in headless mode or if we just resized the window and Chrome still sends us a bigger image than now requested." form := form contentsOfArea: (0 @ 0 extent: viewportSize)]. diff --git a/packages/MagicMouse-Core.package/MMBrowserMorph.class/methodProperties.json b/packages/MagicMouse-Core.package/MMBrowserMorph.class/methodProperties.json index 1dbd38f..dd814a5 100644 --- a/packages/MagicMouse-Core.package/MMBrowserMorph.class/methodProperties.json +++ b/packages/MagicMouse-Core.package/MMBrowserMorph.class/methodProperties.json @@ -1,92 +1,85 @@ { "class" : { - "chromeProfilePath" : "MB 1/30/2022 10:33", - "chromeProfilePath:" : "cmfcmf 11/11/2020 20:04", - "debugEnabled" : "MB 1/30/2022 10:33", - "debugEnabled:" : "cmfcmf 11/11/2020 19:53", - "debugNodejs" : "MB 1/30/2022 10:33", - "debugNodejs:" : "cmfcmf 11/11/2020 20:05", - "doNotUsePrebuiltBinary" : "MB 1/30/2022 10:33", - "doNotUsePrebuiltBinary:" : "cmfcmf 11/11/2020 20:05", - "gitRepositoryPath" : "MB 1/30/2022 10:33", - "gitRepositoryPath:" : "cmfcmf 11/11/2020 20:05", - "initialize" : "MB 1/30/2022 10:33", - "logo" : "MB 1/30/2022 10:33", + "initialize" : "MB 1/15/2022 13:17", + "logo" : "MB 1/15/2022 13:17", "open" : "cmfcmf 6/30/2019 13:11", "openOn:" : "cmfcmf 6/30/2019 13:11", - "portalsOnRightClick" : "MB 1/30/2022 10:33", + "parseImage:into:" : "MB 1/15/2022 20:10", + "portalsOnRightClick" : "MB 1/15/2022 13:17", "portalsOnRightClick:" : "cmfcmf 11/11/2020 20:05", - "runChromeHeadless" : "MB 1/30/2022 10:33", - "runChromeHeadless:" : "cmfcmf 11/11/2020 20:06", "shutDown:" : "cmfcmf 6/27/2019 10:20", - "startUp:" : "MB 1/30/2022 10:33", + "startUp:" : "MB 1/15/2022 13:17", "title" : "cmfcmf 6/30/2019 13:10" }, "instance" : { - "acceptDroppingMorph:event:" : "MB 1/30/2022 10:33", - "assertNodeScriptExists" : "MB 1/30/2022 10:33", - "changeLocation:" : "cmfcmf 6/19/2019 20:17", - "connect:" : "MB 1/30/2022 10:33", - "contentOfField:changedTo:" : "MB 1/30/2022 10:33", + "abandon" : "MB 5/26/2022 13:32", + "acceptDroppingMorph:event:" : "MB 1/15/2022 13:17", + "assertNodeScriptExists" : "MB 1/15/2022 13:17", + "changeLocation:" : "MB 1/15/2022 13:17", + "closeTab" : "MB 5/26/2022 13:32", + "connect:" : "MB 1/15/2022 18:31", + "contentOfField:changedTo:" : "MB 1/15/2022 13:17", "delete" : "cmfcmf 8/3/2019 19:16", - "dispose" : "MB 1/30/2022 10:33", + "dispose" : "MB 5/26/2022 13:32", "doRefresh" : "cmfcmf 7/2/2019 08:20", - "domainObjectFieldFor:object:" : "MB 1/30/2022 10:33", - "drawOn:" : "MB 1/30/2022 10:33", - "droppedDomainObject:at:" : "MB 1/30/2022 10:33", - "droppedString:at:" : "MB 1/30/2022 10:33", - "eventTypeCode:" : "MB 1/30/2022 10:33", - "extent:" : "MB 1/30/2022 10:33", - "fullscreen:" : "MB 1/30/2022 10:33", - "getIdAndRectFrom:startAt:" : "MB 1/30/2022 10:33", - "gitClone:named:" : "MB 1/30/2022 10:33", + "domainObjectFieldFor:object:" : "MB 1/15/2022 13:17", + "drawOn:" : "MB 1/15/2022 13:17", + "droppedDomainObject:at:" : "MB 1/15/2022 13:17", + "droppedString:at:" : "MB 1/15/2022 13:17", + "eventTypeCode:" : "MB 1/15/2022 13:17", + "extent:" : "MB 2/6/2022 17:07", + "fullscreen:" : "MB 1/15/2022 13:17", + "getIdAndRectFrom:startAt:" : "MB 1/15/2022 13:17", + "gitClone:named:" : "MB 1/15/2022 13:17", "goBack" : "cmfcmf 7/2/2019 08:21", "goForward" : "cmfcmf 7/2/2019 08:21", - "handleCodePortal:" : "MB 1/30/2022 10:33", - "handleFormFields:" : "MB 1/30/2022 10:33", - "handleGitClone:" : "MB 1/30/2022 10:33", - "handlePortal:" : "MB 1/30/2022 10:33", - "handlePortalImage:" : "MB 1/30/2022 10:33", - "handlePortalMorph:" : "MB 1/30/2022 10:33", - "handlePortalRefreshData:" : "MB 1/30/2022 10:33", + "handleCodePortal:" : "MB 1/15/2022 13:17", + "handleFormFields:" : "MB 1/15/2022 13:17", + "handleGitClone:" : "MB 1/15/2022 13:17", + "handlePortal:" : "MB 1/15/2022 13:17", + "handlePortalImage:" : "MB 1/15/2022 13:17", + "handlePortalMorph:" : "MB 1/15/2022 13:17", + "handlePortalRefreshData:" : "MB 1/15/2022 13:17", "handleStructuredData:" : "cmfcmf 8/3/2019 19:35", "handlesKeyboard:" : "cmfcmf 7/3/2019 09:15", "handlesMouseDown:" : "T 4/18/2019 20:02", "handlesMouseMove:" : "cf 4/22/2019 14:02", "handlesMouseWheel:" : "TB 4/19/2019 09:54", - "imageUpdaterProcess" : "cf 5/13/2019 15:43", - "imageUpdaterProcess:" : "MB 1/30/2022 10:33", - "initialize" : "MB 1/30/2022 10:33", + "initialize" : "MB 2/27/2022 16:13", "intoWorld:" : "cmfcmf 7/7/2019 11:03", - "isConnected" : "cmfcmf 7/3/2019 09:15", + "isConnected" : "MB 1/8/2022 17:40", "isFullscreen" : "cmfcmf 7/7/2019 19:03", "keyStroke:" : "cmfcmf 6/30/2019 14:24", "keyboardFocusColor" : "TB 4/19/2019 10:02", "location" : "cmfcmf 6/19/2019 20:18", "locationUpdated:" : "cmfcmf 7/8/2019 17:41", - "mouseDown:" : "MB 1/30/2022 10:33", - "mouseMove:" : "MB 1/30/2022 10:33", - "mouseUp:" : "MB 1/30/2022 10:33", - "mouseWheel:" : "cmfcmf 7/3/2019 09:16", + "mouseDown:" : "MB 1/15/2022 13:17", + "mouseMove:" : "MB 1/15/2022 13:17", + "mouseUp:" : "MB 1/15/2022 13:17", + "mouseWheel:" : "MB 2/6/2022 17:07", "movePortal:rect:" : "cf 5/13/2019 16:36", - "nameFromDomainObject:" : "MB 1/30/2022 10:33", + "nameFromDomainObject:" : "MB 1/15/2022 13:17", "outOfWorld:" : "cmfcmf 6/30/2019 11:37", + "performedAutoResizing" : "MB 2/27/2022 16:13", + "performedAutoResizing:" : "MB 2/27/2022 16:13", "portalMorphs" : "cf 5/13/2019 15:43", "portalMorphs:" : "cf 5/13/2019 15:43", - "possibleDomainObjectFieldsFor:" : "MB 1/30/2022 10:33", + "possibleDomainObjectFieldsFor:" : "MB 1/15/2022 13:17", "preferredExtent" : "T 4/18/2019 21:14", "process" : "cf 5/13/2019 15:43", - "process:" : "MB 1/30/2022 10:33", - "refreshPortals:" : "MB 1/30/2022 10:33", + "process:" : "MB 1/15/2022 13:17", + "refreshPortals:" : "MB 1/15/2022 13:17", "searchFor:" : "cmfcmf 8/3/2019 19:29", - "sendCommand:withBuffer:" : "MB 1/30/2022 10:33", "sendEvent:" : "cf 4/22/2019 22:32", - "sendEvent:withBuffer:" : "MB 1/30/2022 10:33", + "sendEvent:withBuffer:" : "MB 1/15/2022 13:17", "sendEvent:withNumber:" : "cf 4/22/2019 22:34", "sendEvent:withNumber:andNumber:" : "cf 4/22/2019 22:35", "sendEvent:withPoint:" : "cf 4/22/2019 22:35", + "sendEvent:withSignedPoint:" : "MB 2/6/2022 15:37", "sendEvent:withString:" : "cmfcmf 7/3/2019 09:17", - "updateImage:" : "MB 1/30/2022 10:33", - "urlFromDomainObject:" : "MB 1/30/2022 10:33", + "tabId" : "MB 1/15/2022 13:17", + "tabId:" : "MB 1/15/2022 13:17", + "updateImage:" : "MB 5/26/2022 14:44", + "urlFromDomainObject:" : "MB 1/15/2022 13:17", "viewportSize" : "cf 5/13/2019 15:43", - "viewportSize:" : "MB 1/30/2022 10:33", - "wantsDroppedMorph:event:" : "MB 1/30/2022 10:33" } } + "viewportSize:" : "MB 1/15/2022 13:17", + "wantsDroppedMorph:event:" : "MB 1/15/2022 13:17" } } diff --git a/packages/MagicMouse-Core.package/MMBrowserMorph.class/properties.json b/packages/MagicMouse-Core.package/MMBrowserMorph.class/properties.json index 5676d04..12816a5 100644 --- a/packages/MagicMouse-Core.package/MMBrowserMorph.class/properties.json +++ b/packages/MagicMouse-Core.package/MMBrowserMorph.class/properties.json @@ -13,13 +13,14 @@ "RunChromeHeadless" ], "commentStamp" : "cmfcmf 8/3/2019 19:11", "instvars" : [ - "process", + "tabId", "viewportSize", "imageUpdaterProcess", "portalMorphs", "location", "tmpDomainObject", - "previousOwner" ], + "previousOwner", + "performedAutoResizing" ], "name" : "MMBrowserMorph", "pools" : [ ], diff --git a/packages/MagicMouse-Core.package/MMBufferedStream.class/instance/initialize.st b/packages/MagicMouse-Core.package/MMBufferedStream.class/instance/initialize.st new file mode 100644 index 0000000..421be62 --- /dev/null +++ b/packages/MagicMouse-Core.package/MMBufferedStream.class/instance/initialize.st @@ -0,0 +1,5 @@ +properties-setting +initialize + + super initialize. + self throwTimeoutError: false \ No newline at end of file diff --git a/packages/MagicMouse-Core.package/MMBufferedStream.class/instance/throwTimeoutError..st b/packages/MagicMouse-Core.package/MMBufferedStream.class/instance/throwTimeoutError..st new file mode 100644 index 0000000..3029f1c --- /dev/null +++ b/packages/MagicMouse-Core.package/MMBufferedStream.class/instance/throwTimeoutError..st @@ -0,0 +1,4 @@ +accessing +throwTimeoutError: anObject + + throwTimeoutError := anObject \ No newline at end of file diff --git a/packages/MagicMouse-Core.package/MMBufferedStream.class/instance/throwTimeoutError.st b/packages/MagicMouse-Core.package/MMBufferedStream.class/instance/throwTimeoutError.st new file mode 100644 index 0000000..73b4029 --- /dev/null +++ b/packages/MagicMouse-Core.package/MMBufferedStream.class/instance/throwTimeoutError.st @@ -0,0 +1,5 @@ +accessing +throwTimeoutError + + throwTimeoutError ifNil: [throwTimeoutError := false]. + ^ throwTimeoutError \ No newline at end of file diff --git a/packages/MagicMouse-Core.package/MMBufferedStream.class/instance/waitForDataReady.st b/packages/MagicMouse-Core.package/MMBufferedStream.class/instance/waitForDataReady.st index 3adc55b..017153d 100644 --- a/packages/MagicMouse-Core.package/MMBufferedStream.class/instance/waitForDataReady.st +++ b/packages/MagicMouse-Core.package/MMBufferedStream.class/instance/waitForDataReady.st @@ -5,4 +5,7 @@ waitForDataReady self flag: #todo. " for some reason the browser stops working after some time when simply using 'self dataAvailableSemaphore wait'" - (self dataAvailableSemaphore waitTimeoutMSecs: 30000) ifTrue: [self error: 'Did not receive a frame in 30 seconds'] \ No newline at end of file + [true] whileTrue: [ + (self dataAvailableSemaphore waitTimeoutMSecs: 30000) + ifTrue: [self throwTimeoutError ifTrue: [self error: 'Did not receive a frame in 30 seconds']] + ifFalse: [^ self]] \ No newline at end of file diff --git a/packages/MagicMouse-Core.package/MMBufferedStream.class/methodProperties.json b/packages/MagicMouse-Core.package/MMBufferedStream.class/methodProperties.json index ea0e487..bf7b0ce 100644 --- a/packages/MagicMouse-Core.package/MMBufferedStream.class/methodProperties.json +++ b/packages/MagicMouse-Core.package/MMBufferedStream.class/methodProperties.json @@ -2,6 +2,9 @@ "class" : { }, "instance" : { - "binary" : "MB 1/30/2022 10:33", - "maxReadBufferSize" : "MB 1/30/2022 10:33", - "waitForDataReady" : "MB 1/30/2022 10:33" } } + "binary" : "MB 1/15/2022 13:17", + "initialize" : "MB 1/15/2022 13:17", + "maxReadBufferSize" : "MB 1/15/2022 13:17", + "throwTimeoutError" : "MB 12/1/2021 15:42", + "throwTimeoutError:" : "MB 1/15/2022 13:17", + "waitForDataReady" : "MB 5/26/2022 12:42" } } diff --git a/packages/MagicMouse-Core.package/MMBufferedStream.class/properties.json b/packages/MagicMouse-Core.package/MMBufferedStream.class/properties.json index f44e129..39486f7 100644 --- a/packages/MagicMouse-Core.package/MMBufferedStream.class/properties.json +++ b/packages/MagicMouse-Core.package/MMBufferedStream.class/properties.json @@ -6,7 +6,7 @@ ], "commentStamp" : "cmfcmf 8/3/2019 19:05", "instvars" : [ - ], + "throwTimeoutError" ], "name" : "MMBufferedStream", "pools" : [ ], diff --git a/packages/MagicMouse-Core.package/MMFastJPEGReader.class/methodProperties.json b/packages/MagicMouse-Core.package/MMFastJPEGReader.class/methodProperties.json index 2000521..6f2a6b4 100644 --- a/packages/MagicMouse-Core.package/MMFastJPEGReader.class/methodProperties.json +++ b/packages/MagicMouse-Core.package/MMFastJPEGReader.class/methodProperties.json @@ -2,5 +2,5 @@ "class" : { }, "instance" : { - "nextImage" : "MB 1/30/2022 10:33", - "nextImage:" : "MB 1/30/2022 10:33" } } + "nextImage" : "MB 1/15/2022 13:17", + "nextImage:" : "MB 1/15/2022 13:17" } } diff --git a/packages/MagicMouse-Core.package/MMPluginDownloader.class/class/download..st b/packages/MagicMouse-Core.package/MMPluginDownloader.class/class/download..st index ff74bd0..dda169b 100644 --- a/packages/MagicMouse-Core.package/MMPluginDownloader.class/class/download..st +++ b/packages/MagicMouse-Core.package/MMPluginDownloader.class/class/download..st @@ -3,7 +3,7 @@ download: aString UIManager default informUserDuring: [:bar | | document fileStream | bar value: 'Downloading plugin'. - document := ('https://github.com/cmfcmf/MagicMouse/releases/download/latest/', aString) asUrl retrieveContents. + document := ('https://dl.bintray.com/cmfcmf/MagicMouse/', aString) asUrl retrieveContents. bar value: 'Saving plugin'. fileStream := FileDirectory default fileNamed: aString. fileStream diff --git a/packages/MagicMouse-Core.package/MMPluginDownloader.class/methodProperties.json b/packages/MagicMouse-Core.package/MMPluginDownloader.class/methodProperties.json index e45d142..ea305f6 100644 --- a/packages/MagicMouse-Core.package/MMPluginDownloader.class/methodProperties.json +++ b/packages/MagicMouse-Core.package/MMPluginDownloader.class/methodProperties.json @@ -1,12 +1,12 @@ { "class" : { "download" : "cmfcmf 8/3/2019 16:21", - "download:" : "MB 1/30/2022 10:33", - "downloadForAllPlatforms" : "MB 1/30/2022 10:33", - "downloadIfConfirmed" : "MB 1/30/2022 10:33", - "downloadIfNeededAndConfirmed" : "MB 1/30/2022 10:33", - "filenameDict" : "MB 1/30/2022 10:33", + "download:" : "MB 1/15/2022 13:17", + "downloadForAllPlatforms" : "MB 1/15/2022 13:17", + "downloadIfConfirmed" : "MB 1/15/2022 13:17", + "downloadIfNeededAndConfirmed" : "MB 1/15/2022 13:17", + "filenameDict" : "MB 1/15/2022 13:17", "filenameForCurrentPlatform" : "cmfcmf 8/3/2019 16:23", - "removeDownloads" : "MB 1/30/2022 10:33" }, + "removeDownloads" : "MB 1/15/2022 13:17" }, "instance" : { } } diff --git a/packages/MagicMouse-Core.package/MMBrowserMorph.class/class/chromeProfilePath..st b/packages/MagicMouse-Core.package/MMProcessWrapper.class/class/chromeProfilePath..st similarity index 76% rename from packages/MagicMouse-Core.package/MMBrowserMorph.class/class/chromeProfilePath..st rename to packages/MagicMouse-Core.package/MMProcessWrapper.class/class/chromeProfilePath..st index 21d1390..dee9c30 100644 --- a/packages/MagicMouse-Core.package/MMBrowserMorph.class/class/chromeProfilePath..st +++ b/packages/MagicMouse-Core.package/MMProcessWrapper.class/class/chromeProfilePath..st @@ -1,4 +1,4 @@ -preferences +instance creation chromeProfilePath: aString ChromeProfilePath := aString \ No newline at end of file diff --git a/packages/MagicMouse-Core.package/MMBrowserMorph.class/class/chromeProfilePath.st b/packages/MagicMouse-Core.package/MMProcessWrapper.class/class/chromeProfilePath.st similarity index 94% rename from packages/MagicMouse-Core.package/MMBrowserMorph.class/class/chromeProfilePath.st rename to packages/MagicMouse-Core.package/MMProcessWrapper.class/class/chromeProfilePath.st index 892e1e0..de9f152 100644 --- a/packages/MagicMouse-Core.package/MMBrowserMorph.class/class/chromeProfilePath.st +++ b/packages/MagicMouse-Core.package/MMProcessWrapper.class/class/chromeProfilePath.st @@ -1,4 +1,4 @@ -preferences +instance creation chromeProfilePath diff --git a/packages/MagicMouse-Core.package/MMBrowserMorph.class/class/debugEnabled..st b/packages/MagicMouse-Core.package/MMProcessWrapper.class/class/debugEnabled..st similarity index 73% rename from packages/MagicMouse-Core.package/MMBrowserMorph.class/class/debugEnabled..st rename to packages/MagicMouse-Core.package/MMProcessWrapper.class/class/debugEnabled..st index dadc900..ca4c784 100644 --- a/packages/MagicMouse-Core.package/MMBrowserMorph.class/class/debugEnabled..st +++ b/packages/MagicMouse-Core.package/MMProcessWrapper.class/class/debugEnabled..st @@ -1,4 +1,4 @@ -preferences +instance creation debugEnabled: aBoolean DebugEnabled := aBoolean \ No newline at end of file diff --git a/packages/MagicMouse-Core.package/MMBrowserMorph.class/class/debugEnabled.st b/packages/MagicMouse-Core.package/MMProcessWrapper.class/class/debugEnabled.st similarity index 90% rename from packages/MagicMouse-Core.package/MMBrowserMorph.class/class/debugEnabled.st rename to packages/MagicMouse-Core.package/MMProcessWrapper.class/class/debugEnabled.st index d5cb0c9..7e8001e 100644 --- a/packages/MagicMouse-Core.package/MMBrowserMorph.class/class/debugEnabled.st +++ b/packages/MagicMouse-Core.package/MMProcessWrapper.class/class/debugEnabled.st @@ -1,4 +1,4 @@ -preferences +instance creation debugEnabled diff --git a/packages/MagicMouse-Core.package/MMBrowserMorph.class/class/debugNodejs..st b/packages/MagicMouse-Core.package/MMProcessWrapper.class/class/debugNodejs..st similarity index 72% rename from packages/MagicMouse-Core.package/MMBrowserMorph.class/class/debugNodejs..st rename to packages/MagicMouse-Core.package/MMProcessWrapper.class/class/debugNodejs..st index 9dac658..39d06b9 100644 --- a/packages/MagicMouse-Core.package/MMBrowserMorph.class/class/debugNodejs..st +++ b/packages/MagicMouse-Core.package/MMProcessWrapper.class/class/debugNodejs..st @@ -1,4 +1,4 @@ -preferences +instance creation debugNodejs: aBoolean DebugNodejs := aBoolean \ No newline at end of file diff --git a/packages/MagicMouse-Core.package/MMBrowserMorph.class/class/debugNodejs.st b/packages/MagicMouse-Core.package/MMProcessWrapper.class/class/debugNodejs.st similarity index 91% rename from packages/MagicMouse-Core.package/MMBrowserMorph.class/class/debugNodejs.st rename to packages/MagicMouse-Core.package/MMProcessWrapper.class/class/debugNodejs.st index 450c4fd..9f44945 100644 --- a/packages/MagicMouse-Core.package/MMBrowserMorph.class/class/debugNodejs.st +++ b/packages/MagicMouse-Core.package/MMProcessWrapper.class/class/debugNodejs.st @@ -1,4 +1,4 @@ -preferences +instance creation debugNodejs diff --git a/packages/MagicMouse-Core.package/MMBrowserMorph.class/class/doNotUsePrebuiltBinary..st b/packages/MagicMouse-Core.package/MMProcessWrapper.class/class/doNotUsePrebuiltBinary..st similarity index 79% rename from packages/MagicMouse-Core.package/MMBrowserMorph.class/class/doNotUsePrebuiltBinary..st rename to packages/MagicMouse-Core.package/MMProcessWrapper.class/class/doNotUsePrebuiltBinary..st index cd9df9e..184b8d5 100644 --- a/packages/MagicMouse-Core.package/MMBrowserMorph.class/class/doNotUsePrebuiltBinary..st +++ b/packages/MagicMouse-Core.package/MMProcessWrapper.class/class/doNotUsePrebuiltBinary..st @@ -1,4 +1,4 @@ -preferences +instance creation doNotUsePrebuiltBinary: aBoolean DoNotUsePrebuiltBinary := aBoolean \ No newline at end of file diff --git a/packages/MagicMouse-Core.package/MMBrowserMorph.class/class/doNotUsePrebuiltBinary.st b/packages/MagicMouse-Core.package/MMProcessWrapper.class/class/doNotUsePrebuiltBinary.st similarity index 93% rename from packages/MagicMouse-Core.package/MMBrowserMorph.class/class/doNotUsePrebuiltBinary.st rename to packages/MagicMouse-Core.package/MMProcessWrapper.class/class/doNotUsePrebuiltBinary.st index 30bcfb5..85dd291 100644 --- a/packages/MagicMouse-Core.package/MMBrowserMorph.class/class/doNotUsePrebuiltBinary.st +++ b/packages/MagicMouse-Core.package/MMProcessWrapper.class/class/doNotUsePrebuiltBinary.st @@ -1,4 +1,4 @@ -preferences +instance creation doNotUsePrebuiltBinary diff --git a/packages/MagicMouse-Core.package/MMProcessWrapper.class/class/getOSDependentSingleton.st b/packages/MagicMouse-Core.package/MMProcessWrapper.class/class/getOSDependentSingleton.st new file mode 100644 index 0000000..fc53f93 --- /dev/null +++ b/packages/MagicMouse-Core.package/MMProcessWrapper.class/class/getOSDependentSingleton.st @@ -0,0 +1,5 @@ +instance creation +getOSDependentSingleton + + OSDependentProcessSingleton ifNil: [self renewOSDependentSingleton]. + ^ OSDependentProcessSingleton \ No newline at end of file diff --git a/packages/MagicMouse-Core.package/MMBrowserMorph.class/class/gitRepositoryPath..st b/packages/MagicMouse-Core.package/MMProcessWrapper.class/class/gitRepositoryPath..st similarity index 76% rename from packages/MagicMouse-Core.package/MMBrowserMorph.class/class/gitRepositoryPath..st rename to packages/MagicMouse-Core.package/MMProcessWrapper.class/class/gitRepositoryPath..st index 27bc7cb..069abd9 100644 --- a/packages/MagicMouse-Core.package/MMBrowserMorph.class/class/gitRepositoryPath..st +++ b/packages/MagicMouse-Core.package/MMProcessWrapper.class/class/gitRepositoryPath..st @@ -1,4 +1,4 @@ -preferences +instance creation gitRepositoryPath: aString GitRepositoryPath := aString \ No newline at end of file diff --git a/packages/MagicMouse-Core.package/MMBrowserMorph.class/class/gitRepositoryPath.st b/packages/MagicMouse-Core.package/MMProcessWrapper.class/class/gitRepositoryPath.st similarity index 95% rename from packages/MagicMouse-Core.package/MMBrowserMorph.class/class/gitRepositoryPath.st rename to packages/MagicMouse-Core.package/MMProcessWrapper.class/class/gitRepositoryPath.st index 9de9cfb..19051c8 100644 --- a/packages/MagicMouse-Core.package/MMBrowserMorph.class/class/gitRepositoryPath.st +++ b/packages/MagicMouse-Core.package/MMProcessWrapper.class/class/gitRepositoryPath.st @@ -1,4 +1,4 @@ -preferences +instance creation gitRepositoryPath diff --git a/packages/MagicMouse-Core.package/MMProcessWrapper.class/class/newForOS.st b/packages/MagicMouse-Core.package/MMProcessWrapper.class/class/newForOS.st deleted file mode 100644 index 3967251..0000000 --- a/packages/MagicMouse-Core.package/MMProcessWrapper.class/class/newForOS.st +++ /dev/null @@ -1,11 +0,0 @@ -instance creation -newForOS - - ^ OSProcess isWindows - ifTrue: [ - "Smalltalk platformSubtype = 'X64' - ifTrue: [" - MMWindowsProcessWrapperFFI new - "] - ifFalse: [MMWindowsProcessWrapperPW new]"] - ifFalse: [MMUnixProcessWrapper new] \ No newline at end of file diff --git a/packages/MagicMouse-Core.package/MMProcessWrapper.class/class/renewOSDependentSingleton.st b/packages/MagicMouse-Core.package/MMProcessWrapper.class/class/renewOSDependentSingleton.st new file mode 100644 index 0000000..43422e4 --- /dev/null +++ b/packages/MagicMouse-Core.package/MMProcessWrapper.class/class/renewOSDependentSingleton.st @@ -0,0 +1,18 @@ +instance creation +renewOSDependentSingleton + + | currentSingleton | + currentSingleton := self getOSDependentSingleton. + currentSingleton isRunning: false. + currentSingleton process ifNotNil: [currentSingleton terminate]. + MMBrowserMorph allInstancesDo: [:inst | inst abandon]. + OSDependentProcessSingleton := OSProcess isWindows + ifTrue: [ + "Smalltalk platformSubtype = 'X64' + ifTrue: [" + MMWindowsProcessWrapperFFI new + "] + ifFalse: [MMWindowsProcessWrapperPW new]"] + ifFalse: [MMUnixProcessWrapper new]. + currentSingleton reactToNodeOutputProcess ifNotNil: [:process | process terminate]. + ^ OSDependentProcessSingleton \ No newline at end of file diff --git a/packages/MagicMouse-Core.package/MMBrowserMorph.class/class/runChromeHeadless..st b/packages/MagicMouse-Core.package/MMProcessWrapper.class/class/runChromeHeadless..st similarity index 76% rename from packages/MagicMouse-Core.package/MMBrowserMorph.class/class/runChromeHeadless..st rename to packages/MagicMouse-Core.package/MMProcessWrapper.class/class/runChromeHeadless..st index fd44728..72f7666 100644 --- a/packages/MagicMouse-Core.package/MMBrowserMorph.class/class/runChromeHeadless..st +++ b/packages/MagicMouse-Core.package/MMProcessWrapper.class/class/runChromeHeadless..st @@ -1,4 +1,4 @@ -preferences +instance creation runChromeHeadless: aBoolean RunChromeHeadless := aBoolean \ No newline at end of file diff --git a/packages/MagicMouse-Core.package/MMBrowserMorph.class/class/runChromeHeadless.st b/packages/MagicMouse-Core.package/MMProcessWrapper.class/class/runChromeHeadless.st similarity index 93% rename from packages/MagicMouse-Core.package/MMBrowserMorph.class/class/runChromeHeadless.st rename to packages/MagicMouse-Core.package/MMProcessWrapper.class/class/runChromeHeadless.st index 57d9a9a..5b4a163 100644 --- a/packages/MagicMouse-Core.package/MMBrowserMorph.class/class/runChromeHeadless.st +++ b/packages/MagicMouse-Core.package/MMProcessWrapper.class/class/runChromeHeadless.st @@ -1,4 +1,4 @@ -preferences +instance creation runChromeHeadless diff --git a/packages/MagicMouse-Core.package/MMProcessWrapper.class/class/shutDown..st b/packages/MagicMouse-Core.package/MMProcessWrapper.class/class/shutDown..st new file mode 100644 index 0000000..cb77264 --- /dev/null +++ b/packages/MagicMouse-Core.package/MMProcessWrapper.class/class/shutDown..st @@ -0,0 +1,12 @@ +instance creation +shutDown: ignored + + | currentSingleton | + currentSingleton := self getOSDependentSingleton. + currentSingleton isRunning: false. + currentSingleton process ifNotNil: [currentSingleton terminate]. + self renewOSDependentSingleton. + currentSingleton reactToNodeOutputProcess ifNotNil: [:process | process terminate]. + Transcript showln: 'killed browser wrapper'. + + super shutDown: ignored \ No newline at end of file diff --git a/packages/MagicMouse-Core.package/MMProcessWrapper.class/class/startUp..st b/packages/MagicMouse-Core.package/MMProcessWrapper.class/class/startUp..st new file mode 100644 index 0000000..a07839d --- /dev/null +++ b/packages/MagicMouse-Core.package/MMProcessWrapper.class/class/startUp..st @@ -0,0 +1,5 @@ +instance creation +startUp: resuming + + super startUp: resuming. + self renewOSDependentSingleton \ No newline at end of file diff --git a/packages/MagicMouse-Core.package/MMProcessWrapper.class/instance/browserMorphMapping..st b/packages/MagicMouse-Core.package/MMProcessWrapper.class/instance/browserMorphMapping..st new file mode 100644 index 0000000..88a73df --- /dev/null +++ b/packages/MagicMouse-Core.package/MMProcessWrapper.class/instance/browserMorphMapping..st @@ -0,0 +1,4 @@ +accessing +browserMorphMapping: anObject + + browserMorphMapping := anObject \ No newline at end of file diff --git a/packages/MagicMouse-Core.package/MMProcessWrapper.class/instance/browserMorphMapping.st b/packages/MagicMouse-Core.package/MMProcessWrapper.class/instance/browserMorphMapping.st new file mode 100644 index 0000000..9dea9eb --- /dev/null +++ b/packages/MagicMouse-Core.package/MMProcessWrapper.class/instance/browserMorphMapping.st @@ -0,0 +1,4 @@ +accessing +browserMorphMapping + + ^ browserMorphMapping \ No newline at end of file diff --git a/packages/MagicMouse-Core.package/MMProcessWrapper.class/instance/closeTab..st b/packages/MagicMouse-Core.package/MMProcessWrapper.class/instance/closeTab..st new file mode 100644 index 0000000..0850a54 --- /dev/null +++ b/packages/MagicMouse-Core.package/MMProcessWrapper.class/instance/closeTab..st @@ -0,0 +1,10 @@ +stdin +closeTab: aNumber + + (self browserMorphMapping includesKey: aNumber) ifFalse: [^ nil]. + self isRunning ifTrue: [self sendCommand: $k withBuffer: '' asByteArray withId: aNumber]. + self browserMorphMapping removeKey: aNumber ifAbsent: []. + Transcript showln: 'Closed Browser with tabId: ', aNumber asString. + self browserMorphMapping isEmpty ifTrue: [ + Transcript showln: 'All Browser tabs should be closed. Killing Chrome ...'. + self class renewOSDependentSingleton] \ No newline at end of file diff --git a/packages/MagicMouse-Core.package/MMProcessWrapper.class/instance/getTabIdOf..st b/packages/MagicMouse-Core.package/MMProcessWrapper.class/instance/getTabIdOf..st new file mode 100644 index 0000000..0e3ae48 --- /dev/null +++ b/packages/MagicMouse-Core.package/MMProcessWrapper.class/instance/getTabIdOf..st @@ -0,0 +1,5 @@ +accessing +getTabIdOf: aMMBrowserMorph + + self browserMorphMapping keysAndValuesDo: [:tabId :aMMBrowserMorphInstance | aMMBrowserMorphInstance = aMMBrowserMorph ifTrue: [^ tabId]]. + Error signal: 'Given browser moprh is not registered for this process wrapper.' \ No newline at end of file diff --git a/packages/MagicMouse-Core.package/MMProcessWrapper.class/instance/initialize.st b/packages/MagicMouse-Core.package/MMProcessWrapper.class/instance/initialize.st index b9db7e4..3b624b7 100644 --- a/packages/MagicMouse-Core.package/MMProcessWrapper.class/instance/initialize.st +++ b/packages/MagicMouse-Core.package/MMProcessWrapper.class/instance/initialize.st @@ -2,4 +2,6 @@ initialize-release initialize super initialize. - debug := false \ No newline at end of file + debug := self class debugEnabled. + self isRunning: false. + self browserMorphMapping: Dictionary new \ No newline at end of file diff --git a/packages/MagicMouse-Core.package/MMProcessWrapper.class/instance/isRunning..st b/packages/MagicMouse-Core.package/MMProcessWrapper.class/instance/isRunning..st new file mode 100644 index 0000000..08e10c5 --- /dev/null +++ b/packages/MagicMouse-Core.package/MMProcessWrapper.class/instance/isRunning..st @@ -0,0 +1,4 @@ +accessing +isRunning: anObject + + isRunning := anObject \ No newline at end of file diff --git a/packages/MagicMouse-Core.package/MMProcessWrapper.class/instance/isRunning.st b/packages/MagicMouse-Core.package/MMProcessWrapper.class/instance/isRunning.st new file mode 100644 index 0000000..a50438a --- /dev/null +++ b/packages/MagicMouse-Core.package/MMProcessWrapper.class/instance/isRunning.st @@ -0,0 +1,4 @@ +accessing +isRunning + + ^ isRunning \ No newline at end of file diff --git a/packages/MagicMouse-Core.package/MMProcessWrapper.class/instance/lauchNewPageAt.withExtend.for..st b/packages/MagicMouse-Core.package/MMProcessWrapper.class/instance/lauchNewPageAt.withExtend.for..st new file mode 100644 index 0000000..0c52178 --- /dev/null +++ b/packages/MagicMouse-Core.package/MMProcessWrapper.class/instance/lauchNewPageAt.withExtend.for..st @@ -0,0 +1,6 @@ +stdin +lauchNewPageAt: aUrl withExtend: aPoint for: aMMBrowserMorph + + self isRunning + ifTrue: [^ self openNewTabAt: aUrl withExtend: aPoint for: aMMBrowserMorph] + ifFalse: [^ self startProcessWithLocation: aUrl withExtend: aPoint for: aMMBrowserMorph] \ No newline at end of file diff --git a/packages/MagicMouse-Core.package/MMProcessWrapper.class/instance/openNewTabAt.withExtend.for..st b/packages/MagicMouse-Core.package/MMProcessWrapper.class/instance/openNewTabAt.withExtend.for..st new file mode 100644 index 0000000..33e41ab --- /dev/null +++ b/packages/MagicMouse-Core.package/MMProcessWrapper.class/instance/openNewTabAt.withExtend.for..st @@ -0,0 +1,18 @@ +stdin +openNewTabAt: aUrl withExtend: aPoint for: aMMbrowserMorph + + | newTabId buffer | + newTabId := self browserMorphMapping keys + ifEmpty: [0] + ifNotEmpty: [:keys | keys max + 1]. + Transcript showln: 'opening new tab for id: ', newTabId. + buffer := aUrl asByteArray. + self + stdinPutUint32: buffer size + 1 + (2 * 4); + stdinPutUint32: newTabId; + stdinPutChar: $n; + stdinPutUint32: aPoint x; + stdinPutUint32: aPoint y; + stdinPutBuffer: buffer asByteArray. + self browserMorphMapping at: newTabId put: aMMbrowserMorph. + ^ newTabId \ No newline at end of file diff --git a/packages/MagicMouse-Core.package/MMProcessWrapper.class/instance/reactToNodeOutputProcess..st b/packages/MagicMouse-Core.package/MMProcessWrapper.class/instance/reactToNodeOutputProcess..st new file mode 100644 index 0000000..4f4a324 --- /dev/null +++ b/packages/MagicMouse-Core.package/MMProcessWrapper.class/instance/reactToNodeOutputProcess..st @@ -0,0 +1,4 @@ +accessing +reactToNodeOutputProcess: aProcess + + reactToNodeOutputProcess := aProcess \ No newline at end of file diff --git a/packages/MagicMouse-Core.package/MMProcessWrapper.class/instance/reactToNodeOutputProcess.st b/packages/MagicMouse-Core.package/MMProcessWrapper.class/instance/reactToNodeOutputProcess.st new file mode 100644 index 0000000..72b7f20 --- /dev/null +++ b/packages/MagicMouse-Core.package/MMProcessWrapper.class/instance/reactToNodeOutputProcess.st @@ -0,0 +1,4 @@ +accessing +reactToNodeOutputProcess + + ^ reactToNodeOutputProcess \ No newline at end of file diff --git a/packages/MagicMouse-Core.package/MMProcessWrapper.class/instance/sendCommand.withBuffer.for..st b/packages/MagicMouse-Core.package/MMProcessWrapper.class/instance/sendCommand.withBuffer.for..st new file mode 100644 index 0000000..843edf1 --- /dev/null +++ b/packages/MagicMouse-Core.package/MMProcessWrapper.class/instance/sendCommand.withBuffer.for..st @@ -0,0 +1,6 @@ +accessing +sendCommand: aCharacter withBuffer: aBuffer for: aMMBrowserMorph + + | tabId | + tabId := self getTabIdOf: aMMBrowserMorph. + self sendCommand: aCharacter withBuffer: aBuffer withId: tabId \ No newline at end of file diff --git a/packages/MagicMouse-Core.package/MMProcessWrapper.class/instance/sendCommand.withBuffer.withId..st b/packages/MagicMouse-Core.package/MMProcessWrapper.class/instance/sendCommand.withBuffer.withId..st new file mode 100644 index 0000000..30d4810 --- /dev/null +++ b/packages/MagicMouse-Core.package/MMProcessWrapper.class/instance/sendCommand.withBuffer.withId..st @@ -0,0 +1,8 @@ +accessing +sendCommand: aCharacter withBuffer: aBuffer withId: aNumber + + self + stdinPutUint32: aBuffer size + 1; + stdinPutUint32: aNumber; + stdinPutChar: aCharacter; + stdinPutBuffer: aBuffer asByteArray \ No newline at end of file diff --git a/packages/MagicMouse-Core.package/MMProcessWrapper.class/instance/sendEvent.withBuffer.for..st b/packages/MagicMouse-Core.package/MMProcessWrapper.class/instance/sendEvent.withBuffer.for..st new file mode 100644 index 0000000..7a55b2b --- /dev/null +++ b/packages/MagicMouse-Core.package/MMProcessWrapper.class/instance/sendEvent.withBuffer.for..st @@ -0,0 +1,12 @@ +accessing +sendEvent: eventTypeCode withBuffer: aBuffer for: aMMBrowserMorph + + | tabId | + tabId := self getTabIdOf: aMMBrowserMorph. + + self + stdinPutUint32: aBuffer size + 2; + stdinPutUint32: tabId; + stdinPutChar: $e; + stdinPutUint8: eventTypeCode; + stdinPutBuffer: aBuffer asByteArray \ No newline at end of file diff --git a/packages/MagicMouse-Core.package/MMProcessWrapper.class/instance/startNodeScript.arguments.nodeArguments..st b/packages/MagicMouse-Core.package/MMProcessWrapper.class/instance/startNodeScript.arguments.nodeArguments..st deleted file mode 100644 index 8722538..0000000 --- a/packages/MagicMouse-Core.package/MMProcessWrapper.class/instance/startNodeScript.arguments.nodeArguments..st +++ /dev/null @@ -1,6 +0,0 @@ -starting -startNodeScript: aString arguments: arguments nodeArguments: nodeArguments - - | node | - node := OSProcess isWindows ifTrue: ['node'] ifFalse: ['/usr/bin/node']. - self startCommand: node withArguments: nodeArguments, {aString. '--'}, arguments \ No newline at end of file diff --git a/packages/MagicMouse-Core.package/MMProcessWrapper.class/instance/startProcessWithLocation.withExtend.for..st b/packages/MagicMouse-Core.package/MMProcessWrapper.class/instance/startProcessWithLocation.withExtend.for..st new file mode 100644 index 0000000..07affc8 --- /dev/null +++ b/packages/MagicMouse-Core.package/MMProcessWrapper.class/instance/startProcessWithLocation.withExtend.for..st @@ -0,0 +1,46 @@ +stdin +startProcessWithLocation: aUrl withExtend: aPoint for: aMMBrowserMorph + + | binaryToExecutePath runJSPath arguments | + self class doNotUsePrebuiltBinary + ifTrue: [ + runJSPath := self class gitRepositoryPath, FileDirectory slash, 'run.js'. + binaryToExecutePath := OSProcess isWindows + ifTrue: ['node'] + ifFalse: [OSProcess isUnixMac ifTrue: ['/usr/local/bin/node'] ifFalse: ['/usr/bin/node']]] + ifFalse: [binaryToExecutePath := (FileDirectory default / MMPluginDownloader filenameForCurrentPlatform) fullName]. + arguments := self class debugNodejs + ifTrue: [{'--inspect'. runJSPath. '--'}] + ifFalse: [{}]. + arguments := arguments, { + aUrl. + aPoint x. + aPoint y. + self class runChromeHeadless ifTrue: ['headless'] ifFalse: ['windowed']. + self class chromeProfilePath}. + self startCommand: binaryToExecutePath withArguments: arguments. + self browserMorphMapping at: 0 put: aMMBrowserMorph. + + self reactToNodeOutputProcess: [ + [ | length tabId command payload browserInstance | + length := self stdoutNextUint32. + tabId := self stdoutNextUint32. + payload := self stdoutNextBuffer: length. + command := payload unsignedCharAt: 1. + + browserInstance := self browserMorphMapping at: tabId ifAbsent: [ + Transcript showln: 'Received data for unregeistered browser morph. Closing this tab. Id is ', tabId. + self closeTab: tabId. nil]. + browserInstance ifNotNil: [ + command caseOf: { + [$i] -> [browserInstance updateImage: payload]. + [$h] -> [browserInstance handlePortal: payload]. + [$l] -> [browserInstance locationUpdated: payload]. + [$s] -> [browserInstance handleStructuredData: payload]. + [$g] -> [browserInstance handleGitClone: payload]. + [$f] -> [browserInstance handleFormFields: payload]. + [$.] -> ["This is a filling event to force a flush of the std out of the nodejs script. We ignore this." + ]}]] repeat] fork. + + self isRunning: true. + ^ 0 \ No newline at end of file diff --git a/packages/MagicMouse-Core.package/MMProcessWrapper.class/instance/takeScreenshotAt.withExtend.for..st b/packages/MagicMouse-Core.package/MMProcessWrapper.class/instance/takeScreenshotAt.withExtend.for..st new file mode 100644 index 0000000..c4371e0 --- /dev/null +++ b/packages/MagicMouse-Core.package/MMProcessWrapper.class/instance/takeScreenshotAt.withExtend.for..st @@ -0,0 +1,18 @@ +stdin +takeScreenshotAt: aUrl withExtend: aPoint for: aMMbrowserMorph + + | newTabId buffer | + newTabId := self browserMorphMapping keys + ifEmpty: [0] + ifNotEmpty: [:keys | keys max + 1]. + Transcript showln: 'opening new tab for id: ', newTabId. + buffer := aUrl asByteArray. + self + stdinPutUint32: buffer size + 1 + (2 * 4); + stdinPutUint32: newTabId; + stdinPutChar: $i; + stdinPutUint32: aPoint x; + stdinPutUint32: aPoint y; + stdinPutBuffer: buffer asByteArray. + self browserMorphMapping at: newTabId put: aMMbrowserMorph. + ^ newTabId \ No newline at end of file diff --git a/packages/MagicMouse-Core.package/MMProcessWrapper.class/instance/throwsTimeoutError..st b/packages/MagicMouse-Core.package/MMProcessWrapper.class/instance/throwsTimeoutError..st new file mode 100644 index 0000000..b2548da --- /dev/null +++ b/packages/MagicMouse-Core.package/MMProcessWrapper.class/instance/throwsTimeoutError..st @@ -0,0 +1,4 @@ +stopping +throwsTimeoutError: aBoolean + + throwsTimeoutError := aBoolean \ No newline at end of file diff --git a/packages/MagicMouse-Core.package/MMProcessWrapper.class/instance/throwsTimeoutError.st b/packages/MagicMouse-Core.package/MMProcessWrapper.class/instance/throwsTimeoutError.st new file mode 100644 index 0000000..f4c633d --- /dev/null +++ b/packages/MagicMouse-Core.package/MMProcessWrapper.class/instance/throwsTimeoutError.st @@ -0,0 +1,4 @@ +stopping +throwsTimeoutError + + ^ throwsTimeoutError \ No newline at end of file diff --git a/packages/MagicMouse-Core.package/MMProcessWrapper.class/methodProperties.json b/packages/MagicMouse-Core.package/MMProcessWrapper.class/methodProperties.json index f9c88c9..07fbbfb 100644 --- a/packages/MagicMouse-Core.package/MMProcessWrapper.class/methodProperties.json +++ b/packages/MagicMouse-Core.package/MMProcessWrapper.class/methodProperties.json @@ -1,14 +1,42 @@ { "class" : { - "newForOS" : "MB 1/30/2022 10:33" }, + "chromeProfilePath" : "MB 1/15/2022 13:17", + "chromeProfilePath:" : "MB 12/12/2021 19:04", + "debugEnabled" : "MB 1/15/2022 13:17", + "debugEnabled:" : "MB 12/12/2021 19:05", + "debugNodejs" : "MB 1/15/2022 13:17", + "debugNodejs:" : "MB 12/12/2021 19:05", + "doNotUsePrebuiltBinary" : "MB 1/15/2022 13:17", + "doNotUsePrebuiltBinary:" : "MB 12/12/2021 19:06", + "getOSDependentSingleton" : "MB 1/2/2022 16:34", + "gitRepositoryPath" : "MB 1/15/2022 13:17", + "gitRepositoryPath:" : "MB 12/12/2021 19:19", + "renewOSDependentSingleton" : "MB 5/26/2022 13:35", + "runChromeHeadless" : "MB 1/15/2022 13:17", + "runChromeHeadless:" : "MB 12/12/2021 19:20", + "shutDown:" : "MB 2/27/2022 16:13", + "startUp:" : "MB 2/27/2022 16:13" }, "instance" : { + "browserMorphMapping" : "MB 1/15/2022 13:17", + "browserMorphMapping:" : "MB 1/15/2022 13:17", + "closeTab:" : "MB 5/26/2022 13:44", "disableDebug" : "cmfcmf 8/3/2019 19:00", - "enableDebug" : "MB 1/30/2022 10:33", - "initialize" : "cmfcmf 8/3/2019 19:00", + "enableDebug" : "MB 1/15/2022 13:17", + "getTabIdOf:" : "MB 2/5/2022 21:53", + "initialize" : "MB 1/15/2022 13:17", + "isRunning" : "MB 1/15/2022 13:17", + "isRunning:" : "MB 1/15/2022 13:17", + "lauchNewPageAt:withExtend:for:" : "MB 1/15/2022 13:17", + "openNewTabAt:withExtend:for:" : "MB 1/15/2022 13:17", "process" : "cmfcmf 8/3/2019 19:00", "process:" : "cmfcmf 8/3/2019 19:00", + "reactToNodeOutputProcess" : "MB 1/15/2022 13:17", + "reactToNodeOutputProcess:" : "MB 1/15/2022 13:17", + "sendCommand:withBuffer:for:" : "MB 1/15/2022 13:17", + "sendCommand:withBuffer:withId:" : "MB 1/15/2022 13:17", + "sendEvent:withBuffer:for:" : "MB 1/15/2022 13:17", "startCommand:withArguments:" : "cmfcmf 8/3/2019 19:00", - "startNodeScript:arguments:nodeArguments:" : "MB 1/30/2022 10:33", + "startProcessWithLocation:withExtend:for:" : "MB 5/26/2022 13:43", "stdinPutBuffer:" : "cmfcmf 8/3/2019 19:00", "stdinPutChar:" : "cmfcmf 8/3/2019 19:00", "stdinPutUint32:" : "cmfcmf 8/3/2019 19:00", @@ -17,4 +45,7 @@ "stdoutNextChar" : "cmfcmf 8/3/2019 19:00", "stdoutNextUint32" : "cmfcmf 8/3/2019 19:00", "stdoutNextUint8" : "cmfcmf 8/3/2019 19:00", - "terminate" : "cmfcmf 8/3/2019 19:00" } } + "takeScreenshotAt:withExtend:for:" : "MB 1/15/2022 19:43", + "terminate" : "cmfcmf 8/3/2019 19:00", + "throwsTimeoutError" : "MB 11/27/2021 18:27", + "throwsTimeoutError:" : "MB 11/27/2021 18:27" } } diff --git a/packages/MagicMouse-Core.package/MMProcessWrapper.class/properties.json b/packages/MagicMouse-Core.package/MMProcessWrapper.class/properties.json index 365aebb..610cd9c 100644 --- a/packages/MagicMouse-Core.package/MMProcessWrapper.class/properties.json +++ b/packages/MagicMouse-Core.package/MMProcessWrapper.class/properties.json @@ -3,11 +3,21 @@ "classinstvars" : [ ], "classvars" : [ - ], + "ChromeProfilePath", + "DebugEnabled", + "DebugNodejs", + "DoNotUsePrebuiltBinary", + "GitRepositoryPath", + "OSDependentProcessSingleton", + "RunChromeHeadless" ], "commentStamp" : "cmfcmf 8/3/2019 18:59", "instvars" : [ "process", - "debug" ], + "debug", + "throwsTimeoutError", + "isRunning", + "reactToNodeOutputProcess", + "browserMorphMapping" ], "name" : "MMProcessWrapper", "pools" : [ ], diff --git a/packages/MagicMouse-Core.package/MMUnixProcessWrapper.class/instance/debugLoggingProcess..st b/packages/MagicMouse-Core.package/MMUnixProcessWrapper.class/instance/debugLoggingProcess..st new file mode 100644 index 0000000..af24659 --- /dev/null +++ b/packages/MagicMouse-Core.package/MMUnixProcessWrapper.class/instance/debugLoggingProcess..st @@ -0,0 +1,4 @@ +accessing +debugLoggingProcess: anObject + + debugLoggingProcess := anObject \ No newline at end of file diff --git a/packages/MagicMouse-Core.package/MMUnixProcessWrapper.class/instance/debugLoggingProcess.st b/packages/MagicMouse-Core.package/MMUnixProcessWrapper.class/instance/debugLoggingProcess.st new file mode 100644 index 0000000..866cd78 --- /dev/null +++ b/packages/MagicMouse-Core.package/MMUnixProcessWrapper.class/instance/debugLoggingProcess.st @@ -0,0 +1,4 @@ +accessing +debugLoggingProcess + + ^ debugLoggingProcess \ No newline at end of file diff --git a/packages/MagicMouse-Core.package/MMUnixProcessWrapper.class/instance/startCommand.withArguments..st b/packages/MagicMouse-Core.package/MMUnixProcessWrapper.class/instance/startCommand.withArguments..st index 391966f..376ed8a 100644 --- a/packages/MagicMouse-Core.package/MMUnixProcessWrapper.class/instance/startCommand.withArguments..st +++ b/packages/MagicMouse-Core.package/MMUnixProcessWrapper.class/instance/startCommand.withArguments..st @@ -21,14 +21,16 @@ startCommand: command withArguments: arguments stdoutReader := outPipe reader asMMBufferedStream. stdoutReader setBlocking; + throwTimeoutError: self throwsTimeoutError; binary. - debug ifTrue: [ | stderrReader | + debug ifTrue: [ | stderrReader process | Transcript clear. stderrReader := errPipe reader. stderrReader ascii. - [ + process := [ [stderrReader closed] whileFalse: [ stderrReader next ifNil: [(Delay forSeconds: 1) wait] - ifNotNil: [:next | Transcript show: next]]] fork] \ No newline at end of file + ifNotNil: [:next | Transcript show: next]]] fork. + self debugLoggingProcess: process] \ No newline at end of file diff --git a/packages/MagicMouse-Core.package/MMUnixProcessWrapper.class/instance/terminate.st b/packages/MagicMouse-Core.package/MMUnixProcessWrapper.class/instance/terminate.st index b4c635f..96e9117 100644 --- a/packages/MagicMouse-Core.package/MMUnixProcessWrapper.class/instance/terminate.st +++ b/packages/MagicMouse-Core.package/MMUnixProcessWrapper.class/instance/terminate.st @@ -1,6 +1,8 @@ stopping terminate + self debugLoggingProcess ifNotNil: [:process | process terminate]. + Transcript showln: 'Killed debug logging process'. self process closeStreams; sigterm \ No newline at end of file diff --git a/packages/MagicMouse-Core.package/MMUnixProcessWrapper.class/methodProperties.json b/packages/MagicMouse-Core.package/MMUnixProcessWrapper.class/methodProperties.json index b7938fe..eb96254 100644 --- a/packages/MagicMouse-Core.package/MMUnixProcessWrapper.class/methodProperties.json +++ b/packages/MagicMouse-Core.package/MMUnixProcessWrapper.class/methodProperties.json @@ -2,11 +2,13 @@ "class" : { }, "instance" : { - "startCommand:withArguments:" : "MB 1/30/2022 10:33", - "stdinPutBuffer:" : "MB 1/30/2022 10:33", + "debugLoggingProcess" : "MB 1/15/2022 13:17", + "debugLoggingProcess:" : "MB 1/15/2022 13:17", + "startCommand:withArguments:" : "MB 1/15/2022 13:17", + "stdinPutBuffer:" : "MB 1/15/2022 13:17", "stdinPutUint32:" : "cmfcmf 8/3/2019 18:58", "stdinPutUint8:" : "cmfcmf 8/3/2019 18:58", "stdoutNextBuffer:" : "cf 4/24/2019 09:42", "stdoutNextUint32" : "cmfcmf 8/3/2019 18:58", "stdoutNextUint8" : "cmfcmf 8/3/2019 18:58", - "terminate" : "cmfcmf 8/3/2019 18:58" } } + "terminate" : "MB 1/15/2022 12:51" } } diff --git a/packages/MagicMouse-Core.package/MMUnixProcessWrapper.class/properties.json b/packages/MagicMouse-Core.package/MMUnixProcessWrapper.class/properties.json index 6faa529..a61a97a 100644 --- a/packages/MagicMouse-Core.package/MMUnixProcessWrapper.class/properties.json +++ b/packages/MagicMouse-Core.package/MMUnixProcessWrapper.class/properties.json @@ -7,7 +7,8 @@ "commentStamp" : "cmfcmf 8/3/2019 18:57", "instvars" : [ "stdinWriter", - "stdoutReader" ], + "stdoutReader", + "debugLoggingProcess" ], "name" : "MMUnixProcessWrapper", "pools" : [ ], diff --git a/packages/MagicMouse-Core.package/MMWindowsProcessWrapperFFI.class/methodProperties.json b/packages/MagicMouse-Core.package/MMWindowsProcessWrapperFFI.class/methodProperties.json index 73fbd0d..0774f53 100644 --- a/packages/MagicMouse-Core.package/MMWindowsProcessWrapperFFI.class/methodProperties.json +++ b/packages/MagicMouse-Core.package/MMWindowsProcessWrapperFFI.class/methodProperties.json @@ -3,14 +3,14 @@ }, "instance" : { "peek:" : "cf 5/12/2019 15:16", - "readBuffer:length:" : "MB 1/30/2022 10:33", - "startCommand:withArguments:" : "MB 1/30/2022 10:33", + "readBuffer:length:" : "MB 1/15/2022 13:17", + "startCommand:withArguments:" : "MB 1/15/2022 13:17", "stderrNextBuffer:" : "cf 5/12/2019 14:36", - "stdinPutBuffer:" : "MB 1/30/2022 10:33", + "stdinPutBuffer:" : "MB 1/15/2022 13:17", "stdinPutUint32:" : "cf 5/12/2019 14:44", "stdinPutUint8:" : "cf 5/12/2019 14:02", "stdoutNextBuffer:" : "cf 5/12/2019 14:36", "stdoutNextUint32" : "cmfcmf 8/3/2019 18:58", "stdoutNextUint8" : "cmfcmf 8/3/2019 18:58", - "terminate" : "MB 1/30/2022 10:33", - "waitFor:at:" : "MB 1/30/2022 10:33" } } + "terminate" : "MB 1/15/2022 13:17", + "waitFor:at:" : "MB 1/15/2022 13:17" } } diff --git a/packages/MagicMouse-Core.package/MMWindowsProcessWrapperPW.class/methodProperties.json b/packages/MagicMouse-Core.package/MMWindowsProcessWrapperPW.class/methodProperties.json index f619ff1..7295f8a 100644 --- a/packages/MagicMouse-Core.package/MMWindowsProcessWrapperPW.class/methodProperties.json +++ b/packages/MagicMouse-Core.package/MMWindowsProcessWrapperPW.class/methodProperties.json @@ -2,11 +2,11 @@ "class" : { }, "instance" : { - "startCommand:withArguments:" : "MB 1/30/2022 10:33", + "startCommand:withArguments:" : "MB 1/15/2022 13:17", "stdinPutBuffer:" : "cmfcmf 8/3/2019 18:53", - "stdinPutUint32:" : "MB 1/30/2022 10:33", + "stdinPutUint32:" : "MB 1/15/2022 13:17", "stdinPutUint8:" : "cmfcmf 8/3/2019 18:53", "stdoutNextBuffer:" : "cmfcmf 8/3/2019 18:53", "stdoutNextUint32" : "cmfcmf 8/3/2019 18:53", "stdoutNextUint8" : "cmfcmf 8/3/2019 18:53", - "terminate" : "MB 1/30/2022 10:33" } } + "terminate" : "MB 1/15/2022 13:17" } } diff --git a/packages/MagicMouse-Tests.package/MMBrowserMorphTest.class/methodProperties.json b/packages/MagicMouse-Tests.package/MMBrowserMorphTest.class/methodProperties.json index 20835a3..f3da837 100644 --- a/packages/MagicMouse-Tests.package/MMBrowserMorphTest.class/methodProperties.json +++ b/packages/MagicMouse-Tests.package/MMBrowserMorphTest.class/methodProperties.json @@ -2,5 +2,5 @@ "class" : { }, "instance" : { - "testHandleStructuredData" : "MB 1/30/2022 10:33", - "testHandleStructuredDataEmpty" : "MB 1/30/2022 10:33" } } + "testHandleStructuredData" : "MB 1/15/2022 13:17", + "testHandleStructuredDataEmpty" : "MB 1/15/2022 13:17" } } diff --git a/patches/puppeteer-core+1.19.0.patch b/patches/puppeteer-core+1.20.0.patch similarity index 99% rename from patches/puppeteer-core+1.19.0.patch rename to patches/puppeteer-core+1.20.0.patch index b65f71f..1057ff5 100644 --- a/patches/puppeteer-core+1.19.0.patch +++ b/patches/puppeteer-core+1.20.0.patch @@ -11,7 +11,7 @@ index c994de5..fbc9d65 100644 Browser: { diff --git a/node_modules/puppeteer-core/lib/Page.js b/node_modules/puppeteer-core/lib/Page.js -index 0a8acb5..64d5558 100644 +index 0ec70f5..4cadbec 100644 --- a/node_modules/puppeteer-core/lib/Page.js +++ b/node_modules/puppeteer-core/lib/Page.js @@ -124,6 +124,7 @@ class Page extends EventEmitter { diff --git a/run.js b/run.js index 70daf4a..a024d95 100644 --- a/run.js +++ b/run.js @@ -6,6 +6,8 @@ const awaitifyStream = require("awaitify-stream"); const { getElements } = require("./getElements"); const uuid = require("uuid").v1; +const userAgent = + "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/69.0.3497.100 Safari/537.36"; Array.prototype.flat = function () { return this.reduce((acc, x) => acc.concat(x), []); }; @@ -34,18 +36,74 @@ const run = async () => { const headless = process.argv[process.argv.length - 2] === "headless"; const chromeProfilePath = process.argv[process.argv.length - 1]; - const terminate = async () => { - console.error("Terminating..."); + const terminate = async (id) => { + console.error(`Terminating tab with id ${id}.`); // await page.stopScreencast(); - await browser.close(); - process.exit(); + await pageMapping[id].close(); + delete pageMapping[id]; + if (Object.keys(pageMapping).length == 0) { + console.error("All tabs are closed now. Terminating ..."); + process.exit(); + } + }; + + let fixStuckPipeTimeout = null; + const renewFixStuckTimeout = () => { + fixStuckPipeTimeout = setTimeout(() => { + const buf = new SmartBuffer(); + buf.writeString("."); + buf.writeString("Something that should be ignored."); + const existingPageId = Object.keys(pageMapping).reduce((id, _id) => id || _id, null); + if (existingPageId) { + sendCommand(buf.toBuffer(), existingPageId, false); + } + }, 500); }; - const sendCommand = (buffer) => { - const lenBuffer = new Buffer(4); + const sendCommand = (buffer, id, shouldRenewFixStuckTimeout = true) => { + if (fixStuckPipeTimeout != null) { + clearInterval(fixStuckPipeTimeout); + } + const lenBuffer = Buffer.alloc(4); + const idBuffer = Buffer.alloc(4); lenBuffer.writeUInt32BE(buffer.length); + idBuffer.writeUInt32BE(id); + console.error(`Sending command with payload size ${buffer.length} for tab ${id}`); process.stdout.write(lenBuffer); + process.stdout.write(idBuffer); process.stdout.write(buffer); + if (shouldRenewFixStuckTimeout) { + renewFixStuckTimeout(); + } + }; + + const sendFrame = async (frame, isString, tabId) => { + const screenshot = isString ? Buffer.from(frame, "base64") : Buffer.from(frame.data, "base64"); + const buf = new SmartBuffer(); + if (IMAGE_FORMAT === "png") { + buf.writeString("ip"); + buf.writeBuffer(screenshot); + } else if (IMAGE_FORMAT === "jpeg") { + buf.writeString("ij"); + buf.writeBuffer(screenshot); + } else if (IMAGE_FORMAT === "raw") { + const pixels = await new Promise((resolve, reject) => + getPixels(screenshot, "image/png", (err, pixels) => { + if (err) { + reject(err); + } else { + resolve(pixels); + } + }), + ); + buf.writeString("ir"); + buf.writeUInt32LE(pixels.shape[0]); + buf.writeUInt32LE(pixels.shape[1]); + buf.writeBuffer(Buffer.from(pixels.data)); + } else { + throw new Error(`Unsupported image format ${IMAGE_FORMAT}.`); + } + sendCommand(buf.toBuffer(), tabId); }; const browser = await puppeteer.launch({ @@ -59,14 +117,16 @@ const run = async () => { ], executablePath: findChrome(), }); - const page = await browser.newPage(); - await page.setBypassCSP(true); - await page.setUserAgent( - "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/69.0.3497.100 Safari/537.36", - ); - await page.setViewport({ width: screenSize.x, height: screenSize.y }); + // Mapping from page id to the page. + const pageMapping = {}; + const openNewTab = async (id, screenSize, url) => { + const page = await browser.newPage(); + pageMapping[id] = page; + await page.setBypassCSP(true); + await page.setUserAgent(userAgent); + await page.setViewport({ width: screenSize.x, height: screenSize.y }); - process.on("SIGTERM", terminate); + process.on("SIGTERM", () => terminate(id)); const instrumentGoogleSlides = async () => { if (!page.url().startsWith("https://docs.google.com/presentation")) { @@ -136,7 +196,7 @@ const run = async () => { ).flat(); console.error("Google Slides Morph Positions", morphPositions); - morphPositions.forEach(sendPortalDataCommand); + morphPositions.forEach(morphPos => sendPortalDataCommand(morphPos, id)); }; const instrumentGitHub = async () => { @@ -170,144 +230,134 @@ const run = async () => { }); }; - const parseLDJsons = async () => { - const ldJsons = await page.$$eval('script[type="application/ld+json"]', (nodes) => - nodes.map((node) => JSON.parse(node.innerText)), - ); - console.error("LD JSON", ldJsons); - const buf = new SmartBuffer(); - buf.writeString("s"); - buf.writeUInt32LE(ldJsons.length); - ldJsons.forEach((ldJson) => { - const json = JSON.stringify(ldJson); - buf.writeStringPrependSize(json); + const parseLDJsons = async () => { + const ldJsons = await page.$$eval('script[type="application/ld+json"]', (nodes) => + nodes.map((node) => JSON.parse(node.innerText)), + ); + console.error(`LD JSON in tab ${id}`, ldJsons); + const buf = new SmartBuffer(); + buf.writeString("s"); + buf.writeUInt32LE(ldJsons.length); + ldJsons.forEach((ldJson) => { + const json = JSON.stringify(ldJson); + buf.writeStringPrependSize(json); + }); + await sendCommand(buf.toBuffer(), id); + }; + + const ignoreExecutionContextDestroyed = (error) => { + // Sometimes the frame is destroyed right after navigation, thus throwing an error + // when trying to evaluate a function in the frame's context. That's why we catch + // those errors here. + if ( + !error.message.endsWith( + "Execution context was destroyed, most likely because of a navigation.", + ) && + !error.message.endsWith("Cannot find context with specified id") + ) { + throw error; + } + }; + + page.on("dialog", async (dialog) => { + // TODO: We could send the dialog contents to Squeak and ask the user what to do. + // For now, accept all dialogs, so that the page remains responsive. + console.error( + `Dialog for tab with id ${id}!`, + dialog.defaultValue(), + dialog.message(), + dialog.type(), + ); + await dialog.accept(); }); - await sendCommand(buf.toBuffer()); - }; - const ignoreExecutionContextDestroyed = (error) => { - // Sometimes the frame is destroyed right after navigation, thus throwing an error - // when trying to evaluate a function in the frame's context. That's why we catch - // those errors here. - if ( - !error.message.endsWith( - "Execution context was destroyed, most likely because of a navigation.", - ) && - !error.message.endsWith("Cannot find context with specified id") - ) { - throw error; - } - }; - - page.on("dialog", async (dialog) => { - // TODO: We could send the dialog contents to Squeak and ask the user what to do. - // For now, accept all dialogs, so that the page remains responsive. - console.error("Dialog!", dialog.defaultValue(), dialog.message(), dialog.type()); - await dialog.accept(); - }); + page.on("framenavigated", async (frame) => { + await new Promise((resolve) => setTimeout(() => resolve(), 50)); + try { + await parseLDJsons(); + await instrumentGoogleSlides(); + await instrumentGitHub(); + + if (!frame.parentFrame()) { + const url = page.url(); + console.error(`Navigating to ${url} in tab with id ${id}`); + const buf = new SmartBuffer(); + buf.writeString("l"); + buf.writeString(url); + sendCommand(buf.toBuffer(), id); + } + } catch (error) { + ignoreExecutionContextDestroyed(error); + } + }); - page.on("framenavigated", async (frame) => { - await new Promise((resolve) => setTimeout(() => resolve(), 50)); - try { + page.on("domcontentloaded", async () => { await parseLDJsons(); - await instrumentGoogleSlides(); + // TODO: Is this needed when we have framenavigated? await instrumentGitHub(); + await instrumentGoogleSlides(); + }); - if (!frame.parentFrame()) { - const url = page.url(); - console.error(`Navigating to ${url}`); - const buf = new SmartBuffer(); - buf.writeString("l"); - buf.writeString(url); - sendCommand(buf.toBuffer()); - } - } catch (error) { - ignoreExecutionContextDestroyed(error); - } - }); - - page.on("domcontentloaded", async () => { - await parseLDJsons(); - // TODO: Is this needed when we have framenavigated? - // await instrumentGitHub(); - // await instrumentGoogleSlides(); - }); - - const refreshTrackedElements = async () => { - const trackedElements = ( - await Promise.all( - page - .frames() - .filter((frame) => !frame.isDetached()) - .map((frame) => - frame.evaluate(getElements, "refreshInfo").catch((error) => { - ignoreExecutionContextDestroyed(error); - return []; - }), - ), - ) - ).flat(); - // console.error(trackedElements); - const buf = new SmartBuffer(); - buf.writeString("hr"); // portal refresh - buf.writeUInt32LE(trackedElements.length); - trackedElements.forEach((element) => - buf - .writeStringNT(element.id) - .writeInt32LE(element.x) - .writeInt32LE(element.y) - .writeInt32LE(element.w) - .writeInt32LE(element.h), - ); - sendCommand(buf.toBuffer()); - }; + const refreshTrackedElements = async () => { + const trackedElements = ( + await Promise.all( + page + .frames() + .filter((frame) => !frame.isDetached()) + .map((frame) => + frame.evaluate(getElements, "refreshInfo").catch((error) => { + ignoreExecutionContextDestroyed(error); + return []; + }), + ), + ) + ).flat(); + // console.error(trackedElements); + const buf = new SmartBuffer(); + buf.writeString("hr"); // portal refresh + buf.writeUInt32LE(trackedElements.length); + trackedElements.forEach((element) => + buf + .writeStringNT(element.id) + .writeInt32LE(element.x) + .writeInt32LE(element.y) + .writeInt32LE(element.w) + .writeInt32LE(element.h), + ); + sendCommand(buf.toBuffer(), id); + }; - page.on("screencastframe", async (frame) => { - const screenshot = Buffer.from(frame.data, "base64"); + page.on("screencastframe", async (frame) => { + await sendFrame(frame, false, id); + await refreshTrackedElements(); - const buf = new SmartBuffer(); - if (IMAGE_FORMAT === "png") { - buf.writeString("ip"); - buf.writeBuffer(screenshot); - } else if (IMAGE_FORMAT === "jpeg") { - buf.writeString("ij"); - buf.writeBuffer(screenshot); - } else if (IMAGE_FORMAT === "raw") { - const pixels = await new Promise((resolve, reject) => - getPixels(screenshot, "image/png", (err, pixels) => { - if (err) { - reject(err); - } else { - resolve(pixels); - } - }), - ); - buf.writeString("ir"); - buf.writeUInt32LE(pixels.shape[0]); - buf.writeUInt32LE(pixels.shape[1]); - buf.writeBuffer(Buffer.from(pixels.data)); - } else { - throw new Error(`Unsupported image format ${IMAGE_FORMAT}.`); - } - sendCommand(buf.toBuffer()); + await page.screencastFrameAck(frame.sessionId); + }); - await refreshTrackedElements(); + await page.exposeFunction("uuid", () => uuid()); + await page.exposeFunction("gitClone", async (name, url) => { + console.error("GIT CLONE", name, url, `in tsb ${id}`); + const buf = new SmartBuffer(); + buf.writeString("g"); + buf.writeStringPrependSize(name); + buf.writeString(url); + await sendCommand(buf.toBuffer(), id); + }); - await page.screencastFrameAck(frame.sessionId); - console.error(`Sent frame at ${Date.now() / 1000}`); - }); + // TODO: This throws an error in case the page can't be reached (e.g., when you have no network connection) + console.error(`Navigating to ${url} on tab ${id}`); + await page.goto(url); - await page.exposeFunction("uuid", () => uuid()); - await page.exposeFunction("gitClone", async (name, url) => { - console.error("GIT CLONE", name, url); - const buf = new SmartBuffer(); - buf.writeString("g"); - buf.writeStringPrependSize(name); - buf.writeString(url); - await sendCommand(buf.toBuffer()); - }); + console.error(`Starting screencast on tab ${id} ...`); + await page.startScreencast({ + format: IMAGE_FORMAT === "jpeg" ? "jpeg" : "png", + everyNthFrame: 1, + }); + console.error(`Recording screencast on tab ${id} ...`); + }; + openNewTab(0, screenSize, url); - const sendPortalDataCommand = (data) => { + const sendPortalDataCommand = (data, id) => { const buf = new SmartBuffer(); switch (data.type) { case "img": @@ -336,29 +386,58 @@ const run = async () => { buf.writeString(data.data); break; } - sendCommand(buf.toBuffer()); + sendCommand(buf.toBuffer(), id); }; - // TODO: This throws an error in case the page can't be reached (e.g., when you have no network connection) - console.error(`Navigating to ${url}`); - await page.goto(url); - - console.error("Starting screencast..."); - await page.startScreencast({ - format: IMAGE_FORMAT === "jpeg" ? "jpeg" : "png", - everyNthFrame: 1, - }); - console.error("Recording screencast..."); - + const takeScreenshotOf = async (id, screenSize, url) => { + const page = await browser.newPage(); + pageMapping[id] = page; + await page.setBypassCSP(true); + await page.setUserAgent(userAgent); + await page.setViewport({ width: screenSize.x, height: screenSize.y }); + page.on("domcontentloaded", async () => { + // Wait one second and then do the screenshot + setTimeout(() => { + page + .screenshot({ encoding: "base64", type: "jpeg" }) + .then((frameString) => sendFrame(frameString, true, id)) + .then(() => terminate(id)); + }, 1000); + }); + await page.goto(url); + }; + // + // ------------------------------------------------ React to squeak commands loop ------------------------------------------------------- + // const reader = awaitifyStream.createReader(process.stdin); while (true) { const size = (await reader.readAsync(4)).readUInt32BE(); - console.error(`Waiting for payload of size ${size}`); + const tabId = (await reader.readAsync(4)).readUInt32BE(); + console.error( + `Receiving Squeak command. Waiting for payload of size ${size} for tab ${tabId}.`, + ); const command = String.fromCharCode((await reader.readAsync(1)).readUInt8()); const payload = size > 1 ? SmartBuffer.fromBuffer(await reader.readAsync(size - 1)) : new SmartBuffer(); - console.error(`Received command ${command} with payload of size ${size}.`); - + const commandMapping = { + s: "Dropped String", + f: "Dropped Morph", + t: "Update Text", + k: "Kill Tab", + l: "Set Location", + e: "Event", + n: "New Tab", + i: "Screenshot", + }; + const commandsCreatingNewTabs = ["n", "i"]; + console.error( + `Received command ${commandMapping[command]} with payload of size ${size} for tab ${tabId}.`, + ); + const page = pageMapping[tabId]; + if (page == null && !commandsCreatingNewTabs.includes(command)) { + console.error("Received command for non existing tab", tabId, ". Skipping ..."); + continue; + } switch (command) { case "s": { const x = payload.readInt32LE(); @@ -492,7 +571,8 @@ const run = async () => { } case "k": { // This command is necessary because the Squeak ProcessWrapper is unable to terminate processes. - await terminate(); + console.error("Killing tab", tabId); + await terminate(tabId); break; } case "l": { @@ -597,13 +677,18 @@ const run = async () => { case 6: { const x = payload.readUInt32LE(); const y = payload.readUInt32LE(); + console.error("Setting page size to ", x, y); page.setViewport({ width: x, height: y }); break; } case 7: { - const y = payload.readUInt32LE(); - console.error("scroll", y); - page.evaluate((y) => window.scrollBy(0, y == 0 ? -20 : 20), y); + const x = payload.readInt32LE(); + const y = payload.readInt32LE(); + console.error("scroll", x, y); + page.evaluate(({ x, y }) => window.scrollBy(x, y), { + x, + y, + }); break; } case 8: { @@ -633,7 +718,7 @@ const run = async () => { h: element.h, }); - sendPortalDataCommand(element); + sendPortalDataCommand(element, tabId); break; } case 9: { @@ -649,6 +734,24 @@ const run = async () => { } break; } + case "n": { + const x = payload.readUInt32BE(); + const y = payload.readUInt32BE(); + const url = payload.readString(); + console.error(`Opened new tab at ${url} with size ${x}, ${y} and tabId ${tabId}`); + openNewTab(tabId, { x, y }, url); + break; + } + case "i": { + const x = payload.readUInt32BE(); + const y = payload.readUInt32BE(); + const url = payload.readString(); + console.error( + `Opened new tab at ${url} with size ${x}, ${y} and tabId ${tabId} to take a screenshot`, + ); + takeScreenshotOf(tabId, { x, y }, url); + break; + } } } };