Определение, выполняется ли код как расширение Chrome - PullRequest
10 голосов
/ 22 сентября 2011

Я работаю с некоторым кодом, который нужно запустить как страницу, и если он запускается как Chrome Extension , я хочу иметь возможность выполнять дополнительные действия.Я использую:

<script>
if (chrome && chrome.extension) {
    // extension stuff
}
</script>

Это похоже на хорошую возможность обнаружение .Использование строки агента пользователя вызывает у меня проблемы, потому что это не зависит от контекста (веб-страница или расширение).

Вопрос: существуют ли другие, более надежные методы для определения, работает ли фрагмент кода внутри расширения Chrome?

Обновление: Мне интересно, есть ли что-то, что я могу вставить в мой файл manifest.json, который я могу затем прочитать обратно.Обратите внимание, что расширение, над которым я работаю, не предназначено как постоянная вещь, которая выполняется постоянно, это приложение для работы с содержимым, которое выполняется в одном окне или вкладке браузера и не нуждается во взаимодействии с другими окнами или вкладками или чем-то еще.

Ответы [ 7 ]

23 голосов
/ 21 марта 2014

Здесь так много сложных ответов, в то время как вы легко можете определить, используете ли вы расширение Chrome, проверив наличие и незаполненность chrome.runtime.id:

if (window.chrome && chrome.runtime && chrome.runtime.id) {
    // Code running in a Chrome extension (content script, background page, etc.)
}
4 голосов
/ 22 сентября 2011

Прагматически это хороший подход.Теоретически (не уверен, является ли это актуальным или нет, например, может предоставить уязвимости), его можно очень легко подделать.Я полагаю, это зависит от вашего контекста, насколько это уместно.

Вот немного более сильная идея:

if (chrome &&
    chrome.windows &&
    chrome.windows.get &&
    typeof chrome.windows.get === 'function' &&
    chrome.windows.get.toString() === 'function get() { [native code] }')

Идея такая же, как у вас, хотя она немного сильнее, так как AFAIK имеетobject является функцией, и его значение toString() иметь это значение невозможно, так как это недопустимый синтаксис, поэтому даже попытка подделать это значение не сработает, если вы не измените собственный код (который требует совершенно другого уровня хакера).

Не запомните, если проверка таких вещей требует разрешений или нет, но идея ясна, надеюсь.

ОБНОВЛЕНИЕ

Я простоПонял, что идею синтаксиса «нативного кода» можно обмануть, создав псевдоним существующей функции.Например,

var FakeFn = Object.create;
FakeFn.toString(); // "function create() { [native code] }"

Но об этом можно позаботиться, тщательно выбрав, какую функцию мы используем, поскольку имя появляется в строке.get, вероятно, слишком распространено, но если мы возьмем непонятное имя функции (например, captureVisibleTab из chrome.tabs.captureVisibleTab), которое реализовано только в расширениях Chrome, это все еще очень переносимое решение, потому что в отличие от базовой проверки, где код можетбыть обманутым другим локальным пользовательским кодом, заранее известно, что браузеры не реализуют никаких собственных функций с этим именем, поэтому он по-прежнему безопасен во всех браузерах и со всем пользовательским кодом.

ОБНОВЛЕНИЕ

Как указывал @Mathew, эта идея глупа (хотя, по-видимому, только злонамеренно).Я думал, что смогу исправить проблему, сравнивая с Function.prototype.toString, но решил, что даже это можно обмануть, наложив псевдоним на оригинальный метод toString и создав новый, который для определенных функций возвращает ложные строки, а для других возвращает исходную строку.

В заключение, моя идея немного сильнее оригинальной, так как она исключает практически все шансы непреднамеренного столкновения (чуть больше, чем идея ОП), но, безусловно, не защищает от злонамеренной атаки, как я вначаледумал, что это может быть.

2 голосов
/ 25 июля 2017

Мне нужно что-то подобное.

Но мне не нужно было заботиться о сайтах, пытающихся обмануть код.

const SCRIPT_TYPE = (() => {
    if (chrome && chrome.extension && chrome.extension.getBackgroundPage && chrome.extension.getBackgroundPage() === window) {
        return 'BACKGROUND';
    } else if (chrome && chrome.extension && chrome.extension.getBackgroundPage && chrome.extension.getBackgroundPage() !== window) {
        return 'POPUP';
    } else if (!chrome || !chrome.runtime || !chrome.runtime.onMessage) {
        return 'WEB';
    } else {
        return 'CONTENT';
    }
})();

Выше должны обнаружить 4 сценария

  • JavaScript запускается на фоновой странице
  • JavaScript запускается на всплывающей странице / iframe
  • JavaScript запускается в контекстном скрипте
  • JavaScript запускается непосредственно на сайте
2 голосов
/ 03 августа 2012

Я знаю, что это старый, но просто подумал, что предложу альтернативу. Вы можете добавить другой файл javascript к расширению chrome, чтобы он содержал два файла .js. manifest.json будет иметь:

"js": ["additionalscript.js", "yourscript.js"]

Additionalalscript.js может просто объявить переменную var isextension = true. yourscript.js может проверить typeof isextension != 'undefined'.

Но, возможно, более интересный пример, он может объявить

var adminpassword='letmein'

Теперь yourscript.js имеет доступ только к adminpassword при запуске в расширении.

(Конечно, вы бы не вставляли пароль в файл скрипта, если бы плагин находился на компьютере, который мог быть скомпрометирован)

1 голос
/ 13 декабря 2016

Chrome не предоставляет какого-либо прямого API-интерфейса для проверки состояния запущенного приложения во всплывающем окне или в представлении Chrome. тем не менее, один косвенный прием может сработать - мы можем сопоставить разрешение тела расширения, которое равно или меньше, чем указано в CSS (в этом случае будет открыто всплывающее окно расширения), или больше, чем это (в этом случае представление веб-страницы будет открыть).

1 голос
/ 08 марта 2013

Я заметил, что в Chrome объект chrome, который является свойством объекта глобального окна, не может быть удален. Если это пользовательское свойство, операция удаления выполнена успешно. Таким образом, вы можете проверить таким образом:

var isRunningInExtension = (!(delete window.chrome) && chrome.extension) ? 
                           true : false;

UPDATE: Строка выше не гарантирует, что код работает в расширении Chrome. Каждый может создать объект с именем «chrome» со свойством extension, а затем заморозить / запечатать этот объект - этого будет достаточно, чтобы пройти проверку и получить неверный результат, что ваш код выполняется внутри расширения chrome.

Чтобы убедиться, что вы выполняете свой код в расширении, вы должны протестировать глобальный объект chrome перед запуском любого javascript - таким образом у вас будет гарантия, что перед тестированием не будет создан поддельный объект chrome.

Одним из возможных решений является использование iframe - в моем примере ниже я использую свойство песочницы iframe, чтобы инструктировать iframe не выполнять никаких сценариев (даже сценариев, включенных в тег script) - таким образом, я могу гарантировать, что ни один сценарий не сможет изменить глобальный объект window.chrome.

(function() {
  var isChromeExtension = (function () {
    var contentWindow,
        iframe = document.createElement("iframe"),
        isChromeExtension;
    // test for sandbox support. It is supported in most recent version of Chrome
    if ("sandbox" in iframe) {
      try {
        iframe.sandbox = "allow-same-origin";
        iframe.src=location.href;
        iframe.style="display: none";
        document.body.appendChild(iframe);
        contentWindow = iframe.contentWindow;
        isChromeExtension = !!(contentWindow.chrome && contentWindow.chrome.extension);
        document.body.removeChild(iframe);
      } catch(e) {}
    }
    return isChromeExtension;
  }());
}());

результат может быть:

  • true - если код работает внутри расширения Chrome
  • false - если код не работает внутри расширения Chrome
  • undefined - если браузер не поддерживает песочницу для iframes или произошла ошибка во время теста
0 голосов
/ 29 мая 2018

Для обнаружения приложений и расширений Chrome используйте:

chrome.app.getDetails()
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...