WebKitTools/DumpRenderTree/chromium/TestNavigationController.cpp
changeset 2 303757a437d3
parent 0 4f2f89ce4247
equal deleted inserted replaced
0:4f2f89ce4247 2:303757a437d3
     1 /*
       
     2  * Copyright (C) 2010 Google Inc. All rights reserved.
       
     3  *
       
     4  * Redistribution and use in source and binary forms, with or without
       
     5  * modification, are permitted provided that the following conditions are
       
     6  * met:
       
     7  *
       
     8  *     * Redistributions of source code must retain the above copyright
       
     9  * notice, this list of conditions and the following disclaimer.
       
    10  *     * Redistributions in binary form must reproduce the above
       
    11  * copyright notice, this list of conditions and the following disclaimer
       
    12  * in the documentation and/or other materials provided with the
       
    13  * distribution.
       
    14  *     * Neither the name of Google Inc. nor the names of its
       
    15  * contributors may be used to endorse or promote products derived from
       
    16  * this software without specific prior written permission.
       
    17  *
       
    18  * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
       
    19  * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
       
    20  * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
       
    21  * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
       
    22  * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
       
    23  * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
       
    24  * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
       
    25  * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
       
    26  * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
       
    27  * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
       
    28  * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
       
    29  */
       
    30 
       
    31 #include "config.h"
       
    32 #include "TestNavigationController.h"
       
    33 
       
    34 #include "TestShell.h"
       
    35 #include <wtf/Assertions.h>
       
    36 
       
    37 using namespace WebKit;
       
    38 using namespace std;
       
    39 
       
    40 // ----------------------------------------------------------------------------
       
    41 // TestNavigationEntry
       
    42 
       
    43 TestNavigationEntry::TestNavigationEntry()
       
    44     : m_pageID(-1) {}
       
    45 
       
    46 TestNavigationEntry::TestNavigationEntry(
       
    47     int pageID, const WebURL& url, const WebString& title, const WebString& targetFrame)
       
    48     : m_pageID(pageID)
       
    49     , m_url(url)
       
    50     , m_title(title)
       
    51     , m_targetFrame(targetFrame) {}
       
    52 
       
    53 TestNavigationEntry::~TestNavigationEntry() {}
       
    54 
       
    55 void TestNavigationEntry::setContentState(const WebHistoryItem& state)
       
    56 {
       
    57     m_state = state;
       
    58 }
       
    59 
       
    60 // ----------------------------------------------------------------------------
       
    61 // TestNavigationController
       
    62 
       
    63 TestNavigationController::TestNavigationController(NavigationHost* host)
       
    64     : m_pendingEntry(0)
       
    65     , m_lastCommittedEntryIndex(-1)
       
    66     , m_pendingEntryIndex(-1)
       
    67     , m_host(host)
       
    68     , m_maxPageID(-1) {}
       
    69 
       
    70 TestNavigationController::~TestNavigationController()
       
    71 {
       
    72     discardPendingEntry();
       
    73 }
       
    74 
       
    75 void TestNavigationController::reset()
       
    76 {
       
    77     m_entries.clear();
       
    78     discardPendingEntry();
       
    79 
       
    80     m_lastCommittedEntryIndex = -1;
       
    81 }
       
    82 
       
    83 void TestNavigationController::reload()
       
    84 {
       
    85     // Base the navigation on where we are now...
       
    86     int currentIndex = currentEntryIndex();
       
    87 
       
    88     // If we are no where, then we can't reload.  TODO(darin): We should add a
       
    89     // CanReload method.
       
    90     if (currentIndex == -1)
       
    91         return;
       
    92 
       
    93     discardPendingEntry();
       
    94 
       
    95     m_pendingEntryIndex = currentIndex;
       
    96     navigateToPendingEntry(true);
       
    97 }
       
    98 
       
    99 void TestNavigationController::goToOffset(int offset)
       
   100 {
       
   101     int index = m_lastCommittedEntryIndex + offset;
       
   102     if (index < 0 || index >= entryCount())
       
   103         return;
       
   104 
       
   105     goToIndex(index);
       
   106 }
       
   107 
       
   108 void TestNavigationController::goToIndex(int index)
       
   109 {
       
   110     ASSERT(index >= 0);
       
   111     ASSERT(index < static_cast<int>(m_entries.size()));
       
   112 
       
   113     discardPendingEntry();
       
   114 
       
   115     m_pendingEntryIndex = index;
       
   116     navigateToPendingEntry(false);
       
   117 }
       
   118 
       
   119 void TestNavigationController::loadEntry(TestNavigationEntry* entry)
       
   120 {
       
   121     // When navigating to a new page, we don't know for sure if we will actually
       
   122     // end up leaving the current page.  The new page load could for example
       
   123     // result in a download or a 'no content' response (e.g., a mailto: URL).
       
   124     discardPendingEntry();
       
   125     m_pendingEntry = entry;
       
   126     navigateToPendingEntry(false);
       
   127 }
       
   128 
       
   129 
       
   130 TestNavigationEntry* TestNavigationController::lastCommittedEntry() const
       
   131 {
       
   132     if (m_lastCommittedEntryIndex == -1)
       
   133         return 0;
       
   134     return m_entries[m_lastCommittedEntryIndex].get();
       
   135 }
       
   136 
       
   137 TestNavigationEntry* TestNavigationController::activeEntry() const
       
   138 {
       
   139     TestNavigationEntry* entry = m_pendingEntry;
       
   140     if (!entry)
       
   141         entry = lastCommittedEntry();
       
   142     return entry;
       
   143 }
       
   144 
       
   145 int TestNavigationController::currentEntryIndex() const
       
   146 {
       
   147     if (m_pendingEntryIndex != -1)
       
   148         return m_pendingEntryIndex;
       
   149     return m_lastCommittedEntryIndex;
       
   150 }
       
   151 
       
   152 
       
   153 TestNavigationEntry* TestNavigationController::entryAtIndex(int index) const
       
   154 {
       
   155     if (index < 0 || index >= entryCount())
       
   156         return 0;
       
   157     return m_entries[index].get();
       
   158 }
       
   159 
       
   160 TestNavigationEntry* TestNavigationController::entryWithPageID(int32_t pageID) const
       
   161 {
       
   162     int index = entryIndexWithPageID(pageID);
       
   163     return (index != -1) ? m_entries[index].get() : 0;
       
   164 }
       
   165 
       
   166 void TestNavigationController::didNavigateToEntry(TestNavigationEntry* entry)
       
   167 {
       
   168     // If the entry is that of a page with PageID larger than any this Tab has
       
   169     // seen before, then consider it a new navigation.
       
   170     if (entry->pageID() > maxPageID()) {
       
   171         insertEntry(entry);
       
   172         return;
       
   173     }
       
   174 
       
   175     // Otherwise, we just need to update an existing entry with matching PageID.
       
   176     // If the existing entry corresponds to the entry which is pending, then we
       
   177     // must update the current entry index accordingly.  When navigating to the
       
   178     // same URL, a new PageID is not created.
       
   179 
       
   180     int existingEntryIndex = entryIndexWithPageID(entry->pageID());
       
   181     TestNavigationEntry* existingEntry = (existingEntryIndex != -1) ?
       
   182         m_entries[existingEntryIndex].get() : 0;
       
   183     if (!existingEntry) {
       
   184         // No existing entry, then simply ignore this navigation!
       
   185     } else if (existingEntry == m_pendingEntry) {
       
   186         // The given entry might provide a new URL... e.g., navigating back to a
       
   187         // page in session history could have resulted in a new client redirect.
       
   188         existingEntry->setURL(entry->URL());
       
   189         existingEntry->setContentState(entry->contentState());
       
   190         m_lastCommittedEntryIndex = m_pendingEntryIndex;
       
   191         m_pendingEntryIndex = -1;
       
   192         m_pendingEntry = 0;
       
   193     } else if (m_pendingEntry && m_pendingEntry->pageID() == -1
       
   194                && GURL(m_pendingEntry->URL()) == GURL(existingEntry->URL().spec())) {
       
   195         // Not a new navigation
       
   196         discardPendingEntry();
       
   197     } else {
       
   198         // The given entry might provide a new URL... e.g., navigating to a page
       
   199         // might result in a client redirect, which should override the URL of the
       
   200         // existing entry.
       
   201         existingEntry->setURL(entry->URL());
       
   202         existingEntry->setContentState(entry->contentState());
       
   203 
       
   204         // The navigation could have been issued by the renderer, so be sure that
       
   205         // we update our current index.
       
   206         m_lastCommittedEntryIndex = existingEntryIndex;
       
   207     }
       
   208 
       
   209     delete entry;
       
   210     updateMaxPageID();
       
   211 }
       
   212 
       
   213 void TestNavigationController::discardPendingEntry()
       
   214 {
       
   215     if (m_pendingEntryIndex == -1)
       
   216         delete m_pendingEntry;
       
   217     m_pendingEntry = 0;
       
   218     m_pendingEntryIndex = -1;
       
   219 }
       
   220 
       
   221 void TestNavigationController::insertEntry(TestNavigationEntry* entry)
       
   222 {
       
   223     discardPendingEntry();
       
   224 
       
   225     // Prune any entry which are in front of the current entry
       
   226     int currentSize = static_cast<int>(m_entries.size());
       
   227     if (currentSize > 0) {
       
   228         while (m_lastCommittedEntryIndex < (currentSize - 1)) {
       
   229             m_entries.removeLast();
       
   230             currentSize--;
       
   231         }
       
   232     }
       
   233 
       
   234     m_entries.append(linked_ptr<TestNavigationEntry>(entry));
       
   235     m_lastCommittedEntryIndex = static_cast<int>(m_entries.size()) - 1;
       
   236     updateMaxPageID();
       
   237 }
       
   238 
       
   239 int TestNavigationController::entryIndexWithPageID(int32 pageID) const
       
   240 {
       
   241     for (int i = static_cast<int>(m_entries.size()) - 1; i >= 0; --i) {
       
   242         if (m_entries[i]->pageID() == pageID)
       
   243             return i;
       
   244     }
       
   245     return -1;
       
   246 }
       
   247 
       
   248 void TestNavigationController::navigateToPendingEntry(bool reload)
       
   249 {
       
   250     // For session history navigations only the pending_entry_index_ is set.
       
   251     if (!m_pendingEntry) {
       
   252         ASSERT(m_pendingEntryIndex != -1);
       
   253         m_pendingEntry = m_entries[m_pendingEntryIndex].get();
       
   254     }
       
   255 
       
   256     if (m_host->navigate(*m_pendingEntry, reload)) {
       
   257         // Note: this is redundant if navigation completed synchronously because
       
   258         // DidNavigateToEntry call this as well.
       
   259         updateMaxPageID();
       
   260     } else
       
   261         discardPendingEntry();
       
   262 }
       
   263 
       
   264 void TestNavigationController::updateMaxPageID()
       
   265 {
       
   266     TestNavigationEntry* entry = activeEntry();
       
   267     if (entry)
       
   268         m_maxPageID = max(m_maxPageID, entry->pageID());
       
   269 }