OLD | NEW |
1 /* | 1 /* |
2 * Copyright (C) 2006, 2007, 2008, 2009, 2010 Apple Inc. All rights reserved. | 2 * Copyright (C) 2006, 2007, 2008, 2009, 2010 Apple Inc. All rights reserved. |
3 * Copyright (C) 2008 Nokia Corporation and/or its subsidiary(-ies) | 3 * Copyright (C) 2008 Nokia Corporation and/or its subsidiary(-ies) |
4 * Copyright (C) 2008, 2009 Torch Mobile Inc. All rights reserved. (http://www.t
orchmobile.com/) | 4 * Copyright (C) 2008, 2009 Torch Mobile Inc. All rights reserved. |
| 5 * (http://www.torchmobile.com/) |
5 * Copyright (C) 2009 Adam Barth. All rights reserved. | 6 * Copyright (C) 2009 Adam Barth. All rights reserved. |
6 * | 7 * |
7 * Redistribution and use in source and binary forms, with or without | 8 * Redistribution and use in source and binary forms, with or without |
8 * modification, are permitted provided that the following conditions | 9 * modification, are permitted provided that the following conditions |
9 * are met: | 10 * are met: |
10 * | 11 * |
11 * 1. Redistributions of source code must retain the above copyright | 12 * 1. Redistributions of source code must retain the above copyright |
12 * notice, this list of conditions and the following disclaimer. | 13 * notice, this list of conditions and the following disclaimer. |
13 * 2. Redistributions in binary form must reproduce the above copyright | 14 * 2. Redistributions in binary form must reproduce the above copyright |
14 * notice, this list of conditions and the following disclaimer in the | 15 * notice, this list of conditions and the following disclaimer in the |
(...skipping 366 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
381 // it commits. | 382 // it commits. |
382 // | 383 // |
383 // Checking Frame::isNavigationAllowed() doesn't make sense in this context: | 384 // Checking Frame::isNavigationAllowed() doesn't make sense in this context: |
384 // NavigationScheduler is always cleared when a new load commits, so it's | 385 // NavigationScheduler is always cleared when a new load commits, so it's |
385 // impossible for a scheduled navigation to clobber a navigation that just | 386 // impossible for a scheduled navigation to clobber a navigation that just |
386 // committed. | 387 // committed. |
387 // | 388 // |
388 // 2. FrameNavigationDisabler / LocalFrame::isNavigationAllowed() are intended | 389 // 2. FrameNavigationDisabler / LocalFrame::isNavigationAllowed() are intended |
389 // to prevent Documents from being reattached during destruction, since it | 390 // to prevent Documents from being reattached during destruction, since it |
390 // can cause bugs with security origin confusion. This is primarily intended | 391 // can cause bugs with security origin confusion. This is primarily intended |
391 // to block /synchronous/ navigations during things lke Document::detachLayou
tTree(). | 392 // to block /synchronous/ navigations during things lke |
| 393 // Document::detachLayoutTree(). |
392 inline bool NavigationScheduler::shouldScheduleReload() const { | 394 inline bool NavigationScheduler::shouldScheduleReload() const { |
393 return m_frame->page() && m_frame->isNavigationAllowed() && | 395 return m_frame->page() && m_frame->isNavigationAllowed() && |
394 NavigationDisablerForUnload::isNavigationAllowed(); | 396 NavigationDisablerForUnload::isNavigationAllowed(); |
395 } | 397 } |
396 | 398 |
397 inline bool NavigationScheduler::shouldScheduleNavigation( | 399 inline bool NavigationScheduler::shouldScheduleNavigation( |
398 const String& url) const { | 400 const String& url) const { |
399 return m_frame->page() && m_frame->isNavigationAllowed() && | 401 return m_frame->page() && m_frame->isNavigationAllowed() && |
400 (protocolIsJavaScript(url) || | 402 (protocolIsJavaScript(url) || |
401 NavigationDisablerForUnload::isNavigationAllowed()); | 403 NavigationDisablerForUnload::isNavigationAllowed()); |
402 } | 404 } |
403 | 405 |
404 void NavigationScheduler::scheduleRedirect(double delay, const String& url) { | 406 void NavigationScheduler::scheduleRedirect(double delay, const String& url) { |
405 if (!shouldScheduleNavigation(url)) | 407 if (!shouldScheduleNavigation(url)) |
406 return; | 408 return; |
407 if (delay < 0 || delay > INT_MAX / 1000) | 409 if (delay < 0 || delay > INT_MAX / 1000) |
408 return; | 410 return; |
409 if (url.isEmpty()) | 411 if (url.isEmpty()) |
410 return; | 412 return; |
411 | 413 |
412 // We want a new back/forward list item if the refresh timeout is > 1 second. | 414 // We want a new back/forward list item if the refresh timeout is > 1 second. |
413 if (!m_redirect || delay <= m_redirect->delay()) | 415 if (!m_redirect || delay <= m_redirect->delay()) |
414 schedule( | 416 schedule( |
415 ScheduledRedirect::create(delay, m_frame->document(), url, delay <= 1)); | 417 ScheduledRedirect::create(delay, m_frame->document(), url, delay <= 1)); |
416 } | 418 } |
417 | 419 |
418 bool NavigationScheduler::mustReplaceCurrentItem(LocalFrame* targetFrame) { | 420 bool NavigationScheduler::mustReplaceCurrentItem(LocalFrame* targetFrame) { |
419 // Non-user navigation before the page has finished firing onload should not c
reate a new back/forward item. | 421 // Non-user navigation before the page has finished firing onload should not |
420 // See https://webkit.org/b/42861 for the original motivation for this. | 422 // create a new back/forward item. See https://webkit.org/b/42861 for the |
| 423 // original motivation for this. |
421 if (!targetFrame->document()->loadEventFinished() && | 424 if (!targetFrame->document()->loadEventFinished() && |
422 !UserGestureIndicator::utilizeUserGesture()) | 425 !UserGestureIndicator::utilizeUserGesture()) |
423 return true; | 426 return true; |
424 | 427 |
425 // Navigation of a subframe during loading of an ancestor frame does not creat
e a new back/forward item. | 428 // Navigation of a subframe during loading of an ancestor frame does not |
426 // The definition of "during load" is any time before all handlers for the loa
d event have been run. | 429 // create a new back/forward item. The definition of "during load" is any time |
427 // See https://bugs.webkit.org/show_bug.cgi?id=14957 for the original motivati
on for this. | 430 // before all handlers for the load event have been run. See |
| 431 // https://bugs.webkit.org/show_bug.cgi?id=14957 for the original motivation |
| 432 // for this. |
428 Frame* parentFrame = targetFrame->tree().parent(); | 433 Frame* parentFrame = targetFrame->tree().parent(); |
429 return parentFrame && parentFrame->isLocalFrame() && | 434 return parentFrame && parentFrame->isLocalFrame() && |
430 !toLocalFrame(parentFrame)->loader().allAncestorsAreComplete(); | 435 !toLocalFrame(parentFrame)->loader().allAncestorsAreComplete(); |
431 } | 436 } |
432 | 437 |
433 void NavigationScheduler::scheduleLocationChange(Document* originDocument, | 438 void NavigationScheduler::scheduleLocationChange(Document* originDocument, |
434 const String& url, | 439 const String& url, |
435 bool replacesCurrentItem) { | 440 bool replacesCurrentItem) { |
436 if (!shouldScheduleNavigation(url)) | 441 if (!shouldScheduleNavigation(url)) |
437 return; | 442 return; |
438 | 443 |
439 replacesCurrentItem = replacesCurrentItem || mustReplaceCurrentItem(m_frame); | 444 replacesCurrentItem = replacesCurrentItem || mustReplaceCurrentItem(m_frame); |
440 | 445 |
441 // If the URL we're going to navigate to is the same as the current one, excep
t for the | 446 // If the URL we're going to navigate to is the same as the current one, |
442 // fragment part, we don't need to schedule the location change. We'll skip th
is | 447 // except for the fragment part, we don't need to schedule the location |
443 // optimization for cross-origin navigations to minimize the navigator's abili
ty to | 448 // change. We'll skip this optimization for cross-origin navigations to |
444 // execute timing attacks. | 449 // minimize the navigator's ability to execute timing attacks. |
445 if (originDocument->getSecurityOrigin()->canAccess( | 450 if (originDocument->getSecurityOrigin()->canAccess( |
446 m_frame->document()->getSecurityOrigin())) { | 451 m_frame->document()->getSecurityOrigin())) { |
447 KURL parsedURL(ParsedURLString, url); | 452 KURL parsedURL(ParsedURLString, url); |
448 if (parsedURL.hasFragmentIdentifier() && | 453 if (parsedURL.hasFragmentIdentifier() && |
449 equalIgnoringFragmentIdentifier(m_frame->document()->url(), | 454 equalIgnoringFragmentIdentifier(m_frame->document()->url(), |
450 parsedURL)) { | 455 parsedURL)) { |
451 FrameLoadRequest request(originDocument, | 456 FrameLoadRequest request(originDocument, |
452 m_frame->document()->completeURL(url), "_self"); | 457 m_frame->document()->completeURL(url), "_self"); |
453 request.setReplacesCurrentItem(replacesCurrentItem); | 458 request.setReplacesCurrentItem(replacesCurrentItem); |
454 if (replacesCurrentItem) | 459 if (replacesCurrentItem) |
(...skipping 40 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
495 } | 500 } |
496 | 501 |
497 ScheduledNavigation* redirect(m_redirect.release()); | 502 ScheduledNavigation* redirect(m_redirect.release()); |
498 redirect->fire(m_frame); | 503 redirect->fire(m_frame); |
499 InspectorInstrumentation::frameClearedScheduledNavigation(m_frame); | 504 InspectorInstrumentation::frameClearedScheduledNavigation(m_frame); |
500 } | 505 } |
501 | 506 |
502 void NavigationScheduler::schedule(ScheduledNavigation* redirect) { | 507 void NavigationScheduler::schedule(ScheduledNavigation* redirect) { |
503 DCHECK(m_frame->page()); | 508 DCHECK(m_frame->page()); |
504 | 509 |
505 // In a back/forward navigation, we sometimes restore history state to iframes
, even though the state was generated | 510 // In a back/forward navigation, we sometimes restore history state to |
506 // dynamically and JS will try to put something different in the iframe. In th
is case, we will load stale things | 511 // iframes, even though the state was generated dynamically and JS will try to |
507 // and/or confuse the JS when it shortly thereafter tries to schedule a locati
on change. Let the JS have its way. | 512 // put something different in the iframe. In this case, we will load stale |
| 513 // things and/or confuse the JS when it shortly thereafter tries to schedule a |
| 514 // location change. Let the JS have its way. |
508 // FIXME: This check seems out of place. | 515 // FIXME: This check seems out of place. |
509 if (!m_frame->loader().stateMachine()->committedFirstRealDocumentLoad() && | 516 if (!m_frame->loader().stateMachine()->committedFirstRealDocumentLoad() && |
510 m_frame->loader().provisionalDocumentLoader()) { | 517 m_frame->loader().provisionalDocumentLoader()) { |
511 m_frame->loader().stopAllLoaders(); | 518 m_frame->loader().stopAllLoaders(); |
512 if (!m_frame->host()) | 519 if (!m_frame->host()) |
513 return; | 520 return; |
514 } | 521 } |
515 | 522 |
516 cancel(); | 523 cancel(); |
517 m_redirect = redirect; | 524 m_redirect = redirect; |
(...skipping 29 matching lines...) Expand all Loading... |
547 m_navigateTaskFactory->cancel(); | 554 m_navigateTaskFactory->cancel(); |
548 m_redirect.clear(); | 555 m_redirect.clear(); |
549 } | 556 } |
550 | 557 |
551 DEFINE_TRACE(NavigationScheduler) { | 558 DEFINE_TRACE(NavigationScheduler) { |
552 visitor->trace(m_frame); | 559 visitor->trace(m_frame); |
553 visitor->trace(m_redirect); | 560 visitor->trace(m_redirect); |
554 } | 561 } |
555 | 562 |
556 } // namespace blink | 563 } // namespace blink |
OLD | NEW |