0

I have a plan to use chrome extensions to do something when a specific js function of web server is called. Here is script of "a.js" from web server. I want to do something when "$.progressHide" function is called. How can I do with background.js or content.js?

[a.js]

(function($) {
var className = 'progressPopup';

$.progressShow = function () {
    $(document).progressShow();
};
$.progressHide = function () {
    $(document).progressHide();
};

$.fn.progressShow = function () {
    var progressClass = this.attr('data-progressClass');
    if(progressClass) {
        $('.' + progressClass).show();
        return;
    }

    $('body').append(
        $('<div></div>').addClass(className).css({
            position: 'fixed',
            zIndex: 9999999999998,
            left: 0, top: 0, right: 0, bottom: 0,
            backgroundColor: '#000',
            opacity: 0.3,
            filter: "alpha(opacity=30)"
        })
    );

    $('body').append(
        $('<img src="/content/assets/images/common/img_loading.gif"/>' ).addClass(className).css({
            position: 'fixed',
            zIndex: 9999999999999,
            left: '50%',
            top: '50%',
            marginLeft: '-200px',
            marginTop: '-90px'
        })
    );

    return this;
};
$.fn.progressHide = function () {
    var progressClass = this.attr('data-progressClass');
    if(progressClass) {
        $('.' + progressClass).hide();
        return;
    }

    $('.' + className).remove();
    return this;
};}(jQuery));
Jade Lee
  • 69
  • 2
  • 8
  • What type of web server are you using? Node, I'm guessing? Look into server sent events, sockets, or long-polling... :) – Todd Sep 15 '19 at 15:53
  • @Todd I do not know exactly, I can see only js and html scripts from chrome developer tools. How can I get server sent events using chrome extensions? – Jade Lee Sep 15 '19 at 16:03
  • The OP incorrectly used the term. There's no server here, it's just a normal web page. – wOxxOm Sep 15 '19 at 16:04

1 Answers1

0
  1. To access a web page you need a content script.

    Depending on your use case you'll use either a) an automatically executed script by declaring it in manifest.json or b) an on-demand injection. In the latter case you'll need to check if the content script was already executed so you don't run it twice (example).

  2. To access a JavaScript function/variable in the web page you need a page script (the code in a standard DOM script element) because content scripts run in an "isolated world" so they can't access those functions/objects directly.

content.js

var eventId = chrome.runtime.id + Math.random();
window.addEventListener(eventId, () => {
  console.log('progressHide was invoked');
});
runInPage(inPageInterceptor, eventId);

function runInPage(fn, ...params) { 
  const el = document.createElement('script');
  el.textContent = `(${fn})(${JSON.stringify(params).slice(1, -1)})`;
  document.documentElement.appendChild(el);
  el.remove();
}

Simple case when you expect the function to be already defined.
content.js continuation A:

function inPageInterceptor(eventId) {
  const realProgressHide = $.fn.progressHide;
  $.fn.progressHide = function () {
    window.dispatchEvent(new Event(eventId));
    return realProgressHide.apply(this, arguments);
  };
}

Or you want to wait for the function to become defined if it's not.
content.js continuation B:

function inPageInterceptor(eventId) {
  waitFor(window, '$', $ => {
    waitFor($.fn, 'progressHide', realProgressHide => {
      $.fn.progressHide = function () {
        window.dispatchEvent(new Event(eventId));
        return realProgressHide.apply(this, arguments);
      };
    });
  });
  function waitFor(obj, name, cb) {
    if (obj[name]) {
      cb(obj[name]);
    } else {
      Object.defineProperty(obj, name, {
        configurable: true,
        enumerable: true,
        set(value) {
          Object.defineProperty(obj, name, {
            value,
            configurable: true,
            enumerable: true,
            writable: true,
          });
          cb(value);
        },
      });
    }
  }
}

This a demo of the approach, not tested on a live page, so use it as a reference, not the final truth.

Community
  • 1
  • 1
wOxxOm
  • 65,848
  • 11
  • 132
  • 136