I want to ask about the normal notification in DART, which is different than the Chrome Packaged App discussed here
I created the below code, the browser [DARTIUM] asked for permission as expected, but the response in both cases (Allow/Deny) appeared as "default" in the console, and the notification did not appear.
{
void main() {
Notification.requestPermission().then((String permission) {
print(permission); // ==> This is always = "default" for both Allow and Deny
if (permission == "default") {
print('permission granted');
var notification = new Notification('hello');
}
else print('sorry no permission!');
});
}
any thought! thanks
The code as it's currently written would never show a permission either way -- "default" means that permission hasn't been allowed or denied. You should be checking for permission == "granted" before displaying the notification.
Keep in mind, there is an outstanding bug with notifications and checking the current permissions, see https://code.google.com/p/dart/issues/detail?id=20585, although this may not be affecting you.
thanks Brian and Gunter, I made my own notification, inspired by this
I made used the same, CSS file, and made a custom element, notification.dart
part of myApp;
class NotificationElement extends HtmlElement {
// Define the custom element tag
static final tag = 'x-Notification';
factory NotificationElement() => new Element.tag(tag);
// Create the element and define its stylesheet
NotificationElement.created() : super.created(){
LinkElement styleSheet = new LinkElement()..rel = "stylesheet"..type="text/css"..href="./style/toastr.css";
document.head.append(styleSheet);
}
var notificationContainer = new Element.html('<div></div>')
..id='notification-container';
var notificationBody = new Element.html('<div></div>')
..classes.add('notification');
var notificationButton = new ButtonElement()
..classes.add('notification-close-button')
..text='x';
var notificationTitle = new Element.html('<div></div>')..classes.add('notification-title');
var notificationMsg = new Element.html('<div></div>')..classes.add('notification-message');
var notificationMsgLabel = new LabelElement();
Element launchElement(type,location,Title,Msg){
notificationButton.onClick.listen((e) => notificationContainer.nodes.remove(notificationBody));
notificationContainer..classes.add('notification-'+location);
notificationBody..classes.add('notification-'+type);
notificationTitle.text=Title;
notificationMsg.innerHtml='<label>'+Msg+'</label>';
notificationBody.nodes..add(notificationButton)..add(notificationTitle)..add(notificationMsg);
notificationContainer.nodes..add(notificationBody);
return (notificationContainer);
}
}
Element mynotification = querySelector('#notification-element');
void CreatefonixNotification(type,location,Title,Msg){
var notifyMe = new Element.tag('x-notification');
notifyMe = notifyMe.launchElement(type,location,Title,Msg);
mynotification.nodes.add(notifyMe);
}
in the index.dart, I registered the element:
document.registerElement(NotificationElement.tag, NotificationElement);
and in index.html, I added this div:
<div id='notification-element'></div>
and any place in the application, I can call it like:
CreateNotification('error','top-left','Error:','sorry we have some issue!!.')
Related
I am using Xamarin.Google.iOS.MobileAds package to show Google App Open Ad in my MAUI app. The code below has error handling code removed for brevity.
this.ad = await AppOpenAd.LoadAsync(
o.IosUnitId,
null,
o.Orientation switch
{
AppOpenAdOrientation.Landscape => UIInterfaceOrientation.LandscapeLeft,
_ => UIInterfaceOrientation.Portrait,
}
);
var oldHandler = ad.PaidEventHandler;
var openTcs = new TaskCompletionSource();
// The handler below is actually called when the ad show up
ad.PaidEventHandler = v =>
{
oldHandler?.Invoke(v);
openTcs.TrySetResult();
};
var root = Platform.GetCurrentUIViewController();
this.ad.PresentFromRootViewController(root);
In the Google's doc on Handle presentation callbacks, a GADFullScreenContentDelegate is needed but I have no idea how I can put it in C# and there is no event/delegate corresponding to this self.appOpenAd.fullScreenContentDelegate = self;.
Please advice on the event of ad dismissal. I could do it for Android like this but I can't see the equivalent in Xamarin.iOS:
this.currAd.FullScreenContentCallback = callback;
I have a script here, which is extracting the links within a web page. It is comming back with the error 'content is not defined'.
// extract the links
var links = new Array();
for (i = 0; i < content.document.links.length; i++) {
var thisLink = content.document.links[i].toString();
//links.push(content.document.links[i].toString());
console.log(thisLink);
}
In order to interact with the HTML documents within the Firefox SDK, do I need to import a library?
It depends on when the self executing anonymous function is running. It is possible that it is running before window.document is defined.
In that case, try adding a listener
window.addEventListener('load', yourFunction, false);
// ..... or
window.addEventListener('DOMContentLoaded', yourFunction, false);
yourFunction () {
// some ocde
}
I am creating a firefox addon using the SDK. My goal is simple, to intercept a specific iframe and load my own HTML page (packaged as a resource with my addon) instead of the content that was requested originally.
So far I have the following code:
var httpRequestObserver =
{
observe: function(subject, topic, data)
{
var httpChannel, requestURL;
if (topic == "http-on-modify-request") {
httpChannel = subject.QueryInterface(Ci.nsIHttpChannel);
requestURL = httpChannel.URI.spec;
var newRequestURL, i;
if (/someurl/.test(requestURL)) {
var ioService = Cc["#mozilla.org/network/io-service;1"].getService(Ci.nsIIOService);
httpChannel.redirectTo(ioService.newURI(self.data.url('pages/test.html'), undefined, undefined));
}
return;
}
}
};
var observerService = Cc["#mozilla.org/observer-service;1"].getService(Ci.nsIObserverService);
observerService.addObserver(httpRequestObserver, "http-on-modify-request", false);
This code works in that it detects the proper iframe loading and does the redirect correctly. However, I get the following error:
Security Error: Content at http://url.com may not load or link to
jar:file:///.../pages/test.html.
How can I get around this limitation?
actually man i was really over thinking this.
its already solved when I changed to using loadContext. Now when you get loadContext you get the contentWindow of whatever browser element (tab browser, or frame or iframe) and then just abort the http request like you are doing and then loadContext.associatedWindow.document.location = self.data('pages/tests.html');
done
ill paste the code here removing all the private stuff. you might need the chrome.manifest ill test it out and paste the code back here
Cu.import('resource://gre/modules/Services.jsm');
var httpRequestObserver = {
observe: function (subject, topic, data) {
var httpChannel, requestURL;
if (topic == "http-on-modify-request") {
httpChannel = subject.QueryInterface(Ci.nsIHttpChannel);
requestURL = httpChannel.URI.spec;
var newRequestURL, i;
if (/someurl/.test(requestURL)) {
var goodies = loadContextGoodies(httpChannel);
if (goodies) {
httpChannel.cancel(Cr.NS_BINDING_ABORTED);
goodies.contentWindow.location = self.data.url('pages/test.html');
} else {
//dont do anything as there is no contentWindow associated with the httpChannel, liekly a google ad is loading or some ajax call or something, so this is not an error
}
}
return;
}
}
};
Services.obs.addObserver(httpRequestObserver, "http-on-modify-request", false);
//this function gets the contentWindow and other good stuff from loadContext of httpChannel
function loadContextGoodies(httpChannel) {
//httpChannel must be the subject of http-on-modify-request QI'ed to nsiHTTPChannel as is done on line 8 "httpChannel = subject.QueryInterface(Ci.nsIHttpChannel);"
//start loadContext stuff
var loadContext;
try {
var interfaceRequestor = httpChannel.notificationCallbacks.QueryInterface(Ci.nsIInterfaceRequestor);
//var DOMWindow = interfaceRequestor.getInterface(Components.interfaces.nsIDOMWindow); //not to be done anymore because: https://developer.mozilla.org/en-US/docs/Updating_extensions_for_Firefox_3.5#Getting_a_load_context_from_a_request //instead do the loadContext stuff below
try {
loadContext = interfaceRequestor.getInterface(Ci.nsILoadContext);
} catch (ex) {
try {
loadContext = subject.loadGroup.notificationCallbacks.getInterface(Ci.nsILoadContext);
} catch (ex2) {}
}
} catch (ex0) {}
if (!loadContext) {
//no load context so dont do anything although you can run this, which is your old code
//this probably means that its loading an ajax call or like a google ad thing
return null;
} else {
var contentWindow = loadContext.associatedWindow;
if (!contentWindow) {
//this channel does not have a window, its probably loading a resource
//this probably means that its loading an ajax call or like a google ad thing
return null;
} else {
var aDOMWindow = contentWindow.top.QueryInterface(Ci.nsIInterfaceRequestor)
.getInterface(Ci.nsIWebNavigation)
.QueryInterface(Ci.nsIDocShellTreeItem)
.rootTreeItem
.QueryInterface(Ci.nsIInterfaceRequestor)
.getInterface(Ci.nsIDOMWindow);
var gBrowser = aDOMWindow.gBrowser;
var aTab = gBrowser._getTabForContentWindow(contentWindow.top); //this is the clickable tab xul element, the one found in the tab strip of the firefox window, aTab.linkedBrowser is same as browser var above //can stylize tab like aTab.style.backgroundColor = 'blue'; //can stylize the tab like aTab.style.fontColor = 'red';
var browser = aTab.linkedBrowser; //this is the browser within the tab //this is where the example in the previous section ends
return {
aDOMWindow: aDOMWindow,
gBrowser: gBrowser,
aTab: aTab,
browser: browser,
contentWindow: contentWindow
};
}
}
//end loadContext stuff
}
NOTE: Now try this first, I didn't test it yet, if you get a security error when it tries to redirect then create a chrome.manifest file and put it in the root directory. If it throws a security error than you definitely need a chrome.manifest file and that will without question fix it up. I'll test this myself later tonight when I get some time.
The chrome.manifest should look like this:
content kaboom-data ./resources/kaboom/data/ contentaccessible=yes
Then in the code way above change the redirect line from goodies.contentWindow.location = self.data.url('pages/test.html'); to goodies.contentWindow.location = 'chrome://kaboom-data/pages/test.html');.
see this addon here: https://addons.mozilla.org/en-US/firefox/addon/ghforkable/?src=search
in the chrome.manifest file we set the contentaccessible parameter to yes
you dont need sdk for this addon. its so simple, just ocpy paste that into a bootstrap skeleton as seen here:
Bootstrap With Some Features, Like chrome.manifest which you will need
Bootstrap Ultra Basic
if you want to really do a redirect of a page to your site, maybe you want to make a custom about page? if you would like ill throw togather a demo for you on making a custom about page. you can see a bit hard to understand demo here
posting my trials here so it can help all:
trail 1 failed - created chrome.manifest file with contents content kaboom-data resources/kaboom/data/ contentaccessible=yes
var myuri = Services.io.newURI('chrome://kaboom-data/content/pages/test.html', undefined, undefined);
httpChannel.redirectTo(myuri);
Error Thrown
Security Error: Content at http://digg.com/tools/diggthis/confirm? may
not load or link to
jar:file:///C:/Documents%20and%20Settings/SONY%20VAIO/Application%20Data/Mozilla/Firefox/Profiles/vr10qb8s.default/extensions/jid1-g4RtC8vdvPagpQ#jetpack.xpi!/resources/kaboom/data/pages/test.html.
trial 2 failed - created resource in bootstrap.js
alias.spec =
file:///C:/Documents%20and%20Settings/SONY%20VAIO/Application%20Data/Mozilla/Firefox/Profiles/vr10qb8s.default/extensions/jid1-g4RtC8vdvPagpQ#jetpack.xpi
alias updated to spec:
jar:file:///C:/Documents%20and%20Settings/SONY%20VAIO/Application%20Data/Mozilla/Firefox/Profiles/vr10qb8s.default/extensions/jid1-g4RtC8vdvPagpQ#jetpack.xpi!/
let resource = Services.io.getProtocolHandler("resource").QueryInterface(Ci.nsIResProtocolHandler);
let alias = Services.io.newFileURI(data.installPath);
Cu.reportError('alias.spec = ' + alias.spec);
if (!data.installPath.isDirectory()) {
alias = Services.io.newURI("jar:" + alias.spec + "!/", null, null);
Cu.reportError('alias updated to spec: ' + alias.spec);
}
resource.setSubstitution("kaboom_data", alias);
...
var myuri = Services.io.newURI('resource://kaboom_data/resources/kaboom/data/pages/test.html', undefined, undefined);
httpChannel.redirectTo(myuri);
Error Thrown
Security Error: Content at http://digg.com/tools/diggthis/confirm? may
not load or link to
jar:file:///C:/Documents%20and%20Settings/SONY%20VAIO/Application%20Data/Mozilla/Firefox/Profiles/vr10qb8s.default/extensions/jid1-g4RtC8vdvPagpQ#jetpack.xpi!/resources/kaboom/data/pages/test.html.
CONCLUSION
in both trials above it was the weirdest thing, it wouldnt show the resource or chrome path in the security error thrown but it would give the full jar path. Leading me to believe that this has something to do with redirectTo function.
The solution that did work was your solution of
var gBrowser = utils.getMostRecentBrowserWindow().gBrowser;
var domWin = httpChannel.notificationCallbacks.getInterface(Ci.nsIDOMWindow);
var browser = gBrowser.getBrowserForDocument(domWin.document);
//redirect
browser.loadURI(self.data.url('pages/test.html'));
however I changed this to use loadContext instead of this method because it is the recommended way. also gBrowser to getMostRecentBrowserWindow will fail if the url load is slow and in that time the user swithces to another tab or window
I also changed to use Services.jsm as you had imported Cu anyways. Using Services.jsm is super fast not even blink fast. Its just a pointer.
Im still working on trying to the redirectTo method working its really bothering me. The changes I made are to my local copy.
Have you considered turning your local HTML file into a data URL and loading that?
I have a bootstrapped extension for Firefox.
And now I want to implement nsIContentPolicy XPCOM component.
I wrote a component module code.
And now I want to register this component.
The reason I want to register component is that I want to add my component to nsICategoryManager.addCategoryEntry with "content-policy" category.
var {Cc, Ci, Cu} = require("chrome");
Cu.import("resource://gre/modules/XPCOMUtils.jsm");
//console.error("Running interceptor");
function Interceptor()
}
Interceptor.prototype = {
classDescription: "DeferredTo HTTP requests Interceptor",
classID: "{B5B3D9A0-08FC-11E3-8253-5EF06188709B}",
contractID: "#deferredto.com/Interceptor;1",
QueryInterface: XPCOMUtils.generateQI([Ci.nsIContentPolicy]),
shouldLoad : function dt_shouldLoad(aContentType, aContentLocation, aRequestOrigin, aContext, aMimeTypeGuess, aExtra) {
console.log("dt_shouldLoad");
if (contentLocation.scheme != "http" && contentLocation.scheme != "https")
return Ci.nsIContentPolicy.ACCEPT;
let result = Ci.nsIContentPolicy.ACCEPT;
// we should check for TYPE_SUBDOCUMENT as well if we want frames.
if ((Ci.nsIContentPolicy.TYPE_DOCUMENT == aContentType) &&
SOME_REGULAR_EXPRESSION.test(aContentLocation.spec)) {
// do stuff here, possibly changing result.
}
return result;
},
shouldProcess: function ILO_shouldProcess() Ci.nsIContentPolicy.ACCEPT,
_xpcom_categories: [
{ category: "content-policy", service: true }
],
classInfo: XPCOMUtils.generateCI(
{classID: Components.ID("{B5B3D9A0-08FC-11E3-8253-5EF06188709B}"),
contractID: "#deferredto.com/Interceptor;1",
classDescription: "Interceptor implements nsIContentPolicy to block images that are not yet at screen #DeferredTo",
interfaces: [
Ci.nsIContentPolicy,
],
flags: Ci.nsIClassInfo.SINGLETON})
}
var components = [Interceptor];
var NSGetFactory = XPCOMUtils.generateNSGetFactory([Interceptor]);
Questions:
Is it possible to register the component from bootstrapped extension?
Is it possible to register the component from restartless extension?
Is it possible to use nsICategoryManager.addCategoryEntry "content-policy" without
component?
How to register the component in bootstrapped extension or somehow add
new "content-policy" category entry?
I've added to harness-options.js
"requirements": {
"sdk/page-mod": "sdk/page-mod",
"sdk/self": "sdk/self",
"chrome": "chrome"},
That is how I try to import module:
var {Cc, Ci, Cu} = require("chrome");
Cu.import("resource://deferredto/lib/interceptor.js");
I' ve tried many paths ))) But none works. resource entry in chrome.manifest file does not allowed for bootstrapped extensions. The path to component module file is:
resources/deferredto/lib/interceptor.js
Adblock Plus, which is restartless but not using the SDK, registers an nsIContentPolicy implementation at runtime, just like your SDK would. There are probably a few SDK add-ons registering components at run time, but I don't know any open source ones that I would recommend to look at off the top of my head.
A few points regarding that ABP implementation and what to change to make it work with the SDK:
The category manager is available via Cc["#mozilla.org/categorymanager;1"].getService(Ci.nsICategoryManager).
The component registrar should be available by requiring also components from the chrome module and then components.manager.getService(Ci.nsIComponentRegistrar).
As Adblock Plus, you must unregister your component yourself on unload.
The unload part is unfortunely also a bit tricking, since you cannot synchronously unregister your component and the category entry, due to Bug 753687. Adblock Plus therefore does it async using Util.runAsync, which just dispatches a runnable (event, if you like) to the main thread. I don't think you can use any SDK stuff here, as the SDK will clean up before any async code gets a chance to run, so you'd need to use a low-level XPCOM runnable (or timer) yourself.
Your code will register your component at runtime. You won't touch harness-options or anything like that.
(I also implemented a generic component register function myself, but that again is not SDK code, and would need to be adapted to run in the SDK, just like the ABP one. It is also very similar to the ABP one.)
Now my nsIContentPolicy sdk-based component look like this. File interceptor.js:
'use strict';
var { Class } = require('sdk/core/heritage');
var xpcom = require('sdk/platform/xpcom');
var { Cc, Ci, Cu, Cm } = require('chrome');
var categoryManager = Cc["#mozilla.org/categorymanager;1"]
.getService(Ci.nsICategoryManager);
// nsIDOMNode
const TYPE_DOCUMENT_NODE = Ci.nsIDOMNode.DOCUMENT_NODE;
/// Interceptor
var contractId = "#deferredto.com/Interceptor;1";
var Interceptor = Class({
extends: xpcom.Unknown,
interfaces: [ 'nsIContentPolicy' ],
get wrappedJSObject() this,
shouldLoad : function dt_shouldLoad(contentType, contentLocation, requestOrigin, context, mimeTypeGuess, extra) {
let result = Ci.nsIContentPolicy.ACCEPT;
return result;
},
shouldProcess: function () Ci.nsIContentPolicy.ACCEPT
});
var factory = xpcom.Factory({
contract: contractId,
Component: Interceptor,
unregister: false // see https://bugzilla.mozilla.org/show_bug.cgi?id=753687
});
/// unload
var unload = require("sdk/system/unload");
unload.when(function() {
function trueUnregister() {
categoryManager.deleteCategoryEntry("content-policy", contractId, false);
try {
console.log("xpcom.isRegistered(factory)=" + xpcom.isRegistered(factory));
console.log("trueUnregister");
xpcom.unregister(factory);
console.log("xpcom.isRegistered(factory)=" + xpcom.isRegistered(factory));
} catch (ex) {
Cu.reportError(ex);
}
}
if ("dispatch" in Cu) {
console.log('"dispatch" in Cu');
Cu.dispatch(trueUnregister, trueUnregister);
} else {
console.log('"dispatch" not! in Cu');
Cu.import("resource://gre/modules/Services.jsm");
Services.tm.mainThread.dispatch(trueUnregister, 0);
}
});
//xpcom.register(factory);
var interceptor = Cc[contractId].createInstance(Ci.nsIContentPolicy);
categoryManager.deleteCategoryEntry("content-policy", contractId, false);
categoryManager.addCategoryEntry("content-policy", contractId, contractId, false, true);
And you can use it from sdk like this:
var interceptor = require("./interceptor");
i am trying to write a tool that creates entries in the google calendar.
after following the google docs and creating an client-identifier/secret in the api console, i managed to put together a client that authenticates correctly and shows my registered google calendars. right now for me it looks like my google-account is somehow tied to my client-identifier/secret. what i want to know is: how can i change the auth process so that it is possible for an other user of this tool to enter his google-id and get access to his calendars?
EDIT: in other words (used in the RFC): I want make the resource owner-part editable while leaving the client-part unchanged. but my example, although working, ties together client and resource owner.
here is my app that works fine so far:
public void Connect()
{
var provider = new NativeApplicationClient(GoogleAuthenticationServer.Description);
provider.ClientIdentifier = "123456123456.apps.googleusercontent.com";
provider.ClientSecret = "nASdjKlhnaxEkasDhhdfLklr";
var auth = new OAuth2Authenticator<NativeApplicationClient>(provider, GetAuthorization);
var service = new CalendarService(auth);
//Events instances = service.Events.Instances("primary", "recurringEventId").Fetch();
var list = service.CalendarList.List().Fetch();
foreach (var itm in list.Items)
Console.WriteLine(itm.Summary);
}
private static readonly byte[] AditionalEntropy = { 1, 2, 3, 4, 5 };
private static IAuthorizationState GetAuthorization(NativeApplicationClient arg)
{
var state = new AuthorizationState(new[] { CalendarService.Scopes.Calendar.GetStringValue() });
state.Callback = new Uri(NativeApplicationClient.OutOfBandCallbackUrl);
var refreshToken = LoadRefreshToken();
if (!String.IsNullOrWhiteSpace(refreshToken))
{
state.RefreshToken = refreshToken;
if (arg.RefreshToken(state))
return state;
}
var authUri = arg.RequestUserAuthorization(state);
// Request authorization from the user (by opening a browser window):
Process.Start(authUri.ToString());
var frm = new FormAuthCodeInput();
frm.ShowDialog();
// Retrieve the access token by using the authorization code:
var auth = arg.ProcessUserAuthorization(frm.txtAuthCode.Text, state);
StoreRefreshToken(state);
return auth;
}
private static string LoadRefreshToken()
{
try
{
return Encoding.Unicode.GetString(ProtectedData.Unprotect(Convert.FromBase64String(Properties.Settings.Default.RefreshToken), AditionalEntropy, DataProtectionScope.CurrentUser));
}
catch
{
return null;
}
}
private static void StoreRefreshToken(IAuthorizationState state)
{
Properties.Settings.Default.RefreshToken = Convert.ToBase64String(ProtectedData.Protect(Encoding.Unicode.GetBytes(state.RefreshToken), AditionalEntropy, DataProtectionScope.CurrentUser));
Properties.Settings.Default.Save();
}
Prompt the user to enter their ClientIdentifier and ClientSecret, then pass these values to your Connect method.
i solved the problem myself.
the problem was, that i'm usually always connected to google and because i did't log out from google before my app redirected to google to get the access-token, google automatically generated the access-token for my account - skipping the part where an input-form appears where anyone could enter his/her user-credentials to let google generate an access-token for his/her account.