void FrameLoaderClientAndroid::saveViewStateToItem(HistoryItem* item) { ASSERT(m_frame); ASSERT(item); // We should have added a bridge when the child item was added to its // parent. AndroidWebHistoryBridge* bridge = item->bridge(); ASSERT(bridge); // store the current scale (only) for the top frame if (!m_frame->tree()->parent()) { WebViewCore* webViewCore = WebViewCore::getWebViewCore(m_frame->view()); bridge->setScale((int)(webViewCore->scale() * 100)); bridge->setScreenWidthScale((int)(webViewCore->screenWidthScale() * 100)); } WebCore::notifyHistoryItemChanged(item); }
static bool read_item_recursive(WebCore::HistoryItem* newItem, const char** pData, int length) { if (!pData || length < HISTORY_MIN_SIZE) return false; const WebCore::TextEncoding& e = WebCore::UTF8Encoding(); const char* data = *pData; const char* end = data + length; int sizeofUnsigned = (int)sizeof(unsigned); // Read the original url // Read the expected length of the string. int l; memcpy(&l, data, sizeofUnsigned); // Increment data pointer by the size of an unsigned int. data += sizeofUnsigned; if (l) { LOGV("Original url %d %.*s", l, l, data); // If we have a length, check if that length exceeds the data length // and return null if there is not enough data. if (data + l < end) newItem->setOriginalURLString(e.decode(data, l)); else return false; // Increment the data pointer by the length of the string. data += l; } // Check if we have enough data left to continue. if (end - data < sizeofUnsigned) return false; // Read the url memcpy(&l, data, sizeofUnsigned); data += sizeofUnsigned; if (l) { LOGV("Url %d %.*s", l, l, data); if (data + l < end) newItem->setURLString(e.decode(data, l)); else return false; data += l; } if (end - data < sizeofUnsigned) return false; // Read the title memcpy(&l, data, sizeofUnsigned); data += sizeofUnsigned; if (l) { LOGV("Title %d %.*s", l, l, data); if (data + l < end) newItem->setTitle(e.decode(data, l)); else return false; data += l; } if (end - data < sizeofUnsigned) return false; // Generate a new ResourceRequest object for populating form information. WebCore::String formContentType; WTF::PassRefPtr<WebCore::FormData> formData = NULL; // Read the form content type memcpy(&l, data, sizeofUnsigned); data += sizeofUnsigned; if (l) { LOGV("Content type %d %.*s", l, l, data); if (data + l < end) formContentType = e.decode(data, l); else return false; data += l; } if (end - data < sizeofUnsigned) return false; // Read the form data memcpy(&l, data, sizeofUnsigned); data += sizeofUnsigned; if (l) { LOGV("Form data %d %.*s", l, l, data); if (data + l < end) formData = WebCore::FormData::create(data, l); else return false; data += l; // Read the identifier { int64_t id; int size = (int)sizeof(int64_t); memcpy(&id, data, size); data += size; if (id) formData->setIdentifier(id); } } if (end - data < sizeofUnsigned) return false; // Set up the form info if (formData != NULL) { WebCore::ResourceRequest r; r.setHTTPMethod("POST"); r.setHTTPContentType(formContentType); r.setHTTPBody(formData); newItem->setFormInfoFromRequest(r); } // Read the target memcpy(&l, data, sizeofUnsigned); data += sizeofUnsigned; if (l) { LOGV("Target %d %.*s", l, l, data); if (data + l < end) newItem->setTarget(e.decode(data, l)); else return false; data += l; } if (end - data < sizeofUnsigned) return false; AndroidWebHistoryBridge* bridge = newItem->bridge(); LOG_ASSERT(bridge, "There should be a bridge object during inflate"); // Read the screen scale memcpy(&l, data, sizeofUnsigned); LOGV("Screen scale %d", l); bridge->setScale(l); data += sizeofUnsigned; memcpy(&l, data, sizeofUnsigned); LOGV("Screen width scale %d", l); bridge->setScreenWidthScale(l); data += sizeofUnsigned; if (end - data < sizeofUnsigned) return false; // Read the document state memcpy(&l, data, sizeofUnsigned); LOGV("Document state %d", l); data += sizeofUnsigned; if (l) { // Check if we have enough data to at least parse the sizes of each // document state string. if (data + l * sizeofUnsigned >= end) return false; // Create a new vector and reserve enough space for the document state. WTF::Vector<WebCore::String> docState; docState.reserveCapacity(l); while (l--) { // Check each time if we have enough to parse the length of the next // string. if (end - data < sizeofUnsigned) return false; int strLen; memcpy(&strLen, data, sizeofUnsigned); data += sizeofUnsigned; if (data + strLen < end) docState.append(e.decode(data, strLen)); else return false; LOGV("\t\t%d %.*s", strLen, strLen, data); data += strLen; } newItem->setDocumentState(docState); } // Check if we have enough to read the next byte if (data >= end) return false; // Read is target item // Cast the value to unsigned char in order to make a negative value larger // than 1. A value that is not 0 or 1 is a failure. unsigned char c = (unsigned char)data[0]; if (c > 1) return false; LOGV("Target item %d", c); newItem->setIsTargetItem((bool)c); data++; if (end - data < sizeofUnsigned) return false; // Read the child count memcpy(&l, data, sizeofUnsigned); LOGV("Child count %d", l); data += sizeofUnsigned; *pData = data; if (l) { // Check if we have the minimum amount need to parse l children. if (data + l * HISTORY_MIN_SIZE >= end) return false; while (l--) { // No need to check the length each time because read_item_recursive // will return null if there isn't enough data left to parse. WTF::PassRefPtr<WebCore::HistoryItem> child = WebCore::HistoryItem::create(); // Set a bridge that will not call into java. child->setBridge(new WebHistoryItem(static_cast<WebHistoryItem*>(bridge))); // Read the child item. if (!read_item_recursive(child.get(), pData, end - data)) { child.clear(); return false; } child->bridge()->setActive(); newItem->addChildItem(child); } } return true; }