I am working on a Firefox extension that would display the SSL certificate information to the user. The actual information would be the same as the one built in to the browser, but I will be experimenting with layouts and other information for UX.
I've been working with Firefox extensions instead of add ons due to deprecation of add-ons in 2017, but this project will be finished before then.
I was trying the example found here, but the extension seems to stop on the require("chrome").
Next I tried writing simpler code to figure out how the example works, but this code doesn't have a channel attached to the request. My code, minus all sorts of printing statements, is below:
document.getElementById("click_button").addEventListener("click",
function(e) {
var url = "https://secure-website-example.google.com";
xhr = new XMLHttpRequest();
xhr.open("GET", url, true);
xhr.addEventListener("error",
function(e) {
dumpSecurityInfo(xhr, -1);
}, false);
xhr.onload = function(e) {
dumpSecurityInfo(xhr);
};
xhr.send();
});
function dumpSecurityInfo(xhr, error) {
var channel = xhr.channel;
try {
console.log("Connection status:");
if (!error) { console.log("Succeeded"); }
else { console.log("Failed :("); }
var securityInfo = channel.securityInfo;
} catch(err) {
alert(err);
}
}
with a manifest like this:
"manifest_version": 2,
"name": "Certificate Browser",
"version": "1.0",
...
"permissions": [
"activeTab",
"webRequest",
"https://secure-website-example.google.com/*"
],
"browser_action": {
...
"default_popup": "popup/certificate_information.html"
}
Am I missing any permissions necessary to have access to the certificate? Is there a better way of grabbing certificate information?
The wiki page you linked to refers to APIs available in the addon sdk and bootstrapped extensions. The kind of manifest indicates you're writing a webextensions which are far more limited.
Related
Because I add them from the dashboard and fetch them into my flutter app with api
this is my api code:
export async function get_adminData(request) {
let options = {
"headers": {
"Content-Type": "application/json",
"Access-Control-Allow-Origin": "*"
}
};
try {
const results = await wixData.query("Admin")
.eq("url", "specificValue")
.eq("image", "specificValue")
.eq("text", "specificValue")
.eq("article", "specificValue")
.find();
if (results.items.length > 0) {
options.body = results.items;
return ok(options);
} else {
return notFound({});
}
} catch (error) {
options.body = {
"error": error
};
return serverError(options);
}
}
But I can only access collects that are under Wix App Collection.
I am new to wix and flutter so please help.
First and most obvious issue here is usually permissions issue
Try to check everything with this article
https://support.wix.com/en/article/velo-exposing-a-site-api-with-http-functions
Permissions HTTP functions, no matter how they are invoked, always run
with the permissions of an anonymous site visitor.
I'm trying to define a new filetype for the web, which is rendered to HTML via a browser extension. What I would like to do is have the server return files in my filetype with the HTTP header "Content-Type: text/mytype". The extension will inspect the response headers, and if the content-type matches text/mytype, it will intercept the response body and replace it with the rendered HTML. This gives us a filetype that interacts nicely with the web if you have the plugin installed.
As a proof of concept, I created a plugin working which intercepts the headers and renders them into the response, but it only works if the content-type is text/html. If I change the response content type to text/mytype on the server, Firefox downloads the file, seemingly without running my extension code at all.
Is there a different event I should be listening to, in order to intercept/change headers before and run extension code instead of just downloading the file?
Here's my code:
manifest.json:
{
"description": "Altering HTTP responses",
"manifest_version": 2,
"name": "http-response-filter",
"version": "1.0",
"homepage_url": "https://github.com/mdn/webextensions-examples/tree/master/http-response",
"icons": {
"48": "pen.svg"
},
"permissions": [
"webRequest", "webRequestBlocking", "<all_urls>"
],
"background": {
"scripts": ["background.js"]
},
"browser_specific_settings": {
"gecko": {
"strict_min_version": "57.0a1"
}
}
}
background.js:
var contentType;
function contentListener(details) {
//if(contentType === 'text/mytype') {
let filter = browser.webRequest.filterResponseData(details.requestId);
let decoder = new TextDecoder("utf-8");
let encoder = new TextEncoder();
filter.ondata = event => {
let str = decoder.decode(event.data, {stream: true});
// Later I want to replace this line with code that parses the
// document and renders it to HTML
str = str.replace(/Example/g, 'Content-Type: ' + contentType);
filter.write(encoder.encode(str));
filter.disconnect();
}
//}
return {};
}
browser.webRequest.onBeforeRequest.addListener(
contentListener,
{urls: ["<all_urls>"], types: ["main_frame"]},
["blocking"]
);
function headersListener(details) {
let headers = details.responseHeaders;
for(var i = 0; i < headers.length; i++) {
if(headers[i].name.toLowerCase() === 'content-type') {
contentType = headers[i].value;
// Try setting the content type to HTML to prevent downloading--
// doesn't work
headers[i].value = 'text/html; charset=utf-8';
}
}
browser.webRequest.onBeforeRequest.addListener(
contentListener,
{urls: ["<all_urls>"], types: ["main_frame"]},
["blocking"]
);
}
browser.webRequest.onHeadersReceived.addListener(
headersListener, {
urls: ["<all_urls>"],
types: ["main_frame"]
}, ["blocking", "responseHeaders"]
);
You may modify response headers only in onHeadersReceived handler.
If you can't execute onHeadersReceived for your file, then you can't change Content-Type header.
But anyway you could catch a url by content type with use documentUrl in onBeforeRequest handler, fetch data by url in background script and then open new window of your addon where you can render fetched content as you wish.
In this case page with content will have url like moz-extension://blah-blah-blah/pageRenderer.html#https://example.com/fileWithCustomType
I'm developing a Microsoft Teams custom app that can add connectors to Teams channels.
My connector has been working fine for a few months now, but a few weeks ago, the ability to register new connectors has stopped working:
After clicking “Save” on the connector configuration page, “loading” shows up until it times out (see the console screenshot below).
When I look in the browser console, I see that the outbound request was actually successful and notifySuccess() was called on the save event, but Teams does not register it (see full JS code below).
Also, a handleMessageError message is emitted, but I could not figure out what the issue is.
I tried this in the native app and in Chrome, and a client tried it in another instance of Teams as well.
Is this a bug or a (undocumented?) change in the Teams API?
Console / UI screenshot
JSON Error Message:
{
"seq": 1615787354693,
"timestamp": 1615793440583,
"flightSettings": {
"Name": "ConnectorFrontEndSettings",
"AriaSDKToken": "d127f72a3abd41c9b9dd94faca947689-d58285e6-3a68-4cab-a458-37b9d9761d35-7033",
"SPAEnabled": true,
"ClassificationFilterEnabled": true,
"ClientRoutingEnabled": true,
"EnableYammerGroupOption": true,
"EnableFadeMessage": false,
"EnableDomainBasedOwaConnectorList": false,
"EnableDomainBasedTeamsConnectorList": false,
"DevPortalSPAEnabled": true,
"ShowHomeNavigationButtonOnConfigurationPage": false,
"DisableConnectToO365InlineDeleteFeedbackPage": true
},
"status": 500,
"clientType": "SkypeSpaces",
"connectorType": "fc0ee140-b62a-4947-9af1-d19a66a00af8",
"name": "handleMessageError"
}
JS code that runs on the connector's configuration page:
const XHR = new XMLHttpRequest();
const subscriptionApiUrl = "https://XYZ.execute-api.us-east-1.amazonaws.com/Prod/subscriptions/";
const channelsApiBaseURL = "https://www.example.com/api/library/v2/channels/";
const defaultChannelParameters = "sorting=latest&language=en&excludeReviews=true";
const url = new URL(window.location.href);
const clientId = url.searchParams.get("clientid");
const clientSecret = url.searchParams.get("clientsecret");
const teamsSettings = {
entityId: "Example",
contentUrl: "https://www.example.com/xyz",
configName: "Example"
};
var saveEvent;
console.log("Example Connector initializing");
microsoftTeams.initialize();
microsoftTeams.settings.setValidityState(true); // make Save button enabled
microsoftTeams.settings.registerOnSaveHandler(handleSaveEvent);
function handleSaveEvent(e) {
saveEvent = e;
microsoftTeams.settings.setSettings(teamsSettings);
microsoftTeams.settings.getSettings(storeSettings);
}
function storeSettings(settings) {
XHR.addEventListener("load", reportSuccess);
XHR.addEventListener("error", reportFailure);
XHR.open("POST", subscriptionApiUrl);
XHR.setRequestHeader("Content-Type", "application/json");
XHR.send(composePayload(settings.webhookUrl));
console.log("Request to store Example Connector sent");
}
function composePayload(webhookUrl) {
return JSON.stringify({
webhookUrl: webhookUrl,
gaChannelUrl: channelsApiBaseURL + document.getElementById("ga-channel-id").value + "/items?" + defaultChannelParameters,
gaClientId: clientId,
gaClientSecret: clientSecret,
cronSchedule: "0 " + document.getElementById("time").value + " * * " + document.getElementById("frequency"),
postNow: document.getElementById("post-now").checked ? true : false
});
}
function reportSuccess(e) {
console.log("Example Connector registered!");
saveEvent.notifySuccess();
}
function reportFailure(e) {
let msg = "Could not connect to subscription API.";
console.log(msg);
saveEvent.notifyFailure(msg);
}
I got the same error. I registered the connector and downloaded the generated manifest.json then packaged (with icons) and tried to sideload the zip. I got the same error when trying to "Save".
I then tried to edit the generated manifest using the App Studio (App Studio -> Import an existing app) and this time I got a meaningful error saying the property needsIdentity is not valid according the schema from the manifest (https://developer.microsoft.com/en-us/json-schemas/teams/v1.3/MicrosoftTeams.schema.json)
Removing this property fixed the issue and I was able to save the connector configuration.
I could not find any documentation about this property. I checked the last version of the schema by now (1.8) and it's not there !!
I created an issue : https://github.com/MicrosoftDocs/msteams-docs/issues/2949
I am having difficulties using the Kapsel OData plugin to retrieve data from a store when the device is offline.
Here is the situation :
Cordova application for Windows platform
When the app opens, I start by opening a store against my OData service (similar to the Northwind service)
The store is created and opened. I then try and retrieve data from the store using OData.read or by setting a model and then calling read() on it.
The store will successfully open. However, my call to read the data will succeed when the device is online, and fail when it is offline, no matter which of the two previous methods I use.
Here is my code :
function openStore() {
var properties = {
"name": "Emergency",
"host": applicationContext.registrationContext.serverHost,
"port": applicationContext.registrationContext.serverPort,
"https": applicationContext.registrationContext.https,
"serviceRoot": appId,
"definingRequests": {
"Products": "/Products"
}
};
store = sap.OData.createOfflineStore(properties);
store.open(openStoreSuccessCallback, errorCallback);
}
function openStoreSuccessCallback() {
sap.OData.applyHttpClient();
retrieveWithModel();//retrieveWithOData();
}
function retrieveWithModel() {
var uri = applicationContext.applicationEndpointURL;
var user = applicationContext.registrationContext.user;
var password = applicationContext.registrationContext.password;
var headers = { "X-SMP-APPCID": applicationContext.applicationConnectionId };
var oModel = new sap.ui.model.odata.ODataModel(uri, {
json: "true",
user: user,
password: password,
headers: headers
});
sap.ui.getCore().setModel(oModel);
oModel.read("/Products", {
success: function (oEvent) {
var msg = new Windows.UI.Popups.MessageDialog("Success");
msg.showAsync();
},
error: function (err) {
console.log("you have failed");
var msg = new Windows.UI.Popups.MessageDialog("Fail");
msg.showAsync();
}
});
}
function retrieveWithOData() {
var sURL = applicationContext.applicationEndpointURL + "/Products";
var oHeaders = {};
oHeaders['Authorization'] = authStr;
oHeaders['X-SMP-APPCID'] = applicationContext.applicationConnectionId;
//oHeaders['Content-Type'] = "application/json";
//oHeaders['X-CSRF-Token'] = "FETCH";
var request = {
headers: oHeaders,
requestUri: sURL,
method: "GET"
};
OData.read(request,
function (data, response) {
console.log('Success');
},
function (err) {
console.log('Fail');
}
);
}
Kapsel SDK version is 3.8.0
SMP SDK is SP08
Cordova version 5.3.3
I am wondering if this is an issue with the way the app is launched. I need a way to open the same instance of the application every time, so the offline store will be kept with all its data. Because Cordova-generated Visual Studio projects do not generate an .exe file (only .appx files which would need to be signed and sideloaded to be used), the way I proceed is : I run the application in online mode from Visual Studio, then pin it to the taskbar or start menu, close it and switch the device to offline mode, and reopen it from the task bar.
However, more and more it seems like this method does not work as expected.
Can anyone confirm that a Visual Studio project, opened from the taskbar, should run the same way as when it is run from VS, with the same dependencies, libraries etc? If such is the case (and I can't really imagine why it wouldn't be), does anyone have any experience with these technologies and see what a potential issue could be?
Any help would be greatly appreciated.
Thanks!
Ok I found the solution to my problem. In case anyone ever encounters the same issue, the problem was that my offline store was not being used (you can see with Fiddler that there are outbound requests to the backend system even in offline mode).
The Visual studio project does keep the store from one build or launch to the next.
I reworked the "Clip to DEVONthink" to use in Opera 15+. The problem I'm left with is that the extension only works after a browser restart.
Update 1: Tested on Mac OS X 10.9.2 with Opera 21.0.1432.67, Opera Next 22.0.1471.40 and Google Chrome 35.0.1916.114. They all behave the same.
Update 2: Opera's own example for message passing got the same behavior. I'm left with the question if that's the expected behavior.
There's a background script defined in manifest.json:
"background": {
"scripts": [ "main.js" ]
},
and a content script:
"content_scripts": [ {
"js": [ "add_listener.js" ],
"matches": [ "http://*/*", "https://*/*" ],
}],
... and in main.js in chrome.browserAction.onClicked.addListener a message is send to the content script to request page title & content, etc.
chrome.browserAction.onClicked.addListener(
function (tab) {
chrome.tabs.sendMessage(tab.id, {line: 'getdevonthinkurl' });
}
);
... and the content script sends a message back:
chrome.runtime.onMessage.addListener(
function (request, sender){
if (request.line=='getdevonthinkurl'){
chrome.runtime.sendMessage({devonthinkurl:getDEVONthinkURL()});
}
}
);
... and that message is received by the main.js background script:
chrome.runtime.onMessage.addListener(
function (request, sender) {
if (request.devonthinkurl){
chrome.tabs.update(sender.tab.id, {"url": request.devonthinkurl});
}
}
);
As mentioned above it works perfect after a browser restart but it don't understand why it won't work without.
Does anyone have got an idea (I may add I'm not strong at programming and there's maybe an fundamental flaw in the design)?
The only thing which comes to my mind is that you reloading extension, but just after this step you are not refreshing page where content script is injected. Is there any error in background page? I tried several times and it works for me. Anyway you can use callback in message which can be more readable.
So main.js can look like:
chrome.browserAction.onClicked.addListener(function (tab) {
chrome.tabs.sendMessage(tab.id, {line: 'getdevonthinkurl'},
function(response){
chrome.tabs.update(tab.id, {'url': request.devonthinkurl});
});
});
And add_listener.js like this:
chrome.runtime.onMessage.addListener(
function (request, sender, sendResponse){
if (request.line=='getdevonthinkurl'){
sendResponse({devonthinkurl:getDEVONthinkURL()});
}
}
);