WebHistory.cpp revision db239ca3504af9998d5717708fdef4676e286602
18e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project/*
28e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project * Copyright 2007, The Android Open Source Project
38e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project *
48e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project * Redistribution and use in source and binary forms, with or without
58e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project * modification, are permitted provided that the following conditions
68e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project * are met:
78e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project *  * Redistributions of source code must retain the above copyright
88e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project *    notice, this list of conditions and the following disclaimer.
98e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project *  * Redistributions in binary form must reproduce the above copyright
108e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project *    notice, this list of conditions and the following disclaimer in the
118e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project *    documentation and/or other materials provided with the distribution.
128e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project *
138e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS ``AS IS'' AND ANY
148e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
158e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
163298a7d84b96ade73c6b170671711a8f2792ae59Steve Block * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE COPYRIGHT OWNER OR
178e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
188e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
198e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
208e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
218e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
228e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
238e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
248e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project */
258e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project
268e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project#define LOG_TAG "webhistory"
278e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project
288e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project#include <config.h>
298e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project#include <wtf/OwnPtr.h>
308e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project#include <wtf/Platform.h>
318e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project
328e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project#include "WebHistory.h"
338e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project
348e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project#include "BackForwardList.h"
358e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project#include "CString.h"
368e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project#include "DocumentLoader.h"
378e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project#include "Frame.h"
388e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project#include "FrameLoader.h"
398e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project#include "FrameLoaderClientAndroid.h"
408e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project#include "FrameTree.h"
418e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project#include "HistoryItem.h"
42635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Project#include "IconDatabase.h"
438e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project#include "Page.h"
448e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project#include "TextEncoding.h"
458e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project#include "WebCoreFrameBridge.h"
468e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project#include "WebCoreJni.h"
478e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project#include "jni_utility.h"
488e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project
498e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project#include <JNIHelp.h>
508e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project#include <SkUtils.h>
518e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project#include <utils/misc.h>
528e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project
538e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Projectnamespace android {
548e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project
558e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project// Forward declarations
568e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Projectstatic void write_item(WTF::Vector<char>& v, WebCore::HistoryItem* item);
578e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Projectstatic void write_children_recursive(WTF::Vector<char>& v, WebCore::HistoryItem* parent);
588e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Projectstatic bool read_item_recursive(WebCore::HistoryItem* child, const char** pData, int length);
598e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project
608e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project// Field ids for WebHistoryItems
618e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Projectstruct WebHistoryItemFields {
628e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    jmethodID   mInit;
638e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    jmethodID   mUpdate;
648e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    jfieldID    mTitle;
658e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    jfieldID    mUrl;
668e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project} gWebHistoryItem;
678e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project
688e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Projectstruct WebBackForwardListFields {
698e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    jmethodID   mAddHistoryItem;
708e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    jmethodID   mRemoveHistoryItem;
718e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    jfieldID    mCurrentIndex;
728e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project} gWebBackForwardList;
738e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project
748e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project//--------------------------------------------------------------------------
758e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project// WebBackForwardList native methods.
768e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project//--------------------------------------------------------------------------
778e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project
788e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Projectstatic void WebHistoryClose(JNIEnv* env, jobject obj, jint frame)
798e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project{
808e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    LOG_ASSERT(frame, "Close needs a valid Frame pointer!");
818e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    WebCore::Frame* pFrame = (WebCore::Frame*)frame;
828e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project
838e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    WebCore::BackForwardList* list = pFrame->page()->backForwardList();
848e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    RefPtr<WebCore::HistoryItem> current = list->currentItem();
858e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    // Remove each item instead of using close(). close() is intended to be used
868e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    // right before the list is deleted.
878e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    WebCore::HistoryItemVector& entries = list->entries();
888e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    int size = entries.size();
898e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    for (int i = size - 1; i >= 0; --i)
908e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project        list->removeItem(entries[i].get());
918e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    // Add the current item back to the list.
928e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    if (current) {
938e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project        current->setBridge(NULL);
948e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project        // addItem will update the children to match the newly created bridge
958e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project        list->addItem(current);
968e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project
978e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project        /*
988e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project         * The Grand Prix site uses anchor navigations to change the display.
998e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project         * WebKit tries to be smart and not load child frames that have the
1008e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project         * same history urls during an anchor navigation. This means that the
1018e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project         * current history item stored in the child frame's loader does not
1028e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project         * match the item found in the history tree. If we remove all the
1038e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project         * entries in the back/foward list, we have to restore the entire tree
1048e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project         * or else a HistoryItem might have a deleted parent.
1058e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project         *
1068e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project         * In order to restore the history tree correctly, we have to look up
1078e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project         * all the frames first and then look up the history item. We do this
1088e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project         * because the history item in the tree may be null at this point.
1098e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project         * Unfortunately, a HistoryItem can only search its immediately
1108e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project         * children so we do a breadth-first rebuild of the tree.
1118e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project         */
1128e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project
1138e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project        // Keep a small list of child frames to traverse.
1148e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project        WTF::Vector<WebCore::Frame*> frameQueue;
1158e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project        // Fix the top-level item.
11667ed0edeb2ad5bb22ec778472b78d41e7eb3b68aSteve Block        pFrame->loader()->history()->setCurrentItem(current.get());
1178e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project        WebCore::Frame* child = pFrame->tree()->firstChild();
1188e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project        // Remember the parent history item so we can search for a child item.
1198e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project        RefPtr<WebCore::HistoryItem> parent = current;
1208e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project        while (child) {
1218e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project            // Use the old history item since the current one may have a
1228e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project            // deleted parent.
1235f1ab04193ad0130ca8204aadaceae083aca9881Feng Qian            WebCore::HistoryItem* item = parent->childItemWithTarget(child->tree()->name());
12467ed0edeb2ad5bb22ec778472b78d41e7eb3b68aSteve Block            child->loader()->history()->setCurrentItem(item);
125db239ca3504af9998d5717708fdef4676e286602Patrick Scott            // Append the first child to the queue if it exists. If there is no
126db239ca3504af9998d5717708fdef4676e286602Patrick Scott            // item, then we do not need to traverse the children since there
127db239ca3504af9998d5717708fdef4676e286602Patrick Scott            // will be no parent history item.
128db239ca3504af9998d5717708fdef4676e286602Patrick Scott            WebCore::Frame* firstChild;
129db239ca3504af9998d5717708fdef4676e286602Patrick Scott            if (item && (firstChild = child->tree()->firstChild()))
130db239ca3504af9998d5717708fdef4676e286602Patrick Scott                frameQueue.append(firstChild);
1318e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project            child = child->tree()->nextSibling();
1328e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project            // If we don't have a sibling for this frame and the queue isn't
1338e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project            // empty, use the next entry in the queue.
1348e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project            if (!child && !frameQueue.isEmpty()) {
1358e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project                child = frameQueue.at(0);
1368e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project                frameQueue.remove(0);
1378e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project                // Figure out the parent history item used when searching for
1388e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project                // the history item to use.
13967ed0edeb2ad5bb22ec778472b78d41e7eb3b68aSteve Block                parent = child->tree()->parent()->loader()->history()->currentItem();
1408e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project            }
1418e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project        }
1428e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    }
1438e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project}
1448e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project
1458e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Projectstatic void WebHistoryRestoreIndex(JNIEnv* env, jobject obj, jint frame, jint index)
1468e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project{
1478e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    LOG_ASSERT(frame, "RestoreState needs a valid Frame pointer!");
1488e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    WebCore::Frame* pFrame = (WebCore::Frame*)frame;
149635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Project    WebCore::Page* page = pFrame->page();
1508e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project
1518e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    // Set the current index in the list.
152635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Project    WebCore::BackForwardList* list = page->backForwardList();
1538e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    WebCore::HistoryItem* currentItem = list->entries()[index].get();
1548e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    list->goToItem(currentItem);
1558e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project
1568e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    // Update the current and previous history item.
1578e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    WebCore::FrameLoader* loader = pFrame->loader();
15867ed0edeb2ad5bb22ec778472b78d41e7eb3b68aSteve Block    loader->history()->setCurrentItem(currentItem);
1598e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project
160635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Project    // load the current page with FrameLoadTypeIndexedBackForward so that it
161635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Project    // will use cache when it is possible
162635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Project    page->goToItem(currentItem, FrameLoadTypeIndexedBackForward);
1638e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project}
1648e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project
1658e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Projectstatic void WebHistoryInflate(JNIEnv* env, jobject obj, jint frame, jbyteArray data)
1668e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project{
1678e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    LOG_ASSERT(frame, "Inflate needs a valid frame pointer!");
1688e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    LOG_ASSERT(data, "Inflate needs a valid data pointer!");
1698e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project
1708e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    // Get the actual bytes and the length from the java array.
1718e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    const jbyte* bytes = env->GetByteArrayElements(data, NULL);
1728e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    jsize size = env->GetArrayLength(data);
1738e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project
1748e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    // Inflate the history tree into one HistoryItem or null if the inflation
1758e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    // failed.
1768e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    RefPtr<WebCore::HistoryItem> newItem = WebCore::HistoryItem::create();
1778e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project#ifdef ANDROID_HISTORY_CLIENT
1788e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    RefPtr<WebHistoryItem> bridge = new WebHistoryItem(env, obj, newItem.get());
1798e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    newItem->setBridge(bridge.get());
1808e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project#endif
1818e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    // Inflate the item recursively. If it fails, that is ok. We'll have an
1828e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    // incomplete HistoryItem but that is better than crashing due to a null
1838e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    // item.
1848e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    // We have a 2nd local variable since read_item_recursive may change the
1858e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    // ptr's value. We can't pass &bytes since we have to send bytes to
1868e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    // ReleaseByteArrayElements unchanged.
1878e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    const char* ptr = reinterpret_cast<const char*>(bytes);
1888e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    read_item_recursive(newItem.get(), &ptr, (int)size);
1898e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    env->ReleaseByteArrayElements(data, const_cast<jbyte*>(bytes), JNI_ABORT);
1908e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project#ifdef ANDROID_HISTORY_CLIENT
1918e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    bridge->setActive();
1928e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project#endif
1938e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project
1948e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    // Add the new item to the back/forward list.
1958e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    WebCore::Frame* pFrame = (WebCore::Frame*)frame;
1968e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    pFrame->page()->backForwardList()->addItem(newItem);
1978e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project
1988e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project#ifdef ANDROID_HISTORY_CLIENT
1998e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    // Update the item.
2008e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    bridge->updateHistoryItem(newItem.get());
2018e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project#endif
2028e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project}
2038e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project
204635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Project// 6 empty strings + no document state + children count = 8 unsigned values
2058e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project// 1 char for isTargetItem
2068e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project// ANDROID_HISTORY_CLIENT adds 1 int for scale.
2078e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project#ifdef ANDROID_HISTORY_CLIENT
2088e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project#define HISTORY_MIN_SIZE ((int)(sizeof(unsigned) * 9 + sizeof(char)))
209635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Project#else
210635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Project#define HISTORY_MIN_SIZE ((int)(sizeof(unsigned) * 8 + sizeof(char)))
2118e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project#endif
2128e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project
2138e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source ProjectjbyteArray WebHistory::Flatten(JNIEnv* env, WTF::Vector<char>& v, WebCore::HistoryItem* item)
2148e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project{
2158e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    if (!item)
2168e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project        return NULL;
2178e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project
2188e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    // Reserve a vector of chars with an initial size of HISTORY_MIN_SIZE.
2198e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    v.reserveCapacity(HISTORY_MIN_SIZE);
2208e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project
2218e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    // Write the top-level history item and then write all the children
2228e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    // recursively.
2238e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project#ifdef ANDROID_HISTORY_CLIENT
2248e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    LOG_ASSERT(item->bridge(), "Why don't we have a bridge object here?");
2258e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project#endif
2268e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    write_item(v, item);
2278e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    write_children_recursive(v, item);
2288e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project
2298e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    // Try to create a new java byte array.
2308e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    jbyteArray b = env->NewByteArray(v.size());
2318e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    if (!b)
2328e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project        return NULL;
2338e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project
2348e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    // Write our flattened data to the java array.
2358e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    env->SetByteArrayRegion(b, 0, v.size(), (const jbyte*)v.data());
2368e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    return b;
2378e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project}
2388e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project
2398e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source ProjectWebHistoryItem::WebHistoryItem(JNIEnv* env, jobject obj,
2408e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project        WebCore::HistoryItem* item) {
2418e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    mObject = adoptGlobalRef(env, obj);
2428e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    mScale = 100;
2438e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    mActive = false;
2448e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    mParent = NULL;
2458e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    mHistoryItem = item;
2468e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project}
2478e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project
2488e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source ProjectWebHistoryItem::~WebHistoryItem() {
2498e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    if (mObject) {
2508e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project        JNIEnv* env = JSC::Bindings::getJNIEnv();
2518e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project        if (!env)
2528e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project            return;
2538e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project        env->DeleteGlobalRef(mObject);
2548e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    }
2558e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project}
2568e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project
2578e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Projectvoid WebHistoryItem::updateHistoryItem(WebCore::HistoryItem* item) {
2588e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project#ifdef ANDROID_HISTORY_CLIENT
2598e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    // Do not want to update during inflation.
2608e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    if (!mActive)
2618e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project        return;
2628e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    WebHistoryItem* webItem = this;
2638e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    // Now we need to update the top-most WebHistoryItem based on the top-most
2648e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    // HistoryItem.
2658e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    if (mParent) {
2668e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project        webItem = mParent.get();
2678e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project        if (webItem->hasOneRef()) {
2688e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project            // if the parent only has one ref, it is from this WebHistoryItem.
2698e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project            // This means that the matching WebCore::HistoryItem has been freed.
2708e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project            // This can happen during clear().
2718e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project            LOGW("Can't updateHistoryItem as the top HistoryItem is gone");
2728e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project            return;
2738e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project        }
2748e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project        while (webItem->parent())
2758e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project            webItem = webItem->parent();
2768e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project        item = webItem->historyItem();
2778e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    }
2788e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    JNIEnv* env = JSC::Bindings::getJNIEnv();
2798e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    if (!env)
2808e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project        return;
2818e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project
2828e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    // Don't do anything if the item has been gc'd already
2838e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    AutoJObject realItem = getRealObject(env, webItem->mObject);
2848e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    if (!realItem.get())
2858e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project        return;
2868e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project
2878e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    const WebCore::String& urlString = item->urlString();
2888e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    jstring urlStr = NULL;
2898e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    if (!urlString.isNull())
2908e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project        urlStr = env->NewString((unsigned short*)urlString.characters(), urlString.length());
2918e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    const WebCore::String& originalUrlString = item->originalURLString();
2928e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    jstring originalUrlStr = NULL;
2938e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    if (!originalUrlString.isNull()) {
2948e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    	originalUrlStr = env->NewString(
2958e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project                (unsigned short*) originalUrlString.characters(),
2968e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project                originalUrlString.length());
2978e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    }
2988e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    const WebCore::String& titleString = item->title();
2998e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    jstring titleStr = NULL;
3008e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    if (!titleString.isNull())
3018e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project        titleStr = env->NewString((unsigned short*)titleString.characters(), titleString.length());
3028e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project
3038e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    // Try to get the favicon from the history item. For some pages like Grand
3048e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    // Prix, there are history items with anchors. If the icon fails for the
3058e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    // item, try to get the icon using the url without the ref.
3068e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    jobject favicon = NULL;
3078e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    WebCore::String url = item->urlString();
3089e2ee40924101fa594b0b31d866f896154b47caaBen Murdoch    if (item->url().hasFragmentIdentifier()) {
3098e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project        int refIndex = url.reverseFind('#');
3108e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project        url = url.substring(0, refIndex);
3118e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    }
3128e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    WebCore::Image* icon = WebCore::iconDatabase()->iconForPageURL(url,
3138e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project            WebCore::IntSize(16, 16));
3148e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project
3158e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    if (icon)
3168e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project        favicon = webcoreImageToJavaBitmap(env, icon);
3178e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project
3188e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    WTF::Vector<char> data;
3198e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    jbyteArray array = WebHistory::Flatten(env, data, item);
3208e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    env->CallVoidMethod(realItem.get(), gWebHistoryItem.mUpdate, urlStr,
3218e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project            originalUrlStr, titleStr, favicon, array);
3228e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    env->DeleteLocalRef(urlStr);
3238e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    env->DeleteLocalRef(originalUrlStr);
3248e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    env->DeleteLocalRef(titleStr);
3258e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    if (favicon)
3268e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project        env->DeleteLocalRef(favicon);
3278e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    env->DeleteLocalRef(array);
3288e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project#endif
3298e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project}
3308e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project
3318e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Projectstatic void historyItemChanged(WebCore::HistoryItem* item) {
3328e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project#ifdef ANDROID_HISTORY_CLIENT
3338e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    LOG_ASSERT(item,
3348e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project            "historyItemChanged called with a null item");
3358e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    if (item->bridge())
3368e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project        item->bridge()->updateHistoryItem(item);
3378e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project#endif
3388e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project}
3398e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project
3408e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Projectvoid WebHistory::AddItem(const AutoJObject& list, WebCore::HistoryItem* item)
3418e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project{
3428e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project#ifdef ANDROID_HISTORY_CLIENT
3438e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    LOG_ASSERT(item, "newItem must take a valid HistoryItem!");
3448e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    // Item already added. Should only happen when we are inflating the list.
3458e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    if (item->bridge() || !list.get())
3468e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project        return;
3478e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project
3488e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    JNIEnv* env = list.env();
3498e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    // Allocate a blank WebHistoryItem
3508e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    jclass clazz = env->FindClass("android/webkit/WebHistoryItem");
3518e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    jobject newItem = env->NewObject(clazz, gWebHistoryItem.mInit);
3528e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project
3538e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    // Create the bridge, make it active, and attach it to the item.
3548e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    WebHistoryItem* bridge = new WebHistoryItem(env, newItem, item);
3558e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    bridge->setActive();
3568e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    item->setBridge(bridge);
3578e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project
3588e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    // Update the history item which will flatten the data and call update on
3598e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    // the java item.
3608e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    bridge->updateHistoryItem(item);
3618e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project
3628e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    // Add it to the list.
3638e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    env->CallVoidMethod(list.get(), gWebBackForwardList.mAddHistoryItem, newItem);
3648e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project
3658e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    // Delete our local reference.
3668e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    env->DeleteLocalRef(newItem);
3678e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project#endif
3688e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project}
3698e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project
3708e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Projectvoid WebHistory::RemoveItem(const AutoJObject& list, int index)
3718e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project{
3728e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    if (list.get())
3738e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project        list.env()->CallVoidMethod(list.get(), gWebBackForwardList.mRemoveHistoryItem, index);
3748e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project}
3758e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project
3768e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Projectvoid WebHistory::UpdateHistoryIndex(const AutoJObject& list, int newIndex)
3778e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project{
3788e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    if (list.get())
3798e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project        list.env()->SetIntField(list.get(), gWebBackForwardList.mCurrentIndex, newIndex);
3808e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project}
3818e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project
3828e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Projectstatic void write_string(WTF::Vector<char>& v, const WebCore::String& str)
3838e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project{
3848e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    unsigned strLen = str.length();
3858e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    // Only do work if the string has data.
3868e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    if (strLen) {
3878e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project        // Determine how much to grow the vector. Use the worst case for utf8 to
3888e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project        // avoid reading the string twice. Add sizeof(unsigned) to hold the
3898e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project        // string length in utf8.
3908e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project        unsigned vectorLen = v.size() + sizeof(unsigned);
3918e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project        unsigned length = (strLen << 2) + vectorLen;
3928e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project        // Grow the vector. This will change the value of v.size() but we
3938e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project        // remember the original size above.
3948e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project        v.grow(length);
3958e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project        // Grab the position to write to.
3968e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project        char* data = v.begin() + vectorLen;
3978e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project        // Write the actual string
3988e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project        int l = SkUTF16_ToUTF8(str.characters(), strLen, data);
3998e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project        LOGV("Writing string       %d %.*s", l, l, data);
4008e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project        // Go back and write the utf8 length. Subtract sizeof(unsigned) from
4018e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project        // data to get the position to write the length.
4028e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project        memcpy(data - sizeof(unsigned), (char*)&l, sizeof(unsigned));
4038e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project        // Shrink the internal state of the vector so we match what was
4048e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project        // actually written.
4058e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project        v.shrink(vectorLen + l);
4068e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    } else
4078e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project        v.append((char*)&strLen, sizeof(unsigned));
4088e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project}
4098e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project
4108e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Projectstatic void write_item(WTF::Vector<char>& v, WebCore::HistoryItem* item)
4118e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project{
4128e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    // Original url
4138e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    write_string(v, item->originalURLString());
4148e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project
4158e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    // Url
4168e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    write_string(v, item->urlString());
4178e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project
4188e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    // Title
4198e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    write_string(v, item->title());
4208e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project
4218e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    // Form content type
4228e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    write_string(v, item->formContentType());
4238e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project
4248e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    // Form data
4258e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    const WebCore::FormData* formData = item->formData();
426ef7b176b34c6a1fe082a87dd17523e47737c1e19Grace Kloba    if (formData) {
4278e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project        write_string(v, formData->flattenToString());
428ef7b176b34c6a1fe082a87dd17523e47737c1e19Grace Kloba        // save the identifier as it is not included in the flatten data
429ef7b176b34c6a1fe082a87dd17523e47737c1e19Grace Kloba        int64_t id = formData->identifier();
430ef7b176b34c6a1fe082a87dd17523e47737c1e19Grace Kloba        v.append((char*)&id, sizeof(int64_t));
431ef7b176b34c6a1fe082a87dd17523e47737c1e19Grace Kloba    } else
4328e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project        write_string(v, WebCore::String()); // Empty constructor does not allocate a buffer.
4338e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project
4348e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    // Target
4358e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    write_string(v, item->target());
4368e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project
4378e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project#ifdef ANDROID_HISTORY_CLIENT
4388e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    WebHistoryItem* bridge = item->bridge();
4398e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    LOG_ASSERT(bridge, "We should have a bridge here!");
4408e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    // Screen scale
4418e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    int scale = bridge->scale();
4428e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    LOGV("Writing scale %d", scale);
4438e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    v.append((char*)&scale, sizeof(int));
4448e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project#endif
4458e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project
4468e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    // Document state
4478e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    const WTF::Vector<WebCore::String>& docState = item->documentState();
4488e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    WTF::Vector<WebCore::String>::const_iterator end = docState.end();
4498e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    unsigned stateSize = docState.size();
4508e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    LOGV("Writing docState     %d", stateSize);
4518e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    v.append((char*)&stateSize, sizeof(unsigned));
4528e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    for (WTF::Vector<WebCore::String>::const_iterator i = docState.begin(); i != end; ++i) {
4538e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project        write_string(v, *i);
4548e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    }
4558e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project
4568e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    // Is target item
4578e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    LOGV("Writing isTargetItem %d", item->isTargetItem());
4588e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    v.append((char)item->isTargetItem());
4598e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project
4608e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    // Children count
4618e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    unsigned childCount = item->children().size();
4628e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    LOGV("Writing childCount   %d", childCount);
4638e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    v.append((char*)&childCount, sizeof(unsigned));
4648e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project}
4658e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project
4668e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Projectstatic void write_children_recursive(WTF::Vector<char>& v, WebCore::HistoryItem* parent)
4678e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project{
4688e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    const WebCore::HistoryItemVector& children = parent->children();
4698e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    WebCore::HistoryItemVector::const_iterator end = children.end();
4708e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    for (WebCore::HistoryItemVector::const_iterator i = children.begin(); i != end; ++i) {
4718e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project        WebCore::HistoryItem* item = (*i).get();
4728e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project#ifdef ANDROID_HISTORY_CLIENT
4738e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project        LOG_ASSERT(parent->bridge(),
4748e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project                "The parent item should have a bridge object!");
4758e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project        if (!item->bridge()) {
4768e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project            WebHistoryItem* bridge = new WebHistoryItem(parent->bridge());
4778e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project            item->setBridge(bridge);
4788e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project            bridge->setActive();
4798e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project        } else {
4808e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project            // The only time this item's parent may not be the same as the
4818e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project            // parent's bridge is during history close. In that case, the
4828e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project            // parent must not have a parent bridge.
4838e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project            LOG_ASSERT(parent->bridge()->parent() == NULL ||
4848e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project                    item->bridge()->parent() == parent->bridge(),
4858e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project                    "Somehow this item has an incorrect parent");
4868e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project            item->bridge()->setParent(parent->bridge());
4878e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project        }
4888e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project#endif
4898e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project        write_item(v, item);
4908e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project        write_children_recursive(v, item);
4918e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    }
4928e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project}
4938e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project
4948e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Projectstatic bool read_item_recursive(WebCore::HistoryItem* newItem,
4958e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project        const char** pData, int length)
4968e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project{
4978e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    if (!pData || length < HISTORY_MIN_SIZE)
4988e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project        return false;
4998e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project
5008e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    const WebCore::TextEncoding& e = WebCore::UTF8Encoding();
5018e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    const char* data = *pData;
5028e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    const char* end = data + length;
5038e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    int sizeofUnsigned = (int)sizeof(unsigned);
5048e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project
5058e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    // Read the original url
5068e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    // Read the expected length of the string.
5078e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    int l;
5088e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    memcpy(&l, data, sizeofUnsigned);
5098e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    // Increment data pointer by the size of an unsigned int.
5108e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    data += sizeofUnsigned;
5118e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    if (l) {
5128e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project        LOGV("Original url    %d %.*s", l, l, data);
5138e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project        // If we have a length, check if that length exceeds the data length
5148e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project        // and return null if there is not enough data.
5158e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project        if (data + l < end)
5168e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project            newItem->setOriginalURLString(e.decode(data, l));
5178e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project        else
5188e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project            return false;
5198e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project        // Increment the data pointer by the length of the string.
5208e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project        data += l;
5218e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    }
5228e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    // Check if we have enough data left to continue.
5238e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    if (end - data < sizeofUnsigned)
5248e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project        return false;
5258e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project
5268e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    // Read the url
5278e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    memcpy(&l, data, sizeofUnsigned);
5288e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    data += sizeofUnsigned;
5298e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    if (l) {
5308e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project        LOGV("Url             %d %.*s", l, l, data);
5318e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project        if (data + l < end)
5328e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project            newItem->setURLString(e.decode(data, l));
5338e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project        else
5348e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project            return false;
5358e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project        data += l;
5368e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    }
5378e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    if (end - data < sizeofUnsigned)
5388e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project        return false;
5398e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project
5408e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    // Read the title
5418e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    memcpy(&l, data, sizeofUnsigned);
5428e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    data += sizeofUnsigned;
5438e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    if (l) {
5448e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project        LOGV("Title           %d %.*s", l, l, data);
5458e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project        if (data + l < end)
5468e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project            newItem->setTitle(e.decode(data, l));
5478e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project        else
5488e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project            return false;
5498e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project        data += l;
5508e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    }
5518e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    if (end - data < sizeofUnsigned)
5528e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project        return false;
5538e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project
5548e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    // Generate a new ResourceRequest object for populating form information.
5558e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    WebCore::String formContentType;
5568e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    WTF::PassRefPtr<WebCore::FormData> formData = NULL;
5578e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project
5588e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    // Read the form content type
5598e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    memcpy(&l, data, sizeofUnsigned);
5608e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    data += sizeofUnsigned;
5618e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    if (l) {
5628e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project        LOGV("Content type    %d %.*s", l, l, data);
5638e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project        if (data + l < end)
5648e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project            formContentType = e.decode(data, l);
5658e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project        else
5668e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project            return false;
5678e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project        data += l;
5688e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    }
5698e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    if (end - data < sizeofUnsigned)
5708e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project        return false;
5718e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project
5728e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    // Read the form data
5738e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    memcpy(&l, data, sizeofUnsigned);
5748e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    data += sizeofUnsigned;
5758e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    if (l) {
5768e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project        LOGV("Form data       %d %.*s", l, l, data);
5778e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project        if (data + l < end)
5788e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project            formData = WebCore::FormData::create(data, l);
5798e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project        else
5808e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project            return false;
5818e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project        data += l;
582ef7b176b34c6a1fe082a87dd17523e47737c1e19Grace Kloba        // Read the identifier
583ef7b176b34c6a1fe082a87dd17523e47737c1e19Grace Kloba        {
584ef7b176b34c6a1fe082a87dd17523e47737c1e19Grace Kloba            int64_t id;
585ef7b176b34c6a1fe082a87dd17523e47737c1e19Grace Kloba            int size = (int)sizeof(int64_t);
586ef7b176b34c6a1fe082a87dd17523e47737c1e19Grace Kloba            memcpy(&id, data, size);
587ef7b176b34c6a1fe082a87dd17523e47737c1e19Grace Kloba            data += size;
588ef7b176b34c6a1fe082a87dd17523e47737c1e19Grace Kloba            if (id)
589ef7b176b34c6a1fe082a87dd17523e47737c1e19Grace Kloba                formData->setIdentifier(id);
590ef7b176b34c6a1fe082a87dd17523e47737c1e19Grace Kloba        }
5918e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    }
5928e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    if (end - data < sizeofUnsigned)
5938e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project        return false;
5948e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project
5958e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    // Set up the form info
5968e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    if (formData != NULL) {
5978e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project        WebCore::ResourceRequest r;
5988e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project        r.setHTTPMethod("POST");
5998e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project        r.setHTTPContentType(formContentType);
6008e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project        r.setHTTPBody(formData);
6018e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project        newItem->setFormInfoFromRequest(r);
6028e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    }
6038e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project
6048e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    // Read the target
6058e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    memcpy(&l, data, sizeofUnsigned);
6068e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    data += sizeofUnsigned;
6078e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    if (l) {
6088e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project        LOGV("Target          %d %.*s", l, l, data);
6098e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project        if (data + l < end)
6108e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project            newItem->setTarget(e.decode(data, l));
6118e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project        else
6128e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project            return false;
6138e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project        data += l;
6148e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    }
6158e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    if (end - data < sizeofUnsigned)
6168e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project        return false;
6178e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project
6188e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project#ifdef ANDROID_HISTORY_CLIENT
6198e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    WebHistoryItem* bridge = newItem->bridge();
6208e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    LOG_ASSERT(bridge, "There should be a bridge object during inflate");
6218e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    // Read the screen scale
6228e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    memcpy(&l, data, sizeofUnsigned);
6238e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    LOGV("Screen scale    %d", l);
6248e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    bridge->setScale(l);
6258e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    data += sizeofUnsigned;
6268e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    if (end - data < sizeofUnsigned)
6278e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project        return false;
6288e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project#endif
6298e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project
6308e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    // Read the document state
6318e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    memcpy(&l, data, sizeofUnsigned);
6328e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    LOGV("Document state  %d", l);
6338e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    data += sizeofUnsigned;
6348e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    if (l) {
6358e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project        // Check if we have enough data to at least parse the sizes of each
6368e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project        // document state string.
6378e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project        if (data + l * sizeofUnsigned >= end)
6388e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project            return false;
6398e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project        // Create a new vector and reserve enough space for the document state.
6408e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project        WTF::Vector<WebCore::String> docState;
6418e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project        docState.reserveCapacity(l);
6428e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project        while (l--) {
6438e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project            // Check each time if we have enough to parse the length of the next
6448e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project            // string.
6458e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project            if (end - data < sizeofUnsigned)
6468e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project                return false;
6478e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project            int strLen;
6488e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project            memcpy(&strLen, data, sizeofUnsigned);
6498e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project            data += sizeofUnsigned;
6508e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project            if (data + strLen < end)
6518e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project                docState.append(e.decode(data, strLen));
6528e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project            else
6538e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project                return false;
6548e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project            LOGV("\t\t%d %.*s", strLen, strLen, data);
6558e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project            data += strLen;
6568e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project        }
6578e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project        newItem->setDocumentState(docState);
6588e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    }
6598e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    // Check if we have enough to read the next byte
6608e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    if (data >= end)
6618e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project        return false;
6628e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project
6638e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    // Read is target item
6648e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    // Cast the value to unsigned char in order to make a negative value larger
6658e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    // than 1. A value that is not 0 or 1 is a failure.
6668e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    unsigned char c = (unsigned char)data[0];
6678e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    if (c > 1)
6688e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project        return false;
6698e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    LOGV("Target item     %d", c);
6708e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    newItem->setIsTargetItem((bool)c);
6718e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    data++;
6728e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    if (end - data < sizeofUnsigned)
6738e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project        return false;
6748e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project
6758e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    // Read the child count
6768e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    memcpy(&l, data, sizeofUnsigned);
6778e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    LOGV("Child count     %d", l);
6788e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    data += sizeofUnsigned;
6798e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    *pData = data;
6808e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    if (l) {
6818e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project        // Check if we have the minimum amount need to parse l children.
6828e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project        if (data + l * HISTORY_MIN_SIZE >= end)
6838e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project            return false;
6848e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project        while (l--) {
6858e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project            // No need to check the length each time because read_item_recursive
6868e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project            // will return null if there isn't enough data left to parse.
6878e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project            WTF::PassRefPtr<WebCore::HistoryItem> child = WebCore::HistoryItem::create();
6888e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project#ifdef ANDROID_HISTORY_CLIENT
6898e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project            // Set a bridge that will not call into java.
6908e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project            child->setBridge(new WebHistoryItem(bridge));
6918e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project#endif
6928e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project            // Read the child item.
6938e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project            if (!read_item_recursive(child.get(), pData, end - data)) {
6948e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project                child.clear();
6958e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project                return false;
6968e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project            }
6978e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project#ifdef ANDROID_HISTORY_CLIENT
6988e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project            child->bridge()->setActive();
6998e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project#endif
7008e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project            newItem->addChildItem(child);
7018e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project        }
7028e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    }
7038e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    return true;
7048e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project}
7058e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project
7068e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project// On arm, this test will cause memory corruption since converting char* will
7078e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project// byte align the result and this test does not use memset (it probably
7088e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project// should).
7098e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project// On the simulator, using HistoryItem will invoke the IconDatabase which will
7108e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project// initialize the main thread. Since this is invoked by the Zygote process, the
7118e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project// main thread will be incorrect and an assert will fire later.
7128e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project// In conclusion, define UNIT_TEST only if you know what you are doing.
7138e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project#ifdef UNIT_TEST
7148e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Projectstatic void unit_test()
7158e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project{
7168e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    LOGD("Entering history unit test!");
7178e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    const char* test1 = new char[0];
7188e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    WTF::RefPtr<WebCore::HistoryItem> item = WebCore::HistoryItem::create();
7198e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    WebCore::HistoryItem* testItem = item.get();
7208e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project#ifdef ANDROID_HISTORY_CLIENT
7218e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    testItem->setBridge(new WebHistoryItem(NULL));
7228e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project#endif
7238e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    LOG_ASSERT(!read_item_recursive(testItem, &test1, 0), "0 length array should fail!");
7248e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    delete[] test1;
7258e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    const char* test2 = new char[2];
7268e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    LOG_ASSERT(!read_item_recursive(testItem, &test2, 2), "Small array should fail!");
7278e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    delete[] test2;
7288e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    LOG_ASSERT(!read_item_recursive(testItem, NULL, HISTORY_MIN_SIZE), "Null data should fail!");
7298e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    // Original Url
7308e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    char* test3 = new char[HISTORY_MIN_SIZE];
7318e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    const char* ptr = (const char*)test3;
7328e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    memset(test3, 0, HISTORY_MIN_SIZE);
7338e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    *(int*)test3 = 4000;
7348e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    LOG_ASSERT(!read_item_recursive(testItem, &ptr, HISTORY_MIN_SIZE), "4000 length originalUrl should fail!");
7358e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    // Url
7368e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    int offset = 4;
7378e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    memset(test3, 0, HISTORY_MIN_SIZE);
7388e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    ptr = (const char*)test3;
7398e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    *(int*)(test3 + offset) = 4000;
7408e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    LOG_ASSERT(!read_item_recursive(testItem, &ptr, HISTORY_MIN_SIZE), "4000 length url should fail!");
7418e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    // Title
7428e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    offset += 4;
7438e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    memset(test3, 0, HISTORY_MIN_SIZE);
7448e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    ptr = (const char*)test3;
7458e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    *(int*)(test3 + offset) = 4000;
7468e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    LOG_ASSERT(!read_item_recursive(testItem, &ptr, HISTORY_MIN_SIZE), "4000 length title should fail!");
7478e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    // Form content type
7488e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    offset += 4;
7498e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    memset(test3, 0, HISTORY_MIN_SIZE);
7508e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    ptr = (const char*)test3;
7518e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    *(int*)(test3 + offset) = 4000;
7528e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    LOG_ASSERT(!read_item_recursive(testItem, &ptr, HISTORY_MIN_SIZE), "4000 length contentType should fail!");
7538e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    // Form data
7548e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    offset += 4;
7558e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    memset(test3, 0, HISTORY_MIN_SIZE);
7568e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    ptr = (const char*)test3;
7578e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    *(int*)(test3 + offset) = 4000;
7588e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    LOG_ASSERT(!read_item_recursive(testItem, &ptr, HISTORY_MIN_SIZE), "4000 length form data should fail!");
7598e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    // Target
7608e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    offset += 4;
7618e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    memset(test3, 0, HISTORY_MIN_SIZE);
7628e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    ptr = (const char*)test3;
7638e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    *(int*)(test3 + offset) = 4000;
7648e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    LOG_ASSERT(!read_item_recursive(testItem, &ptr, HISTORY_MIN_SIZE), "4000 length target should fail!");
7658e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project#ifdef ANDROID_HISTORY_CLIENT
7668e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    offset += 4; // Scale
7678e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project#endif
7688e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    // Document state
7698e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    offset += 4;
7708e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    memset(test3, 0, HISTORY_MIN_SIZE);
7718e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    ptr = (const char*)test3;
7728e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    *(int*)(test3 + offset) = 4000;
7738e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    LOG_ASSERT(!read_item_recursive(testItem, &ptr, HISTORY_MIN_SIZE), "4000 length document state should fail!");
7748e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    // Is target item
7758e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    offset += 1;
7768e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    memset(test3, 0, HISTORY_MIN_SIZE);
7778e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    ptr = (const char*)test3;
7788e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    *(char*)(test3 + offset) = '!';
7798e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    LOG_ASSERT(!read_item_recursive(testItem, &ptr, HISTORY_MIN_SIZE), "IsTargetItem should fail with ! as the value!");
7808e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    // Child count
7818e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    offset += 4;
7828e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    memset(test3, 0, HISTORY_MIN_SIZE);
7838e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    ptr = (const char*)test3;
7848e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    *(int*)(test3 + offset) = 4000;
7858e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    LOG_ASSERT(!read_item_recursive(testItem, &ptr, HISTORY_MIN_SIZE), "4000 kids should fail!");
7868e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project
7878e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project#ifdef ANDROID_HISTORY_CLIENT
7888e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    offset = 36;
7898e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project#else
7908e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    offset = 28;
7918e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project#endif
7928e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    // Test document state
7938e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    delete[] test3;
7948e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    test3 = new char[HISTORY_MIN_SIZE + sizeof(unsigned)];
7958e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    memset(test3, 0, HISTORY_MIN_SIZE + sizeof(unsigned));
7968e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    ptr = (const char*)test3;
7978e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    *(int*)(test3 + offset) = 1;
7988e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    *(int*)(test3 + offset + 4) = 20;
7998e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    LOG_ASSERT(!read_item_recursive(testItem, &ptr, HISTORY_MIN_SIZE + sizeof(unsigned)), "1 20 length document state string should fail!");
8008e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    delete[] test3;
8018e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    test3 = new char[HISTORY_MIN_SIZE + 2 * sizeof(unsigned)];
8028e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    memset(test3, 0, HISTORY_MIN_SIZE + 2 * sizeof(unsigned));
8038e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    ptr = (const char*)test3;
8048e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    *(int*)(test3 + offset) = 2;
8058e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    *(int*)(test3 + offset + 4) = 0;
8068e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    *(int*)(test3 + offset + 8) = 20;
8078e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    LOG_ASSERT(!read_item_recursive(testItem, &ptr, HISTORY_MIN_SIZE + 2 * sizeof(unsigned) ), "2 20 length document state string should fail!");
8088e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    delete[] test3;
8098e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project}
8108e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project#endif
8118e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project
8128e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project//---------------------------------------------------------
8138e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project// JNI registration
8148e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project//---------------------------------------------------------
8158e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Projectstatic JNINativeMethod gWebBackForwardListMethods[] = {
8168e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    { "nativeClose", "(I)V",
8178e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project        (void*) WebHistoryClose },
8188e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    { "restoreIndex", "(II)V",
8198e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project        (void*) WebHistoryRestoreIndex }
8208e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project};
8218e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project
8228e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Projectstatic JNINativeMethod gWebHistoryItemMethods[] = {
8238e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    { "inflate", "(I[B)V",
8248e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project        (void*) WebHistoryInflate }
8258e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project};
8268e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project
8278e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Projectint register_webhistory(JNIEnv* env)
8288e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project{
8298e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project#ifdef ANDROID_HISTORY_CLIENT
8308e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    // Get notified of all changes to history items.
8318e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    WebCore::notifyHistoryItemChanged = historyItemChanged;
8328e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project#endif
8338e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project#ifdef UNIT_TEST
8348e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    unit_test();
8358e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project#endif
8368e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    // Find WebHistoryItem, its constructor, and the update method.
8378e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    jclass clazz = env->FindClass("android/webkit/WebHistoryItem");
8388e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    LOG_ASSERT(clazz, "Unable to find class android/webkit/WebHistoryItem");
8398e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    gWebHistoryItem.mInit = env->GetMethodID(clazz, "<init>", "()V");
8408e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    LOG_ASSERT(gWebHistoryItem.mInit, "Could not find WebHistoryItem constructor");
8418e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    gWebHistoryItem.mUpdate = env->GetMethodID(clazz, "update",
8428e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project            "(Ljava/lang/String;Ljava/lang/String;Ljava/lang/String;Landroid/graphics/Bitmap;[B)V");
8438e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    LOG_ASSERT(gWebHistoryItem.mUpdate, "Could not find method update in WebHistoryItem");
8448e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project
8458e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    // Find the field ids for mTitle and mUrl.
8468e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    gWebHistoryItem.mTitle = env->GetFieldID(clazz, "mTitle", "Ljava/lang/String;");
8478e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    LOG_ASSERT(gWebHistoryItem.mTitle, "Could not find field mTitle in WebHistoryItem");
8488e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    gWebHistoryItem.mUrl = env->GetFieldID(clazz, "mUrl", "Ljava/lang/String;");
8498e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    LOG_ASSERT(gWebHistoryItem.mUrl, "Could not find field mUrl in WebHistoryItem");
8508e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project
8518e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    // Find the WebBackForwardList object, the addHistoryItem and
8528e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    // removeHistoryItem methods and the mCurrentIndex field.
8538e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    clazz = env->FindClass("android/webkit/WebBackForwardList");
8548e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    LOG_ASSERT(clazz, "Unable to find class android/webkit/WebBackForwardList");
8558e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    gWebBackForwardList.mAddHistoryItem = env->GetMethodID(clazz, "addHistoryItem",
8568e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project            "(Landroid/webkit/WebHistoryItem;)V");
8578e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    LOG_ASSERT(gWebBackForwardList.mAddHistoryItem, "Could not find method addHistoryItem");
8588e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    gWebBackForwardList.mRemoveHistoryItem = env->GetMethodID(clazz, "removeHistoryItem",
8598e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project            "(I)V");
8608e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    LOG_ASSERT(gWebBackForwardList.mRemoveHistoryItem, "Could not find method removeHistoryItem");
8618e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    gWebBackForwardList.mCurrentIndex = env->GetFieldID(clazz, "mCurrentIndex", "I");
8628e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    LOG_ASSERT(gWebBackForwardList.mCurrentIndex, "Could not find field mCurrentIndex");
8638e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project
8648e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    int result = jniRegisterNativeMethods(env, "android/webkit/WebBackForwardList",
8658e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project            gWebBackForwardListMethods, NELEM(gWebBackForwardListMethods));
8668e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    return (result < 0) ? result : jniRegisterNativeMethods(env, "android/webkit/WebHistoryItem",
8678e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project            gWebHistoryItemMethods, NELEM(gWebHistoryItemMethods));
8688e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project}
8698e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project
8708e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project} /* namespace android */
871