Skip to content

Commit

Permalink
Add anchor tags to HTTP Server output
Browse files Browse the repository at this point in the history
This means you can now load the raw text in a browser and the resulting
page will have basic blue links that can be clicked on that will in turn
be loaded by the HTTP service.

A significant feature, so worthy of a minor version bump to;
v1.1.0
  • Loading branch information
tombh committed Jun 17, 2018
1 parent 1b42630 commit 3149db4
Show file tree
Hide file tree
Showing 11 changed files with 260 additions and 173 deletions.
15 changes: 14 additions & 1 deletion interfacer/src/browsh/raw_text_server.go
Original file line number Diff line number Diff line change
Expand Up @@ -60,10 +60,23 @@ func (h *slashFix) ServeHTTP(w http.ResponseWriter, r *http.Request) {
func handleHTTPServerRequest(w http.ResponseWriter, r *http.Request) {
urlForBrowsh, _ := url.PathUnescape(strings.TrimPrefix(r.URL.Path, "/"))
rawTextRequestID := pseudoUUID()
sendMessageToWebExtension("/raw_text_request," + rawTextRequestID + "," + urlForBrowsh)
mode := getRawTextMode(r)
sendMessageToWebExtension(
"/raw_text_request," + rawTextRequestID + "," +
mode + "," +
urlForBrowsh)
waitForResponse(rawTextRequestID, w)
}

// 'PLAIN' mode returns raw text without any HTML whatsoever.
// 'HTML' mode returns some basic HTML tags for things like anchor links.
func getRawTextMode(r *http.Request) string {
var mode = "HTML"
if (strings.Contains(r.Host, "text.")) { mode = "PLAIN" }
if (r.Header.Get("X-Browsh-Raw-Mode") == "PLAIN") { mode = "PLAIN" }
return mode
}

func waitForResponse(rawTextRequestID string, w http.ResponseWriter) {
var rawTextRequestResponse string
var ok bool
Expand Down
11 changes: 9 additions & 2 deletions interfacer/test/http-server/server_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -13,9 +13,16 @@ func TestHTTPServer(t *testing.T) {
}

var _ = Describe("HTTP Server", func() {
It("should return text", func() {
response := getPath("/smorgasbord")
It("should return plain text", func() {
response := getPath("/smorgasbord", "plain")
Expect(response).To(ContainSubstring("multiple hot Smörgås"))
Expect(response).To(ContainSubstring("A special Swedish type of smörgåsbord"))
Expect(response).ToNot(ContainSubstring("<a href"))
})

It("should return HTML text", func() {
response := getPath("/smorgasbord", "html")
Expect(response).To(ContainSubstring(
"<a href=\"/http://localhost:4444/smorgasbord/another.html\">Another page</a>"))
})
})
11 changes: 8 additions & 3 deletions interfacer/test/http-server/setup.go
Original file line number Diff line number Diff line change
Expand Up @@ -26,11 +26,16 @@ func startBrowsh() {
browsh.HTTPServerStart()
}

func getPath(path string) string {
func getPath(path string, mode string) string {
browshServiceBase := "http://localhost:" + *browsh.HTTPServerPort
staticFileServerBase := "http://localhost:" + staticFileServerPort
fullBase := browshServiceBase + "/" + staticFileServerBase
response, err := http.Get(fullBase + path)
client := &http.Client{}
request, err := http.NewRequest("GET", fullBase + path, nil)
if mode == "plain" {
request.Header.Add("X-Browsh-Raw-Mode", "PLAIN")
}
response, err := client.Do(request)
if err != nil {
panic(fmt.Sprintf("%s", err))
} else {
Expand All @@ -57,7 +62,7 @@ var _ = ginkgo.BeforeSuite(func() {
time.Sleep(10 * time.Second)
// Allow the browser to sort its sizing out, because sometimes the first test catches the
// browser before it's completed its resizing.
getPath("/smorgasbord")
getPath("/smorgasbord", "plain")
})

var _ = ginkgo.AfterSuite(func() {
Expand Down
2 changes: 1 addition & 1 deletion webext/manifest.json
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
{
"manifest_version": 2,
"name": "Browsh",
"version": "1.0.13",
"version": "1.1.0",

"description": "Renders the browser as realtime, interactive, TTY-compatible text",

Expand Down
1 change: 0 additions & 1 deletion webext/src/background/manager.js
Original file line number Diff line number Diff line change
Expand Up @@ -176,7 +176,6 @@ export default class extends utils.mixins(CommonMixin, TTYCommandsMixin) {
this.log(`Tab ${channel.name} connected for communication with background process`);
let tab = this.tabs[parseInt(channel.name)];
tab.postConnectionInit(channel);
tab.setMode(this._is_raw_text_mode);
this._is_connected_to_browser_dom = true;
}

Expand Down
28 changes: 8 additions & 20 deletions webext/src/background/tab.js
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,8 @@ export default class extends utils.mixins(CommonMixin, TabCommandsMixin) {
this._tab_reloads = 0;
// The maximum amount of times to try to recover a tab that won't connect
this._max_number_of_tab_recovery_reloads = 3;
// Type of raw text mode; HTML or plain
this.raw_text_mode = '';
}

postDOMLoadInit(terminal, dimensions) {
Expand All @@ -22,6 +24,9 @@ export default class extends utils.mixins(CommonMixin, TabCommandsMixin) {
this.channel = channel;
this._sendTTYDimensions();
this._listenForMessages();
let mode = 'interactive';
if (this.raw_text_mode !== '') { mode = this.raw_text_mode }
this.channel.postMessage(`/mode,${mode}`);
}

isConnected() {
Expand Down Expand Up @@ -104,26 +109,8 @@ export default class extends utils.mixins(CommonMixin, TabCommandsMixin) {
}
}

setMode(is_raw_text_mode) {
if (is_raw_text_mode) {
this.channel.postMessage('/mode,raw_text');
this._requestRawText();
} else {
this.channel.postMessage('/mode,interactive');
}
}

// If Browsh is setup in HTTP-server mode then this is the moment that we ask the tab to
// render the entire DOM as plain text. We must only do this for tabs subsequent to the
// initial tab that loads at boot time (there must always remain a single tab to keep the
// browser running).
_requestRawText() {
// The assumption is that Tab ID 1 is always the first tab. However, I have a vague
// memory of seeing the "Firefox Privacy Notice" tab load before the CLI argument requested
// URL. So, maybe ID 1 isn't 100% reliable.
if (this.id !== 1) {
this.channel.postMessage('/request_raw_text');
}
setMode(mode) {
this.raw_text_mode = mode;
}

_listenForMessages() {
Expand All @@ -146,6 +133,7 @@ export default class extends utils.mixins(CommonMixin, TabCommandsMixin) {
// first. So let's just close that tab.
// TODO: Only do this for a testing ENV?
_closeUnwantedStartupTabs() {
if (this.title === undefined) { return false }
if (
this.title.includes('Firefox by default shares data to:') ||
this.title.includes('Firefox Privacy Notice')
Expand Down
11 changes: 6 additions & 5 deletions webext/src/background/tty_commands_mixin.js
Original file line number Diff line number Diff line change
Expand Up @@ -36,7 +36,7 @@ export default (MixinBase) => class extends MixinBase {
);
break;
case '/raw_text_request':
this._rawTextRequest(parts[1], parts.slice(2).join(','));
this._rawTextRequest(parts[1], parts[2], parts.slice(3).join(','));
break;
}
}
Expand Down Expand Up @@ -164,12 +164,13 @@ export default (MixinBase) => class extends MixinBase {
this.sendToTerminal('/screenshot,' + data);
}

_rawTextRequest(request_id, url) {
this.createNewTab(url, tab => {
_rawTextRequest(request_id, mode, url) {
this.createNewTab(url, native_tab => {
this._acknowledgeNewTab({
id: tab.id,
id: native_tab.id,
request_id: request_id
})
});
this.tabs[native_tab.id].setMode(`raw_text_${mode.toLowerCase()}`);
});
}

Expand Down
9 changes: 5 additions & 4 deletions webext/src/dom/commands_mixin.js
Original file line number Diff line number Diff line change
Expand Up @@ -17,9 +17,6 @@ export default (MixinBase) => class extends MixinBase {
this.sendAllBigFrames();
}
break;
case '/request_raw_text':
this.sendRawText();
break;
case '/scroll_status':
this._handleScroll(parts[1], parts[2]);
break;
Expand Down Expand Up @@ -50,10 +47,14 @@ export default (MixinBase) => class extends MixinBase {
}

_setupMode(mode) {
if (mode === 'raw_text') {
if (mode === 'raw_text_plain' || mode === 'raw_text_html') {
this._is_raw_text_mode = true;
this._is_interactive_mode = false;
this._raw_mode_type = mode;
this.sendRawText();
}
if (mode === 'interactive') {
this._is_raw_text_mode = false;
this._is_interactive_mode = true;
this._setupInteractiveMode();
}
Expand Down
6 changes: 3 additions & 3 deletions webext/src/dom/manager.js
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,7 @@ export default class extends utils.mixins(CommonMixin, CommandsMixin) {
// For Browsh used via the interactive CLI ap
this._is_interactive_mode = false;
// For Browsh used via the HTTP server
this._is_raw_text_mode = false;
this._is_raw_mode = false;
this._setupInit();
}

Expand Down Expand Up @@ -44,7 +44,7 @@ export default class extends utils.mixins(CommonMixin, CommandsMixin) {
}

sendAllBigFrames() {
if (this._is_raw_text_mode) { return }
if (this._is_raw_mode) { return }
if (!this.dimensions.tty.width) {
this.log("Not sending big frames without TTY data")
return
Expand All @@ -62,7 +62,7 @@ export default class extends utils.mixins(CommonMixin, CommandsMixin) {
sendRawText() {
this.dimensions.update();
this.dimensions.setSubFrameDimensions('raw_text');
this.text_builder.sendRawText();
this.text_builder.sendRawText(this._raw_mode_type);
}

sendSmallPixelFrame() {
Expand Down
Loading

0 comments on commit 3149db4

Please sign in to comment.