React.js micro frontend subscribe to main app network requests - reactjs

I have a React.js app (chrome extension micro frontend) that is injected into another frontend app.
I have no permissions to alter the main app code.
Is it possible to subscribe and see the HTTP requests made by the main app?
Thanks.

Here's how you can see what HTTP requests does the main app do:
const windowFetch = window.fetch
window.fetch = function (reqestUrl) {
console.log('reqestUrl: ' + reqestUrl)
console.log('arguments: ' + JSON.stringify(arguments)) // method, headers, body
return windowFetch.apply(this, arguments)
}
Update:
It works when the code is simply pasted into the page console, but unfortunately for the content script, "The window object the content script sees is not the same window object that the page sees."
Solution credit:
https://gist.github.com/devjin0617/3e8d72d94c1b9e69690717a219644c7a
Inspired by:
Access window variable from Content Script
Aditional setup:
manifest.json (V2)
{
"content_scripts": [
{
"matches": ["http://*/*", "https://*/*"],
"js": ["inject.js"],
"all_frames": true
}
],
"web_accessible_resources": [
"content.js"
]
}
content.js
console.log(window);
inject.js
/**
* injectScript - Inject internal script to available access to the `window`
*
* #param {type} file_path Local path of the internal script.
* #param {type} tag The tag as string, where the script will be append (default: 'body').
* #see {#link http://stackoverflow.com/questions/20499994/access-window-variable-from-content-script}
*/
function injectScript(file_path, tag) {
var node = document.getElementsByTagName(tag)[0];
var script = document.createElement('script');
script.setAttribute('type', 'text/javascript');
script.setAttribute('src', file_path);
node.appendChild(script);
}
injectScript(chrome.extension.getURL('content.js'), 'body');
For Manifest V3:
Changes in Manifest:
"web_accessible_resources": [
{
"resources": ["content.js"],
"matches": ["https://*.anywebsite.com/*"]
}
]
Changes in Inject.js
injectScript(chrome.runtime.getURL('content.js'), 'body');

Related

Vite serving shader file with wrong (none) MIME type

I'm developing a BabylonJS application. BabylonJS PostProcess class appends .fragment.fx to a given file name and requests that from the server. When my local Vite (version 4.0.4) dev server serves this file the content-type header is empty. This causes Firefox to intepret it as type xml and fail. Chrome fails through a different, but I think related, mechanism.
How do you configure Vite to serve the *.fragment.fx static files as text/plain? I assume I need to disable the default middleware and write some custom code instead, like this: https://vitejs.dev/config/server-options.html#server-middlewaremode but I wanted to first check there wasn't something else going on / a simpler way to configure / fix this.
The vite dev server is started using vite --host --port 3000 --force and the config in vite.config.js is:
import { defineConfig } from 'vite';
export default defineConfig(({ command, mode }) => {
// if (command === 'serve') {
// return {
// // dev specific config
// }
// } else {
// // command === 'build'
// return {
// // build specific config
// }
// }
return {
resolve: {
alias: {
"babylonjs": mode === "development" ? "babylonjs/babylon.max" : "babylonjs",
}
},
base: "",
// assetsInclude: ['**/*.fx'],
};
});
* edit 1 *
I have seen there's a parameter ?raw that can be added to the URL however I don't control how BabylonJS forms the URL so I can't see how to make this work in this situation.
I followed these instructions and set up a dev server using express. I added this block of code above the call to app.use(vite.middlewares):
app.use("**/*.*.fx", async (req, res, next) => {
const url = req.originalUrl
const file_path = path.resolve(__dirname, "." + url)
const file = fs.readFileSync(file_path, "utf-8")
res.status(200).set({ "Content-Type": "text/plain" }).end(file)
})
I now start the dev server using the following script line in the package.json of "dev": "node server",
I could not find a way to solve this by configuring the default vite dev server.

Not able to access global window object from content script in extension [duplicate]

This question already has answers here:
Access variables and functions defined in page context using a content script
(6 answers)
Access global js variables from js injected by a chrome extension
(1 answer)
Closed last month.
I created an extension that append button on each tweet on twitter. Upon clicking that button I should perform a function window.phantom.solana.connect().
When I enter window.phantom.solana.connect() directly in my console it works, but the problem is when I try to trigger this function from content script it the window object has different context than the one I am using inside of my browser and it doesn't contain phantom.solana... properties
here is my manifest.json
{
"manifest_version": 3,
"name": "react-boilerplate",
"description": "react-boilerplate for chrome extension",
"version": "1.0.0",
"action": {
"default_title": "React Boilerplate"
},
"permissions": \["tabs", "bookmarks", "storage", "identity", "scripting"\],
"icons": {
"16": "icon.png",
"48": "icon.png",
"128": "icon.png"
},
"background": {
"service_worker": "background.js"
},
"content_scripts": \[
{
"matches": \["https://*.twitter.com/*"\],
"js": \["contentScript.js"\]
}
\],
"web_accessible_resources": \[
{
"resources": \["web_accessible_resources.js"\],
"matches": \["\<all_urls\>"\],
"extension_ids": \["bfnaelmomeimhlpmgjnjophhpkkoljpa"\]
}
\]
}
and my content script
import React from "react";
import { createRoot } from "react-dom/client";
import "../assets/tailwind.css";
import ContentScript from "./contentScript";
function init() {
const appContainer = document.createElement("div");
if (!appContainer) {
throw new Error("Cannot find app container");
}
const root = createRoot(appContainer);
const articleList = window.document.querySelectorAll("article");
root.render(\<ContentScript /\>);
for (const element of articleList) {
var btn = document.createElement("button");
btn.appendChild(document.createTextNode("Bonk tweet"));
btn.style.color = "white";
btn.addEventListener("click", function () {
// this function should catch the window object
chrome.runtime.sendMessage(
{ greetings: "Bonk tweet" },
function (response) {
console.log(response.farewell);
// don't have access to window.phantom.solana
console.log(this);
console.log(window);
}
);
});
element.appendChild(btn);
}
}
setTimeout(init, 4000);
I tried to access it on a various ways through events, web_accessible_resources... Still no luck. Does anyone knows how can I access the same window object inside my extension
Content scripts don't have access the host page's window object. But they do have access to the host page's DOM. So you can work around this limitation by adding a script tag to the host page's DOM so that it executes in the host page's context and has access to the host window object.
const scriptTag = document.createElement('script');
scriptTag.setAttribute('type','application/javascript');
scriptTag.innerText = `window.phantom.solana.connect()`;
document.head.appendChild(scriptTag);
Additionally, you could set up a message handler in the script tag above, and send a message from your content script to execute that handler.
This workaround will not work if the page has a content security policy though.

webview_flutter javascript channel can't communicate in release mode

I am using webview_flutter with version 3.0.0 in my app. I have heavy usage of two-way communication between flutter and javascript. Everything works on debug mode nicely. But, after I build the APK started to get some errors in the javascript channel. I tried with flutter run --release and got the same error.
In my web application (ReactJs), I am using channels in this way:
index.html
<div id="root">
<script>
function sendToFlutter(message) {
if (flutterChannel) {
flutterChannel.postMessage(message);
}
}
</script>
</div>
calling is from React component like this:
window.sendToFlutter("hello-world");
My Webview setup from Flutter end:
Completer<WebViewController> webViewCompleter = Completer<WebViewController>();
WebView(
debuggingEnabled: false,
initialUrl: "https://example.com",
javascriptMode: JavascriptMode.unrestricted,
onWebViewCreated: (WebViewController webViewController) {
webViewCompleter.complete(webViewController);
},
javascriptChannels: <JavascriptChannel>{
JavascriptChannel(
name: "flutterChannel",
onMessageReceived: (JavascriptMessage message) {
if (message.message == "hello-world") {
// Do something
}
})
},
navigationDelegate: (NavigationRequest request) {
if (request.url.startsWith('https://www.youtube.com/')) {
return NavigationDecision.prevent;
}
return NavigationDecision.navigate;
},
gestureNavigationEnabled: true,
zoomEnabled: false,
userAgent: Platform.isAndroid ? kAndroidUserAgent : kIosUserAgent,
);
When I call the channel from ReactJs, then I am getting this error:
TypeError: flutterChannel.postMessage is not a function
According to alexbatalov's research in https://github.com/flutter/flutter/issues/92548, the current workaround is to do the following:
Create android/app/proguard-rules.pro. At minimum you need to have a
rule for JavascriptInterface, but I recommend to copy entire
proguard-android.txt, given the fact that you don’t have these rules.
# Preserve annotated Javascript interface methods.
-keepclassmembers class * {
#android.webkit.JavascriptInterface <methods>;
}

React/Next.js recommended way to set constants such as backend API URLs

I am looking through next.js documentation and trying to understand what the suggested approach is for setting URLs that change in different environments. Mostly, I want to ensure that I'm pointing backend URLs correctly in development versus production.
I suppose you can create a constants configuration file, but is there a supported, best practice for this?
Open next.config.js and add publicRuntimeConfig config with your constants:
module.exports = {
publicRuntimeConfig: {
// Will be available on both server and client
yourKey: 'your-value'
},
}
you can call it from another .js file like this
import getConfig from 'next/config'
const { publicRuntimeConfig } = getConfig()
console.log(publicRuntimeConfig.yourKey)
or even call it from view like this
${publicRuntimeConfig.yourKey}
You can configure your next app using next-runtime-dotenv, it allows you to specify serverOnly / clientOnly values using next's runtime config.
Then in some component
import getConfig from 'next/config'
const {
publicRuntimeConfig: {MY_API_URL}, // Available both client and server side
serverRuntimeConfig: {GITHUB_TOKEN} // Only available server side
} = getConfig()
function HomePage() {
// Will display the variable on the server’s console
// Will display undefined into the browser’s console
console.log(GITHUB_TOKEN)
return (
<div>
My API URL is {MY_API_URL}
</div>
)
}
export default HomePage
If you don't need this separation, you can use dotenv lib to load your .env file, and configure Next's env property with it.
// next.config.js
require('dotenv').config()
module.exports = {
env: {
// Reference a variable that was defined in the .env file and make it available at Build Time
TEST_VAR: process.env.TEST_VAR,
},
}
Check this with-dotenv example.

Django 1.6.5 - Unable to load initial data from fixtures

I tried to load initial-data as suggested in djangoproject. But I couldn't able to load object on my database. But when I tried to load data, it always says
> python manage.py loaddata ./fixtures/initial_data.json
Installed 0 object(s) from 0 fixture(s)
But I have data on the initial_data.json [/test-project/tableTest/tableTest/fixtures/initial_data.json]
[
{
"model":"tableTest.person",
"pk":1,
"fields": {
"name":"Kevin"
}
},
{
"model":"tableTest.person",
"pk":2,
"fields": {
"name":"Harry"
}
},
{
"model":"tableTest.person",
"pk":3,
"fields": {
"name":"Piter"
}
}
]
#models.py
from django.db import models
class Person(models.Model):
name = models.CharField(max_length=100, verbose_name="full name")
I also tried ./manage.py loaddata pwd/tableTest/fixtures/initial_data.json but could not succeed. Please help me to suggest what I have missed.
This issue arises because I write definition for model at project directory instead of app directory and Table I defined on model was not created on running syncdb. Later I create a app and move fixtures, models.py,views.py to app directory, rewrite urls.py. Then the data was loaded successfully.

Resources