void HistoryController::restoreDocumentState() { Document* doc = m_frame->document(); HistoryItem* itemToRestore = 0; switch (m_frame->loader()->loadType()) { case FrameLoadTypeReload: case FrameLoadTypeReloadFromOrigin: case FrameLoadTypeSame: case FrameLoadTypeReplace: break; case FrameLoadTypeBack: case FrameLoadTypeBackWMLDeckNotAccessible: case FrameLoadTypeForward: case FrameLoadTypeIndexedBackForward: case FrameLoadTypeRedirectWithLockedBackForwardList: case FrameLoadTypeStandard: itemToRestore = m_currentItem.get(); } if (!itemToRestore) return; LOG(Loading, "WebCoreLoading %s: restoring form state from %p", m_frame->tree()->name().string().utf8().data(), itemToRestore); doc->setStateForNewFormElements(itemToRestore->documentState()); }
void HistoryController::saveDocumentState() { // FIXME: Reading this bit of FrameLoader state here is unfortunate. I need to study // this more to see if we can remove this dependency. if (m_frame->loader()->stateMachine()->creatingInitialEmptyDocument()) return; // For a standard page load, we will have a previous item set, which will be used to // store the form state. However, in some cases we will have no previous item, and // the current item is the right place to save the state. One example is when we // detach a bunch of frames because we are navigating from a site with frames to // another site. Another is when saving the frame state of a frame that is not the // target of the current navigation (if we even decide to save with that granularity). // Because of previousItem's "masking" of currentItem for this purpose, it's important // that previousItem be cleared at the end of a page transition. We leverage the // checkLoadComplete recursion to achieve this goal. HistoryItem* item = m_previousItem ? m_previousItem.get() : m_currentItem.get(); if (!item) return; Document* document = m_frame->document(); ASSERT(document); if (item->isCurrentDocument(document)) { LOG(Loading, "WebCoreLoading %s: saving form state to %p", m_frame->tree()->name().string().utf8().data(), item); item->setDocumentState(document->formElementsState()); } }
void CachedFrameBase::restore() { ASSERT(m_document->view() == m_view); if (m_isMainFrame) m_view->setParentVisible(true); Frame& frame = m_view->frame(); m_cachedFrameScriptData->restore(frame); if (m_document->svgExtensions()) m_document->accessSVGExtensions().unpauseAnimations(); frame.animation().resumeAnimationsForDocument(m_document.get()); m_document->resumeActiveDOMObjects(ActiveDOMObject::PageCache); m_document->resumeScriptedAnimationControllerCallbacks(); // It is necessary to update any platform script objects after restoring the // cached page. frame.script().updatePlatformScriptObjects(); if (m_isComposited) frame.view()->restoreBackingStores(); frame.loader().client().didRestoreFromPageCache(); // Reconstruct the FrameTree. And open the child CachedFrames in their respective FrameLoaders. for (unsigned i = 0; i < m_childFrames.size(); ++i) { frame.tree().appendChild(&m_childFrames[i]->view()->frame()); m_childFrames[i]->open(); } #if PLATFORM(IOS) if (m_isMainFrame) { frame.loader().client().didRestoreFrameHierarchyForCachedFrame(); if (DOMWindow* domWindow = m_document->domWindow()) { // FIXME: Add SCROLL_LISTENER to the list of event types on Document, and use m_document->hasListenerType(). See <rdar://problem/9615482>. // FIXME: Can use Document::hasListenerType() now. if (domWindow->scrollEventListenerCount() && frame.page()) frame.page()->chrome().client().setNeedsScrollNotifications(&frame, true); } } #endif // FIXME: update Page Visibility state here. // https://bugs.webkit.org/show_bug.cgi?id=116770 m_document->enqueuePageshowEvent(PageshowEventPersisted); HistoryItem* historyItem = frame.loader().history().currentItem(); m_document->enqueuePopstateEvent(historyItem && historyItem->stateObject() ? historyItem->stateObject() : SerializedScriptValue::nullValue()); #if ENABLE(TOUCH_EVENTS) && !PLATFORM(IOS) if (m_document->hasTouchEventHandlers()) m_document->page()->chrome().client().needTouchEvents(true); #endif m_document->resume(); }
void CachedFrameBase::restore() { ASSERT(m_document->view() == m_view); if (m_isMainFrame) m_view->setParentVisible(true); Frame* frame = m_view->frame(); m_cachedFrameScriptData->restore(frame); #if ENABLE(SVG) if (m_document->svgExtensions()) m_document->accessSVGExtensions()->unpauseAnimations(); #endif frame->animation()->resumeAnimationsForDocument(m_document.get()); frame->eventHandler()->setMousePressNode(m_mousePressNode.get()); m_document->resumeActiveDOMObjects(); m_document->resumeScriptedAnimationControllerCallbacks(); // It is necessary to update any platform script objects after restoring the // cached page. frame->script()->updatePlatformScriptObjects(); #if USE(ACCELERATED_COMPOSITING) if (m_isComposited) frame->view()->restoreBackingStores(); #endif frame->loader()->client()->didRestoreFromPageCache(); // Reconstruct the FrameTree for (unsigned i = 0; i < m_childFrames.size(); ++i) frame->tree()->appendChild(m_childFrames[i]->view()->frame()); // Open the child CachedFrames in their respective FrameLoaders. for (unsigned i = 0; i < m_childFrames.size(); ++i) m_childFrames[i]->open(); if (m_isMainFrame) { frame->loader()->client()->didRestoreFrameHierarchyForCachedFrame(); if (DOMWindow* domWindow = m_document->domWindow()) { // FIXME: add SCROLL_LISTENER to the list of event types on Document, and use m_document->hasListenerType() <rdar://problem/9615482> if (domWindow->scrollEventListenerCount() > 0 && frame->page()) frame->page()->chrome()->client()->setNeedsScrollNotifications(frame, true); } } m_document->enqueuePageshowEvent(PageshowEventPersisted); HistoryItem* historyItem = frame->loader()->history()->currentItem(); m_document->enqueuePopstateEvent(historyItem && historyItem->stateObject() ? historyItem->stateObject() : SerializedScriptValue::nullValue()); m_document->documentDidBecomeActive(); }
// entry.getTarget() JNIEXPORT jstring JNICALL Java_com_sun_webkit_BackForwardList_bflItemGetTarget(JNIEnv* env, jclass z, jlong jitem) { HistoryItem* item = getItem(jitem); String target = item->target(); if (!target.isEmpty()) { return target.toJavaString(env).releaseLocal(); } else { return NULL; } }
int HistoryModel::rowCount(const QModelIndex &parent) const { if (parent.column() > 0) { return 0; } HistoryItem* parentItem = itemFromIndex(parent); return parentItem->childCount(); }
QModelIndex HistoryModel::index(int row, int column, const QModelIndex &parent) const { if (!hasIndex(row, column, parent)) { return QModelIndex(); } HistoryItem* parentItem = itemFromIndex(parent); HistoryItem* childItem = parentItem->child(row); return childItem ? createIndex(row, column, childItem) : QModelIndex(); }
void ApiWrap::gotWebPages(const MTPmessages_Messages &msgs, mtpRequestId req) { const QVector<MTPMessage> *v = 0; switch (msgs.type()) { case mtpc_messages_messages: App::feedUsers(msgs.c_messages_messages().vusers); App::feedChats(msgs.c_messages_messages().vchats); v = &msgs.c_messages_messages().vmessages.c_vector().v; break; case mtpc_messages_messagesSlice: App::feedUsers(msgs.c_messages_messagesSlice().vusers); App::feedChats(msgs.c_messages_messagesSlice().vchats); v = &msgs.c_messages_messagesSlice().vmessages.c_vector().v; break; } QMap<int32, int32> msgsIds; // copied from feedMsgs for (int32 i = 0, l = v->size(); i < l; ++i) { const MTPMessage &msg(v->at(i)); switch (msg.type()) { case mtpc_message: msgsIds.insert(msg.c_message().vid.v, i); break; case mtpc_messageEmpty: msgsIds.insert(msg.c_messageEmpty().vid.v, i); break; case mtpc_messageService: msgsIds.insert(msg.c_messageService().vid.v, i); break; } } MainWidget *m = App::main(); for (QMap<int32, int32>::const_iterator i = msgsIds.cbegin(), e = msgsIds.cend(); i != e; ++i) { HistoryItem *item = App::histories().addToBack(v->at(*i), -1); if (item) { item->initDimensions(); if (m) m->itemResized(item); } } const WebPageItems &items(App::webPageItems()); for (WebPagesPending::iterator i = _webPagesPending.begin(); i != _webPagesPending.cend();) { if (i.value() == req) { if (i.key()->pendingTill > 0) { i.key()->pendingTill = -1; WebPageItems::const_iterator j = items.constFind(i.key()); if (j != items.cend()) { for (HistoryItemsMap::const_iterator k = j.value().cbegin(), e = j.value().cend(); k != e; ++k) { k.key()->initDimensions(); if (m) m->itemResized(k.key()); } } } i = _webPagesPending.erase(i); } else { ++i; } } }
bool HistoryItem::isAncestorOf(const HistoryItem* item) const { for (size_t i = 0; i < m_children.size(); ++i) { HistoryItem* child = m_children[i].get(); if (child == item) return true; if (child->isAncestorOf(item)) return true; } return false; }
void CachedFrameBase::restore() { ASSERT(m_document->view() == m_view); if (m_isMainFrame) m_view->setParentVisible(true); Frame& frame = m_view->frame(); m_cachedFrameScriptData->restore(&frame); #if ENABLE(SVG) if (m_document->svgExtensions()) m_document->accessSVGExtensions()->unpauseAnimations(); #endif frame.animation()->resumeAnimationsForDocument(m_document.get()); frame.eventHandler().setMousePressNode(m_mousePressNode.get()); m_document->resumeActiveDOMObjects(ActiveDOMObject::DocumentWillBecomeInactive); m_document->resumeScriptedAnimationControllerCallbacks(); // It is necessary to update any platform script objects after restoring the // cached page. frame.script().updatePlatformScriptObjects(); #if USE(ACCELERATED_COMPOSITING) if (m_isComposited) frame.view()->restoreBackingStores(); #endif frame.loader().client()->didRestoreFromPageCache(); // Reconstruct the FrameTree for (unsigned i = 0; i < m_childFrames.size(); ++i) frame.tree()->appendChild(&m_childFrames[i]->view()->frame()); // Open the child CachedFrames in their respective FrameLoaders. for (unsigned i = 0; i < m_childFrames.size(); ++i) m_childFrames[i]->open(); // FIXME: update Page Visibility state here. // https://bugs.webkit.org/show_bug.cgi?id=116770 m_document->enqueuePageshowEvent(PageshowEventPersisted); HistoryItem* historyItem = frame.loader().history()->currentItem(); m_document->enqueuePopstateEvent(historyItem && historyItem->stateObject() ? historyItem->stateObject() : SerializedScriptValue::nullValue()); #if ENABLE(TOUCH_EVENTS) if (m_document->hasTouchEventHandlers()) m_document->page()->chrome().client().needTouchEvents(true); #endif m_document->documentDidResumeFromPageCache(); }
// BackForwardList.get() JNIEXPORT jobject JNICALL Java_com_sun_webkit_BackForwardList_bflGet(JNIEnv* env, jclass z, jlong jpage, jint index) { BackForwardList* bfl = getBfl(jpage); HistoryItem* item = itemAtIndex(bfl, index); if (!item) return 0; JLObject host(item->hostObject()); if (!host) { host = createEntry(item, jpage); } return host.releaseLocal(); }
void HistoryController::replaceState(PassRefPtr<SerializedScriptValue> stateObject, const String& title, const String& urlString) { Page* page = m_frame->page(); ASSERT(page); HistoryItem* current = page->backForwardList()->currentItem(); ASSERT(current); if (!urlString.isEmpty()) current->setURLString(urlString); current->setTitle(title); current->setStateObject(stateObject); }
void History::addEntry(const HistoryItem &item, int oldest) { std::lock_guard<std::mutex> lock(historyItemsMutex_); if (item.hasPeerNumber() and item.youngerThan(oldest)) { items_.push_back(item); auto im = item.toMap(); string name(im["display_name"]); string account(im["accountid"]); string number(im["peer_number"]); if (nameCache_[account][number].empty() and not name.empty() and not number.empty()) nameCache_[account][number] = name; } }
bool BackForwardList::clearAllPageCaches() { bool didRemoveAtLeastOneItem = false; unsigned length = m_entries.size(); for (unsigned i = 0; i < length; ++i) { HistoryItem* item = m_entries[i].get(); if (item->isInPageCache()) { didRemoveAtLeastOneItem = true; pageCache()->remove(item); } } return didRemoveAtLeastOneItem; }
void FrameLoaderClientAndroid::restoreViewState() { WebViewCore* webViewCore = WebViewCore::getWebViewCore(m_frame->view()); HistoryItem* item = m_frame->loader()->history()->currentItem(); AndroidWebHistoryBridge* bridge = item->bridge(); // restore the scale (only) for the top frame if (!m_frame->tree()->parent()) { int scale = bridge->scale(); webViewCore->restoreScale(scale); int screenWidthScale = bridge->screenWidthScale(); if (screenWidthScale != scale) webViewCore->restoreScreenWidthScale(screenWidthScale); } }
// We do same-document navigation if going to a different item and if either of the following is true: // - The other item corresponds to the same document (for history entries created via pushState or fragment changes). // - The other item corresponds to the same set of documents, including frames (for history entries created via regular navigation) bool HistoryItem::shouldDoSameDocumentNavigationTo(HistoryItem& otherItem) const { if (this == &otherItem) return false; if (stateObject() || otherItem.stateObject()) return documentSequenceNumber() == otherItem.documentSequenceNumber(); if ((url().hasFragmentIdentifier() || otherItem.url().hasFragmentIdentifier()) && equalIgnoringFragmentIdentifier(url(), otherItem.url())) return documentSequenceNumber() == otherItem.documentSequenceNumber(); return hasSameDocumentTree(otherItem); }
void HistoryController::createNewBackForwardItem(LocalFrame* targetFrame, HistoryItem* item, bool clipAtTarget) { RefPtr<HistoryItem> newItem = item; if (!m_currentEntry) { m_currentEntry = HistoryEntry::create(newItem.get(), targetFrame->frameID()); } else { HistoryItem* oldItem = m_currentEntry->itemForFrame(targetFrame); if (!clipAtTarget && oldItem) newItem->setDocumentSequenceNumber(oldItem->documentSequenceNumber()); m_previousEntry = m_currentEntry.release(); m_currentEntry = m_previousEntry->cloneAndReplace(newItem.get(), clipAtTarget, targetFrame, m_page); } }
QMap<QString, QWebHistoryItem> DumpRenderTreeSupportQt::getChildHistoryItems(const QWebHistoryItem& historyItem) { QWebHistoryItem it = historyItem; HistoryItem* item = QWebHistoryItemPrivate::core(&it); const WebCore::HistoryItemVector& children = item->children(); unsigned size = children.size(); QMap<QString, QWebHistoryItem> kids; for (unsigned i = 0; i < size; ++i) { QWebHistoryItem kid(new QWebHistoryItemPrivate(children[i].get())); kids.insert(DumpRenderTreeSupportQt::historyItemTarget(kid), kid); } return kids; }
void Internals::setFormControlStateOfPreviousHistoryItem(PassRefPtr<DOMStringList> state, ExceptionCode& ec) { HistoryItem* mainItem = frame()->loader()->history()->previousItem(); if (!state || !mainItem) { ec = INVALID_ACCESS_ERR; return; } String uniqueName = frame()->tree()->uniqueName(); if (mainItem->target() == uniqueName) mainItem->setDocumentState(*state.get()); else if (HistoryItem* subItem = mainItem->childItemWithTarget(uniqueName)) subItem->setDocumentState(*state.get()); else ec = INVALID_ACCESS_ERR; }
// Does a non-recursive check that this item and its immediate children have the // same frames as the other item. bool HistoryItem::hasSameFrames(HistoryItem& otherItem) const { if (target() != otherItem.target()) return false; if (children().size() != otherItem.children().size()) return false; for (size_t i = 0; i < children().size(); i++) { if (!otherItem.childItemWithTarget(children()[i]->target())) return false; } return true; }
void StackSelection::setFunction(TraceFunction* f) { if (_function == f) return; _function = f; if (!_data || !_function) return; //qDebug() << "StackSelection::setFunction " << f->name(); HistoryItem* item = _browser->current(); if (!item || item->function() != f) { _browser->select(f); rebuildStackList(); } }
QModelIndex HistoryModel::parent(const QModelIndex &index) const { if (!index.isValid()) { return QModelIndex(); } HistoryItem* childItem = itemFromIndex(index); HistoryItem* parentItem = childItem->parent(); if (!parentItem || parentItem == m_rootItem) { return QModelIndex(); } return createIndex(parentItem->row(), 0, parentItem); }
// entry.getChildren() JNIEXPORT jobjectArray JNICALL Java_com_sun_webkit_BackForwardList_bflItemGetChildren(JNIEnv* env, jclass z, jlong jitem, jlong jpage) { HistoryItem* item = getItem(jitem); if (!item->hasChildren()) { return NULL; } jobjectArray children = env->NewObjectArray(item->children().size(), getJEntryClass(), NULL); int i = 0; for (HistoryItemVector::const_iterator it = item->children().begin(); it != item->children().end(); ++it) { env->SetObjectArrayElement(children, i++, (jobject)createEntry(&**it, jpage)); } return children; }
void PageCache::addIfCacheable(HistoryItem& item, Page* page) { if (item.isInPageCache()) return; if (!page || !canCache(*page)) return; // Make sure all the documents know they are being added to the PageCache. setInPageCache(*page, true); // Focus the main frame, defocusing a focused subframe (if we have one). We do this here, // before the page enters the page cache, while we still can dispatch DOM blur/focus events. if (page->focusController().focusedFrame()) page->focusController().setFocusedFrame(&page->mainFrame()); // Fire the pagehide event in all frames. firePageHideEventRecursively(page->mainFrame()); // Check that the page is still page-cacheable after firing the pagehide event. The JS event handlers // could have altered the page in a way that could prevent caching. if (!canCache(*page)) { setInPageCache(*page, false); return; } // Make sure we no longer fire any JS events past this point. NoEventDispatchAssertion assertNoEventDispatch; item.m_cachedPage = std::make_unique<CachedPage>(*page); item.m_pruningReason = PruningReason::None; m_items.add(&item); prune(PruningReason::ReachedMaxSize); }
bool HistoryModel::setData(const QModelIndex &index, const QVariant &value, int role) { HistoryItem* item = itemFromIndex(index); if (index.row() < 0 || !item || item->isTopLevel()) { return false; } if (role == IconRole) { item->setIcon(value.value<QIcon>()); emit dataChanged(index, index); return true; } return false; }
// Does a recursive check that this item and its descendants have the same // document sequence numbers as the other item. bool HistoryItem::hasSameDocumentTree(HistoryItem* otherItem) const { if (documentSequenceNumber() != otherItem->documentSequenceNumber()) return false; if (children().size() != otherItem->children().size()) return false; for (size_t i = 0; i < children().size(); i++) { HistoryItem* child = children()[i].get(); HistoryItem* otherChild = otherItem->childItemWithDocumentSequenceNumber(child->documentSequenceNumber()); if (!otherChild || !child->hasSameDocumentTree(otherChild)) return false; } return true; }
void AnimatedGif::stop(bool onItemRemoved) { if (isNull()) return; delete reader; reader = 0; HistoryItem *row = msg; msg = 0; frames.clear(); delays.clear(); w = h = frame = framesCount = duration = 0; anim::stop(this); if (row && !onItemRemoved) { row->initDimensions(); if (App::main()) App::main()->itemResized(row, true); } }
void CachedFrameBase::restore() { ASSERT(m_document->view() == m_view); if (m_isMainFrame) m_view->setParentVisible(true); Frame* frame = m_view->frame(); m_cachedFrameScriptData->restore(frame); #if ENABLE(SVG) if (m_document->svgExtensions()) m_document->accessSVGExtensions()->unpauseAnimations(); #endif frame->animation()->resumeAnimationsForDocument(m_document.get()); frame->eventHandler()->setMousePressNode(m_mousePressNode.get()); m_document->resumeActiveDOMObjects(); m_document->resumeScriptedAnimationControllerCallbacks(); // It is necessary to update any platform script objects after restoring the // cached page. frame->script()->updatePlatformScriptObjects(); frame->loader()->client()->didRestoreFromPageCache(); // Reconstruct the FrameTree for (unsigned i = 0; i < m_childFrames.size(); ++i) frame->tree()->appendChild(m_childFrames[i]->view()->frame()); // Open the child CachedFrames in their respective FrameLoaders. for (unsigned i = 0; i < m_childFrames.size(); ++i) m_childFrames[i]->open(); m_document->enqueuePageshowEvent(PageshowEventPersisted); HistoryItem* historyItem = frame->loader()->history()->currentItem(); m_document->enqueuePopstateEvent(historyItem && historyItem->stateObject() ? historyItem->stateObject() : SerializedScriptValue::nullValue()); #if ENABLE(TOUCH_EVENTS) if (m_document->hasListenerType(Document::TOUCH_LISTENER)) m_document->page()->chrome()->client()->needTouchEvents(true); #endif m_document->documentDidBecomeActive(); }
// Does a recursive check that this item and its descendants have the same // document sequence numbers as the other item. bool HistoryItem::hasSameDocumentTree(HistoryItem& otherItem) const { if (documentSequenceNumber() != otherItem.documentSequenceNumber()) return false; if (children().size() != otherItem.children().size()) return false; for (size_t i = 0; i < children().size(); i++) { auto& child = children()[i].get(); auto* otherChild = otherItem.childItemWithDocumentSequenceNumber(child.documentSequenceNumber()); if (!otherChild || !child.hasSameDocumentTree(*otherChild)) return false; } return true; }
PassRefPtr<DOMStringList> Internals::formControlStateOfPreviousHistoryItem(ExceptionCode& ec) { HistoryItem* mainItem = frame()->loader()->history()->previousItem(); if (!mainItem) { ec = INVALID_ACCESS_ERR; return 0; } String uniqueName = frame()->tree()->uniqueName(); if (mainItem->target() != uniqueName && !mainItem->childItemWithTarget(uniqueName)) { ec = INVALID_ACCESS_ERR; return 0; } const Vector<String>& state = mainItem->target() == uniqueName ? mainItem->documentState() : mainItem->childItemWithTarget(uniqueName)->documentState(); RefPtr<DOMStringList> stringList = DOMStringList::create(); for (unsigned i = 0; i < state.size(); ++i) stringList->append(state[i]); return stringList.release(); }