3

Расширения Chrome имеют возможность перехватывать все веб-запросы к указанным URL-адресам с использованием chrome.webRequest.onBeforeRequest. Это включает в себя не только статические запросы к активам, но и запросы для AJAX, PJAX, значков и всего, что происходит между ними.Написание эквивалента onBeforeRequest на Chrome в расширении Safari

Apple, обеспечивает несколько близких приближения к этой функции, таким как beforeLoad (обрабатывает изображения, CSS и JS) и beforeNavigate (обрабатывает полные загрузки страниц) обработчик событий, но ни поймать AJAX запросы. Я попытался перегрузить XMLHttpRequest, пытаясь поймать AJAX нагрузки безрезультатно (я мог бы сделать что-то не так). Вот краткий пример того, как я это делаю:

var originalOpen = window.XMLHttpRequest.prototype.open; 
window.XMLHttpRequest.prototype.open = function(method, url, async, username, password) { 
    console.log("overriden"); 
    return originalOpen.apply(this, arguments); 
} 

Как я могу поймать все веб-запросы (AJAX, CSS, JS и т.д.) в расширении Safari?

+0

Я не специалист по этой теме, но где вы выполняете этот код? В [инъецированном скрипте] (https://developer.apple.com/library/safari/documentation/Tools/Conceptual/SafariExtensionGuide/InjectingScripts/InjectingScripts.html)? Тогда у вас есть те же проблемы, что и скрипты содержания Chrome: они изолированы от веб-страницы и изменяют собственную копию XMLHttpRequest. – Xan

+0

Введенные скрипты запускаются в контексте загруженной страницы, я полагаю. –

+0

Я связал эту страницу специально для справки. _ "... вставляемые скрипты и скрипты, включенные в веб-страницу, выполняются в изолированных мирах, без доступа к функциям или данным друг друга" _ – Xan

ответ

4

Update: Вы можете проверить весь поток кода на моем первом Extension Safari я написал для TimeCamp трекере: https://github.com/qdevro/timecamp.safariextz

мне удалось перехватить все AJAX звонки (на самом деле ответы были интересны для меня, потому что там все волшебство случается), , но, к сожалению, я не смог найти решение для отправки его обратно в мой инъецированный скрипт (я все еще работаю над этим) теперь полностью работает - получение xhr для введенного скрипта:

Я сделал это вот так:

1) на впрыскиваемого START сценарий, я добавил в DOM другой сценарий (тот, который делает перехват):

$(document).ready(function(){ 
     var script = document.createElement('script'); 
     script.type = 'text/javascript'; 
     script.src = safari.extension.baseURI + 'path/to/your/script/bellow.js'; 
     document.getElementsByTagName('head')[0].appendChild(script); 
    }) 

2) код перехвата использует this repository, как переопределение объекта XMLHttpRequest, что Я немного изменил настройки, чтобы прикрепить метод, URL-адрес и отправить данные, чтобы он был легко доступен, когда ответ вернется.

В принципе, я переопределен в open() метод XMLHttpsRequest присоединять те ценности, которые я, возможно, потребуется в моем сценарии, и добавил sentData в методе send(), а также:

var RealXHROpen = XMLHttpRequest.prototype.open; 
    ... 
    // Override open method of all XHR requests (inside wire() method 
    XMLHttpRequest.prototype.open = function(method, url, async, user, pass) { 
     this.method = method; 
     this.url = url; 

     RealXHROpen.apply(this, arguments); 
    } 
    ... 
    // Override send method of all XHR requests 
    XMLHttpRequest.prototype.send = function(sentData) { 
     ... 
     this.sentData = sentData; 
     ... 
    } 

Тогда я ве добавил функцию обратного вызова на ответ, которые получают это модифицированный объект XMLHttpRequest, когда данные возвращается, и cotains все: URL, метод, sentData и responseText с полученными данными:

AjaxInterceptor.addResponseCallback(function(xhr) { 
     console.debug("response",xhr); 
     // xhr.method - contains the method used by the call 
     // xhr.url - contains the URL was sent to 
     // xhr.sentData - contains all the sent data (if any) 
     // xhr.responseText - contains the data sent back to the request 

     // Send XHR object back to injected script using DOM events 
     var event = new CustomEvent("ajaxResponse", { 
     detail: xhr 
     }); 

     window.dispatchEvent(event); 
    }); 

    AjaxInterceptor.wire(); 

Для SENDI нг XHR объект из перехвата сценария обратно в нагнетаемой сценарий, я просто должен был использовать DOM events как @Xan предложил (спасибо за это):

window.addEventListener("ajaxResponse", function(evt) { 
     console.debug('xhr response', evt.detail); 
     // do whatever you want with the XHR details ... 
    }, false); 

Некоторые дополнительные подсказки/(рабочий) оптимизаций, что я используемый в моем проекте:

  • Я очистил GET url и переместил все параметры (?&) в свойство dataSent;
  • Я слился это dataSent свойства, если есть случай (в send(data) методы)
  • Я добавил идентификатор запрос на отправке (временная метка) для того, чтобы соответствовать его позже (см точки, приведенной ниже, и получить представление);
  • Я отправил пользовательское событие в сценарий под названием «ajaxRequest», чтобы подготовить/оптимизировать время загрузки (мне пришлось запросить некоторые другие данные для какого-либо внешнего API с помощью CORS - путем передачи вызова/ответа туда и обратно на global.html, способный обрабатывать CORS), поэтому мне не пришлось ждать, пока исходный запрос вернется, прежде чем отправлять вызов API, но просто сопоставляя ответы на основе метки времени выше;
+0

События DOM - это путь. http://stackoverflow.com/a/25847017/934239 – Xan

+0

@ Xan - Я вижу, позвольте мне проверить полный поток, когда я вернусь домой (где находится мой Mac и код), и я отредактирую ответ, чтобы он был полным. Спасибо ! – qdev

+0

yeap! DOM-события сделали недостающую часть - я отредактирую заключительные шаги;) – qdev