New issue
Advanced search Search tips
Note: Color blocks (like or ) mean that a user may not be available. Tooltip shows the reason.

Issue 895102 link

Starred by 2 users

Issue metadata

Status: Assigned
Owner:
Cc:
Components:
EstimatedDays: ----
NextAction: ----
OS: Windows , Chrome
Pri: 2
Type: Bug



Sign in to add a comment

Partial failure when loading multiple embedded google maps

Reported by co...@redguava.com.au, Oct 13

Issue description

UserAgent: Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/69.0.3497.100 Safari/537.36

Example URL:
https://www.billiam.org/chrome-embedded-maps/

Steps to reproduce the problem:
1. Load a page containing two or more simple embedded google maps (via iframes).
2. Click map to open larger map in new tab

What is the expected behavior?
1. All maps load correctly. Google copyright appears. 'View larger map' panel appears.
2. Map opens correctly in new tab

What went wrong?
1. Maps which load simultaneously do not load completely. Map background and pin appear, but copyright and 'View larger map' panel do not.
2. Clicking partially loaded map opens new tab pointing to google.com/maps/embed/v1/undefined, and 404s

Does it occur on multiple sites: Yes

Is it a problem with a plugin? No 

Did this work before? Yes 65.0.3325.181

Does this work in other browsers? Yes

Chrome version: 69.0.3497.100  Channel: stable
OS Version: 10.0
Flash Version: 

Screenshot shows 2 partially loaded maps, and one successful one, under Chrome 69.

All map loading succeeds for me in Firefox, IE11 & Edge, Chrome 56 and 65 in windows, even with 10 or more visible maps.

Fails under Chrome 69(stable, windows) and 71(dev, linux)
 
chrome_2018-10-13_13-26-54.png
33.5 KB View Download
Labels: Needs-Bisect Needs-Triage-M69
Bisect tool gave me: 

You are probably looking for a change made after 552588 (known good), but no later than 552589 (first known bad).
CHANGELOG URL:
  https://chromium.googlesource.com/chromium/src/+log/7bbdb70b2643201e9ec6236443b7b2003deaf03d..fb1ccf02ee8ca79e1404abfd3a3a7d540b7d2dbd
Opting out of site isolation via chrome://flags/#site-isolation-trial-opt-out in 69.0.3497.100 also "fixes" the issue.
Cc: lukasza@chromium.org vamshi.kommuri@chromium.org
Labels: Triaged-ET Needs-Feedback
Thanks for filing the issue!

Unable to reproduce the issue on reported chrome version 69.0.3497.100 using Windows 10 with the below mentioned steps.
1. Launched Chrome
2. Navigated to https://www.billiam.org/chrome-embedded-maps/
Observed all maps load correctly and 'View larger map' panel is seen. Attaching the screen cast of the same for reference.
Note: Checked the same by Opting out chrome://flags/#site-isolation-trial-opt-out and by keeping it as Default, In neither of the cases we didn't see any issue.

@Reporter: Could you please have a look at the screen cast and let us now if we have missed anything in the process. Any further inputs from your en may be helpful.

CC'ing "Lukasz Anforowicz" for further inputs from Comment#2.
895102.mp4
10.2 MB View Download
Components: Internals>Sandbox>SiteIsolation
Labels: -Needs-Bisect OS-Chrome
Status: Untriaged (was: Unconfirmed)
I can repro on 69.0.3497.95 on a Chromebook.  Adding Internals>Sandbox>SiteIsolation label per #c2 and #c3.
Components: -Blink Blink>Loader
I can definitely reproduce this as well. I've seen it successful too. 

I found you might need to Ctrl-Refresh to cause it to happen which makes me thing this is a resource loading problem.

Changing the URI of the iframes (so they aren't exactly the same lat/long) doesn't seem to fix it either.
>  Could you please have a look at the screen cast and let us now if we have missed anything in the process

Screencast looks fine to me, but may be down to differences in networking. Could you try disabling the cache in dev tools/network conditions, and then reloading? Possibly try network throttling as well?
FWIW, when control.js is successfully included, it is happening from the native/js callstacks shown below.  When control.js is not included (i.e. when the bug repros), I don't see a call to content::URLLoaderFactoryBundle::CreateLoaderAndStart where the URL's path is "/maps-api-v3/api/js/34/13/controls.js".

[1:1:1015/100518.577785:ERROR:url_loader_factory_bundle.cc(108)] URLLoaderFactoryBundle::CreateLoaderAndStart; request.url = https://maps.googleapis.com/maps-api-v3/api/js/34/13/controls.js; stack = #0 0x7f3da14465ff base::debug::StackTrace::StackTrace()
#1 0x7f3d9e283f40 content::URLLoaderFactoryBundle::CreateLoaderAndStart()
#2 0x7f3d9ef3b382 content::ChildURLLoaderFactoryBundle::CreateLoaderAndStart()
#3 0x7f3d9e27dc47 content::ThrottlingURLLoader::StartNow()
#4 0x7f3d9e27d037 content::ThrottlingURLLoader::Start()
#5 0x7f3d9e27ca3a content::ThrottlingURLLoader::CreateLoaderAndStart()
#6 0x7f3d9ef437d5 content::ResourceDispatcher::StartAsync()
#7 0x7f3d9ef51ca1 content::WebURLLoaderImpl::Context::Start()
#8 0x7f3d9ef57837 content::WebURLLoaderImpl::LoadAsynchronously()
#9 0x7f3d97082178 blink::ResourceLoader::StartWith()
#10 0x7f3d9707c73d blink::ResourceLoadScheduler::Run()
#11 0x7f3d9707bdee blink::ResourceLoadScheduler::MaybeRun()
#12 0x7f3d9707c334 blink::ResourceLoadScheduler::Request()
#13 0x7f3d97081c70 blink::ResourceLoader::Start()
#14 0x7f3d97068ac9 blink::ResourceFetcher::StartLoad()
#15 0x7f3d97067284 blink::ResourceFetcher::RequestResource()
#16 0x7f3d98f7f2fb blink::ScriptResource::Fetch()
#17 0x7f3d99107150 blink::ClassicPendingScript::Fetch()
#18 0x7f3d9911d05b blink::ScriptLoader::FetchClassicScript()
#19 0x7f3d9911c227 blink::ScriptLoader::PrepareScript()
#20 0x7f3d9911b822 blink::ScriptLoader::DidNotifySubtreeInsertionsToDocument()
#21 0x7f3d985fd2d3 blink::ContainerNode::DidInsertNodeVector()
#22 0x7f3d985fe168 blink::ContainerNode::AppendChild()
#23 0x7f3d986c5428 blink::Node::appendChild()
#24 0x7f3d99369378 blink::V8Node::appendChildMethodCallbackForMainWorld()
#25 0x7f3d99c6ffe4 v8::internal::FunctionCallbackArguments::Call()
#26 0x7f3d99c6e668 v8::internal::(anonymous namespace)::HandleApiCallHelper<>()
#27 0x7f3d99c6caa1 v8::internal::Builtin_Impl_HandleApiCall()
#28 0x7f3d99c6c53f v8::internal::Builtin_HandleApiCall()
#29 0x7f3d9a97baf5 <unknown>

; js stack = ze (https://maps.googleapis.com/maps/api/js?client=google-maps-embed&paint_origin=&libraries=geometry,search&v=3.exp&language=en_US:71:503)
https://maps.googleapis.com/maps/api/js?client=google-maps-embed&paint_origin=&libraries=geometry,search&v=3.exp&language=en_US:73:128
Fe (https://maps.googleapis.com/maps/api/js?client=google-maps-embed&paint_origin=&libraries=geometry,search&v=3.exp&language=en_US:73:478)
Ge (https://maps.googleapis.com/maps/api/js?client=google-maps-embed&paint_origin=&libraries=geometry,search&v=3.exp&language=en_US:73:37)
Object._.U (https://maps.googleapis.com/maps/api/js?client=google-maps-embed&paint_origin=&libraries=geometry,search&v=3.exp&language=en_US:74:158)
zd (https://maps.googleapis.com/maps-api-v3/api/js/34/13/map.js:100:75)
_.jl.Zd (https://maps.googleapis.com/maps-api-v3/api/js/34/13/map.js:93:97)
Nr.Zd (https://maps.googleapis.com/maps-api-v3/api/js/34/13/map.js:58:106)
Kr (https://maps.googleapis.com/maps-api-v3/api/js/34/13/map.js:2:295)
HTMLDivElement.<anonymous> (https://maps.googleapis.com/maps-api-v3/api/js/34/13/map.js:3:18)


The callstacks above were generated via:

void URLLoaderFactoryBundle::CreateLoaderAndStart(
    network::mojom::URLLoaderRequest loader,
    int32_t routing_id,
    int32_t request_id,
    uint32_t options,
    const network::ResourceRequest& request,
    network::mojom::URLLoaderClientPtr client,
    const net::MutableNetworkTrafficAnnotationTag& traffic_annotation) {
  if (request.url.path_piece() == "/maps-api-v3/api/js/34/13/controls.js") {
    LOG(ERROR) << "URLLoaderFactoryBundle::CreateLoaderAndStart"
               << "; request.url = " << request.url
               << "; stack = " << base::debug::StackTrace().ToString()
               << "; js stack = "
                          << [](){
                             char* buf = nullptr; size_t size = 0;
                             FILE* f = open_memstream(&buf, &size);
                             if (!f) return std::string("<mem error>");
                             v8::Message::PrintCurrentStackTrace(
                                 v8::Isolate::GetCurrent(), f);
                             fflush(f); fclose(f);
                             std::string result(buf, size);
                             free(buf);
                             return result; }();;
  }



I think I can confirm that this bug is related to Site Isolation:
- It usually repros when Site Isolation is turned on
  (I note that it was turned on by default in M67)
- It never reproed for me after turning Site Isolation off by
  --disable-site-isolation-trials (I tried around 10 times)

Give obfuscated Javascript in #c9 above, we'll probably need help from the Maps team to understand what is the root cause of the bug.  I've opened an internal b/117769016 to ask for help from the Maps team.
Cc: zwarts@google.com
Components: Blink>Image
zwarts@ has kindly looked at this bug and suggested that this might be something similar to issue 807164, where load event for images was missing in OOPIFs.  I was able to confirm this theory, by logging how many times HTMLImageLoader::DispatchLoadEvent is called for each frame.  If it is called 8 times, the map is loaded completely (including the "View larger map" button).  If it is called less times, the bug repros (i.e. the "View larger map" button is missing).  In my attempts to repro sometimes 1 frame fails, sometimes 2 fail and sometimes all 3 fail and so far this was always consistent with the number of observed hits of HTMLImageLoader::DispatchLoadEvent method.
Owner: vmp...@chromium.org
Status: Assigned (was: Untriaged)
vmpstr@, could you PTAL (since you've fixed a possibly related issue 807164)?
I'm guessing that the load event failing to fire is the thing that is causing the rest of the page not to be constructed here? Looking at devtools, it seems that the "bad" frames don't have a chunk of html that the good ones have. (see screenshots)

issue 807164 specifically dealt with the img decode api not resolving things correctly, but that was for the map content itself not for the decorations around. I'll take a look to see if it's the same issue

page.png
54.6 KB View Download
inspect.png
291 KB View Download
Update: I can reproduce on my dev channel and stable, but I can't seem to make it happen on a locally build version. Someone near me reproduced it and from the logs that we've added it seems that there are a total of 14 image decodes that are requested and each of them is processed and the promise is resolved, which is different from the cited issue.

For #11, I think the differences is that the dom for the overlay (large map, logo, etc) is simply not inserted if something before it prevents it, so that could account for the smaller number of DispatchLoadEvent()s

lukasza@ is it possible to match up the number of times the image would have fired as compared to how many times it does fire (ie possibly the number of times a src is set on an image, or maybe the number of HTMLImageElements that is created?) I'll keep trying to repro but it seems that locally my timing is different and causes the page to work :\
Cc: khushals...@chromium.org
It looks like the load of controls.js is triggered via a 'transitionend' event, and the transition (of opacity) itself is (supposed to be) triggered via a rAF callback. So that could be another angle to consider.
Cc: vmp...@chromium.org
Owner: lukasza@chromium.org
Is it possible to get the author(s) of the iframe content to help in debugging this? Ie, which event is expected to fire to continue loading the content. From #16, it's an opacity transition event, but maybe that transition is started by an image load?

From my brief debugging, it seems that the decode api part of the process is in fact working as intended with every requested decode finishing successfully and resolving the corresponding promise, so I'm leaning towards the issue being elsewhere. 

Reassigning back to lukasza@, since I don't think I can help more here (largely due to the fact that I still can't reproduce this on a local build :\)
Thank you fs@ and zwarts@ for providing suggestions and details in https://crbug.com/895102#c16 and b/117769016#comment4.

I've tried to gather again info on how many images are inserted, loaded, decoded (limiting to images with src containing "maps/vt" substrung) and how many times transitionend event fires.  In my repro there was one successful frame and two broken frames.

All 3 frames saw the same number of the following events:
- 4 x HTMLImageLoader::DispatchLoadEvent.*maps/vt
- 8 x InsertedInto.*maps/vt
- 4 x DecodeRequest::Resolve.*maps/vt

1 frame saw:
- 4 x transitionend

2 frames saw:
- 0 x transitionend

So - yes, the problem seems to be the missing transitionend event.

Owner: fsam...@chromium.org
fsamuel@, I wonder if you could please help understand why transitionend event is not firing for some OOPIFs in the repro?  I am afraid that I am not able to help much with rAF and compositor stuff - this goes way beyond what I know about Chrome... :-/
BTW: I also wonder what guarantees the specs offer wrt 1) css animations, 2) transitionend events, 3) rAF.  Are all of these guaranteed to happen, even if a frame is not invisible (scrolled away / below the fold / in invisible parent / in a background tab)?
rAFs [1] should be guaranteed to fire [2]. CSS Transitions (are specced to) trigger[3] on style changes (but don't define exactly when that is...) 'transitionend'[4] should fire if the associated transition completes.

[1] https://html.spec.whatwg.org/multipage/imagebitmap-and-animations.html#animation-frames
[2] Not necessarily in a timely fashion - I believe the spec provides a fair amount of leeway here.
[3] https://drafts.csswg.org/css-transitions/#starting
[4] https://drafts.csswg.org/css-transitions/#transitionend
Would love to know what [2] means. What does the "leeway" entail here?

If [2] is not guaranteed are we supposed to race it with a timeout of a certain value? It would be sad if for neatness purposes.


It boils down to this:

https://html.spec.whatwg.org/multipage/webappapis.html#update-the-rendering

specifically, step 7.3:

 "Rendering opportunites: If there are browsing contexts browsingContexts that do not have a
  rendering opportunity, then remove from docs all Document objects whose browsing context is
  in browsingContexts.

  A browsing context has a rendering opportunity if the user agent is currently able to present
  the contents of the browsing context to the user, accounting for hardware refresh rate
  constraints and user agent throttling for performance reasons, but considering content
  presentable even if it's outside the viewport.

  Browsing context rendering opportunities are determined based on hardware constraints such as
  display refresh rates and other factors such as page performance or whether the page is in the
  background. Rendering opportunities typically occur at regular intervals."

So there are cases (some of which lukasza listed) where, from a spec perspective, the callbacks could be deferred. That being said though, I don't think there any such cases likely being surfaced here - or that they would affect functionality in general in this case (i.e callbacks could be deferred but would always be run at some point in time.)
Owner: flackr@chromium.org
Passing along to flackr@ who's probably a better fit to figure out this bug. Please pass along to me if it's a viz bug.
Any tips for reproducing this? I've tried refreshing the site dozens of times and haven't seen it fail to load on tip of tree (72.0.3597.0) and dev channel (72.0.3590.0).

Re #23, the transition code seems to come down to the following:
requestAnimationFrame(() => {
  element.style.transition = 'opacity 200ms linear';
  element.style.opacity = '0';
  requestAnimationFrame(() => {
    element.style.opacity = '';
  });
  element.addEventListener('transitionend', () {
    finish();
  });
});

Updating the styles on one requestAnimationFrame and then removing on the next requestAnimationFrame should reliably cause a rendering opportunity before the style is removed allowing the transition to start.
Our team has added a race between the transitionend and a 400ms timer to avoid this.
We pushed that to production yesterday. So I understand the issue no longer is reproducible easily, though the underlying issue may persist if it is a chrome bug.

Sign in to add a comment