Recently, I have encountered a problem that can be said to be a headache. The wechat API cannot be called within the Iframe framework, and then I have to solve this problem because of business requirements. Window.parent.wx.xxx () can be used to call the wechat API method in iframe framework, but!! If the current page and the embedded Iframe framework are not in the same domain (cross-domain), this is a hell of a requirement!

Have a problem

Fortunately, I am still a more intelligent teenager, coupled with the guidance of my army brother, found that the new HTML5 API window.postmessage () seems to be able to solve my problem. So.. A series of research tests were conducted.

reference

MDN – Window.postMessage()

Syntax

otherWindow.postMessage(message, targetOrigin, [transfer])

  • messageThe information you want to send (either a string or an object)
  • targetOriginThe target domain name you want to send the message to
  • transferOptional parameter, the specific meaning has not done in-depth understanding, also have not used to.

MDN introduces window.postMessage() for cross-domain communication using window.open() to dynamically open new pages on a page. It is very detailed and the Demo is very useful, but it seems to me that something is missing.

Tips

Var targetPage = window.open(‘http://target.com’); var targetPage = window.open(‘http://target.com’); But we can’t listen for onLoad events on targetPage in the cross-domain case, so we can only do deferred setTimeout or scheduled setInterval. Similarly, in the case of embedded iframe pages, we need to wait until the iframe within the page is loaded to postMessage cross-domain communication.

It is OK to use window.open() to dynamically open a new page using postMessage cross-domain communication (dry code), but it is not possible to embed iframe in the page.

Failed to execute ‘postMessage’ on ‘DOMWindow’: The target of origin provided (‘ http://192.168.198.157:8000 ‘) does not match The recipient window ‘s origin (‘ http://192.168.198.157:3000 ‘).

PS

PageA > > http://192.168.198.157:8000

PageB > > http://192.168.198.157:3000

PageA Embedded within the pageiframe PageB

Thinking about thinking

Half an hour did not solve, this time I think it should be put off, and then carefully think about where the problem is, there must be not understand the place, and then Google a lot of information to view in detail, talk about the train of thought.

  • To solve the problem from the source of the problem, I now encounter the problem boils down to two pages with different domain names how to communicate?
  • The browser’s same-origin policy does not allow cross-domain crossings, however the HTML5 APIwindow.postMessage()Is used to achieve cross-domain communication.
  • So how does communication work?
  • If there are two pages PageA and PageB, PageA is embedded inside the pageiframePageB, then theoretically should be able to achieve two-way communication.

PageA sends a message to PageB via window.postMessage(), PageB adds an event listener to the window and binds the message event to the postMessage method from any different domain name. When PageB receives the message sent by PageA, the listener event is OK. The event parameter of the listener contains all the data received by the message event. Including the content of sending information event.data, sending information domain event.origin and so on.

Similarly, add an event listener in PageA bound to the message event, and send a message to PageA in PageB via the postMessage method for cross-domain communication.

Tips

We can go throughevent.originTo filter out messages from other unknown sitesmessageEvent information to prevent XSS attacks!

Probably the above thinking, and then continue to write the Demo…

Dry goods code

PageA




  
  Page A


  

This is Page A

Open New Window Post Message

Copy the code

PageB




  
  Page B


  

This is Page B

Post Message

Copy the code

The pit of tread

PageB needs special attention!!

  • Open the PageB page directly in the browser is unable to send cross-domain information to PageA page!!

  • The receiveMessage method on the PageB page automatically replies with a timestamp to all postMessage messages from the PageA page.

  • Why does the sendMessage method in PageB use top.postMessage() to send cross-domain information??

    • The answer lies in the conclusion below

Tips

If the page is not opened with window.open() or embedded with iframe, there is no relation to the current page and you cannot use window.postMessage() for cross-domain communication!!

The description doesn’t seem to be very clear. Here’s an example:

  • If you open a browser and type in PageA, then open a new TAB and type in PageB, then these two pages cannot use window.postmessage () for cross-domain communication in any way, they are not related…

  • Similarly, open the browser, enter a page address PageA, and then use PageA to dynamically open PageB (of course, not through the A TAB link in PageA), or PageA to embed iframe PageB, then this time is great. They’re related! Is PageB at this point equivalent to PageA being a cub? It is because of PageA that there is PageB. Then, of course, PageA has some control over PageB, including window.postMessage().

Come to the conclusion

What exactly is window in window.postMessage()?

A: It’s always the target page you want to communicate towindow

PageA Embedded within the pageiframePageB page

  • PageA page sends cross-domain information to PageB page. Window is the window of PageB page, namely iframe. ContentWindow.

  • The PageB page sends cross-domain information to the PageA page. Window is the window of the PageA page, that is, top or parent.

PageA Page code usedwindow.open()Open the PageB page

  • PageA page to PageB send cross-domain information page, the window for var PageB = window. The open PageB (‘ http://192.168.197.157:3000/pageB.html ‘) of the variables.

  • PageB page can not actively send cross-domain information to PageA page, must first receive the message sent by PageA page and then send to PageA through event.source, yes… The window is event.source, which is PageA’s window

Finally the last

Are you listening anywaymessageEvent inside the function pairevent.originFilter it, otherwise it’s from an unknown sitewindow.postMessage()You can do whatever you want with your site.