Request to external server is possible in MV3? [duplicate] - google-chrome

I'm working on a Manifest v3 browser extension where I need to identify the browser in which the extension is currently running from the backgroundScript. Since ManifestV3 extension uses a service worker, it doesn't have DOM or window. So I'm not able to use window.navigator.userAgent.
I found a related question which talks about how to gets window height and width information, but I couldn't find any other information to fetch the userAgent of the browser.
Is this possible?

Neutral globals
Things like navigator aren't specific to visual representation of a window.
Just omit window. and read it directly:
navigator
navigator.userAgent
atob
fetch
Window-specific globals
Things specific to user interaction or visual/aural representation like DOM or AudioContext, or those that may show a prompt for user permissions.
Not available in a worker.
Aliases for window
Use them instead of window for code clarity or if a local variable is named just as a global property.
Built-in globalThis (Chrome/ium 71+, FF 65+) and self
These are worker-compatible aliases for the global scope. Note that a JS library you're loading may redefine them theoretically, but that'd be really weird and abnormal.
Self-made global
The most reliable method, but you'll have to add 'use strict' only inside an IIFE not globally.
This is already offered by bundlers like webpack.
Here's how you can replicate it yourself:
const global = (function(){
if (!this) throw "Don't add 'use strict' globally, use it inside IIFE/functions";
return this;
})();

Related

Using Chrome DevTools Protocol Input.dispatchKeyEvent or Input.dispatchMouseEvent to send an event

I'm writing a DSL that will interact with a page via Google Chrome's Remote Debugging API.
The INPUT domain (link here:
https://chromedevtools.github.io/devtools-protocol/1-2/Input/) lists two functions that can be used for sending events: Input.dispatchKeyEvent and Input.dispatchMouseEvent.
I can't seem to figure out how to specify the target element as there is no link between the two functions and DOM.NodeId, or an intermediate API that accepts a DOM.NodeId which then returns an X,Y co-ordinate.
I know that it's possible to use Selenium, but I'm interested in doing directly using WebSockets.
Any help is appreciated.
Brief Intro
I'm currently working on a NodeJS interaction library to work with Chrome Headless via the Remote Debugging Protocol. The idea is to integrate it into my colleague's testing framework to eventually replace the usage of PhantomJS, which is no longer being supported.
Evaluating JavaScript
I'm just experimenting with things currently, but I have a way of evaluating JavaScript on the page, for example, to click on element via a selector reference. It should in theory work for anything assuming my implementation isn't flawed.
let evaluateOnPage: function (fn) {
let args = [...arguments].slice(1).map(a => {
return JSON.stringify(a);
});
let evaluationStr = `
(function() {
let fn = ${String(fn)};
return fn.apply(null, [${args}]);
})()`;
return Runtime.evaluate({expression: evaluationStr});
}
}
The code above will accept a function and any number of arguments. It will turn the arguments into strings, so they are serializable. It then evaluates an IIFE on the page, which calls the function passed in with the arguments.
Example Usage
let selector = '.mySelector';
let result = evaluateOnPage(selector => {
return document.querySelector(selector).click();
}, selector);
The result of Runtime.evaluate is a promise, which when is fulfilled, you can check the result object for a type to determine success or failure. For example, subtype may be node or error.
I hope this may be of some use to you.
this protocol is probably not the best if you are wanting to click on specific elements rather than clicking on spots on the screen...
It's important to keep in mind that this area of the devtools protocol is intended to emulate the raw input. If you want to try and figure out the position of the elements using the protocol or by running some javascript in the page you could do that, however it might be better to use something like target.dispatchEvent() with MouseEvent and inject the javascript into the page instead.

How to close browser popup in robot framework?

After login in Chrome browser, I am getting a save password popup from the browser. I want to handle that popup and want to close that using Robot Framework
Browse popup window
Thanks
This question has been asked and answered before with a pure Python context. This answer continues on this SO post for a working Robot Example.
The popup you see is generated by Chrome itself. It's not an HTML alert. For this reason none of the Selenium2Library keywords will have any effect on it. Nor wil settings cookies or javascript.
These settings can be manually set using the chrome://settings link. Go to advanced settings and then scroll down to Passwords and Forms. Untick the second item and this will prevent the popup.
To do the same automatically in Robot Framework the WebDriver needs to be started with additional preferences:
Chrome With Preferences
${chrome_options} = Evaluate sys.modules['selenium.webdriver'].ChromeOptions() sys, selenium.webdriver
${prefs} Create Dictionary credentials_enable_service=${false}
Call Method ${chrome_options} add_experimental_option prefs ${prefs}
Call Method ${chrome_options} add_argument --disable-infobars
Create WebDriver Chrome chrome_options=${chrome_options}
Go To https://secure.url.com
This key things here are credentials_enable_service=${false} where it is important to use ${false} and not false, as the latter is interpreted as a string and then added to Chrome as "false" instead of the correct value false.
The second item is that preferences are not added as arguments but through assigning a dictionary to the prefs property of the ChromeOptions() object like so: add_experimental_option prefs ${prefs}
I do not think this is real to be honest (as it's property of the browser.) Are you having issues with that? The only thing you can dismiss is javascript alert and probably the best way to handle this is:
${alert} = Get Alert Message dismiss=${dismiss}
I have this in my test teardown with Run Keyword and Ignore Error, it makes me able to fetch optional js alert content and debug (also dismisses it do the rest of the suite can be executed.)
Three Ways To do do it.
1) Many a times, Once pop-up appear on screen and Disappear a cookie is set which you can view in developer console-> application. If you set this cookie with value using Add Cookie keyword. Pop- up wont appear.
2) if first doesn't work, then open developer tools and monitor the local store from developer tools -> application and close the pop-up. U will notice some variable with a value is stored in local storage. You can set that value using your script and u wont see the pop-up while executing variable.
3) If first and second doesn't work, the pop-up is most likely linked to a javascript variable. set java script variable using Execute Javascript Keyword and your problem must be solved.
Talk with your dev team, to see which way will work for you.

How do I clear cached angularjs files

I have an angularjs based web application with some functionality deployed to users that I need to hide. I've added the code to hide it and successfully verified the controls are hidden when appropriate but there are still users who have the old version of the file and can perform the undesired activities. Is there a way I can control from the server the view file to refresh on the client? (The tester was able to clear their cache but it's a burden to the users in the field)
Thanks!
Scott
One way to handle this would be to version the files. For example, the following line in your index.html
<script src="abc.js" />
could be rewritten as
<script src="abc.js?v1" />
v1 is the current file version and should be changed for each deployment of your application when abc.js has changed.
Since index.html(the initial page) is obtained from the server, updations to abc.js will now be reflected on all your clients.
This would need to be automated in a huge application. You could use Grunt for this. You can refer the following answer on StackOverflow for automating this:
https://stackoverflow.com/a/20446748/802651
UPDATE
HTML views/templates are cached using $templateCache in AngularJS. Basically, when you request templates for the first time, browser requests the template from the server and puts it in the template cache. Any subsequent requests to the same template are served from the template cache.
If you do not want these to be cached, you could listen to the $routeChangeStart event inside app.run block to remove the specific templates.
app.run(function($rootScope, $templateCache) {
$rootScope.$on('$routeChangeStart', function(event, next, current) {
if (typeof(current) !== 'undefined'){
$templateCache.remove(current.templateUrl);
}
});
});
Reference: http://opensourcesoftwareandme.blogspot.in/2014/02/safely-prevent-template-caching-in-angularjs.html

Chromium + Raw Html (directly from a C# string) + Angular => Problems when attempting to use routing

CefSharp: 1.25.0 (based on Chromium 25.0.1364.152)
Angular: 1.3.0-beta16
UIRouter: 0.2.10
I'm developing a stand-alone C# application that uses CefSharp Chromium + Angular + UIRouter as the stack upon which the GUI will be relying on.
I hit it off by trying to make the above stack load the sample-code provided here:
http://scotch.io/tutorials/javascript/angular-routing-using-ui-router
For the sake of elegance the HTML + Javascript-libs of the GUI, get cobundled in a single resource file inside the .Net executable of the application.
This resource is then passed programmatically during application-init to the Chromium control (by means of .LoadHtml) to be loaded directly into the browser, aka the HTML is not loaded from a separate .html file residing in the hard-drive or on a remote HTTP server. If the HTML gets loaded from the later ("standard") venues then everything works flawlessly.
I noticed that when loading the HTML directly as a string, as described above, the url of the resulting static web page (aka window.location) is set to 'about:blank'. It appears that angular has some sort of pet peeve with such a url, especially when it comes to using routing:
First of all, the invocation of:
history.pushState(null, "", url);
inside
self.url = function(url, replace) { ... }
throws an exception ala
Error: SecurityError: DOM Exception 18
Error: An attempt was made to break through the security policy of the user agent.
at Browser.self.url (about:blank:8004:21)
at about:blank:10049:24
at Scope.$eval (about:blank:11472:28)
at Scope.$digest (about:blank:11381:31)
at Scope.$apply (about:blank:11493:24)
at about:blank:6818:15
at Object.invoke (about:blank:7814:19)
at doBootstrap (about:blank:6817:16)
at bootstrap (about:blank:6827:14)
at angularInit (about:blank:6796:7)
the url that is passed to .pushState is:
about:blank#/home
which appears to be the result of concatenating 'about:blank' with the default state '/home'.
Secondly, even if the above problem is solved there appears to be a major issue inside:
$rootScope.$watch(function $locationWatch() { ... })
which causes the following error:
Error: [$rootScope:infdig] 10 $digest() iterations reached. Aborting!
the reason is that when 'window.location' is set to 'about:blank' then
$browser.url()
always returns
about:blank
while
$location.absUrl()
returns
about:blank#/home
causing $watch to fire non-stop.
Is there any proper way to handle this shortcoming of angular when its dealing with web pages loaded directly into the browser in the manner described here?
If there is no workaround for this issue then I'm afraid that I will have to resort to loading the HTML directly from a file in the hard drive, which apart from being slower (can't cache the string to memory for subsequent usages), it's also a noticable deviation from the goal of developing a stand-alone-exe. :(
Thanks in advance and I apologize if this issue has been addressed elsewhere.
By default Firefox allows loading of external files within html file that loaded from "file:///...". but Chrome does not. in CefSharp(Chrome) you can do it in this way:
// Allow angular routing and load external files
BrowserSettings setting = new BrowserSettings();
setting.FileAccessFromFileUrls = CefState.Enabled;
browser.BrowserSettings = setting;
this.Controls.Add(browser);
Most browsers don't allow to do AJAX on the file-system. But Chromium can be tweaked to do so:
browser = new ChromiumWebBrowser(path);
browser.BrowserSettings = new BrowserSettings();
browser.BrowserSettings.FileAccessFromFileUrlsAllowed = true;

Is there a way to target specific file in Box app on IOS through box:// url scheme?

Box:// seems to open the app, however I am not able to discern how to target a specific file.
Currently we don't have support for this, but it is a great idea that we'll consider for our roadmap.
We actually do support this. The best way to add this integration into your app is to use our OneCloud AppToApp framework (additional information available here http://developers.box.com/the-box-sdk-for-onecloud-on-ios/)
This is easy using the app-to-app framework. You just need to call BoxAppToAppAPI's sendFileDownloadRequestToApplication:withMetaData: if you want an app to go to a particular file and in Box's case download/preview it.
To make it go to the Box app you can simply pass in [BoxAppToAppApplication BoxApplication] in the first parameter.
As for the metadata parameter, you can create it with BoxAppToAppFileMetadata's appToAppFileMetadataWithFileName:fileExtension:folderPath:mimeType:fileID:folderPathByID:exportToken:username:
Assuming your app already integrates with the Box API via the SDK or otherwise, it should be able to get all of that information easily.
If the mimeType is not known, nil can be passed in. Also, nil can be passed in for the exportToken if the file was not exported out of the Box app (with the AppToApp framework, a roundtrip scenario is also supported where the user starts in the Box app, picks a file to view/edit/etc in your app, and then sends it back to Box to upload). So if it's not a round-trip, it's just a one-way from your app to Box, use nil for the exportToken.
Before doing this, you can also check if the Box app is installed by checking for [[BoxAppToAppApplication BoxApplication] isInstalled].
Below is a fictional example (the values are made up):
BoxAppToAppFileMetadata *metadata = [BoxAppToAppFileMetadata appToAppFileMetadataWithFileName:#"fileName"
fileExtension:#"png"
folderPath:#"All Files/Folder1"
mimeType:nil
fileID:[NSNumber numberWithLongLong:123456]
folderPathByID:#"0/12345"
exportToken:nil
username:#"username#email.com"]
BoxAppToAppStatus status = [BoxAppToAppAPI sendFileDownloadRequestToApplication:[BoxAppToAppApplication BoxApplication]
withMetaData:metadata];