Struggling with Chrome Extension architecture - google-chrome-extension

I'm new to Chrome extension development, and I'm a bit struggling with the architecture to put in place.
I would like to develop an extension (browser_action), that, when the button is clicked, opens a window where information will be populated from the WebTraffic.
I figured out I could use the WebRequest API to get info about the traffic.
I could create a popup window, but it's displayed only when I click on the extension button, and hides as soon as I click somewhere else
I tried creating a background window, but it does not show up.
I'd be very grateful if anyone could help me with the initial setup of my application.
Thanks in advance

You need both.
Take a look at the Architecture Overview, or maybe this question.
The lifetime of the popup is indeed equal to how long it stays on screen. It's the UI part, but putting logic there is usually bad.
A background page is permanently there but invisible. It's typically the "brain" of an extension, taking care of heavy lifting and routing messages to other parts.
In short:
You need a background script to collect webRequest information for you in some format.
You need a popup page to show it. Keep in mind it's not guaranteed to be present at a given time and can close at any time.
It's probably best to use Messaging to request the information from the background page. If you need real-time updates, you can use long-lived connections.
In your case you can also tightly couple the two and call chrome.runtime.getBackgroundPage() to directly reference stuff in it.

Related

Electron custom web browser with on screen keyboard

I am trying to make a custom web browser inside an electron application. Using webview (because iframe is not loading some necessary web pages) I can load a web page.
Then trying to write something into the web pageĀ“s input by clicking on the react-simple-keyboard which causes blur event, so input loses focus.
I figured out, that this approach would not work directly, so via ipc communication I am trying to resend the key button value and then set it to the window with const {keyboard} = require("#nut-tree/nut-js"); keyboard.type(args.value);
In my input, above the webview tag, it works like a charm, but I am not able to type inside the webview.
Can anyone help me to solve this problem or does anyone know a perfect solution how to use other OSK in electron app or how to open native windows osk on input focus? Thank you in advance.
I'm not sure how you'd accomplish that with this library. But you can just use Window's default on-screen-keyboard to accomplish that. Here is a link to how enable it. windows support
You should also use a BrowserView instead of a Webview, as the Webview is not guaranteed to be present in future versions and it's API is unstable.
The BrowserView doesn't work like an HTML element though and you should read the docs here.
But anyways, just use the system's default and you should be fine.
Also, if you're interested, I'm developing a web browser with Electron (in fact, I'm currently writing this using that browser) and as far as I can say, it's written pretty simply and anyone should understand most of it, so take a look if you're in trouble. But I am no expert and you shouldn't rely on my code as a standard of any kind, really.
Well, I might have just found an answer for you.
Firstly, as I mentioned, you should use a BrowserView instead of webView for your external content, and this time it is a requirement for this method to work. I would create a BrowserWindow with the controls at the top, then place a BrowserView to act as a "browser" and create another BrowserView at the bottom and load in the keyboard html file. And then, when a key is pressed on the virtual keyboard, you should send an ipc message to the main script with the information of what key was pressed(it should be done via a preload script for the OSK BrowserView). In the main script, once you recieve the ipc message (via ipcMain.on()) you should then send an input event to the BrowserView containing your external content. That's done by calling contents.sendInputEvent(Event), so it has to be a main script. Here is a link to contents.sendInputEvent(Event), BrowserView (link) and preload script as well as ipc communication (link).
As for invoking the keyboard once you click on the input element, you could probably do it with a preload script for your "browser's" BrowserView, if you can find how you can check whether the focused element is an input element or something like that, and call an ipc message to then hide or show the keyboard. (Hiding and shwoing the keyboard could be done by calling BrowserWindow.addBrowserView(BrowserView) or BrowserWindow.removeBrowserView(BrowserView). But you would have to search the documentation yourself for those methods as I can't write anymore right now. Documentation could anwser any of your questions if you search for it there.

Is it possible to move Google Chrome tab between windows? got it :)

Edit: Thank you wOxxOm. It worked :)
chrome.tabs.move(XXX,{windowId:YYY, index:ZZZ})
Somehow I did not see the move option :(
I am writing simple Google Chrome web extension and I want to manipulate the tabs and windows. I actually want to be able to move a tab between the windows. The tab will have programatically spawned dynamic page, that I do not want to reload. The windowId is not listed in the modifiable properties chrome.tabs.
Am I missing something or it is currently not supported? What are the workarounds?
p.s. In extreme case also powershell or .Net might be acceptable (I have total control of the target PC). Currently spawning clearly distinguishable iframe over the web pages (background script injected and message listener) but the iframe gets reloaded, which I want to avoid.
p.p.s. Workaround might be to detect the currently active window and spawn new tab in the active window (if required), but this would require to save the page state, close the inactive tab and spown new one in the active window (this should be possible)
p.p.p.s. Main target is Google Chrome, but want it also for Microsoft Edge. Hopefully also for other browsers.
Edit: Thank you wOxxOm. It worked :)
chrome.tabs.move(XXX,{windowId:YYY, index:ZZZ})
Somehow I did not see the move option :(

Tab-specific, non-intrusive notification in a chrome extension

I'm developing a chrome extension. When the user goes to the options page, they might modify a setting which will require them to refresh any tabs they have in which they're using the extension. So if the user changes one of these settings, then goes back to a tab which requires a refresh, I'd like to notify them of this in a non-intrusive way.
Is there a part of the API specifically for doing this sort of thing, or some other recommended way of doing it? I was thinking of maybe a little message that comes down from the top of the page, but can be closed, or a popup coming out of the browser action.
You have many options.. To name a few:
Do not require it. As much as you can, make the (presumably) content script adapt to new settings. It's by far a better UX - in some cases.
Least intrusive would probably be to update a browser action / page action icon if you use one.
Both APIs allow a per-tab change of icon/badge. You could also animate it a little to bring attention.
An in-page notification injected into the DOM. Some sort of toast or <dialog>.
Watch tab changes with chrome.tabs events, and do something on activation of affected tab, such as a chrome.notifications notification.

How do all types of Chrome extension scripts work?

I'm new to Chrome extensions and would like to understand how all types of scripts/pages work.
Here is my understanding:
First - there are "content scripts", ones that should be used to actually modify the pages.
Second - there is a "background script", designed to work like as a server that you send and receive messages from, but it does not modify the pages' DOM; so it can perform tasks like dealing with storage and communicating between scripts but not modifying the page.
Lastly - there are "popup scripts", they are separated from both content scripts and background scripts, but you can still send/receive messages between them.
The popup scripts can NOT directly modify the page (same as background script), they can only send messages to the other two.
You do not declare them at all in the manifest file, you can just go straight and use them in your popup html file.
In the end only the content scripts can eventually actually modify a page.
Am I correct?
One Chrome extension documentation Link to rule them all, One Link to find them,
One Link to bring them all and in the darkness bind() them1:
>> Architecture Overview <<
(artist's impression)
It should answer many of your questions. However, that would be a bad SO answer, so a summary from me:
Background page/scripts: Only one page exists per extension. It is invisible and can never be displayed in a tab. Normally, it is open as long as Chrome is open, though there are exceptions. Since it's always there and has the highest level of access to Chrome APIs, it's frequently used for main logic / event routing between parts of the extension. In short, background work.
Event page/scripts: A variant of background pages that are unloaded if there is no code running. This saves memory, but introduces complexity as to maintaining state. Chrome remembers which events should be listened to (via addListener) and loads the page again when they happen. Hence, event page.
Besides that, extension can have other, visible pages. You can just open them in a tab (they would have chrome-extension://extensionidgoeshere/page.html address), and they will have same level of access to Chrome API. Two UI types are special to extensions though:
Browser/Page Action popup: A small window that's opened with a click on the corresponding UI element. Unfortunately, it's also very fragile - it will close as soon as it loses focus. Other than that, it's just an extension page.
Options page: Comes in two flavours. Version 1 Options page is just a tab that's opened when invoking options for an extension; Version 2 Options page can optionally show in a special box inside chrome://extensions/. Again, other than that it's just a page with extension privileges.
Finally, having a bunch of pages is fun, but if you want to interact with existing pages/tabs, you'll need to inject scripts in them.
Content Scripts are scripts that run alongside pages; for compatibility reasons, they run in an isolated world. For security reasons, they are severely limited in access to Chrome API. But they share the DOM with the page, and as such can modify it.
Page-level Scripts is something you barely find mentioned in documentation (as "DOM injected scripts"), but they are very useful to break the barrier between extension JavaScript and page's own JavaScript. A good overview of them is presented in this answer by the magnificent Rob W.
Having defined all relevant extension parts, the documentation page also briefly mentions how to communicate between them. For a more in-depth look into this aspect, see this answer (again by Rob W) and the Messaging documentation.
1 Seriously though, every beginning extension developer needs to read that, and this page is not prominent the documentation. Good job, Google.

How is the panel displayed when launching Chrome Hangout extension made to be always on top and pinned?

When launching the Chrome Extension Google-Hangouts, a panel initially appears that lists members and a link/button to create a new Hangout.
This panel is initially pinned to the bottom right of the browser window. When pinned like this, it remains always on top as a browser navigation session continues: users can go to different URLs, change tabs, etc. and that panel stays at the bottom right and stays on top of all other windows (or at least on top of the main browser window).
Once it's unpinned, you can drag it around the window, but it no longer stays always on top.
My question is, how was that achieved - what code, or what functions, do i need to call to create that window/panel so that it stays initially pinned and always on top? Is there some binding to some native code that's involved? Some other approach?
If anyone know and can show or explain, i would be hugely grateful as this feature is key to an extension i'm trying to build.
Thanks a lot!
This may not be an answer but to get a clue of what is happening I extracted the crx file to view its content there are a few OS specific files : ace.dll , libace.so and ace. After researching a bit i found this. This is a plugin. Hangouts extension is using ace plugin which is actually running on your desktop(i'm not sure about this). You can check this article
I found this related post: How to build an chrome extension like Google Hangouts
ACE is actually not what makes the window, Chrome has that capability built in, apparently. Even if you don't enable panels, extensions from Google can still make them, provided your OS is capable.

Resources