In my project, I have a QWebView that loads a page that opens a pop-up window. But the window won't open. I looked into the createWindow function but I have no clue how to subclass a widget. These are some settings I put onto the webView:
QWebSettings *settings = ui->webView_2->settings();
settings->setAttribute(QWebSettings::JavascriptEnabled, true);
settings->setAttribute(QWebSettings::JavascriptCanOpenWindows, true);
What is the easiest way to allow my webView to allow pop-up windows?
Thanks for your time :)
You need to reimplement QWebView's createWindow method. The QWebView returned will be set to the required URL automatically.
For example:
QWebView* WebView::createWindow(QWebPage::WebWindowType type)
{
// WindowDialog is just a simple QDialog with a QWebView
WindowDialog* dlg = new WindowDialog(this);
dlg->show();
// A method to retrieve a pointer to the QWebView of the dialog is needed
return dlg->webView();
}
Keep in mind that cookies do not share between the two QWebViews, so you also need to implement your own cookie manager. One way to do it would be to inherit QNetworkCookieJar, and keep a static "global" instance.
Related
Im Building a webview app in ElectronJs, Im using a Custom User Agent to make the user interact with the webApp. When the user clicks on links that has target="_blank" property, it opens a new tab and not using the custom user agent.
any ideas?
the target=_black will create a new browserWindow Object so a think that you could track this events with the webContents api and apply the custom userAgent to this new browserwindow objects. for example:
you need this webContents event on your main window
win.webContents.setWindowOpenHandler(({ url }) => {
/*
Here you will allow the browserWindow creation and configure it
look a bit of the documentation here https://www.electronjs.org/es/docs/latest/api/web-contents#contentssetwindowopenhandlerhandler
*/
}
this SetWindowOpenHandler event will allow the window creation, now with the event did-create-window you will get the new BrowserWindow object and with that reference you will be able to set the custom userAgent
win.webContents.on('did-create-window', (childWindow) => {
/*
Here you can use childWindow to set the new user agent for example
here documentation for did-create-window https://www.electronjs.org/es/docs/latest/api/web-contents#evento-did-create-window
*/
childwindow.webContents.setUserAgent('your-custom-user-agent)
});
I hope that helps you, bye!
I’ve done a lot of research on and off Stackoverflow and I’ve read many posts and tried many suggestions to no avail.
So I am posting a new question since all the answers that I have read haven’t led me to a solution.
Issue: I need to close all tabs that I’ve opened via window.open() function.
My original implementation uses LocalStorage to keep track of tabs that have been open via the parent window.
When a link is clicked (in the parent window), a new tab is open via window.open(“url”, “uniqueId”);
I store the uniqueId in an array in localstorage which in essence is my list of tabs.
To close all the windows that I opened, I loop through the localStorage array (the tablist).
I get the window uniqueId which I use to reference and close the (child) window…
// (localstorage) myTabList': [“window1”,” window2”,” window3”,” window4”]
var arr = JSON.parse(localStorage.getItem(‘myTabList'));
for (var i = 0; i < arr.length; i++) {
newWindowObj = window.open('', arr [i]);
if (newWindowObj != null) {
newWindowObj.close();
}}
This works like a charm as long as the (child) window.name doesn’t change.
Unfortunately, the names of some of the (child) tabs do change.
I have no control over the child tabs.
Think of if as if I open Google or Bing website in a child tab and the name changes.
Parent window (tab)
link A <a href=”#” #click=”window.open(‘http://www.google.ca’,’GOOGLE’) ”>Google</a>
link B <a href=”#” #click=”window.open(‘http://www.bing.com,’BING’)”>Bing</a>
I should point out that the tabs that change names load 3rd party web apps that are cross domain.
My app (parent tab web app) is a Vue 2.x project. Since the implementation described above doesn’t work as desired when a window name changes, I need a different solution.
I thought I could persist the tabs (window object) in an array of windows using the “vuex-presistedstate”.
If I use simple objects with Strings (just for testing purposes) to store data, all works flawlessly. e.g. storing objects containing String properties in an array {“url”:’http;//www.google.com”, “name”: “GOOOGLE”}, {“url”:’http;//www.bing.com”, “name”: “BING”}
But I run into issues when I try to store actual window objects.
var myTabList = [];
var newWinRef = window.open(“url”, “uniqueId”);
myTabList.push(newWinRef);
The storage of the window seems OK… based on the console output.
But it’s followed by this message.
Error in v-on handler: "TypeError: Converting circular structure to JSON
-- starting at bojec with constructor 'Window'
-- propery 'widow' closes the circle
So this solution doesn’t works very well either.
All I am trying to do is to open a window via window.open and persist some info about the newly opened windows / tab so that I can identify the tab(s) and call window.close() to close the child tab.
Any suggestions would be much appreciated.
Thank you!
well google translate extension in chrome, has popup feature, it displays translation of selected word instantly, I wanted to access those translations displayed by popup, but this popup element is shadowRoot("closed"), so javascript cant access its content, I red an article about that subject and author says:
But really there is nothing stopping someone executing the following JavaScript before your component definition.
Element.prototype._attachShadow = Element.prototype.attachShadow; Element.prototype.attachShadow = function () { return this._attachShadow( { mode: "open" } ); };
Is it possible to change attachShadow method of other extension? if so where should it be executed by my extension? background_script or maybe somewhere. I think each extension has its own enviroment and I have no chane to edit their methods. I wish I'm wrong :)
No need to override it.
There's a special method in the content script.
Chrome 88+:
let shadowRoot = chrome.dom.openOrClosedShadowRoot(element);
Firefox 63:
let shadowRoot = element.openOrClosedShadowRoot();
Combined:
let shadowRoot = chrome.dom?.openOrClosedShadowRoot(element)
|| element.openOrClosedShadowRoot();
It seems it's fairly common practice to grab the contents of a Google-calendar embed code, and add a stylesheet into it (either manually or through something like a PHP script) and display a custom-styled public calendar.
The odd thing is, I noticed if you click the print button at the top, or the "Google Calendar" in the lower right, it goes to localhost or whatever domain the page is - not the Google calendar.
If you try to trace the "gcal$func$[3]();" onclick through the Chrome devtools, or through Firefox with gcal$func$[3].toSource(); it will not find it or say
"function () {
[native code]
}"
So where is this function coming from, and how can you tweak this to make it open in a new window with the Google url, not the current domain (404)?
According to the Google Calendar embed JS code, the function points to the following code
window.open(Pf(this.c.i.Nb + "/render", "cid", b))
this.c.i.Nb represents the base URL, which is by default the domain where the script runs (in your case that's your domain). However, it's intended to be google.com domain and fortunately, it's very easy to change that. baseURL is one of the parameters in the initialization script (declared in the page you're grabbing) and you just need to configure that to https://www.google.com.
If you use PHP, your code might look like this.
$page = new DOMDocument("1.0", "utf-8");
// grab the Google Calendar code
$page->loadHTMLfile("https://www.google.com/calendar/embed?src=yourcalendar%40gmail.com");
// set up the baseUrl and print the grabbed page
echo str_replace('"baseUrl":"/"', '"baseUrl":"https://www.google.com/"', $page->saveHTML());
Now all the links should work correctly.
I have been able to get content out of WebView using javascript and loadUrl() method having specified an interface thats called from javascript string that is injected into WebView.The problem is that this only works for me when the loadUrl() method is present in onPageFinished() method in the WebView client. What I want to do is I want to get the content out of the WebView (with the content already loaded). The WebView is in an activity instrumentation test case and I can for instance use findAll() method and that works fine. For some reason I can not use loadUrl() and get the desired behaviour (which is injecting javascript and getting content out of the WebView with a help of an interface).
PLease help.
Thanks
Pawel
EDIT:
Just adding code to show what I am doing exactly:
Yes I understand that but my problem is that I am trying to do it within a test case this way:
public void testWebView() throws Exception {
solo.sleep(3000); // wait for views to load on the screen
WebView a=null;
ArrayList<View> views = solo.getCurrentViews(); // I am using solo object to get views for the screen currently loaded
for(View s:views)
{
if (s instanceof WebView)
{
a = (WebView)s; // this is where I get my WebView
}
}
Instrumentation inst = getInstrumentation();
inst.runOnMainSync(new Runnable()
{
public void run()
{
int d =a.findAll("something"); // this method runs fine on the object and i get the desired result
WebSettings settings = a.getSettings();
settings.setJavaScriptEnabled(true);
a.loadUrl("javascript:document.location = document.getElementById('google').getAttribute('href')"); // this javascript is never executed and that is my problem
}
});
}
You can inject javascript in a loaded page much the same way you can do it in desktop browsers - via inline javascript entered into navigation bar.
Bind some Java object so that it can be called from Javascript with WebView:
addJavascriptInterface(javaObjectExposed, "JSname")
Force execute javascript within an existing page by
WebView.loadUrl("javascript:window.JSname.passData("some data from page");");