diff options
-rw-r--r-- | WebKit/android/WebCoreSupport/WebRequest.cpp | 56 | ||||
-rw-r--r-- | WebKit/android/WebCoreSupport/WebRequest.h | 5 | ||||
-rw-r--r-- | WebKit/android/WebCoreSupport/WebResponse.cpp | 45 | ||||
-rw-r--r-- | WebKit/android/WebCoreSupport/WebResponse.h | 17 | ||||
-rw-r--r-- | WebKit/android/WebCoreSupport/WebUrlLoaderClient.cpp | 30 | ||||
-rw-r--r-- | WebKit/android/WebCoreSupport/WebUrlLoaderClient.h | 1 | ||||
-rw-r--r-- | WebKit/android/WebCoreSupport/autofill/WebAutoFill.cpp | 14 | ||||
-rw-r--r-- | WebKit/android/WebCoreSupport/autofill/WebAutoFill.h | 4 | ||||
-rw-r--r-- | WebKit/android/jni/CookieManager.cpp | 57 | ||||
-rw-r--r-- | WebKit/android/jni/WebSettings.cpp | 6 | ||||
-rw-r--r-- | WebKit/android/nav/CachedRoot.cpp | 25 |
11 files changed, 208 insertions, 52 deletions
diff --git a/WebKit/android/WebCoreSupport/WebRequest.cpp b/WebKit/android/WebCoreSupport/WebRequest.cpp index cefd541..ef09ff7 100644 --- a/WebKit/android/WebCoreSupport/WebRequest.cpp +++ b/WebKit/android/WebCoreSupport/WebRequest.cpp @@ -99,6 +99,16 @@ WebRequest::~WebRequest() env->DeleteGlobalRef((_jobject*)m_inputStream); } +const std::string& WebRequest::getUrl() const +{ + return m_url; +} + +const std::string& WebRequest::getUserAgent() const +{ + return m_userAgent; +} + void WebRequest::finish(bool success) { ASSERT(m_loadState < Finished, "called finish on an already finished WebRequest (%d)", m_loadState); @@ -181,9 +191,20 @@ void WebRequest::handleAndroidURL() } m_loadState = Response; - FilePath path(m_url); - std::string mimeType(""); - net::GetMimeTypeFromFile(path, &mimeType); + + // Get the MIME type from the URL. "text/html" is a last resort, hopefully overridden. + std::string mimeType("text/html"); + + // Gmail appends the MIME to the end of the URL, with a ? separator. + size_t mimeTypeIndex = m_url.find_last_of('?'); + if (mimeTypeIndex != std::string::npos) { + mimeType.assign(m_url.begin() + mimeTypeIndex + 1, m_url.end()); + } else { + // Get the MIME type from the file extension, if any. + FilePath path(m_url); + net::GetMimeTypeFromFile(path, &mimeType); + } + OwnPtr<WebResponse> webResponse(new WebResponse(m_url, mimeType, 0, "", 200)); m_urlLoader->maybeCallOnMainThread(NewRunnableMethod( m_urlLoader.get(), &WebUrlLoaderClient::didReceiveResponse, webResponse.release())); @@ -274,20 +295,15 @@ void WebRequest::handleBrowserURL(GURL url) void WebRequest::OnReceivedRedirect(URLRequest* newRequest, const GURL& newUrl, bool* deferRedirect) { ASSERT(m_loadState < Response, "Redirect after receiving response"); + ASSERT(newRequest && newRequest->status().is_success(), "Invalid redirect"); - if (newRequest && newRequest->status().is_success()) { - OwnPtr<WebResponse> webResponse(new WebResponse(newRequest)); - webResponse->setUrl(newUrl.spec()); - m_urlLoader->maybeCallOnMainThread(NewRunnableMethod( - m_urlLoader.get(), &WebUrlLoaderClient::willSendRequest, webResponse.release())); - } else { - // why would this happen? And what to do? - } + OwnPtr<WebResponse> webResponse(new WebResponse(newRequest)); + webResponse->setUrl(newUrl.spec()); + m_urlLoader->maybeCallOnMainThread(NewRunnableMethod( + m_urlLoader.get(), &WebUrlLoaderClient::willSendRequest, webResponse.release())); - // Here we should check if the url we get back from webkit is the same - // as newUrl, but since we are on a different thread that is not - // possible. Look into later. - return; + // Defer the redirect until followDeferredRedirect() is called. + *deferRedirect = true; } // Called when we receive an authentication failure. The delegate should @@ -341,15 +357,11 @@ void WebRequest::cancelAuth() m_request->CancelAuth(); } -void WebRequest::downloadFile(WebFrame* frame) +void WebRequest::followDeferredRedirect() { - std::string contentDisposition; - std::string mimeType; - - m_request->GetResponseHeaderByName("content-disposition", &contentDisposition); - m_request->GetMimeType(&mimeType); + ASSERT(m_loadState < Response, "Redirect after receiving response"); - frame->downloadStart(m_request->url().spec(), m_userAgent, contentDisposition, mimeType, m_request->GetExpectedContentSize()); + m_request->FollowDeferredRedirect(); } void WebRequest::startReading() diff --git a/WebKit/android/WebCoreSupport/WebRequest.h b/WebKit/android/WebCoreSupport/WebRequest.h index b96126b..1f73d2a 100644 --- a/WebKit/android/WebCoreSupport/WebRequest.h +++ b/WebKit/android/WebCoreSupport/WebRequest.h @@ -74,7 +74,10 @@ public: // Methods called during a request by the UI code (via WebUrlLoaderClient). void setAuth(const string16& username, const string16& password); void cancelAuth(); - void downloadFile(WebFrame*); + void followDeferredRedirect(); + + const std::string& getUrl() const; + const std::string& getUserAgent() const; private: void startReading(); diff --git a/WebKit/android/WebCoreSupport/WebResponse.cpp b/WebKit/android/WebCoreSupport/WebResponse.cpp index cb10cba..5c9b79b 100644 --- a/WebKit/android/WebCoreSupport/WebResponse.cpp +++ b/WebKit/android/WebCoreSupport/WebResponse.cpp @@ -29,6 +29,8 @@ #include "ResourceResponse.h" #include "ResourceError.h" +using namespace std; + namespace android { WebResponse::WebResponse(URLRequest* request) @@ -38,7 +40,7 @@ WebResponse::WebResponse(URLRequest* request) m_host = request->url().HostNoBrackets(); request->GetMimeType(&m_mime); request->GetCharset(&m_encoding); - m_length = request->GetExpectedContentSize(); + m_expectedSize = request->GetExpectedContentSize(); net::HttpResponseHeaders* responseHeaders = request->response_headers(); if (!responseHeaders) @@ -47,18 +49,18 @@ WebResponse::WebResponse(URLRequest* request) m_httpStatusCode = responseHeaders->response_code(); m_httpStatusText = responseHeaders->GetStatusText(); - std::string value; - std::string name; + string value; + string name; void* iter = 0; while (responseHeaders->EnumerateHeaderLines(&iter, &name, &value)) m_headerFields[name] = value; } -WebResponse::WebResponse(const std::string &url, const std::string &mimeType, const long long length, const std::string &encoding, const int httpStatusCode) +WebResponse::WebResponse(const string &url, const string &mimeType, long long expectedSize, const string &encoding, int httpStatusCode) : m_encoding(encoding) , m_httpStatusCode(httpStatusCode) , m_httpStatusText("") - , m_length(length) + , m_expectedSize(expectedSize) , m_mime(mimeType) , m_url(url) { @@ -66,11 +68,11 @@ WebResponse::WebResponse(const std::string &url, const std::string &mimeType, co WebCore::ResourceResponse WebResponse::createResourceResponse() { - WebCore::ResourceResponse resourceResponse(url(), m_mime.c_str(), m_length, m_encoding.c_str(), ""); + WebCore::ResourceResponse resourceResponse(createKurl(), m_mime.c_str(), m_expectedSize, m_encoding.c_str(), ""); resourceResponse.setHTTPStatusCode(m_httpStatusCode); resourceResponse.setHTTPStatusText(m_httpStatusText.c_str()); - std::map<std::string, std::string>::const_iterator it; + map<string, string>::const_iterator it; for (it = m_headerFields.begin(); it != m_headerFields.end(); ++it) resourceResponse.setHTTPHeaderField(it->first.c_str(), it->second.c_str()); @@ -85,15 +87,40 @@ WebCore::ResourceError WebResponse::createResourceError() } -WebCore::KURL WebResponse::url() +WebCore::KURL WebResponse::createKurl() { WebCore::KURL kurl(WebCore::ParsedURLString, m_url.c_str()); return kurl; } -void WebResponse::setUrl(std::string url) +const string& WebResponse::getUrl() const +{ + return m_url; +} + +void WebResponse::setUrl(const string& url) { m_url = url; } +const string& WebResponse::getMimeType() const +{ + return m_mime; +} + +bool WebResponse::getHeader(const string& header, string* result) const +{ + map<string, string>::const_iterator iter = m_headerFields.find(header); + if (iter == m_headerFields.end()) + return false; + if (result) + *result = iter->second; + return true; +} + +long long WebResponse::getExpectedSize() const +{ + return m_expectedSize; +} + } // namespace android diff --git a/WebKit/android/WebCoreSupport/WebResponse.h b/WebKit/android/WebCoreSupport/WebResponse.h index fc90bf1..eafc4e3 100644 --- a/WebKit/android/WebCoreSupport/WebResponse.h +++ b/WebKit/android/WebCoreSupport/WebResponse.h @@ -46,13 +46,18 @@ class WebResponse { public: WebResponse() {} WebResponse(URLRequest*); - WebResponse(const std::string &url, const std::string &mimeType, const long long length, const std::string &encoding, const int httpStatusCode); - WebCore::KURL url(); - void setUrl(std::string); + WebResponse(const std::string &url, const std::string &mimeType, long long expectedSize, const std::string &encoding, int httpStatusCode); - // Only use on the WebCore thread! + const std::string& getUrl() const; + void setUrl(const std::string&); + + const std::string& getMimeType() const; + bool getHeader(const std::string& header, std::string* result) const; + long long getExpectedSize() const; + + // The create() methods create WebCore objects. They must only be called on the WebKit thread. + WebCore::KURL createKurl(); WebCore::ResourceResponse createResourceResponse(); - // Only use on the WebCore thread! WebCore::ResourceError createResourceError(); private: @@ -60,7 +65,7 @@ private: int m_httpStatusCode; std::string m_host; std::string m_httpStatusText; - long long m_length; + long long m_expectedSize; std::string m_mime; std::string m_url; diff --git a/WebKit/android/WebCoreSupport/WebUrlLoaderClient.cpp b/WebKit/android/WebCoreSupport/WebUrlLoaderClient.cpp index e6c06af..8925fbc 100644 --- a/WebKit/android/WebCoreSupport/WebUrlLoaderClient.cpp +++ b/WebKit/android/WebCoreSupport/WebUrlLoaderClient.cpp @@ -23,6 +23,8 @@ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ +#define LOG_TAG "WebUrlLoaderClient" + #include "config.h" #include "WebUrlLoaderClient.h" @@ -171,7 +173,16 @@ bool WebUrlLoaderClient::start(bool sync, bool isPrivateBrowsing) void WebUrlLoaderClient::downloadFile() { - m_request->downloadFile(m_webFrame); + if (m_response) { + std::string contentDisposition; + m_response->getHeader("content-disposition", &contentDisposition); + m_webFrame->downloadStart(m_request->getUrl(), m_request->getUserAgent(), contentDisposition, m_response->getMimeType(), m_response->getExpectedSize()); + } else { + LOGE("Unexpected call to downloadFile() before didReceiveResponse(). URL: %s", m_request->getUrl().c_str()); + // TODO: Turn off asserts crashing before release + // http://b/issue?id=2951985 + CRASH(); + } } void WebUrlLoaderClient::cancel() @@ -243,7 +254,8 @@ void WebUrlLoaderClient::didReceiveResponse(PassOwnPtr<WebResponse> webResponse) if (!isActive()) return; - m_resourceHandle->client()->didReceiveResponse(m_resourceHandle.get(), webResponse->createResourceResponse()); + m_response = webResponse; + m_resourceHandle->client()->didReceiveResponse(m_resourceHandle.get(), m_response->createResourceResponse()); } void WebUrlLoaderClient::didReceiveData(scoped_refptr<net::IOBuffer> buf, int size) @@ -290,8 +302,20 @@ void WebUrlLoaderClient::willSendRequest(PassOwnPtr<WebResponse> webResponse) if (!isActive()) return; - OwnPtr<WebCore::ResourceRequest> resourceRequest(new WebCore::ResourceRequest(webResponse->url())); + KURL url = webResponse->createKurl(); + OwnPtr<WebCore::ResourceRequest> resourceRequest(new WebCore::ResourceRequest(url)); m_resourceHandle->client()->willSendRequest(m_resourceHandle.get(), *resourceRequest, webResponse->createResourceResponse()); + + // WebKit may have killed the request. + if (!isActive()) + return; + + // Like Chrome, we only follow the redirect if WebKit left the URL unmodified. + if (url == resourceRequest->url()) { + ioThread()->message_loop()->PostTask(FROM_HERE, NewRunnableMethod(m_request.get(), &WebRequest::followDeferredRedirect)); + } else { + cancel(); + } } void WebUrlLoaderClient::didFinishLoading() diff --git a/WebKit/android/WebCoreSupport/WebUrlLoaderClient.h b/WebKit/android/WebCoreSupport/WebUrlLoaderClient.h index d038489..5f2c528 100644 --- a/WebKit/android/WebCoreSupport/WebUrlLoaderClient.h +++ b/WebKit/android/WebCoreSupport/WebUrlLoaderClient.h @@ -104,6 +104,7 @@ private: volatile bool m_finished; scoped_refptr<WebRequest> m_request; + OwnPtr<WebResponse> m_response; // NULL until didReceiveResponse is called. // Check if a request is active bool isActive() const; diff --git a/WebKit/android/WebCoreSupport/autofill/WebAutoFill.cpp b/WebKit/android/WebCoreSupport/autofill/WebAutoFill.cpp index ef9d598..1aecef1 100644 --- a/WebKit/android/WebCoreSupport/autofill/WebAutoFill.cpp +++ b/WebKit/android/WebCoreSupport/autofill/WebAutoFill.cpp @@ -44,6 +44,7 @@ #include "WebUrlLoaderClient.h" #include "WebViewCore.h" +#define NO_PROFILE_SET 0 #define FORM_NOT_AUTOFILLABLE -1 namespace android @@ -56,6 +57,7 @@ static URLRequestContext* webAutoFillContextGetter() WebAutoFill::WebAutoFill() : mWebViewCore(0) + , mUniqueProfileId(NO_PROFILE_SET) { mFormManager = new FormManager(); mQueryId = 1; @@ -172,6 +174,7 @@ void WebAutoFill::setProfile(int id, const string16& fullName, const string16& e const string16& state, const string16& zipCode, const string16& country, const string16& phoneNumber) { AutoFillProfile autoFillProfile; + mUniqueProfileId = id; autoFillProfile.set_unique_id(id); // Constants for AutoFill field types are found in external/chromium/chrome/browser/autofill/field_types.h. @@ -191,6 +194,17 @@ void WebAutoFill::setProfile(int id, const string16& fullName, const string16& e mTabContents->profile()->GetPersonalDataManager()->SetProfiles(&profiles); } +void WebAutoFill::clearProfiles() +{ + // For now Chromium only ever knows about one profile, so we can just + // remove it by unique id. If we support multiple profiles in the future + // we need to remove them all here. + if (mUniqueProfileId != NO_PROFILE_SET) { + mTabContents->profile()->GetPersonalDataManager()->RemoveProfile(mUniqueProfileId); + mUniqueProfileId = NO_PROFILE_SET; + } +} + } #endif diff --git a/WebKit/android/WebCoreSupport/autofill/WebAutoFill.h b/WebKit/android/WebCoreSupport/autofill/WebAutoFill.h index 46850e6..d74c838 100644 --- a/WebKit/android/WebCoreSupport/autofill/WebAutoFill.h +++ b/WebKit/android/WebCoreSupport/autofill/WebAutoFill.h @@ -66,6 +66,7 @@ public: void setProfile(int id, const string16& fullName, const string16& emailAddress, const string16& companyName, const string16& addressLine1, const string16& addressLine2, const string16& city, const string16& state, const string16& zipCode, const string16& country, const string16& phoneNumber); + void clearProfiles(); private: OwnPtr<FormManager> mFormManager; @@ -83,6 +84,9 @@ private: AutoFillQueryToUniqueIdMap mUniqueIdMap; int mQueryId; + // This is set by Java when a profile is synced. + int mUniqueProfileId; + WebViewCore* mWebViewCore; }; diff --git a/WebKit/android/jni/CookieManager.cpp b/WebKit/android/jni/CookieManager.cpp index f686b7f..b38cc3a 100644 --- a/WebKit/android/jni/CookieManager.cpp +++ b/WebKit/android/jni/CookieManager.cpp @@ -80,7 +80,7 @@ static jstring getCookie(JNIEnv* env, jobject, jstring url) CookieOptions options; options.set_include_httponly(); std::string cookies = WebRequestContext::get(false)->cookie_store()->GetCookieMonster()->GetCookiesWithOptions(gurl, options); - return env->NewStringUTF(cookies.c_str()); + return cookies.empty() ? 0 : env->NewStringUTF(cookies.c_str()); #else // The Android HTTP stack is implemented Java-side. ASSERT_NOT_REACHED(); @@ -88,6 +88,17 @@ static jstring getCookie(JNIEnv* env, jobject, jstring url) #endif } +static bool hasCookies(JNIEnv*, jobject) +{ +#if USE(CHROME_NETWORK_STACK) + return !WebRequestContext::get(false)->cookie_store()->GetCookieMonster()->GetAllCookies().empty(); +#else + // The Android HTTP stack is implemented Java-side. + ASSERT_NOT_REACHED(); + return false; +#endif +} + static void removeAllCookie(JNIEnv*, jobject) { #if USE(CHROME_NETWORK_STACK) @@ -101,6 +112,35 @@ static void removeAllCookie(JNIEnv*, jobject) #endif } +static void removeExpiredCookie(JNIEnv*, jobject) +{ +#if USE(CHROME_NETWORK_STACK) + // This simply forces a GC. The getters delete expired cookies so won't return expired cookies anyway. + WebRequestContext::get(false)->cookie_store()->GetCookieMonster()->GetAllCookies(); + WebRequestContext::get(true)->cookie_store()->GetCookieMonster()->GetAllCookies(); +#endif +} + +static void removeSessionCookies(WebRequestContext* context) +{ +#if USE(CHROME_NETWORK_STACK) + CookieMonster* cookieMonster = context->cookie_store()->GetCookieMonster(); + CookieMonster::CookieList cookies = cookieMonster->GetAllCookies(); + for (CookieMonster::CookieList::const_iterator iter = cookies.begin(); iter != cookies.end(); ++iter) { + if (!iter->IsPersistent()) + cookieMonster->DeleteCanonicalCookie(*iter); + } +#endif +} + +static void removeSessionCookie(JNIEnv*, jobject) +{ +#if USE(CHROME_NETWORK_STACK) + removeSessionCookies(WebRequestContext::get(false)); + removeSessionCookies(WebRequestContext::get(true)); +#endif +} + static void setAcceptCookie(JNIEnv*, jobject, jboolean accept) { #if USE(CHROME_NETWORK_STACK) @@ -112,12 +152,27 @@ static void setAcceptCookie(JNIEnv*, jobject, jboolean accept) #endif } +static void setCookie(JNIEnv* env, jobject, jstring url, jstring value) +{ +#if USE(CHROME_NETWORK_STACK) + GURL gurl(jstringToStdString(env, url)); + std::string line(jstringToStdString(env, value)); + CookieOptions options; + options.set_include_httponly(); + WebRequestContext::get(false)->cookie_store()->GetCookieMonster()->SetCookieWithOptions(gurl, line, options); +#endif +} + static JNINativeMethod gCookieManagerMethods[] = { { "nativeUseChromiumHttpStack", "()Z", (void*) useChromiumHttpStack }, { "nativeAcceptCookie", "()Z", (void*) acceptCookie }, { "nativeGetCookie", "(Ljava/lang/String;)Ljava/lang/String;", (void*) getCookie }, + { "nativeHasCookies", "()Z", (void*) hasCookies }, { "nativeRemoveAllCookie", "()V", (void*) removeAllCookie }, + { "nativeRemoveExpiredCookie", "()V", (void*) removeExpiredCookie }, + { "nativeRemoveSessionCookie", "()V", (void*) removeSessionCookie }, { "nativeSetAcceptCookie", "(Z)V", (void*) setAcceptCookie }, + { "nativeSetCookie", "(Ljava/lang/String;Ljava/lang/String;)V", (void*) setCookie }, }; int registerCookieManager(JNIEnv* env) diff --git a/WebKit/android/jni/WebSettings.cpp b/WebKit/android/jni/WebSettings.cpp index 62594ff..fc9d628 100644 --- a/WebKit/android/jni/WebSettings.cpp +++ b/WebKit/android/jni/WebSettings.cpp @@ -519,6 +519,12 @@ public: jobject autoFillProfile = env->GetObjectField(obj, gFieldIds->mAutoFillProfile); if (autoFillProfile) syncAutoFillProfile(env, autoFillProfile, webAutoFill); + else { + // The autofill profile is null. We need to tell Chromium about this because + // this may be because the user just deleted their profile but left the + // autofill feature setting enabled. + webAutoFill->clearProfiles(); + } #endif } }; diff --git a/WebKit/android/nav/CachedRoot.cpp b/WebKit/android/nav/CachedRoot.cpp index 3340792..1897cc0 100644 --- a/WebKit/android/nav/CachedRoot.cpp +++ b/WebKit/android/nav/CachedRoot.cpp @@ -712,15 +712,19 @@ public: layers - mLayers.begin(), TypeNames[layerType], layers->getBounds().fLeft, layers->getBounds().fTop, layers->getBounds().fRight, layers->getBounds().fBottom); - if (collectGlyphs && layerType == kDrawGlyph_Type) { + if (collectGlyphs && (layerType == kDrawGlyph_Type + || ((layerType == kDrawRect_Type + || layerType == kDrawBitmap_Type) + && mTextTest.contains(*layers)))) { DBG_NAV_LOGD("RingCheck #%d collectOvers", layers - mLayers.begin()); collectOvers = true; clipped->op(*layers, SkRegion::kUnion_Op); + continue; } collectGlyphs &= layerType != kPushLayer_Type; if (collectOvers && (layerType == kDrawRect_Type - || (!collectGlyphs && layerType == kDrawSprite_Type))) - { + || layerType == kDrawBitmap_Type + || (!collectGlyphs && layerType == kDrawSprite_Type))) { DBG_NAV_LOGD("RingCheck #%d over.op", layers - mLayers.begin()); over.op(*layers, SkRegion::kUnion_Op); } @@ -835,7 +839,7 @@ public: layers->getBounds().fRight, layers->getBounds().fBottom, active.getBounds().fLeft, active.getBounds().fTop, active.getBounds().fRight, active.getBounds().fBottom); - if (layerType == kDrawRect_Type) { + if (layerType == kDrawRect_Type || layerType == kDrawBitmap_Type) { SkRegion temp = *layers; temp.op(mTestBounds, SkRegion::kIntersect_Op); active.op(temp, SkRegion::kDifference_Op); @@ -887,7 +891,7 @@ protected: { joinGlyphs(rect); if (mType != kDrawGlyph_Type && mType != kDrawRect_Type - && mType != kDrawSprite_Type) + && mType != kDrawSprite_Type && mType != kDrawBitmap_Type) return false; if (mLayerTypes.isEmpty() || mLayerTypes.last() != mType) push(mType, mEmpty); @@ -956,13 +960,14 @@ private: mTextSlop.contains(*layers) ? "true" : "false", gb.fLeft, gb.fTop, gb.fRight, gb.fBottom); #endif - if (layerType == kDrawGlyph_Type) { + if ((layerType == kDrawGlyph_Type && mTextSlop.contains(*layers)) + || ((layerType == kDrawRect_Type + || layerType == kDrawBitmap_Type) + && mTextTest.contains(*layers))) { if (!testLayer) testLayer = layers; - if (mTextSlop.contains(*layers)) { - testRegion.op(*layers, SkRegion::kUnion_Op); - continue; - } + testRegion.op(*layers, SkRegion::kUnion_Op); + continue; } if (testLayer) { int area = calcOverlap(testRegion); |