How to Communicate Between Frames

How to communicate between frames?

If the parent page A and the iframe page B are in different domains, you will not be able to access methods or fields via B's parent property, nor will script in A be able to reach into B's content, nor will you be able to share global variables between A and B. This boundary placed between page A and page B is a key part of the browser security model. It's what prevents evil.com from wrapping your online bank web page and stealing your account info just by reading the internal variables of the javascript of the bank's web page.

If you have the luxury of requiring the latest generation of browsers, you can use the postmessage technique mentioned in one of the other answers here. If you need to support older browsers, you may be able to pass small amounts of information using cross-domain client scripting techniques in the browser. One example of this is to use iframes to communicate info between the outer page A and the inner page B. It's not easy and there are many steps involved, but it can be done. I wrote an article on this awhile ago.

You will not be able to monitor clicks in B's iframe from the parent page A. That's a violation of browser security policies at multiple levels. (Click hijacking, for one) You won't be able to see when B's URL changes - A can write to the iframe.src property to change the URL, but once the iframe.src points to a different domain than A's domain, A can no longer read the iframe.src property.

If A and B are in different subdomains of the same root domain, you may have an opportunity to "lower" the domain to a common root. For example, if the outer page A is hosted in subdomain A.foo.bar.com, and B is hosted in subdomain foo.bar.com, then you can lower the domain in page A to foo.bar.com (by assigning window.domain = "foo.bar.com" in A's script). Page A will then behave as a peer of page B and the two can then access each other's data as needed, even though A is technically being served from a different domain than B. I wrote an article on domain lowering, too.

Domain lowering can only peel off innermost subdomains to operate in the context of a root domain. You can't change A.foo.bar.com to abc.com.

There is also a slight risk in lowering domains to a common root domain. When you operate your page in its own subdomain, your html and script are segregated from the other subdomains off the common root domain. If a server in one of the other subdomains is compromised, it doesn't really affect your html page.

If you lower your page's domain to the common root domain, you are exposing your internals to script running on the common root domain and to script from other subdomains that has also lowered its domain to the common root. If a server in one of the other subdomains is compromised, it will have access to your script's internals and therefore it may have compromised your subdomain as well.

Communication between frames

OK, I solved the issue myself.

I tried many variations, and above all I placed both alerts in the same html file. I noticed the alert displaying its own name was correctly executed only if it was the first one. So I guessed there was a JS error somewhere in the other alert and indeed there was one - I eventually located the error in the Firefox console. It was caused by a browser security setting, as I suspected, and some good solutions can be found in this other thread:
Disable firefox same origin policy

This worked perfectly for me (as I'm using Firefox):
after Firefox 68 I need to adjust 'privacy.file_unique_origin' -> false (by open 'about:config') to solve 'CORS request not HTTP' for new CORS same-origin rule introduced.

How to communicate between iframe and the parent site?

With different domains, it is not possible to call methods or access the iframe's content document directly.

You have to use cross-document messaging.

parent -> iframe

For example in the top window:

myIframe.contentWindow.postMessage('hello', '*');

and in the iframe:

window.onmessage = function(e) {
if (e.data == 'hello') {
alert('It works!');
}
};

iframe -> parent

For example in the top window:

window.onmessage = function(e) {
if (e.data == 'hello') {
alert('It works!');
}
};

and in the iframe:

window.top.postMessage('hello', '*')

Communicating between frames in Delphi

The same way you would if the controls were in the same Form. Just prefix the Edit control with the Frame object that owns it, eg:

uses
Frame1Unit, Frame2Unit;

procedure TForm1.FormCreate(Sender: TObject);
begin
Frame1 := TFrame1.Create(Self);
Frame1.Parent := ...;
...
Frame2 := TFrame2.Create(Self);
Frame2.Parent := ...;
...
end;

uses
Frame2Unit;

procedure TFrame1.Button1Click(Sender: TObject);
begin
Frame2.Edit1.Text := '...';
end;

A better design would be to encapsulate the logic so Frame1 and Frame2 do not know about each other. Have Frame1 expose an event that it fires when the button is clicked, and then the parent Form can assign a handler to that event and assign the text on the Frame2, eg:

uses
Frame1Unit, Frame2Unit;

procedure TForm1.FormCreate(Sender: TObject);
begin
Frame1 := TFrame1.Create(Self);
Frame1.Parent := ...;
Frame1.OnNewText := Frame1Text;
...
Frame2 := TFrame2.Create(Self);
Frame2.Parent := ...;
...
end;

procedure TForm1.Frame1Text(Sender: TObject; const NewText: string);
begin
Frame2.EditText := NewText;
end;

type
TFrame1TextEvent = procedure(Sender: TObject; const NewText; string) of object;

TFrame1 = class(TFrame)
Button1: TButton;
procedure Button1Click(Sender: TObject);
public
OnNewText: TFrame1TextEvent;
end;

procedure TFrame1.Button1Click(Sender: TObject);
begin
if Assigned(OnNewText) then
OnNewText(Self, '...');
end;

type
TFrame2 = class(TFrame)
Edit1: TEdit;
private
function GetEditText: string;
procedure SetEditText(const Value: string);
public
property EditText: string read GetEditText write SetEditText;
end;

function TFrame2.GetEditText: string;
begin
Result := Edit1.Text;
end;

procedure TFrame2.SetEditText(const Value: string);
begin
Edit1.Text := Value;
end;

Communication between two different JFrames?

Basically, it's just a matter of having a reference to frame A in frame B, and a reference to frame B in frame A :

public class FrameA extends JFrame {
private FrameB frameB;

public void setFrameB(FrameB frameB) {
this.frameB = frameB;
}

public void foo() {
// change things in this frame
frameB.doSomethingBecauseFrameAHasChanged();
}
}

public class FrameB extends JFrame {
private FrameA frameA;

public void setFrameA(FrameA frameA) {
this.frameA = frameA;
}

public void bar() {
// change things in this frame
frameA.doSomethingBecauseFrameBHasChanged();
}
}

public class Main {
public static void main(String[] args) {
FrameA frameA = new FrameA();
FrameB frameB = new FrameB();
frameA.setFrameB(frameB);
frameB.setFrameA(frameA);
// make both frames visible
}
}

Most of the time, interfaces are introduced to decouple the frames (listeners, etc.), or a mediator is used in order to avoid too much linkings between all the frames, but you should get the idea.

Communication between iFrames?

If the <iframe> elements are served from the same domain, then they can access each other directly. For example, in iframe1 you could do:

document.getElementById('someDiv').innerHTML = 
top.document.getElementById('otherIframe').contentWindow.
document.getElementById('someOtherDiv').innerHTML;

Communication between child iframes

Kinda hacky, but you could build a communication channel on top of localStorage. Frames could send messages by writing to localStorage, and then read messages by constantly polling localStorage for changes.



Related Topics



Leave a reply



Submit