void WebHistory::AddItem(const AutoJObject& list, WebCore::HistoryItem* item) { LOG_ASSERT(item, "newItem must take a valid HistoryItem!"); // Item already added. Should only happen when we are inflating the list. if (item->bridge() || !list.get()) return; JNIEnv* env = list.env(); // Allocate a blank WebHistoryItem jclass clazz = env->FindClass("android/webkit/WebHistoryItem"); jobject newItem = env->NewObject(clazz, gWebHistoryItem.mInit); // Create the bridge, make it active, and attach it to the item. WebHistoryItem* bridge = new WebHistoryItem(env, newItem, item); bridge->setActive(); item->setBridge(bridge); // Update the history item which will flatten the data and call update on // the java item. bridge->updateHistoryItem(item); // Add it to the list. env->CallVoidMethod(list.get(), gWebBackForwardList.mAddHistoryItem, newItem); // Delete our local reference. env->DeleteLocalRef(newItem); }
string dumpHistoryItem(const WebHistoryItem& item, int indent, bool isCurrent) { string result; if (isCurrent) { result.append("curr->"); result.append(indent - 6, ' '); // 6 == "curr->".length() } else result.append(indent, ' '); string url = normalizeLayoutTestURL(item.urlString().utf8()); result.append(url); if (!item.target().isEmpty()) { result.append(" (in frame \""); result.append(item.target().utf8()); result.append("\")"); } result.append("\n"); const WebVector<WebHistoryItem>& children = item.children(); if (!children.isEmpty()) { // Must sort to eliminate arbitrary result ordering which defeats // reproducible testing. // FIXME: WebVector should probably just be a std::vector!! std::vector<WebHistoryItem> sortedChildren; for (size_t i = 0; i < children.size(); ++i) sortedChildren.push_back(children[i]); std::sort(sortedChildren.begin(), sortedChildren.end(), HistoryItemCompareLess); for (size_t i = 0; i < sortedChildren.size(); ++i) result += dumpHistoryItem(sortedChildren[i], indent + 4, false); } return result; }
void WebFrameLoaderClient::setTitle(const String& title, const KURL& url) { #if PLATFORM(AMIGAOS4) if (!m_webFrame->parentFrame()) { BalWidget* viewWindow = m_webFrame->webView()->viewWindow(); if (viewWindow && viewWindow->window) { extern char* utf8ToAmiga(const char* utf8); char *titlestr = utf8ToAmiga(title.utf8().data()); if (titlestr && titlestr[0]) snprintf(viewWindow->title, sizeof(viewWindow->title), viewWindow->clickTabNode ? "%s" : "OWB: %s", titlestr); else strcpy(viewWindow->title, "Origyn Web Browser"); free(titlestr); if (amigaConfig.tabs) { IIntuition->SetGadgetAttrs(viewWindow->gad_clicktab, viewWindow->window, NULL, CLICKTAB_Labels, ~0, TAG_DONE); IClickTab->SetClickTabNodeAttrs(viewWindow->clickTabNode, TNA_Text, viewWindow->title, TAG_DONE); IIntuition->RefreshSetGadgetAttrs(viewWindow->gad_clicktab, viewWindow->window, NULL, CLICKTAB_Labels, viewWindow->clickTabList, TAG_DONE); } else IIntuition->SetWindowTitles(viewWindow->window, viewWindow->title, (STRPTR)~0UL); CString urlLatin1 = url.prettyURL().latin1(); const char *urlstr = urlLatin1.data(); if (urlstr && urlstr[0] && viewWindow->gad_url) { snprintf(viewWindow->url, sizeof(viewWindow->url), "%s", urlstr); if (ILayout->SetPageGadgetAttrs(viewWindow->gad_url, viewWindow->page, viewWindow->window, NULL, STRINGA_TextVal, viewWindow->url, TAG_DONE)) ILayout->RefreshPageGadget(viewWindow->gad_url, viewWindow->page, viewWindow->window, NULL); } } } #endif bool privateBrowsingEnabled = false; WebPreferences* preferences = m_webFrame->webView()->preferences(); if (preferences) privateBrowsingEnabled = preferences->privateBrowsingEnabled(); if (privateBrowsingEnabled) return; // update title in global history WebHistory* history = webHistory(); if (!history) return; WebHistoryItem* item = history->itemForURL(url.string()); if (!item) return; item->setTitle(title.utf8().data()); }
static void WebHistoryInflate(JNIEnv* env, jobject obj, jint frame, jbyteArray data) { LOG_ASSERT(frame, "Inflate needs a valid frame pointer!"); LOG_ASSERT(data, "Inflate needs a valid data pointer!"); // Inflate the history tree into one HistoryItem or null if the inflation // failed. RefPtr<WebCore::HistoryItem> newItem = WebCore::HistoryItem::create(); WebHistoryItem* bridge = new WebHistoryItem(env, obj, newItem.get()); // Get the actual bytes and the length from the java array. const jbyte* bytes = env->GetByteArrayElements(data, NULL); jsize size = env->GetArrayLength(data); newItem->setBridge(bridge); // Inflate the item recursively. If it fails, that is ok. We'll have an // incomplete HistoryItem but that is better than crashing due to a null // item. // We have a 2nd local variable since read_item_recursive may change the // ptr's value. We can't pass &bytes since we have to send bytes to // ReleaseByteArrayElements unchanged. const char* ptr = reinterpret_cast<const char*>(bytes); bool readCheck = read_item_recursive(newItem.get(), &ptr, (int)size); if(!readCheck) LOGV("read_item_recursive returned %d ",readCheck); env->ReleaseByteArrayElements(data, const_cast<jbyte*>(bytes), JNI_ABORT); bridge->setActive(); // Add the new item to the back/forward list. WebCore::Frame* pFrame = (WebCore::Frame*)frame; pFrame->page()->backForwardList()->addItem(newItem); // Update the item. bridge->updateHistoryItem(newItem.get()); }
// Returns True if item1 < item2. static bool HistoryItemCompareLess(const WebHistoryItem& item1, const WebHistoryItem& item2) { string16 target1 = item1.target(); string16 target2 = item2.target(); std::transform(target1.begin(), target1.end(), target1.begin(), ToLower()); std::transform(target2.begin(), target2.end(), target2.begin(), ToLower()); return target1 < target2; }
WebHistoryItem* WebHistoryItem::createInstance(PassRefPtr<HistoryItem> historyItem) { WebHistoryItem* instance; instance = historyItemWrappers().get(historyItem.get()); if (!instance) instance = new WebHistoryItem(historyItem); instance->AddRef(); return instance; }
static void dumpBackForwardList(const TestNavigationController& navigationController, string& result) { result.append("\n============== Back Forward List ==============\n"); for (int index = 0; index < navigationController.entryCount(); ++index) { int currentIndex = navigationController.lastCommittedEntryIndex(); WebHistoryItem historyItem = navigationController.entryAtIndex(index)->contentState(); if (historyItem.isNull()) { historyItem.initialize(); historyItem.setURLString(navigationController.entryAtIndex(index)->URL().spec().utf16()); } result.append(dumpHistoryItem(historyItem, 8, index == currentIndex)); } result.append("===============================================\n"); }
static string dumpHistoryItem(const WebHistoryItem& item, int indent, bool isCurrent) { string result; if (isCurrent) { result.append("curr->"); result.append(indent - 6, ' '); // 6 == "curr->".length() } else { result.append(indent, ' '); } string url = item.urlString().utf8(); size_t pos; if (!url.find(fileUrlPattern) && ((pos = url.find(layoutTestsPattern)) != string::npos)) { // adjust file URLs to match upstream results. url.replace(0, pos + layoutTestsPatternSize, fileTestPrefix); } else if (!url.find(dataUrlPattern)) { // URL-escape data URLs to match results upstream. string path = webkit_support::EscapePath(url.substr(dataUrlPatternSize)); url.replace(dataUrlPatternSize, url.length(), path); } result.append(url); if (!item.target().isEmpty()) { result.append(" (in frame \""); result.append(item.target().utf8()); result.append("\")"); } if (item.isTargetItem()) result.append(" **nav target**"); result.append("\n"); const WebVector<WebHistoryItem>& children = item.children(); if (!children.isEmpty()) { // Must sort to eliminate arbitrary result ordering which defeats // reproducible testing. // FIXME: WebVector should probably just be a std::vector!! std::vector<WebHistoryItem> sortedChildren; for (size_t i = 0; i < children.size(); ++i) sortedChildren.push_back(children[i]); std::sort(sortedChildren.begin(), sortedChildren.end(), HistoryItemCompareLess); for (size_t i = 0; i < sortedChildren.size(); ++i) result += dumpHistoryItem(sortedChildren[i], indent + 4, false); } return result; }
HRESULT STDMETHODCALLTYPE WebHistoryItem::children(unsigned* outChildCount, SAFEARRAY** outChildren) { if (!outChildCount || !outChildren) { ASSERT_NOT_REACHED(); return E_POINTER; } *outChildCount = 0; *outChildren = 0; const HistoryItemVector& coreChildren = m_historyItem->children(); if (coreChildren.isEmpty()) return S_OK; size_t childCount = coreChildren.size(); SAFEARRAY* children = SafeArrayCreateVector(VT_UNKNOWN, 0, static_cast<ULONG>(childCount)); if (!children) return E_OUTOFMEMORY; for (unsigned i = 0; i < childCount; ++i) { WebHistoryItem* item = WebHistoryItem::createInstance(coreChildren[i]); if (!item) { SafeArrayDestroy(children); return E_OUTOFMEMORY; } COMPtr<IUnknown> unknown; HRESULT hr = item->QueryInterface(IID_IUnknown, (void**)&unknown); if (FAILED(hr)) { SafeArrayDestroy(children); return hr; } LONG longI = i; hr = SafeArrayPutElement(children, &longI, unknown.get()); if (FAILED(hr)) { SafeArrayDestroy(children); return hr; } } *outChildCount = static_cast<unsigned>(childCount); *outChildren = children; return S_OK; }
static void write_children_recursive(WTF::Vector<char>& v, WebCore::HistoryItem* parent) { const WebCore::HistoryItemVector& children = parent->children(); WebCore::HistoryItemVector::const_iterator end = children.end(); for (WebCore::HistoryItemVector::const_iterator i = children.begin(); i != end; ++i) { WebCore::HistoryItem* item = (*i).get(); LOG_ASSERT(parent->bridge(), "The parent item should have a bridge object!"); if (!item->bridge()) { WebHistoryItem* bridge = new WebHistoryItem(static_cast<WebHistoryItem*>(parent->bridge())); item->setBridge(bridge); bridge->setActive(); } else { // The only time this item's parent may not be the same as the // parent's bridge is during history close. In that case, the // parent must not have a parent bridge. WebHistoryItem* bridge = static_cast<WebHistoryItem*>(item->bridge()); WebHistoryItem* parentBridge = static_cast<WebHistoryItem*>(parent->bridge()); LOG_ASSERT(parentBridge->parent() == 0 || bridge->parent() == parentBridge, "Somehow this item has an incorrect parent"); bridge->setParent(parentBridge); } write_item(v, item); write_children_recursive(v, item); } }
void WebFrameLoaderClient::setTitle(const String& title, const KURL& url) { #if PLATFORM(AMIGAOS4) if (!m_webFrame->parentFrame()) { BalWidget* viewWindow = m_webFrame->webView()->viewWindow(); if (viewWindow && viewWindow->window) { CString titleLatin1 = title.latin1(); const char *titlestr = titleLatin1.data(); if (titlestr && titlestr[0]) snprintf(viewWindow->title, sizeof(viewWindow->title), "OWB: %s", titlestr); else strcpy(viewWindow->title, "Origyn Web Browser"); IIntuition->SetWindowTitles(viewWindow->window, viewWindow->title, (STRPTR)~0UL); CString urlLatin1 = url.prettyURL().latin1(); const char *urlstr = urlLatin1.data(); if (urlstr && urlstr[0] && viewWindow->gad_url) { snprintf(viewWindow->url, sizeof(viewWindow->url), "%s", urlstr); IIntuition->RefreshSetGadgetAttrs(viewWindow->gad_url, viewWindow->window, NULL, STRINGA_TextVal, viewWindow->url, TAG_DONE); } } } #endif bool privateBrowsingEnabled = false; WebPreferences* preferences = m_webFrame->webView()->preferences(); if (preferences) privateBrowsingEnabled = preferences->privateBrowsingEnabled(); if (privateBrowsingEnabled) return; // update title in global history WebHistory* history = webHistory(); if (!history) return; WebHistoryItem* item = history->itemForURL(url.string()); if (!item) return; item->setTitle(title); }
void WebFrameLoaderClient::setTitle(const String& title, const KURL& url) { bool privateBrowsingEnabled = false; WebPreferences* preferences = m_webFrame->webView()->preferences(); if (preferences) privateBrowsingEnabled = preferences->privateBrowsingEnabled(); if (privateBrowsingEnabled) return; // update title in global history WebHistory* history = webHistory(); if (!history) return; WebHistoryItem* item = history->itemForURL(url.string()); if (!item) return; item->setTitle(title); }
void TestShell::captureHistoryForWindow(size_t windowIndex, WebVector<WebHistoryItem>* history, size_t* currentEntryIndex) { ASSERT(history); ASSERT(currentEntryIndex); if (windowIndex >= m_windowList.size()) return; TestNavigationController& navigationController = *m_windowList[windowIndex]->navigationController(); size_t entryCount = navigationController.entryCount(); WebVector<WebHistoryItem> result(entryCount); *currentEntryIndex = navigationController.lastCommittedEntryIndex(); for (size_t index = 0; index < entryCount; ++index) { WebHistoryItem historyItem = navigationController.entryAtIndex(index)->contentState(); if (historyItem.isNull()) { historyItem.initialize(); historyItem.setURLString(navigationController.entryAtIndex(index)->URL().spec().utf16()); } result[index] = historyItem; } history->swap(result); }
static jint WebHistoryInflate(JNIEnv* env, jobject obj, jint frame, jbyteArray data) { ALOG_ASSERT(frame, "Inflate needs a valid frame pointer!"); ALOG_ASSERT(data, "Inflate needs a valid data pointer!"); // Get the actual bytes and the length from the java array. const jbyte* bytes = env->GetByteArrayElements(data, NULL); jsize size = env->GetArrayLength(data); // Inflate the history tree into one HistoryItem or null if the inflation // failed. RefPtr<WebCore::HistoryItem> newItem = WebCore::HistoryItem::create(); WebHistoryItem* bridge = new WebHistoryItem(newItem.get()); newItem->setBridge(bridge); // Inflate the item recursively. If it fails, that is ok. We'll have an // incomplete HistoryItem but that is better than crashing due to a null // item. // We have a 2nd local variable since read_item_recursive may change the // ptr's value. We can't pass &bytes since we have to send bytes to // ReleaseByteArrayElements unchanged. const char* ptr = reinterpret_cast<const char*>(bytes); readItemRecursive(newItem.get(), &ptr, (int)size); env->ReleaseByteArrayElements(data, const_cast<jbyte*>(bytes), JNI_ABORT); bridge->setActive(); // Add the new item to the back/forward list. WebCore::Frame* pFrame = (WebCore::Frame*)frame; pFrame->page()->backForwardList()->addItem(newItem); // Update the item. bridge->updateHistoryItem(newItem.get()); // Ref here because Java expects to adopt the reference, and as such will not // call ref on it. However, setBridge has also adopted the reference // TODO: This is confusing as hell, clean up ownership and have setBridge // take a RefPtr instead of a raw ptr and calling adoptRef on it bridge->ref(); return reinterpret_cast<jint>(bridge); }
void WebHistoryItem::updateHistoryItem(WebCore::HistoryItem* item) { // Do not want to update during inflation. if (!m_active) return; WebHistoryItem* webItem = this; // Now we need to update the top-most WebHistoryItem based on the top-most // HistoryItem. if (m_parent) { webItem = m_parent.get(); if (webItem->hasOneRef()) { // if the parent only has one ref, it is from this WebHistoryItem. // This means that the matching WebCore::HistoryItem has been freed. // This can happen during clear(). ALOGW("Can't updateHistoryItem as the top HistoryItem is gone"); return; } while (webItem->parent()) webItem = webItem->parent(); item = webItem->historyItem(); if (!item) { // If a HistoryItem only exists for page cache, it is possible that // the parent HistoryItem destroyed before the child HistoryItem. If // it happens, skip updating. ALOGW("Can't updateHistoryItem as the top HistoryItem is gone"); return; } } JNIEnv* env = JSC::Bindings::getJNIEnv(); if (!env) return; MutexLocker locker(webItem->m_lock); // TODO: Figure out if we can't just use item->urlString() instead... const WTF::String urlString = WebFrame::convertIDNToUnicode(item->url()); webItem->m_url = urlString.threadsafeCopy(); const WTF::String originalUrlString = WebFrame::convertIDNToUnicode(item->originalURL()); webItem->m_originalUrl = originalUrlString.threadsafeCopy(); const WTF::String& titleString = item->title(); webItem->m_title = titleString.threadsafeCopy(); // Try to get the favicon from the history item. For some pages like Grand // Prix, there are history items with anchors. If the icon fails for the // item, try to get the icon using the url without the ref. jobject favicon = NULL; WTF::String url = item->urlString(); if (item->url().hasFragmentIdentifier()) { int refIndex = url.reverseFind('#'); url = url.substring(0, refIndex); } // FIXME: This method should not be used from outside WebCore and will be removed. // http://trac.webkit.org/changeset/81484 WebCore::Image* icon = WebCore::iconDatabase().synchronousIconForPageURL(url, WebCore::IntSize(16, 16)); delete webItem->m_favicon; webItem->m_favicon = webcoreImageToSkBitmap(icon); if (webItem->m_faviconCached) { env->DeleteGlobalRef(webItem->m_faviconCached); webItem->m_faviconCached = 0; } webItem->m_data.clear(); WebHistory::Flatten(env, webItem->m_data, item); if (webItem->m_dataCached) { env->DeleteGlobalRef(webItem->m_dataCached); webItem->m_dataCached = 0; } }
void WebHistoryItem::updateHistoryItem(WebCore::HistoryItem* item) { // Do not want to update during inflation. if (!m_active) return; WebHistoryItem* webItem = this; // Now we need to update the top-most WebHistoryItem based on the top-most // HistoryItem. if (m_parent) { webItem = m_parent.get(); if (webItem->hasOneRef()) { // if the parent only has one ref, it is from this WebHistoryItem. // This means that the matching WebCore::HistoryItem has been freed. // This can happen during clear(). LOGW("Can't updateHistoryItem as the top HistoryItem is gone"); return; } while (webItem->parent()) webItem = webItem->parent(); item = webItem->historyItem(); if (!item) { // If a HistoryItem only exists for page cache, it is possible that // the parent HistoryItem destroyed before the child HistoryItem. If // it happens, skip updating. LOGW("Can't updateHistoryItem as the top HistoryItem is gone"); return; } } JNIEnv* env = JSC::Bindings::getJNIEnv(); if (!env) return; // Don't do anything if the item has been gc'd already AutoJObject realItem = getRealObject(env, webItem->m_object); if (!realItem.get()) return; const WebCore::String& urlString = item->urlString(); jstring urlStr = NULL; if (!urlString.isNull()) urlStr = env->NewString((unsigned short*)urlString.characters(), urlString.length()); const WebCore::String& originalUrlString = item->originalURLString(); jstring originalUrlStr = NULL; if (!originalUrlString.isNull()) { originalUrlStr = env->NewString( (unsigned short*) originalUrlString.characters(), originalUrlString.length()); } const WebCore::String& titleString = item->title(); jstring titleStr = NULL; if (!titleString.isNull()) titleStr = env->NewString((unsigned short*)titleString.characters(), titleString.length()); // Try to get the favicon from the history item. For some pages like Grand // Prix, there are history items with anchors. If the icon fails for the // item, try to get the icon using the url without the ref. jobject favicon = NULL; WebCore::String url = item->urlString(); if (item->url().hasFragmentIdentifier()) { int refIndex = url.reverseFind('#'); url = url.substring(0, refIndex); } WebCore::Image* icon = WebCore::iconDatabase()->iconForPageURL(url, WebCore::IntSize(16, 16)); if (icon) favicon = webcoreImageToJavaBitmap(env, icon); WTF::Vector<char> data; jbyteArray array = WebHistory::Flatten(env, data, item); env->CallVoidMethod(realItem.get(), gWebHistoryItem.mUpdate, urlStr, originalUrlStr, titleStr, favicon, array); env->DeleteLocalRef(urlStr); env->DeleteLocalRef(originalUrlStr); env->DeleteLocalRef(titleStr); if (favicon) env->DeleteLocalRef(favicon); env->DeleteLocalRef(array); }
WebHistoryItem* WebHistoryItem::createInstance() { WebHistoryItem* instance = new WebHistoryItem(HistoryItem::create()); instance->AddRef(); return instance; }