Как поделиться данными между окном и фреймом в JavaScript - PullRequest
2 голосов
/ 14 декабря 2011

Это браузеры, специфичные для WebKit (это означает, что мне нужно, чтобы он работал только в WebKit, то есть в браузерах iOS / Android, но я тестирую в Chrome).

У меня есть страница.Страница загружает один или несколько фреймов с содержимым из другого домена.Мне нужно получать сообщения (используя postMessage ()) от этих iframes, и я должен быть в состоянии определить, из какого iframe пришло конкретное сообщение.

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

Я попробовал что-то, что мне показалось разумным.Когда я создаю элемент iframe (это сделано из J / S), я связал свойство с элементом, скажем, «shared_secret».Когда я получаю событие сообщения обратно из фрейма, я попытался найти элемент, с которым был создан вызывающий фрейм, и прочитать это свойство.

function onMessage(evt) {
  var callerId = evt.source.frameElement.shared_secret;
  // ....
}

window.addEventListener(message, onMessage);

var frameEl = document.createElement('iframe');
frameEl.shared_secret = 'sommething blue';
frameEl.src = 'http://aliens.com/my.html';
somewhereInMyDoc.appendChild(frameEl);

Когда фрейм загрузится, он запустится:

window.parent.postMessage('do you know who I am?', '*');

Однако, frameElement оказывается неопределенным в вышеупомянутом onMessage ().Я полагаю, по соображениям безопасности, он отлично работает, когда родитель / ребенок находятся в одном домене.

И на самом деле это иронично.Родительское окно не может получить доступ к event.source.frameElement, потому что event.source является чужим окном.Окно iFrame не может вызвать window.frameElement, потому что frameElement находится в чужом окне.Так что никто не может получить к нему доступ.

Итак, есть ли что-то, что я могу использовать в качестве токена, который я могу установить для недавно загруженного фрейма и каким-то образом получить обратно?

Ответы [ 2 ]

7 голосов
/ 30 марта 2012

Для людей, которые ищут какой-то код, вот что я использовал, чтобы найти iframe, который отправил сообщение:

/**
 * Returns the iframe corresponding to a message event or null if not found.
 * 
 * 'e' is the event object
 */
function getFrameTarget (e) {
    var frames = document.getElementsByTagName('iframe'),
        frameId = 0,
        framesLength = frames.length;

    for (; frameId < framesLength; frameId++) {
        if (frames[frameId].contentWindow === e.source) {
            return frames[frameId];
        }
    }

    return null;
}

Спасибо Павлу Веселову и Д.М.Осесу!

1 голос
/ 14 декабря 2011

Это должно быть зачислено на https://stackoverflow.com/users/695461/dmoses.

Вы можете фактически сравнить объект окна содержимого элемента frame с event.source события сообщения, и сравнение даст TRUE, если они есть, вФакт, то же самое.

Итак, чтобы решить мою конкретную проблему, мне нужно будет сохранить список созданных элементов фрейма (при необходимости добавив их, с какими-либо дополнительными свойствами), и когдасобытие приходит, перебирая все, ища тот, у которого свойство contentWindow равно свойству event.source.

UPDATE

Мы сделали это, встретивнеприятные ошибки, также выяснилось, что вы должны поместить 'id' в iframe, созданный из родительского окна.Особенно, если это окно само в фрейме.В противном случае некоторые браузеры (Android 4.x известен наверняка) приведут к истинному сравнению, даже если сообщение будет получено из совершенно другого дочернего фрейма.

...