So I'm trying to follow the instructions for a firefox extension using WebExtensions and I want to attach a content script to certain pages (as discussed here: https://developer.mozilla.org/en-US/Add-ons/WebExtensions/Modify_a_web_page ).
Problem is I don't want to specify the set of pages I want the content_script to run on in manifest.json when I write the extension but load it from local storage, i.e., I have an options page set up where the user can specify the pages the content script should be run on. Is it possible to dynamically change the list of pages to be modified that is normally set using the content_script directive in manifest.json?
Thanks
No, there is no way to modify the URLs into which injection will occur for a manifest.json content_script (either CSS or JavaScript). The specified code will be injected in all matching URLs. This is for multiple reasons.
One of the reasons this is not possible is security/transparency to the user. The manifest.json explicitly declares which URLs your content script will be modifying, states that it will be modifying the active tab, or that it will have access all URLs/tabs. If you were permitted to change the URLs, then you would effectively be given the ability to access all URLs without explicitly declaring that you are doing so.
Yes, it would be possible to have a way to declare that you are going to do so. Chrome has an experimental way to do so with chrome.declarativeContent. In Chrome this is considered experimental, even after being available for a couple/few years. It is not available in Firefox. When it will be available, or even if it will be available in Firefox is unclear. In addition, even in Chrome, it lacks some features available to other methods of injecting scripts (e.g. run_at/runAt).
In order to have complete control over injecting, or not injecting, you will need to perform the injection via tabs.insertCSS() and/or tabs.executeScript(). Injecting, or not injecting, scripts and CSS with these methods is fully under the control of the JavaScript in your extension. It is possible to get similar functionality using these methods to what you obtain with manifest.json content_script entries, but with more control. This greater control comes at the expense of greater complexity.
How about that? There is a bunch of events to listen, you can pick any one which would satisfy uour requirements:
onBeforeNavigate
onCommitted
onDOMContentLoaded
onCompleted.
The documentation is here. And this is an example of how to make red background on subdomains of example.com. Of course, you can build the list of URL filters dynamically, this is just a PoC:
browser.webNavigation.onCommitted.addListener(
function(details) {
browser.tabs.insertCSS(details.tabId, {code: 'body {background:red}'})
},
{url: [{hostSuffix: '.example.com'}]}
);
Related
I never thought to ask this, but I work on a security product and so we implement pretty strict protection against XSS:
We disallow < and > in user input both server- and client-side
If the user does manage to make a request containing either of those characters, the server will disable their account and leave a warning for an admin
Angular also sanitizes interpolated content before injecting it into the DOM
This is all great and dandy, except, it hurts UX and it's bad for performance. Surely, SURELY, there is a way to just tell the browser NOT to execute <script> tags added after initial document parsing, right? We use a modern bundled workflow and any lazy-loading of JavaScript will be done via import("/some/js/module") calls which get rebased by the bundler but will never be fed a dynamic value at runtime.
Even if there isn't a way to straight up tell the browser not to run dynamically added (by JS after page load) <script> tags, is there a tried and true workflow for rendering, say, markdown + HTML subset user-produced content in iframes? I am familiar with iframes at a high-level, but I mean can the parent document/page manipulate the DOM content of the iframe or something so even if it does add a <script> tag inside the iframe, the script code will not have access to the parent document's JS environment?
Actually that would be cool as a sandboxed way to display user content because they could intentionally include a script and make a little interactive widget for other users to mess with, in theory (maybe an antifeature in practice).
You can do it with CSP (Content Security Policy)
https://developers.google.com/web/fundamentals/security/csp#inline-code-considered-harmful
Example:
Allow only :
<script nonce="EDNnf03nceIOfn39fn3e9h3sdfa">
// Some inline code I can't remove yet, but need to asap.
</script>
with
Content-Security-Policy: script-src 'nonce-EDNnf03nceIOfn39fn3e9h3sdfa'
Start by blocking all with:
default-src 'none'
Soo, now with all the GDPR, and opt-in cookie boxes, i have run in to a small issue..
I have set my google analytics code into a javascript file, and added it to my layout :
<script src="~/Scripts/Google/analytics.js" class="cookie-script" type="text/plain"></script>
I have it set to text/plain in the beginning, and then i have some other script that checks if you have accepted cookies.
When you have accepted cookies, it will change it to text/javascript.
It also checks at page load if you have already accepted and then changes it to text/javascript..
My issue...
It does not appear it is tracking correctly with google analytics..
Can analytics not figure out to track once it has been "activated" ?
How to overcome this, so i can still get my data ?
in my analytics account, i have taken the code it says to include in my head element. But no data makes it through...
It does not cause problems, if the intent is that browsers do not interpret the content of the element as script code but just as text data that is not rendered. It’s there for scripts to use it, but otherwise it’s ignored. Well, in some browsers, the content might be made visible using CSS, but by default it’s not shown.
Using is valid by HTML specs. Even is valid, though it violates the prose requirement that the attribute value be a MIME type. The specs do not specify its meaning, but the only feasible interpretation, and what browsers do in practice, is that it is not in any scripting language and no execution as script is attempted.
So type="text/plain" may be used to intentionally prevent execution of a script, while still keeping it in the source. It may also be used to carry bulks of character data used for some processing.
The type attribute may serve purposes like this, and it can also be used to specify scripting languages other than JavaScript (rarely used, but still possible in some environments). Using the type attribute just to specify JavaScript is not needed, and cannot be recommended: the only thing that you might achieve is errors: if you mistype, e.g. type="text/javascript", the content will be regarded as being in an unknown language, hence ignored.
We're struggling into possible DTM Adobe Analytics Tool conditions, in order to let the tool be active only on certain pages.
In fact, tools settings don't allow any Conditions, like Rules instead.
If we flag the "Page code is already present" checkbox, no tool code would be active at all.
Our requirement is that just some pages already have the page code, thus the Adobe Analytics tool would be active just for the other ones.
In short, it would be like the "Page code is already present" checkbox could be conditioned.
We tested some Page-load rules which could fire, conditionally, the tool, but it does not work.
Hi and thanks for replying! (i'm the same user who posted),You all confirmed my thoughts about, especially the need for some workarounds to condition the tool triggering. For the time being, I simply included all my tool content within an "if" clause and so it works.The possibile use of the s.abort option is interesting but I suppose every call, next to the initial onload, would be stopped if this is set to true.
The DTM tool would be prevented from working, but any Custom Links or user actions generated calls would be blocked.Is this right?
If so, the "manual" condition of the tool code content seems to be the easiest and quicker solution.
As was suggested, if the "Page Code is already on the page" is selected then the Adobe Analytics Tool will not run via DTM.
In your case where essentially different configurations are required to run on different pages, you could consider creating 2 individual properties (one for each configuration) and 1 global property in DTM that would then deploy the specific property header file based on URL.
In essence, you deploy the global header on all pages and then write a script within the global property that would deploy the "child" property script based on URL.
Something like:
switch (trimPath) {
// Code present property
case "myURL.com":
document.write("<script src='//header-code-path-here.js'</scr'+'ipt>");
break;
// Adobe Analytics Tool Property
case "myOtherURL.com":
document.write("<script src='//header-code-path-here.js'</scr'+'ipt>");
}
Hope this helps.
I have 4 pages, I use ajax and historyPopState to change betweens them. But there is a problem since the pages are very different they use different stylesheets and scripts. I could just download them over and over again, but I wanted to ask if there is a way how to keep it onpage, but only disabling it for a moment and reenable them when needed.
PS.:Those 4 pages have one stylesheet & one script in common.
PPS.: And I can't set headers (not access to all things in server)
In javascript you can disable stylesheets by accessing the styleSheets object on the document and setting disabled to true:
(tested in Chrome and IE9. I couldn't find any useful statistics on compatibility for this)
document.styleSheets[0].disabled = true
Quick question, I have some scripts that only need to be run on some pages and some only on a certain page, would it be best to include the script at the bottom of the actual page with script tags or do something like in my js inlcude;
var pageURL = window.location.href;
if (pageURL == 'http://example.com') {
// run code
}
Which would be better and faster?
The best is to include the script only on pages that need it. Also in terms of maintenance your script is more independant from the pages that are using it. Putting those ifs in your script makes it tightly coupled to the structure of your site and if you decide to rename some page it will no longer work.
I can recommend you to use an asynchrounous resource loader, LAB.js for example. Then you could build a dependencies list, for instance:
var MYAPP = MYAPP || {};
/*
* Bunches of scripts
* to load together
*/
MYAPP.bunches = {
defaults: ["libs/jquery-1.6.2.min.js"],
cart: ["plugins/jquery.tmpl.min.js",
"libs/knockout-1.2.1.min.js",
"scripts/shopping-cart.js"],
signup: ["libs/knockout-1.2.1.min.js",
"scripts/validator.js"]
/*
... etc
*/
};
/*
* Loading default libraries
*/
$LAB.script(MYAPP.defaults);
if (typeof MYAPP.require !== 'undefined') {
$LAB.script(MYAPP.dependencies[MYAPP.require]);
}
and in the end of your page you could write:
<script type="text/javascript">
var MYAPP = MYAPP || {};
MYAPP.require = "cart";
</script>
<script type="text/javascript" src='js/libs/LAB.min.js'></script>
<script type="text/javascript" src='js/dependencies.js'></script>
By the way, a question to everyone, is it a good idea to do so?
In so far as possible only include the scripts on the pages that requirement. That said, if you're delivering content via AJAX that can be hard to do, since the script might already be loaded and reloading could cause problems. Of course you can deliver code in a script block (as opposed to referencing an external js file), in code delivered via AJAX.
In cases where you need to load scripts (say via a master page) for all pages, but that only apply to certain pages, take advantage of the fact that jQuery understands and deals well with selectors that don't match any elements. You can also use live handlers along with very specific selectors to allow scripts loaded at page load time to work with elements added dynamically later.
Note: if you use scripts loaded via content distribution network, you'll find that they are often cached locally in the browser anyway and don't really hurt your page load time. The same is true with scripts on your own site, if they've already been loaded once.
You have two competing things to optimize for, page load time over the network and page initialization time.
You can minimize your page load time over the network by taking maximum advantage of browser caching so that JS files don't have to be loaded over the network. To do this, you want as much javascript code for your site in on or two larger and fully minimized JS files. To do this, you should put JS for multiple different pages in one common JS file. It will vary from site to site whether the JS for all pages should be ine one or two larger JS files or whether you group it into a small number of common JS files that are each targeted at part of your site. But, the general idea is that you want to combine the JS code from different pages into a common JS file that can be most effectively cached.
You can minimize your page initialization time by only calling initialization code that actually needs to execute on the particular page that is being displayed. There are several different ways to approach this. I agree with the other callers that you do not want to be looking at URLs to decide which code to execute because this ties your code to the URL structure which is better to avoid. If your code has a manageable number of different types of pages, then I'd recommend identifying each of those page types with a unique class name on the body tag. You can then have your initialization code look for the appropriate class on the body tag and branch to the appropriate initialization code based on that. I've even seen it done where you find a class name with a particular common prefix, parse out the non-common part of the name and call an initialization function by that name. This allows you to give a page a specific set of behaviors by only adding a classname to the body tag. The code remains very separate from the actual page.
the less general purpose way of doing this is to keep all the code in the one or two common JS files, but to add the appropriate initialization call to each specific page's HTML. So, the JS code that does the initialization code lives in the common JS files and thus is maximally cached, but the calling of the appropriate initialization code for that page is embedded inline in each specific page. This minimizes the execution time of the initialization, but still lets you use maximal caching. It's slightly less generic than the class name technique mentioned earlier, but some may like the more direct calling technique.
Include scripts at bottom of pages that need it only.
The YSlow add-on is the best solution to know why your website is slow.
There are many issues which could be the reason for slowness.
Combining many jQuery to one could help you increasing your performance.
Also you can put the script at the bottom of your page and CSS at top.
Its basically up to you and depends on what the code is.
Generally with small things I will slip it into the bottom of the page. (I'm talking minor ui things that relate only to that page).
If you're doing the location ref testing for more than a couple pages it probably means you're doing something wrong.
You might want to take a look at one of these:
http://en.wikipedia.org/wiki/Unobtrusive_JavaScript
http://2tbsp.com/node/91
And as for which is faster it's wildly negligible, pick what is easier for you to maintain.