Follow up to this question:
apply downloaded CSS on windows 8 metroUI app
So, yes, Windows says "for security reasons, you cannot navigate to HTML you have downloaded to this location and you cannot run any executable or potentially executable code, such as script or CSS. It is intended for media such as images or videos and the like."
But I really, really want to use that css file from my local storage. Shouldn't I be able to use the execUnsafeLocalFunction method to bypass this restriction like this?:
MSApp.execUnsafeLocalFunction(function () {
el["href"] = "ms-appdata:///local/style.css"
});
It still throws "An app can’t load remote web content in the local context."
I also tried just reading the file with localFolder.getFileAsync and readText, but nothing seems to help. Is there really no way to work around this?
I think I found a way to get the CSS to load.
I tested the code below by adding a css file that sets the body background to red in the local storage folder.
The code reads the contents of the file, creates a style tag in the head and adds the content of the css file to the style.
var url = new Windows.Foundation.Uri(filename);
Windows.Storage.StorageFile.getFileFromApplicationUriAsync(url).then(function (file) {
Windows.Storage.FileIO.readTextAsync(file).then(function(text) {
var style = document.createElement("style");
style.innerText = text;
document.getElementsByTagName("head")[0].appendChild(style);
});
});
Related
I'm writing a vscode extension where I'm hoping to squeeze more dynamic functionality out of markdown preview. Effectively the problem I'm trying to solve is:
In markdown preview, there's a checkbox
When user clicks the checkbox in markdown preview, send a message/event to the vscode extension runtime
Vscode extension can listen for this message/event and store the action in local storage
Checkbox state is saved - and subsequent renders of the markdown preview can use this action
Ideally, I'd like to do this while keeping the default markdown preview security (https://code.visualstudio.com/Docs/languages/markdown#_strict). After all, I don't need the extension to or markdown preview script to talk to a remote server - I just want them to be able to talk to one another.
Problem as code
To write the problem as sudo code, I want my markdown preview script to contain something like:
const button = ... // get button element
button.addEventListener('click', () => {
... /*
* Send a message to the vscode extension. Something like:
* `vscode.postMessage('vscode.my-extension.preview-action' + value)`
* (which I can't get to work, I'll discuss why)
*/
});
where then my extension can listen for messages like 'vscode.my-extension.preview-action'.
What I've Tried Already
I have tried acquireVsCodeApi() but because the markdown extension already does that, I can't do it again in the subsequent loaded script. I've also tried registering a uri handler but as far as I can try out the preview script still needs to fetch to that uri, which is still blocked by the default markdown security settings.
Perhaps markdown preview scripts are not the place to do this kind of thing, but I just wanted to leverage as much as possible that's already there with the vscode markdown extension. I want to supplement markdown but not replace it, the functionality I want to add is just icing on markdown documentation.
I've read https://code.visualstudio.com/api/extension-guides/markdown-extension#adding-advanced-functionality-with-scripts and it doesn't tell me much about markdown extension scripts capabilities and limitations.
Thanks to #LexLi I looked at some of the source code in the markdown extension and was able to come up with an ugly hack to make this work in preview scripts. Markdown allows normal clicks. And vscode extensions can handle normal clicks. I've paraphrased the code so there could be small syntax errors.
In the extension I did this:
vscode.window.registerUriHandler({
handleUri(uri: vscode.Uri): vscode.ProviderResult<void> {
console.log(`EXTENSION GOT URL: ${uri.toString()}`);
},
});
Then I made sure my extension/preview script put this in the document
<!-- in the preview script I place a button like this -->
<!-- it even works with hidden :) so I can do more app customization -->
<a
hidden
id="my-extension-messager"
href="vscode://publisher-id.my-extension"
>
cant see me but I'm there
</a>
Then my preview script I can even set href before faking a click:
const aMessager = document.querySelector("#my-extension-messager");
console.log('client is setting attribute and clicking...')
aMessager.setAttribute('href', 'vscode://publisher-id.my-extension?action=do-something');
aMessager.click();
console.log('client clicked');
Logs I saw (trimmed/tweaked from my particular extension to match the contrived example):
client is setting attribute and clicking...
client clicked
[Extension Host] EXTENSION GOT URL: vscode://publisher-id.my-extension?action%3Ddo-something
It's a hack but I can do a lot with this. Within the URL I can encode data back to the extension and kind of pass whatever I want (as long as data is relatively small).
In SAPUI5 I am using fileuploader to to upload file to gateway service.
Functionality works if I select file using by pressing "Browse" button, however if I set file path using using setValue() and after that call upload() function, file upload is not triggered. There are no errors in the browser.
This is the same behavior if I press upload button, but file path is not set. I suspect that there something additional that I need to set, but I have no idea what is that. Below is the code
UI
<u:FileUploader id="fileUploader"
tooltip="Select file to upload"
width="415px"
icon="sap-icon://add-document"
uploadOnChange="false"
sendXHR="true"
uploadUrl="/sap/opu/odata/sap/ZUPLOAD_DOC_SRV/Upload_DocSet"
useMultipart="false"
uploadStart="onUploadStart"
uploadComplete="handleUploadComplete"
sameFilenameAllowed="true"
change="onChange"/>
Controller
var oFileUploader = this.byId("fileUploader");
oFileUploader.removeAllHeaderParameters(oCustomerHeaderToken);
oFileUploader.setValue("C:\\TEMP\\test.txt");
oCustomerHeaderToken = new sap.ui.unified.FileUploaderParameter({
name: "x-csrf-token",
value: oFileUploader.getModel().getSecurityToken()
});
oFileUploader.addHeaderParameter(oCustomerHeaderToken);
var oSlug = new sap.ui.unified.FileUploaderParameter({
name: "slug",
value: slugTemp
});
oFileUploader.addHeaderParameter(oSlug);
oFileUploader.upload();
Can someone help me with this?
For security reasons this is not allowed in JavaScript by Browsers. This has nothing to do with UI5, it is a general security measure.
If it was allowed a script could access ALL your files by generating random paths, read them and upload them to ANY server.
In some browsers it's possible to access a sandboxed environment but it's unlikely that this will help you.
Accessing the complete hard drive is impossible (at the moment).
I have a fairly simply web app that uses expressjs and handlebarsjs to retrieve and format markdown files and render them as html to the browser. I'd like to write the html output to the disk instead of sending it to the browser ? I know there are static website generators out there, but I'd rather just modify the existing program a tiny bit instead of installing a whole new kitchen sink.
The standard filesystem library should be able to do this -
fs.writeFile(filename, html, function (err) {
if (err) throw err;
console.log('It\'s saved!');
});
Where filename is the filename, and html is the content you want to write to the file.
See the filesystem docs.
I have an MHT (Microsoft web archive) file that I have added to my project folder. I need this file to display in a WebView on a help page. I have set the file's build action to "Content," like this question reccomended. I then use this code in the page's Loaded event handler.
Try
Dim strHelpNavigate = Path.Combine(Windows.ApplicationModel.Package.Current.InstalledLocation.ToString(), "\MyAppsHelp.mht")
webHelp.Navigate(New Uri(strHelpNavigate))
Catch ex As Exception
webHelp.NavigateToString("<html><head><style>body {font-family: segoe ui; color: white; background-color: black;}</style></head><body><h2>Sorry, the help page is currently unavailable.</h2></body></html>")
End Try
This code produces an exception: {"Invalid URI: The format of the URI could not be determined."}
I have also tried passing "\MyAppsHelp.mht" to the Navigate method like this question reccomended, but this produces the same exception, and I see from the Local window that the string passed to the Navigate method is the same either way.
Does anyone have any advice on how to display this file in the WebView?
WebView does not natively support HTML archive files, but you can do the work convert these files to html + images if you're so inclined.
Open the .mht file in notepad, and you'll see that there are separate sections for each part of the HTML file - you can parse these sections to get the HTML out, then the base64 encoded images, then save them in your local app folder and use WebView.NavigateToLocalStreamUri to load them. See http://blogs.msdn.com/b/wsdevsol/archive/2014/06/20/a-primer-on-webview-navigatetolocalstreamuri.aspx for details on how to use this method.
OF course, if it's a static file that you will be using all of the time, it would be far easier to just convert it before packaging the app.
I'd like to reopen the question posed here and here about testing file uploading within Nightwatch.js which uses selenium.
Both links have the recommended solution of setting the value of the file input element as the url. In my use case, I've been unable to get this to work. Even setting the value tag manually, outside of nightwatch, of the input where type="file", does not change the url. I've tried this on Chrome, Firefox, and IE10, within the dev tools.
An alternative solution I've looked at was trying to emulate the entire file upload process keystrokes. This would follow the path of clicking the file upload button, typing the path, and typing enter. This would be done through the .click and .key methods. However, you lose focus of the actual file upload window, which delays the keystrokes until that window is closed. Other developers have seemed to be able to fix this solution directly in selenium using the .findElement and .sendKeys methods in java, but I could not figure out how to do this within javascript and nightwatch itself.
Any ideas?
// My test
module.exports = {
"Standard File Upload" : function (browser) {
browser
.url("http://localhost:3000")
.waitForElementVisible('body', 1000)
.waitForElementVisible('input[type="file"]', 1000)
.setValue('input[type="file"]','http://localhost:3000/testfile.txt')
.click('#submit')
.pause(1000)
.assert.containsText('h3', 'File Uploaded Successfully')
.end();
}
};
// http://localhost:3000/testfile.txt was tested manually in the file upload window and worked successfully
<!-- My input tag -->
<input id="fileUpload" type="file" name="textfile"/>
There were two seperate issues with my setValue() method implementation.
Using the --verbose tag in the nightwatch command led me to an issue
where it was not actually finding the input tag during the
setValue(), however it was during the waitForElementVisible().
Changing input[type="file"] to input#fileUpload solved this
issue.
Secondly, the following ways of describing the path were not working...
'textfile.txt'
'http://localhost:3000/testfile.txt' (Will work if typed manually into file upload window)
What did work was using require('path').resolve(__dirname + '/testfile.txt')
Take a look here to see the discussion that led to the fix. Thanks goes out to richard-flosi.
The working code:
module.exports = {
"Standard File Upload" : function (browser) {
browser
.url("http://localhost:3000")
.waitForElementVisible('body', 1000)
.waitForElementVisible('input#fileUpload', 1000)
.pause(1000)
.setValue('input#fileUpload', require('path').resolve(__dirname + '/testfile.txt')) // Works
// .setValue('input#fileUpload', "testfile.txt") // Will not work
// .setValue('input#fileUpload', "http://localhost:3000/testfile.txt") // Will not work
// .setValue('input[type="file"]', require('path').resolve(__dirname + '/testfile.txt')) // Will not work
.click('#submit')
.pause(1000)
.assert.containsText('h3', 'File Uploaded Successfully')
.end();
}
};
I'm not sure why you're having these issues, maybe check to see if you are using the latest version of selenium server and nightwatch. This code works for me 100% in Chrome, Safari, Firefox, IE7/8/9/10/11 (not tested in IE6 but assume it as well).
driver.setValue('input#fileUpload', __dirname + '\\testfile.txt')
In my case, I had an additional problem because the file I was trying to upload was too high up in my directory structure.
As soon as I moved the file to the same level (or in a subdirectory of) the actual test files, things worked.
From a script living in my page-objects folder:
// No dice:
var fullPath = require('path').resolve(__dirname + '/../../somefile.pdf');
// Works:
var fullPath = require('path').resolve(__dirname + '/../somefile.pdf');
this.setValue('input#fileUpload', fullPath);