Uncaught DOMException: Blocked a frame with origin

2020-01-26 09:41发布

问题:

I am trying to list the names of all the iframes in a page, so I can access them through Selenium.

The problem is that the name of the iframe changes each time, so I need to loop through all of them.

I am getting:

Uncaught DOMException: Blocked a frame with origin "http://localhost:8080" from accessing a cross-origin frame.

error when I try to loop over them using:

for (var f = 0; f < window.frames.length; f++) {
    console.log(window.frames[f].name)
}

Is there a way to get the name of the iframe in a different way?

回答1:

This error message...

Uncaught DOMException: Blocked a frame with origin "http://localhost:8080" from accessing a cross-origin frame.

...implies that the WebDriver instance blocked from accessing a cross-origin frame.


Same-origin policy

Same-origin policy : Same-origin policy restricts how a document or script loaded from one origin can interact with a resource from another origin. It is a critical security mechanism for isolating potentially malicious documents.


Cross-Origin Resource Sharing (CORS)

Cross-Origin Resource Sharing (CORS) : Cross-Origin Resource Sharing (CORS) is a mechanism that uses additional HTTP headers to tell a Browser Client to let the AUT (Application under Test) running at one origin (domain) have permission to access selected resources from a server at a different origin. A web application makes a cross-origin HTTP request when it requests a resource that has a different origin (domain, protocol, and port) than its own origin.


Example of an origin

Here is an example of origin comparisons to the URL http://store.company.com/dir/page.html

URL                                                  Outcome    Reason
http://store.company.com/dir2/other.html             Success
http://store.company.com/dir/inner/another.html      Success
https://store.company.com/secure.html                Failure    Different protocol
http://store.company.com:81/dir/etc.html             Failure    Different port
http://news.company.com/dir/other.html               Failure    Different host

What went wrong

When you tried to loop through frames your script/program tried to access an <iframe> with different origin using JavaScript which would been a huge security flaw if you would have achieved it. As mentioned above the same-origin policy browsers block scripts trying to access a <iframe> with a different origin.

Two pages have the same origin if the protocol, port (if one is specified), and host are the same for both the webpages. You'll see this referred to as the "scheme/host/port tuple" at times (where a "tuple" is a set of three components that together comprise a whole). Perhaps the protocol, domain, hostname and port must be the same of your same domain when you want to access the desired frame.

Solution

The AUT may contain numerous frames / iframes and some of them may be loaded only after certain JavaScript / Ajax have completed where as some of them may be having style attribute set as display:none; or visiblity as hidden. Of-course won't require to interact with all of them. So it will be a better approach to identify the attributes of the <iframe> and switch accordingly. You can switch to an <iframe> through:

  • Frame Name
  • Frame ID
  • Frame Index
  • WebElement

As per best practices when you intent to switch to a frame induce WebDriverWait for frameToBeAvailableAndSwitchToIt as per the references below.

Here you can find a relevant discussion on Uncaught DOMException


References

Some references:

  • In this discussion you will find a detailed analysis on SecurityError: Blocked a frame with origin from accessing a cross-origin frame

  • In this discussion you will find the different approaches on Is it possible to switch to an element in a frame without using driver.switchTo().frame(“frameName”) in Selenium Webdriver Java?

  • In the A Better Approach to Switch Frames section of this discussion you will find the different approaches on How can I select a html element no matter what frame it is in in selenium?



回答2:

Dirty solution:

for windows:

chrome.exe --user-data-dir="" --disable-web-security

for mac:

open -a Google\ Chrome --args --disable-web-security --user-data-dir=""

In this way you open the chrome and let it ignore the web security.



回答3:

You can use selenium to get iframe tags like this:

var iframeElems = driver.findElements(webdriver.By.xpath("//iframe"));

Then loop on those elements and get the name attribute:

iframe.getAttribute('name')


回答4:

You can try something like this : (Not sure about JavaScript)

var iframeElems = driver.findElements(webdriver.By.tagName("iframe"));

iterate this list to get the attribute.

for (var f = 0; f < iframeElems.length; f++) {
    console.log(iframeElems.getAttribute("attribute name"))
}