I would like to override a javascript file with my own version of the similar javascript file in chrome.
Let me explain:
Lets say a site 'http://example.com' calls 'http://example.com/script/somescript.js'.
What I would like to do is override the file 'http://example.com/script/somescript.js' with my own version located at 'http://localhost/script/somescript.js'.
I need to effectively modify a function in the original Javascript file.
With Chrome 65 this has become trivial.
Using local overrides – Chrome 65
What is it?
It is a new feature that allows us to override a websites code/css with a local copy that is persisted across sessions. Once you override a file it shall remain until you remove the override.
How to set it up?
Open the Sources panel.
Open the Overrides tab.
Open overrides tab
Click Setup Overrides.
Select which directory you want to save your changes to.
At the top of your viewport, click Allow to give DevTools read and write access to the directory.
Make your changes.
After you add a folder you can switch to the network tab and right click on any file and select “Save for overrides”. I have already overridden scripts.js so it shows with a “blue dot”.
There are plugins and tools in Chrome for these purposes:
Chrome's DevTools, tab Local Overrides (supported from Chrome 65)
Requestly
Resource Override
You might also want to use Tamper, which is a mitmproxy based devtools extension that lets you edit remote files locally and serve them directly to Chrome. (but it's more headache to install and use it)
Choose the one which is easier to use for you.
You can create a chrome extension yourself. It is surprisingly easy and takes only a few minutes if you use a tool like yeoman chrome extension. Create a new directory and run the generator
yo chrome-extension
Enter a name for your extension and a short description. Select Page Action and that you want to use Content Scripts. You can ignore other options - follow this excellent guide if you come in doubt, but it is really straight forward.
? What would you like to call this extension? insert-script
? How would you like to describe this extension? replace a function with another function
? Would you like to use UI Action? Page Action
? Would you like more UI Features? Content Scripts
? Would you like to set permissions?
..etc. Now you have a directory structure like this
app
bower_components
images
_locales
scripts.babel
background.js
chromereload.js
contentscript.js
You cannot replace an existing loaded remote script with another script, since the script already is loaded into the DOM. But you can insert a new script at the end of body which overrides the function you want to replace. Functions is variables, if you add a new function to the document with the same name as an existing function, the new function will be executed instead of the old, exactly as if you declared a new variable with the same name as an existing variable. Now open and edit contentscript.js :
'use strict';
console.log('\'Allo \'Allo! Content script');
The code could look like this
'use strict';
var code = `
function foo() {
alert('foo');
}
`;
var script = document.createElement('script');
script.textContent = code;
document.body.appendChild(script);
Notice the template literal. We need to insert the code as a string, but with backticks it is more readable. Replace foo() with the function you want to override.
There is no need for deployment or bundling. You can install your extension right away from the path where you runned the generator
go to chrome://extensions
check developer mode
click upload unpacked extension
select manifest.json from your path
after that you just have to hit reload on the extensions page when you have made changes to contentscript.js.
you can load your file into the page by adding (or executing in the console) this script.
window.onload = function () {
var script = document.createElement('script');
script.src = '//localhost/your/script';
script.onload = function() {
console.log('your script have been loaded');
}
document.body.appendChild(script);
}
If the file that you want to override contains global functions/variables will be override with the new version in your file or if the elements that you want to override are namespaced just follow the path (e.g My.namespace.method = myNewMethod)
According to dharam's answer above,Resource Override works.
For people who doesn't have access to Chrome store,you can download the source here:
https://github.com/kylepaulsen/ResourceOverride
in Chrome,get into chrome://extensions/ ,enable developer mode,then load the extracted source root directory(which contains the file manifest.json) into Chrome.
tested for Chrome 73.0.3683.86 on Windows 10 .I can't post anything on StackOverflow before because https://ajax.googleapis.com/ajax/libs/jquery/1.12.4/jquery.min.js is blocked.Then in the settings of ResourceOverride,I map it to https://localhost/jquery-1.12.4.min.js and it finally works.
I run an ASP.NET Core 2.1 project with SSL enabled and localhost certificate enabled to serve jquery-1.12.4.min.js from local disk.
In the launchSettings.json,there is
"applicationUrl": "https://localhost:443;http://localhost:80",
in the Kestral profile(not IIS profile).
Related
Pretty straight-forward, I'm developing an MVC5 application and have noticed (lately) that my Browser appears to be caching the JavaScript code I have on the view within #section Scripts { }.
Currently I am developing with Chrome and I have tried CTRL+F5 & CTRL+SHFT+R which reloads the page, but the alert() I uncommented within the javascript code is still rendering as commented. I also tried going to my localhost through Incognito Mode as well as other Browsers (Firefox, IE) and am getting the same behavior. This is my /Home/Index.cshtml View, which is the default View which loads when the application starts. I have also tried adding some extra HTML text into the page and again the new code is not taking effect/showing.
My current Chrome version is Version 41.0.2272.118 m if anyone has any ideas what might be going on?
UPDATE:
I have gone under the Developer Tools => General Settings in Chrome and checked [X] Disable cache (while DevTools is open) and then repeatedly (with DevTools still open) tried CTRL+SHFT+R and CTRL+F5 with the same results of before where my changes are not taking effect.
UPDATE 2:
With DevTools open I have also held the Refresh button down and tried Normal/Hard/and Empty Cache & Hard Reload options all with the same result. For simplicity of testing I added an alert in the below to dispaly as soon as the page loads (and currently no alert comes up):
$(document).ready(function () {
alert("Test");
// Other Code/Functions -- No Error showing in Console
});
If you are using Bundling from MVC, you have two options to disable caching:
Use BundleTable.EnableOptimizations. This instructs the bundling to minify and optimize your bundle even while debugging. It generates a hash in the process, based on the content of the script, so your customers browsers can cache this file for a long time. It will generate a whole different hash the next time your file changes, so your customers can see your changes. The downside is that your script will become unreadable and you won't be able to debug it, so this might not be your best option.
Use System.Web.Optimization.BundleTable.Bundles.ResolveBundleUrl("url", true) to resolve your script's URL, the second parameter (true) is requiring a hash to be generated with the URL, thus, preventing caching from your browser when you change the file. This is exactly the same hash generated in the first option, but without minifying.
I created a small demo showing that the second option prevents caching from happening, the trick is getting the hash generated from your script's content without minifying your script.
I created a script file called myscript.js with this content:
$(document).ready(function () {
alert('a');
});
Then I added this to my BundleConfig.cs:
// PLEASE NOTE this is **NOT** a ScriptBundle
bundles.Add(new Bundle("~/bundles/myscripts").Include(
"~/Scripts/myscript*"));
If you add a ScriptBundle, you will get a minified response again, since ScriptBundle is just a Bundle using JsMinify transformation (source). That's why we just use Bundle.
Now you can just add your script using this method to resolve the script URL with the hash appendend. You can use the Script.Render
#Scripts.Render(System.Web.Optimization.BundleTable.Bundles.ResolveBundleUrl("~/bundles/myscripts", true))
Or the script tag:
<script src="#System.Web.Optimization.BundleTable.Bundles.ResolveBundleUrl("~/bundles/myscripts", true)"></script>
Either way will generate a URL with a hash to prevent caching:
After editing my file:
You might want to add a no_cache variable after your script url like:
<script src="js/stg/Stg.js?nocache=#random_number"></script>
If you manage to put a random number to the place i indicated, the browser will automatically download the latest version of the script after an F5
A quick trick that solves this problem consists of opening the script file in a new tab, then refresh it on this page.
If you happen to have Chrome dev tools open it will even refresh it there.
From dev tool you can even easily right click-open in new tab the script.
How do i set up a custom protocol handler in chrome? Something like:
myprotocol://testfile
I would need this to send a request to http://example.com?query=testfile, then send the httpresponse to my extension.
The following method registers an application to a URI Scheme. So, you can use mycustproto: in your HTML code to trigger a local application. It works on a Google Chrome Version 51.0.2704.79 m (64-bit).
I mainly used this method for printing document silently without the print dialog popping up. The result is pretty good and is a seamless solution to integrate the external application with the browser.
HTML code (simple):
Click Me
HTML code (alternative):
<input id="DealerName" />
<button id="PrintBtn"></button>
$('#PrintBtn').on('click', function(event){
event.preventDefault();
window.location.href = 'mycustproto:dealer ' + $('#DealerName').val();
});
URI Scheme will look like this:
You can create the URI Scheme manually in registry, or run the "mycustproto.reg" file (see below).
HKEY_CURRENT_USER\Software\Classes
mycustproto
(Default) = "URL:MyCustProto Protocol"
URL Protocol = ""
DefaultIcon
(Default) = "myprogram.exe,1"
shell
open
command
(Default) = "C:\Program Files\MyProgram\myprogram.exe" "%1"
mycustproto.reg example:
Windows Registry Editor Version 5.00
[HKEY_CURRENT_USER\Software\Classes\mycustproto]
"URL Protocol"="\"\""
#="\"URL:MyCustProto Protocol\""
[HKEY_CURRENT_USER\Software\Classes\mycustproto\DefaultIcon]
#="\"mycustproto.exe,1\""
[HKEY_CURRENT_USER\Software\Classes\mycustproto\shell]
[HKEY_CURRENT_USER\Software\Classes\mycustproto\shell\open]
[HKEY_CURRENT_USER\Software\Classes\mycustproto\shell\open\command]
#="\"C:\\Program Files\\MyProgram\\myprogram.exe\" \"%1\""
C# console application - myprogram.exe:
using System;
using System.Collections.Generic;
using System.Text;
namespace myprogram
{
class Program
{
static string ProcessInput(string s)
{
// TODO Verify and validate the input
// string as appropriate for your application.
return s;
}
static void Main(string[] args)
{
Console.WriteLine("Raw command-line: \n\t" + Environment.CommandLine);
Console.WriteLine("\n\nArguments:\n");
foreach (string s in args)
{
Console.WriteLine("\t" + ProcessInput(s));
}
Console.WriteLine("\nPress any key to continue...");
Console.ReadKey();
}
}
}
Try to run the program first to make sure the program has been placed in the correct path:
cmd> "C:\Program Files\MyProgram\myprogram.exe" "mycustproto:Hello World"
Click the link on your HTML page:
You will see a warning window popup for the first time.
To reset the external protocol handler setting in Chrome:
If you have ever accepted the custom protocol in Chrome and would like to reset the setting, do this (currently, there is no UI in Chrome to change the setting):
Edit "Local State" this file under this path:
C:\Users\Username\AppData\Local\Google\Chrome\User Data\
or Simply go to:
%USERPROFILE%\AppData\Local\Google\Chrome\User Data\
Then, search for this string: protocol_handler
You will see the custom protocol from there.
Note: Please close your Google Chrome before editing the file. Otherwise, the change you have made will be overwritten by Chrome.
Reference:
https://msdn.microsoft.com/en-us/library/aa767914(v=vs.85).aspx
Chrome 13 now supports the navigator.registerProtocolHandler API. For example,
navigator.registerProtocolHandler(
'web+custom', 'http://example.com/rph?q=%s', 'My App');
Note that your protocol name has to start with web+, with a few exceptions for common ones (like mailto, etc). For more details, see: http://updates.html5rocks.com/2011/06/Registering-a-custom-protocol-handler
This question is old now, but there's been a recent update to Chrome (at least where packaged apps are concerned)...
http://developer.chrome.com/apps/manifest/url_handlers
and
https://github.com/GoogleChrome/chrome-extensions-samples/blob/e716678b67fd30a5876a552b9665e9f847d6d84b/apps/samples/url-handler/README.md
It allows you to register a handler for a URL (as long as you own it). Sadly no myprotocol:// but at least you can do http://myprotocol.mysite.com and can create a webpage there that points people to the app in the app store.
This is how I did it. Your app would need to install a few reg keys on installation, then in any browser you can just link to foo:\anythingHere.txt and it will open your app and pass it that value.
This is not my code, just something I found on the web when searching the same question. Just change all "foo" in the text below to the protocol name you want and change the path to your exe as well.
(put this in to a text file as save as foo.reg on your desktop, then double click it to install the keys)
-----Below this line goes into the .reg file (NOT including this line)------
REGEDIT4
[HKEY_CLASSES_ROOT\foo]
#="URL:foo Protocol"
"URL Protocol"=""
[HKEY_CLASSES_ROOT\foo\shell]
[HKEY_CLASSES_ROOT\foo\shell\open]
[HKEY_CLASSES_ROOT\foo\shell\open\command]
#="\"C:\\Program Files (x86)\\Notepad++\\notepad++.exe\" \"%1\""
Not sure whether this is the right place for my answer, but as I found very few helpful threads and this was one of them, I am posting my solution here.
Problem: I wanted Linux Mint 19.2 Cinnamon to open Evolution when clicking on mailto links in Chromium. Gmail was registered as default handler in chrome://settings/handlers and I could not choose any other handler.
Solution:
Use the xdg-settings in the console
xdg-settings set default-url-scheme-handler mailto org.gnome.Evolution.desktop
Solution was found here https://alt.os.linux.ubuntu.narkive.com/U3Gy7inF/kubuntu-mailto-links-in-chrome-doesn-t-open-evolution and adapted for my case.
I've found the solution by Jun Hsieh and MuffinMan generally works when it comes to clicking links on pages in Chrome or pasting into the URL bar, but it doesn't seem to work in a specific case of passing the string on the command line.
For example, both of the following commands open a blank Chrome window which then does nothing.
"c:\Program Files (x86)\Google\Chrome\Application\chrome.exe" "foo://C:/test.txt"
"c:\Program Files (x86)\Google\Chrome\Application\chrome.exe" --new-window "foo://C:/test.txt"
For comparison, feeding Chrome an http or https URL with either of these commands causes the web page to be opened.
This became apparent because one of our customers reported that clicking links for our product from a PDF being displayed within Adobe Reader fails to invoke our product when Chrome is the default browser. (It works fine with MSIE and Firefox as default, but not when either Chrome or Edge are default.)
I'm guessing that instead of just telling Windows to invoke the URL and letting Windows figure things out, the Adobe product is finding the default browser, which is Chrome in this case, and then passing the URL on the command line.
I'd be interested if anyone knows of Chrome security or other settings which might be relevant here so that Chrome will fully handle a protocol handler, even if it's provided via the command line. I've been looking but so far haven't found anything.
I've been testing this against Chrome 88.0.4324.182.
open
C:\Users\<Username>\AppData\Local\Google\Chrome\User Data\Default
open Preferences then search for excluded_schemes you will find it in 'protocol_handler' delete this excluded scheme(s) to reset chrome to open url with default application
This question already has answers here:
getting the raw source from Firefox with javascript
(3 answers)
Closed 8 years ago.
I'm not using Selenium to automate testing, but to automate saving AJAX pages that inject content, even if they require prior authentication to access.
I tried
tl;dr: I tried multiple tools for downloading sites with AJAX and gave up because they were hard to work with or simply didn't work. I'm resorting to using Selenium after trying out WebHTTrack (whose GUI wasn't able to start up on my Ubuntu machine + was a headache to provide authentication with in interactive-terminal mode), wget (which didn't download any of the scripts of stylesheets included on my page, see the bottom for what I tried with wget)... and then I finally gave up after a promising post on using a Mozilla XULRunner AJAX scraper called Crowbar simply seg-faulted on me. So...
ended up making my own broken thing in NodeJS and Selenium-WebdriverJS
My NodeJS script uses selenium-webdriver npm module which is "officially supported by the main project" to:
provide login information + do necessary button-clicking & typing for authentication
download all JS and CSS referenced on target page
download target page with original JS/CSS file links change to local file paths
Now when I view my test page locally I see double of many page elements because the target site loads HTML snippets into the page each time it's loaded. I use this to download my target page right now:
var $;
var getTarget = function () {
driver.getPageSource().then(function (source) {
$ = cheerio.load(source.toString());
});
};
var targetHtmlDest = 'test.html';
var writeTarget = function () {
fs.writeFile(targetHtmlDest, $.html());
}
driver.get(targetSite)
.then(authenticate)
.then(getRoot)
.then(downloadResources)
.then(writeRoot);
driver.quit();
The problem is that the page source I get is the already modified page source, instead of the original one. Trying to run alert("x");window.stop(); within driver.executeAsyncScript() and driver.executeScript() does nothing.
Perhaps using Curl to get the page (you can pass authentication in the command) will get you the bare source?
Otherwise you may be able to turn off JavaScript on your test browsers to prevent JS actions from firing.
Here it is described how to check if Firebug is installed by checking if an image of firebug exists: http://webdevwonders.com/detecting-firefox-add-ons/
But it seems to be a bit outdated, cause the images he uses there don't exist anymore in firebug.
the firebug chrome.manifest looks like:
content firebug content/firebug/ contentaccessible=yes
...
but in the whole addon I only find one png now, and that is placed in the rootfolder of the addon. But some other content is accessible, for example: chrome://firebug/content/trace.js
Ho
So, in gerneral:
How do I make an image accessible that resides inside a Firefox SDK Addon?
I program an Addon and I want to make an image ok.png available to all javascripts in Firefox.
I added the image in the data folder and added a chrome.manifest
content response-timeout-24-hours data/
content response-timeout-24-hours data/ contentaccessible=yes
But no way to call it via a URL like
chrome://response-timeout-24-hours/data/ok.png
How do the paths belong together? which is relative to which?
I created a Bug report here.
So if you want to make your add-on detectable you need another approach:
you can use a PageMod to attach a content script that would wait for a
message from your web-app and "respond" by sending another message
back to your app. you would know that if you don't receive the
response, your addon is not installed. check out the documentation for
more details:
https://developer.mozilla.org/en-US/Add-ons/SDK/High-Level_APIs/page-mod
I used this to make my add-on detectable.
On my production website, I have compiled Javascript.
<script src="/js/mycode.min.js"></script>
It would be very convient for debugging if I could make my browser replace that with
<script src="http://localhost/js/mycode1.js"></script>
<script src="http://localhost/js/mycode2.js"></script>
...
I know I could manipulate the DOM using something like Greasemonkey userscripts, but I couldn't come up with a solution which would prevent the execution of "mycode.min.js".
Any ideas?
The way I do it:
Download and install Fiddler if you are on windows.
Enable it to catch http traffic [IE/Chrome does it by default, Firefox - enable it through the add on it installs]
Load up the page in question.
Find the file you want to replace in the http traffic list on the left and click on it.
On the right there is an AutoResponder tab. click on it.
Click on the checkbox to "enable automatic responses"
Click Add.. button
The 2nd dropdown on right, choose the option that says "find a file"
Locate the file in the dialog and click save
Repeat steps 4-9 until you replace all the files you want to replace
Refresh the browser window and your new js files are running
Instead of replacing the js file, you can replace the html file and change the js links on the page.
You can install Charles if you are on a mac/linux. (not free, has trial) Steps are similar, but not the same.
If you are using Google Closure to compress files, you can install their plug-in to do the source mapping.
What about using a subdomain like http://static.example.comfor static files (e.g. .js files), and changing the hostfile?
<script type="text/javascript" src="http://static.example.com/js/mycode.min.js"></script>
Add the following line to the hostfile (/etc/hosts for Linux, C:\WINDOWS\System32\drivers\etc\host):
static.example.com 127.0.0.1
Of course you've to run a server with the files from http://static.example.com/ on 127.0.0.1.
Another solution is using a (local) proxy server like Privoxy for redirecting http://example.com/js/ to http://localhost/js/.
To add a NEW file you can use something like one of the other post:
document.body.appendChild(document.createElement("script").src = "http://example.com/addThisJSFile.js");
This tampermonkey script can replace any JS file on a webpage with your custom one from a domain:
// ==UserScript==
// #name ReplaceJS
// #namespace http://example.com/
// #version 1.0.0
// #description Replace javascript files on any webpage!
// #author Mr.Sonic Master
// #match *
// #run-at document-start
// ==/UserScript==
var newJSFile = "http://example.com/newJSFile.js"; //The JS file to load in replacment od old JS file
var oldJSFile = "oldJSFile.replaceThis.js"; //The old JS file as it is named in inspect element (make sure its spelled EXACTLY the same)
var pattern = new RegExp(oldJSFile, "i"); //Create the RegExp pattern with the /i switch to make it case-insensitive
function injectScript(originalPage) { //Function injectScript replaces the file
console.log('Replace stage 2: Replace text matching', oldJSFile, 'with', newJSFile);
var moddedPage = originalPage.replace(pattern, newJSFile); //Modify the HTML code that we got, replacing the old JS file with the new one
document.open();
console.log('Replace stage 3: Write new HTML to page...');
document.write(moddedPage); //Write to the page the new HTML code
document.close();
}
setTimeout(function() { //Wait a bit for the page's HTML to load...
console.log('Replace stage 1: target HTML');
injectScript(document.documentElement.outerHTML); //Run function injectScript with the page's HTML as oldPage in the function
}, 1111);
Without using any web proxy below chrome feature can be used to apply local overrides for js and css files
https://developer.chrome.com/blog/new-in-devtools-65/#overrides
Assuming your scripts are simply the raw version of the production file, you can just crack open your favorite debugger or JS console and import your scripts:
document.body.appendChild(document.createElement("script")).src =
"http://localhost/js/mycode1.js";
Doing so will overwrite the originally defined functions and variables. You'll have to manually re-run window.onload. If you have script that runs immediately or on load that changes much on the page, you may have some work to do to get it back to the original state.
Good luck!
Though the epascarello's solution works, there is a quicker solution for the minified files debugging. Consider using JavaScript source maps. Modern Firefox and Chrome supports them.
The idea of source map is to say browser where to find the unminified version. When you start the debugging in your browser developer tools - browser loads unminified version of the script and shows you the easy-to-read JavaScript (or whatever code you compiled to JavaScript) code in the debugger.
Add something to your URL to distinguish between your dev and prod context ;
example :
http://url_of_prod.com
http://url_of_dev.com?debug=true
and then, use some javascript to check if the GET variable debug is ON or NOT or check the URL with
if (window.location.host.indexOf(‘url_of_dev’) > -1) ...
THEN USE a load function to load or not your file, as in this example :
http://www.softpeople.fr/replaceswitch-dev-local-production-website-javascript-during-debug/