I am trying to refresh an element in the DOM tree. Basically the typescript code simply update the data & type of an existing HTMLObjectElement. Here is the pseudocode:
const textCanvas: HTMLObjectElement = <HTMLObjectElement>(curElement.children.namedItem('text-canvas'));
// Populate both the actual data as well as the associated mime/type:
textCanvas.data = enabledTextElement.textData; // 'blob:http://localhost:8081/d3c9a0ac-8e40-4e0e-aeb8-91656273837c'
textCanvas.type = enabledTextElement.mimeType; // 'application/pdf'
Which then gets updated with:
textCanvas.data = enabledTextElement.textData; // 'blob:http://localhost:8081/3c5ad888-0a7f-41d0-8ec9-35c334ef3f20'
textCanvas.type = enabledTextElement.mimeType; // 'text/html'
My chrome simply display the PDF version:
The funny part is if I do the opposite (html first), then the element gets properly updated (html text is displayed, then the PDF box is displayed). I tried to verify if this is supposed to work at:
https://html.spec.whatwg.org/multipage/iframe-embed-object.html#the-object-element
And it seems it should. I also found an old bug report:
https://bugs.chromium.org/p/chromium/issues/detail?id=123536
-> <object> works in every browser except Google Chrome
Using:
Google Chrome 80.0.3987.163 (Official Build) (64-bit) (cohort: 81_Win_122)
Revision e7fbe071abe9328cdce4ffedac9822435fbd3656-refs/branch-heads/3987#{#1037}
OS Windows 8.1 (Build 9600.19676)
JavaScript V8 8.0.426.30
If that help the URL are created from a Blob which is then passed to URL.createObjectURL.
I am currently using the following work-around:
textCanvas.data = '';
textCanvas.type = enabledTextElement.mimeType;
textCanvas.data = enabledTextElement.textData;
Seems to make the symptoms go away. I've filled a bug report just in case:
https://bugs.chromium.org/p/chromium/issues/detail?id=1076373
Related
Is Chrome blocking access to the webstore url?
I would like to make an extension that displays a like button beside the +1 button, but it looks like that content scripts are not working on https://chrome.google.com/webstore/*
Is that true?
TL;DR The webstore cannot be scripted by extensions, and the flag that previously allowed you to do that (--allow-scripting-gallery) has been removed in Chrome 35.
Chrome extensions cannot execute Content scripts / insert CSS the Chrome Web Store. This is explicitly defined in the source code, at function IsScriptableURL (click on the previous link to see the full logic).
// The gallery is special-cased as a restricted URL for scripting to prevent
// access to special JS bindings we expose to the gallery (and avoid things
// like extensions removing the "report abuse" link).
// TODO(erikkay): This seems like the wrong test. Shouldn't we we testing
// against the store app extent?
GURL store_url(extension_urls::GetWebstoreLaunchURL());
if (url.host() == store_url.host()) {
if (error)
*error = manifest_errors::kCannotScriptGallery;
return false;
}
manifest_errors::kCannotScriptGallery is defined here:
const char kCannotScriptGallery[] =
"The extensions gallery cannot be scripted.";
The error can be viewed in the background page's console when you use chrome.tabs.executeScript to inject a script in a Web Store tab. For instance, open https://chrome.google.com/webstore/, then execute the following script in the background page of an extension (via the console, for live debugging):
chrome.tabs.query({url:'https://chrome.google.com/webstore/*'}, function(result) {
if (result.length) chrome.tabs.executeScript(result[0].id, {code:'alert(0)'});
});
I've created a Winforms app that uses a WebBrowser control; I dynamically assign its Uri. It worked fine for awhile, but now I'm getting this msg:
You seem to be using an unsupported browser. Older browsers can put your security at risk, are slow and don't work with newer Google Maps features. To access Google Maps, you'll need to update to a modern browser.
The last two words are a link, and following that link, I see:
You are currently using...
IE 11
So, okay, the WebBrowser component uses IE 11; how can I change that?
My machine is set to use Chrome as its browser; perhaps the control should use whatever your current browser is? I don't know if that's possible/feasible.
UPDATE
Okay, I'm willing to give Reza's suggestion a try. But when I navigate to the specified spot in regedit, and right-click in the right pane to add a New entry, it has three options:
Key, String Value, Binary Value
I reckon the string values are the ".exe" strings, and the Binary values are the "dword" vals, but what should the "Key" values be?
Note: The post is about WebBrowser control, however, for all the new
.NET projects the main solution is using
WebView2.
To learn more, take a look at this post:
Getting started with WebView2.
WebBrowser Control
The WebBrowser control uses the same Internet Explorer version which is installed on your OS but it doesn't use the latest document mode by default and shows content in compatibility mode.
Symptom - As a symptom, the site works properly in Internet Explorer or other browsers, but WebBrowser control doesn't show the site well and for some sites it shows script errors.
Solution - You can tell the WebBrowser control to use the latest document mode without compatibility mode in WebBrowser control. You can follow instructions here to disable the setting using registry.
[Reference: Browser Emulation]
Apply Browser Emulation setting using code
If you want to apply the settings using code, run the following code once:
using (var key = Microsoft.Win32.Registry.CurrentUser.OpenSubKey(
#"Software\Microsoft\Internet Explorer\Main\FeatureControl\FEATURE_BROWSER_EMULATION",
true))
{
var app = System.IO.Path.GetFileName(Application.ExecutablePath);
key.SetValue(app, 11001, Microsoft.Win32.RegistryValueKind.DWord);
key.Close();
}
In above code, I've used 11001 which means IE11 Edge mode.
Internet Explorer 11. Webpages are displayed in IE11 edge mode,
regardless of the declared !DOCTYPE directive. Failing to declare a
!DOCTYPE directive causes the page to load in Quirks.
Apply the Browser Emulation setting manually
Open Registry editor and browse HKEY_CURRENT_USER, go to the following key:
Software\Microsoft\Internet Explorer\Main\FeatureControl\FEATURE_BROWSER_EMULATION
Add the following values:
"YourApplicationFileName.exe"=dword:00002af9
"YourApplicationFileName.vshost.exe"=dword:00002af9
(In older versions of Visual Studio you needed to add vshost.exe value as well, when you run your program in Visual Studio.)
To create entries right click on an empty area of the right pane, then in the window which appears after selecting dword value, choose hexadecimal and enter 2af9:
In above steps, I've used 11001 which means IE11 Edge mode.
Use WebViewCompatible Control for Windows Forms
You can also use the new WebViewCompatible control for Windows Forms. You can see simple steps to use here: Replace WebBrowser control by new WebView Compatible control for Windows Forms.
WebViewCompatible uses one of two rendering engines to support a broader set of Windows clients:
On Windows 10 devices, the newer Microsoft Edge rendering engine is used to embed a view that renders richly formatted HTML content from a remote web server, dynamically generated code, or content files.
On devices running older versions of Windows, the System.Windows.Controls.WebBrowser is used, which provides Internet Explorer engine-based rendering.
Note: WebView2 is a replacement for WebView and WebViewCompatible.
Set X-UA-Compatibile meta tag
In case that you have access to the html content of the page and you can change the content (for example it's a local html file, or the site belong to yourself) then you can set X-UA-Compatibile meta tag in the head like: <meta http-equiv="X-UA-Compatible" content="IE=Edge" />.
Use other Browser Controls
You can rely on other browser controls like CefSharp.
In my case for embedded custom protocol on an application, I will allow only to browse pages served by the application, and no content from the outside, so I wanted to skip saving to the Windows Registry. When I tested after following Reza Aghaei answer and found that you can change the compatibility mode from within the content page. This will skip the need to configure a registry key, but you will have to add it to every page.
For changing the compatibility mode of a page, you must add a meta tag for it to be applied by the rendering engine:
<html>
<head>
<meta http-equiv="X-UA-Compatible" content="IE=Edge" />
</head>
<body>
...
</body>
</html>
The below procedures will add the correct key and remove it again.
Call the CreateBrowserKey upon loading the form that your web browser is in.
Then when closing the form, call the RemoveBrowserKey
Private Sub CreateBrowserKey(Optional ByVal IgnoreIDocDirective As Boolean = False)
' Dim basekey As String = Microsoft.Win32.Registry.CurrentUser.ToString
Dim value As Int32
' Dim thisAppsName As String = My.Application.Info.AssemblyName & ".exe"
' Value reference: http://msdn.microsoft.com/en-us/library/ee330730%28v=VS.85%29.aspx
' IDOC Reference: http://msdn.microsoft.com/en-us/library/ms535242%28v=vs.85%29.aspx
Select Case (New WebBrowser).Version.Major
Case 8
If IgnoreIDocDirective Then
value = 8888
Else
value = 8000
End If
Case 9
If IgnoreIDocDirective Then
value = 9999
Else
value = 9000
End If
Case 10
If IgnoreIDocDirective Then
value = 10001
Else
value = 10000
End If
Case 11
If IgnoreIDocDirective Then
value = 11001
Else
value = 11000
End If
Case Else
Exit Sub
End Select
Microsoft.Win32.Registry.SetValue(Microsoft.Win32.Registry.CurrentUser.ToString & BrowserKeyPath, _
Process.GetCurrentProcess.ProcessName & ".exe", _
value, _
Microsoft.Win32.RegistryValueKind.DWord)
End Sub
Private Sub RemoveBrowserKey()
Dim key As Microsoft.Win32.RegistryKey
key = Microsoft.Win32.Registry.CurrentUser.OpenSubKey(BrowserKeyPath.Substring(1), True)
key.DeleteValue(Process.GetCurrentProcess.ProcessName & ".exe", False)
End Sub
The C# WebBrowser class is a basically a IE wrapper and because of this it cannot be changed.
See this link:
The WebBrowser control is a managed wrapper around a component installed with Internet Explorer.
For alternatives you can check out
WebKit.NET
GeckoFX
This page was developed in english which works well in Chrome and Edge browsers. Some community members asked then to translate it to Chinese. Same strategy to create the page was taken with the following resulting page.
The problem is that sometimes the Chinese version page doesn't load. Specially when pasting the URL from somewhere else. In the other hand when navigating from the landing page, blog area, it displays correctly.
How to fix that so that it works for every browser correctly.
One interesting thing I just noticed was that sometimes copying the link results in:
https://ethereumclassic.github.io/blog/2017-08-27-社会币的崛起/
Sometimes in:
https://ethereumclassic.github.io/blog/2017-08-27-%E7%A4%BE%E4%BC%9A%E5%B8%81%E7%9A%84%E5%B4%9B%E8%B5%B7/
check the vendor of bundle.js for updates. It appears to be an old version.
function webpackContextResolve(req) {
return map[req] || (function() { throw new Error("Cannot find module '" + req + "'.") }());
// error occurs in above.
};
To debug web site load code, first navigate to a blank page (about:blank). Then display and pin the dev tool to the blank page.... select the debug tab of dev tools and choose "Break on All Exceptions" from the dropdown.. (looks like a Stop sign).
Without closing the dev tool, return to the blank page and navigate to the English and then the Chinese sites.... the dev tool will now break on errors.
To debug browser sniffing issues. (find code that uses browser userAgent sniffing to load different versions of a web site). Use the debug tab of the dev tool to find occurrences of "navigator" or "userAgent".
You can test if a web site is incorrectly determining the browser features by changing the userAgent header from the Emulation tab of dev tools. Oddly, changing the UAS in dev tools in IE11 has the same result... suggesting that the enableLazy assignment in bundle.js is the cause.
var enableLazy = typeof document !== 'undefined' && typeof document.documentMode === 'number' || typeof navigator !== 'undefined' && typeof navigator.userAgent === 'string' && /\bEdge/\d/.test(navigator.userAgent);
bundle.js seems to be a problem.... check the vendors website for updates to their software....
Also... you have set the page language to en... it should be zh. eg.lang="zn"......
I have detected some problems due to the url encoding and difference between lower and uppercase characters.
With PHP i am doing a URI conversion previous the router parse:
if(strpos($_SERVER['REQUEST_URI'], '%') > 0){
$uri = $_SERVER['REQUEST_URI'];
$result = preg_replace_callback(
'/\%(\w{2})/',
function ($matches) {
return strtoupper($matches[0]);
} ,
$uri
);
$_SERVER['REQUEST_URI'] = $result;
}
Your problem is the bundle.js by removing it i obtained your webpage without any problem:
Did you put it in an unsupported event?
The js says:
NOTE: This will not work correctly for non-generic events such as
change, * reset, load, error, and select. *
I just updated my Chrome browser (Version 50.0.2661.75) and have found that the chrome://downloads page has changed such that my automated tests can no longer interact with it. Previously, I had been using Watir-Webdriver to clear the downloads page, delete files from my machine, etc, without too much difficulty.
It looks like Google is using Polymer on this page, and
there are new (to me) elements like paper-button that Watir-Webdriver doesn't recognize
even browser.img(:id, 'file-icon').present? returns false when I
can clearly see that the image is on the page.
Is automating a page made with Polymer (specifically the chrome://downloads page) a lost cause until changes are made to Watir-Webdriver, or is there a solution to this problem?
Given that the download items are accessible in Javascript and that Watir allows Javascript execution (as #titusfortner pointed out), it's possible to automate the new Downloads page with Watir.
Note the shadow root elements (aka "local DOM" in Polymer) can be queried with $$.
Here's an example Javascript that logs the icon presence and filename of each download item and removes the items from the list. Copy and paste the snippet into Chrome's console to test (verified in Chrome 49.0.2623.112 on OS X El Capitan).
(function() {
var items = document
.querySelector('downloads-manager')
.$$('iron-list')
.querySelectorAll('downloads-item');
Array.from(items).forEach(item => {
let hasIcon = typeof item.$$('#file-icon') !== 'undefined';
console.log('hasIcon', hasIcon);
let filename = item.$$('#file-link').textContent;
console.log('filename', filename);
item.$.remove.click();
});
})();
UPDATE: I verified the Javascript with Watir-Webdriver in OS X (with ChromeDriver 2.21). It works the same as in the console for me (i.e., I see the console logs, and the download items are removed). Here are the steps to reproduce:
Run the following commands in a new irb shell (copy+paste):
require 'watir-webdriver'
b = Watir::Browser.new :chrome
In the newly opened Chrome window, download several files to create some download items, and then open the Downloads tab.
Run the following commands in the irb shell (copy+paste):
script = "(function() {
var items = document
.querySelector('downloads-manager')
.$$('iron-list')
.querySelectorAll('downloads-item');
Array.from(items).forEach(item => {
let hasIcon = typeof item.$$('#file-icon') !== 'undefined';
console.log('hasIcon', hasIcon);
let filename = item.$$('#file-link').textContent;
console.log('filename', filename);
item.$.remove.click();
});
})();"
b.execute_script(script)
Observe the Downloads tab no longer contains download items.
Open the Chrome console from the Downloads tab.
Observe the console shows several lines of hasIcon true and the filenames of the downloaded items.
Looks like Google put the elements inside the Shadow-Dom, which isn't supported by Selenium/Watir/WebDriver spec (yet). There might a way to obtain the element via javascript (browser.execute_script(<...>)), but it is experimental at best still.
Attempting to automated a Polymer page, I found I was able to access the web elements by asking Polymer to use the shady dom by adding ?dom=shady in the URL. Like in the example on this page https://www.polymer-project.org/1.0/docs/devguide/settings:
http://example.com/test-app/index.html?dom=shady
Adding the dom parameter to request Polymer to use the shady dom may be worth a try.
I'm writing an Google Chrome extension that lets you download a backup file of your data. I want the user to be able to press a button and a "Save as" dialog box should open and they can save the file to their computer. Nothing appears to work and I have not found an answer on the internet. I have tried several approaches:
Using document.execCommand('SaveAs', null, 'filename.json'); This does not work because this command is IE-only and there does not appear to be a Webkit-alternative
Using data URIs. This was the most promising and worked in Opera and Firefox, but the problem being that neither Chrome nor Safari appear to support the Content-disposition=attachment;-header in the URI. This should work. (Chrome doesn't even allow me to ctrl/cmd+s a page from a data URI)
Using an XMLHTTPRequest. I haven't tried this, but there has to be some way in which you could relay the request around? Please note that I do not want to use an external server (in that case I could have simply sent a POST-request and applied a Content-disposition:-header)
Using an available Chrome Extension API. But there does not seem to be anything for this purpose.
The reason I don't want to use any external server is that I don't want to have to pay for the hosting, and the data sent might be sensitive to the user, and I don't want infringe on anyone's privacy.
Has anyone gotten this to work?
I did it as follows in Appmator code on Github.
The basic approach is to build your Blob, however you want (Chrome/WebKit/Firefox has a responseBlob on XmlHttpRequest so you can use that), create an iframe (hidden, display:none) then assign the src of the iframe to be the Blob.
This will initiate a download and save it to the filesystem. The only problem is, you can't set the filename yet.
var savaeas = document.getElementById("saveas");
var bb = new (window.BlobBuilder || window.WebKitBlobBuilder)();
var output = Builder.output({"binary":true});
var ui8a = new Uint8Array(output.length);
for(var i = 0; i< output.length; i++) {
ui8a[i] = output.charCodeAt(i);
}
bb.append(ui8a.buffer);
var blob = bb.getBlob("application/octet-stream");
var saveas = document.createElement("iframe");
saveas.style.display = "none";
if(!!window.createObjectURL == false) {
saveas.src = window.webkitURL.createObjectURL(blob);
}
else {
saveas.src = window.createObjectURL(blob);
}
document.body.appendChild(saveas);