So At the moment, My code is listening in, and I want it to listen and then see any url which belongs under "https://www.stackoverflow.com/questions/*"
How do I go about using the asterisk in my current code to make sure that all of the website can use my function ?
var regex = /^((ftp|http|https):\/\/)?(www.)?(?!.*(ftp|http|https|www.))[a-zA-Z0-9_-]+(\.[a-zA-Z]+)+((\/)[\w#]+)*(\/\w+\?[a-zA-Z0-9_]+=\w+(&[a-zA-Z0-9_]+=\w+)*)?$/gm;
var str = ["http://www.whatevershop this is/jackets/#", "https://www.whatevershop this is/shoes/#"];
var matches_array = str.match(regex);
chrome.tabs.onUpdated.addListener(function(tabId, changeInfo, tab) {
chrome.extension.getBackgroundPage().console.log(tab.url);
if (matches_array == tab.url) {
chrome.tabs.executeScript(null, {
file: "test.js"
});
}
});
The issue is when I use the asterisk (*) at the end of the slash (/) it doesn't actually let me use every single url, only the one which I enter ?
Any fixes ?
UPDATE:
Ive edited it as told, including the url and function still wont run :(
var regex = /^((ftp|http|https):\/\/)?(www.)?(?!.*(ftp|http|https|www.))[a-zA-Z0-9_-]+(\.[a-zA-Z]+)+((\/[\w#-]+)*(\/\w+\?[a-zA-Z0-9_]+=\w+(&[a-zA-Z0-9_]+=\w+)*)?$/gm;
And the str code is var str = ["http://www.whateversiteyouneed.com/shop/#", "https://www.whateversiteyouneed.com/shop/#"];
Bare in mind on the site, there are different categories, hence why the # is in place to allow it to use all of the different locations.
I'm still wondering why the script wont run though.
It's something in the script which isn't actually seeing the new url ?
If you only want your script executed on specific urls then in your manifest add a section for content_scripts with an array of urls allowed. This is a lot simpler than using tab update events and regex and has wildcards
e.g.
"content_scripts": [
{
"matches": ["*://*.whatever.com/dogs/*"],
"js": ["test.js"],
"run_at": "document_end",
}
]
Note it's an array of arrays, so you can put as many urls in 'matches' as you wish and with the outer array, you could have different scripts on different domains. Not that that's a common use case. See extension match patterns
With this approach, the script is injected automatically and by default is inject once the page is idle, which is usually equivalent to after document ready. I usually use document_end if my code is to execute immediately. If the code will be invoked by a message from the background, e.g. by context menus, you can load at start.
Related
I am trying to navigate a webpage with a content script. However the function keeps running because every time the page changes it runs through the script. I was wondering if there was a better way to do this as it is a resource hog and also disallows the user to interact with the page because of the constant refreshing.
Here's the code in question, sorry if it looks weird. I do not have more then a few weeks of knowledge in jQuery.
$(document).ready(function(){
console.log("Made it here" + window.location.href);
loc = window.location.href;
match = loc.match('http://url.com/uc/');
if (match) {
window.location = "http://url.com/uc/health/index/1";
console.log("2 here");
window.location = "http://url.com/uc/health/communication/createSelectTemplate";
console.log("3 here");
chrome.storage.local.get('formOption', function(result) {
document.getElementById('formTemplate').value = result.formOption;
document.forms[0].submit();
});
}
});
The reason i have to navigate three windows before using values because whoever made this website has timeout cookies and the pages can not be called before the previous one loads.
It is a content script tho, so all the code is on the next page. Maybe if there was a way to check exact url? But when i was playing with that awhile back the computer didn't distinguish between.
urlhere.com/uc/
and
urlhere.com/uc/health/index/1
Every time you navigate (e.g. immediately after assigning window.location), your script stops executing is unloaded with the page, and when the next page loads, the content scripts are indeed loaded again. If the same script is loaded, with the same initial state, it will of course execute the same operation.
Possible solutions (there are many):
Be more precise with your matching (= better notice the actually changing state).
loc.match('http://url.com/uc/') will only check that the address includes that string - which all URLs you show do. Why not just use loc == 'http://url.com/uc/' (and check for intermediate pages)?
Use fine-grained content scripts (= load different scripts).
Manifest defines which pages get what scripts on load. I assume you have something like this:
"content_scripts" : [{
"js" : ["jquery.js", "content1.js"],
"matches": ["http://*"]
}]
You can make several scripts and let Chrome parse the URLs. For example, content1.js will do the first redirect, content2.js will do the second.
"content_scripts" : [{
"js" : ["jquery.js", "content1.js"],
"matches": ["http://url.com/uc/"]
}, {
"js" : ["jquery.js", "content2.js"],
"matches": ["http://url.com/uc/health/index/1"]
}]
Use some persistent state (that persists between navigation) to indicate which stage of redirect are you on (= control changing state yourself).
The page's sessionStorage is ideal for this, as it's only persistent within the tab:
if (match) {
switch (sessionStorage.redirectStage) {
case 3:
// We're at the final page, do actual work
break;
case 2:
sessionStorage.redirectStage = 3;
window.location = "http://url.com/uc/health/communication/createSelectTemplate";
break;
default: // Includes initial state when it's unset
window.location = "http://url.com/uc/health/index/1";
}
}
I'm attempting to perform programmatic injection of my content script into open tabs after my Chrome extension is reloaded or updated.
My script may call the following method for an arbitrary tab:
var manifest = chrome.app.getDetails();
var scripts = manifest.content_scripts[0].js;
chrome.tabs.executeScript(nTabID, {
file: scripts[0]
});
This works, except when I try to load it into a page that was not supposed to have a content script running according to the matches clause in the manifest.json. I get the following exception:
Cannot access contents of url "actual-url-here". Extension manifest
must request permission to access this host.
So my question. Is there a way to parse the page URL and see if it matches matches clause from manifest.json and prevent calling chrome.tabs.executeScript for unnecessary URL?
PS. I understand that one "hacky" solution is to catch-and-ignore exceptions. So I'm not asking for it.
When you use chrome.tabs.query for a list of tabs, use the url attribute to filter by a match patterns. As of Chrome 39, this key also supports an array of match patterns. If you need to support Chrome 38 or earlier, or if you got the tabs without chrome.tabs.query, use the parse_match_pattern function from this answer to filter tabs. To use it, copy that function and include it within your (background) page (e.g. by pasting it before the following snippet).
var content_scripts = chrome.runtime.getManifest().content_scripts;
// Exclude CSS files - CSS is automatically inserted.
content_scripts = content_scripts.filter(function(content_script) {
return content_script.js && content_script.js.length > 0;
});
content_scripts.forEach(function(content_script) {
try {
// NOTE: an array of patterns is only supported in Chrome 39+
chrome.tabs.query({
url: content_script.matches
}, injectScripts);
} catch (e) {
// NOTE: This requires the "tabs" permission!
chrome.tabs.query({
}, function(tabs) {
var parsed = content_script.matches.map(parse_match_pattern);
var pattern = new RegExp(parsed.join('|'));
tabs = tabs.filter(function(tab) {
return pattern.test(tab.url);
});
injectScripts(tabs);
});
}
function injectScripts(tabs) {
tabs.forEach(function(tab) {
content_script.js.forEach(function(js) {
chrome.tabs.executeScript(tab.id, {
file: js
});
});
});
}
});
The previous snippet inserts a content script in all tabs. It is your responsibility to make sure that inserting the script does not conflict with an earlier/later instance of your script.
Mimicking the all_frames and match_about_blank functionality is slightly more complex, because the chrome.tabs.executeScript API cannot be used to target specific frames (crbug.com/63979). If you want to inject in frames as well, then you have to insert in every tab (because there might be a frame under the non-matching top-level frame that matches the URL) and check the page's URL within the content script.
Finally, note that your content script must also deal with the fact that it may run at a point different from "run_at". In particular, content scripts that rely on "run_at":"document_start" might fail to work because calling chrome.tabs.executeScript will cause a script to be injected far past the document_start phase.
I tried to replace by a local script the url of scripts loaded by websites.
I tried to channel.redirectTo() with data.url() and chrome:// (with contentaccessible=yes flag in manifest), but doesn't work, so I compared a regex pattern, if true, it will cancel the XHR GET request.
For example
<script src="http://url/to/script.js"></script>
become
<script src="resource://url/to/new/script.js"></script>
or
<script src="chrome://url/to/new/script.js"></script>
Now I need to replace the url or inject my new script to the page
main.js
var listener = function (event) {
var channel = event.subject.QueryInterface(Ci.nsIHttpChannel);
var match = someFunctionToMatchRegex(channel.URI.spec);
if (match) {
channel.cancel(Cr.NS_BINDING_ABORTED);
}
};
events.on("http-on-modify-request", listener);
I have a redirect module here which is a good example for what you want to do. You might be able to use it, though the module only takes specific urls and not reg expressions at the moment. I'd certainly take a pull request to make this change though.
The code basically just uses redirectTo as you mention, so something else is wrong.
I am building a chrome extension for reddit.com and I am using page action for that. Now I want page_action icon to be visible only for a specific url format i.e.
http://www.reddit.com [allowed]
http://www.reddit.com/r/* [allowed]
http://www.reddit.com/r/books/comments/* [not allowed]
So, as I have mentioned above that I don't want my extension page action icon to be visible for the 3rd case involving comments url of redddit .
Currently I am using the below code in my background.js to achieve this:
function check(tab_id, data, tab){
if(tab.url.indexOf("reddit.com") > -1 && tab.url.indexOf("/comments/") == -1){
chrome.pageAction.show(tab_id);
}
};
chrome.tabs.onUpdated.addListener(check);
I have also added the below line in my manifest.json to disable the extension on the comment page
"exclude_matches": ["http://www.reddit.com/r/*/comments/*"],
So, my question is this the correct/ideal way to disable & hide an extension from a specific page/url?
Why not Zoidb- I mean, Regular Expressions?
var displayPageAction = function (tabId, changeInfo, tab) {
var regex = new RegExp(/.../); //Your regex goes here
var match = regex.exec(tab.url);
// We only display the Page Action if we are inside a tab that matches
if(match && changeInfo.status == 'complete') {
chrome.pageAction.show(tabId);
}
};
chrome.tabs.onUpdated.addListener(displayPageAction);
About the approach, I think using the onUpdated.addListener is the correct approach. As a good practice, try to show your page Action only when the tab has been loaded, unless your application requirements specify otherwise.
You can use this tool in order to generate your regular expression, and if you need help, feel free to ask again and we will help you assemble the regular expression you need.
I'd like to write an extension that redirects all web traffic to a specific domain, let's say wikipedia.org, to an intermediate page that says something like, "Whoa, bub. You're about to go to Wikipedia. Are you sure about this?" followed by Yes and No buttons.
How do I respond to a specific URL request and replace the desired page with a custom one when it meets the condition of being a page with "wikipedia.org" in the domain?
You can do this using webRequest feature, a background page, and custom page with yes and no buttons. For example, write something similar in the background page:
var URLStorage;
function interceptRequest(request)
{
if(request && request.url)
{
if(request.type == "main_frame") // new page/site is loading in main window
{
if(request.url.indexOf("wikipedia.org") > -1)
{
URLStorage = request.url;
return {redirectUrl: chrome.extension.getURL("confirmation.html")};
}
}
}
}
chrome.webRequest.onBeforeRequest.addListener(interceptRequest, {urls: ["*://*/*"]}, ['blocking']);
This example does not strictly check if wikipedia is mentioned in domain, but I did this for clarity. In my real code a special class 'URL' is used which parses passed url and provides properties for every part of it, so they can be checked selectively.
In the confirmation.html just place 2 buttons, and bind them to an appropriate code, for example redirecting to requested site, if a user answered "yes".
$('#okbutton').click(function()
{
document.location.href = chrome.extension.getBackgroundPage().URLStorage;
});
Don't forget to mention "webRequest" and "webRequestBlocking" in permissions section of your manifest.
You can create a content script that injects javascript code into each page that the user visits. In your content script you could have the js check the current url against invalid url's and redirect them accordingly.
I think content scripts load after the page has loaded so there may be a brief period where the user sees the page they were looking for and then gets redirected to your landing page. Check out the content script docs here:
http://developer.chrome.com/extensions/content_scripts.html
{
"name": "My extension",
...
"content_scripts": [
{
"matches": ["http://www.google.com/*"],
"css": ["mystyles.css"],
"js": ["jquery.js", "myscript.js"]
}
],
...
}
"matches" you should make the array of something similar to
"matches": ["http://www.*.com/*", "http://*.com/*, "https://www.*.com/*", "https://*.*.com/*]
and "js" would be the name of your javascript file that you want to use to write the injection into the page.
something like:
if(window.location == "http://wikipedia.com"){
window.location.href = "http://mysplashpage.com";
}
Of course, that js won't work in all instances, for instance, if the user is trying to get to a directory of the target website. You will probably need to some regex checks or some other functions like protocol and host as defined here : http://css-tricks.com/snippets/javascript/get-url-and-url-parts-in-javascript/