minbrowser / min

A fast, minimal browser that protects your privacy
https://minbrowser.org/
Apache License 2.0
7.94k stars 703 forks source link

How to reload the browser programmatically? #554

Open code-hunger opened 6 years ago

code-hunger commented 6 years ago

I want to request a browser reload when settings that require reload are changed. First, I tried just doing banner.onclick = _ => window.location.reload() but this only reloaded the settings page.

Then I tried with ipc events - I created an ipc reload event in default.js: ipc.on('reload', window.location.reload) And then:

banner.onclick = _ => ipc.send('reload')

But ipc was undefined. Why? I thought such variables were available all across the browser code, isn't it concatenated?

Then I tried importing it like I saw you did on some other places:

var electron = require('electron')
var ipc = electron.ipcRenderer

I got an error saying that require() wasn't a function.

How does this browser work? I just can't wrap my head around it :smiley:

PalmerAL commented 6 years ago

Yeah, this is kind of confusing. Basically, there's three places your code can run:

So I think what you have is mostly correct. What you would need to do is add a function in the preload script to reload the browser and expose it to the window:

window.reloadBrowser = function() {
   ipc.sendToHost("reloadBrowser");
}

Since this function is located in the preload script, it will have access to IPC. Then, in the regular settings JS, you could call window.reloadBrowser() to run it, and finally that IPC message will go to the browser UI process, where you would have a listener for it.

(Also, this function would have to check the page origin before sending the IPC, because we don't want to give ordinary webpages the ability to reload the browser).

code-hunger commented 6 years ago

It looks to me like this way reloadBrowser will be available to all ordinary webpages, which is not good. Even if we put some domain guards, it is a code smell and I feel it's better to avoid that.
I agree it's highly unlikely that a webpage will overwrite this function but still it doesn't sound good to rely on it.

Instead, can't we have the internal browser pages even more internal? As I understand from your answer, they're currently just the same as every other webpage on the internet, with the exception of being loaded from the local filesystem. Can't we make them part of the electron app?

If we decide to create a history page, we'll have to expose a history API to all webpages, right? And every other internal webpage that would need to operate with the browser will need some API that would be exposed to all ordinary webpages. From this POV, it looks to me it's better to find some way to separate internal pages and provide APIs only to them.

PalmerAL commented 6 years ago

You could only define the function for internal pages:

if(window.location.protocol === "file:") {
   window.reloadBrowser = function() {
...

Making internal pages have the same privileges as the browser UI would be nice, although it's kind of difficult to implement. You could add nodeintegration to the webview tag, but I think there's a pretty big risk of accidentaly loading a regular webpage with nodeintegration enabled if we do that, which would be bad. I'm guessing the best approach would be to use iframes for the internal pages instead, but then you need a bunch of logic to manage those (because iframes don't emit the same events as webviews, you need to destroy them and create a webview if you navigate from an internal page to an external page, etc.) We'd also need to be really careful about links from internal pages - for example, if we made the settings page an iframe and you clicked on the Easylist link that's currently there, the Easylist website would load in the main browser UI and have node access.

I do think it's probably worth doing this, but we're going to need to be really careful not to introduce any security vulnerabilities when we do.

code-hunger commented 6 years ago

You could only define the function for internal pages:

Doesn't this create the function once a file:// url is opened? And isn't the function available to everyone thereafter? By your confidence I'd guess it isn't. Which leads me to think that this:

The preload script (which is all the files in /js/webview). This code runs inside the webview process, but it also has access to Node and the Electron APIs.

Is loaded for every webpage that is requested, and all actions in it are completely isolated from the other tabs.

My idea about the internal pages was to make them just like index.html, loaded directly by electron and not via webviews. Or is that impossible?

PalmerAL commented 6 years ago

Is loaded for every webpage that is requested, and all actions in it are completely isolated from the other tabs.

Yup, that's right.

My idea about the internal pages was to make them just like index.html, loaded directly by electron and not via webviews. Or is that impossible?

You mean just put them in the same HTML file as the main UI? You could definitely do that, the downside is that it makes the webview logic more complicated, and you also have to figure out how to handle opening multiple tabs. There's not really any perfect solution here; I guess it just depends whether we think having Node API's in the content pages is worth the additional complexity.

code-hunger commented 6 years ago

the downside is that it makes the webview logic more complicated, and you also have to figure out how to handle opening multiple tabs. There's not really any perfect solution here; I guess it just depends whether we think having Node API's in the content pages is worth the additional complexity.

Like I suggested in the other issue - what about opening a new 'library' window like Firefox does? It'll be native to electron, no security threats for the Webview, and easy to integrate because no APIs will have to be exposed.

PalmerAL commented 6 years ago

Yeah, I think that would work. With the bookmarks and history views specifically, I kind of wonder if it would make sense to just add more features to the existing display within the searchbar. On the other hand, depending on how complicated we wanted to make the history view (I reallly like this concept for example) a separate window might work nicely as well.