Inject javascript before the page is loaded

3,311 views
Skip to first unread message

ik...@ludei.com

unread,
May 23, 2016, 4:52:06 AM5/23/16
to android-webview-dev
Hello,

I am modifying the default Chromium webview test and I am trying to inject some javascript code before a page is loaded. I have tried to override some methods from the AwContentsClient and execute evaluateJavaScript. 

        AwContentsClient awContentsClient = new NullContentsClient() {
            private View mCustomView;

            @Override
            public void onPageStarted(String url) {

                System.out.println("VRWebGL: onPageStarted url = " + url);
                 mAwTestContainerView.getAwContents().evaluateJavaScript(jsCode, null);
 
            }

            @Override
            public void onLoadResource(String url) {
                System.out.println("VRWebGL: onLoadResource url = " + url);
                if (url.equals(AwShellActivity.this.url))
                {
                    mAwTestContainerView.getAwContents().evaluateJavaScript(jsCode, null);
                }
            }

...

This code works and I am able to see a console.log command in the jsCode being executed. But is I define a global variable in window in the jsCode (just for testing purposes) when the page is loaded, the injected code is wiped out. Is there a way inject code right before the page is loaded but the code stays within the page? Any other method in any other interface or something?

Just for reference purposes, the Crosswalk project (based on chromium) has a similar resource client interface to know when a resource is being loaded (the page) and it's evaluateJavaScript works.

Any help would be much appreciated.

Thank you in advance.

Regards,
Iker

Hui Shu

unread,
May 24, 2016, 11:01:52 PM5/24/16
to ik...@ludei.com, android-webview-dev
There was a discussion about this: (Googler only access) crbug.com/593984
The gist is, the window object (which is the holder of all javascript global states) will be wiped out after the page load.

If you want to persist some states, I think "addJavascriptInterface" would be better because the javascript bridge persists between page loads.

--
You received this message because you are subscribed to the Google Groups "android-webview-dev" group.
To unsubscribe from this group and stop receiving emails from it, send an email to android-webview...@chromium.org.
To post to this group, send email to android-w...@chromium.org.
To view this discussion on the web visit https://groups.google.com/a/chromium.org/d/msgid/android-webview-dev/54b69da4-26ba-4004-b7ea-c8038dcede44%40chromium.org.

Iker Jamardo

unread,
May 25, 2016, 2:12:00 AM5/25/16
to Hui Shu, android-webview-dev
Hello Hui and thanks for the reply,

I could not access the discussion as I am not a Googler. Your advice is interesting but I wonder how I could inject code from a JavaScript interface object. As far as I understand, the JS code needs to call the Java object that is added. I am looking for a way to inject code automatically at the beginning of any page. Maybe there is a way using the JavaScriptInterface of a Java object, but I do not see how.

Thank you very much!
--
Iker Jamardo
CTO @ Ludei
http://ludei.com
156 2nd Street
San Francisco
CA, 94105

Iker Jamardo

unread,
May 25, 2016, 2:15:53 AM5/25/16
to Hui Shu, android-webview-dev
Just to provide more information/perspective, imagine I want to inject some JS code such as the following in every page that is loaded using my modified chromium webview:

(function() {
  var oldAlert = window.alert;
  window.alert = function() {
    ... // My new implementation of alert.
  };
})();

Regards,
Iker

Torne (Richard Coles)

unread,
May 26, 2016, 8:23:49 AM5/26/16
to Iker Jamardo, Hui Shu, android-webview-dev
There isn't a particularly good way to inject JS into every page with WebView, especially if the page content is third-party and can't be modified to cooperate with your application.

However, for the specific case of intercepting alerts, there's no need to do this in JS, there's already a callback in Java for this that you can do anything you want with..

Iker Jamardo

unread,
May 26, 2016, 1:50:27 PM5/26/16
to Torne (Richard Coles), Hui Shu, android-webview-dev
Yeah, I know. It wasn't the best example I suppose. I don't want to intercept alerts, it was just a simple example I came up with.

So, do you think there is no other workaround for arbitrary JS injection into any webpage?

Regards,
Iker

Torne (Richard Coles)

unread,
May 27, 2016, 6:23:59 AM5/27/16
to Iker Jamardo, Hui Shu, android-webview-dev
You can inject JS into any webpage, but I don't think there's any way to guarantee it happens before that page's JS starts running, no.

Why do you want to do this? What's the actual use case? Maybe we can suggest a different way to achieve what you want?

Iker Jamardo

unread,
Jun 4, 2016, 1:15:39 PM6/4/16
to Torne (Richard Coles), Hui Shu, android-webview-dev
What I want to do is to change the getContext funtion prototype from the HTMLCanvasElement. Here is a simple code to ilustrate it (not my production code though):

(function() {
  var originalGetContext = HTMLCanvasElement.prototype.getContext;
  HTMLCanvasElement.prototype.getContext = function() {
    ...
  };
})();

I need this code to be injected once the page is loaded so every call to getContext is captured.

Thank you so much for the help!

Regards,
Iker

Torne (Richard Coles)

unread,
Jun 6, 2016, 6:26:22 AM6/6/16
to Iker Jamardo, Hui Shu, android-webview-dev
I don't think we have any way to guarantee this would execute at the right time.

Hui Shu

unread,
Jun 6, 2016, 2:31:24 PM6/6/16
to Torne (Richard Coles), Iker Jamardo, android-webview-dev

you can rebuild chromium webview by putting logs in the blink code to log any calls HTMLCanvasElement.prototype.getContext. 

Iker Jamardo

unread,
Jun 9, 2016, 1:32:15 AM6/9/16
to Hui Shu, Torne (Richard Coles), android-webview-dev
Thank you for your help. 

Is there anyway to access the "eval" call from within the C++ code of Chromium? I have been adding new functionalities like new types using IDL and C++ files so I am familiar with it, but I was wondering if one solution could be to inject some JS code from the C++ code at a certain point when I know for sure that the page is being loaded. Where exactly this is done in C++ I do not know.

Thank you once again for all the great suggestions.

Regards.
Iker.

Chen Zhixiang

unread,
Dec 16, 2016, 8:51:23 AM12/16/16
to android-webview-dev, hu...@google.com, to...@chromium.org, ik...@ludei.com
Hi
You can use Opera's sitepatcher extension which injects js code when render side parser first sees <html> start tag.

The problem i've found is: can access Element.prototype.removeChild and store it to window.__removeChild, but cannot do the same to `querySelector(All)`

Cannot figure out why.
To unsubscribe from this group and stop receiving emails from it, send an email to android-webview-dev+unsub...@chromium.org.
To post to this group, send email to android-webview-dev@chromium.org.
--
Iker Jamardo
CTO @ Ludei
http://ludei.com
156 2nd Street
San Francisco
CA, 94105



--
Iker Jamardo
CTO @ Ludei
http://ludei.com
156 2nd Street
San Francisco
CA, 94105

--
You received this message because you are subscribed to the Google Groups "android-webview-dev" group.
To unsubscribe from this group and stop receiving emails from it, send an email to android-webview-dev+unsub...@chromium.org.
To post to this group, send email to android-webview-dev@chromium.org.

Alex Meng

unread,
Dec 18, 2016, 4:14:38 AM12/18/16
to android-webview-dev, ik...@ludei.com
Now there is no interfaces, alow you to inject javascript in all page . 

you can see addJavascriptInterface, you will see code in GinJavaBridgeDispatcher::DidClearWindowObject().

You can do all that you need in this function.

啁啾

unread,
Aug 27, 2020, 11:15:19 PM8/27/20
to android-webview-dev, imxia...@gmail.com, Iker Jamardo
为什么没有类似于electron的方法:
const createWindow = () => { mainWindow = new BrowserWindow({ frame: false, modal: false, show: false, fullscreen: true, webPreferences: { nodeIntegration: true, preload: path.join(__dirname, 'preload.js') } }); 
Reply all
Reply to author
Forward
0 new messages