PostMessage ข้ามต้นทางเสียใน IE10 หรือไม่


91

ฉันกำลังพยายามสร้างpostMessageตัวอย่างงานเล็กน้อย...

  • ใน IE10
  • ระหว่างหน้าต่าง / แท็บ (เทียบกับ iframes)
  • ข้ามต้นกำเนิด

ลบเงื่อนไขใด ๆ เหล่านี้ออกและสิ่งต่างๆก็ใช้ได้ดี :-)

แต่เท่าที่ฉันสามารถบอกได้ว่าระหว่างหน้าต่างpostMessageดูเหมือนจะทำงานใน IE10 เท่านั้นเมื่อทั้งสองหน้าต่างแชร์จุดเริ่มต้น (ในความเป็นจริง - และแปลก - พฤติกรรมนั้นอนุญาตมากกว่านั้นเล็กน้อย: สองต้นกำเนิดที่แตกต่างกันที่แบ่งปันโฮสต์ดูเหมือนจะทำงานได้เช่นกัน)

นี่เป็นข้อบกพร่องที่มีการบันทึกไว้หรือไม่ วิธีแก้ปัญหาหรือคำแนะนำอื่น ๆ ?

(หมายเหตุ: คำถามนี้เกี่ยวข้องกับปัญหา แต่คำตอบคือเกี่ยวกับ IE8 และ IE9 ไม่ใช่ 10)


รายละเอียดเพิ่มเติม + ตัวอย่าง ...

หน้าตัวเรียกใช้การสาธิต

<!DOCTYPE html>
<html>
  <script>
    window.addEventListener("message", function(e){
      console.log("Received message: ", e);
    }, false);
  </script>
  <button onclick="window.open('http://jsbin.com/ameguj/1');">
    Open new window
  </button>
</html>

เปิดตัวการสาธิตหน้า

<!DOCTYPE html>
<html>
  <script>
    window.opener.postMessage("Ahoy!", "*");
  </script>
</html>

ใช้งานได้ที่: http://jsbin.com/ahuzir/1 - เนื่องจากทั้งสองเพจโฮสต์ที่ต้นทางเดียวกัน (jsbin.com) แต่ย้ายหน้าที่สองไปที่อื่นแล้วมันล้มเหลวใน IE10



5
โปรดพิจารณาเปลี่ยนคำตอบที่ยอมรับเป็นคำตอบที่ตอบคำถามแทนที่จะเป็นคำตอบที่ระบุว่า MessageChannel เป็นทางออกที่ดีที่สุดของคุณเมื่อ MessageChannel ต้องการให้ postMessage ทำงาน ฉันใช้เวลามากกว่าหนึ่งชั่วโมงในการเล่นกับ MessageChannel เพื่อพบว่าโซลูชันเดียวที่ใช้งานได้คือพร็อกซี iframe
Akrikos

1
หาก window.open ของคุณเป็นเพียงกล่องโต้ตอบป๊อปอัปคุณสามารถหลีกเลี่ยงได้ทั้งหมดและใช้ iframe ในโมดอล js บางอย่างเช่นjQuery DialogหรือBootstrap Modalเป็นวิธีที่ฉันใช้งาน จากนั้นคุณสามารถใช้window.parent.postMessageใน IE
styfle

@Bosh เนื่องจากคำตอบของฉันดูเหมือนจะใช้งานได้ในปี 2018 และไม่ต้องใช้กรอบพร็อกซีคุณช่วยคิดไหมว่าคำตอบนั้นเป็นคำตอบที่ได้รับการยอมรับเพราะดูเหมือนว่าจะช่วยเราได้ แต่ผู้โชคร้ายที่ยังคงต้องให้การสนับสนุนเช่นเดิม
Bruno Laurinec

คำตอบ:


62

ฉันเข้าใจผิดเมื่อฉันโพสต์คำตอบนี้ในตอนแรก: มันใช้ไม่ได้จริงใน IE10 เห็นได้ชัดว่าผู้คนพบว่าสิ่งนี้มีประโยชน์ด้วยเหตุผลอื่น ๆ ดังนั้นฉันจึงทิ้งมันไว้เพื่อลูกหลาน คำตอบเดิมด้านล่าง:


สิ่งที่น่าสังเกต: ลิงก์ในคำตอบที่คุณเชื่อมโยงกับสถานะที่postMessageไม่ได้ข้ามจุดเริ่มต้นสำหรับหน้าต่างแยกต่างหากใน IE8 และ IE9 - อย่างไรก็ตามมันถูกเขียนในปี 2009 ก่อนที่ IE10 จะเข้ามา ดังนั้นฉันจะไม่ใช้สิ่งนั้นเป็นข้อบ่งชี้ว่าได้รับการแก้ไขใน IE10

สำหรับpostMessageตัวมันเองhttp://caniuse.com/#feat=x-doc-messagingโดยเฉพาะบ่งชี้ว่ามันยังใช้งานไม่ได้ใน IE10 ซึ่งดูเหมือนจะตรงกับการสาธิตของคุณ หน้า caniuse เชื่อมโยงไปยังบทความนี้ซึ่งมีคำพูดที่เกี่ยวข้องมาก:

Internet Explorer 8+ รองรับการส่งข้อความข้ามเอกสารบางส่วน: ขณะนี้ใช้งานได้กับ iframes แต่ไม่ใช่หน้าต่างใหม่ อย่างไรก็ตาม Internet Explorer 10 จะรองรับ MessageChannel ปัจจุบัน Firefox รองรับการส่งข้อความข้ามเอกสาร แต่ไม่ใช่ MessageChannel

ดังนั้นทางออกที่ดีที่สุดของคุณคือการมีMessageChannelcodepath ที่ใช้และทางเลือกpostMessageหากไม่มีอยู่ มันจะไม่ได้รับการสนับสนุน IE8 / IE9 แต่อย่างน้อยมันก็ใช้งานได้กับ IE10

เอกสารบนMessageChannel: http://msdn.microsoft.com/en-us/library/windows/apps/hh441303.aspx


8
คุณจะสร้างMessageChannelcodepath ที่ใช้งานได้อย่างไร? คุณยังต้องทำงานpostMessageเพื่อรับพอร์ตของช่องไปยังหน้าต่างอื่น
balpha

1
การใช้postMessageกับMessageChannelAPI ใหม่จะใช้ได้กับหน้าต่างและต้นกำเนิดใหม่ การทำงานเป็นเรื่องที่น่าอึดอัดใจเล็กน้อย แต่โดยพื้นฐานแล้ว: postMessage('foo', '*')ไม่ดีpostMessage('foo', [messageChannel.port2])เป็นสิ่งที่ดี
ShZ

3
ฉันไม่สามารถรับ postMessage ที่ทำงานร่วมกับหน้าต่างป๊อปอัปข้ามโดเมนได้ตลอดชีวิตโดยใช้ IE (11) และ MessageChannel API เวอร์ชันล่าสุด และโดยสุจริตฉันไม่พบที่อื่นใน InterWebs นอกเหนือจากคำตอบนี้ที่ระบุว่าสถานการณ์เฉพาะนี้ควรใช้งานได้ ใครสามารถชี้ไปที่ตัวอย่างที่พิสูจน์ว่าได้ผล? ฉันจะขอบคุณตลอดไป
Todd Menier

4
MessageChannel ไม่ควรทำงานด้วยเหตุผลเดียวกัน postMessage จะไม่ทำงาน Microsoft จำเป็นต้องแก้ไขการมาร์แชลข้ามกระบวนการ blogs.msdn.com/b/ieinternals/archive/2009/09/15/…
EricLaw

9
คำตอบนี้น่ารำคาญเพราะทำให้เรามีความหวังผิด ๆ คำตอบคือมันจะไม่ทำงานหากไม่มีพร็อกซีเพราะต้องใช้ postMessage เพื่อให้ MessageChannel ทำงานได้ (อย่างน้อยก็ในทุกการสาธิตที่ฉันเคยเห็น) เว้นแต่จะมีใครแสดงการสาธิตของ MessageChannel ที่ทำงานโดยไม่ใช้ postMessage หรือ postMessage ('name', '<domain>', [messageChannel.port2]) ที่ทำงานข้ามโดเมน (ฉันไม่สามารถใช้งานได้) ฉันจะไม่เชื่อสิ่งนี้ ทำงานโดยไม่มีกรอบพร็อกซี
Akrikos

30

สร้างหน้าพร็อกซีบนโฮสต์เดียวกับตัวเรียกใช้งาน หน้าพร็อกซีมีiframeซอร์สที่ตั้งค่าเป็นเพจระยะไกล ตอนนี้ postMessage ข้ามแหล่งที่มาจะทำงานใน IE10 ดังนี้:

  • เพจระยะไกลใช้window.parent.postMessageส่งข้อมูลไปยังเพจพร็อกซี เนื่องจากใช้ iframe จึงรองรับโดย IE10
  • หน้าพร็อกซีใช้window.opener.postMessageเพื่อส่งข้อมูลกลับไปที่หน้าตัวเรียกใช้งาน เนื่องจากอยู่ในโดเมนเดียวกันจึงไม่มีปัญหาข้ามแหล่งที่มา นอกจากนี้ยังสามารถเรียกใช้วิธีการส่วนกลางบนหน้าตัวเรียกใช้งานได้โดยตรงหากคุณไม่ต้องการใช้ postMessagewindow.opener.someMethod(data)

ตัวอย่าง (URL ทั้งหมดเป็นสมมติ)

หน้าเปิดที่ http://example.com/launcher.htm

<!DOCTYPE html>
<html>
    <head>
        <title>Test launcher page</title>
        <link rel="stylesheet" href="/css/style.css" />
    </head>
    <body>

    <script>
        function log(msg) {
            if (!msg) return;

            var logger = document.getElementById('logger');
            logger.value += msg + '\r\n';
        }            

        function toJson(obj) {
            return JSON.stringify(obj, null, 2);
        }

        function openProxy() {
            var url = 'proxy.htm';
            window.open(url, 'wdwProxy', 'location=no');
            log('Open proxy: ' + url);
        }

        window.addEventListener('message', function(e) {
            log('Received message: ' + toJson(e.data));
        }, false);
    </script>
    
    <button onclick="openProxy();">Open remote</button> <br/>
    <textarea cols="150" rows="20" id="logger"></textarea>

    </body>
</html>

หน้าพร็อกซีที่ http://example.com/proxy.htm

<!DOCTYPE html>
<html>
    <head>
        <title>Proxy page</title>
        <link rel="stylesheet" href="/css/style.css" />
    </head>
    <body>

    <script>
        function toJson(obj) {
            return JSON.stringify(obj, null, 2);
        }

        window.addEventListener('message', function(e) {
            console.log('Received message: ' + toJson(e.data));

            window.opener.postMessage(e.data, '*');
            window.close(self);
        }, false);
    </script>

    <iframe src="http://example.net/remote.htm" frameborder="0" height="300" width="500" marginheight="0" marginwidth="0" scrolling="auto"></iframe>

    </body>
</html>

เพจระยะไกลที่ http://example.net/remote.htm

<!DOCTYPE html>
<html>
    <head>
        <title>Remote page</title>
        <link rel="stylesheet" href="/css/style.css" />
    </head>
    <body>

    <script>
        function remoteSubmit() {
            var data = {
                message: document.getElementById('msg').value
            };

            window.parent.postMessage(data, '*');
        }
    </script>
    
    <h2>Remote page</h2>

    <input type="text" id="msg" placeholder="Type a message" /><button onclick="remoteSubmit();">Close</button>

    </body>
</html>

คำตอบของคุณจะดีกว่าหากมีลิงก์ไปยังหน้าตัวอย่างของ Microsoft และหน้าวิธีแก้ปัญหาที่เชื่อมโยงกับคำตอบอื่น ๆ วิธีแก้ปัญหา: blogs.msdn.com/b/ieinternals/archive/2009/09/16/…ตัวอย่าง (จากหน้าวิธีแก้ปัญหา): debugtheweb.com/test/xdm/origin
Akrikos

นอกจากนี้หน้าตัวอย่างของคุณยังลิงก์ไปยังหน้า GoDaddy ไม่พบ
Akrikos

8
ฮะ? ... URL ทั้งหมดเป็นตัวอย่างและไม่ได้มีไว้เพื่อชี้ไปยังหน้าที่มีอยู่จริงๆ ... จากแหล่งที่มาที่ระบุไว้คุณสามารถกำหนดสิ่งที่ต้องทำเพื่อให้มันใช้งานได้ ..
LyphTEC

ขอขอบคุณสำหรับการชี้แจง. :-)
Akrikos

29

== โซลูชันการทำงานในปี 2020 โดยไม่มี iframe ==

จากคำตอบโดยยุ่งเหยิงฉันประสบความสำเร็จใน IE11 [และจำลองโหมด IE10] โดยใช้ตัวอย่างต่อไปนี้:

var submitWindow = window.open("/", "processingWindow");
submitWindow.location.href = 'about:blank';
submitWindow.location.href = 'remotePage to comunicate with';

จากนั้นฉันก็สามารถสื่อสารโดยใช้สแต็ก postMessage ทั่วไปฉันใช้ผู้ส่งสารแบบคงที่ทั่วโลกในสถานการณ์ของฉัน (แม้ว่าฉันจะไม่คิดว่ามันเป็นสัญญาณบ่งชี้ใด ๆ แต่ฉันก็แนบคลาส Messenger ของฉันด้วย)

var messagingProvider = {
    _initialized: false,
    _currentHandler: null,

    _init: function () {
        var self = this;
        this._initialized = true;
        var eventMethod = window.addEventListener ? "addEventListener" : "attachEvent";
        var eventer = window[eventMethod];
        var messageEvent = eventMethod == "attachEvent" ? "onmessage" : "message";

        eventer(messageEvent, function (e) {
            var callback = self._currentHandler;
            if (callback != null) {
                var key = e.message ? "message" : "data";
                var data = e[key];
                callback(data);
            }
        }, false);
    },

    post: function (target, message) {
        target.postMessage(message, '*');
    },

    setListener: function (callback) {
        if (!this._initialized) {
            this._init();
        }

        this._currentHandler = callback;
    }
}

ไม่ว่าฉันจะพยายามแค่ไหนฉันก็ไม่สามารถทำให้สิ่งต่างๆทำงานบน IE9 และ IE8 ได้

การกำหนดค่าของฉันที่ทำงาน:
เวอร์ชัน IE: 11.0.10240.16590 เวอร์ชันอัปเดต: 11.0.25 (KB3100773)


6
ฉันต้องบอกว่า - ในกรณีที่คนอื่นกำลังมองหาวิธีแก้ปัญหานี้โดยคิดว่า "ไม่มีทางที่อาจแก้ไขไม่ได้" ใช่มันแก้ไขการไม่สามารถ postMessage ไปที่ window.opener ใน IE11 ได้จริง เหลือเชื่อ.
dkr88

1
ไม่มีทาง ... ฉันพยายามอยู่ 2 วันและ "แก้" ปัญหานี้
lmiguelmh

ใช้งานได้เหมือนมีเสน่ห์และลึกลับ !! (IE10.0.9200, win7)
Simon

คุณสามารถให้ตัวอย่างแบบเต็มสำหรับวิธีแก้ปัญหานี้ได้หรือไม่
msm2020

1
@SidJonnala ไม่ได้จริงๆ แต่ฉันอยากจะแนะนำ หากคุณกำหนดใหม่ให้กับเพจระยะไกลจริงทันทีและเพจของคุณใช้เวลาโหลด 3-4 วินาที [อาจเกิดขึ้นเป็นครั้งคราว] คุณเสี่ยงที่หน้า window.open ('/') ของคุณจะโหลดและทำให้ผู้ใช้สับสน
Bruno Laurinec

2

จากคำตอบของ LyphTEC และ Akrikos วิธีแก้ปัญหาอีกอย่างหนึ่งคือการสร้าง<iframe>ภายในหน้าต่างป๊อปอัพเปล่าซึ่งหลีกเลี่ยงความจำเป็นในการแยกหน้าพร็อกซีเนื่องจากป๊อปอัปว่างมีต้นกำเนิดเดียวกันกับที่เปิด

หน้าเปิดที่ http://example.com/launcher.htm

<html>
  <head>
    <title>postMessage launcher</title>
    <script>
      function openWnd() {
        var w = window.open("", "theWnd", "resizeable,status,width=400,height=300"),
            i = w.document.createElement("iframe");

        i.src = "http://example.net/remote.htm";
        w.document.body.appendChild(i);

        w.addEventListener("message", function (e) {
          console.log("message from " + e.origin + ": " + e.data);

          // Send a message back to the source
          e.source.postMessage("reply", e.origin);
        });
      }
    </script>
  </head>
  <body>
    <h2>postMessage launcher</h2>
    <p><a href="javascript:openWnd();">click me</a></p>
  </body>
</html>

เพจระยะไกลที่ http://example.net/remote.htm

<html>
  <head>
    <title>postMessage remote</title>
    <script>
      window.addEventListener("message", function (e) {
        alert("message from " + e.origin + ": " + e.data);
      });

      // Send a message to the parent window every 5 seconds
      setInterval(function () {
        window.parent.postMessage("hello", "*");
      }, 5000);
    </script>
  </head>
  <body>
    <h2>postMessage remote</h2>
  </body>
</html>

ฉันไม่แน่ใจว่ามันบอบบางแค่ไหน แต่มันใช้งานได้ใน IE 11 และ Firefox 40.0.3


1
... และตอนนี้มันใช้งานไม่ได้ (ความล้มเหลวแบบเงียบในหน้าต่างป๊อปอัปไปยัง<iframe>ทิศทาง) ใน IE 11 ( 11.0.9600.18036เวอร์ชันอัปเดต11.0.23 (KB3087038)) อาจเกี่ยวข้องกับการอัปเดตความปลอดภัยล่าสุด ( KB3087038 )
ยุ่งเหยิง

1

ตอนนี้ (2014-09-02) ทางออกที่ดีที่สุดของคุณคือใช้เฟรมพร็อกซีตามที่ระบุไว้ในบล็อกโพสต์ msdn ซึ่งให้รายละเอียดวิธีแก้ปัญหาสำหรับปัญหานี้: https://blogs.msdn.microsoft.com/ieinternals/2009 / 09/15 / html5 -plement-issue-in-ie8-and-later /

นี่คือตัวอย่างการทำงาน: http://www.debugtheweb.com/test/xdm/origin/

คุณต้องตั้งค่าเฟรมพร็อกซีบนเพจของคุณที่มีจุดเริ่มต้นเดียวกับป๊อปอัป window.opener.frames[0]ส่งข้อมูลจากป๊อปอัพไปที่กรอบภาพโดยใช้พร็อกซี่ จากนั้นใช้ postMessage จากกรอบพร็อกซีไปยังหน้าหลัก


1

โซลูชันนี้เกี่ยวข้องกับการเพิ่มไซต์ลงในไซต์ที่เชื่อถือได้ของ Internet Explore และไม่ได้อยู่ในไซต์อินทราเน็ตเฉพาะที่ ฉันทดสอบโซลูชันนี้ใน Windows 10 / IE 11.0.10240.16384, Windows 10 / Microsoft Edge 20.10240.16384.0 และ Windows 7 SP1 / IE 10.0.9200.17148 หน้าจะต้องไม่ถูกรวมอยู่ในโซนอินทราเน็ต

ดังนั้นเปิดการกำหนดค่า Internet Explorer (เครื่องมือ> ตัวเลือกอินเทอร์เน็ต> ความปลอดภัย> ไซต์ที่เชื่อถือได้> ไซต์) และเพิ่มเพจที่นี่ฉันใช้ * เพื่อจับคู่โดเมนย่อยทั้งหมด ตรวจสอบให้แน่ใจว่าหน้านั้นไม่อยู่ในไซต์อินทราเน็ตเฉพาะที่ (เครื่องมือ> ตัวเลือกอินเทอร์เน็ต> ความปลอดภัย> อินทราเน็ตภายใน> ไซต์> ขั้นสูง) รีสตาร์ทเบราว์เซอร์ของคุณและทดสอบอีกครั้ง

เพิ่มลงในไซต์ที่เชื่อถือได้ใน Internet Explorer

ในWindows 10 / Microsoft Edgeคุณจะพบการกำหนดค่านี้ในแผงควบคุม> ตัวเลือกอินเทอร์เน็ต

อัปเดต

หากวิธีนี้ไม่ได้ผลคุณสามารถลองรีเซ็ตการตั้งค่าทั้งหมดของคุณในเครื่องมือ> ตัวเลือกอินเทอร์เน็ต> การตั้งค่าขั้นสูง> รีเซ็ตการตั้งค่า Internet Explorerจากนั้นรีเซ็ต: ใช้ด้วยความระมัดระวัง ! จากนั้นคุณจะต้องรีบูตระบบของคุณ หลังจากนั้นให้เพิ่มไซต์ลงในไซต์ที่เชื่อถือได้

ดูว่าเพจของคุณอยู่ในโซนใดในไฟล์> คุณสมบัติหรือคลิกขวา

คุณสมบัติของเพจใน internet explorer

อัปเดต

ฉันอยู่ในอินทราเน็ตขององค์กรและบางครั้งก็ใช้งานได้และบางครั้งก็ใช้ไม่ได้ (การกำหนดค่าอัตโนมัติฉันเริ่มตำหนิพร็อกซีขององค์กร) ในท้ายที่สุดผมใช้วิธีนี้https://stackoverflow.com/a/36630058/2692914


0

Q นี้เก่า แต่นี่คือสิ่งที่ easyXDM มีไว้สำหรับอาจตรวจสอบว่าเป็นทางเลือกที่อาจเกิดขึ้นเมื่อคุณตรวจพบเบราว์เซอร์ที่ไม่รองรับ html5 .postMessage:

https://easyxdm.net/

ใช้ VBObject wrapper และสิ่งต่างๆทุกประเภทที่คุณไม่ต้องการจัดการเพื่อส่งข้อความข้ามโดเมนระหว่างหน้าต่างหรือเฟรมที่ window.postMessage ล้มเหลวสำหรับ IE เวอร์ชันต่างๆ (และขอบอาจยังไม่แน่ใจ 100% ในการสนับสนุน Edge มี แต่ดูเหมือนว่าจะต้องมีวิธีแก้ปัญหาสำหรับ. PostMessage ด้วย)


-3

MessageChannel ใช้ไม่ได้กับ IE 9-11 ระหว่างหน้าต่าง / แท็บเนื่องจากใช้ postMessage ซึ่งยังคงใช้งานไม่ได้ในสถานการณ์นี้ วิธีแก้ปัญหาที่ "ดีที่สุด" คือการเรียกใช้ฟังก์ชันผ่าน window.opener (เช่น window.opener.somefunction ("somedata"))

วิธีแก้ปัญหาโดยละเอียดเพิ่มเติมที่นี่


1
สิ่งนี้ใช้ไม่ได้ในการตั้งค่าข้ามแหล่งกำเนิดซึ่งเป็นหนึ่งในข้อกำหนดเบื้องต้นในคำถาม
PhistucK
โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.