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 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); }
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()); }
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); }