I noticed that when logging out of my app, it takes me back to the login screen as intended. However, the input fields are still populated with previous login info (i.e. email/password). I thought they would be empty again upon navigating back to the login screen, but this isn't the case.
Here is my login.js file with respect to loading actions:
var frameModule = require("ui/frame");
var Observable = require("data/observable").Observable;
var home_navigation = {
moduleName: "views/home/home",
clearHistory: true
};
var page_data = new Observable({
email: "",
password: ""
})
exports.onNavigatingTo = function(args) {
var page = args.object;
page.bindingContext = page_data;
}
There are other functions below this, but they just the email/pass and perform login logic as well as navigate to the appropriate screen, without storing the email/password anywhere locally. Also, there are no checks for previous session or anything like that.
When u leave its saved only in memory and its not available to other parts of app until saved somewhere like application-settings or db
Related
We have enabled deep linking in Microsoft Teams Tabs. We are generating link to the custom tabs with subEntityId as mentioned in Microsoft docs
https://teams.microsoft.com/l/entity/<appId>/<entityId>?webUrl=<entityWebUrl>&label=<entityLabel>&context=<context>
In home page, we are using Ms Teams Js SDK and calling getContext() for retrieving the subEntityId passed in the URL.
We used the following code for navigating to different page based on subEntityId
microsoftTeams.initialize();
microsoftTeams.getContext(function (context) {
console.log(context);
let currentUrl = window.location.href;
let isAdmin = false;
if(currentUrl.indexOf('admin') > 0){
isAdmin = true;
}
let subEntityId = context.subEntityId;
let redirectUrl = "";
if(subEntityId == "all-tasks")
{
redirectUrl = isAdmin ?
window.location.origin + "/admin/task/all-tasks" :
window.location.origin + "/member/task/all-tasks";
}
microsoftTeams.setContext
if(redirectUrl != ""){
window.location.assign(redirectUrl);
}
});
but when we are navigating back to home page using navigation bar (not by using any back button) it is automatically redirecting back. The subEntityId is not resetting and on home page load it is picking the id and navigating again.
Please help, is there any possible way to reset or set the subEntityId as empty.
Thank you.
There appears to be no way to change the context, or otherwise record that the subEntityId has already been followed once, using the Teams client SDK
My solution was to add a hash or url parameter to the tab's contentURL (during tab configuration).
microsoftTeams.settings.setSettings({
contentUrl: https://my_tab_url#follow_deep_link,
})
Then the subEntityId is only used when this hash is present. Subsequent navigation within the tab removes the #follow_deep_link and subEntityId is not used.
if (window.location.hash === '#follow_deep_link') {
microsoftTeams.getContext(function (context) {
//handle subEntityId
})
}
Can you try below code to update subEntityId value after redircting.
microsoftTeams.settings.setSettings({
subEntityId: "Reset value here",
});
I'm porting a Chrome extension to a Firefox extension and due to the nature of the website that it runs on, I need to monitor the pushState.
Chrome Extensions has a handy way to handle this: chrome.webNavigation.onHistoryStateUpdated. The way that I use it in the Chrome extension is as follows:
chrome.webNavigation.onHistoryStateUpdated.addListener(function(details) {
var tabUrl = details.url;
if (isTabUrlValid(tabUrl)) {
$.get(tabUrl, function(data) {
var videoUrl = $(data).find('meta[itemprop=contentURL]').prop('content');
videoUrl = validateUrl(videoUrl);
videoUrl5k = make5kUrl(videoUrl);
});
}
});
I need to do the same thing for the Firefox Extension, but I haven't found any good answers. I've tried doing the answer mentioned here: How to get notified about changes of the history via history.pushState?
(function(history) {
var pushState = history.pushState;
history.pushState = function(state) {
if (typeof history.onpushstate == "function") {
history.onpushstate({state: state});
}
var tabUrl = tabs.activeTab.url;
console.log("UPDATED TAB URL: " + tabUrl);
if (isTabUrlValid(tabUrl)) {
$.get(tabUrl, function(data) {
var videoUrl = $(data).find('meta[itemprop=contentURL]').prop('content');
videoUrl = validateUrl(videoUrl);
videoUrl5k = make5kUrl(videoUrl);
});
}
return pushState.apply(history, arguments);
};
})(window.history);
The problem is that when I do cfx run it complains that history/window is undefined and therefore never gets detected. I think this is due to it being within the SDK, but I don't know of a good workaround.
Any thoughts?
Edit: I looked at #willma's answer below and I don't think that would work for me. The issue is that the URL is updated via pushState and the DOM is not... Is there any good way replicate what I do in the chrome extension?
Edit: Here's the pageMod portion
pageMod.PageMod({
attachTo: 'top', // Don't attach to iFrames --> http://goo.gl/b6b1Iv
include: [URLs],
contentScriptFile: [data.url("jquery-2.1.1.min.js"),
data.url("csScript.js")],
onAttach: function(worker) {
worker.port.on('url', function(url) {
var videoUrl = validateUrl(url);
videoUrl5k = make5kUrl(videoUrl);
console.log("--5K URL--: " + videoUrl5k);
});
}
});
That history code needs to get injected into a tab using a content script. Right now your logic says when the history event occurs, check to see if the tab URL is valid.
In Firefox, the logic will be the other way around: when a tab is opened, check if its URL is valid, and if so, then attach a script to it that will monitor for the history event. To do so you'll need to use a Page Mod.
Edit: All the code
One key concept you're missing is the difference between a content script and a main/library script. The library scripts are stored in lib and have access to all the SDK modules, but don't have access to the DOM, window object… The content scripts are stored in data, are injected into a page using the PageMod or tabs modules, can access the dom and window objects, but have no access to any SDK modules. Content scripts are essentially like the page scripts you'd attach your standard HTML page (with <script></script>) with the caveats that they can't share variables other page scripts but they can communicate with the main scripts.
The only reason I bring this up is because your initial problem was trying to access the window object from a main script and the problem in your fiddle is that you're trying to access the tabs module inside a content script. It's worth reading the topmost link in this answer if this is still confusing.
main.js
const { PageMod } = require('sdk/page-mod');
var sendXHR = function(url) {
// Do something with the new URL
// See Request Module docs (below) for sending XHRs from main script.
}
const pageMod = PageMod({
attachTo: 'top',
include: '*',
onAttach: function(worker) {
worker.port.on('newURL', sendXHR);
}
});
content.js
var sendNewUrlToMain = function() {
self.port.emit('newURL', location.href);
}
var pushState = window.history.pushState;
window.history.pushState = function(state) {
if (typeof history.onpushstate == "function") {
history.onpushstate({state: state});
}
sendNewUrlToMain();
return pushState.apply(history, arguments);
}
window.addEventListener('hashchange', sendNewUrlToMain);
Here are the request module docs, for making XHRs.
NB: if you don't want to use the request module (the only reason being that you already have standard XHR code for your chrome extension and don't want to take the time to learn/rewrite that code), you can send a standard XHR from the content script, but in doing so, you risk allowing the user to close the tab and thus destroy the script before your XHR callbacks are executed.
I'm trying to capture the page load time using casperjs. The page in question is login protected. Here is what I have so far:
var casper = require('casper').create();
// Enter the login page, fill up the form and submit it
casper.start('https://example.net/login', function () {
// Fill the form
this.fill('form[name=signin]', {
'user': 'username',
'passwd': 'password'
}, false);
// Submit the form by clicking the submit button
this.then(function() {
this.click('#sign_in');
});
});
// Now on the loggedin page click the link of page for which response time is needed
casper.then (function() {
var start = Date.now();
this.click ('#pageLink');
// Measure response time of this page
var end = Date.now();
this.echo (end - start);
});
casper.run();
I can pretty much tell it's the wrong approach because I should perhaps wait for the page to load and then capture the end time. But on the casper js documentation page, I did not find any thing that lets me know when the page has loaded fully. Would it make sense to look for the closing tag and see if that has loaded ?
You should use the events : here an example :
(function(){
"use strict";
var s
,e
;
//we use casper events to calculate the time between a http request and its response
casper.on('page.resource.requested', function(requestData, request) {
//console.log("request url " + requestData.url);
s = new Date().getTime();
});
casper.on('page.resource.received', function(response) {
//console.log("response url " + response.url);
e = new Date().getTime();
casper.echo("Time between HTTP request and HTTP response : " + (e-s) + "ms","INFO");
});
})();//then your code
I use an IIFE just to create a scope for var s (start) and e (end).
For what you want, you could do the same with load.started and load.finished.
http://casperjs.readthedocs.org/en/latest/events-filters.html
But there are better tools to do that, Casper isn't that good for monitoring.
I am attempting to add a function to my Firefox extension to trigger an event to delete cookies from site B when a button on site A is clicked. Site A and B do not share a domain but site B is running in an iframe injected into site A. I need the click event in the Firefox content script to trigger an event either in the content script or the Firefox extension main to delete all of the cookies from site B.
I have the click listener assigned to the button and firing. I have already achieved this same effect in Google Chrome with an extension. I get an error about using components, but I could not find a solution to use instead of components. It only needs to work on Firefox 22+. I am using addon-sdk-1.14 to develop the extension.
ContentScript.js
function DeleteCookies() {
var payload="Delete";
self.port.emit("Delete", payload);
}
Main.js
var {Cc, Ci} = require("chrome");
pageMod.PageMod({
include: "*",
contentScriptFile: [ self.data.url("jquery-1.9.1.js")
,self.data.url("script.js")],
onAttach: function(worker) {
worker.port.on('Delete',function (){ DeleteCookies();});
}
});
function DeleteCookies() {
var cookieManager = Cc["#mozilla.org/cookiemanager;1"].getService(Ci.nsICookieManager);
var domain= "siteB.com";
var iter = cookieManager.enumerator;
var cookie_count = 0;
while (iter.hasMoreElements()) {
var cookie = iter.getNext();
if (cookie instanceof Ci.nsICookie) {
if (domain.indexOf(cookie.host.toUpperCase()) != -1) {
cookieManager.remove(cookie.host, cookie.name, cookie.path, cookie.blocked);
cookie_count++;
}
}
}
};
You can't access XPCOM from a content script. Use the port mechanism for communication between the content script and main.js, and do the cookie deletion from the latter.
It appears the code that will correctly perform the task was edited into the question rather than be posted as an answer. Unfortunately, there appears to be a bug and it iterates over all cookies rather than just those in the domain from which you desire to delete. For the question Deleting cookies with JavaScript in Firefox extension, I modified the code in this question to be more efficient, and fixed the bug. Given that I already worked on the code, I am posting it here so that others don't need to go through figuring out that the code was edited into the question and finding the issues with the code.
The bug is that cookie.blocked is passed to cookieManager.remove() when there is no blocked attribute defined for nsICookie. What should be passed there is false, assuming that there is no intent to block cookies from that host. As it is, undefined is currently being passed.
Iterating over only those cookies from the host in question, rather than all cookies, is accomplished by using the nsICookieManager2 interface. Specifically the getCookiesFromHost() method.
The updated code is:
ContentScript.js
function DeleteCookies() {
var payload="Delete";
self.port.emit("Delete", payload);
}
Main.js
var {Cc, Ci} = require("chrome");
pageMod.PageMod({
include: "*",
contentScriptFile: [ self.data.url("jquery-1.9.1.js")
,self.data.url("script.js")],
onAttach: function(worker) {
worker.port.on('Delete',function (){ DeleteCookies();});
}
});
var cookieManager = Cc["#mozilla.org/cookiemanager;1"].getService(Ci.nsICookieManager2);
function DeleteCookies() {
DeleteAllCookiesForDomain("siteB.com");
};
function DeleteAllCookiesForDomain( domain ) {
var iter = cookieManager.getCookiesFromHost(domain);
var cookie_count = 0;
while (iter.hasMoreElements()) {
var cookie = iter.getNext();
if (cookie instanceof Ci.nsICookie) {
cookieManager.remove(cookie.host, cookie.name, cookie.path, false);
cookie_count++;
}
}
return cookie_count;
};
I am trying to pass a value from one tab to another.
I tried sessionStorage and clipboard, but no luck so far. Here is the demo, and the code as well:
https://builder.addons.mozilla.org/package/154290/latest/
What it tries to do is get the selected text, and pass it to the opened tab:
// Create a new context menu item.
var menuItem = contextMenu.Item({
label: "Check with Proofread Bot",
context: contextMenu.SelectionContext(),
contentScript: 'self.on("click", function () {' +
' var text = window.getSelection().toString();' +
' sessionStorage.setItem("proofread_bot_chrome", text);' +
' self.postMessage(text);' +
'});',
onMessage: function(text) {
clipboard.set(text);
//sessionStorage.setItem("proofread_bot_chrome", text);
tabs.open({
url: "http://proofreadbot.com",
onOpen: function onOpen(tab) {
// do stuff like listen for content
// loading.
alert(clipboard.get());
alert(selection.text);
sessionStorage.setItem("proofread_bot_chrome", clipboard.get());
}
});
}
});
sessionStorage and localStorage are always bound to a domain. Content scripts run with the privileges of the web page meaning that they access the session storage for that web page - not very useful to pass data around. And they simply don't have clipboard access.
This means that you can't get around "traditional" messaging. When you open the tab you should attach a content script, wait for it to be ready (the content script can send a message to indicate that) and send it the text. Something like this:
onOpen: function(tab) {
var worker = tab.attach({
contentScript: "self.on('message', function(text) {alert(text);});" +
"self.postMessage(null);",
onMessage: function() {
worker.postMessage(text);
}
});
}
For reference: Communicating using postMessage()
You should try localStorage instead of sessionStorage. localStorage is shared between the documents from same origin.
Although it persists even on tab close, which may or may not be desirable depending on your requirement.
sessionStorage is per document, and hence not shared between tabs.