| 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 |