Replicate chrome://offline-internals/ functionality - chrome.send is not a function - javascript

I am trying to build a chrome://offline-internals/ functionality. The chrome://offline-internals/ shows among many things, the pages which are stored for offline viewing, and this feature are only available in mobile chrome browser.
The page at chrome://offline-internals/ basically has a HTML page which I found using view-source:chrome://offline-internals/. I the HTML a javascript is referenced (offline_internals.js), which in turn has nested javascript referenced. I downloaded all referenced javascript in my local folder since chrome doesn't allow access to chrome://resources/js for referencing js pages.
After downloading, I tried to open HTML page and I got an error as below
cr.m.js:107 Uncaught TypeError: chrome.send is not a function
at sendWithPromise (cr.m.js:107)
at OfflineInternalsBrowserProxyImpl.getStoredPages (offline_internals_browser_proxy.js:30)
at refreshAll (offline_internals.js:64)
at HTMLDocument.initialize (offline_internals.js:248)
This basically comes in a file called cr.m.js in the below function
export function sendWithPromise(methodName, var_args) {
const args = Array.prototype.slice.call(arguments, 1);
const promiseResolver = new PromiseResolver();
const id = methodName + '_' + createUid();
chromeSendResolverMap[id] = promiseResolver;
chrome.send(methodName, [id].concat(args)); <-- Error
return promiseResolver.promise;
}
I tried to open chrome://offline-internals/ and set my breakpoint at the above function and that time chrome.send was found to be a function and when I ran my custom HTML page having same source and references, it says chrome.send is not a function.
Probably, the chrome instance given to my script vis-a-vis the one given to chrome://offline-internals/ is a different one.
What can I do to resolve this issue ?
P.S.: This link chrome://offline-internals/ will open in your mobile chrome browser only.
P.S.: All downloaded files are present at this path, in case you wish to see:
https://easyupload.io/9x332s

Related

How to edit an object within a very simple JS file using Node.js

Whilst this question is related to Workbox and Webpack, it does not require any prior knowledge of either library.
Background (skip if not familiar with Workbox)
I am currently utilising the InjectManifest plugin from Workbox 4.3.1 (workbox-webpack-plugin). This version of the library offers an option called manifestTransforms, but unfortunately, the transformations are not applied to assets within the webpack compilation (this is a known issue).
Whilst this has been fixed in Workbox v5+, I am unable to upgrade due to another library in my build process requiring webpack v3 (Dynamic Importing in Laravel Mix)
The reason I mention the above is because unforunately the solution is not to upgrade to workbox v5+.
The Problem
I have an auto-generated file that looks like this:
self.__precacheManifest = (self.__precacheManifest || []).concat([
{
"revision": "68cd3870a6400d76a16c",
"url": "//css/app.css"
},
// etc...
]);
I need to somehow extract the the contents of the object stored within self.__precacheManifest, apply my own transformations, and then save it back to the file.
What I have Tried...
This is as far as I have got:
// As the precached filename is hashed, we need to read the
// directory in order to find the filename. Assuming there
// are no other files called `precache-manifest`, we can assume
// it is the first value in the filtered array. There is no
// need to test if [0] has a value because if it doesn't
// this needs to throw an error
let manifest = fs
.readdirSync(path.normalize(`${__dirname}/dist/js`))
.filter(filename => filename.startsWith('precache-manifest'))[0];
require('./dist/js/' + manifest);
// This does not fire because of thrown error...
console.log(self.__precacheManifest);
This throws the following error:
self is not defined
I understand why it is throwing the error, but I have no idea how I am going to get around this because I need to somehow read the contents of the file in order to extract the object. Can anyone advise me here?
Bear in mind that once I have applied the transformations to the object, I then need to save the updated object to the file...
Since self refers to window and window does not exist in node.js a way around is needed.
One thing that should work is to define the variable self in Node's global scope and let the require statement populate the content of the variable, like this:
global['self'] = {};
require('./dist/js/' + manifest);
console.log(self.__precacheManifest);
To save the modified contents back to the file
const newPrecacheManifest = JSON.stringify(updatedArray);
fs.writeFileSync('./dist/js/' + manifest, `self.__precacheManifest = (self.__precacheManifest || []).concat(${newPrecachedManifes});`, 'utf8');

Chrome extension: missing class instances in background page

I'm trying to build a "complex" extension for google chrome, in fact the extension is actually build (JSLoader), and the structure used in the extension worked a few months ago. Now I want to update it but none of my pop-up's are showing due to some strange behavior of chrome.runtime.getBackgroundPage(). I have several "modules" declared in manifest.json as follows:
"background": {
"scripts": [
"dependencies/dep1.js",
" ... ",
"bg/module1.js",
"bg/module2.js",
" ... "
"bg/background.js"
]
},
Then in my background page I do instantiate each of the modules the following way:
this.module1 = new Module1(this);
this.module2 = new Module2(this);
Where module1 and module2 defines the functions (or old style classes) Module1 and Module2 respectively. Then from my pop-up's, concretelly from page action and options page of the extension I'm doing:
chrome.runtime.getBackgroundPage(page => {
...
/* this fails and says that module1 is not defined */
page.module1.callSomeFunctionOnModule1()
...
})
As said above this used to work some months ago, and I don't know why my instances are not defined anymore, actually none of the functions defined in the background page are available. Is there any reason I can not do this anymore? What will be the way to call functions on the background from the page actions and option page?
I don't know what to try ... my functions are not defined in the foreground anymore.. I tried to call chrome.extension.getBackgroundPage instead of chrome.runtime.getBackgroundPage with no luck.
You can find the complete extension at https://github.com/szz-dvl/JSLoader/tree/chrome
I do expect to be able to access my background functions from my foreground pages (both page action and options page.)
Thanks in advance!

Moving created files with JXA

I'm new to JXA scripting, but I'm attempting to troubleshoot some older scripts currently in place here at work. They loop through an InDesign document and create several PDFs based on it. Previously, they would be stored in a folder called "~/PDFExports". However, this doesn't work with 10.10.
If I change the code to just place the PDFs in "~/", it works fine. From there, I'd like to move the files to "~/PDFExports", but I can't seem to find an answer on how to do that. I've seen things about making calls to ObjC, or to call Application('Finder'), but neither work - they both return undefined.
Am I just missing something basic here, or is it really this hard to simply move a file with JXA?
EDIT: Some syntax for how I'm creating the folder in question and how I'm attempting to work with Finder.
//This is called in the Main function of the script, on first run.
var exportFolder = new Folder(exportPath);
if(!exportFolder.exists) {
exportFolder.create();
}
//This is called right after the PDF is created. file is a reference to the
actual PDF file, and destination is a file path string.
function MoveFile(file,destination){
var Finder = Application("Finder");
Application('Finder').move(sourceFile, { to: destinationFolder });
alert("File moved");
}
Adobe apps have long included their own embedded JS interpreter, JS API, and .jsx filename extension. It has nothing to do with JXA, and is not compatible with it.
InDesign's JSX documentation:
http://www.adobe.com/devnet/indesign/documentation.html#idscripting
(BTW, I'd also strongly advise against using JXA for Adobe app automation as it has a lot of missing/broken features and application compatibility problems, and really isn't fit for production work.)
Here's the link to Adobe's InDesign Scripting forum, which is the best place to get help with JSX:
https://forums.adobe.com/community/indesign/indesign_scripting
You could use Cocoa to create the folder
var exportFolder = $.NSHomeDirectory().stringByAppendingPathComponent("PDFExports")
var fileManager = $.NSFileManager.defaultManager
var folderExists = fileManager.fileExistsAtPath(exportFolder)
if (!folderExists) {
fileManager.createDirectoryAtPathWithIntermediateDirectoriesAttributesError(exportFolder, false, $(), $())
}
and to move a file
var success = fileManager.moveItemAtPathToPathError(sourceFile, destinationLocation, $());
if (success) alert("File moved");
Consider that destinationLocation must be the full path including the file name
and both sourceFile and destinationLocation must be NSString objects like exportFolder
Could it be that the folder is missing ? Could be your reference to the folder object not valid ? Any syntax to show ?
I will share some of what I learned about JXA move and duplicate methods. I am not a professional programmer just an attorney that is passionate about automation. My comments come from much trial and error, reading whatever I could find online, and A LOT of struggle. The move method does not work well with Finder. Use the System Events move method instead. The duplicate method in Finder works just fine. The duplicate method does not work well in system events. This is a modified snippet from a script I wrote showing move() using System Events.
(() => {
const strPathTargetFile = '/Users/bretfarve/Documents/MyFolderA/myFile.txt';
const strPathFolder = '/Users/bretfarve/Documents/MyFolderB/';
/* System Events Objects */
const SysEvents = Application('System Events');
const objPathFolder = SysEvents.aliases[strPathFolder];
SysEvents.move(SysEvents.aliases.byName(strPathTargetFile), {to: objPathFolder});
})();

Firefox: How do I get an nsIMessageManager instance from a JS Module under Electrolysis (e10s)?

I'm trying to port my Firefox extension to work under Electrolysis / e10s / multi-process mode. I've got a feature that requires registration through nsIComponentRegistrar so it's in a JSM which gets loaded only once (per process). I'm running in the child scope, so I don't have access to things like files, but my feature requires that. So I want to sendSyncMessage() to the parent process to fetch that detail (just the path to a file in this case).
The docs even mention doing something like this explicitly. But in the JSM I don't have a message manager in scope to call sendSyncMessage() on. How do I get a handle to (the right?) one? When I get called I don't have anything relating to the content document/window in scope.
Update, for clarity:
var c = Cc['#mozilla.org/childprocessmessagemanager;1'];
var s = c.getService(Ci.nsISyncMessageSender);
var response = s.sendSyncMessage('id', {'data': 'x'});
dump('response len?? ' + response.length + '\n');
This code produces 0 responses, even running directly in the frame script (not in the JSM which the frame script loads). If I just use the globally available sendSyncMessage() in the frame script then it gets the 1 response I expect.
"#mozilla.org/childprocessmessagemanager;1" is the way to go. Use that in child process JSMs.
However, as MDN puts it:
In addition to Message Managers centered around window and tab objects
there also is a separate hierachy focusing on process boundaries.
Therefore, you cannot use the regular frame script messengers, but have to use "#mozilla.org/parentprocessmessagemanager;1" in the parent (main) process.
child.jsm
let cpmm = Cc["#mozilla.org/childprocessmessagemanager;1"].
getService(Ci.nsISyncMessageSender);
cpmm.sendSyncMessage("addon:present?!")[0] === "yup"
parent.jsm
let ppmm = Cc["#mozilla.org/parentprocessmessagemanager;1"].
getService(Ci.nsIMessageListenerManager);
ppmm.addMessageListener("addon:present?", m => "yup");
Core code uses this scheme in various places, e.g. Network:SampleRate
This may work, no promises.
Try loading:
Cc["#mozilla.org/globalmessagemanager;1"].getService(Ci.nsIMessageListenerManager);
If that doesn't work then try using:
Cc['#mozilla.org/childprocessmessagemanager;1'].getService(Ci.nsISyncMessageSender);
Or vice-versa

error with google swiffy calling runtime.js multiple times in the same page

I have converted multiple swf files using google swiffy v5.2 and will have my new animations displayed on many different pages, most of which I do not have control of or access to. In order for the animation to work it needs the swiffy's runtime.js file, which might look something like this on the page:
<script src="https://www.gstatic.com/swiffy/v5.2/runtime.js"></script>
The problem arises when I either have multiple instances of the animation on the same page or a client has this runtime.js file included on their own. When checking the javascript console I get this error:
Uncaught TypeError: Cannot redefine property: __swiffy_override - runtime.js:186
If i was only worried about the conflict with myself I could possibly keep track of a variable or check if the script src existed already, however I do not have this luxury when a client's page may have renamed or changed the source to this file.
Is there a way to prevent the swiffy runtime.js from redefining this property when there are multiple instances of the same javascript file being included on the page?
I imagine you are seeing this problem happen when using AS3 swfs, which have Document classes applied to them. For example, say you have animationAS3.swf, which uses AnimationBaseClass.as. When it is "compiled" by Google Swiffy service the resultant JSON data will contain
{"internedStrings":["...", "AnimationBaseClass", "..."] ....}
The Google Swiffy runtime applies JavaScript's defineProperties() or perhaps defineProperty() to seal an "AnimationBaseClass" object it creates. So, when another instance of the data is loaded the Swiffy runtime attempts to do the same thing again, and the JavaScript interpreter says "Hey, I've already defined that object, I won't redefine it."
The solution I've found, which I believe is inefficient, is to rename the class before giving the data to the Swiffy runtime. Like this:
var classEnumerator = 0;
$.getJSON('animationAS3.json', function(data) {
// Due to "TypeError: Cannot redefine property: AnimationBaseClass",
// we need to enumerate the name of the class. I have no idea about
// the impact on resource usage when doing this.
var classNameIndex;
var i = data.internedStrings.length;
while(i--) {
if (data.internedStrings[i].indexOf("AnimationBaseClass") > -1) {
classNameIndex = i;
}
}
data.internedStrings[classNameIndex] = "AnimationBaseClass_" + (classEnumerator++));
}

Categories

Resources