1 /* 2 * Copyright (C) 2007 Apple 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 6 * are met: 7 * 1. Redistributions of source code must retain the above copyright 8 * notice, this list of conditions and the following disclaimer. 9 * 2. Redistributions in binary form must reproduce the above copyright 10 * notice, this list of conditions and the following disclaimer in the 11 * documentation and/or other materials provided with the distribution. 12 * 13 * THIS SOFTWARE IS PROVIDED BY APPLE COMPUTER, INC. ``AS IS'' AND ANY 14 * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 15 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR 16 * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE COMPUTER, INC. OR 17 * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, 18 * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, 19 * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR 20 * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY 21 * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 22 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE 23 * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 24 */ 25 26 #include "config.h" 27 #include "core/page/History.h" 28 29 #include "bindings/v8/ExceptionState.h" 30 #include "bindings/v8/SerializedScriptValue.h" 31 #include "core/dom/Document.h" 32 #include "core/dom/ExceptionCode.h" 33 #include "core/history/BackForwardController.h" 34 #include "core/history/HistoryItem.h" 35 #include "core/loader/DocumentLoader.h" 36 #include "core/loader/FrameLoader.h" 37 #include "core/loader/FrameLoaderClient.h" 38 #include "core/page/Frame.h" 39 #include "core/page/Page.h" 40 #include "weborigin/KURL.h" 41 #include "weborigin/SecurityOrigin.h" 42 #include "wtf/MainThread.h" 43 44 namespace WebCore { 45 46 History::History(Frame* frame) 47 : DOMWindowProperty(frame) 48 , m_lastStateObjectRequested(0) 49 { 50 ScriptWrappable::init(this); 51 } 52 53 unsigned History::length() const 54 { 55 if (!m_frame) 56 return 0; 57 if (!m_frame->page()) 58 return 0; 59 return m_frame->page()->backForward()->count(); 60 } 61 62 SerializedScriptValue* History::state() 63 { 64 m_lastStateObjectRequested = stateInternal(); 65 return m_lastStateObjectRequested.get(); 66 } 67 68 SerializedScriptValue* History::stateInternal() const 69 { 70 if (!m_frame) 71 return 0; 72 73 if (HistoryItem* historyItem = m_frame->loader()->history()->currentItem()) 74 return historyItem->stateObject(); 75 76 return 0; 77 } 78 79 bool History::stateChanged() const 80 { 81 return m_lastStateObjectRequested != stateInternal(); 82 } 83 84 bool History::isSameAsCurrentState(SerializedScriptValue* state) const 85 { 86 return state == stateInternal(); 87 } 88 89 void History::back() 90 { 91 go(-1); 92 } 93 94 void History::back(ScriptExecutionContext* context) 95 { 96 go(context, -1); 97 } 98 99 void History::forward() 100 { 101 go(1); 102 } 103 104 void History::forward(ScriptExecutionContext* context) 105 { 106 go(context, 1); 107 } 108 109 void History::go(int distance) 110 { 111 if (!m_frame) 112 return; 113 114 m_frame->navigationScheduler()->scheduleHistoryNavigation(distance); 115 } 116 117 void History::go(ScriptExecutionContext* context, int distance) 118 { 119 if (!m_frame) 120 return; 121 122 ASSERT(isMainThread()); 123 Document* activeDocument = toDocument(context); 124 if (!activeDocument) 125 return; 126 127 if (!activeDocument->canNavigate(m_frame)) 128 return; 129 130 m_frame->navigationScheduler()->scheduleHistoryNavigation(distance); 131 } 132 133 KURL History::urlForState(const String& urlString) 134 { 135 KURL baseURL = m_frame->document()->baseURL(); 136 if (urlString.isEmpty()) 137 return baseURL; 138 139 return KURL(baseURL, urlString); 140 } 141 142 void History::stateObjectAdded(PassRefPtr<SerializedScriptValue> data, const String& title, const String& urlString, SameDocumentNavigationSource sameDocumentNavigationSource, ExceptionState& es) 143 { 144 if (!m_frame || !m_frame->page()) 145 return; 146 147 KURL fullURL = urlForState(urlString); 148 if (!fullURL.isValid() || !m_frame->document()->securityOrigin()->canRequest(fullURL)) { 149 es.throwDOMException(SecurityError, "A history state object with URL '" + fullURL.elidedString() + "' cannot be created in a document with origin '" + m_frame->document()->securityOrigin()->toString() + "'."); 150 return; 151 } 152 m_frame->loader()->updateForSameDocumentNavigation(fullURL, sameDocumentNavigationSource, data, title, FrameLoader::DoNotUpdateBackForwardList); 153 } 154 155 } // namespace WebCore 156